From 663b176466a0063fbd9d128aca45220131990f7c Mon Sep 17 00:00:00 2001 From: Michi Mutsuzaki Date: Wed, 8 Jan 2025 16:51:14 +0000 Subject: [PATCH 01/17] Update stable release to v0.16.23 Signed-off-by: Michi Mutsuzaki --- stable.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stable.txt b/stable.txt index cd39980610..68f57a48e6 100644 --- a/stable.txt +++ b/stable.txt @@ -1 +1 @@ -v0.16.22 +v0.16.23 From 79ec43efb721750483f374756122b3fac2328cb0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Jan 2025 13:58:38 +0000 Subject: [PATCH 02/17] chore(deps): update docker/build-push-action action to v6.11.0 Signed-off-by: renovate[bot] --- .github/workflows/images.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index d40330587f..f188edb22d 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -59,7 +59,7 @@ jobs: # main branch or tag pushes - name: CI Build ${{ matrix.name }} if: ${{ github.event_name != 'pull_request_target' }} - uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6.10.0 + uses: docker/build-push-action@b32b51a8eda65d6793cd0494a773d4f6bcef32dc # v6.11.0 id: docker_build_ci_main with: context: . @@ -82,7 +82,7 @@ jobs: # PR updates - name: CI Build ${{ matrix.name }} if: ${{ github.event_name == 'pull_request_target' }} - uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6.10.0 + uses: docker/build-push-action@b32b51a8eda65d6793cd0494a773d4f6bcef32dc # v6.11.0 id: docker_build_ci_pr with: context: . From 0356f1e047949e7555a8f8a32f6ef44d9e62da43 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 10 Jan 2025 19:16:32 +0000 Subject: [PATCH 03/17] chore(deps): update actions/upload-artifact action to v4.6.0 Signed-off-by: renovate[bot] --- .github/workflows/aks-byocni.yaml | 2 +- .github/workflows/eks-tunnel.yaml | 2 +- .github/workflows/eks.yaml | 2 +- .github/workflows/externalworkloads.yaml | 2 +- .github/workflows/gke.yaml | 2 +- .github/workflows/images.yaml | 2 +- .github/workflows/kind.yaml | 10 +++++----- .github/workflows/multicluster.yaml | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/aks-byocni.yaml b/.github/workflows/aks-byocni.yaml index 6194f59f86..1dcef1a9c8 100644 --- a/.github/workflows/aks-byocni.yaml +++ b/.github/workflows/aks-byocni.yaml @@ -175,7 +175,7 @@ jobs: - name: Upload artifacts if: ${{ !success() }} - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: cilium-sysdump-out.zip path: cilium-sysdump-out.zip diff --git a/.github/workflows/eks-tunnel.yaml b/.github/workflows/eks-tunnel.yaml index 58ed7303d2..e02d608a34 100644 --- a/.github/workflows/eks-tunnel.yaml +++ b/.github/workflows/eks-tunnel.yaml @@ -199,7 +199,7 @@ jobs: - name: Upload artifacts if: ${{ !success() }} - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: cilium-sysdump-out.zip path: cilium-sysdump-out.zip diff --git a/.github/workflows/eks.yaml b/.github/workflows/eks.yaml index 54d7d3807d..10520dabd7 100644 --- a/.github/workflows/eks.yaml +++ b/.github/workflows/eks.yaml @@ -192,7 +192,7 @@ jobs: - name: Upload artifacts if: ${{ !success() }} - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: cilium-sysdump-out.zip path: cilium-sysdump-out.zip diff --git a/.github/workflows/externalworkloads.yaml b/.github/workflows/externalworkloads.yaml index 90a62072ec..005268ce41 100644 --- a/.github/workflows/externalworkloads.yaml +++ b/.github/workflows/externalworkloads.yaml @@ -250,7 +250,7 @@ jobs: - name: Upload artifacts if: ${{ !success() }} - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: cilium-sysdump-out.zip path: cilium-sysdump-out.zip diff --git a/.github/workflows/gke.yaml b/.github/workflows/gke.yaml index 838e29238d..ab3ce3eac7 100644 --- a/.github/workflows/gke.yaml +++ b/.github/workflows/gke.yaml @@ -182,7 +182,7 @@ jobs: - name: Upload artifacts if: ${{ !success() }} - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: cilium-sysdump-out.zip path: cilium-sysdump-out.zip diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index f188edb22d..fe011e472d 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -102,7 +102,7 @@ jobs: # Upload artifact digests - name: Upload artifact digests - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: image-digest ${{ matrix.name }} path: image-digest diff --git a/.github/workflows/kind.yaml b/.github/workflows/kind.yaml index d423f78daa..b53b1d572b 100644 --- a/.github/workflows/kind.yaml +++ b/.github/workflows/kind.yaml @@ -176,7 +176,7 @@ jobs: - name: Upload JUnit if: ${{ always() }} - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: cilium-junits path: cilium-junit*.xml @@ -192,7 +192,7 @@ jobs: - name: Upload sysdump if: ${{ !success() }} - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: cilium-sysdumps path: cilium-sysdump-*.zip @@ -333,7 +333,7 @@ jobs: - name: Upload JUnit if: ${{ always() }} - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: cilium-junits-helm-upgrade-clustermesh path: cilium-junit*.xml @@ -352,7 +352,7 @@ jobs: - name: Upload sysdump from cluster 1 if: ${{ !success() }} - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: cilium-sysdump-out-c1.zip path: cilium-sysdump-out-c1.zip @@ -360,7 +360,7 @@ jobs: - name: Upload sysdump from cluster 2 if: ${{ !success() }} - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: cilium-sysdump-out-c2.zip path: cilium-sysdump-out-c2.zip diff --git a/.github/workflows/multicluster.yaml b/.github/workflows/multicluster.yaml index 81568d8541..d035f39dbb 100644 --- a/.github/workflows/multicluster.yaml +++ b/.github/workflows/multicluster.yaml @@ -287,7 +287,7 @@ jobs: - name: Upload artifacts if: ${{ !success() }} - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: cilium-sysdump-out.zip path: | From 3783f691a0b3d914acba86c10d66b2b6d5692c1e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 14:12:29 +0000 Subject: [PATCH 04/17] chore(deps): update docker/build-push-action action to v6.12.0 Signed-off-by: renovate[bot] --- .github/workflows/images.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index fe011e472d..e3fd8f52d0 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -59,7 +59,7 @@ jobs: # main branch or tag pushes - name: CI Build ${{ matrix.name }} if: ${{ github.event_name != 'pull_request_target' }} - uses: docker/build-push-action@b32b51a8eda65d6793cd0494a773d4f6bcef32dc # v6.11.0 + uses: docker/build-push-action@67a2d409c0a876cbe6b11854e3e25193efe4e62d # v6.12.0 id: docker_build_ci_main with: context: . @@ -82,7 +82,7 @@ jobs: # PR updates - name: CI Build ${{ matrix.name }} if: ${{ github.event_name == 'pull_request_target' }} - uses: docker/build-push-action@b32b51a8eda65d6793cd0494a773d4f6bcef32dc # v6.11.0 + uses: docker/build-push-action@67a2d409c0a876cbe6b11854e3e25193efe4e62d # v6.12.0 id: docker_build_ci_pr with: context: . From b7347bb42112b764a5ec106070ac0397a8c75b1d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 17 Jan 2025 07:24:00 +0000 Subject: [PATCH 05/17] chore(deps): update golangci/golangci-lint-action action to v6.2.0 Signed-off-by: renovate[bot] --- .github/workflows/go.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/go.yaml b/.github/workflows/go.yaml index f2bc3bcfe9..75074a4962 100644 --- a/.github/workflows/go.yaml +++ b/.github/workflows/go.yaml @@ -26,7 +26,7 @@ jobs: go-version: 1.23.4 - name: Run static checks - uses: golangci/golangci-lint-action@971e284b6050e8a5849b72094c50ab08da042db8 # v6.1.1 + uses: golangci/golangci-lint-action@ec5d18412c0aeab7936cb16880d708ba2a64e1ae # v6.2.0 with: # renovate: datasource=docker depName=golangci/golangci-lint version: v1.63.4 From 3a7dcf53d2191e28dac949d45c6d9ba187ee05d7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 17 Jan 2025 01:30:56 +0000 Subject: [PATCH 06/17] chore(deps): update dependency go to v1.23.5 Signed-off-by: renovate[bot] --- .github/workflows/go.yaml | 2 +- .github/workflows/kind.yaml | 4 ++-- .github/workflows/multicluster.yaml | 2 +- .github/workflows/release.yaml | 2 +- action.yaml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/go.yaml b/.github/workflows/go.yaml index 75074a4962..1bb78f1dab 100644 --- a/.github/workflows/go.yaml +++ b/.github/workflows/go.yaml @@ -23,7 +23,7 @@ jobs: uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: # renovate: datasource=golang-version depName=go - go-version: 1.23.4 + go-version: 1.23.5 - name: Run static checks uses: golangci/golangci-lint-action@ec5d18412c0aeab7936cb16880d708ba2a64e1ae # v6.2.0 diff --git a/.github/workflows/kind.yaml b/.github/workflows/kind.yaml index b53b1d572b..b8b9f41435 100644 --- a/.github/workflows/kind.yaml +++ b/.github/workflows/kind.yaml @@ -41,7 +41,7 @@ jobs: uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: # renovate: datasource=golang-version depName=go - go-version: 1.23.4 + go-version: 1.23.5 - name: Install Cilium CLI uses: ./ @@ -229,7 +229,7 @@ jobs: uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: # renovate: datasource=golang-version depName=go - go-version: 1.23.4 + go-version: 1.23.5 - name: Install Cilium CLI uses: ./ diff --git a/.github/workflows/multicluster.yaml b/.github/workflows/multicluster.yaml index d035f39dbb..a762711780 100644 --- a/.github/workflows/multicluster.yaml +++ b/.github/workflows/multicluster.yaml @@ -95,7 +95,7 @@ jobs: uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: # renovate: datasource=golang-version depName=go - go-version: 1.23.4 + go-version: 1.23.5 - name: Set up job variables id: vars diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a7fd0fa906..f6162e039f 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -20,7 +20,7 @@ jobs: uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: # renovate: datasource=golang-version depName=go - go-version: 1.23.4 + go-version: 1.23.5 - name: Generate the artifacts run: make release diff --git a/action.yaml b/action.yaml index 2003ea8732..411c7b79a4 100644 --- a/action.yaml +++ b/action.yaml @@ -59,7 +59,7 @@ runs: if: ${{ steps.build-cli.outputs.path != '' }} with: # renovate: datasource=golang-version depName=go - go-version: 1.23.4 + go-version: 1.23.5 cache: true cache-dependency-path: '${{ steps.build-cli.outputs.go-sum-path }}' From 709391a9ef220e386dd4b3dc8f6eecf35cd76166 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 12:51:57 +0000 Subject: [PATCH 07/17] chore(deps): update all github action dependencies Signed-off-by: renovate[bot] --- .github/workflows/close-stale-issues.yaml | 2 +- .github/workflows/go.yaml | 2 +- .github/workflows/kind.yaml | 4 ++-- .github/workflows/multicluster.yaml | 2 +- .github/workflows/release.yaml | 2 +- action.yaml | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/close-stale-issues.yaml b/.github/workflows/close-stale-issues.yaml index ff2d5b7f03..bfc0392669 100644 --- a/.github/workflows/close-stale-issues.yaml +++ b/.github/workflows/close-stale-issues.yaml @@ -15,7 +15,7 @@ jobs: steps: # https://github.com/marketplace/actions/close-stale-issues - name: Close stale issues - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0 + uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0 with: operations-per-run: 1000 stale-issue-label: stale diff --git a/.github/workflows/go.yaml b/.github/workflows/go.yaml index 1bb78f1dab..19863243d2 100644 --- a/.github/workflows/go.yaml +++ b/.github/workflows/go.yaml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Set up Go - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: # renovate: datasource=golang-version depName=go go-version: 1.23.5 diff --git a/.github/workflows/kind.yaml b/.github/workflows/kind.yaml index b8b9f41435..00ca4916ea 100644 --- a/.github/workflows/kind.yaml +++ b/.github/workflows/kind.yaml @@ -38,7 +38,7 @@ jobs: kubectl version --client - name: Set up Go - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: # renovate: datasource=golang-version depName=go go-version: 1.23.5 @@ -226,7 +226,7 @@ jobs: kubectl version --client - name: Set up Go - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: # renovate: datasource=golang-version depName=go go-version: 1.23.5 diff --git a/.github/workflows/multicluster.yaml b/.github/workflows/multicluster.yaml index a762711780..8e90752146 100644 --- a/.github/workflows/multicluster.yaml +++ b/.github/workflows/multicluster.yaml @@ -92,7 +92,7 @@ jobs: gcloud info - name: Set up Go - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: # renovate: datasource=golang-version depName=go go-version: 1.23.5 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index f6162e039f..b5084f6bf2 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -17,7 +17,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Set up Go - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: # renovate: datasource=golang-version depName=go go-version: 1.23.5 diff --git a/action.yaml b/action.yaml index 411c7b79a4..830f99437b 100644 --- a/action.yaml +++ b/action.yaml @@ -55,7 +55,7 @@ runs: fi - name: Setup Go - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 if: ${{ steps.build-cli.outputs.path != '' }} with: # renovate: datasource=golang-version depName=go From c432c30b7f14b5195a1fd1067ef1f10c2fe37a59 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 Jan 2025 01:38:33 +0000 Subject: [PATCH 08/17] chore(deps): update dependency cilium/cilium to v1.16.6 Signed-off-by: renovate[bot] --- .github/workflows/aks-byocni.yaml | 2 +- .github/workflows/eks-tunnel.yaml | 2 +- .github/workflows/eks.yaml | 2 +- .github/workflows/externalworkloads.yaml | 2 +- .github/workflows/gke.yaml | 2 +- .github/workflows/kind.yaml | 2 +- .github/workflows/multicluster.yaml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/aks-byocni.yaml b/.github/workflows/aks-byocni.yaml index 1dcef1a9c8..770ca4fbbe 100644 --- a/.github/workflows/aks-byocni.yaml +++ b/.github/workflows/aks-byocni.yaml @@ -39,7 +39,7 @@ env: location: westus2 cost_reduction: --node-vm-size Standard_B2s --node-osdisk-size 30 # renovate: datasource=github-releases depName=cilium/cilium - cilium_version: v1.16.5 + cilium_version: v1.16.6 kubectl_version: v1.23.6 jobs: diff --git a/.github/workflows/eks-tunnel.yaml b/.github/workflows/eks-tunnel.yaml index e02d608a34..b51314e6af 100644 --- a/.github/workflows/eks-tunnel.yaml +++ b/.github/workflows/eks-tunnel.yaml @@ -29,7 +29,7 @@ env: region: us-east-2 eksctl_version: v0.147.0 # renovate: datasource=github-releases depName=cilium/cilium - cilium_version: v1.16.5 + cilium_version: v1.16.6 kubectl_version: v1.23.6 jobs: diff --git a/.github/workflows/eks.yaml b/.github/workflows/eks.yaml index 10520dabd7..4da81de0a2 100644 --- a/.github/workflows/eks.yaml +++ b/.github/workflows/eks.yaml @@ -29,7 +29,7 @@ env: region: us-east-2 eksctl_version: v0.147.0 # renovate: datasource=github-releases depName=cilium/cilium - cilium_version: v1.16.5 + cilium_version: v1.16.6 kubectl_version: v1.23.6 jobs: diff --git a/.github/workflows/externalworkloads.yaml b/.github/workflows/externalworkloads.yaml index 005268ce41..d3093eabc8 100644 --- a/.github/workflows/externalworkloads.yaml +++ b/.github/workflows/externalworkloads.yaml @@ -37,7 +37,7 @@ env: zone: us-west2-a vmStartupScript: .github/gcp-vm-startup.sh # renovate: datasource=github-releases depName=cilium/cilium - cilium_version: v1.16.5 + cilium_version: v1.16.6 kubectl_version: v1.23.6 USE_GKE_GCLOUD_AUTH_PLUGIN: True diff --git a/.github/workflows/gke.yaml b/.github/workflows/gke.yaml index ab3ce3eac7..f8b8a9cf2d 100644 --- a/.github/workflows/gke.yaml +++ b/.github/workflows/gke.yaml @@ -36,7 +36,7 @@ concurrency: env: zone: us-west2-a # renovate: datasource=github-releases depName=cilium/cilium - cilium_version: v1.16.5 + cilium_version: v1.16.6 kubectl_version: v1.23.6 USE_GKE_GCLOUD_AUTH_PLUGIN: True diff --git a/.github/workflows/kind.yaml b/.github/workflows/kind.yaml index 00ca4916ea..c2e4a5fddb 100644 --- a/.github/workflows/kind.yaml +++ b/.github/workflows/kind.yaml @@ -17,7 +17,7 @@ env: TIMEOUT: 2m LOG_TIME: 30m # renovate: datasource=github-releases depName=cilium/cilium - cilium_version: v1.16.5 + cilium_version: v1.16.6 kubectl_version: v1.23.6 jobs: diff --git a/.github/workflows/multicluster.yaml b/.github/workflows/multicluster.yaml index 8e90752146..a68ffdf5b7 100644 --- a/.github/workflows/multicluster.yaml +++ b/.github/workflows/multicluster.yaml @@ -36,7 +36,7 @@ concurrency: env: zone: us-west2-a # renovate: datasource=github-releases depName=cilium/cilium - cilium_version: v1.16.5 + cilium_version: v1.16.6 kubectl_version: v1.23.6 USE_GKE_GCLOUD_AUTH_PLUGIN: True From 8779371e16aa6fbda5c3208ccd1285dd2d281102 Mon Sep 17 00:00:00 2001 From: David Bimmler Date: Wed, 22 Jan 2025 11:42:48 +0100 Subject: [PATCH 09/17] renovate: remove busybox It's no longer part of the Dockerfile, hence does nothing. Signed-off-by: David Bimmler --- .github/renovate.json5 | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index d4d0c719ee..06013e64aa 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -152,14 +152,6 @@ "Makefile" ] }, - { - "matchPackageNames": [ - "docker.io/library/busybox" - ], - "matchPaths": [ - "Dockerfile" - ], - }, { "groupName": "Go", "matchDepNames": [ From 4c28bbb07f24100a1da917c5c861dc98cb8b2c96 Mon Sep 17 00:00:00 2001 From: David Bimmler Date: Wed, 22 Jan 2025 11:43:09 +0100 Subject: [PATCH 10/17] renovate: remove defaults/defaults.go Since the move of the code to cilium/cilium this file doesn't exist anymore. Signed-off-by: David Bimmler --- .github/renovate.json5 | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 06013e64aa..13ca6313bd 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -203,18 +203,6 @@ "# renovate: datasource=(?.*?) depName=(?.*?)\\s+.+_VERSION = (?.*)\\s+.+_SHA = (?sha256:[a-f0-9]+)" ] }, - { - "fileMatch": [ - "^defaults/defaults.go$" - ], - // This regex manages image version strings in defaults/defaults.go - // similar to the examples shown here: - // https://docs.renovatebot.com/modules/manager/regex/#advanced-capture - "matchStrings": [ - "\/\/ renovate: datasource=(?.*?)\\s+.+Image = \"(?.*):(?.*)@(?sha256:[a-f0-9]+)\"", - "\/\/ renovate: datasource=(?.*?) depName=(?.*?)\\s+Version = \"(?.*)\"" - ] - }, { "fileMatch": [ "^go\\.mod$" From 80e24b0d799dd8df0ab10d4ef34cece240a6dfbb Mon Sep 17 00:00:00 2001 From: David Bimmler Date: Wed, 22 Jan 2025 13:42:44 +0100 Subject: [PATCH 11/17] renovate: remove old go dependency matchers These are only indirect dependencies now, no need for special handling. Signed-off-by: David Bimmler --- .github/renovate.json5 | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 13ca6313bd..eb2cf22f53 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -99,44 +99,6 @@ "main", ] }, - { - "enabled": false, - "matchPackageNames": [ - // All of these packages are maintained on a Cilium fork. Thus, we don't - // want to update them automatically. - "go.universe.tf/metallb", - "github.com/cilium/metallb", - "github.com/miekg/dns", - "github.com/cilium/dns", - "sigs.k8s.io/controller-tools", - "github.com/cilium/controller-tools", - // We update this dependency manually together with envoy proxy updates - "github.com/cilium/proxy", - // We need v1.0.6-0.20210604193023-d5e0c0615ace from pflag, but - // renovate wants to downgrade to 1.0.5. Can be removed if pflag ever - // tags a new release. - "github.com/spf13/pflag", - // v0.0.0-20230801115018-d63ba01acd4b causes this complilation error: - // - // # github.com/cilium/cilium/pkg/hive/cell - // Error: vendor/github.com/cilium/cilium/pkg/hive/cell/health.go:194:23: - // type func(a Status, b Status) bool of func(a, b Status) bool {…} does not match inferred - // type func(a Status, b Status) int for func(a E, b E) int - "golang.org/x/exp", - // This package is not versioned leading to "empty" updates every week. - // Update it manually once newly introduces tetragon CRDs are required. - "github.com/cilium/tetragon/pkg/k8s", - // Do not update GoBGP until https://github.com/osrg/gobgp/issues/2777 - // is resolved and a new version is released. - // Ref: https://github.com/cilium/cilium/pull/31123 - "github.com/osrg/gobgp/v3", - ], - "matchPackagePatterns": [ - // k8s dependencies will be updated manually in lockstep. - "k8s.io/*", - "sigs.k8s.io/*" - ] - }, { // Allow github.com/cilium/cilium to upgrade to prerelease versions. "ignoreUnstable": false, From 38aac3edcdb1f15c5227f7a1a2fc190a23b3e5a6 Mon Sep 17 00:00:00 2001 From: David Bimmler Date: Wed, 22 Jan 2025 13:09:37 +0100 Subject: [PATCH 12/17] renovate: reformat using json5format Formatter used is https://github.com/google/json5format/, as below. $ formatjson5 -i 2 renovate.json5 This gets us closer to what renovate produces. Signed-off-by: David Bimmler --- .github/renovate.json5 | 175 +++++++++++++++++++++-------------------- 1 file changed, 90 insertions(+), 85 deletions(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index eb2cf22f53..b35da89e22 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -1,177 +1,182 @@ { - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": [ + $schema: "https://docs.renovatebot.com/renovate-schema.json", + extends: [ "config:base", ":gitSignOff", - "helpers:pinGitHubActionDigests" + "helpers:pinGitHubActionDigests", ], + // This ensures that the gitAuthor and gitSignOff fields match - "gitAuthor": "renovate[bot] ", - "includePaths": [ + gitAuthor: "renovate[bot] ", + includePaths: [ ".github/workflows/**", "action.yaml", "defaults/defaults.go", "go.mod", "go.sum", "Dockerfile", - "Makefile" + "Makefile", ], postUpdateOptions: [ - "gomodTidy" + "gomodTidy", ], - "pinDigests": true, - "ignorePresets": [":prHourlyLimit2"], - "separateMajorMinor": true, - "separateMultipleMajor": true, - "separateMinorPatch": true, - "pruneStaleBranches": true, - "baseBranches": [ - "main" + pinDigests: true, + ignorePresets: [ + ":prHourlyLimit2", ], - "vulnerabilityAlerts": { - "enabled": true + separateMajorMinor: true, + separateMultipleMajor: true, + separateMinorPatch: true, + pruneStaleBranches: true, + baseBranches: [ + "main", + ], + vulnerabilityAlerts: { + enabled: true, }, - "labels": [ + labels: [ "renovate/stop-updating", "kind/enhancement", - "priority/release-blocker" + "priority/release-blocker", ], - "stopUpdatingLabel": "renovate/stop-updating", - "packageRules": [ + stopUpdatingLabel: "renovate/stop-updating", + packageRules: [ { - "groupName": "all github action dependencies", - "groupSlug": "all-github-action", - "matchPaths": [ + groupName: "all github action dependencies", + groupSlug: "all-github-action", + matchPaths: [ ".github/workflows/**", - "action.yaml" + "action.yaml", ], - "matchUpdateTypes": [ + matchUpdateTypes: [ "major", "minor", "digest", "patch", "pin", - "pinDigest" - ] + "pinDigest", + ], }, { - "groupName": "all go dependencies main", - "groupSlug": "all-go-deps-main", - "matchFiles": [ + groupName: "all go dependencies main", + groupSlug: "all-go-deps-main", + matchFiles: [ "go.mod", - "go.sum" + "go.sum", ], - "postUpdateOptions": [ + postUpdateOptions: [ // update source import paths on major updates "gomodUpdateImportPaths", ], - "matchUpdateTypes": [ + matchUpdateTypes: [ "major", "minor", "digest", "patch", "pin", - "pinDigest" + "pinDigest", ], matchBaseBranches: [ - "main" + "main", ], - "schedule": [ - "on friday" + schedule: [ + "on friday", ], }, { // Avoid updating patch releases of golang in go.mod - "enabled": "false", - "matchFiles": [ + enabled: "false", + matchFiles: [ "go.mod", ], - "matchDepNames": [ - "go" + matchDepNames: [ + "go", ], - "matchDatasources": [ - "golang-version" + matchDatasources: [ + "golang-version", ], - "matchUpdateTypes": [ - "patch" + matchUpdateTypes: [ + "patch", ], matchBaseBranches: [ "main", - ] + ], }, { // Allow github.com/cilium/cilium to upgrade to prerelease versions. - "ignoreUnstable": false, - "matchPackageNames": [ + ignoreUnstable: false, + matchPackageNames: [ "github.com/cilium/cilium", ], }, { // Images that directly use docker.io/library/golang for building. - "groupName": "golang-images", - "matchFiles": [ + groupName: "golang-images", + matchFiles: [ "Dockerfile", - "Makefile" - ] + "Makefile", + ], }, { - "groupName": "Go", - "matchDepNames": [ + groupName: "Go", + matchDepNames: [ "go", - "docker.io/library/golang" + "docker.io/library/golang", + ], + schedule: [ + "on friday", ], - "schedule": [ - "on friday" - ] }, { // Group golangci-lint updates to overrule grouping of version updates in the GHA files. // Without this, golangci-lint updates are not in sync for GHA files and other usages. - "groupName": "golangci-lint", - "matchDepNames": [ - "golangci/golangci-lint" - ] + groupName: "golangci-lint", + matchDepNames: [ + "golangci/golangci-lint", + ], }, { // Group cilium updates to overrule grouping of version updates in the GHA files. // Without this, cilium updates are not in sync for GHA files and other usages. - "groupName": "cilium", - "matchDepNames": [ - "cilium/cilium" - ] - } + groupName: "cilium", + matchDepNames: [ + "cilium/cilium", + ], + }, ], - "regexManagers": [ + regexManagers: [ { - "fileMatch": [ + fileMatch: [ "^\\.github/workflows/[^/]+\\.yaml$", - "^action.yaml$" + "^action.yaml$", ], + // This regex manages version strings in GitHub actions workflow files, // similar to the examples shown here: // https://docs.renovatebot.com/modules/manager/regex/#advanced-capture - "matchStrings": [ - "# renovate: datasource=(?.*?) depName=(?.*?)\\s+.+version: (?.*)" - ] + matchStrings: [ + "# renovate: datasource=(?.*?) depName=(?.*?)\\s+.+version: (?.*)", + ], }, { - "fileMatch": [ - "^Makefile$" + fileMatch: [ + "^Makefile$", ], + // This regex manages version strings in the Makefile, // similar to the examples shown here: // https://docs.renovatebot.com/modules/manager/regex/#advanced-capture - "matchStrings": [ - "# renovate: datasource=(?.*?) depName=(?.*?)\\s+.+_VERSION = (?.*)\\s+.+_SHA = (?sha256:[a-f0-9]+)" - ] + matchStrings: [ + "# renovate: datasource=(?.*?) depName=(?.*?)\\s+.+_VERSION = (?.*)\\s+.+_SHA = (?sha256:[a-f0-9]+)", + ], }, { - "fileMatch": [ - "^go\\.mod$" + fileMatch: [ + "^go\\.mod$", + ], + matchStrings: [ + "// renovate: datasource=(?.*?) depName=(?.*?)\\s+go (?.*)", ], - "matchStrings": [ - "// renovate: datasource=(?.*?) depName=(?.*?)\\s+go (?.*)" - ] }, - ] + ], } From 7c233efc5a924cbf34ada67d6c14fc5363cd1a9b Mon Sep 17 00:00:00 2001 From: David Bimmler Date: Wed, 22 Jan 2025 13:14:43 +0100 Subject: [PATCH 13/17] renovate: apply migration changes These are the actual changes to the schema, as gleaned from the messy diff of https://github.com/cilium/cilium-cli/pull/2913. Signed-off-by: David Bimmler --- .github/renovate.json5 | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index b35da89e22..173cc03b67 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -1,7 +1,7 @@ { $schema: "https://docs.renovatebot.com/renovate-schema.json", extends: [ - "config:base", + "config:recommended", ":gitSignOff", "helpers:pinGitHubActionDigests", ], @@ -44,7 +44,7 @@ { groupName: "all github action dependencies", groupSlug: "all-github-action", - matchPaths: [ + matchFileNames: [ ".github/workflows/**", "action.yaml", ], @@ -86,7 +86,7 @@ { // Avoid updating patch releases of golang in go.mod enabled: "false", - matchFiles: [ + matchFileNames: [ "go.mod", ], matchDepNames: [ @@ -112,7 +112,7 @@ { // Images that directly use docker.io/library/golang for building. groupName: "golang-images", - matchFiles: [ + matchFileNames: [ "Dockerfile", "Makefile", ], @@ -144,8 +144,9 @@ ], }, ], - regexManagers: [ + customManagers: [ { + customType: "regex", fileMatch: [ "^\\.github/workflows/[^/]+\\.yaml$", "^action.yaml$", @@ -159,6 +160,7 @@ ], }, { + customType: "regex", fileMatch: [ "^Makefile$", ], @@ -171,6 +173,7 @@ ], }, { + customType: "regex", fileMatch: [ "^go\\.mod$", ], From 9791ab5b1b3a0320652f9cfc4cfc0194ab7385c2 Mon Sep 17 00:00:00 2001 From: David Bimmler Date: Wed, 22 Jan 2025 13:15:46 +0100 Subject: [PATCH 14/17] renovate: convert double quotes to single quotes Signed-off-by: David Bimmler --- .github/renovate.json5 | 140 ++++++++++++++++++++--------------------- 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 173cc03b67..07cd5979e6 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -1,184 +1,184 @@ { - $schema: "https://docs.renovatebot.com/renovate-schema.json", + $schema: 'https://docs.renovatebot.com/renovate-schema.json', extends: [ - "config:recommended", - ":gitSignOff", - "helpers:pinGitHubActionDigests", + 'config:recommended', + ':gitSignOff', + 'helpers:pinGitHubActionDigests', ], // This ensures that the gitAuthor and gitSignOff fields match - gitAuthor: "renovate[bot] ", + gitAuthor: 'renovate[bot] ', includePaths: [ - ".github/workflows/**", - "action.yaml", - "defaults/defaults.go", - "go.mod", - "go.sum", - "Dockerfile", - "Makefile", + '.github/workflows/**', + 'action.yaml', + 'defaults/defaults.go', + 'go.mod', + 'go.sum', + 'Dockerfile', + 'Makefile', ], postUpdateOptions: [ - "gomodTidy", + 'gomodTidy', ], pinDigests: true, ignorePresets: [ - ":prHourlyLimit2", + ':prHourlyLimit2', ], separateMajorMinor: true, separateMultipleMajor: true, separateMinorPatch: true, pruneStaleBranches: true, baseBranches: [ - "main", + 'main', ], vulnerabilityAlerts: { enabled: true, }, labels: [ - "renovate/stop-updating", - "kind/enhancement", - "priority/release-blocker", + 'renovate/stop-updating', + 'kind/enhancement', + 'priority/release-blocker', ], - stopUpdatingLabel: "renovate/stop-updating", + stopUpdatingLabel: 'renovate/stop-updating', packageRules: [ { - groupName: "all github action dependencies", - groupSlug: "all-github-action", + groupName: 'all github action dependencies', + groupSlug: 'all-github-action', matchFileNames: [ - ".github/workflows/**", - "action.yaml", + '.github/workflows/**', + 'action.yaml', ], matchUpdateTypes: [ - "major", - "minor", - "digest", - "patch", - "pin", - "pinDigest", + 'major', + 'minor', + 'digest', + 'patch', + 'pin', + 'pinDigest', ], }, { - groupName: "all go dependencies main", - groupSlug: "all-go-deps-main", + groupName: 'all go dependencies main', + groupSlug: 'all-go-deps-main', matchFiles: [ - "go.mod", - "go.sum", + 'go.mod', + 'go.sum', ], postUpdateOptions: [ // update source import paths on major updates - "gomodUpdateImportPaths", + 'gomodUpdateImportPaths', ], matchUpdateTypes: [ - "major", - "minor", - "digest", - "patch", - "pin", - "pinDigest", + 'major', + 'minor', + 'digest', + 'patch', + 'pin', + 'pinDigest', ], matchBaseBranches: [ - "main", + 'main', ], schedule: [ - "on friday", + 'on friday', ], }, { // Avoid updating patch releases of golang in go.mod - enabled: "false", + enabled: 'false', matchFileNames: [ - "go.mod", + 'go.mod', ], matchDepNames: [ - "go", + 'go', ], matchDatasources: [ - "golang-version", + 'golang-version', ], matchUpdateTypes: [ - "patch", + 'patch', ], matchBaseBranches: [ - "main", + 'main', ], }, { // Allow github.com/cilium/cilium to upgrade to prerelease versions. ignoreUnstable: false, matchPackageNames: [ - "github.com/cilium/cilium", + 'github.com/cilium/cilium', ], }, { // Images that directly use docker.io/library/golang for building. - groupName: "golang-images", + groupName: 'golang-images', matchFileNames: [ - "Dockerfile", - "Makefile", + 'Dockerfile', + 'Makefile', ], }, { - groupName: "Go", + groupName: 'Go', matchDepNames: [ - "go", - "docker.io/library/golang", + 'go', + 'docker.io/library/golang', ], schedule: [ - "on friday", + 'on friday', ], }, { // Group golangci-lint updates to overrule grouping of version updates in the GHA files. // Without this, golangci-lint updates are not in sync for GHA files and other usages. - groupName: "golangci-lint", + groupName: 'golangci-lint', matchDepNames: [ - "golangci/golangci-lint", + 'golangci/golangci-lint', ], }, { // Group cilium updates to overrule grouping of version updates in the GHA files. // Without this, cilium updates are not in sync for GHA files and other usages. - groupName: "cilium", + groupName: 'cilium', matchDepNames: [ - "cilium/cilium", + 'cilium/cilium', ], }, ], customManagers: [ { - customType: "regex", + customType: 'regex', fileMatch: [ - "^\\.github/workflows/[^/]+\\.yaml$", - "^action.yaml$", + '^\\.github/workflows/[^/]+\\.yaml$', + '^action.yaml$', ], // This regex manages version strings in GitHub actions workflow files, // similar to the examples shown here: // https://docs.renovatebot.com/modules/manager/regex/#advanced-capture matchStrings: [ - "# renovate: datasource=(?.*?) depName=(?.*?)\\s+.+version: (?.*)", + '# renovate: datasource=(?.*?) depName=(?.*?)\\s+.+version: (?.*)', ], }, { - customType: "regex", + customType: 'regex', fileMatch: [ - "^Makefile$", + '^Makefile$', ], // This regex manages version strings in the Makefile, // similar to the examples shown here: // https://docs.renovatebot.com/modules/manager/regex/#advanced-capture matchStrings: [ - "# renovate: datasource=(?.*?) depName=(?.*?)\\s+.+_VERSION = (?.*)\\s+.+_SHA = (?sha256:[a-f0-9]+)", + '# renovate: datasource=(?.*?) depName=(?.*?)\\s+.+_VERSION = (?.*)\\s+.+_SHA = (?sha256:[a-f0-9]+)', ], }, { - customType: "regex", + customType: 'regex', fileMatch: [ - "^go\\.mod$", + '^go\\.mod$', ], matchStrings: [ - "// renovate: datasource=(?.*?) depName=(?.*?)\\s+go (?.*)", + '// renovate: datasource=(?.*?) depName=(?.*?)\\s+go (?.*)', ], }, ], From ebc07d9882e40cfb9e6013c44e535af6d4cdfc6e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 24 Jan 2025 09:50:52 +0000 Subject: [PATCH 15/17] chore(deps): update docker/build-push-action action to v6.13.0 Signed-off-by: renovate[bot] --- .github/workflows/images.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index e3fd8f52d0..792b594487 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -59,7 +59,7 @@ jobs: # main branch or tag pushes - name: CI Build ${{ matrix.name }} if: ${{ github.event_name != 'pull_request_target' }} - uses: docker/build-push-action@67a2d409c0a876cbe6b11854e3e25193efe4e62d # v6.12.0 + uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6.13.0 id: docker_build_ci_main with: context: . @@ -82,7 +82,7 @@ jobs: # PR updates - name: CI Build ${{ matrix.name }} if: ${{ github.event_name == 'pull_request_target' }} - uses: docker/build-push-action@67a2d409c0a876cbe6b11854e3e25193efe4e62d # v6.12.0 + uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6.13.0 id: docker_build_ci_pr with: context: . From 4a58c701c0823fd9110e7da24c8b62151a89c8a6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 28 Jan 2025 00:58:54 +0000 Subject: [PATCH 16/17] chore(deps): update aws-actions/configure-aws-credentials action to v4.0.3 Signed-off-by: renovate[bot] --- .github/workflows/eks-tunnel.yaml | 2 +- .github/workflows/eks.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/eks-tunnel.yaml b/.github/workflows/eks-tunnel.yaml index b51314e6af..da98fe8f25 100644 --- a/.github/workflows/eks-tunnel.yaml +++ b/.github/workflows/eks-tunnel.yaml @@ -64,7 +64,7 @@ jobs: rm eksctl_$(uname -s)_amd64.tar.gz - name: Set up AWS CLI credentials - uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 + uses: aws-actions/configure-aws-credentials@4fc4975a852c8cd99761e2de1f4ba73402e44dd9 # v4.0.3 with: role-to-assume: ${{ secrets.AWS_PR_ASSUME_ROLE }} aws-region: ${{ env.region }} diff --git a/.github/workflows/eks.yaml b/.github/workflows/eks.yaml index 4da81de0a2..aede372653 100644 --- a/.github/workflows/eks.yaml +++ b/.github/workflows/eks.yaml @@ -64,7 +64,7 @@ jobs: rm eksctl_$(uname -s)_amd64.tar.gz - name: Set up AWS CLI credentials - uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 + uses: aws-actions/configure-aws-credentials@4fc4975a852c8cd99761e2de1f4ba73402e44dd9 # v4.0.3 with: role-to-assume: ${{ secrets.AWS_PR_ASSUME_ROLE }} aws-region: ${{ env.region }} From a4936ec2afa58bf755162928456190344a179207 Mon Sep 17 00:00:00 2001 From: Michi Mutsuzaki Date: Wed, 29 Jan 2025 17:12:21 +0000 Subject: [PATCH 17/17] Prepare for v0.16.24 release Ref: https://github.com/cilium/cilium/commit/a50d083bc18f52d676d296ba2ed20ba97d27c13c Signed-off-by: Michi Mutsuzaki --- README.md | 2 +- RELEASE.md | 2 +- go.mod | 69 +- go.sum | 133 +- vendor/github.com/BurntSushi/toml/README.md | 2 +- vendor/github.com/BurntSushi/toml/decode.go | 93 +- .../BurntSushi/toml/decode_go116.go | 19 - .../github.com/BurntSushi/toml/deprecated.go | 12 +- vendor/github.com/BurntSushi/toml/doc.go | 3 - vendor/github.com/BurntSushi/toml/encode.go | 45 +- vendor/github.com/BurntSushi/toml/error.go | 111 +- vendor/github.com/BurntSushi/toml/lex.go | 50 +- vendor/github.com/BurntSushi/toml/meta.go | 49 +- vendor/github.com/BurntSushi/toml/parse.go | 269 +- .../github.com/BurntSushi/toml/type_fields.go | 8 +- .../github.com/BurntSushi/toml/type_toml.go | 11 +- vendor/github.com/cilium/charts/README.md | 250 +- .../cilium/charts/cilium-1.14.19.tgz | Bin 0 -> 166977 bytes .../cilium/charts/cilium-1.15.13.tgz | Bin 0 -> 180297 bytes .../cilium/charts/cilium-1.16.6.tgz | Bin 0 -> 204717 bytes .../cilium/charts/cilium-1.17.0-rc.1.tgz | Bin 0 -> 217110 bytes vendor/github.com/cilium/charts/index.yaml | 465 +- .../cilium/cilium/api/v1/flow/flow.pb.go | 4 +- .../cilium/api/v1/observer/observer.pb.go | 4 +- .../api/v1/observer/observer_grpc.pb.go | 2 +- .../cilium/cilium/api/v1/relay/relay.pb.go | 4 +- .../cilium/cilium/cilium-cli/cli/cmd.go | 2 +- .../cilium/cilium-cli/cli/connectivity.go | 2 + .../cilium/cilium/cilium-cli/cli/features.go | 31 + .../cilium/cilium/cilium-cli/cli/install.go | 3 + .../builder/client_egress_l7_set_header.go | 14 +- .../builder/client_egress_l7_tls_headers.go | 30 +- .../builder/client_egress_tls_sni.go | 18 +- .../manifests/client-egress-l7-tls-sni.yaml | 6 +- .../manifests/client-egress-l7-tls.yaml | 20 + .../manifests/client-egress-tls-sni.yaml | 9 +- .../cilium-cli/connectivity/check/check.go | 1 + .../cilium-cli/connectivity/check/context.go | 8 +- .../cilium-cli/connectivity/check/result.go | 10 + .../cilium-cli/connectivity/check/test.go | 15 +- .../cilium-cli/connectivity/tests/common.go | 7 + .../cilium-cli/connectivity/tests/errors.go | 17 +- .../cilium-cli/connectivity/tests/pod.go | 8 + .../cilium-cli/connectivity/tests/world.go | 149 + .../cilium/cilium-cli/defaults/defaults.go | 3 +- .../cilium/cilium-cli/features/features.go | 4 + .../cilium/cilium-cli/features/markdown.go | 10 +- .../cilium/cilium-cli/features/summary.go | 522 + .../cilium/cilium-cli/features/tab_writer.go | 10 +- .../cilium/cilium-cli/install/autodetect.go | 23 +- .../cilium/cilium-cli/install/install.go | 3 + .../cilium/cilium-cli/install/upgrade.go | 1 + .../cilium/cilium-cli/internal/helm/helm.go | 3 + .../cilium/cilium/cilium-cli/k8s/client.go | 72 +- .../cilium/cilium/cilium-cli/k8s/exec.go | 14 - .../cilium/cilium-cli/sysdump/client.go | 3 +- .../cilium/cilium-cli/sysdump/constants.go | 2 + .../cilium/cilium-cli/sysdump/defaults.go | 1 + .../cilium/cilium-cli/sysdump/sysdump.go | 325 +- .../cilium/cilium-cli/sysdump/writers.go | 109 +- .../cilium/cilium-cli/utils/features/utils.go | 21 + .../cilium/cilium/daemon/k8s/pods.go | 141 + .../cilium/cilium/daemon/k8s/resources.go | 13 - .../cilium/cilium/daemon/k8s/tables.go | 44 + .../cilium/cilium/pkg/allocator/allocator.go | 8 +- .../pkg/byteorder/byteorder_littleendian.go | 2 +- .../cilium/pkg/clustermesh/types/option.go | 23 + .../cilium/pkg/container/bitlpm/cidr.go | 52 +- .../cilium/pkg/container/bitlpm/trie.go | 219 +- .../cilium/pkg/container/bitlpm/unsigned.go | 135 +- .../cilium/pkg/container/versioned/value.go | 14 +- .../certificatemanager/certificate_manager.go | 54 +- .../cilium/cilium/pkg/defaults/defaults.go | 19 +- .../pkg/fqdn/matchpattern/matchpattern.go | 2 +- .../github.com/cilium/cilium/pkg/hive/hive.go | 16 - .../cilium/cilium/pkg/hubble/helpers.go | 25 - .../cilium/cilium/pkg/identity/identity.go | 2 +- .../cilium/cilium/pkg/ipcache/types/types.go | 8 +- .../pkg/k8s/apis/cilium.io/v2/ccnp_types.go | 11 - .../pkg/k8s/apis/cilium.io/v2/cnp_types.go | 11 - .../cilium/cilium/pkg/k8s/service.go | 10 +- .../cilium/cilium/pkg/k8s/service_cache.go | 23 +- .../cilium/cilium/pkg/labels/array.go | 38 +- .../cilium/cilium/pkg/labels/arraylist.go | 149 +- .../cilium/cilium/pkg/labels/labels.go | 20 + .../cilium/pkg/loadbalancer/loadbalancer.go | 25 +- .../cilium/cilium/pkg/metrics/cmd.go | 103 +- .../cilium/pkg/node/local_node_store.go | 2 + .../cilium/cilium/pkg/option/config.go | 113 +- .../cilium/cilium/pkg/policy/api/egress.go | 7 +- .../cilium/cilium/pkg/policy/api/fqdn.go | 4 +- .../cilium/cilium/pkg/policy/api/rule.go | 14 +- .../cilium/pkg/policy/api/rule_validation.go | 5 +- .../cilium/cilium/pkg/policy/api/service.go | 9 +- .../github.com/cilium/cilium/pkg/policy/l4.go | 124 +- .../cilium/cilium/pkg/policy/lookup.go | 165 + .../cilium/cilium/pkg/policy/mapstate.go | 204 +- .../cilium/cilium/pkg/policy/repository.go | 234 +- .../cilium/cilium/pkg/policy/resolve.go | 27 +- .../cilium/cilium/pkg/policy/rule.go | 16 +- .../cilium/cilium/pkg/policy/selectorcache.go | 25 +- .../pkg/policy/selectorcache_selector.go | 4 +- .../cilium/cilium/pkg/policy/types/types.go | 6 - .../cilium/cilium/pkg/source/source.go | 67 +- .../github.com/cilium/hive/script/engine.go | 7 +- .../containerd/content/local/store.go | 28 +- .../containerd/remotes/docker/resolver.go | 31 +- .../remotes/docker/resolver_unix.go | 28 + .../remotes/docker/resolver_windows.go | 30 + .../containerd/containerd/version/version.go | 2 +- .../cyphar/filepath-securejoin/CHANGELOG.md | 35 +- .../cyphar/filepath-securejoin/VERSION | 2 +- .../gocompat_errors_go120.go | 18 + .../gocompat_errors_unsupported.go | 38 + .../gocompat_generics_go121.go | 32 + .../gocompat_generics_unsupported.go | 124 + .../filepath-securejoin/lookup_linux.go | 3 +- .../cyphar/filepath-securejoin/mkdir_linux.go | 18 +- .../filepath-securejoin/openat2_linux.go | 3 +- .../filepath-securejoin/procfs_linux.go | 30 +- .../docker/docker/pkg/ioutils/bytespipe.go | 6 + .../docker/docker/pkg/ioutils/writeflusher.go | 8 +- .../docker/docker/pkg/ioutils/writers.go | 15 +- vendor/github.com/google/btree/btree.go | 2 +- .../github.com/google/go-github/v68/AUTHORS | 548 + .../github.com/google/go-github/v68/LICENSE | 27 + .../google/go-github/v68/github/actions.go | 12 + .../go-github/v68/github/actions_artifacts.go | 177 + .../go-github/v68/github/actions_cache.go | 249 + .../go-github/v68/github/actions_oidc.go | 81 + .../github/actions_permissions_enterprise.go | 258 + .../v68/github/actions_permissions_orgs.go | 271 + .../v68/github/actions_required_workflows.go | 267 + .../v68/github/actions_runner_groups.go | 337 + .../go-github/v68/github/actions_runners.go | 377 + .../go-github/v68/github/actions_secrets.go | 407 + .../go-github/v68/github/actions_variables.go | 341 + .../v68/github/actions_workflow_jobs.go | 165 + .../v68/github/actions_workflow_runs.go | 475 + .../go-github/v68/github/actions_workflows.go | 237 + .../google/go-github/v68/github/activity.go | 77 + .../go-github/v68/github/activity_events.go | 235 + .../v68/github/activity_notifications.go | 258 + .../go-github/v68/github/activity_star.go | 152 + .../go-github/v68/github/activity_watching.go | 158 + .../google/go-github/v68/github/admin.go | 123 + .../google/go-github/v68/github/admin_orgs.go | 95 + .../go-github/v68/github/admin_stats.go | 172 + .../go-github/v68/github/admin_users.go | 137 + .../google/go-github/v68/github/apps.go | 495 + .../google/go-github/v68/github/apps_hooks.go | 52 + .../v68/github/apps_hooks_deliveries.go | 78 + .../go-github/v68/github/apps_installation.go | 138 + .../go-github/v68/github/apps_manifest.go | 51 + .../go-github/v68/github/apps_marketplace.go | 207 + .../go-github/v68/github/attestations.go | 27 + .../go-github/v68/github/authorizations.go | 293 + .../google/go-github/v68/github/billing.go | 218 + .../google/go-github/v68/github/checks.go | 478 + .../go-github/v68/github/code_scanning.go | 664 + .../go-github/v68/github/codesofconduct.go | 87 + .../google/go-github/v68/github/codespaces.go | 266 + .../v68/github/codespaces_secrets.go | 451 + .../google/go-github/v68/github/copilot.go | 570 + .../google/go-github/v68/github/dependabot.go | 12 + .../go-github/v68/github/dependabot_alerts.go | 176 + .../v68/github/dependabot_secrets.go | 289 + .../go-github/v68/github/dependency_graph.go | 82 + .../v68/github/dependency_graph_snapshots.go | 113 + .../google/go-github/v68/github/doc.go | 194 + .../google/go-github/v68/github/emojis.go | 40 + .../google/go-github/v68/github/enterprise.go | 12 + .../enterprise_actions_runner_groups.go | 336 + .../v68/github/enterprise_actions_runners.go | 139 + .../v68/github/enterprise_audit_log.go | 37 + .../enterprise_code_security_and_analysis.go | 85 + .../v68/github/enterprise_properties.go | 121 + .../google/go-github/v68/github/event.go | 54 + .../go-github/v68/github/event_types.go | 1928 ++ .../google/go-github/v68/github/gists.go | 397 + .../go-github/v68/github/gists_comments.go | 128 + .../google/go-github/v68/github/git.go | 12 + .../google/go-github/v68/github/git_blobs.go | 88 + .../go-github/v68/github/git_commits.go | 224 + .../google/go-github/v68/github/git_refs.go | 185 + .../google/go-github/v68/github/git_tags.go | 88 + .../google/go-github/v68/github/git_trees.go | 166 + .../go-github/v68/github/github-accessors.go | 26951 ++++++++++++++++ .../google/go-github/v68/github/github.go | 1618 + .../google/go-github/v68/github/gitignore.go | 68 + .../go-github/v68/github/interactions.go | 28 + .../go-github/v68/github/interactions_orgs.go | 86 + .../v68/github/interactions_repos.go | 86 + .../go-github/v68/github/issue_import.go | 154 + .../google/go-github/v68/github/issues.go | 383 + .../go-github/v68/github/issues_assignees.go | 103 + .../go-github/v68/github/issues_comments.go | 165 + .../go-github/v68/github/issues_events.go | 189 + .../go-github/v68/github/issues_labels.go | 253 + .../go-github/v68/github/issues_milestones.go | 157 + .../go-github/v68/github/issues_timeline.go | 202 + .../google/go-github/v68/github/licenses.go | 101 + .../google/go-github/v68/github/markdown.go | 69 + .../google/go-github/v68/github/messages.go | 356 + .../google/go-github/v68/github/meta.go | 184 + .../google/go-github/v68/github/migrations.go | 240 + .../v68/github/migrations_source_import.go | 321 + .../go-github/v68/github/migrations_user.go | 230 + .../google/go-github/v68/github/orgs.go | 318 + .../v68/github/orgs_actions_allowed.go | 34 + .../v68/github/orgs_actions_permissions.go | 34 + .../go-github/v68/github/orgs_attestations.go | 40 + .../go-github/v68/github/orgs_audit_log.go | 142 + .../orgs_codesecurity_configurations.go | 284 + .../github/orgs_credential_authorizations.go | 109 + .../github/orgs_custom_repository_roles.go | 154 + .../google/go-github/v68/github/orgs_hooks.go | 142 + .../v68/github/orgs_hooks_configuration.go | 53 + .../v68/github/orgs_hooks_deliveries.go | 79 + .../go-github/v68/github/orgs_members.go | 436 + .../v68/github/orgs_organization_roles.go | 295 + .../v68/github/orgs_outside_collaborators.go | 87 + .../go-github/v68/github/orgs_packages.go | 180 + .../v68/github/orgs_personal_access_tokens.go | 167 + .../go-github/v68/github/orgs_properties.go | 243 + .../google/go-github/v68/github/orgs_rules.go | 115 + .../v68/github/orgs_security_managers.go | 63 + .../v68/github/orgs_users_blocking.go | 99 + .../google/go-github/v68/github/packages.go | 143 + .../google/go-github/v68/github/pulls.go | 516 + .../go-github/v68/github/pulls_comments.go | 217 + .../go-github/v68/github/pulls_reviewers.go | 106 + .../go-github/v68/github/pulls_reviews.go | 329 + .../go-github/v68/github/pulls_threads.go | 17 + .../google/go-github/v68/github/rate_limit.go | 125 + .../google/go-github/v68/github/reactions.go | 570 + .../google/go-github/v68/github/repos.go | 2428 ++ .../v68/github/repos_actions_access.go | 59 + .../v68/github/repos_actions_allowed.go | 53 + .../v68/github/repos_actions_permissions.go | 118 + .../v68/github/repos_attestations.go | 39 + .../go-github/v68/github/repos_autolinks.go | 112 + .../go-github/v68/github/repos_codeowners.go | 61 + .../v68/github/repos_collaborators.go | 178 + .../go-github/v68/github/repos_comments.go | 173 + .../go-github/v68/github/repos_commits.go | 325 + .../v68/github/repos_community_health.go | 63 + .../go-github/v68/github/repos_contents.go | 367 + .../repos_deployment_branch_policies.go | 135 + .../repos_deployment_protection_rules.go | 148 + .../go-github/v68/github/repos_deployments.go | 264 + .../v68/github/repos_environments.go | 252 + .../go-github/v68/github/repos_forks.go | 97 + .../go-github/v68/github/repos_hooks.go | 271 + .../v68/github/repos_hooks_configuration.go | 68 + .../v68/github/repos_hooks_deliveries.go | 142 + .../go-github/v68/github/repos_invitations.go | 96 + .../google/go-github/v68/github/repos_keys.go | 99 + .../google/go-github/v68/github/repos_lfs.go | 53 + .../go-github/v68/github/repos_merging.go | 76 + .../go-github/v68/github/repos_pages.go | 324 + .../v68/github/repos_prereceive_hooks.go | 118 + .../go-github/v68/github/repos_properties.go | 60 + .../go-github/v68/github/repos_releases.go | 476 + .../go-github/v68/github/repos_rules.go | 995 + .../go-github/v68/github/repos_stats.go | 242 + .../go-github/v68/github/repos_statuses.go | 138 + .../google/go-github/v68/github/repos_tags.go | 85 + .../go-github/v68/github/repos_traffic.go | 149 + .../google/go-github/v68/github/scim.go | 219 + .../google/go-github/v68/github/search.go | 347 + .../go-github/v68/github/secret_scanning.go | 261 + .../v68/github/security_advisories.go | 279 + .../google/go-github/v68/github/strings.go | 94 + .../google/go-github/v68/github/teams.go | 1100 + .../v68/github/teams_discussion_comments.go | 262 + .../go-github/v68/github/teams_discussions.go | 267 + .../go-github/v68/github/teams_members.go | 263 + .../google/go-github/v68/github/timestamp.go | 52 + .../google/go-github/v68/github/users.go | 302 + .../v68/github/users_administration.go | 80 + .../v68/github/users_attestations.go | 40 + .../go-github/v68/github/users_blocking.go | 99 + .../go-github/v68/github/users_emails.go | 105 + .../go-github/v68/github/users_followers.go | 135 + .../go-github/v68/github/users_gpg_keys.go | 138 + .../google/go-github/v68/github/users_keys.go | 122 + .../go-github/v68/github/users_packages.go | 235 + .../v68/github/users_ssh_signing_keys.go | 117 + .../go-github/v68/github/with_appengine.go | 20 + .../go-github/v68/github/without_appengine.go | 19 + .../github.com/google/go-querystring/LICENSE | 27 + .../google/go-querystring/query/encode.go | 357 + .../common/expfmt/openmetrics_create.go | 4 +- .../prometheus/common/model/metric.go | 14 +- vendor/github.com/spf13/afero/.editorconfig | 12 + vendor/github.com/spf13/afero/.golangci.yaml | 18 + vendor/github.com/spf13/afero/README.md | 2 +- vendor/github.com/spf13/afero/iofs.go | 1 - vendor/github.com/spf13/afero/memmap.go | 2 - vendor/github.com/spf13/pflag/.editorconfig | 12 + vendor/github.com/spf13/pflag/.golangci.yaml | 4 + .../vishvananda/netlink/addr_linux.go | 15 +- .../vishvananda/netlink/conntrack_linux.go | 9 +- .../github.com/vishvananda/netlink/filter.go | 29 + .../vishvananda/netlink/filter_linux.go | 49 +- .../vishvananda/netlink/link_linux.go | 4 +- .../vishvananda/netlink/nl/tc_linux.go | 40 +- .../net/http/otelhttp/common.go | 7 - .../net/http/otelhttp/config.go | 15 +- .../net/http/otelhttp/handler.go | 93 +- .../otelhttp/internal/request/body_wrapper.go | 75 + .../internal/request/resp_writer_wrapper.go | 112 + .../net/http/otelhttp/internal/semconv/env.go | 97 +- .../semconv/{v1.24.0.go => httpconv.go} | 153 +- .../http/otelhttp/internal/semconv/util.go | 11 +- .../http/otelhttp/internal/semconv/v1.20.0.go | 118 + .../otelhttp/internal/semconvutil/netconv.go | 2 +- .../net/http/otelhttp/transport.go | 64 +- .../net/http/otelhttp/version.go | 2 +- .../instrumentation/net/http/otelhttp/wrap.go | 99 - vendor/go.opentelemetry.io/otel/CHANGELOG.md | 21 +- vendor/go.opentelemetry.io/otel/README.md | 2 +- vendor/go.opentelemetry.io/otel/RELEASING.md | 6 +- .../otel/metric/noop/README.md | 3 + .../otel/metric/noop/noop.go | 281 + vendor/go.opentelemetry.io/otel/renovate.json | 6 - .../otel/semconv/v1.24.0/README.md | 3 - .../otel/semconv/v1.24.0/attribute_group.go | 4387 --- .../otel/semconv/v1.24.0/doc.go | 9 - .../otel/semconv/v1.24.0/event.go | 200 - .../otel/semconv/v1.24.0/exception.go | 9 - .../otel/semconv/v1.24.0/metric.go | 1071 - .../otel/semconv/v1.24.0/resource.go | 2545 -- .../otel/semconv/v1.24.0/schema.go | 9 - .../otel/semconv/v1.24.0/trace.go | 1323 - vendor/go.opentelemetry.io/otel/version.go | 2 +- vendor/go.opentelemetry.io/otel/versions.yaml | 6 +- vendor/golang.org/x/oauth2/oauth2.go | 2 +- vendor/google.golang.org/grpc/version.go | 2 +- .../protobuf/encoding/protojson/decode.go | 2 +- .../protobuf/encoding/prototext/decode.go | 2 +- .../protobuf/internal/flags/flags.go | 5 + .../protobuf/internal/impl/codec_map.go | 14 +- .../protobuf/internal/impl/codec_map_go111.go | 38 - .../protobuf/internal/impl/codec_map_go112.go | 12 - .../protobuf/internal/impl/codec_message.go | 4 +- .../internal/impl/codec_message_opaque.go | 6 +- .../protobuf/internal/impl/convert_map.go | 2 +- .../protobuf/internal/impl/message.go | 12 +- .../protobuf/internal/impl/message_opaque.go | 12 +- .../internal/impl/message_reflect_field.go | 56 +- .../protobuf/internal/impl/pointer_unsafe.go | 2 +- .../protobuf/internal/version/version.go | 2 +- .../protobuf/proto/decode.go | 2 +- .../reflect/protodesc/desc_validate.go | 2 +- .../protobuf/reflect/protodesc/editions.go | 31 +- .../helm/v3/internal/version/version.go | 2 +- .../helm.sh/helm/v3/pkg/action/dependency.go | 15 +- .../helm/v3/pkg/action/get_metadata.go | 55 +- vendor/helm.sh/helm/v3/pkg/action/hooks.go | 2 +- vendor/helm.sh/helm/v3/pkg/action/install.go | 1 + vendor/helm.sh/helm/v3/pkg/action/package.go | 11 +- vendor/helm.sh/helm/v3/pkg/action/push.go | 2 +- .../helm.sh/helm/v3/pkg/chart/dependency.go | 16 +- .../helm.sh/helm/v3/pkg/chart/loader/load.go | 4 +- .../helm.sh/helm/v3/pkg/chartutil/create.go | 32 +- vendor/helm.sh/helm/v3/pkg/cli/environment.go | 3 +- .../v3/pkg/downloader/chart_downloader.go | 38 +- vendor/helm.sh/helm/v3/pkg/engine/engine.go | 4 +- vendor/helm.sh/helm/v3/pkg/engine/funcs.go | 31 + vendor/helm.sh/helm/v3/pkg/getter/getter.go | 8 + .../helm.sh/helm/v3/pkg/getter/httpgetter.go | 4 + .../helm.sh/helm/v3/pkg/getter/ocigetter.go | 4 + vendor/helm.sh/helm/v3/pkg/kube/client.go | 48 +- .../helm/v3/pkg/{cli => kube}/roundtripper.go | 12 +- vendor/helm.sh/helm/v3/pkg/kube/wait.go | 2 +- .../helm.sh/helm/v3/pkg/pusher/ocipusher.go | 5 +- vendor/helm.sh/helm/v3/pkg/registry/client.go | 159 +- .../helm.sh/helm/v3/pkg/registry/reference.go | 78 + vendor/helm.sh/helm/v3/pkg/registry/util.go | 28 +- vendor/helm.sh/helm/v3/pkg/release/mock.go | 18 + .../helm/v3/pkg/storage/driver/cfgmaps.go | 5 +- .../helm/v3/pkg/storage/driver/secrets.go | 5 +- .../helm.sh/helm/v3/pkg/time/ctime/ctime.go | 6 +- .../helm/v3/pkg/time/ctime/ctime_linux.go | 4 +- .../helm/v3/pkg/time/ctime/ctime_other.go | 2 +- .../api/resource/v1alpha3/generated.proto | 2 +- vendor/k8s.io/api/resource/v1alpha3/types.go | 6 +- .../v1alpha3/types_swagger_doc_generated.go | 2 +- .../api/resource/v1beta1/generated.proto | 2 +- vendor/k8s.io/api/resource/v1beta1/types.go | 6 +- .../v1beta1/types_swagger_doc_generated.go | 2 +- vendor/k8s.io/client-go/util/retry/OWNERS | 4 + vendor/k8s.io/client-go/util/retry/util.go | 105 + vendor/modules.txt | 87 +- .../pkg/client/apiutil/restmapper.go | 125 +- .../pkg/apis/v1alpha1/serviceimport.go | 2 +- 398 files changed, 70626 insertions(+), 12073 deletions(-) delete mode 100644 vendor/github.com/BurntSushi/toml/decode_go116.go create mode 100644 vendor/github.com/cilium/charts/cilium-1.14.19.tgz create mode 100644 vendor/github.com/cilium/charts/cilium-1.15.13.tgz create mode 100644 vendor/github.com/cilium/charts/cilium-1.16.6.tgz create mode 100644 vendor/github.com/cilium/charts/cilium-1.17.0-rc.1.tgz create mode 100644 vendor/github.com/cilium/cilium/cilium-cli/features/summary.go create mode 100644 vendor/github.com/cilium/cilium/daemon/k8s/pods.go create mode 100644 vendor/github.com/cilium/cilium/daemon/k8s/tables.go delete mode 100644 vendor/github.com/cilium/cilium/pkg/hubble/helpers.go create mode 100644 vendor/github.com/cilium/cilium/pkg/policy/lookup.go create mode 100644 vendor/github.com/containerd/containerd/remotes/docker/resolver_unix.go create mode 100644 vendor/github.com/containerd/containerd/remotes/docker/resolver_windows.go create mode 100644 vendor/github.com/cyphar/filepath-securejoin/gocompat_errors_go120.go create mode 100644 vendor/github.com/cyphar/filepath-securejoin/gocompat_errors_unsupported.go create mode 100644 vendor/github.com/cyphar/filepath-securejoin/gocompat_generics_go121.go create mode 100644 vendor/github.com/cyphar/filepath-securejoin/gocompat_generics_unsupported.go create mode 100644 vendor/github.com/google/go-github/v68/AUTHORS create mode 100644 vendor/github.com/google/go-github/v68/LICENSE create mode 100644 vendor/github.com/google/go-github/v68/github/actions.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_artifacts.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_cache.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_oidc.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_permissions_enterprise.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_permissions_orgs.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_required_workflows.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_runner_groups.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_runners.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_secrets.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_variables.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_workflow_jobs.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_workflow_runs.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_workflows.go create mode 100644 vendor/github.com/google/go-github/v68/github/activity.go create mode 100644 vendor/github.com/google/go-github/v68/github/activity_events.go create mode 100644 vendor/github.com/google/go-github/v68/github/activity_notifications.go create mode 100644 vendor/github.com/google/go-github/v68/github/activity_star.go create mode 100644 vendor/github.com/google/go-github/v68/github/activity_watching.go create mode 100644 vendor/github.com/google/go-github/v68/github/admin.go create mode 100644 vendor/github.com/google/go-github/v68/github/admin_orgs.go create mode 100644 vendor/github.com/google/go-github/v68/github/admin_stats.go create mode 100644 vendor/github.com/google/go-github/v68/github/admin_users.go create mode 100644 vendor/github.com/google/go-github/v68/github/apps.go create mode 100644 vendor/github.com/google/go-github/v68/github/apps_hooks.go create mode 100644 vendor/github.com/google/go-github/v68/github/apps_hooks_deliveries.go create mode 100644 vendor/github.com/google/go-github/v68/github/apps_installation.go create mode 100644 vendor/github.com/google/go-github/v68/github/apps_manifest.go create mode 100644 vendor/github.com/google/go-github/v68/github/apps_marketplace.go create mode 100644 vendor/github.com/google/go-github/v68/github/attestations.go create mode 100644 vendor/github.com/google/go-github/v68/github/authorizations.go create mode 100644 vendor/github.com/google/go-github/v68/github/billing.go create mode 100644 vendor/github.com/google/go-github/v68/github/checks.go create mode 100644 vendor/github.com/google/go-github/v68/github/code_scanning.go create mode 100644 vendor/github.com/google/go-github/v68/github/codesofconduct.go create mode 100644 vendor/github.com/google/go-github/v68/github/codespaces.go create mode 100644 vendor/github.com/google/go-github/v68/github/codespaces_secrets.go create mode 100644 vendor/github.com/google/go-github/v68/github/copilot.go create mode 100644 vendor/github.com/google/go-github/v68/github/dependabot.go create mode 100644 vendor/github.com/google/go-github/v68/github/dependabot_alerts.go create mode 100644 vendor/github.com/google/go-github/v68/github/dependabot_secrets.go create mode 100644 vendor/github.com/google/go-github/v68/github/dependency_graph.go create mode 100644 vendor/github.com/google/go-github/v68/github/dependency_graph_snapshots.go create mode 100644 vendor/github.com/google/go-github/v68/github/doc.go create mode 100644 vendor/github.com/google/go-github/v68/github/emojis.go create mode 100644 vendor/github.com/google/go-github/v68/github/enterprise.go create mode 100644 vendor/github.com/google/go-github/v68/github/enterprise_actions_runner_groups.go create mode 100644 vendor/github.com/google/go-github/v68/github/enterprise_actions_runners.go create mode 100644 vendor/github.com/google/go-github/v68/github/enterprise_audit_log.go create mode 100644 vendor/github.com/google/go-github/v68/github/enterprise_code_security_and_analysis.go create mode 100644 vendor/github.com/google/go-github/v68/github/enterprise_properties.go create mode 100644 vendor/github.com/google/go-github/v68/github/event.go create mode 100644 vendor/github.com/google/go-github/v68/github/event_types.go create mode 100644 vendor/github.com/google/go-github/v68/github/gists.go create mode 100644 vendor/github.com/google/go-github/v68/github/gists_comments.go create mode 100644 vendor/github.com/google/go-github/v68/github/git.go create mode 100644 vendor/github.com/google/go-github/v68/github/git_blobs.go create mode 100644 vendor/github.com/google/go-github/v68/github/git_commits.go create mode 100644 vendor/github.com/google/go-github/v68/github/git_refs.go create mode 100644 vendor/github.com/google/go-github/v68/github/git_tags.go create mode 100644 vendor/github.com/google/go-github/v68/github/git_trees.go create mode 100644 vendor/github.com/google/go-github/v68/github/github-accessors.go create mode 100644 vendor/github.com/google/go-github/v68/github/github.go create mode 100644 vendor/github.com/google/go-github/v68/github/gitignore.go create mode 100644 vendor/github.com/google/go-github/v68/github/interactions.go create mode 100644 vendor/github.com/google/go-github/v68/github/interactions_orgs.go create mode 100644 vendor/github.com/google/go-github/v68/github/interactions_repos.go create mode 100644 vendor/github.com/google/go-github/v68/github/issue_import.go create mode 100644 vendor/github.com/google/go-github/v68/github/issues.go create mode 100644 vendor/github.com/google/go-github/v68/github/issues_assignees.go create mode 100644 vendor/github.com/google/go-github/v68/github/issues_comments.go create mode 100644 vendor/github.com/google/go-github/v68/github/issues_events.go create mode 100644 vendor/github.com/google/go-github/v68/github/issues_labels.go create mode 100644 vendor/github.com/google/go-github/v68/github/issues_milestones.go create mode 100644 vendor/github.com/google/go-github/v68/github/issues_timeline.go create mode 100644 vendor/github.com/google/go-github/v68/github/licenses.go create mode 100644 vendor/github.com/google/go-github/v68/github/markdown.go create mode 100644 vendor/github.com/google/go-github/v68/github/messages.go create mode 100644 vendor/github.com/google/go-github/v68/github/meta.go create mode 100644 vendor/github.com/google/go-github/v68/github/migrations.go create mode 100644 vendor/github.com/google/go-github/v68/github/migrations_source_import.go create mode 100644 vendor/github.com/google/go-github/v68/github/migrations_user.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_actions_allowed.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_actions_permissions.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_attestations.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_audit_log.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_codesecurity_configurations.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_credential_authorizations.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_custom_repository_roles.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_hooks.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_hooks_configuration.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_hooks_deliveries.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_members.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_organization_roles.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_outside_collaborators.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_packages.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_personal_access_tokens.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_properties.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_rules.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_security_managers.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_users_blocking.go create mode 100644 vendor/github.com/google/go-github/v68/github/packages.go create mode 100644 vendor/github.com/google/go-github/v68/github/pulls.go create mode 100644 vendor/github.com/google/go-github/v68/github/pulls_comments.go create mode 100644 vendor/github.com/google/go-github/v68/github/pulls_reviewers.go create mode 100644 vendor/github.com/google/go-github/v68/github/pulls_reviews.go create mode 100644 vendor/github.com/google/go-github/v68/github/pulls_threads.go create mode 100644 vendor/github.com/google/go-github/v68/github/rate_limit.go create mode 100644 vendor/github.com/google/go-github/v68/github/reactions.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_actions_access.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_actions_allowed.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_actions_permissions.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_attestations.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_autolinks.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_codeowners.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_collaborators.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_comments.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_commits.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_community_health.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_contents.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_deployment_branch_policies.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_deployment_protection_rules.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_deployments.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_environments.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_forks.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_hooks.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_hooks_configuration.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_hooks_deliveries.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_invitations.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_keys.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_lfs.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_merging.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_pages.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_prereceive_hooks.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_properties.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_releases.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_rules.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_stats.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_statuses.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_tags.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_traffic.go create mode 100644 vendor/github.com/google/go-github/v68/github/scim.go create mode 100644 vendor/github.com/google/go-github/v68/github/search.go create mode 100644 vendor/github.com/google/go-github/v68/github/secret_scanning.go create mode 100644 vendor/github.com/google/go-github/v68/github/security_advisories.go create mode 100644 vendor/github.com/google/go-github/v68/github/strings.go create mode 100644 vendor/github.com/google/go-github/v68/github/teams.go create mode 100644 vendor/github.com/google/go-github/v68/github/teams_discussion_comments.go create mode 100644 vendor/github.com/google/go-github/v68/github/teams_discussions.go create mode 100644 vendor/github.com/google/go-github/v68/github/teams_members.go create mode 100644 vendor/github.com/google/go-github/v68/github/timestamp.go create mode 100644 vendor/github.com/google/go-github/v68/github/users.go create mode 100644 vendor/github.com/google/go-github/v68/github/users_administration.go create mode 100644 vendor/github.com/google/go-github/v68/github/users_attestations.go create mode 100644 vendor/github.com/google/go-github/v68/github/users_blocking.go create mode 100644 vendor/github.com/google/go-github/v68/github/users_emails.go create mode 100644 vendor/github.com/google/go-github/v68/github/users_followers.go create mode 100644 vendor/github.com/google/go-github/v68/github/users_gpg_keys.go create mode 100644 vendor/github.com/google/go-github/v68/github/users_keys.go create mode 100644 vendor/github.com/google/go-github/v68/github/users_packages.go create mode 100644 vendor/github.com/google/go-github/v68/github/users_ssh_signing_keys.go create mode 100644 vendor/github.com/google/go-github/v68/github/with_appengine.go create mode 100644 vendor/github.com/google/go-github/v68/github/without_appengine.go create mode 100644 vendor/github.com/google/go-querystring/LICENSE create mode 100644 vendor/github.com/google/go-querystring/query/encode.go create mode 100644 vendor/github.com/spf13/afero/.editorconfig create mode 100644 vendor/github.com/spf13/afero/.golangci.yaml create mode 100644 vendor/github.com/spf13/pflag/.editorconfig create mode 100644 vendor/github.com/spf13/pflag/.golangci.yaml create mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/body_wrapper.go create mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/resp_writer_wrapper.go rename vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/{v1.24.0.go => httpconv.go} (57%) delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/wrap.go create mode 100644 vendor/go.opentelemetry.io/otel/metric/noop/README.md create mode 100644 vendor/go.opentelemetry.io/otel/metric/noop/noop.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.24.0/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.24.0/attribute_group.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.24.0/doc.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.24.0/event.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.24.0/exception.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.24.0/metric.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.24.0/resource.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.24.0/schema.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.24.0/trace.go delete mode 100644 vendor/google.golang.org/protobuf/internal/impl/codec_map_go111.go delete mode 100644 vendor/google.golang.org/protobuf/internal/impl/codec_map_go112.go rename vendor/helm.sh/helm/v3/pkg/{cli => kube}/roundtripper.go (87%) create mode 100644 vendor/helm.sh/helm/v3/pkg/registry/reference.go create mode 100644 vendor/k8s.io/client-go/util/retry/OWNERS create mode 100644 vendor/k8s.io/client-go/util/retry/util.go diff --git a/README.md b/README.md index fc1a305bec..708a7f11ce 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ binary releases. | Release | Maintained | Compatible Cilium Versions | |------------------------------------------------------------------------|------------|----------------------------| -| [v0.16.23](https://github.com/cilium/cilium-cli/releases/tag/v0.16.23) | Yes | Cilium 1.15 and newer | +| [v0.16.24](https://github.com/cilium/cilium-cli/releases/tag/v0.16.24) | Yes | Cilium 1.15 and newer | | [v0.15.22](https://github.com/cilium/cilium-cli/releases/tag/v0.15.22) | Yes | Cilium 1.14 (*) | Note: diff --git a/RELEASE.md b/RELEASE.md index 8e7f0c3516..7b1b16ee15 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -19,7 +19,7 @@ table](https://github.com/cilium/cilium-cli#releases) for the most recent suppor Set `RELEASE` environment variable to the new version. This variable will be used in the commands throughout the documenat to allow copy-pasting. - export RELEASE=v0.16.24 + export RELEASE=v0.16.25 ## Update local checkout diff --git a/go.mod b/go.mod index 1b5c5aa0d1..0d76f59c37 100644 --- a/go.mod +++ b/go.mod @@ -4,19 +4,20 @@ module github.com/cilium/cilium-cli go 1.23.0 // Replace directives from github.com/cilium/cilium. Keep in sync when updating Cilium! -// Copied from https://github.com/cilium/cilium/blob/a34e1653699191ee1b4b379d43c609765e263363/go.mod#L323-L325 +// Copied from https://github.com/cilium/cilium/blob/a50d083bc18f52d676d296ba2ed20ba97d27c13c/go.mod#L318-L320 + // Using private fork of controller-tools. See commit msg for more context // as to why we are using a private fork. replace sigs.k8s.io/controller-tools => github.com/cilium/controller-tools v0.16.5-1 -require github.com/cilium/cilium v1.17.0-pre.3.0.20250108154004-47bb433883b2 +require github.com/cilium/cilium v1.17.0-pre.3.0.20250129155153-a50d083bc18f require ( cel.dev/expr v0.18.0 // indirect dario.cat/mergo v1.0.1 // indirect github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.3.0 // indirect @@ -28,27 +29,27 @@ require ( github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect - github.com/cilium/charts v0.0.0-20241218153829-9518b30a2027 // indirect + github.com/cilium/charts v0.0.0-20250122005123-9aa3c2db578d // indirect github.com/cilium/ebpf v0.17.1 // indirect - github.com/cilium/hive v0.0.0-20241213121623-605c1412b9b3 // indirect + github.com/cilium/hive v0.0.0-20250121145729-e67f66eb0375 // indirect github.com/cilium/proxy v0.0.0-20241219105110-b2e1bb5839df // indirect github.com/cilium/statedb v0.3.5 // indirect github.com/cilium/stream v0.0.0-20241203114243-53c3e5d79744 // indirect github.com/cilium/workerpool v1.2.0 // indirect github.com/cloudflare/cfssl v1.6.5 // indirect github.com/cncf/xds/go v0.0.0-20241213214725-57cfbe6fad57 // indirect - github.com/containerd/containerd v1.7.23 // indirect + github.com/containerd/containerd v1.7.24 // indirect github.com/containerd/errdefs v0.3.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect - github.com/cyphar/filepath-securejoin v0.3.4 // indirect + github.com/cyphar/filepath-securejoin v0.3.6 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/cli v25.0.1+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect - github.com/docker/docker v27.4.1+incompatible // indirect + github.com/docker/docker v27.5.1+incompatible // indirect github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-metrics v0.0.1 // indirect @@ -78,10 +79,12 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/golang/protobuf v1.5.4 // indirect - github.com/google/btree v1.1.2 // indirect + github.com/google/btree v1.1.3 // indirect github.com/google/certificate-transparency-go v1.1.7 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect + github.com/google/go-github/v68 v68.0.0 // indirect + github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/gops v0.3.28 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect @@ -136,10 +139,10 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.61.0 // indirect + github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rivo/uniseg v0.4.4 // indirect - github.com/rubenv/sql-migrate v1.7.0 // indirect + github.com/rubenv/sql-migrate v1.7.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect @@ -147,13 +150,13 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/afero v1.12.0 // indirect github.com/spf13/cast v1.7.1 // indirect github.com/spf13/cobra v1.8.1 // indirect - github.com/spf13/pflag v1.0.6-0.20210604193023-d5e0c0615ace // indirect + github.com/spf13/pflag v1.0.6-0.20250109003754-5ca813443bd2 // indirect github.com/spf13/viper v1.19.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/vishvananda/netlink v1.3.1-0.20241227191253-26ee0e2abe2d // indirect + github.com/vishvananda/netlink v1.3.1-0.20250121061148-364253875734 // indirect github.com/vishvananda/netns v0.0.5 // indirect github.com/weppos/publicsuffix-go v0.30.0 // indirect github.com/x448/float16 v0.8.4 // indirect @@ -168,10 +171,10 @@ require ( go.etcd.io/etcd/client/v3 v3.5.17 // indirect go.mongodb.org/mongo-driver v1.14.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect - go.opentelemetry.io/otel v1.33.0 // indirect - go.opentelemetry.io/otel/metric v1.33.0 // indirect - go.opentelemetry.io/otel/trace v1.33.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect + go.opentelemetry.io/otel v1.34.0 // indirect + go.opentelemetry.io/otel/metric v1.34.0 // indirect + go.opentelemetry.io/otel/trace v1.34.0 // indirect go.opentelemetry.io/proto/otlp v1.4.0 // indirect go.uber.org/dig v1.17.1 // indirect go.uber.org/multierr v1.11.0 // indirect @@ -180,7 +183,7 @@ require ( golang.org/x/crypto v0.32.0 // indirect golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa // indirect golang.org/x/net v0.34.0 // indirect - golang.org/x/oauth2 v0.24.0 // indirect + golang.org/x/oauth2 v0.25.0 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/term v0.28.0 // indirect @@ -188,32 +191,32 @@ require ( golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.29.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20241216192217-9240e9c98484 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250106144421-5f5ef82da422 // indirect - google.golang.org/grpc v1.69.2 // indirect - google.golang.org/protobuf v1.36.2 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250122153221-138b5a5a4fd4 // indirect + google.golang.org/grpc v1.69.4 // indirect + google.golang.org/protobuf v1.36.3 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - helm.sh/helm/v3 v3.16.4 // indirect - k8s.io/api v0.32.0 // indirect - k8s.io/apiextensions-apiserver v0.32.0 // indirect - k8s.io/apimachinery v0.32.0 // indirect - k8s.io/apiserver v0.32.0 // indirect - k8s.io/cli-runtime v0.32.0 // indirect - k8s.io/client-go v0.32.0 // indirect - k8s.io/component-base v0.32.0 // indirect + helm.sh/helm/v3 v3.17.0 // indirect + k8s.io/api v0.32.1 // indirect + k8s.io/apiextensions-apiserver v0.32.1 // indirect + k8s.io/apimachinery v0.32.1 // indirect + k8s.io/apiserver v0.32.1 // indirect + k8s.io/cli-runtime v0.32.1 // indirect + k8s.io/client-go v0.32.1 // indirect + k8s.io/component-base v0.32.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect - k8s.io/kubectl v0.32.0 // indirect + k8s.io/kubectl v0.32.1 // indirect k8s.io/utils v0.0.0-20241210054802-24370beab758 // indirect oras.land/oras-go v1.2.5 // indirect - sigs.k8s.io/controller-runtime v0.19.3 // indirect + sigs.k8s.io/controller-runtime v0.20.1 // indirect sigs.k8s.io/gateway-api v1.2.1 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect sigs.k8s.io/kustomize/api v0.18.0 // indirect sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect - sigs.k8s.io/mcs-api v0.1.1-0.20241217092652-fede3192824f // indirect + sigs.k8s.io/mcs-api v0.1.1-0.20250116162235-62ede9a032dc // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/go.sum b/go.sum index 84a4374c58..3637569d79 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8af github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= @@ -54,14 +54,14 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= -github.com/cilium/charts v0.0.0-20241218153829-9518b30a2027 h1:DffBrEg57RLbc1jzajDDRYgTqWw1gr02+sMnzQp8yks= -github.com/cilium/charts v0.0.0-20241218153829-9518b30a2027/go.mod h1:M3C9VOlFvRzuV+a01t07Tw4uFLSfkCH3L542IWjf6BU= -github.com/cilium/cilium v1.17.0-pre.3.0.20250108154004-47bb433883b2 h1:OchA13nVom6cJbv3JKt2R1Qmg0CY3uw5e4llxDusxYA= -github.com/cilium/cilium v1.17.0-pre.3.0.20250108154004-47bb433883b2/go.mod h1:UTaLU297951gY5wxCGShvANCLv31z3U9Tm62creoYpo= +github.com/cilium/charts v0.0.0-20250122005123-9aa3c2db578d h1:LHfNg3xAHRnM/lhlG/nqFf7gQOXwaOg4AvsK5wVJi8M= +github.com/cilium/charts v0.0.0-20250122005123-9aa3c2db578d/go.mod h1:M3C9VOlFvRzuV+a01t07Tw4uFLSfkCH3L542IWjf6BU= +github.com/cilium/cilium v1.17.0-pre.3.0.20250129155153-a50d083bc18f h1:NPkFHPlXg7SDNIHl3ZC5x6kQ3dGjFjoehy2V423iQkI= +github.com/cilium/cilium v1.17.0-pre.3.0.20250129155153-a50d083bc18f/go.mod h1:bRqIXIkzYoKPyPNHSe2fEc1yfOhpNqvCtC/kKfseDcE= github.com/cilium/ebpf v0.17.1 h1:G8mzU81R2JA1nE5/8SRubzqvBMmAmri2VL8BIZPWvV0= github.com/cilium/ebpf v0.17.1/go.mod h1:vay2FaYSmIlv3r8dNACd4mW/OCaZLJKJOo+IHBvCIO8= -github.com/cilium/hive v0.0.0-20241213121623-605c1412b9b3 h1:RfmUH1ouzj0LzORYJRhp43e1rlGpx6GNv4NIRUakU2w= -github.com/cilium/hive v0.0.0-20241213121623-605c1412b9b3/go.mod h1:pI2GJ1n3SLKIQVFrKF7W6A6gb6BQkZ+3Hp4PAEo5SuI= +github.com/cilium/hive v0.0.0-20250121145729-e67f66eb0375 h1:EhoCO0AI3qJavnhfAls4w7VpVVpAr12wIh293sNA0hQ= +github.com/cilium/hive v0.0.0-20250121145729-e67f66eb0375/go.mod h1:pI2GJ1n3SLKIQVFrKF7W6A6gb6BQkZ+3Hp4PAEo5SuI= github.com/cilium/proxy v0.0.0-20241219105110-b2e1bb5839df h1:wrv1jOKhBnFOhHb9jpE/C6Fm2kaXUDvT0HrdoeETLnQ= github.com/cilium/proxy v0.0.0-20241219105110-b2e1bb5839df/go.mod h1:BsqJTwrsaSy5DsyH+y5zATYYCsg8/fc/K0qnsNM+43A= github.com/cilium/statedb v0.3.5 h1:/lN7noYjC+JP6+fII7dhUNRS2FuLrlE0CtNOtuBtI9c= @@ -76,8 +76,8 @@ github.com/cncf/xds/go v0.0.0-20241213214725-57cfbe6fad57 h1:put7Je9ZyxbHtwr7IqG github.com/cncf/xds/go v0.0.0-20241213214725-57cfbe6fad57/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= -github.com/containerd/containerd v1.7.23 h1:H2CClyUkmpKAGlhQp95g2WXHfLYc7whAuvZGBNYOOwQ= -github.com/containerd/containerd v1.7.23/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw= +github.com/containerd/containerd v1.7.24 h1:zxszGrGjrra1yYJW/6rhm9cJ1ZQ8rkKBR48brqsa7nA= +github.com/containerd/containerd v1.7.24/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw= github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/containerd/errdefs v0.3.0 h1:FSZgGOeK4yuT/+DnF07/Olde/q4KBoMsaamhXxIMDp4= @@ -93,8 +93,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/cyphar/filepath-securejoin v0.3.4 h1:VBWugsJh2ZxJmLFSM06/0qzQyiQX2Qs0ViKrUAcqdZ8= -github.com/cyphar/filepath-securejoin v0.3.4/go.mod h1:8s/MCNJREmFK0H02MF6Ihv1nakJe4L/w3WZLHNkvlYM= +github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM= +github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -107,8 +107,8 @@ github.com/docker/cli v25.0.1+incompatible h1:mFpqnrS6Hsm3v1k7Wa/BO23oz0k121MTbT github.com/docker/cli v25.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v27.4.1+incompatible h1:ZJvcY7gfwHn1JF48PfbyXg7Jyt9ZCWDW+GGXOIxEwp4= -github.com/docker/docker v27.4.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.5.1+incompatible h1:4PYU5dnBYqRQi0294d1FBECqT9ECWeQAIfE8q4YnPY8= +github.com/docker/docker v27.5.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= @@ -201,18 +201,23 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k= github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= -github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= -github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/certificate-transparency-go v1.1.7 h1:IASD+NtgSTJLPdzkthwvAG1ZVbF2WtFg4IvoA68XGSw= github.com/google/certificate-transparency-go v1.1.7/go.mod h1:FSSBo8fyMVgqptbfF6j5p/XNdgQftAhSmXcIxV9iphE= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-github/v68 v68.0.0 h1:ZW57zeNZiXTdQ16qrDiZ0k6XucrxZ2CGmoTvcCyQG6s= +github.com/google/go-github/v68 v68.0.0/go.mod h1:K9HAUBovM2sLwM408A18h+wd9vqdLOEqTUCbnRIcx68= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -397,8 +402,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ= -github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s= +github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= +github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= @@ -409,8 +414,8 @@ github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= -github.com/rubenv/sql-migrate v1.7.0 h1:HtQq1xyTN2ISmQDggnh0c9U3JlP8apWh8YO2jzlXpTI= -github.com/rubenv/sql-migrate v1.7.0/go.mod h1:S4wtDEG1CKn+0ShpTtzWhFpHHI5PvCUtiGI+C+Z2THE= +github.com/rubenv/sql-migrate v1.7.1 h1:f/o0WgfO/GqNuVg+6801K/KW3WdDSupzSjDYODmiUq4= +github.com/rubenv/sql-migrate v1.7.1/go.mod h1:Ob2Psprc0/3ggbM6wCzyYVFFuc6FyZrb2AS+ezLDFb4= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= @@ -431,15 +436,15 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= -github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= -github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= +github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.6-0.20210604193023-d5e0c0615ace h1:9PNP1jnUjRhfmGMlkXHjYPishpcw4jpSt/V/xYY3FMA= -github.com/spf13/pflag v1.0.6-0.20210604193023-d5e0c0615ace/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.6-0.20250109003754-5ca813443bd2 h1:VXx/BSJSJC/DjbDkZMZw8MhF9at8Rxo5I0PrDA5Bui4= +github.com/spf13/pflag v1.0.6-0.20250109003754-5ca813443bd2/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -462,8 +467,8 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/vishvananda/netlink v1.3.1-0.20241227191253-26ee0e2abe2d h1:aho1TDN+owyRC4gMe3PRewg0yBVdBsMg5kO9PYvzjo8= -github.com/vishvananda/netlink v1.3.1-0.20241227191253-26ee0e2abe2d/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs= +github.com/vishvananda/netlink v1.3.1-0.20250121061148-364253875734 h1:JORba7blBByKVn3heVQNxLZqLl5PZn/5Dzao98bVH7A= +github.com/vishvananda/netlink v1.3.1-0.20250121061148-364253875734/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs= github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY= github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= @@ -515,18 +520,18 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= -go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw= -go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I= -go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ= -go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= -go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s= -go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= go.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg= go.opentelemetry.io/proto/otlp v1.4.0/go.mod h1:PPBWZIP98o2ElSqI35IHfu7hIhSwvc5N38Jw8pXuGFY= go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc= @@ -573,8 +578,8 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= -golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= -golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= +golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -642,12 +647,12 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto/googleapis/api v0.0.0-20241216192217-9240e9c98484 h1:ChAdCYNQFDk5fYvFZMywKLIijG7TC2m1C2CMEu11G3o= google.golang.org/genproto/googleapis/api v0.0.0-20241216192217-9240e9c98484/go.mod h1:KRUmxRI4JmbpAm8gcZM4Jsffi859fo5LQjILwuqj9z8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250106144421-5f5ef82da422 h1:3UsHvIr4Wc2aW4brOaSCmcxh9ksica6fHEr8P1XhkYw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250106144421-5f5ef82da422/go.mod h1:3ENsm/5D1mzDyhpzeRi1NR784I0BcofWBoSc5QqqMK4= -google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU= -google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.2 h1:R8FeyR1/eLmkutZOM5CWghmo5itiG9z0ktFlTVLuTmU= -google.golang.org/protobuf v1.36.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250122153221-138b5a5a4fd4 h1:yrTuav+chrF0zF/joFGICKTzYv7mh/gr9AgEXrVU8ao= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250122153221-138b5a5a4fd4/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= +google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= +google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= +google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= +google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -669,34 +674,34 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= -helm.sh/helm/v3 v3.16.4 h1:rBn/h9MACw+QlhxQTjpl8Ifx+VTWaYsw3rguGBYBzr0= -helm.sh/helm/v3 v3.16.4/go.mod h1:k8QPotUt57wWbi90w3LNmg3/MWcLPigVv+0/X4B8BzA= -k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE= -k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0= -k8s.io/apiextensions-apiserver v0.32.0 h1:S0Xlqt51qzzqjKPxfgX1xh4HBZE+p8KKBq+k2SWNOE0= -k8s.io/apiextensions-apiserver v0.32.0/go.mod h1:86hblMvN5yxMvZrZFX2OhIHAuFIMJIZ19bTvzkP+Fmw= -k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg= -k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= -k8s.io/apiserver v0.32.0 h1:VJ89ZvQZ8p1sLeiWdRJpRD6oLozNZD2+qVSLi+ft5Qs= -k8s.io/apiserver v0.32.0/go.mod h1:HFh+dM1/BE/Hm4bS4nTXHVfN6Z6tFIZPi649n83b4Ag= -k8s.io/cli-runtime v0.32.0 h1:dP+OZqs7zHPpGQMCGAhectbHU2SNCuZtIimRKTv2T1c= -k8s.io/cli-runtime v0.32.0/go.mod h1:Mai8ht2+esoDRK5hr861KRy6z0zHsSTYttNVJXgP3YQ= -k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8= -k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8= -k8s.io/component-base v0.32.0 h1:d6cWHZkCiiep41ObYQS6IcgzOUQUNpywm39KVYaUqzU= -k8s.io/component-base v0.32.0/go.mod h1:JLG2W5TUxUu5uDyKiH2R/7NnxJo1HlPoRIIbVLkK5eM= +helm.sh/helm/v3 v3.17.0 h1:DUD4AGdNVn7PSTYfxe1gmQG7s18QeWv/4jI9TubnhT0= +helm.sh/helm/v3 v3.17.0/go.mod h1:Mo7eGyKPPHlS0Ml67W8z/lbkox/gD9Xt1XpD6bxvZZA= +k8s.io/api v0.32.1 h1:f562zw9cy+GvXzXf0CKlVQ7yHJVYzLfL6JAS4kOAaOc= +k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k= +k8s.io/apiextensions-apiserver v0.32.1 h1:hjkALhRUeCariC8DiVmb5jj0VjIc1N0DREP32+6UXZw= +k8s.io/apiextensions-apiserver v0.32.1/go.mod h1:sxWIGuGiYov7Io1fAS2X06NjMIk5CbRHc2StSmbaQto= +k8s.io/apimachinery v0.32.1 h1:683ENpaCBjma4CYqsmZyhEzrGz6cjn1MY/X2jB2hkZs= +k8s.io/apimachinery v0.32.1/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= +k8s.io/apiserver v0.32.1 h1:oo0OozRos66WFq87Zc5tclUX2r0mymoVHRq8JmR7Aak= +k8s.io/apiserver v0.32.1/go.mod h1:UcB9tWjBY7aryeI5zAgzVJB/6k7E97bkr1RgqDz0jPw= +k8s.io/cli-runtime v0.32.1 h1:19nwZPlYGJPUDbhAxDIS2/oydCikvKMHsxroKNGA2mM= +k8s.io/cli-runtime v0.32.1/go.mod h1:NJPbeadVFnV2E7B7vF+FvU09mpwYlZCu8PqjzfuOnkY= +k8s.io/client-go v0.32.1 h1:otM0AxdhdBIaQh7l1Q0jQpmo7WOFIk5FFa4bg6YMdUU= +k8s.io/client-go v0.32.1/go.mod h1:aTTKZY7MdxUaJ/KiUs8D+GssR9zJZi77ZqtzcGXIiDg= +k8s.io/component-base v0.32.1 h1:/5IfJ0dHIKBWysGV0yKTFfacZ5yNV1sulPh3ilJjRZk= +k8s.io/component-base v0.32.1/go.mod h1:j1iMMHi/sqAHeG5z+O9BFNCF698a1u0186zkjMZQ28w= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= -k8s.io/kubectl v0.32.0 h1:rpxl+ng9qeG79YA4Em9tLSfX0G8W0vfaiPVrc/WR7Xw= -k8s.io/kubectl v0.32.0/go.mod h1:qIjSX+QgPQUgdy8ps6eKsYNF+YmFOAO3WygfucIqFiE= +k8s.io/kubectl v0.32.1 h1:/btLtXLQUU1rWx8AEvX9jrb9LaI6yeezt3sFALhB8M8= +k8s.io/kubectl v0.32.1/go.mod h1:sezNuyWi1STk4ZNPVRIFfgjqMI6XMf+oCVLjZen/pFQ= k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0= k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo= oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo= -sigs.k8s.io/controller-runtime v0.19.3 h1:XO2GvC9OPftRst6xWCpTgBZO04S2cbp0Qqkj8bX1sPw= -sigs.k8s.io/controller-runtime v0.19.3/go.mod h1:j4j87DqtsThvwTv5/Tc5NFRyyF/RF0ip4+62tbTSIUM= +sigs.k8s.io/controller-runtime v0.20.1 h1:JbGMAG/X94NeM3xvjenVUaBjy6Ui4Ogd/J5ZtjZnHaE= +sigs.k8s.io/controller-runtime v0.20.1/go.mod h1:BrP3w158MwvB3ZbNpaAcIKkHQ7YGpYnzpoSTZ8E14WU= sigs.k8s.io/gateway-api v1.2.1 h1:fZZ/+RyRb+Y5tGkwxFKuYuSRQHu9dZtbjenblleOLHM= sigs.k8s.io/gateway-api v1.2.1/go.mod h1:EpNfEXNjiYfUJypf0eZ0P5iXA9ekSGWaS1WgPaM42X0= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= @@ -705,8 +710,8 @@ sigs.k8s.io/kustomize/api v0.18.0 h1:hTzp67k+3NEVInwz5BHyzc9rGxIauoXferXyjv5lWPo sigs.k8s.io/kustomize/api v0.18.0/go.mod h1:f8isXnX+8b+SGLHQ6yO4JG1rdkZlvhaCf/uZbLVMb0U= sigs.k8s.io/kustomize/kyaml v0.18.1 h1:WvBo56Wzw3fjS+7vBjN6TeivvpbW9GmRaWZ9CIVmt4E= sigs.k8s.io/kustomize/kyaml v0.18.1/go.mod h1:C3L2BFVU1jgcddNBE1TxuVLgS46TjObMwW5FT9FcjYo= -sigs.k8s.io/mcs-api v0.1.1-0.20241217092652-fede3192824f h1:nNsLiQPASpDDB5dNq96rmVCvQ3p5B5ChEAsh0Nq0VC0= -sigs.k8s.io/mcs-api v0.1.1-0.20241217092652-fede3192824f/go.mod h1:x0rgWQwGd3FJzrb94BNn3Nu7YxUwBWcgjVRbkrkVy2A= +sigs.k8s.io/mcs-api v0.1.1-0.20250116162235-62ede9a032dc h1:oQrn1nrTacXiaXEYg+0TozPznSDIHFl2U/KZ5UFiYT8= +sigs.k8s.io/mcs-api v0.1.1-0.20250116162235-62ede9a032dc/go.mod h1:Uicqc5FnWP4dco2y7+AEg2mzNN20mVX1TDB3aDfmvhc= sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= diff --git a/vendor/github.com/BurntSushi/toml/README.md b/vendor/github.com/BurntSushi/toml/README.md index 3651cfa960..639e6c3998 100644 --- a/vendor/github.com/BurntSushi/toml/README.md +++ b/vendor/github.com/BurntSushi/toml/README.md @@ -9,7 +9,7 @@ See the [releases page](https://github.com/BurntSushi/toml/releases) for a changelog; this information is also in the git tag annotations (e.g. `git show v0.4.0`). -This library requires Go 1.13 or newer; add it to your go.mod with: +This library requires Go 1.18 or newer; add it to your go.mod with: % go get github.com/BurntSushi/toml@latest diff --git a/vendor/github.com/BurntSushi/toml/decode.go b/vendor/github.com/BurntSushi/toml/decode.go index 4d38f3bfce..7aaf462c94 100644 --- a/vendor/github.com/BurntSushi/toml/decode.go +++ b/vendor/github.com/BurntSushi/toml/decode.go @@ -6,7 +6,7 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" + "io/fs" "math" "os" "reflect" @@ -18,13 +18,13 @@ import ( // Unmarshaler is the interface implemented by objects that can unmarshal a // TOML description of themselves. type Unmarshaler interface { - UnmarshalTOML(interface{}) error + UnmarshalTOML(any) error } // Unmarshal decodes the contents of data in TOML format into a pointer v. // // See [Decoder] for a description of the decoding process. -func Unmarshal(data []byte, v interface{}) error { +func Unmarshal(data []byte, v any) error { _, err := NewDecoder(bytes.NewReader(data)).Decode(v) return err } @@ -32,12 +32,12 @@ func Unmarshal(data []byte, v interface{}) error { // Decode the TOML data in to the pointer v. // // See [Decoder] for a description of the decoding process. -func Decode(data string, v interface{}) (MetaData, error) { +func Decode(data string, v any) (MetaData, error) { return NewDecoder(strings.NewReader(data)).Decode(v) } // DecodeFile reads the contents of a file and decodes it with [Decode]. -func DecodeFile(path string, v interface{}) (MetaData, error) { +func DecodeFile(path string, v any) (MetaData, error) { fp, err := os.Open(path) if err != nil { return MetaData{}, err @@ -46,6 +46,17 @@ func DecodeFile(path string, v interface{}) (MetaData, error) { return NewDecoder(fp).Decode(v) } +// DecodeFS reads the contents of a file from [fs.FS] and decodes it with +// [Decode]. +func DecodeFS(fsys fs.FS, path string, v any) (MetaData, error) { + fp, err := fsys.Open(path) + if err != nil { + return MetaData{}, err + } + defer fp.Close() + return NewDecoder(fp).Decode(v) +} + // Primitive is a TOML value that hasn't been decoded into a Go value. // // This type can be used for any value, which will cause decoding to be delayed. @@ -58,7 +69,7 @@ func DecodeFile(path string, v interface{}) (MetaData, error) { // overhead of reflection. They can be useful when you don't know the exact type // of TOML data until runtime. type Primitive struct { - undecoded interface{} + undecoded any context Key } @@ -122,7 +133,7 @@ var ( ) // Decode TOML data in to the pointer `v`. -func (dec *Decoder) Decode(v interface{}) (MetaData, error) { +func (dec *Decoder) Decode(v any) (MetaData, error) { rv := reflect.ValueOf(v) if rv.Kind() != reflect.Ptr { s := "%q" @@ -136,8 +147,8 @@ func (dec *Decoder) Decode(v interface{}) (MetaData, error) { return MetaData{}, fmt.Errorf("toml: cannot decode to nil value of %q", reflect.TypeOf(v)) } - // Check if this is a supported type: struct, map, interface{}, or something - // that implements UnmarshalTOML or UnmarshalText. + // Check if this is a supported type: struct, map, any, or something that + // implements UnmarshalTOML or UnmarshalText. rv = indirect(rv) rt := rv.Type() if rv.Kind() != reflect.Struct && rv.Kind() != reflect.Map && @@ -148,7 +159,7 @@ func (dec *Decoder) Decode(v interface{}) (MetaData, error) { // TODO: parser should read from io.Reader? Or at the very least, make it // read from []byte rather than string - data, err := ioutil.ReadAll(dec.r) + data, err := io.ReadAll(dec.r) if err != nil { return MetaData{}, err } @@ -179,7 +190,7 @@ func (dec *Decoder) Decode(v interface{}) (MetaData, error) { // will only reflect keys that were decoded. Namely, any keys hidden behind a // Primitive will be considered undecoded. Executing this method will update the // undecoded keys in the meta data. (See the example.) -func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error { +func (md *MetaData) PrimitiveDecode(primValue Primitive, v any) error { md.context = primValue.context defer func() { md.context = nil }() return md.unify(primValue.undecoded, rvalue(v)) @@ -190,7 +201,7 @@ func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error { // // Any type mismatch produces an error. Finding a type that we don't know // how to handle produces an unsupported type error. -func (md *MetaData) unify(data interface{}, rv reflect.Value) error { +func (md *MetaData) unify(data any, rv reflect.Value) error { // Special case. Look for a `Primitive` value. // TODO: #76 would make this superfluous after implemented. if rv.Type() == primitiveType { @@ -207,7 +218,11 @@ func (md *MetaData) unify(data interface{}, rv reflect.Value) error { rvi := rv.Interface() if v, ok := rvi.(Unmarshaler); ok { - return v.UnmarshalTOML(data) + err := v.UnmarshalTOML(data) + if err != nil { + return md.parseErr(err) + } + return nil } if v, ok := rvi.(encoding.TextUnmarshaler); ok { return md.unifyText(data, v) @@ -227,14 +242,6 @@ func (md *MetaData) unify(data interface{}, rv reflect.Value) error { return md.unifyInt(data, rv) } switch k { - case reflect.Ptr: - elem := reflect.New(rv.Type().Elem()) - err := md.unify(data, reflect.Indirect(elem)) - if err != nil { - return err - } - rv.Set(elem) - return nil case reflect.Struct: return md.unifyStruct(data, rv) case reflect.Map: @@ -258,14 +265,13 @@ func (md *MetaData) unify(data interface{}, rv reflect.Value) error { return md.e("unsupported type %s", rv.Kind()) } -func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error { - tmap, ok := mapping.(map[string]interface{}) +func (md *MetaData) unifyStruct(mapping any, rv reflect.Value) error { + tmap, ok := mapping.(map[string]any) if !ok { if mapping == nil { return nil } - return md.e("type mismatch for %s: expected table but found %T", - rv.Type().String(), mapping) + return md.e("type mismatch for %s: expected table but found %s", rv.Type().String(), fmtType(mapping)) } for key, datum := range tmap { @@ -304,14 +310,14 @@ func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error { return nil } -func (md *MetaData) unifyMap(mapping interface{}, rv reflect.Value) error { +func (md *MetaData) unifyMap(mapping any, rv reflect.Value) error { keyType := rv.Type().Key().Kind() if keyType != reflect.String && keyType != reflect.Interface { return fmt.Errorf("toml: cannot decode to a map with non-string key type (%s in %q)", keyType, rv.Type()) } - tmap, ok := mapping.(map[string]interface{}) + tmap, ok := mapping.(map[string]any) if !ok { if tmap == nil { return nil @@ -347,7 +353,7 @@ func (md *MetaData) unifyMap(mapping interface{}, rv reflect.Value) error { return nil } -func (md *MetaData) unifyArray(data interface{}, rv reflect.Value) error { +func (md *MetaData) unifyArray(data any, rv reflect.Value) error { datav := reflect.ValueOf(data) if datav.Kind() != reflect.Slice { if !datav.IsValid() { @@ -361,7 +367,7 @@ func (md *MetaData) unifyArray(data interface{}, rv reflect.Value) error { return md.unifySliceArray(datav, rv) } -func (md *MetaData) unifySlice(data interface{}, rv reflect.Value) error { +func (md *MetaData) unifySlice(data any, rv reflect.Value) error { datav := reflect.ValueOf(data) if datav.Kind() != reflect.Slice { if !datav.IsValid() { @@ -388,7 +394,7 @@ func (md *MetaData) unifySliceArray(data, rv reflect.Value) error { return nil } -func (md *MetaData) unifyString(data interface{}, rv reflect.Value) error { +func (md *MetaData) unifyString(data any, rv reflect.Value) error { _, ok := rv.Interface().(json.Number) if ok { if i, ok := data.(int64); ok { @@ -408,7 +414,7 @@ func (md *MetaData) unifyString(data interface{}, rv reflect.Value) error { return md.badtype("string", data) } -func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error { +func (md *MetaData) unifyFloat64(data any, rv reflect.Value) error { rvk := rv.Kind() if num, ok := data.(float64); ok { @@ -429,7 +435,7 @@ func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error { if num, ok := data.(int64); ok { if (rvk == reflect.Float32 && (num < -maxSafeFloat32Int || num > maxSafeFloat32Int)) || (rvk == reflect.Float64 && (num < -maxSafeFloat64Int || num > maxSafeFloat64Int)) { - return md.parseErr(errParseRange{i: num, size: rvk.String()}) + return md.parseErr(errUnsafeFloat{i: num, size: rvk.String()}) } rv.SetFloat(float64(num)) return nil @@ -438,7 +444,7 @@ func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error { return md.badtype("float", data) } -func (md *MetaData) unifyInt(data interface{}, rv reflect.Value) error { +func (md *MetaData) unifyInt(data any, rv reflect.Value) error { _, ok := rv.Interface().(time.Duration) if ok { // Parse as string duration, and fall back to regular integer parsing @@ -481,7 +487,7 @@ func (md *MetaData) unifyInt(data interface{}, rv reflect.Value) error { return nil } -func (md *MetaData) unifyBool(data interface{}, rv reflect.Value) error { +func (md *MetaData) unifyBool(data any, rv reflect.Value) error { if b, ok := data.(bool); ok { rv.SetBool(b) return nil @@ -489,12 +495,12 @@ func (md *MetaData) unifyBool(data interface{}, rv reflect.Value) error { return md.badtype("boolean", data) } -func (md *MetaData) unifyAnything(data interface{}, rv reflect.Value) error { +func (md *MetaData) unifyAnything(data any, rv reflect.Value) error { rv.Set(reflect.ValueOf(data)) return nil } -func (md *MetaData) unifyText(data interface{}, v encoding.TextUnmarshaler) error { +func (md *MetaData) unifyText(data any, v encoding.TextUnmarshaler) error { var s string switch sdata := data.(type) { case Marshaler: @@ -523,13 +529,13 @@ func (md *MetaData) unifyText(data interface{}, v encoding.TextUnmarshaler) erro return md.badtype("primitive (string-like)", data) } if err := v.UnmarshalText([]byte(s)); err != nil { - return err + return md.parseErr(err) } return nil } -func (md *MetaData) badtype(dst string, data interface{}) error { - return md.e("incompatible types: TOML value has type %T; destination has type %s", data, dst) +func (md *MetaData) badtype(dst string, data any) error { + return md.e("incompatible types: TOML value has type %s; destination has type %s", fmtType(data), dst) } func (md *MetaData) parseErr(err error) error { @@ -543,7 +549,7 @@ func (md *MetaData) parseErr(err error) error { } } -func (md *MetaData) e(format string, args ...interface{}) error { +func (md *MetaData) e(format string, args ...any) error { f := "toml: " if len(md.context) > 0 { f = fmt.Sprintf("toml: (last key %q): ", md.context) @@ -556,7 +562,7 @@ func (md *MetaData) e(format string, args ...interface{}) error { } // rvalue returns a reflect.Value of `v`. All pointers are resolved. -func rvalue(v interface{}) reflect.Value { +func rvalue(v any) reflect.Value { return indirect(reflect.ValueOf(v)) } @@ -600,3 +606,8 @@ func isUnifiable(rv reflect.Value) bool { } return false } + +// fmt %T with "interface {}" replaced with "any", which is far more readable. +func fmtType(t any) string { + return strings.ReplaceAll(fmt.Sprintf("%T", t), "interface {}", "any") +} diff --git a/vendor/github.com/BurntSushi/toml/decode_go116.go b/vendor/github.com/BurntSushi/toml/decode_go116.go deleted file mode 100644 index 086d0b6866..0000000000 --- a/vendor/github.com/BurntSushi/toml/decode_go116.go +++ /dev/null @@ -1,19 +0,0 @@ -//go:build go1.16 -// +build go1.16 - -package toml - -import ( - "io/fs" -) - -// DecodeFS reads the contents of a file from [fs.FS] and decodes it with -// [Decode]. -func DecodeFS(fsys fs.FS, path string, v interface{}) (MetaData, error) { - fp, err := fsys.Open(path) - if err != nil { - return MetaData{}, err - } - defer fp.Close() - return NewDecoder(fp).Decode(v) -} diff --git a/vendor/github.com/BurntSushi/toml/deprecated.go b/vendor/github.com/BurntSushi/toml/deprecated.go index b9e309717e..155709a80b 100644 --- a/vendor/github.com/BurntSushi/toml/deprecated.go +++ b/vendor/github.com/BurntSushi/toml/deprecated.go @@ -15,15 +15,15 @@ type TextMarshaler encoding.TextMarshaler // Deprecated: use encoding.TextUnmarshaler type TextUnmarshaler encoding.TextUnmarshaler +// DecodeReader is an alias for NewDecoder(r).Decode(v). +// +// Deprecated: use NewDecoder(reader).Decode(&value). +func DecodeReader(r io.Reader, v any) (MetaData, error) { return NewDecoder(r).Decode(v) } + // PrimitiveDecode is an alias for MetaData.PrimitiveDecode(). // // Deprecated: use MetaData.PrimitiveDecode. -func PrimitiveDecode(primValue Primitive, v interface{}) error { +func PrimitiveDecode(primValue Primitive, v any) error { md := MetaData{decoded: make(map[string]struct{})} return md.unify(primValue.undecoded, rvalue(v)) } - -// DecodeReader is an alias for NewDecoder(r).Decode(v). -// -// Deprecated: use NewDecoder(reader).Decode(&value). -func DecodeReader(r io.Reader, v interface{}) (MetaData, error) { return NewDecoder(r).Decode(v) } diff --git a/vendor/github.com/BurntSushi/toml/doc.go b/vendor/github.com/BurntSushi/toml/doc.go index 81a7c0fe9f..82c90a9057 100644 --- a/vendor/github.com/BurntSushi/toml/doc.go +++ b/vendor/github.com/BurntSushi/toml/doc.go @@ -2,9 +2,6 @@ // // This package supports TOML v1.0.0, as specified at https://toml.io // -// There is also support for delaying decoding with the Primitive type, and -// querying the set of keys in a TOML document with the MetaData type. -// // The github.com/BurntSushi/toml/cmd/tomlv package implements a TOML validator, // and can be used to verify if TOML document is valid. It can also be used to // print the type of each key. diff --git a/vendor/github.com/BurntSushi/toml/encode.go b/vendor/github.com/BurntSushi/toml/encode.go index 9cd25d7571..73366c0d9a 100644 --- a/vendor/github.com/BurntSushi/toml/encode.go +++ b/vendor/github.com/BurntSushi/toml/encode.go @@ -2,6 +2,7 @@ package toml import ( "bufio" + "bytes" "encoding" "encoding/json" "errors" @@ -76,6 +77,17 @@ type Marshaler interface { MarshalTOML() ([]byte, error) } +// Marshal returns a TOML representation of the Go value. +// +// See [Encoder] for a description of the encoding process. +func Marshal(v any) ([]byte, error) { + buff := new(bytes.Buffer) + if err := NewEncoder(buff).Encode(v); err != nil { + return nil, err + } + return buff.Bytes(), nil +} + // Encoder encodes a Go to a TOML document. // // The mapping between Go values and TOML values should be precisely the same as @@ -115,26 +127,21 @@ type Marshaler interface { // NOTE: only exported keys are encoded due to the use of reflection. Unexported // keys are silently discarded. type Encoder struct { - // String to use for a single indentation level; default is two spaces. - Indent string - + Indent string // string for a single indentation level; default is two spaces. + hasWritten bool // written any output to w yet? w *bufio.Writer - hasWritten bool // written any output to w yet? } // NewEncoder create a new Encoder. func NewEncoder(w io.Writer) *Encoder { - return &Encoder{ - w: bufio.NewWriter(w), - Indent: " ", - } + return &Encoder{w: bufio.NewWriter(w), Indent: " "} } // Encode writes a TOML representation of the Go value to the [Encoder]'s writer. // // An error is returned if the value given cannot be encoded to a valid TOML // document. -func (enc *Encoder) Encode(v interface{}) error { +func (enc *Encoder) Encode(v any) error { rv := eindirect(reflect.ValueOf(v)) err := enc.safeEncode(Key([]string{}), rv) if err != nil { @@ -280,18 +287,30 @@ func (enc *Encoder) eElement(rv reflect.Value) { case reflect.Float32: f := rv.Float() if math.IsNaN(f) { + if math.Signbit(f) { + enc.wf("-") + } enc.wf("nan") } else if math.IsInf(f, 0) { - enc.wf("%cinf", map[bool]byte{true: '-', false: '+'}[math.Signbit(f)]) + if math.Signbit(f) { + enc.wf("-") + } + enc.wf("inf") } else { enc.wf(floatAddDecimal(strconv.FormatFloat(f, 'f', -1, 32))) } case reflect.Float64: f := rv.Float() if math.IsNaN(f) { + if math.Signbit(f) { + enc.wf("-") + } enc.wf("nan") } else if math.IsInf(f, 0) { - enc.wf("%cinf", map[bool]byte{true: '-', false: '+'}[math.Signbit(f)]) + if math.Signbit(f) { + enc.wf("-") + } + enc.wf("inf") } else { enc.wf(floatAddDecimal(strconv.FormatFloat(f, 'f', -1, 64))) } @@ -304,7 +323,7 @@ func (enc *Encoder) eElement(rv reflect.Value) { case reflect.Interface: enc.eElement(rv.Elem()) default: - encPanic(fmt.Errorf("unexpected type: %T", rv.Interface())) + encPanic(fmt.Errorf("unexpected type: %s", fmtType(rv.Interface()))) } } @@ -712,7 +731,7 @@ func (enc *Encoder) writeKeyValue(key Key, val reflect.Value, inline bool) { } } -func (enc *Encoder) wf(format string, v ...interface{}) { +func (enc *Encoder) wf(format string, v ...any) { _, err := fmt.Fprintf(enc.w, format, v...) if err != nil { encPanic(err) diff --git a/vendor/github.com/BurntSushi/toml/error.go b/vendor/github.com/BurntSushi/toml/error.go index efd68865bb..b45a3f45f6 100644 --- a/vendor/github.com/BurntSushi/toml/error.go +++ b/vendor/github.com/BurntSushi/toml/error.go @@ -114,13 +114,22 @@ func (pe ParseError) ErrorWithPosition() string { msg, pe.Position.Line, col, col+pe.Position.Len) } if pe.Position.Line > 2 { - fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line-2, lines[pe.Position.Line-3]) + fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line-2, expandTab(lines[pe.Position.Line-3])) } if pe.Position.Line > 1 { - fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line-1, lines[pe.Position.Line-2]) + fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line-1, expandTab(lines[pe.Position.Line-2])) } - fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line, lines[pe.Position.Line-1]) - fmt.Fprintf(b, "% 10s%s%s\n", "", strings.Repeat(" ", col), strings.Repeat("^", pe.Position.Len)) + + /// Expand tabs, so that the ^^^s are at the correct position, but leave + /// "column 10-13" intact. Adjusting this to the visual column would be + /// better, but we don't know the tabsize of the user in their editor, which + /// can be 8, 4, 2, or something else. We can't know. So leaving it as the + /// character index is probably the "most correct". + expanded := expandTab(lines[pe.Position.Line-1]) + diff := len(expanded) - len(lines[pe.Position.Line-1]) + + fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line, expanded) + fmt.Fprintf(b, "% 10s%s%s\n", "", strings.Repeat(" ", col+diff), strings.Repeat("^", pe.Position.Len)) return b.String() } @@ -159,17 +168,47 @@ func (pe ParseError) column(lines []string) int { return col } +func expandTab(s string) string { + var ( + b strings.Builder + l int + fill = func(n int) string { + b := make([]byte, n) + for i := range b { + b[i] = ' ' + } + return string(b) + } + ) + b.Grow(len(s)) + for _, r := range s { + switch r { + case '\t': + tw := 8 - l%8 + b.WriteString(fill(tw)) + l += tw + default: + b.WriteRune(r) + l += 1 + } + } + return b.String() +} + type ( errLexControl struct{ r rune } errLexEscape struct{ r rune } errLexUTF8 struct{ b byte } - errLexInvalidNum struct{ v string } - errLexInvalidDate struct{ v string } + errParseDate struct{ v string } errLexInlineTableNL struct{} errLexStringNL struct{} errParseRange struct { - i interface{} // int or float - size string // "int64", "uint16", etc. + i any // int or float + size string // "int64", "uint16", etc. + } + errUnsafeFloat struct { + i interface{} // float32 or float64 + size string // "float32" or "float64" } errParseDuration struct{ d string } ) @@ -183,18 +222,20 @@ func (e errLexEscape) Error() string { return fmt.Sprintf(`invalid escape func (e errLexEscape) Usage() string { return usageEscape } func (e errLexUTF8) Error() string { return fmt.Sprintf("invalid UTF-8 byte: 0x%02x", e.b) } func (e errLexUTF8) Usage() string { return "" } -func (e errLexInvalidNum) Error() string { return fmt.Sprintf("invalid number: %q", e.v) } -func (e errLexInvalidNum) Usage() string { return "" } -func (e errLexInvalidDate) Error() string { return fmt.Sprintf("invalid date: %q", e.v) } -func (e errLexInvalidDate) Usage() string { return "" } +func (e errParseDate) Error() string { return fmt.Sprintf("invalid datetime: %q", e.v) } +func (e errParseDate) Usage() string { return usageDate } func (e errLexInlineTableNL) Error() string { return "newlines not allowed within inline tables" } func (e errLexInlineTableNL) Usage() string { return usageInlineNewline } func (e errLexStringNL) Error() string { return "strings cannot contain newlines" } func (e errLexStringNL) Usage() string { return usageStringNewline } func (e errParseRange) Error() string { return fmt.Sprintf("%v is out of range for %s", e.i, e.size) } func (e errParseRange) Usage() string { return usageIntOverflow } -func (e errParseDuration) Error() string { return fmt.Sprintf("invalid duration: %q", e.d) } -func (e errParseDuration) Usage() string { return usageDuration } +func (e errUnsafeFloat) Error() string { + return fmt.Sprintf("%v is out of the safe %s range", e.i, e.size) +} +func (e errUnsafeFloat) Usage() string { return usageUnsafeFloat } +func (e errParseDuration) Error() string { return fmt.Sprintf("invalid duration: %q", e.d) } +func (e errParseDuration) Usage() string { return usageDuration } const usageEscape = ` A '\' inside a "-delimited string is interpreted as an escape character. @@ -251,19 +292,35 @@ bug in the program that uses too small of an integer. The maximum and minimum values are: size │ lowest │ highest - ───────┼────────────────┼────────── + ───────┼────────────────┼────────────── int8 │ -128 │ 127 int16 │ -32,768 │ 32,767 int32 │ -2,147,483,648 │ 2,147,483,647 int64 │ -9.2 × 10¹⁷ │ 9.2 × 10¹⁷ uint8 │ 0 │ 255 - uint16 │ 0 │ 65535 - uint32 │ 0 │ 4294967295 + uint16 │ 0 │ 65,535 + uint32 │ 0 │ 4,294,967,295 uint64 │ 0 │ 1.8 × 10¹⁸ int refers to int32 on 32-bit systems and int64 on 64-bit systems. ` +const usageUnsafeFloat = ` +This number is outside of the "safe" range for floating point numbers; whole +(non-fractional) numbers outside the below range can not always be represented +accurately in a float, leading to some loss of accuracy. + +Explicitly mark a number as a fractional unit by adding ".0", which will incur +some loss of accuracy; for example: + + f = 2_000_000_000.0 + +Accuracy ranges: + + float32 = 16,777,215 + float64 = 9,007,199,254,740,991 +` + const usageDuration = ` A duration must be as "number", without any spaces. Valid units are: @@ -277,3 +334,23 @@ A duration must be as "number", without any spaces. Valid units are: You can combine multiple units; for example "5m10s" for 5 minutes and 10 seconds. ` + +const usageDate = ` +A TOML datetime must be in one of the following formats: + + 2006-01-02T15:04:05Z07:00 Date and time, with timezone. + 2006-01-02T15:04:05 Date and time, but without timezone. + 2006-01-02 Date without a time or timezone. + 15:04:05 Just a time, without any timezone. + +Seconds may optionally have a fraction, up to nanosecond precision: + + 15:04:05.123 + 15:04:05.856018510 +` + +// TOML 1.1: +// The seconds part in times is optional, and may be omitted: +// 2006-01-02T15:04Z07:00 +// 2006-01-02T15:04 +// 15:04 diff --git a/vendor/github.com/BurntSushi/toml/lex.go b/vendor/github.com/BurntSushi/toml/lex.go index 3545a6ad66..a1016d98a8 100644 --- a/vendor/github.com/BurntSushi/toml/lex.go +++ b/vendor/github.com/BurntSushi/toml/lex.go @@ -17,6 +17,7 @@ const ( itemEOF itemText itemString + itemStringEsc itemRawString itemMultilineString itemRawMultilineString @@ -53,6 +54,7 @@ type lexer struct { state stateFn items chan item tomlNext bool + esc bool // Allow for backing up up to 4 runes. This is necessary because TOML // contains 3-rune tokens (""" and '''). @@ -164,7 +166,7 @@ func (lx *lexer) next() (r rune) { } r, w := utf8.DecodeRuneInString(lx.input[lx.pos:]) - if r == utf8.RuneError { + if r == utf8.RuneError && w == 1 { lx.error(errLexUTF8{lx.input[lx.pos]}) return utf8.RuneError } @@ -270,7 +272,7 @@ func (lx *lexer) errorPos(start, length int, err error) stateFn { } // errorf is like error, and creates a new error. -func (lx *lexer) errorf(format string, values ...interface{}) stateFn { +func (lx *lexer) errorf(format string, values ...any) stateFn { if lx.atEOF { pos := lx.getPos() pos.Line-- @@ -333,9 +335,7 @@ func lexTopEnd(lx *lexer) stateFn { lx.emit(itemEOF) return nil } - return lx.errorf( - "expected a top-level item to end with a newline, comment, or EOF, but got %q instead", - r) + return lx.errorf("expected a top-level item to end with a newline, comment, or EOF, but got %q instead", r) } // lexTable lexes the beginning of a table. Namely, it makes sure that @@ -698,7 +698,12 @@ func lexString(lx *lexer) stateFn { return lexStringEscape case r == '"': lx.backup() - lx.emit(itemString) + if lx.esc { + lx.esc = false + lx.emit(itemStringEsc) + } else { + lx.emit(itemString) + } lx.next() lx.ignore() return lx.pop() @@ -748,6 +753,7 @@ func lexMultilineString(lx *lexer) stateFn { lx.backup() /// backup: don't include the """ in the item. lx.backup() lx.backup() + lx.esc = false lx.emit(itemMultilineString) lx.next() /// Read over ''' again and discard it. lx.next() @@ -837,6 +843,7 @@ func lexMultilineStringEscape(lx *lexer) stateFn { } func lexStringEscape(lx *lexer) stateFn { + lx.esc = true r := lx.next() switch r { case 'e': @@ -879,10 +886,8 @@ func lexHexEscape(lx *lexer) stateFn { var r rune for i := 0; i < 2; i++ { r = lx.next() - if !isHexadecimal(r) { - return lx.errorf( - `expected two hexadecimal digits after '\x', but got %q instead`, - lx.current()) + if !isHex(r) { + return lx.errorf(`expected two hexadecimal digits after '\x', but got %q instead`, lx.current()) } } return lx.pop() @@ -892,10 +897,8 @@ func lexShortUnicodeEscape(lx *lexer) stateFn { var r rune for i := 0; i < 4; i++ { r = lx.next() - if !isHexadecimal(r) { - return lx.errorf( - `expected four hexadecimal digits after '\u', but got %q instead`, - lx.current()) + if !isHex(r) { + return lx.errorf(`expected four hexadecimal digits after '\u', but got %q instead`, lx.current()) } } return lx.pop() @@ -905,10 +908,8 @@ func lexLongUnicodeEscape(lx *lexer) stateFn { var r rune for i := 0; i < 8; i++ { r = lx.next() - if !isHexadecimal(r) { - return lx.errorf( - `expected eight hexadecimal digits after '\U', but got %q instead`, - lx.current()) + if !isHex(r) { + return lx.errorf(`expected eight hexadecimal digits after '\U', but got %q instead`, lx.current()) } } return lx.pop() @@ -975,7 +976,7 @@ func lexDatetime(lx *lexer) stateFn { // lexHexInteger consumes a hexadecimal integer after seeing the '0x' prefix. func lexHexInteger(lx *lexer) stateFn { r := lx.next() - if isHexadecimal(r) { + if isHex(r) { return lexHexInteger } switch r { @@ -1109,7 +1110,7 @@ func lexBaseNumberOrDate(lx *lexer) stateFn { return lexOctalInteger case 'x': r = lx.peek() - if !isHexadecimal(r) { + if !isHex(r) { lx.errorf("not a hexidecimal number: '%s%c'", lx.current(), r) } return lexHexInteger @@ -1207,7 +1208,7 @@ func (itype itemType) String() string { return "EOF" case itemText: return "Text" - case itemString, itemRawString, itemMultilineString, itemRawMultilineString: + case itemString, itemStringEsc, itemRawString, itemMultilineString, itemRawMultilineString: return "String" case itemBool: return "Bool" @@ -1240,7 +1241,7 @@ func (itype itemType) String() string { } func (item item) String() string { - return fmt.Sprintf("(%s, %s)", item.typ.String(), item.val) + return fmt.Sprintf("(%s, %s)", item.typ, item.val) } func isWhitespace(r rune) bool { return r == '\t' || r == ' ' } @@ -1256,10 +1257,7 @@ func isControl(r rune) bool { // Control characters except \t, \r, \n func isDigit(r rune) bool { return r >= '0' && r <= '9' } func isBinary(r rune) bool { return r == '0' || r == '1' } func isOctal(r rune) bool { return r >= '0' && r <= '7' } -func isHexadecimal(r rune) bool { - return (r >= '0' && r <= '9') || (r >= 'a' && r <= 'f') || (r >= 'A' && r <= 'F') -} - +func isHex(r rune) bool { return (r >= '0' && r <= '9') || (r|0x20 >= 'a' && r|0x20 <= 'f') } func isBareKeyChar(r rune, tomlNext bool) bool { if tomlNext { return (r >= 'A' && r <= 'Z') || diff --git a/vendor/github.com/BurntSushi/toml/meta.go b/vendor/github.com/BurntSushi/toml/meta.go index 2e78b24e95..e614537300 100644 --- a/vendor/github.com/BurntSushi/toml/meta.go +++ b/vendor/github.com/BurntSushi/toml/meta.go @@ -13,7 +13,7 @@ type MetaData struct { context Key // Used only during decoding. keyInfo map[string]keyInfo - mapping map[string]interface{} + mapping map[string]any keys []Key decoded map[string]struct{} data []byte // Input file; for errors. @@ -31,12 +31,12 @@ func (md *MetaData) IsDefined(key ...string) bool { } var ( - hash map[string]interface{} + hash map[string]any ok bool - hashOrVal interface{} = md.mapping + hashOrVal any = md.mapping ) for _, k := range key { - if hash, ok = hashOrVal.(map[string]interface{}); !ok { + if hash, ok = hashOrVal.(map[string]any); !ok { return false } if hashOrVal, ok = hash[k]; !ok { @@ -94,28 +94,55 @@ func (md *MetaData) Undecoded() []Key { type Key []string func (k Key) String() string { - ss := make([]string, len(k)) - for i := range k { - ss[i] = k.maybeQuoted(i) + // This is called quite often, so it's a bit funky to make it faster. + var b strings.Builder + b.Grow(len(k) * 25) +outer: + for i, kk := range k { + if i > 0 { + b.WriteByte('.') + } + if kk == "" { + b.WriteString(`""`) + } else { + for _, r := range kk { + // "Inline" isBareKeyChar + if !((r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '_' || r == '-') { + b.WriteByte('"') + b.WriteString(dblQuotedReplacer.Replace(kk)) + b.WriteByte('"') + continue outer + } + } + b.WriteString(kk) + } } - return strings.Join(ss, ".") + return b.String() } func (k Key) maybeQuoted(i int) string { if k[i] == "" { return `""` } - for _, c := range k[i] { - if !isBareKeyChar(c, false) { - return `"` + dblQuotedReplacer.Replace(k[i]) + `"` + for _, r := range k[i] { + if (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '_' || r == '-' { + continue } + return `"` + dblQuotedReplacer.Replace(k[i]) + `"` } return k[i] } +// Like append(), but only increase the cap by 1. func (k Key) add(piece string) Key { + if cap(k) > len(k) { + return append(k, piece) + } newKey := make(Key, len(k)+1) copy(newKey, k) newKey[len(k)] = piece return newKey } + +func (k Key) parent() Key { return k[:len(k)-1] } // all except the last piece. +func (k Key) last() string { return k[len(k)-1] } // last piece of this key. diff --git a/vendor/github.com/BurntSushi/toml/parse.go b/vendor/github.com/BurntSushi/toml/parse.go index 9c19153698..11ac3108be 100644 --- a/vendor/github.com/BurntSushi/toml/parse.go +++ b/vendor/github.com/BurntSushi/toml/parse.go @@ -2,6 +2,7 @@ package toml import ( "fmt" + "math" "os" "strconv" "strings" @@ -20,9 +21,9 @@ type parser struct { ordered []Key // List of keys in the order that they appear in the TOML data. - keyInfo map[string]keyInfo // Map keyname → info about the TOML key. - mapping map[string]interface{} // Map keyname → key value. - implicits map[string]struct{} // Record implicit keys (e.g. "key.group.names"). + keyInfo map[string]keyInfo // Map keyname → info about the TOML key. + mapping map[string]any // Map keyname → key value. + implicits map[string]struct{} // Record implicit keys (e.g. "key.group.names"). } type keyInfo struct { @@ -49,6 +50,7 @@ func parse(data string) (p *parser, err error) { // it anyway. if strings.HasPrefix(data, "\xff\xfe") || strings.HasPrefix(data, "\xfe\xff") { // UTF-16 data = data[2:] + //lint:ignore S1017 https://github.com/dominikh/go-tools/issues/1447 } else if strings.HasPrefix(data, "\xef\xbb\xbf") { // UTF-8 data = data[3:] } @@ -71,7 +73,7 @@ func parse(data string) (p *parser, err error) { p = &parser{ keyInfo: make(map[string]keyInfo), - mapping: make(map[string]interface{}), + mapping: make(map[string]any), lx: lex(data, tomlNext), ordered: make([]Key, 0), implicits: make(map[string]struct{}), @@ -97,7 +99,7 @@ func (p *parser) panicErr(it item, err error) { }) } -func (p *parser) panicItemf(it item, format string, v ...interface{}) { +func (p *parser) panicItemf(it item, format string, v ...any) { panic(ParseError{ Message: fmt.Sprintf(format, v...), Position: it.pos, @@ -106,7 +108,7 @@ func (p *parser) panicItemf(it item, format string, v ...interface{}) { }) } -func (p *parser) panicf(format string, v ...interface{}) { +func (p *parser) panicf(format string, v ...any) { panic(ParseError{ Message: fmt.Sprintf(format, v...), Position: p.pos, @@ -139,7 +141,7 @@ func (p *parser) nextPos() item { return it } -func (p *parser) bug(format string, v ...interface{}) { +func (p *parser) bug(format string, v ...any) { panic(fmt.Sprintf("BUG: "+format+"\n\n", v...)) } @@ -194,11 +196,11 @@ func (p *parser) topLevel(item item) { p.assertEqual(itemKeyEnd, k.typ) /// The current key is the last part. - p.currentKey = key[len(key)-1] + p.currentKey = key.last() /// All the other parts (if any) are the context; need to set each part /// as implicit. - context := key[:len(key)-1] + context := key.parent() for i := range context { p.addImplicitContext(append(p.context, context[i:i+1]...)) } @@ -207,7 +209,8 @@ func (p *parser) topLevel(item item) { /// Set value. vItem := p.next() val, typ := p.value(vItem, false) - p.set(p.currentKey, val, typ, vItem.pos) + p.setValue(p.currentKey, val) + p.setType(p.currentKey, typ, vItem.pos) /// Remove the context we added (preserving any context from [tbl] lines). p.context = outerContext @@ -222,7 +225,7 @@ func (p *parser) keyString(it item) string { switch it.typ { case itemText: return it.val - case itemString, itemMultilineString, + case itemString, itemStringEsc, itemMultilineString, itemRawString, itemRawMultilineString: s, _ := p.value(it, false) return s.(string) @@ -239,9 +242,11 @@ var datetimeRepl = strings.NewReplacer( // value translates an expected value from the lexer into a Go value wrapped // as an empty interface. -func (p *parser) value(it item, parentIsArray bool) (interface{}, tomlType) { +func (p *parser) value(it item, parentIsArray bool) (any, tomlType) { switch it.typ { case itemString: + return it.val, p.typeOfPrimitive(it) + case itemStringEsc: return p.replaceEscapes(it, it.val), p.typeOfPrimitive(it) case itemMultilineString: return p.replaceEscapes(it, p.stripEscapedNewlines(stripFirstNewline(it.val))), p.typeOfPrimitive(it) @@ -274,7 +279,7 @@ func (p *parser) value(it item, parentIsArray bool) (interface{}, tomlType) { panic("unreachable") } -func (p *parser) valueInteger(it item) (interface{}, tomlType) { +func (p *parser) valueInteger(it item) (any, tomlType) { if !numUnderscoresOK(it.val) { p.panicItemf(it, "Invalid integer %q: underscores must be surrounded by digits", it.val) } @@ -298,7 +303,7 @@ func (p *parser) valueInteger(it item) (interface{}, tomlType) { return num, p.typeOfPrimitive(it) } -func (p *parser) valueFloat(it item) (interface{}, tomlType) { +func (p *parser) valueFloat(it item) (any, tomlType) { parts := strings.FieldsFunc(it.val, func(r rune) bool { switch r { case '.', 'e', 'E': @@ -322,7 +327,9 @@ func (p *parser) valueFloat(it item) (interface{}, tomlType) { p.panicItemf(it, "Invalid float %q: '.' must be followed by one or more digits", it.val) } val := strings.Replace(it.val, "_", "", -1) - if val == "+nan" || val == "-nan" { // Go doesn't support this, but TOML spec does. + signbit := false + if val == "+nan" || val == "-nan" { + signbit = val == "-nan" val = "nan" } num, err := strconv.ParseFloat(val, 64) @@ -333,6 +340,9 @@ func (p *parser) valueFloat(it item) (interface{}, tomlType) { p.panicItemf(it, "Invalid float value: %q", it.val) } } + if signbit { + num = math.Copysign(num, -1) + } return num, p.typeOfPrimitive(it) } @@ -352,7 +362,7 @@ var dtTypes = []struct { {"15:04", internal.LocalTime, true}, } -func (p *parser) valueDatetime(it item) (interface{}, tomlType) { +func (p *parser) valueDatetime(it item) (any, tomlType) { it.val = datetimeRepl.Replace(it.val) var ( t time.Time @@ -365,26 +375,44 @@ func (p *parser) valueDatetime(it item) (interface{}, tomlType) { } t, err = time.ParseInLocation(dt.fmt, it.val, dt.zone) if err == nil { + if missingLeadingZero(it.val, dt.fmt) { + p.panicErr(it, errParseDate{it.val}) + } ok = true break } } if !ok { - p.panicItemf(it, "Invalid TOML Datetime: %q.", it.val) + p.panicErr(it, errParseDate{it.val}) } return t, p.typeOfPrimitive(it) } -func (p *parser) valueArray(it item) (interface{}, tomlType) { +// Go's time.Parse() will accept numbers without a leading zero; there isn't any +// way to require it. https://github.com/golang/go/issues/29911 +// +// Depend on the fact that the separators (- and :) should always be at the same +// location. +func missingLeadingZero(d, l string) bool { + for i, c := range []byte(l) { + if c == '.' || c == 'Z' { + return false + } + if (c < '0' || c > '9') && d[i] != c { + return true + } + } + return false +} + +func (p *parser) valueArray(it item) (any, tomlType) { p.setType(p.currentKey, tomlArray, it.pos) var ( - types []tomlType - - // Initialize to a non-nil empty slice. This makes it consistent with - // how S = [] decodes into a non-nil slice inside something like struct - // { S []string }. See #338 - array = []interface{}{} + // Initialize to a non-nil slice to make it consistent with how S = [] + // decodes into a non-nil slice inside something like struct { S + // []string }. See #338 + array = make([]any, 0, 2) ) for it = p.next(); it.typ != itemArrayEnd; it = p.next() { if it.typ == itemCommentStart { @@ -394,21 +422,20 @@ func (p *parser) valueArray(it item) (interface{}, tomlType) { val, typ := p.value(it, true) array = append(array, val) - types = append(types, typ) - // XXX: types isn't used here, we need it to record the accurate type + // XXX: type isn't used here, we need it to record the accurate type // information. // // Not entirely sure how to best store this; could use "key[0]", // "key[1]" notation, or maybe store it on the Array type? - _ = types + _ = typ } return array, tomlArray } -func (p *parser) valueInlineTable(it item, parentIsArray bool) (interface{}, tomlType) { +func (p *parser) valueInlineTable(it item, parentIsArray bool) (any, tomlType) { var ( - hash = make(map[string]interface{}) + topHash = make(map[string]any) outerContext = p.context outerKey = p.currentKey ) @@ -436,11 +463,11 @@ func (p *parser) valueInlineTable(it item, parentIsArray bool) (interface{}, tom p.assertEqual(itemKeyEnd, k.typ) /// The current key is the last part. - p.currentKey = key[len(key)-1] + p.currentKey = key.last() /// All the other parts (if any) are the context; need to set each part /// as implicit. - context := key[:len(key)-1] + context := key.parent() for i := range context { p.addImplicitContext(append(p.context, context[i:i+1]...)) } @@ -448,7 +475,21 @@ func (p *parser) valueInlineTable(it item, parentIsArray bool) (interface{}, tom /// Set the value. val, typ := p.value(p.next(), false) - p.set(p.currentKey, val, typ, it.pos) + p.setValue(p.currentKey, val) + p.setType(p.currentKey, typ, it.pos) + + hash := topHash + for _, c := range context { + h, ok := hash[c] + if !ok { + h = make(map[string]any) + hash[c] = h + } + hash, ok = h.(map[string]any) + if !ok { + p.panicf("%q is not a table", p.context) + } + } hash[p.currentKey] = val /// Restore context. @@ -456,7 +497,7 @@ func (p *parser) valueInlineTable(it item, parentIsArray bool) (interface{}, tom } p.context = outerContext p.currentKey = outerKey - return hash, tomlHash + return topHash, tomlHash } // numHasLeadingZero checks if this number has leading zeroes, allowing for '0', @@ -486,9 +527,9 @@ func numUnderscoresOK(s string) bool { } } - // isHexadecimal is a superset of all the permissable characters - // surrounding an underscore. - accept = isHexadecimal(r) + // isHexis a superset of all the permissable characters surrounding an + // underscore. + accept = isHex(r) } return accept } @@ -511,21 +552,19 @@ func numPeriodsOK(s string) bool { // Establishing the context also makes sure that the key isn't a duplicate, and // will create implicit hashes automatically. func (p *parser) addContext(key Key, array bool) { - var ok bool - - // Always start at the top level and drill down for our context. + /// Always start at the top level and drill down for our context. hashContext := p.mapping - keyContext := make(Key, 0) + keyContext := make(Key, 0, len(key)-1) - // We only need implicit hashes for key[0:-1] - for _, k := range key[0 : len(key)-1] { - _, ok = hashContext[k] + /// We only need implicit hashes for the parents. + for _, k := range key.parent() { + _, ok := hashContext[k] keyContext = append(keyContext, k) // No key? Make an implicit hash and move on. if !ok { p.addImplicit(keyContext) - hashContext[k] = make(map[string]interface{}) + hashContext[k] = make(map[string]any) } // If the hash context is actually an array of tables, then set @@ -534,9 +573,9 @@ func (p *parser) addContext(key Key, array bool) { // Otherwise, it better be a table, since this MUST be a key group (by // virtue of it not being the last element in a key). switch t := hashContext[k].(type) { - case []map[string]interface{}: + case []map[string]any: hashContext = t[len(t)-1] - case map[string]interface{}: + case map[string]any: hashContext = t default: p.panicf("Key '%s' was already created as a hash.", keyContext) @@ -547,39 +586,33 @@ func (p *parser) addContext(key Key, array bool) { if array { // If this is the first element for this array, then allocate a new // list of tables for it. - k := key[len(key)-1] + k := key.last() if _, ok := hashContext[k]; !ok { - hashContext[k] = make([]map[string]interface{}, 0, 4) + hashContext[k] = make([]map[string]any, 0, 4) } // Add a new table. But make sure the key hasn't already been used // for something else. - if hash, ok := hashContext[k].([]map[string]interface{}); ok { - hashContext[k] = append(hash, make(map[string]interface{})) + if hash, ok := hashContext[k].([]map[string]any); ok { + hashContext[k] = append(hash, make(map[string]any)) } else { p.panicf("Key '%s' was already created and cannot be used as an array.", key) } } else { - p.setValue(key[len(key)-1], make(map[string]interface{})) + p.setValue(key.last(), make(map[string]any)) } - p.context = append(p.context, key[len(key)-1]) -} - -// set calls setValue and setType. -func (p *parser) set(key string, val interface{}, typ tomlType, pos Position) { - p.setValue(key, val) - p.setType(key, typ, pos) + p.context = append(p.context, key.last()) } // setValue sets the given key to the given value in the current context. // It will make sure that the key hasn't already been defined, account for // implicit key groups. -func (p *parser) setValue(key string, value interface{}) { +func (p *parser) setValue(key string, value any) { var ( - tmpHash interface{} + tmpHash any ok bool hash = p.mapping - keyContext Key + keyContext = make(Key, 0, len(p.context)+1) ) for _, k := range p.context { keyContext = append(keyContext, k) @@ -587,11 +620,11 @@ func (p *parser) setValue(key string, value interface{}) { p.bug("Context for key '%s' has not been established.", keyContext) } switch t := tmpHash.(type) { - case []map[string]interface{}: + case []map[string]any: // The context is a table of hashes. Pick the most recent table // defined as the current hash. hash = t[len(t)-1] - case map[string]interface{}: + case map[string]any: hash = t default: p.panicf("Key '%s' has already been defined.", keyContext) @@ -618,9 +651,8 @@ func (p *parser) setValue(key string, value interface{}) { p.removeImplicit(keyContext) return } - - // Otherwise, we have a concrete key trying to override a previous - // key, which is *always* wrong. + // Otherwise, we have a concrete key trying to override a previous key, + // which is *always* wrong. p.panicf("Key '%s' has already been defined.", keyContext) } @@ -683,8 +715,11 @@ func stripFirstNewline(s string) string { // the next newline. After a line-ending backslash, all whitespace is removed // until the next non-whitespace character. func (p *parser) stripEscapedNewlines(s string) string { - var b strings.Builder - var i int + var ( + b strings.Builder + i int + ) + b.Grow(len(s)) for { ix := strings.Index(s[i:], `\`) if ix < 0 { @@ -714,9 +749,8 @@ func (p *parser) stripEscapedNewlines(s string) string { continue } if !strings.Contains(s[i:j], "\n") { - // This is not a line-ending backslash. - // (It's a bad escape sequence, but we can let - // replaceEscapes catch it.) + // This is not a line-ending backslash. (It's a bad escape sequence, + // but we can let replaceEscapes catch it.) i++ continue } @@ -727,79 +761,78 @@ func (p *parser) stripEscapedNewlines(s string) string { } func (p *parser) replaceEscapes(it item, str string) string { - replaced := make([]rune, 0, len(str)) - s := []byte(str) - r := 0 - for r < len(s) { - if s[r] != '\\' { - c, size := utf8.DecodeRune(s[r:]) - r += size - replaced = append(replaced, c) + var ( + b strings.Builder + skip = 0 + ) + b.Grow(len(str)) + for i, c := range str { + if skip > 0 { + skip-- continue } - r += 1 - if r >= len(s) { + if c != '\\' { + b.WriteRune(c) + continue + } + + if i >= len(str) { p.bug("Escape sequence at end of string.") return "" } - switch s[r] { + switch str[i+1] { default: - p.bug("Expected valid escape code after \\, but got %q.", s[r]) + p.bug("Expected valid escape code after \\, but got %q.", str[i+1]) case ' ', '\t': - p.panicItemf(it, "invalid escape: '\\%c'", s[r]) + p.panicItemf(it, "invalid escape: '\\%c'", str[i+1]) case 'b': - replaced = append(replaced, rune(0x0008)) - r += 1 + b.WriteByte(0x08) + skip = 1 case 't': - replaced = append(replaced, rune(0x0009)) - r += 1 + b.WriteByte(0x09) + skip = 1 case 'n': - replaced = append(replaced, rune(0x000A)) - r += 1 + b.WriteByte(0x0a) + skip = 1 case 'f': - replaced = append(replaced, rune(0x000C)) - r += 1 + b.WriteByte(0x0c) + skip = 1 case 'r': - replaced = append(replaced, rune(0x000D)) - r += 1 + b.WriteByte(0x0d) + skip = 1 case 'e': if p.tomlNext { - replaced = append(replaced, rune(0x001B)) - r += 1 + b.WriteByte(0x1b) + skip = 1 } case '"': - replaced = append(replaced, rune(0x0022)) - r += 1 + b.WriteByte(0x22) + skip = 1 case '\\': - replaced = append(replaced, rune(0x005C)) - r += 1 + b.WriteByte(0x5c) + skip = 1 + // The lexer guarantees the correct number of characters are present; + // don't need to check here. case 'x': if p.tomlNext { - escaped := p.asciiEscapeToUnicode(it, s[r+1:r+3]) - replaced = append(replaced, escaped) - r += 3 + escaped := p.asciiEscapeToUnicode(it, str[i+2:i+4]) + b.WriteRune(escaped) + skip = 3 } case 'u': - // At this point, we know we have a Unicode escape of the form - // `uXXXX` at [r, r+5). (Because the lexer guarantees this - // for us.) - escaped := p.asciiEscapeToUnicode(it, s[r+1:r+5]) - replaced = append(replaced, escaped) - r += 5 + escaped := p.asciiEscapeToUnicode(it, str[i+2:i+6]) + b.WriteRune(escaped) + skip = 5 case 'U': - // At this point, we know we have a Unicode escape of the form - // `uXXXX` at [r, r+9). (Because the lexer guarantees this - // for us.) - escaped := p.asciiEscapeToUnicode(it, s[r+1:r+9]) - replaced = append(replaced, escaped) - r += 9 + escaped := p.asciiEscapeToUnicode(it, str[i+2:i+10]) + b.WriteRune(escaped) + skip = 9 } } - return string(replaced) + return b.String() } -func (p *parser) asciiEscapeToUnicode(it item, bs []byte) rune { - s := string(bs) +func (p *parser) asciiEscapeToUnicode(it item, s string) rune { hex, err := strconv.ParseUint(strings.ToLower(s), 16, 32) if err != nil { p.bug("Could not parse '%s' as a hexadecimal number, but the lexer claims it's OK: %s", s, err) diff --git a/vendor/github.com/BurntSushi/toml/type_fields.go b/vendor/github.com/BurntSushi/toml/type_fields.go index 254ca82e54..10c51f7eeb 100644 --- a/vendor/github.com/BurntSushi/toml/type_fields.go +++ b/vendor/github.com/BurntSushi/toml/type_fields.go @@ -25,10 +25,8 @@ type field struct { // breaking ties with index sequence. type byName []field -func (x byName) Len() int { return len(x) } - +func (x byName) Len() int { return len(x) } func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] } - func (x byName) Less(i, j int) bool { if x[i].name != x[j].name { return x[i].name < x[j].name @@ -45,10 +43,8 @@ func (x byName) Less(i, j int) bool { // byIndex sorts field by index sequence. type byIndex []field -func (x byIndex) Len() int { return len(x) } - +func (x byIndex) Len() int { return len(x) } func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] } - func (x byIndex) Less(i, j int) bool { for k, xik := range x[i].index { if k >= len(x[j].index) { diff --git a/vendor/github.com/BurntSushi/toml/type_toml.go b/vendor/github.com/BurntSushi/toml/type_toml.go index 4e90d77373..1c090d331e 100644 --- a/vendor/github.com/BurntSushi/toml/type_toml.go +++ b/vendor/github.com/BurntSushi/toml/type_toml.go @@ -22,13 +22,8 @@ func typeIsTable(t tomlType) bool { type tomlBaseType string -func (btype tomlBaseType) typeString() string { - return string(btype) -} - -func (btype tomlBaseType) String() string { - return btype.typeString() -} +func (btype tomlBaseType) typeString() string { return string(btype) } +func (btype tomlBaseType) String() string { return btype.typeString() } var ( tomlInteger tomlBaseType = "Integer" @@ -54,7 +49,7 @@ func (p *parser) typeOfPrimitive(lexItem item) tomlType { return tomlFloat case itemDatetime: return tomlDatetime - case itemString: + case itemString, itemStringEsc: return tomlString case itemMultilineString: return tomlString diff --git a/vendor/github.com/cilium/charts/README.md b/vendor/github.com/cilium/charts/README.md index 0188db588d..fb414cf4cc 100644 --- a/vendor/github.com/cilium/charts/README.md +++ b/vendor/github.com/cilium/charts/README.md @@ -1,501 +1,259 @@ This repository holds helm templates for the following Cilium releases: +* [v1.17.0-rc.1](https://github.com/cilium/cilium/releases/tag/v1.17.0-rc.1) (_[source](https://github.com/cilium/cilium/tree/v1.17.0-rc.1/install/kubernetes/cilium)_) * [v1.17.0-rc.0](https://github.com/cilium/cilium/releases/tag/v1.17.0-rc.0) (_[source](https://github.com/cilium/cilium/tree/v1.17.0-rc.0/install/kubernetes/cilium)_) * [v1.17.0-pre.3](https://github.com/cilium/cilium/releases/tag/v1.17.0-pre.3) (_[source](https://github.com/cilium/cilium/tree/v1.17.0-pre.3/install/kubernetes/cilium)_) -* [v1.17.0-pre.3](https://github.com/cilium/cilium/releases/tag/v1.17.0-pre.3) (_[source](https://github.com/cilium/cilium/tree/v1.17.0-pre.3/install/kubernetes/cilium)_) -* [v1.17.0-pre.2](https://github.com/cilium/cilium/releases/tag/v1.17.0-pre.2) (_[source](https://github.com/cilium/cilium/tree/v1.17.0-pre.2/install/kubernetes/cilium)_) * [v1.17.0-pre.2](https://github.com/cilium/cilium/releases/tag/v1.17.0-pre.2) (_[source](https://github.com/cilium/cilium/tree/v1.17.0-pre.2/install/kubernetes/cilium)_) * [v1.17.0-pre.1](https://github.com/cilium/cilium/releases/tag/v1.17.0-pre.1) (_[source](https://github.com/cilium/cilium/tree/v1.17.0-pre.1/install/kubernetes/cilium)_) -* [v1.17.0-pre.1](https://github.com/cilium/cilium/releases/tag/v1.17.0-pre.1) (_[source](https://github.com/cilium/cilium/tree/v1.17.0-pre.1/install/kubernetes/cilium)_) -* [v1.17.0-pre.0](https://github.com/cilium/cilium/releases/tag/v1.17.0-pre.0) (_[source](https://github.com/cilium/cilium/tree/v1.17.0-pre.0/install/kubernetes/cilium)_) * [v1.17.0-pre.0](https://github.com/cilium/cilium/releases/tag/v1.17.0-pre.0) (_[source](https://github.com/cilium/cilium/tree/v1.17.0-pre.0/install/kubernetes/cilium)_) +* [v1.16.6](https://github.com/cilium/cilium/releases/tag/v1.16.6) (_[source](https://github.com/cilium/cilium/tree/v1.16.6/install/kubernetes/cilium)_) * [v1.16.5](https://github.com/cilium/cilium/releases/tag/v1.16.5) (_[source](https://github.com/cilium/cilium/tree/v1.16.5/install/kubernetes/cilium)_) * [v1.16.4](https://github.com/cilium/cilium/releases/tag/v1.16.4) (_[source](https://github.com/cilium/cilium/tree/v1.16.4/install/kubernetes/cilium)_) -* [v1.16.4](https://github.com/cilium/cilium/releases/tag/v1.16.4) (_[source](https://github.com/cilium/cilium/tree/v1.16.4/install/kubernetes/cilium)_) -* [v1.16.3](https://github.com/cilium/cilium/releases/tag/v1.16.3) (_[source](https://github.com/cilium/cilium/tree/v1.16.3/install/kubernetes/cilium)_) * [v1.16.3](https://github.com/cilium/cilium/releases/tag/v1.16.3) (_[source](https://github.com/cilium/cilium/tree/v1.16.3/install/kubernetes/cilium)_) * [v1.16.2](https://github.com/cilium/cilium/releases/tag/v1.16.2) (_[source](https://github.com/cilium/cilium/tree/v1.16.2/install/kubernetes/cilium)_) -* [v1.16.2](https://github.com/cilium/cilium/releases/tag/v1.16.2) (_[source](https://github.com/cilium/cilium/tree/v1.16.2/install/kubernetes/cilium)_) -* [v1.16.1](https://github.com/cilium/cilium/releases/tag/v1.16.1) (_[source](https://github.com/cilium/cilium/tree/v1.16.1/install/kubernetes/cilium)_) * [v1.16.1](https://github.com/cilium/cilium/releases/tag/v1.16.1) (_[source](https://github.com/cilium/cilium/tree/v1.16.1/install/kubernetes/cilium)_) * [v1.16.0](https://github.com/cilium/cilium/releases/tag/v1.16.0) (_[source](https://github.com/cilium/cilium/tree/v1.16.0/install/kubernetes/cilium)_) -* [v1.16.0](https://github.com/cilium/cilium/releases/tag/v1.16.0) (_[source](https://github.com/cilium/cilium/tree/v1.16.0/install/kubernetes/cilium)_) -* [v1.16.0-rc.2](https://github.com/cilium/cilium/releases/tag/v1.16.0-rc.2) (_[source](https://github.com/cilium/cilium/tree/v1.16.0-rc.2/install/kubernetes/cilium)_) * [v1.16.0-rc.2](https://github.com/cilium/cilium/releases/tag/v1.16.0-rc.2) (_[source](https://github.com/cilium/cilium/tree/v1.16.0-rc.2/install/kubernetes/cilium)_) * [v1.16.0-rc.1](https://github.com/cilium/cilium/releases/tag/v1.16.0-rc.1) (_[source](https://github.com/cilium/cilium/tree/v1.16.0-rc.1/install/kubernetes/cilium)_) -* [v1.16.0-rc.1](https://github.com/cilium/cilium/releases/tag/v1.16.0-rc.1) (_[source](https://github.com/cilium/cilium/tree/v1.16.0-rc.1/install/kubernetes/cilium)_) -* [v1.16.0-rc.0](https://github.com/cilium/cilium/releases/tag/v1.16.0-rc.0) (_[source](https://github.com/cilium/cilium/tree/v1.16.0-rc.0/install/kubernetes/cilium)_) * [v1.16.0-rc.0](https://github.com/cilium/cilium/releases/tag/v1.16.0-rc.0) (_[source](https://github.com/cilium/cilium/tree/v1.16.0-rc.0/install/kubernetes/cilium)_) * [v1.16.0-pre.3](https://github.com/cilium/cilium/releases/tag/v1.16.0-pre.3) (_[source](https://github.com/cilium/cilium/tree/v1.16.0-pre.3/install/kubernetes/cilium)_) -* [v1.16.0-pre.3](https://github.com/cilium/cilium/releases/tag/v1.16.0-pre.3) (_[source](https://github.com/cilium/cilium/tree/v1.16.0-pre.3/install/kubernetes/cilium)_) -* [v1.16.0-pre.2](https://github.com/cilium/cilium/releases/tag/v1.16.0-pre.2) (_[source](https://github.com/cilium/cilium/tree/v1.16.0-pre.2/install/kubernetes/cilium)_) * [v1.16.0-pre.2](https://github.com/cilium/cilium/releases/tag/v1.16.0-pre.2) (_[source](https://github.com/cilium/cilium/tree/v1.16.0-pre.2/install/kubernetes/cilium)_) * [v1.16.0-pre.1](https://github.com/cilium/cilium/releases/tag/v1.16.0-pre.1) (_[source](https://github.com/cilium/cilium/tree/v1.16.0-pre.1/install/kubernetes/cilium)_) -* [v1.16.0-pre.1](https://github.com/cilium/cilium/releases/tag/v1.16.0-pre.1) (_[source](https://github.com/cilium/cilium/tree/v1.16.0-pre.1/install/kubernetes/cilium)_) -* [v1.16.0-pre.0](https://github.com/cilium/cilium/releases/tag/v1.16.0-pre.0) (_[source](https://github.com/cilium/cilium/tree/v1.16.0-pre.0/install/kubernetes/cilium)_) * [v1.16.0-pre.0](https://github.com/cilium/cilium/releases/tag/v1.16.0-pre.0) (_[source](https://github.com/cilium/cilium/tree/v1.16.0-pre.0/install/kubernetes/cilium)_) +* [v1.15.13](https://github.com/cilium/cilium/releases/tag/v1.15.13) (_[source](https://github.com/cilium/cilium/tree/v1.15.13/install/kubernetes/cilium)_) * [v1.15.12](https://github.com/cilium/cilium/releases/tag/v1.15.12) (_[source](https://github.com/cilium/cilium/tree/v1.15.12/install/kubernetes/cilium)_) * [v1.15.11](https://github.com/cilium/cilium/releases/tag/v1.15.11) (_[source](https://github.com/cilium/cilium/tree/v1.15.11/install/kubernetes/cilium)_) -* [v1.15.11](https://github.com/cilium/cilium/releases/tag/v1.15.11) (_[source](https://github.com/cilium/cilium/tree/v1.15.11/install/kubernetes/cilium)_) -* [v1.15.10](https://github.com/cilium/cilium/releases/tag/v1.15.10) (_[source](https://github.com/cilium/cilium/tree/v1.15.10/install/kubernetes/cilium)_) * [v1.15.10](https://github.com/cilium/cilium/releases/tag/v1.15.10) (_[source](https://github.com/cilium/cilium/tree/v1.15.10/install/kubernetes/cilium)_) * [v1.15.9](https://github.com/cilium/cilium/releases/tag/v1.15.9) (_[source](https://github.com/cilium/cilium/tree/v1.15.9/install/kubernetes/cilium)_) -* [v1.15.9](https://github.com/cilium/cilium/releases/tag/v1.15.9) (_[source](https://github.com/cilium/cilium/tree/v1.15.9/install/kubernetes/cilium)_) -* [v1.15.8](https://github.com/cilium/cilium/releases/tag/v1.15.8) (_[source](https://github.com/cilium/cilium/tree/v1.15.8/install/kubernetes/cilium)_) * [v1.15.8](https://github.com/cilium/cilium/releases/tag/v1.15.8) (_[source](https://github.com/cilium/cilium/tree/v1.15.8/install/kubernetes/cilium)_) * [v1.15.7](https://github.com/cilium/cilium/releases/tag/v1.15.7) (_[source](https://github.com/cilium/cilium/tree/v1.15.7/install/kubernetes/cilium)_) -* [v1.15.7](https://github.com/cilium/cilium/releases/tag/v1.15.7) (_[source](https://github.com/cilium/cilium/tree/v1.15.7/install/kubernetes/cilium)_) -* [v1.15.6](https://github.com/cilium/cilium/releases/tag/v1.15.6) (_[source](https://github.com/cilium/cilium/tree/v1.15.6/install/kubernetes/cilium)_) * [v1.15.6](https://github.com/cilium/cilium/releases/tag/v1.15.6) (_[source](https://github.com/cilium/cilium/tree/v1.15.6/install/kubernetes/cilium)_) * [v1.15.5](https://github.com/cilium/cilium/releases/tag/v1.15.5) (_[source](https://github.com/cilium/cilium/tree/v1.15.5/install/kubernetes/cilium)_) -* [v1.15.5](https://github.com/cilium/cilium/releases/tag/v1.15.5) (_[source](https://github.com/cilium/cilium/tree/v1.15.5/install/kubernetes/cilium)_) -* [v1.15.4](https://github.com/cilium/cilium/releases/tag/v1.15.4) (_[source](https://github.com/cilium/cilium/tree/v1.15.4/install/kubernetes/cilium)_) * [v1.15.4](https://github.com/cilium/cilium/releases/tag/v1.15.4) (_[source](https://github.com/cilium/cilium/tree/v1.15.4/install/kubernetes/cilium)_) * [v1.15.3](https://github.com/cilium/cilium/releases/tag/v1.15.3) (_[source](https://github.com/cilium/cilium/tree/v1.15.3/install/kubernetes/cilium)_) -* [v1.15.3](https://github.com/cilium/cilium/releases/tag/v1.15.3) (_[source](https://github.com/cilium/cilium/tree/v1.15.3/install/kubernetes/cilium)_) -* [v1.15.2](https://github.com/cilium/cilium/releases/tag/v1.15.2) (_[source](https://github.com/cilium/cilium/tree/v1.15.2/install/kubernetes/cilium)_) * [v1.15.2](https://github.com/cilium/cilium/releases/tag/v1.15.2) (_[source](https://github.com/cilium/cilium/tree/v1.15.2/install/kubernetes/cilium)_) * [v1.15.1](https://github.com/cilium/cilium/releases/tag/v1.15.1) (_[source](https://github.com/cilium/cilium/tree/v1.15.1/install/kubernetes/cilium)_) -* [v1.15.1](https://github.com/cilium/cilium/releases/tag/v1.15.1) (_[source](https://github.com/cilium/cilium/tree/v1.15.1/install/kubernetes/cilium)_) -* [v1.15.0](https://github.com/cilium/cilium/releases/tag/v1.15.0) (_[source](https://github.com/cilium/cilium/tree/v1.15.0/install/kubernetes/cilium)_) * [v1.15.0](https://github.com/cilium/cilium/releases/tag/v1.15.0) (_[source](https://github.com/cilium/cilium/tree/v1.15.0/install/kubernetes/cilium)_) * [v1.15.0-rc.1](https://github.com/cilium/cilium/releases/tag/v1.15.0-rc.1) (_[source](https://github.com/cilium/cilium/tree/v1.15.0-rc.1/install/kubernetes/cilium)_) -* [v1.15.0-rc.1](https://github.com/cilium/cilium/releases/tag/v1.15.0-rc.1) (_[source](https://github.com/cilium/cilium/tree/v1.15.0-rc.1/install/kubernetes/cilium)_) -* [v1.15.0-rc.0](https://github.com/cilium/cilium/releases/tag/v1.15.0-rc.0) (_[source](https://github.com/cilium/cilium/tree/v1.15.0-rc.0/install/kubernetes/cilium)_) * [v1.15.0-rc.0](https://github.com/cilium/cilium/releases/tag/v1.15.0-rc.0) (_[source](https://github.com/cilium/cilium/tree/v1.15.0-rc.0/install/kubernetes/cilium)_) * [v1.15.0-pre.3](https://github.com/cilium/cilium/releases/tag/v1.15.0-pre.3) (_[source](https://github.com/cilium/cilium/tree/v1.15.0-pre.3/install/kubernetes/cilium)_) -* [v1.15.0-pre.3](https://github.com/cilium/cilium/releases/tag/v1.15.0-pre.3) (_[source](https://github.com/cilium/cilium/tree/v1.15.0-pre.3/install/kubernetes/cilium)_) * [v1.15.0-pre.2](https://github.com/cilium/cilium/releases/tag/v1.15.0-pre.2) (_[source](https://github.com/cilium/cilium/tree/v1.15.0-pre.2/install/kubernetes/cilium)_) -* [v1.15.0-pre.2](https://github.com/cilium/cilium/releases/tag/v1.15.0-pre.2) (_[source](https://github.com/cilium/cilium/tree/v1.15.0-pre.2/install/kubernetes/cilium)_) -* [v1.15.0-pre.1](https://github.com/cilium/cilium/releases/tag/v1.15.0-pre.1) (_[source](https://github.com/cilium/cilium/tree/v1.15.0-pre.1/install/kubernetes/cilium)_) * [v1.15.0-pre.1](https://github.com/cilium/cilium/releases/tag/v1.15.0-pre.1) (_[source](https://github.com/cilium/cilium/tree/v1.15.0-pre.1/install/kubernetes/cilium)_) * [v1.15.0-pre.0](https://github.com/cilium/cilium/releases/tag/v1.15.0-pre.0) (_[source](https://github.com/cilium/cilium/tree/v1.15.0-pre.0/install/kubernetes/cilium)_) -* [v1.15.0-pre.0](https://github.com/cilium/cilium/releases/tag/v1.15.0-pre.0) (_[source](https://github.com/cilium/cilium/tree/v1.15.0-pre.0/install/kubernetes/cilium)_) +* [v1.14.19](https://github.com/cilium/cilium/releases/tag/v1.14.19) (_[source](https://github.com/cilium/cilium/tree/v1.14.19/install/kubernetes/cilium)_) * [v1.14.18](https://github.com/cilium/cilium/releases/tag/v1.14.18) (_[source](https://github.com/cilium/cilium/tree/v1.14.18/install/kubernetes/cilium)_) * [v1.14.17](https://github.com/cilium/cilium/releases/tag/v1.14.17) (_[source](https://github.com/cilium/cilium/tree/v1.14.17/install/kubernetes/cilium)_) -* [v1.14.17](https://github.com/cilium/cilium/releases/tag/v1.14.17) (_[source](https://github.com/cilium/cilium/tree/v1.14.17/install/kubernetes/cilium)_) * [v1.14.16](https://github.com/cilium/cilium/releases/tag/v1.14.16) (_[source](https://github.com/cilium/cilium/tree/v1.14.16/install/kubernetes/cilium)_) -* [v1.14.16](https://github.com/cilium/cilium/releases/tag/v1.14.16) (_[source](https://github.com/cilium/cilium/tree/v1.14.16/install/kubernetes/cilium)_) -* [v1.14.15](https://github.com/cilium/cilium/releases/tag/v1.14.15) (_[source](https://github.com/cilium/cilium/tree/v1.14.15/install/kubernetes/cilium)_) * [v1.14.15](https://github.com/cilium/cilium/releases/tag/v1.14.15) (_[source](https://github.com/cilium/cilium/tree/v1.14.15/install/kubernetes/cilium)_) * [v1.14.14](https://github.com/cilium/cilium/releases/tag/v1.14.14) (_[source](https://github.com/cilium/cilium/tree/v1.14.14/install/kubernetes/cilium)_) -* [v1.14.14](https://github.com/cilium/cilium/releases/tag/v1.14.14) (_[source](https://github.com/cilium/cilium/tree/v1.14.14/install/kubernetes/cilium)_) -* [v1.14.13](https://github.com/cilium/cilium/releases/tag/v1.14.13) (_[source](https://github.com/cilium/cilium/tree/v1.14.13/install/kubernetes/cilium)_) * [v1.14.13](https://github.com/cilium/cilium/releases/tag/v1.14.13) (_[source](https://github.com/cilium/cilium/tree/v1.14.13/install/kubernetes/cilium)_) * [v1.14.12](https://github.com/cilium/cilium/releases/tag/v1.14.12) (_[source](https://github.com/cilium/cilium/tree/v1.14.12/install/kubernetes/cilium)_) -* [v1.14.12](https://github.com/cilium/cilium/releases/tag/v1.14.12) (_[source](https://github.com/cilium/cilium/tree/v1.14.12/install/kubernetes/cilium)_) -* [v1.14.11](https://github.com/cilium/cilium/releases/tag/v1.14.11) (_[source](https://github.com/cilium/cilium/tree/v1.14.11/install/kubernetes/cilium)_) * [v1.14.11](https://github.com/cilium/cilium/releases/tag/v1.14.11) (_[source](https://github.com/cilium/cilium/tree/v1.14.11/install/kubernetes/cilium)_) * [v1.14.10](https://github.com/cilium/cilium/releases/tag/v1.14.10) (_[source](https://github.com/cilium/cilium/tree/v1.14.10/install/kubernetes/cilium)_) -* [v1.14.10](https://github.com/cilium/cilium/releases/tag/v1.14.10) (_[source](https://github.com/cilium/cilium/tree/v1.14.10/install/kubernetes/cilium)_) -* [v1.14.9](https://github.com/cilium/cilium/releases/tag/v1.14.9) (_[source](https://github.com/cilium/cilium/tree/v1.14.9/install/kubernetes/cilium)_) * [v1.14.9](https://github.com/cilium/cilium/releases/tag/v1.14.9) (_[source](https://github.com/cilium/cilium/tree/v1.14.9/install/kubernetes/cilium)_) * [v1.14.8](https://github.com/cilium/cilium/releases/tag/v1.14.8) (_[source](https://github.com/cilium/cilium/tree/v1.14.8/install/kubernetes/cilium)_) -* [v1.14.8](https://github.com/cilium/cilium/releases/tag/v1.14.8) (_[source](https://github.com/cilium/cilium/tree/v1.14.8/install/kubernetes/cilium)_) -* [v1.14.7](https://github.com/cilium/cilium/releases/tag/v1.14.7) (_[source](https://github.com/cilium/cilium/tree/v1.14.7/install/kubernetes/cilium)_) * [v1.14.7](https://github.com/cilium/cilium/releases/tag/v1.14.7) (_[source](https://github.com/cilium/cilium/tree/v1.14.7/install/kubernetes/cilium)_) * [v1.14.6](https://github.com/cilium/cilium/releases/tag/v1.14.6) (_[source](https://github.com/cilium/cilium/tree/v1.14.6/install/kubernetes/cilium)_) -* [v1.14.6](https://github.com/cilium/cilium/releases/tag/v1.14.6) (_[source](https://github.com/cilium/cilium/tree/v1.14.6/install/kubernetes/cilium)_) -* [v1.14.5](https://github.com/cilium/cilium/releases/tag/v1.14.5) (_[source](https://github.com/cilium/cilium/tree/v1.14.5/install/kubernetes/cilium)_) * [v1.14.5](https://github.com/cilium/cilium/releases/tag/v1.14.5) (_[source](https://github.com/cilium/cilium/tree/v1.14.5/install/kubernetes/cilium)_) * [v1.14.4](https://github.com/cilium/cilium/releases/tag/v1.14.4) (_[source](https://github.com/cilium/cilium/tree/v1.14.4/install/kubernetes/cilium)_) -* [v1.14.4](https://github.com/cilium/cilium/releases/tag/v1.14.4) (_[source](https://github.com/cilium/cilium/tree/v1.14.4/install/kubernetes/cilium)_) -* [v1.14.3](https://github.com/cilium/cilium/releases/tag/v1.14.3) (_[source](https://github.com/cilium/cilium/tree/v1.14.3/install/kubernetes/cilium)_) * [v1.14.3](https://github.com/cilium/cilium/releases/tag/v1.14.3) (_[source](https://github.com/cilium/cilium/tree/v1.14.3/install/kubernetes/cilium)_) * [v1.14.2](https://github.com/cilium/cilium/releases/tag/v1.14.2) (_[source](https://github.com/cilium/cilium/tree/v1.14.2/install/kubernetes/cilium)_) -* [v1.14.2](https://github.com/cilium/cilium/releases/tag/v1.14.2) (_[source](https://github.com/cilium/cilium/tree/v1.14.2/install/kubernetes/cilium)_) -* [v1.14.1](https://github.com/cilium/cilium/releases/tag/v1.14.1) (_[source](https://github.com/cilium/cilium/tree/v1.14.1/install/kubernetes/cilium)_) * [v1.14.1](https://github.com/cilium/cilium/releases/tag/v1.14.1) (_[source](https://github.com/cilium/cilium/tree/v1.14.1/install/kubernetes/cilium)_) * [v1.14.0](https://github.com/cilium/cilium/releases/tag/v1.14.0) (_[source](https://github.com/cilium/cilium/tree/v1.14.0/install/kubernetes/cilium)_) -* [v1.14.0](https://github.com/cilium/cilium/releases/tag/v1.14.0) (_[source](https://github.com/cilium/cilium/tree/v1.14.0/install/kubernetes/cilium)_) -* [v1.14.0-snapshot.4](https://github.com/cilium/cilium/releases/tag/v1.14.0-snapshot.4) (_[source](https://github.com/cilium/cilium/tree/v1.14.0-snapshot.4/install/kubernetes/cilium)_) * [v1.14.0-snapshot.4](https://github.com/cilium/cilium/releases/tag/v1.14.0-snapshot.4) (_[source](https://github.com/cilium/cilium/tree/v1.14.0-snapshot.4/install/kubernetes/cilium)_) * [v1.14.0-snapshot.3](https://github.com/cilium/cilium/releases/tag/v1.14.0-snapshot.3) (_[source](https://github.com/cilium/cilium/tree/v1.14.0-snapshot.3/install/kubernetes/cilium)_) -* [v1.14.0-snapshot.3](https://github.com/cilium/cilium/releases/tag/v1.14.0-snapshot.3) (_[source](https://github.com/cilium/cilium/tree/v1.14.0-snapshot.3/install/kubernetes/cilium)_) -* [v1.14.0-snapshot.2](https://github.com/cilium/cilium/releases/tag/v1.14.0-snapshot.2) (_[source](https://github.com/cilium/cilium/tree/v1.14.0-snapshot.2/install/kubernetes/cilium)_) * [v1.14.0-snapshot.2](https://github.com/cilium/cilium/releases/tag/v1.14.0-snapshot.2) (_[source](https://github.com/cilium/cilium/tree/v1.14.0-snapshot.2/install/kubernetes/cilium)_) * [v1.14.0-snapshot.1](https://github.com/cilium/cilium/releases/tag/v1.14.0-snapshot.1) (_[source](https://github.com/cilium/cilium/tree/v1.14.0-snapshot.1/install/kubernetes/cilium)_) -* [v1.14.0-snapshot.1](https://github.com/cilium/cilium/releases/tag/v1.14.0-snapshot.1) (_[source](https://github.com/cilium/cilium/tree/v1.14.0-snapshot.1/install/kubernetes/cilium)_) -* [v1.14.0-snapshot.0](https://github.com/cilium/cilium/releases/tag/v1.14.0-snapshot.0) (_[source](https://github.com/cilium/cilium/tree/v1.14.0-snapshot.0/install/kubernetes/cilium)_) * [v1.14.0-snapshot.0](https://github.com/cilium/cilium/releases/tag/v1.14.0-snapshot.0) (_[source](https://github.com/cilium/cilium/tree/v1.14.0-snapshot.0/install/kubernetes/cilium)_) * [v1.14.0-rc.1](https://github.com/cilium/cilium/releases/tag/v1.14.0-rc.1) (_[source](https://github.com/cilium/cilium/tree/v1.14.0-rc.1/install/kubernetes/cilium)_) -* [v1.14.0-rc.1](https://github.com/cilium/cilium/releases/tag/v1.14.0-rc.1) (_[source](https://github.com/cilium/cilium/tree/v1.14.0-rc.1/install/kubernetes/cilium)_) -* [v1.14.0-rc.0](https://github.com/cilium/cilium/releases/tag/v1.14.0-rc.0) (_[source](https://github.com/cilium/cilium/tree/v1.14.0-rc.0/install/kubernetes/cilium)_) * [v1.14.0-rc.0](https://github.com/cilium/cilium/releases/tag/v1.14.0-rc.0) (_[source](https://github.com/cilium/cilium/tree/v1.14.0-rc.0/install/kubernetes/cilium)_) * [v1.13.18](https://github.com/cilium/cilium/releases/tag/v1.13.18) (_[source](https://github.com/cilium/cilium/tree/v1.13.18/install/kubernetes/cilium)_) -* [v1.13.18](https://github.com/cilium/cilium/releases/tag/v1.13.18) (_[source](https://github.com/cilium/cilium/tree/v1.13.18/install/kubernetes/cilium)_) -* [v1.13.17](https://github.com/cilium/cilium/releases/tag/v1.13.17) (_[source](https://github.com/cilium/cilium/tree/v1.13.17/install/kubernetes/cilium)_) * [v1.13.17](https://github.com/cilium/cilium/releases/tag/v1.13.17) (_[source](https://github.com/cilium/cilium/tree/v1.13.17/install/kubernetes/cilium)_) * [v1.13.16](https://github.com/cilium/cilium/releases/tag/v1.13.16) (_[source](https://github.com/cilium/cilium/tree/v1.13.16/install/kubernetes/cilium)_) -* [v1.13.16](https://github.com/cilium/cilium/releases/tag/v1.13.16) (_[source](https://github.com/cilium/cilium/tree/v1.13.16/install/kubernetes/cilium)_) * [v1.13.15](https://github.com/cilium/cilium/releases/tag/v1.13.15) (_[source](https://github.com/cilium/cilium/tree/v1.13.15/install/kubernetes/cilium)_) -* [v1.13.15](https://github.com/cilium/cilium/releases/tag/v1.13.15) (_[source](https://github.com/cilium/cilium/tree/v1.13.15/install/kubernetes/cilium)_) -* [v1.13.14](https://github.com/cilium/cilium/releases/tag/v1.13.14) (_[source](https://github.com/cilium/cilium/tree/v1.13.14/install/kubernetes/cilium)_) * [v1.13.14](https://github.com/cilium/cilium/releases/tag/v1.13.14) (_[source](https://github.com/cilium/cilium/tree/v1.13.14/install/kubernetes/cilium)_) * [v1.13.13](https://github.com/cilium/cilium/releases/tag/v1.13.13) (_[source](https://github.com/cilium/cilium/tree/v1.13.13/install/kubernetes/cilium)_) -* [v1.13.13](https://github.com/cilium/cilium/releases/tag/v1.13.13) (_[source](https://github.com/cilium/cilium/tree/v1.13.13/install/kubernetes/cilium)_) -* [v1.13.12](https://github.com/cilium/cilium/releases/tag/v1.13.12) (_[source](https://github.com/cilium/cilium/tree/v1.13.12/install/kubernetes/cilium)_) * [v1.13.12](https://github.com/cilium/cilium/releases/tag/v1.13.12) (_[source](https://github.com/cilium/cilium/tree/v1.13.12/install/kubernetes/cilium)_) * [v1.13.11](https://github.com/cilium/cilium/releases/tag/v1.13.11) (_[source](https://github.com/cilium/cilium/tree/v1.13.11/install/kubernetes/cilium)_) -* [v1.13.11](https://github.com/cilium/cilium/releases/tag/v1.13.11) (_[source](https://github.com/cilium/cilium/tree/v1.13.11/install/kubernetes/cilium)_) -* [v1.13.10](https://github.com/cilium/cilium/releases/tag/v1.13.10) (_[source](https://github.com/cilium/cilium/tree/v1.13.10/install/kubernetes/cilium)_) * [v1.13.10](https://github.com/cilium/cilium/releases/tag/v1.13.10) (_[source](https://github.com/cilium/cilium/tree/v1.13.10/install/kubernetes/cilium)_) * [v1.13.9](https://github.com/cilium/cilium/releases/tag/v1.13.9) (_[source](https://github.com/cilium/cilium/tree/v1.13.9/install/kubernetes/cilium)_) -* [v1.13.9](https://github.com/cilium/cilium/releases/tag/v1.13.9) (_[source](https://github.com/cilium/cilium/tree/v1.13.9/install/kubernetes/cilium)_) -* [v1.13.8](https://github.com/cilium/cilium/releases/tag/v1.13.8) (_[source](https://github.com/cilium/cilium/tree/v1.13.8/install/kubernetes/cilium)_) * [v1.13.8](https://github.com/cilium/cilium/releases/tag/v1.13.8) (_[source](https://github.com/cilium/cilium/tree/v1.13.8/install/kubernetes/cilium)_) * [v1.13.7](https://github.com/cilium/cilium/releases/tag/v1.13.7) (_[source](https://github.com/cilium/cilium/tree/v1.13.7/install/kubernetes/cilium)_) -* [v1.13.7](https://github.com/cilium/cilium/releases/tag/v1.13.7) (_[source](https://github.com/cilium/cilium/tree/v1.13.7/install/kubernetes/cilium)_) -* [v1.13.6](https://github.com/cilium/cilium/releases/tag/v1.13.6) (_[source](https://github.com/cilium/cilium/tree/v1.13.6/install/kubernetes/cilium)_) * [v1.13.6](https://github.com/cilium/cilium/releases/tag/v1.13.6) (_[source](https://github.com/cilium/cilium/tree/v1.13.6/install/kubernetes/cilium)_) * [v1.13.5](https://github.com/cilium/cilium/releases/tag/v1.13.5) (_[source](https://github.com/cilium/cilium/tree/v1.13.5/install/kubernetes/cilium)_) -* [v1.13.5](https://github.com/cilium/cilium/releases/tag/v1.13.5) (_[source](https://github.com/cilium/cilium/tree/v1.13.5/install/kubernetes/cilium)_) -* [v1.13.4](https://github.com/cilium/cilium/releases/tag/v1.13.4) (_[source](https://github.com/cilium/cilium/tree/v1.13.4/install/kubernetes/cilium)_) * [v1.13.4](https://github.com/cilium/cilium/releases/tag/v1.13.4) (_[source](https://github.com/cilium/cilium/tree/v1.13.4/install/kubernetes/cilium)_) * [v1.13.3](https://github.com/cilium/cilium/releases/tag/v1.13.3) (_[source](https://github.com/cilium/cilium/tree/v1.13.3/install/kubernetes/cilium)_) -* [v1.13.3](https://github.com/cilium/cilium/releases/tag/v1.13.3) (_[source](https://github.com/cilium/cilium/tree/v1.13.3/install/kubernetes/cilium)_) -* [v1.13.2](https://github.com/cilium/cilium/releases/tag/v1.13.2) (_[source](https://github.com/cilium/cilium/tree/v1.13.2/install/kubernetes/cilium)_) * [v1.13.2](https://github.com/cilium/cilium/releases/tag/v1.13.2) (_[source](https://github.com/cilium/cilium/tree/v1.13.2/install/kubernetes/cilium)_) * [v1.13.1](https://github.com/cilium/cilium/releases/tag/v1.13.1) (_[source](https://github.com/cilium/cilium/tree/v1.13.1/install/kubernetes/cilium)_) -* [v1.13.1](https://github.com/cilium/cilium/releases/tag/v1.13.1) (_[source](https://github.com/cilium/cilium/tree/v1.13.1/install/kubernetes/cilium)_) -* [v1.13.0](https://github.com/cilium/cilium/releases/tag/v1.13.0) (_[source](https://github.com/cilium/cilium/tree/v1.13.0/install/kubernetes/cilium)_) * [v1.13.0](https://github.com/cilium/cilium/releases/tag/v1.13.0) (_[source](https://github.com/cilium/cilium/tree/v1.13.0/install/kubernetes/cilium)_) * [v1.13.0-rc5](https://github.com/cilium/cilium/releases/tag/v1.13.0-rc5) (_[source](https://github.com/cilium/cilium/tree/v1.13.0-rc5/install/kubernetes/cilium)_) -* [v1.13.0-rc5](https://github.com/cilium/cilium/releases/tag/v1.13.0-rc5) (_[source](https://github.com/cilium/cilium/tree/v1.13.0-rc5/install/kubernetes/cilium)_) -* [v1.13.0-rc4](https://github.com/cilium/cilium/releases/tag/v1.13.0-rc4) (_[source](https://github.com/cilium/cilium/tree/v1.13.0-rc4/install/kubernetes/cilium)_) * [v1.13.0-rc4](https://github.com/cilium/cilium/releases/tag/v1.13.0-rc4) (_[source](https://github.com/cilium/cilium/tree/v1.13.0-rc4/install/kubernetes/cilium)_) * [v1.13.0-rc3](https://github.com/cilium/cilium/releases/tag/v1.13.0-rc3) (_[source](https://github.com/cilium/cilium/tree/v1.13.0-rc3/install/kubernetes/cilium)_) -* [v1.13.0-rc3](https://github.com/cilium/cilium/releases/tag/v1.13.0-rc3) (_[source](https://github.com/cilium/cilium/tree/v1.13.0-rc3/install/kubernetes/cilium)_) -* [v1.13.0-rc2](https://github.com/cilium/cilium/releases/tag/v1.13.0-rc2) (_[source](https://github.com/cilium/cilium/tree/v1.13.0-rc2/install/kubernetes/cilium)_) * [v1.13.0-rc2](https://github.com/cilium/cilium/releases/tag/v1.13.0-rc2) (_[source](https://github.com/cilium/cilium/tree/v1.13.0-rc2/install/kubernetes/cilium)_) * [v1.13.0-rc1](https://github.com/cilium/cilium/releases/tag/v1.13.0-rc1) (_[source](https://github.com/cilium/cilium/tree/v1.13.0-rc1/install/kubernetes/cilium)_) -* [v1.13.0-rc1](https://github.com/cilium/cilium/releases/tag/v1.13.0-rc1) (_[source](https://github.com/cilium/cilium/tree/v1.13.0-rc1/install/kubernetes/cilium)_) -* [v1.13.0-rc0](https://github.com/cilium/cilium/releases/tag/v1.13.0-rc0) (_[source](https://github.com/cilium/cilium/tree/v1.13.0-rc0/install/kubernetes/cilium)_) * [v1.13.0-rc0](https://github.com/cilium/cilium/releases/tag/v1.13.0-rc0) (_[source](https://github.com/cilium/cilium/tree/v1.13.0-rc0/install/kubernetes/cilium)_) * [v1.12.19](https://github.com/cilium/cilium/releases/tag/v1.12.19) (_[source](https://github.com/cilium/cilium/tree/v1.12.19/install/kubernetes/cilium)_) -* [v1.12.19](https://github.com/cilium/cilium/releases/tag/v1.12.19) (_[source](https://github.com/cilium/cilium/tree/v1.12.19/install/kubernetes/cilium)_) -* [v1.12.18](https://github.com/cilium/cilium/releases/tag/v1.12.18) (_[source](https://github.com/cilium/cilium/tree/v1.12.18/install/kubernetes/cilium)_) * [v1.12.18](https://github.com/cilium/cilium/releases/tag/v1.12.18) (_[source](https://github.com/cilium/cilium/tree/v1.12.18/install/kubernetes/cilium)_) * [v1.12.17](https://github.com/cilium/cilium/releases/tag/v1.12.17) (_[source](https://github.com/cilium/cilium/tree/v1.12.17/install/kubernetes/cilium)_) -* [v1.12.17](https://github.com/cilium/cilium/releases/tag/v1.12.17) (_[source](https://github.com/cilium/cilium/tree/v1.12.17/install/kubernetes/cilium)_) -* [v1.12.16](https://github.com/cilium/cilium/releases/tag/v1.12.16) (_[source](https://github.com/cilium/cilium/tree/v1.12.16/install/kubernetes/cilium)_) * [v1.12.16](https://github.com/cilium/cilium/releases/tag/v1.12.16) (_[source](https://github.com/cilium/cilium/tree/v1.12.16/install/kubernetes/cilium)_) * [v1.12.15](https://github.com/cilium/cilium/releases/tag/v1.12.15) (_[source](https://github.com/cilium/cilium/tree/v1.12.15/install/kubernetes/cilium)_) -* [v1.12.15](https://github.com/cilium/cilium/releases/tag/v1.12.15) (_[source](https://github.com/cilium/cilium/tree/v1.12.15/install/kubernetes/cilium)_) -* [v1.12.14](https://github.com/cilium/cilium/releases/tag/v1.12.14) (_[source](https://github.com/cilium/cilium/tree/v1.12.14/install/kubernetes/cilium)_) * [v1.12.14](https://github.com/cilium/cilium/releases/tag/v1.12.14) (_[source](https://github.com/cilium/cilium/tree/v1.12.14/install/kubernetes/cilium)_) * [v1.12.13](https://github.com/cilium/cilium/releases/tag/v1.12.13) (_[source](https://github.com/cilium/cilium/tree/v1.12.13/install/kubernetes/cilium)_) -* [v1.12.13](https://github.com/cilium/cilium/releases/tag/v1.12.13) (_[source](https://github.com/cilium/cilium/tree/v1.12.13/install/kubernetes/cilium)_) -* [v1.12.12](https://github.com/cilium/cilium/releases/tag/v1.12.12) (_[source](https://github.com/cilium/cilium/tree/v1.12.12/install/kubernetes/cilium)_) * [v1.12.12](https://github.com/cilium/cilium/releases/tag/v1.12.12) (_[source](https://github.com/cilium/cilium/tree/v1.12.12/install/kubernetes/cilium)_) * [v1.12.11](https://github.com/cilium/cilium/releases/tag/v1.12.11) (_[source](https://github.com/cilium/cilium/tree/v1.12.11/install/kubernetes/cilium)_) -* [v1.12.11](https://github.com/cilium/cilium/releases/tag/v1.12.11) (_[source](https://github.com/cilium/cilium/tree/v1.12.11/install/kubernetes/cilium)_) * [v1.12.10](https://github.com/cilium/cilium/releases/tag/v1.12.10) (_[source](https://github.com/cilium/cilium/tree/v1.12.10/install/kubernetes/cilium)_) -* [v1.12.10](https://github.com/cilium/cilium/releases/tag/v1.12.10) (_[source](https://github.com/cilium/cilium/tree/v1.12.10/install/kubernetes/cilium)_) -* [v1.12.9](https://github.com/cilium/cilium/releases/tag/v1.12.9) (_[source](https://github.com/cilium/cilium/tree/v1.12.9/install/kubernetes/cilium)_) * [v1.12.9](https://github.com/cilium/cilium/releases/tag/v1.12.9) (_[source](https://github.com/cilium/cilium/tree/v1.12.9/install/kubernetes/cilium)_) * [v1.12.8](https://github.com/cilium/cilium/releases/tag/v1.12.8) (_[source](https://github.com/cilium/cilium/tree/v1.12.8/install/kubernetes/cilium)_) -* [v1.12.8](https://github.com/cilium/cilium/releases/tag/v1.12.8) (_[source](https://github.com/cilium/cilium/tree/v1.12.8/install/kubernetes/cilium)_) -* [v1.12.7](https://github.com/cilium/cilium/releases/tag/v1.12.7) (_[source](https://github.com/cilium/cilium/tree/v1.12.7/install/kubernetes/cilium)_) * [v1.12.7](https://github.com/cilium/cilium/releases/tag/v1.12.7) (_[source](https://github.com/cilium/cilium/tree/v1.12.7/install/kubernetes/cilium)_) * [v1.12.6](https://github.com/cilium/cilium/releases/tag/v1.12.6) (_[source](https://github.com/cilium/cilium/tree/v1.12.6/install/kubernetes/cilium)_) -* [v1.12.6](https://github.com/cilium/cilium/releases/tag/v1.12.6) (_[source](https://github.com/cilium/cilium/tree/v1.12.6/install/kubernetes/cilium)_) -* [v1.12.5](https://github.com/cilium/cilium/releases/tag/v1.12.5) (_[source](https://github.com/cilium/cilium/tree/v1.12.5/install/kubernetes/cilium)_) * [v1.12.5](https://github.com/cilium/cilium/releases/tag/v1.12.5) (_[source](https://github.com/cilium/cilium/tree/v1.12.5/install/kubernetes/cilium)_) * [v1.12.4](https://github.com/cilium/cilium/releases/tag/v1.12.4) (_[source](https://github.com/cilium/cilium/tree/v1.12.4/install/kubernetes/cilium)_) -* [v1.12.4](https://github.com/cilium/cilium/releases/tag/v1.12.4) (_[source](https://github.com/cilium/cilium/tree/v1.12.4/install/kubernetes/cilium)_) -* [v1.12.3](https://github.com/cilium/cilium/releases/tag/v1.12.3) (_[source](https://github.com/cilium/cilium/tree/v1.12.3/install/kubernetes/cilium)_) * [v1.12.3](https://github.com/cilium/cilium/releases/tag/v1.12.3) (_[source](https://github.com/cilium/cilium/tree/v1.12.3/install/kubernetes/cilium)_) * [v1.12.2](https://github.com/cilium/cilium/releases/tag/v1.12.2) (_[source](https://github.com/cilium/cilium/tree/v1.12.2/install/kubernetes/cilium)_) -* [v1.12.2](https://github.com/cilium/cilium/releases/tag/v1.12.2) (_[source](https://github.com/cilium/cilium/tree/v1.12.2/install/kubernetes/cilium)_) -* [v1.12.1](https://github.com/cilium/cilium/releases/tag/v1.12.1) (_[source](https://github.com/cilium/cilium/tree/v1.12.1/install/kubernetes/cilium)_) * [v1.12.1](https://github.com/cilium/cilium/releases/tag/v1.12.1) (_[source](https://github.com/cilium/cilium/tree/v1.12.1/install/kubernetes/cilium)_) * [v1.12.0](https://github.com/cilium/cilium/releases/tag/v1.12.0) (_[source](https://github.com/cilium/cilium/tree/v1.12.0/install/kubernetes/cilium)_) -* [v1.12.0](https://github.com/cilium/cilium/releases/tag/v1.12.0) (_[source](https://github.com/cilium/cilium/tree/v1.12.0/install/kubernetes/cilium)_) -* [v1.12.0-rc3](https://github.com/cilium/cilium/releases/tag/v1.12.0-rc3) (_[source](https://github.com/cilium/cilium/tree/v1.12.0-rc3/install/kubernetes/cilium)_) * [v1.12.0-rc3](https://github.com/cilium/cilium/releases/tag/v1.12.0-rc3) (_[source](https://github.com/cilium/cilium/tree/v1.12.0-rc3/install/kubernetes/cilium)_) * [v1.12.0-rc2](https://github.com/cilium/cilium/releases/tag/v1.12.0-rc2) (_[source](https://github.com/cilium/cilium/tree/v1.12.0-rc2/install/kubernetes/cilium)_) -* [v1.12.0-rc2](https://github.com/cilium/cilium/releases/tag/v1.12.0-rc2) (_[source](https://github.com/cilium/cilium/tree/v1.12.0-rc2/install/kubernetes/cilium)_) -* [v1.12.0-rc1](https://github.com/cilium/cilium/releases/tag/v1.12.0-rc1) (_[source](https://github.com/cilium/cilium/tree/v1.12.0-rc1/install/kubernetes/cilium)_) * [v1.12.0-rc1](https://github.com/cilium/cilium/releases/tag/v1.12.0-rc1) (_[source](https://github.com/cilium/cilium/tree/v1.12.0-rc1/install/kubernetes/cilium)_) * [v1.12.0-rc0](https://github.com/cilium/cilium/releases/tag/v1.12.0-rc0) (_[source](https://github.com/cilium/cilium/tree/v1.12.0-rc0/install/kubernetes/cilium)_) -* [v1.12.0-rc0](https://github.com/cilium/cilium/releases/tag/v1.12.0-rc0) (_[source](https://github.com/cilium/cilium/tree/v1.12.0-rc0/install/kubernetes/cilium)_) * [v1.11.20](https://github.com/cilium/cilium/releases/tag/v1.11.20) (_[source](https://github.com/cilium/cilium/tree/v1.11.20/install/kubernetes/cilium)_) -* [v1.11.20](https://github.com/cilium/cilium/releases/tag/v1.11.20) (_[source](https://github.com/cilium/cilium/tree/v1.11.20/install/kubernetes/cilium)_) -* [v1.11.19](https://github.com/cilium/cilium/releases/tag/v1.11.19) (_[source](https://github.com/cilium/cilium/tree/v1.11.19/install/kubernetes/cilium)_) * [v1.11.19](https://github.com/cilium/cilium/releases/tag/v1.11.19) (_[source](https://github.com/cilium/cilium/tree/v1.11.19/install/kubernetes/cilium)_) * [v1.11.18](https://github.com/cilium/cilium/releases/tag/v1.11.18) (_[source](https://github.com/cilium/cilium/tree/v1.11.18/install/kubernetes/cilium)_) -* [v1.11.18](https://github.com/cilium/cilium/releases/tag/v1.11.18) (_[source](https://github.com/cilium/cilium/tree/v1.11.18/install/kubernetes/cilium)_) -* [v1.11.17](https://github.com/cilium/cilium/releases/tag/v1.11.17) (_[source](https://github.com/cilium/cilium/tree/v1.11.17/install/kubernetes/cilium)_) * [v1.11.17](https://github.com/cilium/cilium/releases/tag/v1.11.17) (_[source](https://github.com/cilium/cilium/tree/v1.11.17/install/kubernetes/cilium)_) * [v1.11.16](https://github.com/cilium/cilium/releases/tag/v1.11.16) (_[source](https://github.com/cilium/cilium/tree/v1.11.16/install/kubernetes/cilium)_) -* [v1.11.16](https://github.com/cilium/cilium/releases/tag/v1.11.16) (_[source](https://github.com/cilium/cilium/tree/v1.11.16/install/kubernetes/cilium)_) -* [v1.11.15](https://github.com/cilium/cilium/releases/tag/v1.11.15) (_[source](https://github.com/cilium/cilium/tree/v1.11.15/install/kubernetes/cilium)_) * [v1.11.15](https://github.com/cilium/cilium/releases/tag/v1.11.15) (_[source](https://github.com/cilium/cilium/tree/v1.11.15/install/kubernetes/cilium)_) * [v1.11.14](https://github.com/cilium/cilium/releases/tag/v1.11.14) (_[source](https://github.com/cilium/cilium/tree/v1.11.14/install/kubernetes/cilium)_) -* [v1.11.14](https://github.com/cilium/cilium/releases/tag/v1.11.14) (_[source](https://github.com/cilium/cilium/tree/v1.11.14/install/kubernetes/cilium)_) -* [v1.11.13](https://github.com/cilium/cilium/releases/tag/v1.11.13) (_[source](https://github.com/cilium/cilium/tree/v1.11.13/install/kubernetes/cilium)_) * [v1.11.13](https://github.com/cilium/cilium/releases/tag/v1.11.13) (_[source](https://github.com/cilium/cilium/tree/v1.11.13/install/kubernetes/cilium)_) * [v1.11.12](https://github.com/cilium/cilium/releases/tag/v1.11.12) (_[source](https://github.com/cilium/cilium/tree/v1.11.12/install/kubernetes/cilium)_) -* [v1.11.12](https://github.com/cilium/cilium/releases/tag/v1.11.12) (_[source](https://github.com/cilium/cilium/tree/v1.11.12/install/kubernetes/cilium)_) -* [v1.11.11](https://github.com/cilium/cilium/releases/tag/v1.11.11) (_[source](https://github.com/cilium/cilium/tree/v1.11.11/install/kubernetes/cilium)_) * [v1.11.11](https://github.com/cilium/cilium/releases/tag/v1.11.11) (_[source](https://github.com/cilium/cilium/tree/v1.11.11/install/kubernetes/cilium)_) * [v1.11.10](https://github.com/cilium/cilium/releases/tag/v1.11.10) (_[source](https://github.com/cilium/cilium/tree/v1.11.10/install/kubernetes/cilium)_) -* [v1.11.10](https://github.com/cilium/cilium/releases/tag/v1.11.10) (_[source](https://github.com/cilium/cilium/tree/v1.11.10/install/kubernetes/cilium)_) -* [v1.11.9](https://github.com/cilium/cilium/releases/tag/v1.11.9) (_[source](https://github.com/cilium/cilium/tree/v1.11.9/install/kubernetes/cilium)_) * [v1.11.9](https://github.com/cilium/cilium/releases/tag/v1.11.9) (_[source](https://github.com/cilium/cilium/tree/v1.11.9/install/kubernetes/cilium)_) * [v1.11.8](https://github.com/cilium/cilium/releases/tag/v1.11.8) (_[source](https://github.com/cilium/cilium/tree/v1.11.8/install/kubernetes/cilium)_) -* [v1.11.8](https://github.com/cilium/cilium/releases/tag/v1.11.8) (_[source](https://github.com/cilium/cilium/tree/v1.11.8/install/kubernetes/cilium)_) -* [v1.11.7](https://github.com/cilium/cilium/releases/tag/v1.11.7) (_[source](https://github.com/cilium/cilium/tree/v1.11.7/install/kubernetes/cilium)_) * [v1.11.7](https://github.com/cilium/cilium/releases/tag/v1.11.7) (_[source](https://github.com/cilium/cilium/tree/v1.11.7/install/kubernetes/cilium)_) * [v1.11.6](https://github.com/cilium/cilium/releases/tag/v1.11.6) (_[source](https://github.com/cilium/cilium/tree/v1.11.6/install/kubernetes/cilium)_) -* [v1.11.6](https://github.com/cilium/cilium/releases/tag/v1.11.6) (_[source](https://github.com/cilium/cilium/tree/v1.11.6/install/kubernetes/cilium)_) * [v1.11.5](https://github.com/cilium/cilium/releases/tag/v1.11.5) (_[source](https://github.com/cilium/cilium/tree/v1.11.5/install/kubernetes/cilium)_) -* [v1.11.5](https://github.com/cilium/cilium/releases/tag/v1.11.5) (_[source](https://github.com/cilium/cilium/tree/v1.11.5/install/kubernetes/cilium)_) -* [v1.11.4](https://github.com/cilium/cilium/releases/tag/v1.11.4) (_[source](https://github.com/cilium/cilium/tree/v1.11.4/install/kubernetes/cilium)_) * [v1.11.4](https://github.com/cilium/cilium/releases/tag/v1.11.4) (_[source](https://github.com/cilium/cilium/tree/v1.11.4/install/kubernetes/cilium)_) * [v1.11.3](https://github.com/cilium/cilium/releases/tag/v1.11.3) (_[source](https://github.com/cilium/cilium/tree/v1.11.3/install/kubernetes/cilium)_) -* [v1.11.3](https://github.com/cilium/cilium/releases/tag/v1.11.3) (_[source](https://github.com/cilium/cilium/tree/v1.11.3/install/kubernetes/cilium)_) -* [v1.11.2](https://github.com/cilium/cilium/releases/tag/v1.11.2) (_[source](https://github.com/cilium/cilium/tree/v1.11.2/install/kubernetes/cilium)_) * [v1.11.2](https://github.com/cilium/cilium/releases/tag/v1.11.2) (_[source](https://github.com/cilium/cilium/tree/v1.11.2/install/kubernetes/cilium)_) * [v1.11.1](https://github.com/cilium/cilium/releases/tag/v1.11.1) (_[source](https://github.com/cilium/cilium/tree/v1.11.1/install/kubernetes/cilium)_) -* [v1.11.1](https://github.com/cilium/cilium/releases/tag/v1.11.1) (_[source](https://github.com/cilium/cilium/tree/v1.11.1/install/kubernetes/cilium)_) -* [v1.11.0](https://github.com/cilium/cilium/releases/tag/v1.11.0) (_[source](https://github.com/cilium/cilium/tree/v1.11.0/install/kubernetes/cilium)_) * [v1.11.0](https://github.com/cilium/cilium/releases/tag/v1.11.0) (_[source](https://github.com/cilium/cilium/tree/v1.11.0/install/kubernetes/cilium)_) * [v1.11.0-rc3](https://github.com/cilium/cilium/releases/tag/v1.11.0-rc3) (_[source](https://github.com/cilium/cilium/tree/v1.11.0-rc3/install/kubernetes/cilium)_) -* [v1.11.0-rc3](https://github.com/cilium/cilium/releases/tag/v1.11.0-rc3) (_[source](https://github.com/cilium/cilium/tree/v1.11.0-rc3/install/kubernetes/cilium)_) -* [v1.11.0-rc2](https://github.com/cilium/cilium/releases/tag/v1.11.0-rc2) (_[source](https://github.com/cilium/cilium/tree/v1.11.0-rc2/install/kubernetes/cilium)_) * [v1.11.0-rc2](https://github.com/cilium/cilium/releases/tag/v1.11.0-rc2) (_[source](https://github.com/cilium/cilium/tree/v1.11.0-rc2/install/kubernetes/cilium)_) * [v1.11.0-rc1](https://github.com/cilium/cilium/releases/tag/v1.11.0-rc1) (_[source](https://github.com/cilium/cilium/tree/v1.11.0-rc1/install/kubernetes/cilium)_) -* [v1.11.0-rc1](https://github.com/cilium/cilium/releases/tag/v1.11.0-rc1) (_[source](https://github.com/cilium/cilium/tree/v1.11.0-rc1/install/kubernetes/cilium)_) -* [v1.11.0-rc0](https://github.com/cilium/cilium/releases/tag/v1.11.0-rc0) (_[source](https://github.com/cilium/cilium/tree/v1.11.0-rc0/install/kubernetes/cilium)_) * [v1.11.0-rc0](https://github.com/cilium/cilium/releases/tag/v1.11.0-rc0) (_[source](https://github.com/cilium/cilium/tree/v1.11.0-rc0/install/kubernetes/cilium)_) * [v1.10.20](https://github.com/cilium/cilium/releases/tag/v1.10.20) (_[source](https://github.com/cilium/cilium/tree/v1.10.20/install/kubernetes/cilium)_) -* [v1.10.20](https://github.com/cilium/cilium/releases/tag/v1.10.20) (_[source](https://github.com/cilium/cilium/tree/v1.10.20/install/kubernetes/cilium)_) -* [v1.10.19](https://github.com/cilium/cilium/releases/tag/v1.10.19) (_[source](https://github.com/cilium/cilium/tree/v1.10.19/install/kubernetes/cilium)_) * [v1.10.19](https://github.com/cilium/cilium/releases/tag/v1.10.19) (_[source](https://github.com/cilium/cilium/tree/v1.10.19/install/kubernetes/cilium)_) * [v1.10.18](https://github.com/cilium/cilium/releases/tag/v1.10.18) (_[source](https://github.com/cilium/cilium/tree/v1.10.18/install/kubernetes/cilium)_) -* [v1.10.18](https://github.com/cilium/cilium/releases/tag/v1.10.18) (_[source](https://github.com/cilium/cilium/tree/v1.10.18/install/kubernetes/cilium)_) -* [v1.10.17](https://github.com/cilium/cilium/releases/tag/v1.10.17) (_[source](https://github.com/cilium/cilium/tree/v1.10.17/install/kubernetes/cilium)_) * [v1.10.17](https://github.com/cilium/cilium/releases/tag/v1.10.17) (_[source](https://github.com/cilium/cilium/tree/v1.10.17/install/kubernetes/cilium)_) * [v1.10.16](https://github.com/cilium/cilium/releases/tag/v1.10.16) (_[source](https://github.com/cilium/cilium/tree/v1.10.16/install/kubernetes/cilium)_) -* [v1.10.16](https://github.com/cilium/cilium/releases/tag/v1.10.16) (_[source](https://github.com/cilium/cilium/tree/v1.10.16/install/kubernetes/cilium)_) -* [v1.10.15](https://github.com/cilium/cilium/releases/tag/v1.10.15) (_[source](https://github.com/cilium/cilium/tree/v1.10.15/install/kubernetes/cilium)_) * [v1.10.15](https://github.com/cilium/cilium/releases/tag/v1.10.15) (_[source](https://github.com/cilium/cilium/tree/v1.10.15/install/kubernetes/cilium)_) * [v1.10.14](https://github.com/cilium/cilium/releases/tag/v1.10.14) (_[source](https://github.com/cilium/cilium/tree/v1.10.14/install/kubernetes/cilium)_) -* [v1.10.14](https://github.com/cilium/cilium/releases/tag/v1.10.14) (_[source](https://github.com/cilium/cilium/tree/v1.10.14/install/kubernetes/cilium)_) -* [v1.10.13](https://github.com/cilium/cilium/releases/tag/v1.10.13) (_[source](https://github.com/cilium/cilium/tree/v1.10.13/install/kubernetes/cilium)_) * [v1.10.13](https://github.com/cilium/cilium/releases/tag/v1.10.13) (_[source](https://github.com/cilium/cilium/tree/v1.10.13/install/kubernetes/cilium)_) * [v1.10.12](https://github.com/cilium/cilium/releases/tag/v1.10.12) (_[source](https://github.com/cilium/cilium/tree/v1.10.12/install/kubernetes/cilium)_) -* [v1.10.12](https://github.com/cilium/cilium/releases/tag/v1.10.12) (_[source](https://github.com/cilium/cilium/tree/v1.10.12/install/kubernetes/cilium)_) -* [v1.10.11](https://github.com/cilium/cilium/releases/tag/v1.10.11) (_[source](https://github.com/cilium/cilium/tree/v1.10.11/install/kubernetes/cilium)_) * [v1.10.11](https://github.com/cilium/cilium/releases/tag/v1.10.11) (_[source](https://github.com/cilium/cilium/tree/v1.10.11/install/kubernetes/cilium)_) * [v1.10.10](https://github.com/cilium/cilium/releases/tag/v1.10.10) (_[source](https://github.com/cilium/cilium/tree/v1.10.10/install/kubernetes/cilium)_) -* [v1.10.10](https://github.com/cilium/cilium/releases/tag/v1.10.10) (_[source](https://github.com/cilium/cilium/tree/v1.10.10/install/kubernetes/cilium)_) -* [v1.10.9](https://github.com/cilium/cilium/releases/tag/v1.10.9) (_[source](https://github.com/cilium/cilium/tree/v1.10.9/install/kubernetes/cilium)_) * [v1.10.9](https://github.com/cilium/cilium/releases/tag/v1.10.9) (_[source](https://github.com/cilium/cilium/tree/v1.10.9/install/kubernetes/cilium)_) * [v1.10.8](https://github.com/cilium/cilium/releases/tag/v1.10.8) (_[source](https://github.com/cilium/cilium/tree/v1.10.8/install/kubernetes/cilium)_) -* [v1.10.8](https://github.com/cilium/cilium/releases/tag/v1.10.8) (_[source](https://github.com/cilium/cilium/tree/v1.10.8/install/kubernetes/cilium)_) -* [v1.10.7](https://github.com/cilium/cilium/releases/tag/v1.10.7) (_[source](https://github.com/cilium/cilium/tree/v1.10.7/install/kubernetes/cilium)_) * [v1.10.7](https://github.com/cilium/cilium/releases/tag/v1.10.7) (_[source](https://github.com/cilium/cilium/tree/v1.10.7/install/kubernetes/cilium)_) * [v1.10.6](https://github.com/cilium/cilium/releases/tag/v1.10.6) (_[source](https://github.com/cilium/cilium/tree/v1.10.6/install/kubernetes/cilium)_) -* [v1.10.6](https://github.com/cilium/cilium/releases/tag/v1.10.6) (_[source](https://github.com/cilium/cilium/tree/v1.10.6/install/kubernetes/cilium)_) -* [v1.10.5](https://github.com/cilium/cilium/releases/tag/v1.10.5) (_[source](https://github.com/cilium/cilium/tree/v1.10.5/install/kubernetes/cilium)_) * [v1.10.5](https://github.com/cilium/cilium/releases/tag/v1.10.5) (_[source](https://github.com/cilium/cilium/tree/v1.10.5/install/kubernetes/cilium)_) * [v1.10.4](https://github.com/cilium/cilium/releases/tag/v1.10.4) (_[source](https://github.com/cilium/cilium/tree/v1.10.4/install/kubernetes/cilium)_) -* [v1.10.4](https://github.com/cilium/cilium/releases/tag/v1.10.4) (_[source](https://github.com/cilium/cilium/tree/v1.10.4/install/kubernetes/cilium)_) -* [v1.10.3](https://github.com/cilium/cilium/releases/tag/v1.10.3) (_[source](https://github.com/cilium/cilium/tree/v1.10.3/install/kubernetes/cilium)_) * [v1.10.3](https://github.com/cilium/cilium/releases/tag/v1.10.3) (_[source](https://github.com/cilium/cilium/tree/v1.10.3/install/kubernetes/cilium)_) * [v1.10.2](https://github.com/cilium/cilium/releases/tag/v1.10.2) (_[source](https://github.com/cilium/cilium/tree/v1.10.2/install/kubernetes/cilium)_) -* [v1.10.2](https://github.com/cilium/cilium/releases/tag/v1.10.2) (_[source](https://github.com/cilium/cilium/tree/v1.10.2/install/kubernetes/cilium)_) -* [v1.10.1](https://github.com/cilium/cilium/releases/tag/v1.10.1) (_[source](https://github.com/cilium/cilium/tree/v1.10.1/install/kubernetes/cilium)_) * [v1.10.1](https://github.com/cilium/cilium/releases/tag/v1.10.1) (_[source](https://github.com/cilium/cilium/tree/v1.10.1/install/kubernetes/cilium)_) * [v1.10.0](https://github.com/cilium/cilium/releases/tag/v1.10.0) (_[source](https://github.com/cilium/cilium/tree/v1.10.0/install/kubernetes/cilium)_) -* [v1.10.0](https://github.com/cilium/cilium/releases/tag/v1.10.0) (_[source](https://github.com/cilium/cilium/tree/v1.10.0/install/kubernetes/cilium)_) * [v1.10.0-rc2](https://github.com/cilium/cilium/releases/tag/v1.10.0-rc2) (_[source](https://github.com/cilium/cilium/tree/v1.10.0-rc2/install/kubernetes/cilium)_) -* [v1.10.0-rc2](https://github.com/cilium/cilium/releases/tag/v1.10.0-rc2) (_[source](https://github.com/cilium/cilium/tree/v1.10.0-rc2/install/kubernetes/cilium)_) -* [v1.10.0-rc1](https://github.com/cilium/cilium/releases/tag/v1.10.0-rc1) (_[source](https://github.com/cilium/cilium/tree/v1.10.0-rc1/install/kubernetes/cilium)_) * [v1.10.0-rc1](https://github.com/cilium/cilium/releases/tag/v1.10.0-rc1) (_[source](https://github.com/cilium/cilium/tree/v1.10.0-rc1/install/kubernetes/cilium)_) * [v1.10.0-rc0](https://github.com/cilium/cilium/releases/tag/v1.10.0-rc0) (_[source](https://github.com/cilium/cilium/tree/v1.10.0-rc0/install/kubernetes/cilium)_) -* [v1.10.0-rc0](https://github.com/cilium/cilium/releases/tag/v1.10.0-rc0) (_[source](https://github.com/cilium/cilium/tree/v1.10.0-rc0/install/kubernetes/cilium)_) -* [v1.9.18](https://github.com/cilium/cilium/releases/tag/v1.9.18) (_[source](https://github.com/cilium/cilium/tree/v1.9.18/install/kubernetes/cilium)_) * [v1.9.18](https://github.com/cilium/cilium/releases/tag/v1.9.18) (_[source](https://github.com/cilium/cilium/tree/v1.9.18/install/kubernetes/cilium)_) * [v1.9.17](https://github.com/cilium/cilium/releases/tag/v1.9.17) (_[source](https://github.com/cilium/cilium/tree/v1.9.17/install/kubernetes/cilium)_) -* [v1.9.17](https://github.com/cilium/cilium/releases/tag/v1.9.17) (_[source](https://github.com/cilium/cilium/tree/v1.9.17/install/kubernetes/cilium)_) -* [v1.9.16](https://github.com/cilium/cilium/releases/tag/v1.9.16) (_[source](https://github.com/cilium/cilium/tree/v1.9.16/install/kubernetes/cilium)_) * [v1.9.16](https://github.com/cilium/cilium/releases/tag/v1.9.16) (_[source](https://github.com/cilium/cilium/tree/v1.9.16/install/kubernetes/cilium)_) * [v1.9.15](https://github.com/cilium/cilium/releases/tag/v1.9.15) (_[source](https://github.com/cilium/cilium/tree/v1.9.15/install/kubernetes/cilium)_) -* [v1.9.15](https://github.com/cilium/cilium/releases/tag/v1.9.15) (_[source](https://github.com/cilium/cilium/tree/v1.9.15/install/kubernetes/cilium)_) -* [v1.9.14](https://github.com/cilium/cilium/releases/tag/v1.9.14) (_[source](https://github.com/cilium/cilium/tree/v1.9.14/install/kubernetes/cilium)_) * [v1.9.14](https://github.com/cilium/cilium/releases/tag/v1.9.14) (_[source](https://github.com/cilium/cilium/tree/v1.9.14/install/kubernetes/cilium)_) * [v1.9.13](https://github.com/cilium/cilium/releases/tag/v1.9.13) (_[source](https://github.com/cilium/cilium/tree/v1.9.13/install/kubernetes/cilium)_) -* [v1.9.13](https://github.com/cilium/cilium/releases/tag/v1.9.13) (_[source](https://github.com/cilium/cilium/tree/v1.9.13/install/kubernetes/cilium)_) -* [v1.9.12](https://github.com/cilium/cilium/releases/tag/v1.9.12) (_[source](https://github.com/cilium/cilium/tree/v1.9.12/install/kubernetes/cilium)_) * [v1.9.12](https://github.com/cilium/cilium/releases/tag/v1.9.12) (_[source](https://github.com/cilium/cilium/tree/v1.9.12/install/kubernetes/cilium)_) * [v1.9.11](https://github.com/cilium/cilium/releases/tag/v1.9.11) (_[source](https://github.com/cilium/cilium/tree/v1.9.11/install/kubernetes/cilium)_) -* [v1.9.11](https://github.com/cilium/cilium/releases/tag/v1.9.11) (_[source](https://github.com/cilium/cilium/tree/v1.9.11/install/kubernetes/cilium)_) -* [v1.9.10](https://github.com/cilium/cilium/releases/tag/v1.9.10) (_[source](https://github.com/cilium/cilium/tree/v1.9.10/install/kubernetes/cilium)_) * [v1.9.10](https://github.com/cilium/cilium/releases/tag/v1.9.10) (_[source](https://github.com/cilium/cilium/tree/v1.9.10/install/kubernetes/cilium)_) * [v1.9.9](https://github.com/cilium/cilium/releases/tag/v1.9.9) (_[source](https://github.com/cilium/cilium/tree/v1.9.9/install/kubernetes/cilium)_) -* [v1.9.9](https://github.com/cilium/cilium/releases/tag/v1.9.9) (_[source](https://github.com/cilium/cilium/tree/v1.9.9/install/kubernetes/cilium)_) -* [v1.9.8](https://github.com/cilium/cilium/releases/tag/v1.9.8) (_[source](https://github.com/cilium/cilium/tree/v1.9.8/install/kubernetes/cilium)_) * [v1.9.8](https://github.com/cilium/cilium/releases/tag/v1.9.8) (_[source](https://github.com/cilium/cilium/tree/v1.9.8/install/kubernetes/cilium)_) * [v1.9.7](https://github.com/cilium/cilium/releases/tag/v1.9.7) (_[source](https://github.com/cilium/cilium/tree/v1.9.7/install/kubernetes/cilium)_) -* [v1.9.7](https://github.com/cilium/cilium/releases/tag/v1.9.7) (_[source](https://github.com/cilium/cilium/tree/v1.9.7/install/kubernetes/cilium)_) -* [v1.9.6](https://github.com/cilium/cilium/releases/tag/v1.9.6) (_[source](https://github.com/cilium/cilium/tree/v1.9.6/install/kubernetes/cilium)_) * [v1.9.6](https://github.com/cilium/cilium/releases/tag/v1.9.6) (_[source](https://github.com/cilium/cilium/tree/v1.9.6/install/kubernetes/cilium)_) * [v1.9.5](https://github.com/cilium/cilium/releases/tag/v1.9.5) (_[source](https://github.com/cilium/cilium/tree/v1.9.5/install/kubernetes/cilium)_) -* [v1.9.5](https://github.com/cilium/cilium/releases/tag/v1.9.5) (_[source](https://github.com/cilium/cilium/tree/v1.9.5/install/kubernetes/cilium)_) -* [v1.9.4](https://github.com/cilium/cilium/releases/tag/v1.9.4) (_[source](https://github.com/cilium/cilium/tree/v1.9.4/install/kubernetes/cilium)_) * [v1.9.4](https://github.com/cilium/cilium/releases/tag/v1.9.4) (_[source](https://github.com/cilium/cilium/tree/v1.9.4/install/kubernetes/cilium)_) * [v1.9.3](https://github.com/cilium/cilium/releases/tag/v1.9.3) (_[source](https://github.com/cilium/cilium/tree/v1.9.3/install/kubernetes/cilium)_) -* [v1.9.3](https://github.com/cilium/cilium/releases/tag/v1.9.3) (_[source](https://github.com/cilium/cilium/tree/v1.9.3/install/kubernetes/cilium)_) -* [v1.9.2](https://github.com/cilium/cilium/releases/tag/v1.9.2) (_[source](https://github.com/cilium/cilium/tree/v1.9.2/install/kubernetes/cilium)_) * [v1.9.2](https://github.com/cilium/cilium/releases/tag/v1.9.2) (_[source](https://github.com/cilium/cilium/tree/v1.9.2/install/kubernetes/cilium)_) * [v1.9.1](https://github.com/cilium/cilium/releases/tag/v1.9.1) (_[source](https://github.com/cilium/cilium/tree/v1.9.1/install/kubernetes/cilium)_) -* [v1.9.1](https://github.com/cilium/cilium/releases/tag/v1.9.1) (_[source](https://github.com/cilium/cilium/tree/v1.9.1/install/kubernetes/cilium)_) -* [v1.9.0](https://github.com/cilium/cilium/releases/tag/v1.9.0) (_[source](https://github.com/cilium/cilium/tree/v1.9.0/install/kubernetes/cilium)_) * [v1.9.0](https://github.com/cilium/cilium/releases/tag/v1.9.0) (_[source](https://github.com/cilium/cilium/tree/v1.9.0/install/kubernetes/cilium)_) * [v1.9.0-rc3](https://github.com/cilium/cilium/releases/tag/v1.9.0-rc3) (_[source](https://github.com/cilium/cilium/tree/v1.9.0-rc3/install/kubernetes/cilium)_) -* [v1.9.0-rc3](https://github.com/cilium/cilium/releases/tag/v1.9.0-rc3) (_[source](https://github.com/cilium/cilium/tree/v1.9.0-rc3/install/kubernetes/cilium)_) -* [v1.9.0-rc2](https://github.com/cilium/cilium/releases/tag/v1.9.0-rc2) (_[source](https://github.com/cilium/cilium/tree/v1.9.0-rc2/install/kubernetes/cilium)_) * [v1.9.0-rc2](https://github.com/cilium/cilium/releases/tag/v1.9.0-rc2) (_[source](https://github.com/cilium/cilium/tree/v1.9.0-rc2/install/kubernetes/cilium)_) * [v1.9.0-rc1](https://github.com/cilium/cilium/releases/tag/v1.9.0-rc1) (_[source](https://github.com/cilium/cilium/tree/v1.9.0-rc1/install/kubernetes/cilium)_) -* [v1.9.0-rc1](https://github.com/cilium/cilium/releases/tag/v1.9.0-rc1) (_[source](https://github.com/cilium/cilium/tree/v1.9.0-rc1/install/kubernetes/cilium)_) -* [v1.9.0-rc0](https://github.com/cilium/cilium/releases/tag/v1.9.0-rc0) (_[source](https://github.com/cilium/cilium/tree/v1.9.0-rc0/install/kubernetes/cilium)_) * [v1.9.0-rc0](https://github.com/cilium/cilium/releases/tag/v1.9.0-rc0) (_[source](https://github.com/cilium/cilium/tree/v1.9.0-rc0/install/kubernetes/cilium)_) * [v1.8.13](https://github.com/cilium/cilium/releases/tag/v1.8.13) (_[source](https://github.com/cilium/cilium/tree/v1.8.13/install/kubernetes/cilium)_) -* [v1.8.13](https://github.com/cilium/cilium/releases/tag/v1.8.13) (_[source](https://github.com/cilium/cilium/tree/v1.8.13/install/kubernetes/cilium)_) -* [v1.8.12](https://github.com/cilium/cilium/releases/tag/v1.8.12) (_[source](https://github.com/cilium/cilium/tree/v1.8.12/install/kubernetes/cilium)_) * [v1.8.12](https://github.com/cilium/cilium/releases/tag/v1.8.12) (_[source](https://github.com/cilium/cilium/tree/v1.8.12/install/kubernetes/cilium)_) * [v1.8.11](https://github.com/cilium/cilium/releases/tag/v1.8.11) (_[source](https://github.com/cilium/cilium/tree/v1.8.11/install/kubernetes/cilium)_) -* [v1.8.11](https://github.com/cilium/cilium/releases/tag/v1.8.11) (_[source](https://github.com/cilium/cilium/tree/v1.8.11/install/kubernetes/cilium)_) -* [v1.8.10](https://github.com/cilium/cilium/releases/tag/v1.8.10) (_[source](https://github.com/cilium/cilium/tree/v1.8.10/install/kubernetes/cilium)_) * [v1.8.10](https://github.com/cilium/cilium/releases/tag/v1.8.10) (_[source](https://github.com/cilium/cilium/tree/v1.8.10/install/kubernetes/cilium)_) * [v1.8.9](https://github.com/cilium/cilium/releases/tag/v1.8.9) (_[source](https://github.com/cilium/cilium/tree/v1.8.9/install/kubernetes/cilium)_) -* [v1.8.9](https://github.com/cilium/cilium/releases/tag/v1.8.9) (_[source](https://github.com/cilium/cilium/tree/v1.8.9/install/kubernetes/cilium)_) * [v1.8.8](https://github.com/cilium/cilium/releases/tag/v1.8.8) (_[source](https://github.com/cilium/cilium/tree/v1.8.8/install/kubernetes/cilium)_) -* [v1.8.8](https://github.com/cilium/cilium/releases/tag/v1.8.8) (_[source](https://github.com/cilium/cilium/tree/v1.8.8/install/kubernetes/cilium)_) -* [v1.8.7](https://github.com/cilium/cilium/releases/tag/v1.8.7) (_[source](https://github.com/cilium/cilium/tree/v1.8.7/install/kubernetes/cilium)_) * [v1.8.7](https://github.com/cilium/cilium/releases/tag/v1.8.7) (_[source](https://github.com/cilium/cilium/tree/v1.8.7/install/kubernetes/cilium)_) * [v1.8.6](https://github.com/cilium/cilium/releases/tag/v1.8.6) (_[source](https://github.com/cilium/cilium/tree/v1.8.6/install/kubernetes/cilium)_) -* [v1.8.6](https://github.com/cilium/cilium/releases/tag/v1.8.6) (_[source](https://github.com/cilium/cilium/tree/v1.8.6/install/kubernetes/cilium)_) -* [v1.8.5](https://github.com/cilium/cilium/releases/tag/v1.8.5) (_[source](https://github.com/cilium/cilium/tree/v1.8.5/install/kubernetes/cilium)_) * [v1.8.5](https://github.com/cilium/cilium/releases/tag/v1.8.5) (_[source](https://github.com/cilium/cilium/tree/v1.8.5/install/kubernetes/cilium)_) * [v1.8.4](https://github.com/cilium/cilium/releases/tag/v1.8.4) (_[source](https://github.com/cilium/cilium/tree/v1.8.4/install/kubernetes/cilium)_) -* [v1.8.4](https://github.com/cilium/cilium/releases/tag/v1.8.4) (_[source](https://github.com/cilium/cilium/tree/v1.8.4/install/kubernetes/cilium)_) -* [v1.8.3](https://github.com/cilium/cilium/releases/tag/v1.8.3) (_[source](https://github.com/cilium/cilium/tree/v1.8.3/install/kubernetes/cilium)_) * [v1.8.3](https://github.com/cilium/cilium/releases/tag/v1.8.3) (_[source](https://github.com/cilium/cilium/tree/v1.8.3/install/kubernetes/cilium)_) * [v1.8.2](https://github.com/cilium/cilium/releases/tag/v1.8.2) (_[source](https://github.com/cilium/cilium/tree/v1.8.2/install/kubernetes/cilium)_) -* [v1.8.2](https://github.com/cilium/cilium/releases/tag/v1.8.2) (_[source](https://github.com/cilium/cilium/tree/v1.8.2/install/kubernetes/cilium)_) -* [v1.8.1](https://github.com/cilium/cilium/releases/tag/v1.8.1) (_[source](https://github.com/cilium/cilium/tree/v1.8.1/install/kubernetes/cilium)_) * [v1.8.1](https://github.com/cilium/cilium/releases/tag/v1.8.1) (_[source](https://github.com/cilium/cilium/tree/v1.8.1/install/kubernetes/cilium)_) * [v1.8.0](https://github.com/cilium/cilium/releases/tag/v1.8.0) (_[source](https://github.com/cilium/cilium/tree/v1.8.0/install/kubernetes/cilium)_) -* [v1.8.0](https://github.com/cilium/cilium/releases/tag/v1.8.0) (_[source](https://github.com/cilium/cilium/tree/v1.8.0/install/kubernetes/cilium)_) -* [v1.8.0-rc4](https://github.com/cilium/cilium/releases/tag/v1.8.0-rc4) (_[source](https://github.com/cilium/cilium/tree/v1.8.0-rc4/install/kubernetes/cilium)_) * [v1.8.0-rc4](https://github.com/cilium/cilium/releases/tag/v1.8.0-rc4) (_[source](https://github.com/cilium/cilium/tree/v1.8.0-rc4/install/kubernetes/cilium)_) * [v1.8.0-rc3](https://github.com/cilium/cilium/releases/tag/v1.8.0-rc3) (_[source](https://github.com/cilium/cilium/tree/v1.8.0-rc3/install/kubernetes/cilium)_) -* [v1.8.0-rc3](https://github.com/cilium/cilium/releases/tag/v1.8.0-rc3) (_[source](https://github.com/cilium/cilium/tree/v1.8.0-rc3/install/kubernetes/cilium)_) -* [v1.8.0-rc2](https://github.com/cilium/cilium/releases/tag/v1.8.0-rc2) (_[source](https://github.com/cilium/cilium/tree/v1.8.0-rc2/install/kubernetes/cilium)_) * [v1.8.0-rc2](https://github.com/cilium/cilium/releases/tag/v1.8.0-rc2) (_[source](https://github.com/cilium/cilium/tree/v1.8.0-rc2/install/kubernetes/cilium)_) * [v1.8.0-rc1](https://github.com/cilium/cilium/releases/tag/v1.8.0-rc1) (_[source](https://github.com/cilium/cilium/tree/v1.8.0-rc1/install/kubernetes/cilium)_) -* [v1.8.0-rc1](https://github.com/cilium/cilium/releases/tag/v1.8.0-rc1) (_[source](https://github.com/cilium/cilium/tree/v1.8.0-rc1/install/kubernetes/cilium)_) -* [v1.7.16](https://github.com/cilium/cilium/releases/tag/v1.7.16) (_[source](https://github.com/cilium/cilium/tree/v1.7.16/install/kubernetes/cilium)_) * [v1.7.16](https://github.com/cilium/cilium/releases/tag/v1.7.16) (_[source](https://github.com/cilium/cilium/tree/v1.7.16/install/kubernetes/cilium)_) * [v1.7.15](https://github.com/cilium/cilium/releases/tag/v1.7.15) (_[source](https://github.com/cilium/cilium/tree/v1.7.15/install/kubernetes/cilium)_) -* [v1.7.15](https://github.com/cilium/cilium/releases/tag/v1.7.15) (_[source](https://github.com/cilium/cilium/tree/v1.7.15/install/kubernetes/cilium)_) -* [v1.7.14](https://github.com/cilium/cilium/releases/tag/v1.7.14) (_[source](https://github.com/cilium/cilium/tree/v1.7.14/install/kubernetes/cilium)_) * [v1.7.14](https://github.com/cilium/cilium/releases/tag/v1.7.14) (_[source](https://github.com/cilium/cilium/tree/v1.7.14/install/kubernetes/cilium)_) * [v1.7.13](https://github.com/cilium/cilium/releases/tag/v1.7.13) (_[source](https://github.com/cilium/cilium/tree/v1.7.13/install/kubernetes/cilium)_) -* [v1.7.13](https://github.com/cilium/cilium/releases/tag/v1.7.13) (_[source](https://github.com/cilium/cilium/tree/v1.7.13/install/kubernetes/cilium)_) -* [v1.7.12](https://github.com/cilium/cilium/releases/tag/v1.7.12) (_[source](https://github.com/cilium/cilium/tree/v1.7.12/install/kubernetes/cilium)_) * [v1.7.12](https://github.com/cilium/cilium/releases/tag/v1.7.12) (_[source](https://github.com/cilium/cilium/tree/v1.7.12/install/kubernetes/cilium)_) * [v1.7.11](https://github.com/cilium/cilium/releases/tag/v1.7.11) (_[source](https://github.com/cilium/cilium/tree/v1.7.11/install/kubernetes/cilium)_) -* [v1.7.11](https://github.com/cilium/cilium/releases/tag/v1.7.11) (_[source](https://github.com/cilium/cilium/tree/v1.7.11/install/kubernetes/cilium)_) -* [v1.7.10](https://github.com/cilium/cilium/releases/tag/v1.7.10) (_[source](https://github.com/cilium/cilium/tree/v1.7.10/install/kubernetes/cilium)_) * [v1.7.10](https://github.com/cilium/cilium/releases/tag/v1.7.10) (_[source](https://github.com/cilium/cilium/tree/v1.7.10/install/kubernetes/cilium)_) * [v1.7.9](https://github.com/cilium/cilium/releases/tag/v1.7.9) (_[source](https://github.com/cilium/cilium/tree/v1.7.9/install/kubernetes/cilium)_) -* [v1.7.9](https://github.com/cilium/cilium/releases/tag/v1.7.9) (_[source](https://github.com/cilium/cilium/tree/v1.7.9/install/kubernetes/cilium)_) -* [v1.7.8](https://github.com/cilium/cilium/releases/tag/v1.7.8) (_[source](https://github.com/cilium/cilium/tree/v1.7.8/install/kubernetes/cilium)_) * [v1.7.8](https://github.com/cilium/cilium/releases/tag/v1.7.8) (_[source](https://github.com/cilium/cilium/tree/v1.7.8/install/kubernetes/cilium)_) * [v1.7.7](https://github.com/cilium/cilium/releases/tag/v1.7.7) (_[source](https://github.com/cilium/cilium/tree/v1.7.7/install/kubernetes/cilium)_) -* [v1.7.7](https://github.com/cilium/cilium/releases/tag/v1.7.7) (_[source](https://github.com/cilium/cilium/tree/v1.7.7/install/kubernetes/cilium)_) -* [v1.7.6](https://github.com/cilium/cilium/releases/tag/v1.7.6) (_[source](https://github.com/cilium/cilium/tree/v1.7.6/install/kubernetes/cilium)_) * [v1.7.6](https://github.com/cilium/cilium/releases/tag/v1.7.6) (_[source](https://github.com/cilium/cilium/tree/v1.7.6/install/kubernetes/cilium)_) * [v1.7.5](https://github.com/cilium/cilium/releases/tag/v1.7.5) (_[source](https://github.com/cilium/cilium/tree/v1.7.5/install/kubernetes/cilium)_) -* [v1.7.5](https://github.com/cilium/cilium/releases/tag/v1.7.5) (_[source](https://github.com/cilium/cilium/tree/v1.7.5/install/kubernetes/cilium)_) -* [v1.7.4](https://github.com/cilium/cilium/releases/tag/v1.7.4) (_[source](https://github.com/cilium/cilium/tree/v1.7.4/install/kubernetes/cilium)_) * [v1.7.4](https://github.com/cilium/cilium/releases/tag/v1.7.4) (_[source](https://github.com/cilium/cilium/tree/v1.7.4/install/kubernetes/cilium)_) * [v1.7.3](https://github.com/cilium/cilium/releases/tag/v1.7.3) (_[source](https://github.com/cilium/cilium/tree/v1.7.3/install/kubernetes/cilium)_) -* [v1.7.3](https://github.com/cilium/cilium/releases/tag/v1.7.3) (_[source](https://github.com/cilium/cilium/tree/v1.7.3/install/kubernetes/cilium)_) -* [v1.7.2](https://github.com/cilium/cilium/releases/tag/v1.7.2) (_[source](https://github.com/cilium/cilium/tree/v1.7.2/install/kubernetes/cilium)_) * [v1.7.2](https://github.com/cilium/cilium/releases/tag/v1.7.2) (_[source](https://github.com/cilium/cilium/tree/v1.7.2/install/kubernetes/cilium)_) * [v1.7.1](https://github.com/cilium/cilium/releases/tag/v1.7.1) (_[source](https://github.com/cilium/cilium/tree/v1.7.1/install/kubernetes/cilium)_) -* [v1.7.1](https://github.com/cilium/cilium/releases/tag/v1.7.1) (_[source](https://github.com/cilium/cilium/tree/v1.7.1/install/kubernetes/cilium)_) -* [v1.7.0](https://github.com/cilium/cilium/releases/tag/v1.7.0) (_[source](https://github.com/cilium/cilium/tree/v1.7.0/install/kubernetes/cilium)_) * [v1.7.0](https://github.com/cilium/cilium/releases/tag/v1.7.0) (_[source](https://github.com/cilium/cilium/tree/v1.7.0/install/kubernetes/cilium)_) * [v1.7.0-rc4](https://github.com/cilium/cilium/releases/tag/v1.7.0-rc4) (_[source](https://github.com/cilium/cilium/tree/v1.7.0-rc4/install/kubernetes/cilium)_) -* [v1.7.0-rc4](https://github.com/cilium/cilium/releases/tag/v1.7.0-rc4) (_[source](https://github.com/cilium/cilium/tree/v1.7.0-rc4/install/kubernetes/cilium)_) * [v1.7.0-rc3](https://github.com/cilium/cilium/releases/tag/v1.7.0-rc3) (_[source](https://github.com/cilium/cilium/tree/v1.7.0-rc3/install/kubernetes/cilium)_) -* [v1.7.0-rc3](https://github.com/cilium/cilium/releases/tag/v1.7.0-rc3) (_[source](https://github.com/cilium/cilium/tree/v1.7.0-rc3/install/kubernetes/cilium)_) -* [v1.6.12](https://github.com/cilium/cilium/releases/tag/v1.6.12) (_[source](https://github.com/cilium/cilium/tree/v1.6.12/install/kubernetes/cilium)_) * [v1.6.12](https://github.com/cilium/cilium/releases/tag/v1.6.12) (_[source](https://github.com/cilium/cilium/tree/v1.6.12/install/kubernetes/cilium)_) * [v1.6.11](https://github.com/cilium/cilium/releases/tag/v1.6.11) (_[source](https://github.com/cilium/cilium/tree/v1.6.11/install/kubernetes/cilium)_) -* [v1.6.11](https://github.com/cilium/cilium/releases/tag/v1.6.11) (_[source](https://github.com/cilium/cilium/tree/v1.6.11/install/kubernetes/cilium)_) -* [v1.6.10](https://github.com/cilium/cilium/releases/tag/v1.6.10) (_[source](https://github.com/cilium/cilium/tree/v1.6.10/install/kubernetes/cilium)_) * [v1.6.10](https://github.com/cilium/cilium/releases/tag/v1.6.10) (_[source](https://github.com/cilium/cilium/tree/v1.6.10/install/kubernetes/cilium)_) * [v1.6.9](https://github.com/cilium/cilium/releases/tag/v1.6.9) (_[source](https://github.com/cilium/cilium/tree/v1.6.9/install/kubernetes/cilium)_) -* [v1.6.9](https://github.com/cilium/cilium/releases/tag/v1.6.9) (_[source](https://github.com/cilium/cilium/tree/v1.6.9/install/kubernetes/cilium)_) -* [v1.6.8](https://github.com/cilium/cilium/releases/tag/v1.6.8) (_[source](https://github.com/cilium/cilium/tree/v1.6.8/install/kubernetes/cilium)_) * [v1.6.8](https://github.com/cilium/cilium/releases/tag/v1.6.8) (_[source](https://github.com/cilium/cilium/tree/v1.6.8/install/kubernetes/cilium)_) * [v1.6.7](https://github.com/cilium/cilium/releases/tag/v1.6.7) (_[source](https://github.com/cilium/cilium/tree/v1.6.7/install/kubernetes/cilium)_) -* [v1.6.7](https://github.com/cilium/cilium/releases/tag/v1.6.7) (_[source](https://github.com/cilium/cilium/tree/v1.6.7/install/kubernetes/cilium)_) -* [v1.6.6](https://github.com/cilium/cilium/releases/tag/v1.6.6) (_[source](https://github.com/cilium/cilium/tree/v1.6.6/install/kubernetes/cilium)_) * [v1.6.6](https://github.com/cilium/cilium/releases/tag/v1.6.6) (_[source](https://github.com/cilium/cilium/tree/v1.6.6/install/kubernetes/cilium)_) * [v1.6.5](https://github.com/cilium/cilium/releases/tag/v1.6.5) (_[source](https://github.com/cilium/cilium/tree/v1.6.5/install/kubernetes/cilium)_) -* [v1.6.5](https://github.com/cilium/cilium/releases/tag/v1.6.5) (_[source](https://github.com/cilium/cilium/tree/v1.6.5/install/kubernetes/cilium)_) This repository holds helm templates for the following Tetragon releases: -* [v1.3.0](https://github.com/cilium/tetragon/releases/tag/v1.3.0) (_[source](https://github.com/cilium/tetragon/tree/v1.3.0/install/kubernetes/tetragon)_) * [v1.3.0](https://github.com/cilium/tetragon/releases/tag/v1.3.0) (_[source](https://github.com/cilium/tetragon/tree/v1.3.0/install/kubernetes/tetragon)_) * [v1.2.1](https://github.com/cilium/tetragon/releases/tag/v1.2.1) (_[source](https://github.com/cilium/tetragon/tree/v1.2.1/install/kubernetes/tetragon)_) -* [v1.2.1](https://github.com/cilium/tetragon/releases/tag/v1.2.1) (_[source](https://github.com/cilium/tetragon/tree/v1.2.1/install/kubernetes/tetragon)_) -* [v1.2.0](https://github.com/cilium/tetragon/releases/tag/v1.2.0) (_[source](https://github.com/cilium/tetragon/tree/v1.2.0/install/kubernetes/tetragon)_) * [v1.2.0](https://github.com/cilium/tetragon/releases/tag/v1.2.0) (_[source](https://github.com/cilium/tetragon/tree/v1.2.0/install/kubernetes/tetragon)_) * [v1.1.2](https://github.com/cilium/tetragon/releases/tag/v1.1.2) (_[source](https://github.com/cilium/tetragon/tree/v1.1.2/install/kubernetes/tetragon)_) -* [v1.1.2](https://github.com/cilium/tetragon/releases/tag/v1.1.2) (_[source](https://github.com/cilium/tetragon/tree/v1.1.2/install/kubernetes/tetragon)_) -* [v1.1.0](https://github.com/cilium/tetragon/releases/tag/v1.1.0) (_[source](https://github.com/cilium/tetragon/tree/v1.1.0/install/kubernetes/tetragon)_) * [v1.1.0](https://github.com/cilium/tetragon/releases/tag/v1.1.0) (_[source](https://github.com/cilium/tetragon/tree/v1.1.0/install/kubernetes/tetragon)_) * [v1.0.3](https://github.com/cilium/tetragon/releases/tag/v1.0.3) (_[source](https://github.com/cilium/tetragon/tree/v1.0.3/install/kubernetes)_) -* [v1.0.3](https://github.com/cilium/tetragon/releases/tag/v1.0.3) (_[source](https://github.com/cilium/tetragon/tree/v1.0.3/install/kubernetes)_) * [v1.0.2](https://github.com/cilium/tetragon/releases/tag/v1.0.2) (_[source](https://github.com/cilium/tetragon/tree/v1.0.2/install/kubernetes)_) -* [v1.0.2](https://github.com/cilium/tetragon/releases/tag/v1.0.2) (_[source](https://github.com/cilium/tetragon/tree/v1.0.2/install/kubernetes)_) -* [v1.0.1](https://github.com/cilium/tetragon/releases/tag/v1.0.1) (_[source](https://github.com/cilium/tetragon/tree/v1.0.1/install/kubernetes)_) * [v1.0.1](https://github.com/cilium/tetragon/releases/tag/v1.0.1) (_[source](https://github.com/cilium/tetragon/tree/v1.0.1/install/kubernetes)_) * [v1.0.0](https://github.com/cilium/tetragon/releases/tag/v1.0.0) (_[source](https://github.com/cilium/tetragon/tree/v1.0.0/install/kubernetes)_) -* [v1.0.0](https://github.com/cilium/tetragon/releases/tag/v1.0.0) (_[source](https://github.com/cilium/tetragon/tree/v1.0.0/install/kubernetes)_) -* [v1.0.0-rc.5](https://github.com/cilium/tetragon/releases/tag/v1.0.0-rc.5) (_[source](https://github.com/cilium/tetragon/tree/v1.0.0-rc.5/install/kubernetes)_) * [v1.0.0-rc.5](https://github.com/cilium/tetragon/releases/tag/v1.0.0-rc.5) (_[source](https://github.com/cilium/tetragon/tree/v1.0.0-rc.5/install/kubernetes)_) * [v1.0.0-rc.3](https://github.com/cilium/tetragon/releases/tag/v1.0.0-rc.3) (_[source](https://github.com/cilium/tetragon/tree/v1.0.0-rc.3/install/kubernetes)_) -* [v1.0.0-rc.3](https://github.com/cilium/tetragon/releases/tag/v1.0.0-rc.3) (_[source](https://github.com/cilium/tetragon/tree/v1.0.0-rc.3/install/kubernetes)_) -* [v1.0.0-rc.2](https://github.com/cilium/tetragon/releases/tag/v1.0.0-rc.2) (_[source](https://github.com/cilium/tetragon/tree/v1.0.0-rc.2/install/kubernetes)_) * [v1.0.0-rc.2](https://github.com/cilium/tetragon/releases/tag/v1.0.0-rc.2) (_[source](https://github.com/cilium/tetragon/tree/v1.0.0-rc.2/install/kubernetes)_) * [v1.0.0-rc.1](https://github.com/cilium/tetragon/releases/tag/v1.0.0-rc.1) (_[source](https://github.com/cilium/tetragon/tree/v1.0.0-rc.1/install/kubernetes)_) -* [v1.0.0-rc.1](https://github.com/cilium/tetragon/releases/tag/v1.0.0-rc.1) (_[source](https://github.com/cilium/tetragon/tree/v1.0.0-rc.1/install/kubernetes)_) -* [v0.11.0](https://github.com/cilium/tetragon/releases/tag/v0.11.0) (_[source](https://github.com/cilium/tetragon/tree/v0.11.0/install/kubernetes)_) * [v0.11.0](https://github.com/cilium/tetragon/releases/tag/v0.11.0) (_[source](https://github.com/cilium/tetragon/tree/v0.11.0/install/kubernetes)_) * [v0.10.0](https://github.com/cilium/tetragon/releases/tag/v0.10.0) (_[source](https://github.com/cilium/tetragon/tree/v0.10.0/install/kubernetes)_) -* [v0.10.0](https://github.com/cilium/tetragon/releases/tag/v0.10.0) (_[source](https://github.com/cilium/tetragon/tree/v0.10.0/install/kubernetes)_) -* [v0.9.0](https://github.com/cilium/tetragon/releases/tag/v0.9.0) (_[source](https://github.com/cilium/tetragon/tree/v0.9.0/install/kubernetes)_) * [v0.9.0](https://github.com/cilium/tetragon/releases/tag/v0.9.0) (_[source](https://github.com/cilium/tetragon/tree/v0.9.0/install/kubernetes)_) * [v0.8.4](https://github.com/cilium/tetragon/releases/tag/v0.8.4) (_[source](https://github.com/cilium/tetragon/tree/v0.8.4/install/kubernetes)_) -* [v0.8.4](https://github.com/cilium/tetragon/releases/tag/v0.8.4) (_[source](https://github.com/cilium/tetragon/tree/v0.8.4/install/kubernetes)_) -* [v0.8.3](https://github.com/cilium/tetragon/releases/tag/v0.8.3) (_[source](https://github.com/cilium/tetragon/tree/v0.8.3/install/kubernetes)_) * [v0.8.3](https://github.com/cilium/tetragon/releases/tag/v0.8.3) (_[source](https://github.com/cilium/tetragon/tree/v0.8.3/install/kubernetes)_) * [v0.8.2](https://github.com/cilium/tetragon/releases/tag/v0.8.2) (_[source](https://github.com/cilium/tetragon/tree/v0.8.2/install/kubernetes)_) -* [v0.8.2](https://github.com/cilium/tetragon/releases/tag/v0.8.2) (_[source](https://github.com/cilium/tetragon/tree/v0.8.2/install/kubernetes)_) -* [v0.8.1](https://github.com/cilium/tetragon/releases/tag/v0.8.1) (_[source](https://github.com/cilium/tetragon/tree/v0.8.1/install/kubernetes)_) * [v0.8.1](https://github.com/cilium/tetragon/releases/tag/v0.8.1) (_[source](https://github.com/cilium/tetragon/tree/v0.8.1/install/kubernetes)_) * [v0.8.0](https://github.com/cilium/tetragon/releases/tag/v0.8.0) (_[source](https://github.com/cilium/tetragon/tree/v0.8.0/install/kubernetes)_) -* [v0.8.0](https://github.com/cilium/tetragon/releases/tag/v0.8.0) (_[source](https://github.com/cilium/tetragon/tree/v0.8.0/install/kubernetes)_) diff --git a/vendor/github.com/cilium/charts/cilium-1.14.19.tgz b/vendor/github.com/cilium/charts/cilium-1.14.19.tgz new file mode 100644 index 0000000000000000000000000000000000000000..74c07f85d15c4d2886a9d322b936125b30fb765b GIT binary patch literal 166977 zcmV)2K+L}%iwG0|00000|0w_~VMtOiV@ORlOnEsqVl!4SWK%V1T2nbTPgYhoO;>Dc zVQyr3R8em|NM&qo0POvHciXso~TP*3-75v7PSO zt5>fCA|VOe6u~AyJL=i9Kl`&#RRBSX@+F-hh~dCbC%Voi2H9 zx@*2l{^8sI>-BoQ(QpX=?e%)K|MvF}2K|5N4-bdK-v0jn;qV`N{lRcF`Ulqg19;i^ zS7^iYf9U=0w(6bxFY=G4sWRM1mFjVeF`gSa=aE?!v#wNoQ6B3t`)i9a#yadyrtz4a z!i>2R=0W9mQ*acsUoE>%>#{D!Yv=RA(jK#}8K~z@$ny(SG{WV`^ zYjyjTbdhB$H!M==TrP@SrVBT7mT{tW-^VEBDQ3BmL+ST zr((h8G8Yd#Np#cbo_{eSPkHi_%I^}z<7bVkph^!^>3M_cnqsxK9v{PvT5jNUW#occ z$mS|%jzv!{RcR-f%bs;R5C5WM3KVE8n+EDaMLf9{vCKteUN8d_TQ8@2FPePNB6Cf? zWZpH_#1*L-FvJ{3(Epk6V<}=!>_M8POc}>nWR#z=g%&L0T4CmVDmMsp9AEmnF$3c1hcbTx7Y>A~o7|YsFK(z%368cG(2hq~S8vjC(RV z6Oo+D2u=<=8n#TX5_ZpXsS1tcTq!@ESe)DEMtfpBjTyIltSL0pB62i6e=r;Ay_&-> zOTTGQC$ZfK%=2cW#KO;=f;HNYkFYE3CYrS410A=$lc}9SA}VrQq~wE{@Dw6amO{i~ zoi1gxq~h~6)55@jBzz_ktjl;V7}r`ZQV}zw$`dV(<-Lpxo-mQdnUeOiKfTb;sqFK1 zLPz*{J7AUc6B{2D4kvAORsGGe5F&(GiX5jX9$)sAv%Ht7u&}LXehH|u{d+8ORb=p2<#PlR^1sUGSXh$pxe*V1{erVjK)nUld(l~k zEi!8IC1+h@O()7~ze}ro8WdXywvD=sl?Z+>bma@-fZDI5Rgp)+4Yq(&(;kCX)Cj3P zA;6xe_iB9#N5f0SS7EE-sq%8!720K$hMzCFhLzm`Cp10I1rCjd!TRCI9%uQzT_!7@ zWinmp@KP`n_+@ODMT}mSa|L}KGuNu!(}Q-m zjLn&t%M|wfM~O6!6v|3$GKF0%>@mB+iP$(aR)F5N$hHoNJpf;_(m+Z-4L{R!=19q! zJ?J<~q&D^#t_tCIV%@ptNg-IqWv)Tcx5cw8kyXjjNl~#C_wiijC~`6_5)m2IC^?=^ z&aU5E8Q=v26v;S8x#4-6`sD1Ig>5`KE}o(4u-L~WJ4ZaVJ4`O-A{S{SV#aMrD^4V+ zVX*hUREZ1*QP;cR`|U}e4)TErkb**C(radOFC%dY6cNUe&*$PUzk zH!Bs3H{BM`W-y z?c3F`va&D!TRmP1Z z#r0AonYNo_uBia1wiOepE^RtqOD!GUBeNSD#M~BPZxqkxir!qI>UO@$5@9!m!#3-8kL>?B z-qO!8d)4nAy=t{$F)J417Gt}t(_!Z+pCy99Lzbw;0!4QLkK-|$^F#|**vW{(9(yyT z?eHbyUL+bAtrMZXsSI_I8c!e?kD$?&(Aw_NK*A4UblKg#HYyiw2G`6si@D($H%kV`os}lu;K?&j)B}?msDa7CvSL4YjTy0$#9Itvq#^BZU+Np$--tH-_T{c0(17E2kg^L5t zKG;a?n}Dm6=>#|vb}xv8h;^`0fmvxcXt}+mS=_)Ncp(g4_+|>WgFX3~n3RBptN@14v3P?6DX#Qq8 zxjwhe;$oup;2L}_Q}c#>Oy#eIV3V_rwl529K>o)PWX$GC;`T5wKkm8;s39Y@c@9UK znzO#08iRv_r@GPxQY*f;E%un4S364Qn>`3@e`GvnJz6}VT@h}jokS5V08pzzE0J1d zDix`L^Do>KPTiYVnxU%w*McWMPOb}()wZOe5FN9Dkcy#iK1ijrUIBhhi6g`M57m0b)x(V*iE3U3HJ)k)xKykIuK+5U_P)^S3> zvk99heimI5#T|dRJfFU+@|-rlf_#>Xc_J6fZOf!WKg&f2OTVB6D>^ z)(Mw0V3TqopF_5gFJP9o-IdVGlT6}q{`kn06*}D2ctL|Gs+2?`k(-4m1#~$No9Ox` zx+c+G+eCLI%u>aFigK0yziL+P15tZ<4?6C0*s&z^OFQ&E41Ggi@S8ls{4%WhoX`7} zjBdz?pw`4=evxx4U5Z>PJX2}ykyvqr0zwY%NVXjcExA*I;!&ZnC<*p@HM!VhKJ`) zi!s9&W43coIyC#lUPw^$JZ3wS`IRzLbTimNkqEy+EEhuC4G8}jvmL$UgM-mHo(s`C zI696;@oY94&Z8(6`$q>yN8&(;ARx^Z?JxD(Vj1}n5*KYOIfB-$yxY4+k& zcQO@s=-u8f{OI6gP?f}~_G{U(byB)x`@KXn9>=Iz3iiiflNDb~&QE>uG5h(KO>(@p zLGgS6b_Y%MPx8exYl`$<<|+mA**(vtl|&tt^Ys2PB6ej?xmhwed|ajP>FFijc5Ho| zadeC+Z91#ebYgBeO(Up}3KUrGd#lv!1@B!$W47(h?K%@>YnMF9guh3-3mnq-2VyzZ=5hf-!Y*U0HI?h|G27`6_J=#w z$Fni}YsWrf%m{5*KlpnP{Jl?IbG9qc1Bx$ZQ^3Flnt>nzMX6*Ux15yH40*`-MO4yg z!Fkjq_FRzf=wmhM>iqW8$=T)P>JeIa6Voi`57e1vI@c#ZJ<3sPF9%kv z(QLKinXfyUo_@OcaQZ{FvP_xGkn679HMNYv4zyDDwm*vI8K|hJTxXsO;mO|o`R3E* zhqI3t=brFSf~CUJHl%-hV6(!om0Ts?5O(-_=iYs){5=7aPVCi0?7- zUU)uy4gci&VsbgT{d6_G{%~3$?6~!`-zu}T?7Xx5Sk^3ybbHb4&hF)j?MgckmhvJs z(qBb(S(M9;vR%IKcL#%RkEy&Y9n*`0ZZ8<2dAV5I0smFqqA%ZZ9F`B>PTzTICtxy& zrH*m|(m}pv9L;Xd4H`|96_t6$qdRUloWQR8#t+un$?2yLKb~J-PtMM34bi%;8TKyh zHG#c8Ila(t?Eb^^nKYnTp36k&mviv$!%tV|*PCq%yhhj^VUhC{`4_?FsoDF<*~?qH zIlp~BIeTGCAHTAtkJQp5yDiA3oe10mKi5tts0#&7;eEN~f>FdfSiOQWuNYE!WO03T zHBv27Lk+m1r{79k%%3=){#j%>R#jzximsI_6Ew{K+zAr zWZAE4H@q@sDvwc&py_P||5uvr2@~yMW8Ij=GXDenyXAmP1W!A3Olrf8XzVH!!+YtC zEmZdMQlXC~Na|q|VBh3q&(&bqONCP{rd|XHR7G$~ztX{mH4_oH*J&`Bl#fHFJnyr( z%ZijHFBs_P7VTw2^kIOFeXeqlS0n}mChIV!YnQxI1j#?Zdf2n>A9sBJ{p|ev+4;oT zNt*CbMTBZ$rcKU`Sgc$4`-XnnrHV52wF2*xkMO$1SRVey6}{qLKBk__F&o(SD(>y< zM|91q--BB%ey3+^6{WK7WOMSv4SW0N52sfXa1dUUJ~X@RN*V7ahQ3@fjmY;Z5qLwf z^}T@|yv0DUh2=tY?ac(6wcEwXZ{UMdw#8n5=Jr{aOqHMCz&R&440p|b*$R0Nk3+l7 zO;rpo?RI?&&1S+p2$6#ISLCf-=ZQb3C-hq{A?A}sYPC`+yBPSuc`X(z)Jzvfp#tbi z#o`*s*R=Ym91!g8h=O;E3>^8Skvx&V1x^n*Jzi8=e-rHXbP8MX$FpgGbpWmrR;+E|2?VA? zQ1QUwN?;uj?-2wSPgP8Yiu1Eu_WGRXi4@wfGm-J!6uD^avRkVAZTVN1*q{1XZFX3u^PFRVlU-o1!I>h<1)V*h#kSpi`}X?HR!`EC z$jE!U54?SQ4Z{{GE7-%zan~kG#EwFXvDqxIevZhOd}ovG6={rC~u+Y z!DNQ-Rsad2a&RMK+E#0o4p&_;!nm>!KA0LG+LDX7h)QdPHo1(f=#$EoJw4O7wd*I5 zt0U5gXS(nXv=PtqbrTRkx3#SGqdr2m&64Y~C#Gb1>-kfDrHcUzBaC#b8gZoSt!|Xx zHj%7A!V@j%y%e`PTp`RM!@6**}262YxdiUK(Zs3K;u;BlLA@V71tWHP!V z2RUfwj0lcd|3HThh!8h)&lAQCMG`^$5fXwA1Dv_1)CKtK+P*jwJWgaP#;i)$N^Ghy z{+P~%$t9l8K#(VF&Sj!QawcD+W5AdVbkoPkXd4JW2GhfJ+K)rpscFK~`nH1Gq;0_M_L(i!w3B2jQ=Ca1se6%c?BC$ye|h^66mU=iHDqbb zCa0HEHqZIO2ZMF&EfIW-vjjj;6iPwfSG%eCSvCj6vcf2^88&=i=kdb4&$hjbf#wZt z0950rrAXOlPw2DVU8ptOovO9$Yal3MMi={C_IZ}gySY;4Gj^S94MiG@9MPvBJ{=7! zF#R_?fHLL%BPVl;dx@ont_0k*nKZ976JIiP{REL2ON04?SR+caY(Cc^^At1V!tmpe zb2Q3&T}B$1Qt*{O$6Ws(>5FfPuW&ll{5ieZdBZ;+zZQawxD##T!UY)`NC-dyj^ zvU#gMk+WQMf;Fz@5KPEcJfk3xE`|7{cJ*k18#S5$Spo4RvjSaa@u+9^*iNH$7kwoi zEYBs+%F9&6^}E(B{skn1v{=nV4*aBaVx-_*&cN_&DO4gW4hF-)(a~p|>&r`?UGgsw zbMm!q*#acmr4DT==h2-D4g%fJql`r6Hu`;RxbK>(v{U5;Ss;G4@-i3=`okgea+0oV zygbE)+uN&yf(NzYF>_nH{UV@}OJ;7|M+XP{qu<%-tCQPj406iNw;5s~7t5Lb@pO~6 z=nKa(7()j@9y7BCf_K${T59f*EW;6_YX}7+PmcQBQ0PbT+ z!e}7}A%~@z7gunX?&g6PLad@7(0fm$dm4shkMt#bVwTPKEZM!yLF#pTy}^MUq!rK3 z)+t}f=tlk~uI=u!eZ0UvZik647P&yL8t8?ye5T5HAT^Cl|Hu;=dlNm+VU>tBOVmS~ ztwaovNc16W4I*_?wlJn*TbMHI3<4po1nb4uMus4w($e4&C`ij?s)Lp%Bw>%)&Vk-( zXcWb6yUyncUub4>xmbvLTi}zbEiW{6F&I$h6tV>SWG%jrICy8tj@b@RlCpg?SvklY zhk@v&et@2(;E6%A$Y2vAxffO5Qj*gOtaUDO+*x^s7Qeg=Dlny80*yHvz>{x#6Y{?6;;L-XT$K%l<1f0+k2H|#k{o!B#j7WoUzULy5 zcHf5(W-@`WyhubDmg>WL?AQ}dEA42H@o4~P+JiJp`z?98CU{wyE*kj!`4`LNeZteXKpGgW zT;HbeSd^&f&S8ILxth5RxjKEAkT zjA9GLiWIfVPGa=d@A^qt?qAW8BM29Ow`TU!D>$(1=w(TLR8x-4aRxc3|gD;2c9Ob#9_1O05+JFwnu)3|Z=;DgvAb=)@^f&_T!& zQ3=#`bi~fMmO60jf2AAds+}2K3||Mk8k(krY1@Xl*2PNrzIlm4%_{@lWha1yMe6g2 zYtgRP0lHSw#m|T5e}(id&mkJ!m+1yy3}1%d?2_O4uVU=q>LC@mUdpTlu>1^OE>SA2 z5Z{eIlVD@7@T$Dj*{R)Txv)}u3U1_Z@pJ*X^&x{*@cEzUuJCEb?>-0L8bL!eOBLFJ zXd9#;6cMum@JBZ$zgvo@E_!*F=84@dtb7Yvt}k{EkoTgt8`W+VYC#KLVH1Syf%7UC z#tJAZb@wneXNN52YZ4jU=3*-X6<2!(kiuyFLR=S-ATG!%GwVP?0Wn!E-pNFa+1@?R z_wpjG$3&;Ho2Z5F!Ofk_*h7xSH99vpMxInMp$`rTo=?>TlYq$QDqkUrO)2k_8jz4R z3T@QN4(Il*3_O#q974y%W@GhP27)M%SLvL>F)9=DnXS;7vX%TyrbJz32B^ysf_;>4If+zZKq+XKc?gOTMAOh` z_VF2RS3;AL4rDs+dN|QLf0k2P&|+tH~iF^f$!sP$>Z3z(W%heGGXt;+KGCW zg_3nQwM=O#)l8L_#s-FSwQ@@aXh48t$;cB+<^g;F?Tqw8TXGZVr7OyHOWE#PmqApO zS!H|A?S8HCC-#QYP(WX`nJGKjY%^yvzpO`l)i#kT4o=D2Qa!LaM7O~GeZljYU8Rvq z64LOJJfoth$h~UNBOC2DDTAHDu#WW8(>tGAwmcMke;TNNHo$|LwTHwig(TWH4IJZ6 z|0rwd-is(0lzYY7d?K~V3R5cFK<;<#wsv8uEIAzG7^;bDiYr47mN4 zV-M~F_99titVr<$E8+c}oennOTlMZ=&aRk8^$f@Kl7DF!)`wo^^zZK7_U3Mn2 zTtv=OYR>N!Tw7<^yz7lh&Jn81ZdC~5Ayd}x_78wFZ0;Ic+prooweH|yYMhc3a)at4 zw-I_st|*s^{-jGmKyr-Fwofv$$;*@k`w$CGe6f=C9PFT^RyC#Gcw?F$tn4(;V|(Mi zMY_SKxaHEy!AZiFO5IUcLAF3$2D!)EuZj`}Pm&GGy?Hi~P5WmIN``ThveoWQ&O_PF z4$xwhmm0u2gWV@DNTk@Q335$}T<+L&=((A@&(&lA0s$a(ktX3nIEW;>pmr!~a>cW8 zB@DA2K)cYRoh|_DX*Xwp9?qLK(}KKVM3ONdM+x_%LME{b?$pIBQmYkrNK-Y3Lp+Xy zYai$`ct;B>Y1ny+)2%$RZd{08d1WEZ9S+zB8U)>h!)&{4Ptz*&FpXO*{N<9vSQ*7M zUjtZAz%1@cPS$W^&0dQyk;sfo1cVB7m5MjE6}+X{ZPR}v-~tYH@L5MmbGMWS?cEE^ zsgZ~Us7LMXYnG_!ZlkMZ)wgT+vDsEBD(I%&ah#RgaRlGgc*uvN1>6#8QO#@vj<#=t;kZQH^ z^#T(J*nl9+(WwFmg{k_r?Ek~((Eip5Y0tBlek^+fX&kpwVeIZ81msNGjS{;V?dcT8 zTG9H_>ADg;)c|M54dW0xBn*QzKyYeua4x`TP@#oTNf&1 zg<-KE%>tFiRbF6|+=YxP~CLoof_eND!s}K_+p;^BC`Iy97x_{(jvS9(5#YoI&+7 z*Wa4XehG=GjG{S@G92kD!9F1bM7b0R4L5Ez6H=AGgV)#gZSVyE2eAx-L2D7Z?3Oc$ zfJ^+$4#4ntsqm$rb>8bPZ00AIoyG&No?cB|1|1x5?FQpC&2HcY22|)R{+uWT7uo|I z{_x|CJ?Sgn(BYjNw8~4K#tABb>{^j|u0T^|2f?Y#fA|qZ26U7r&sV!MEbXOFrYzz4 zLX@7f#P$zI`rJ10Jx^m>y3u#r>71lXnYH5i9W;c77@tjMm&VC?onP|&t^&?O1cMG% zaw&PII+;58NLDZzD>hBvob5zNrm4w>%uTK}{|PsX_~8&`(w4f6xRKSx%CAtS@eS;+ z4o447uwYYk7=N=hol)dp&?H(qbrQnGUikzn5~o+0QN@ed7?gfl(>0#-37^P>r&YQoUX4Dh10`v2s1VTjJEM1SA~L^~(P+-U%-T3waL?y*wswf$k;% z9x>W#$rKhlIaMZ`uKMH|N9CMjWg_yL{h)eOl#ZW>L+HdQG)1o;M{PZdILx(H>PY zT22wjXNIOxj6_h{?#N&t^hf6H#SOlYDVq>KByvV-6^5%A1++kh6=~_=Zi+l*`@JK4 zE9@4}A{7f~GQiY?_n4T2aul*9ILYHw13te83vSgkLHu024UuSEY;HNoj6ykdJIM9s zfX7|#+bWh#Mo2^?1zYKl8gn}HYMvjGRzPL2!PAtQAG4odQNiv^7~ZW!=Dcb%|90aA z1TA$JN-aPOyn6M^#vI<*Wx#0!xd~QB*A92rB>LxHx>yCkT1h6Sb#mih&|djSW8bEo z@weRj?VSBq`+qR!w{G|j-`P!(`lono53jq9Q(e7IBR5@9jnD4{gPZ~OmK637X7X(9 zTeq{@RwtnRTEDx9;OM=*Ni2=q6`Csoh+c7-5)8MqYM~8|K@+w0XxBt%R$CJcOxkvj z@<2P~ebJ{lN*b#=r^`ugchvYrp-}K434)z@V8Y6f(;O{}Hvmw%OAax7@iti5gmUO0 zpqzPs3kcTZlr|AdYh3^Up~q=p^m7;_5=`kpZ{`)Gsfq!fo>nZxehK#d?d{a>;SQ*% zu|Zemis&HD=CfN2+PisPgVpBP)9od}U;rZFR{HF<4~!3F_I`IT{9kW;oK1z)%UYjI zAMaYN>=xqENABb%j2eQ=a)5GDBmNQq%LZ6Q52sjJl%N!~j0B+#IF~6JA)JZso1uD! zA}>#-le&N!Di>Vp(39x|5>A%R3V(#4`k(5M3A+BQgC-oR|8a-SM$FipC&`RQcPy%8 z@zE+NybaDgn)+5#I0R>EESkW2oTXIgD(Q9P<&Y3Y{@PTed>0~8E#h(>gO_% zC+jY|5rV~G<}u2MW4KIUV+KEn{T+>%8&Z)*`8spZzZE-C&QqOn2$6Lv)w1*>E9~4CVhFF@WvAFnAwdfuGc6(p zxkhraD0mLW5j@o3T`jCCXqJ-Bd_Bfrb#Rt>D{Xhd$^B9Jgf>f*sG( zPM4B6l>G^M3Veta%*(maEbwlA+ID~{X)S1#Pht1rvn2Jbf&C$Eb(#o9_=7;+yq`tBBUXlYr z>6Th(k$31obMXV-A&p`1rhQv(2z3QXqX|D)Ij{t}G*7o$@xki(Z5PMyT;j-gD_CN7 zM!&e@epx-*^_MT$Z`HdH#95eVue!57x0k`lKlclN&0g}YIvwsv?(%2fb-wBo`)%pb zzQ1g<`&K=zZJ93G@q57&vpii2a9P^W3X@mUJ?1*JMOj2;eNdi@_;)0$>iSJHgpa^P zD^j<$%g}5@!p)dmg4@($J5c26Hux1=scX+l1mH4)eisAg!hBp*q8(Rz=>k#LwTexR zn_w7_pX&G!4pnVj$aocojXFRq0%?NeYZU(Gg51g|oKK`Dbc;EytI3->`c*Sj2b%f-2qm=`z3}{WKt;iZ`J?3ax>t#{zZQtfGMSbszXF2b(#sz-6+8c8&+5rk*LZXNyqb_+ z*B+h}eToFI1ZrK+{JT0CM5hb(6f2JQ^p5>6NjnW;bm%h1*dnUx+@#)Rla<|_cnS!cVvL8FSEPX?D>x)f*9O8_mmG4B z+r>&*6TM-Hcyx2I^ci>dam`|pC2B2V5cSupz*Ex212~u%*Ae^0VWRr!?WZ%QAasVf zEgtOT44~O-@b~x88Wo5>Y;1C-akR@s8kO;fRrdPsPxo*BKK_5i_}k_G=m$9Y=>~TA zi5rOLe35!39P{UYA2;eX?pjWnWzVwuDOSGn`v%DX%@Ar1z3A4tqdSBqa3gbXOKBFy9JS|YQ9b_2vS?ub0 z?4HPEhZJ_uB8bWCdfk4vKf*^F>FIidcsM+c_Gg3r<9^f|4iAs^598V3Xvq8gpf{NB z?;p-b`_b^=cyx5!6aC}EgD4&ihyCND{y^+Fy-_7W9RSKbo;MGTE-JO+66n3k@aIUa zvP4+<^Dk;f31)D#tz?fPr7;OrKe4sn$yDm4ov;0)p3hO!oKc8UG`c*H8RCallM6jz z%q3C3Mu{MbnVlu}?t1F;M~3EI7@WVTnYZ)OWDMJFOjZX-W`K5!drR7os_tdBzGo+^ zV<9tmh;3da+%WhIT#Rkz;CiZ>%fnTv8)o9dF|Ti3v;hFB3??Io>&BY~B?VP{Tg>Mo zXIlPNrs7^gc)ueCnP4E8FcK2r>=2d+JXN)iV=n_h+>ry35SHMtg(w6z5hOGY{M{VM zvLNn>(8Rykhd1&!ul~lV;o+_() z>bKc`n;o`U|DetG`)xMbZ?pd3u+0Vs2W@uH@3&dMH`s4e`9W`Z*ap&VcGN$%Z%6w_ z`)#&AI2;|e0ix`n>=BOnDbIK$jolV(&9ZC6|4Nu#M!FV`y>Ug_ZU~#%!x6#v*Ly^5 zZ5OA>@u0J3m!=)JJ4o0%u z)3ZpDHY@pZLZ-82ID6^&7YO>L2I*lrz5Rm@i&H)RwGjFGf1@w@$;rt{_&Qfv@Y6)$ zFFT!rpE6p7Z|&e$+W)gEK%u9DfbV+8y-H^(5=c5;??R_z*M=Kg>d>Ed{;jDWZOeVz zL|NN%+P3_)Em!}(6A<-F{%@OR5%I+eOn`$~oo_N_A2N|%I<8f|;wFTO4Bl?wtk!~a zt%z2h5Yz<2EXL#zshP97WGH|hj}D%8BP!1?$F}nkB-FCN?(MV zN{Jxd9KdYn$_h`S&~}sn`%v&vrOt*NL8?DzCeSo>N4ivY6(^SFd;e2kymR|~TFb|`pk zGs~}i_vzD082+i0NaTYm3>h>(P=!pHHQ*Pz_Sqt( z$eD)eSt-D-CO7$Zow#8__?eyYa4;P1I2;mtMgu=~iV+PvZ`N(bb%MdoQH*c~$(&&qA)IeEnck1Aa1llmA|m`u8T5FsY{p1p zlHHGLb`gRu1k4<26$N0tcNFPesvc6xW5#5xH}(Bi?*44Q*qzKiV);`@Q8GDmfv}kn z`OQ}U-D#-qnTpaOIB+HNf;akU#fXavZh@Rqgn%PIjP-Eej>PT7O)#erYg!RSD0kFD zk4xj)p=MEIbkqx6TM$obE2C|6Y6E3!AQ*HjU;9v7;|v-Y`*%>%8^JDa>e^esrtHNr(VKYa zh^_-wA-FCa1+a3J$WM5)G74uU!t;RING_Ji8bRHQ9IPn>MMix-nNFOFMF&W$nF2^E zpY+Rq)Kp8bvO9-1D_Q!SLg@U5a$~S{BQhvfXvP!YkPJ&i5E!#iA5`kIkd`f45z$Tx zqdH!n6xJ<8sh<$F7H^q(A=)+f*is$EPERmvLC8apVvclnE6b;I0B~Cl%CNR}xaWCg zH(rd93r`Qe9p%>$xv6ZsL=Y3vft2VKV8>dYUXvGWQ#8ePtf|+ zc2Vw-ak8VA%0RuqPFERtxA=VLf>e-|^lz09?TduEq?L?Q$g4<-Gem`mIRH!uNUzo?ns+jT1V4z@tV-P1AK>9HQ` zvwzwfvVS5sQrq^=q)++9Ke3}jIj$yJ7b3qF^Kq~qFrjN@YImgy3f##w9(ycrAQ8MJ z7ku84)i<5WT4MMXXAVfe+iVzRop8Eubbv%|YRO(dMnfjjNZE~GdVc9097t@bZp)$3 z#qRl8j!C)h#M)~Wgx4n6(&U1`&~-KVg#y4AlXG@iRrVs@Q;D9lvFdb1Iv-GROYs90cfBG>EE`m||( zdfWoF42Zi=Pll*|w?FLmkKI$d0R)9RXq%#!bwkx?cyN5YKiZF@ql3}xc%KjEhX+Ta zI1&d(hy0k&dwkTJjrcGc&H3T%C_Xwq81B#Z4~9qkgQzE5qfMr&M~zj%b%cObP|U2V z#{zRu?mrn>>$F2>s;tCNkq_|n8o+28iQ$I6qWnY5*BG;YK=EWgm#IAtOO-?iR3*4n zIlXqDHB<3P?Gf`~WM_a7d*dxc69n?X$LElEo1#PTUxyi$sYET-fSp*~(5t9iC;*i#H5`0GSRsU^)Z9gh-{@*x>CjoAmQv#F{y`| zjDJmvqL*6wkQ(@tr79MCyI@VEF9HqN2lY=>ZAIxZgSetP=U->L{KKr5jrPk;Q)Fe$ z1t75=(2E31I2_K?`#Pm3b@sKbfzs*Klw;2^UT+c#jMqeCs^T-L^8);&-xl!#z^l-w z%GIhDsN6Z}7T7?iS$qFHDb6yz7kh$w?@49*B_*=NOh0>>$Rm*&0`-TZ5j@>o>Jfn& zMdz4NyC1`m4~n8{5@;WF=*({RlJvQrC^{{Yf1$n>Q8rowb3J<(RC3E6DLW5J5D zCD%l)`F<^$D$AvUbe)K85=0qn>~*dv#4a}kX9WfPKe4Cta5#LjBR zQc&}~t%wOG$xoxoePtfkGke21y^-CUv27W?8Eee){nQ9zb^@g6G;$zp(xu%rQql1I}!8XFBq}NDZH`7KyYI~c#R?58d`6?>% zQ(mMe`bwqOkPEN=;-eP1<1Khx;TfNYS@X+}80RVrMU9h-i*0>$esLSl12udItV`)r z*O>@&vH5hQ6&V~=h;0|HT4rogIdkFd-O4oeMK)SQ`!KFnABn6(sE5*Dq)t2aXbb!O z!TvB5>y)-<_pFYD&9Pauc{A2AWWCiy-enCO6#~1A=gBdPM*XM7d;Y_wvS@ z`3uMTnfigchM-wbO_GM4B@I)9NCXsKOEE@m9duNCZ(^L1|c5HP6+V8-8fvK@lm39J(wN!SMDM}H64e;P(y{dW%!I5WI(MI3C z^%Q$@QaK^=1qz>17gK(#ExMix^=E5)wl&b8=wZ&`nX(hA!UZ|lZ{=ng+RT>D{n!N; zlum=0z$v6S3 zUYj?>RKM3FmMkrF7Q7H?nFX{og5!yqiM&HJh&x-6*mB;Ob8xTYXwIt-Mwtv_G{6?qZ1G2e^B#4?BH7u4O0AY?F;6JPiZ^x6R%im9ZZ) z9^K(pWaHxZA8q^I(18XnU#rrGuFAMd1GsDm=g_HviD8pUSUw&y#yZF6s{ zXl~c_kd6{`2{RQ0K8~2wTq7c68VBU+GbfnL;Uo&&qv}WEOWo~iW0i0Erm^4a{8nqC z(FqRTE>u<((P=%|=go?TM{M$?&H<{^g~CT`HISmUessK#>||N4=1u&-izgY{P&Jht zApv43^cHKN$DOwpoWe_`%`<2|-OW*N1b6vDjw^>>4XQhkc0W#Pt|)=!$BG0oPgGjD z0n=d$Qh1pa7mmsjy1dc?n4Q}m*V6+<#3B=EEK*D$<64*)iUp$tUfg>v@gx^KUV~`s zGWM5FC3)#olDGqEtqS&+A{bnVJS`c+UD*ez*7Sa!)V<{3V9*Y`_;C^>+=x{wpx9^d zSf^Z-pE0M^Cb1In!Adt|&;LwMNF<|g)#()SbMq{8s)Nw#QGOxpRp4p(5kT?EkJ=_( zdQu+h!96NRzeH)m`)SY&LfqcVSTIidD~gUNQlGwK^LnkTw*ieRuF4J$0!6O=0`dCe z%3}}vijc&;VXs$v?<{Av#~li}uRmwr%1&#lkR4BP$E_aTaX}MF#Z)jJ3zUIcqOP4pPh8^&E z8k(Bx+3!-&KM?;Z6Ad~i7H z&!druj}K-g<-A%Wz!)#hIRG0W}6%S;T!@qT|_%nl)A>rxt5*pexkvr2p7i%15eu)XU+wHsqw;r8kN;tw9!-9I1uh!z(^s8NFYtyV zLVtIK`@1XL^IVE(!aU_qRPJ3h?;b)L{^Q+yZfX)oeRnN)d%wGGae)b(So*zQKYU6) zEWzV>lc7>X2>9NhscUX5a$v1{SkX#@=o!=ROfvWd&GP0~=P6#v*50tpwA>tm8nvKv$4+ z2@1x~d!IMbbWjFkTfWW2moEG4a&2^0Jlp$B_kArs=E<1t>@}~iAQ4)9I?<~~&1c(9 zFV!u_Cm+M)C+R|_U$z!DiSFxou zmMeMU3!=(%C(7fEMD@2|j8^P{OXIBR2xgj!hq6(XmRPm^Ax_}UMEM7L=dCo`4`LkZHFQsJu<)?B9I)~-jleh#vA2{D-$DTKw#lwmfF z)~*MQv)7<`ktFPg={4q#VwWlx_I}+)>pis+!JLNN5~OkqT50Xp+Tk9KHB3huTr8E# zk-S9DfzvCy)tVyfw#X20rA}SKd^d2E$(2;3GUKa;1nHA0BgYelaa+({nHH-e0c-_4 zqA2829}luA63fRkD=iqr(~YdB0GyU+&Zu8cKpaO4Z(v3w0FYIgbu zV19LG>%eveU<9X=vulJ1$}#n?a)8b7w@hPsFXMtIBo{%_wdu)aB_e&QRAQ-3Rcz^9 zNNvXK=be793;)|Y+WDoa*%jA!h{yH2TD|1@4uQD_!%8!wZ`!+2t#|Xd*Bg)b`n_ST zccX9FyHVM@{-77O!|VjoK6IJ@Pi4whMPejOFQDotFvhVXx)9E)sfs64+fY>`ap^dN z-B@P#!rB}4Z zW<{&pG+r!#{SkaggpPPndM�ZCLd^cGjn^0|d|B2w)@1M9@JmC=#}h`BsdC1PlK z`;p|DOtp&4dAkJz`e^@$-7N#~FVmYcQG6A>#Vr`wF3yVEty?%{p-ns zY&A7uYBz9ff=uWtEt78B<*8e{^coL>%>o{~*fx40)4K~ReuQ`|l^1rc23V;sN%)0| z?#S27t}Bp^!N1#`=sTT`6)kq$X-O9Cdv)jF_Z{YYBhfLl(u6(IaDj$i7qHVdLDHfM z&MmfDmC*}OY{N7nF3(;?@NL~4RUkY`;0_K850Pv~0W!0zJfs`g!U4twYvFked%Cmv zhn__Cw5;Un-E6mxrCXL5{ReS2s&fW>{UAg}D3v}Tic^L-J{4p^_&KNuP=gp8Cn=ykE^S7ka4@$lO6Cu~ihf`n?18 zg$*?3IZFr^1wj_TH)P50r7FCtJr_K-D@-F1_PRglY0Tcl{ukTtu`g_2ziBbYz^!Y4 zY@2f2Io~z!TMkY&+UE-o`2?_}N?6sPmB@QxnRrH@T~SZ0iLqz$wLz=K*nY3&$LATW z)yA@sxBX|bwn=M~x2DbC-eNmhuD+~8khvgBe+b;&+GPMP;#1M^T+n^D&30fq+CQ9{ zd566&r}~>V+sSxtBu_S;+lydis*mkv{Ic6Xc_D{Cp;MiCF2r7I*FKoq2iGBz9uZ(!NKU2SJl`9rL`M+@~1Ig>t6jl z9{;ZN6QXiR4W+HlnG+m=x)^w=#|GB@8dY$>2)J#qvz*$lfbA67pOOSZWK* zRF2qFfObN#?kFd0Iy?e_4`c=|OTN;cUr*ES)Rd+&7jrxBY36nTd;*^MOZ$FL?^IFs zFZf#I?9d}wVUDG4D>;PTHzjHUS%O_t@=7*!HSA;e)R}z!{(WmN6;V>e!rqR>7yJ_< z_W=ssLnD+~Q%WU;uu}mK>s_zYK@CKr79ZSVO2DIktqQ!(SV_jdUx20o3w4=Tj4Rdb zFGkp{WA+!V(prL098Jj1OQhxu0~#R*Z!1xY8~Ayl_*N-o#TSXV2a^hzBMn<}y_D&q zg>OOu1Xkq@VL-!nZvTFr@tm)O5jnejuL^JS_B$o$GoNEh>UCFwsNv6jTwk~E^Bil_`UNI1c3v-dypy&R|MUi zN#T5cHH(N_%Z=!u~fs3xZ5%NR^Vi{3JPb9Hiy*Gp;{td_QU zyg=CNi^B#)Qj~SLG0R#-nOJLiG9|5|ZPq7LV=9l)ui2%{W!eY```g{%-La_X)|Epy z&aWnA7^_Rbk|dPft;!o{S)K4;a=BQD9K?rOQ;>U(X)D-7v2ZYEGhz4}iu_d%tz8mrTn;WWSu19ELU}`F9y2SfteGXpVgV__!LiB7 zMFtw)dVxE^1bs{kyYE?1-+_b&6ia>fWUAYkED;s)Y^UFa|1oC&Ge9RO5vF8&K{IgK zZlvGa8w{xh`{zyz)j?$gKnCiwORn#5jqof>BwiHkY%j~y+87)hblv~&S=uYE?_SFM z<;iIvBEk2y&)(G9`ZD(aV{APR{)Y`mfzIDs9!~Jc1x-|z$VeKy2!q&}Qj-ds9S03Q zspqW(h5@t$lN7hz{*n?+AsE4Xao9ptjhxxtL5!N zro|U8_-MnUI~SzT+Qk%oXhc}UR%h8oSiuB4$t_=P*Ig)D>ml*FqOWZ^pbkddiZU1h z;bPptD2Qza{YJhFX2KCHvj@I$cTAZB728dhIao0T!HnDr8&NKdaNoGi=lkhLnE5EBIe@h}1mci!SJyu7I6u!GID`8XfXu!0T;HjF|nV7?UeWi@QxS`Mo4eOMfHj8!M zX3O;~m&hGjWbM1M+fgK(Lsr?ei}&|$%g<-`m4q@5vwuCCmTls^Z+pE5b~d0tE?>Fk zW1XK#odGa;R3@-_pfJP9)G-4l!^za%AbF;X#4+qrIbw)8*P3z9>SRiHA$0wz4i;1l znjhPiJYPiO)_F0yS@^?|X8z&H1J4Ef9()?fW>fk=?UuJBhE5Caj$5N$pNJQS>>^kb zEyj|=O~}uS!z~L6zKclj)tZ57%)0_Dy-PQI*)Y)GS;3Y(uxkWqWN}InfP1O+OJ<$q zuub$GVDMb!4?GXjlp!{R(=DL74*i`1#>?WRt|7?u4Q|GmuGuFWh!utSYmb&4I1`20 zl{OrcT<)Kf3>>S=Y*b+yBN)SRFy2p$GkTg}2x}##O$$Twrvv3XWTxYqJ%}Xf25q|a zG4`nrH`|@9*#lx7`_#U^+gSCBr3kCBzRNEv2|emud7#3TI4x7@%G6 zpymAaK;e1uw%mn-^$|C`WT6zPIfs5XTv4BRf}vXR#sRB zdQ?I)mqy$+Z&w91Z(F#=u2z_EIatAN0QM&DnCh$~jf3Y$|NAnlZK1Rv0Ezqk;tvRy5&sM`8L|D{X*AoR(Fa@#KN8QSp`vkjb8FR&uVfIattR1O2rK`eeb@HE0A2iz5fda?c{|v_VxJ}@CL1(;;wIDbX?&5 zjJ9e51#!tZeGXd8O=)*KJmqg)3Qy_gQh;#aRMWGyz2@1;(q*sz7t;7NSE|IN!TWCc zqRl8}<)<0P>jMec<(_5OWZlJ-?T@9#?6_s6E}tETJQ*!3Ps(^pH; zx0#-ABQ;;$KOK^`)M8w9>P2^m z0Q=X;`3VONFJN1OqF}*RLTlSipZ-kEkrg~8oM*+(&)@yI^WCcRUCh3_?S3bI`T0BZ z%g^5>zx@1N`V0H{yT$ms-Cx*u_rWZzI%4+w5GDPMD|bYU1j>SlsVv6RU#4 z!4T^vNQn)mTsuS!`Q$m6^Mha&Zj4xE27n&5?Rks2*W}gHo4#{Y+S~PsKow|r?G1l>Yq7%FxV{uupbbo;6`Sz zb9N|vK%QrJ)U&J0wnN`zgUL~EGZ{LZk0NGEl|kArp2to*@ulN6VjXZEOJfiMY;ow* zQt(*hr5NA>>MjnOE>$#V35EcA{AE7BDpt41!uKlE7l&xKpHTcA`-3?a--_XL&u_UK z+1d?Bf&!G2I>O0g=q7aP!j^}dgHH~$-|HTC`iJ|&mfZA|CWd z$MfF)AQB=P92^e@aoih;-mE_$bf8C|Nmv6`%0V=W2Yr6rI~wdC%tptDV%R@E=*Neg z9~?)~;Gj1e4rT|lgW=KOP#nemebJxA@&53D_xF$Il*Fixlj8LiB`$~`x&WFuK#arj zt#0XGOwLbzH5a5^CoF1ThUW`NTdzHhlYH^)+FOxS>L@DBgzQBcHu#lCJAsPd)AIo9 zgboCU)TXrQtWwjlhmBXn0u{>bYfJ2{QnObn;TjyX?eA_OB>4>Vo63XzGM~_(B5$}x zbCvN0SxYSUx5|Ht?cEPBW18?{9;7n7X6#V+lIK^;Ml#&&ke#=jrLR)Oujv zex8^mJDCE!B>tKb66fKOuUBb$GpEN_VTgn||6=Hk7G`f3sLOQG;T`|9)r=~z4O5^I zQJ{_|;6(rro=3};><%x)&ud1{tD+SU_Q2-HbfC`-X+XlX+K-^plyq9#@Ms=Eqp8=f z;?M+#g%1}c$H;&5r~J!iLB(#ghwf<|?_1m{H`cvY6Rgp01=48OArTEdoY8IoLo|FZ zecV|HVzj#fU=-Fm=noJntR8goqOg-cH1K45=*iawpEQJ@Ft!nZ@}dxwtwAVX8HUmn z?7`S(D9X!%QMQGnd~HBVV@S#t2oh-Fqeio9UJ&}dib0lk^R@&j3C8ZaR+x!I+*7QT zyqAes2nV)KKQ|SsH|OY`V?L{*youQ)$SB z{ejI2!&Z>t*WTj7xBvVncF^tj@zU#)s3RedO?UI>n@`v0Hy=J;pPs)8LD45E5;(Hu za`8%g6zI3pcW}*_o?l;nxT*|iz`iA1XaB7-OIz)ot!GJCQr^UIXHS>JHrWn@-MmQc z#WkQ3<+7tJbNBu3V9@O`m6zpXdU4S0ReCco=SjQd&6(<*E> z!Z`vK%1W|MIKGXnXYl;G{GBh$-nlh*=hn=fwY;6!C*O_#id}$rsfxw7;l7G6b}RB# z%`^ghoqIiIjX4Jp?bYO|>Nr@uO2Gh@gIy^zNo#Mb+3rj79>oWh7%CQJNO03!-NZ|K z1TC$kS;tC4k+Xz1vpaedTG}6kl@=nUwd^pIg9m09?eDUP(0nJ>J6=XC%kG^2TJYqr zSfwm*Pnvl6Z}}LZamH-tN;xpRzfQsDDtK_Ea0-dn{q6`Lb>0N}&_`k1>Yu6s$n9^Q z)Y;XIQz_ZHr}fJZ>ie#rJ^17i(J6h3_u^Co@*ch0+l3z;d~928F&3xVsdoO>a3QW} z)dNeYSFqa}R|=BgbAv!#-Z{$aD9PD3Gz+oD@oF%7Je~q)W7pfXcQog$dD^7^-_59B z{Zim#@8p{x%w}fK{L1C{6Hnt$n-*L2i!@7`8#L}7i+3v!=`(!@$}idgPWECyf{@yF z@V@7y!)Z>2^9}t8p5;-{>{IZyUIpRk?6T^)gNrrz(3`9@xFS5}jPMe7gvT5bwz(wy zUZ;fLIT}xSGUWHq+RV1NH3hcVo#W%tuok3VXi;8^!6O_3TU~tkGkntS``yDmitgN_ z^elV3UhCFDvKWrx$hPpIl`|&vs3{!YE3bYnl;H%~S~*Nz4hsr4@js+W)}o{eV;?v{Dsp*3jQ z0?JgV5{MGPQ^NcEh>3*2qG-<@Ba(G%mlY{ZhB9W$XEV}9W$rP$TN|GHh#~?pvrpzc zGPD83IKkc@3S@(w{eFZL| zA?;F(+Dy_L;#zcDl;eeD%rI(8v!!|n9g^`|f(oBJ#G~9!XIMD57dIUaksAaxh{7O9 zczEC6Wv}fHo2)C9K?oKQsxVuZ=8SY<8Mj?mxm=Ww$eU=Yw3gKX19bIw$fEe`?ntBd z%{KMc`R@||D0TYnlPPjfPaeyN>-?*vb~*wW4{k?twNk0Aj_FA;;wQ|sghhQKNSwU5 zlvhG8VLhnSng3kkt(1gX4?CNx94VolLga?xzViTqt>geUxLUrahzEi%>i2l!dfsJ| zIiar*R8?Fi7IPh*t=(Sc(cXNEb`dKS#KU&k2m9B#MJ28uPUdgI~g6377Adh@GC41N0-&a{d)#*6$r3 zG}#+*VuQm1n-yuC1Pu_hkBpHWI@d#{fnXx;MGo)+Tc>ar190ikgsyEGt2po0<3R_b5`A7R{NgK%TJT_ZG)X1o@ce%BV;s z9==7Ui%XEsZdIW7wl(|R{(+^paRyg|?da$Imjoiw?ca9Gx)&Qb)=*^Ua|<~M;;0e$ z#Ln-`u}3;DE5rDg5XlR3&F+nHXQ?83s~_PL5IVk!LpN3dr?iD&tZv7}sAGt6USst+ zJRu?afz>yd!pA$GTfyfFSSsfZqR7|*dJo+rf(+3)t7IX@>1cR3fWd^CZG1TD9rfWM z5^-Yz7s6)Ty-m0Qc6s~JenNW$Jmk{2Kzj<=vah?X%iE77MHjG%n=|EKK?&32;hbKd zbz3y;+{4rBGrwg$h$Q(TRSzj$5v9;gVRy9m+tMAxx0SwplT)rRQCz2EpW$bB$0&)} zTVwUy&D%t=SF(LGf4q=r#V>Er?R5{Eedv0_+0p*saDF&HJ|2vY_oG2H8y@Y?j*pLf z!@h`*=EnmukB&rtI3MtX`97Z=9~>MG`RG9KK^!&v(6J};jJ-h19d@f(*&R3%hhBS4 zWBs+hc8$bd=rZ;QjpurhHJVr&>Hgi~@-mCdbMh^1nUPN?UTR3Y^x~vT&rP{h&XXYF zQsWfa$inmo=U{rdMe(WpKij&cf0vKl6I5U3a`yzWx(D79dEmBYfddYn$N~2aGr(;N z-24{V-@b9~w=J39klo*(_pLE~)%LUgf1qRK?_SAG`9;~L!`!3ezUj;SEgX$+ihLo; zM0(rj!eoxZqSS0AmVm=tfr~(dKet&ZH{=9Q}J|65J9@jA+NZ`M{xY@h8xu7dF zhBV#ViD?ut)Mc;Xmf|yg&k4sf;KI&H?Xx<@bV*%9v#4&&%x ze>j})_oJiZ*+JAlKA!gv;^Ur}9q@w@KR!O3@#Fpd!`|VH_u|=nbi6+ph>fQCZ$&P` zhT%cI*=RV52eX6YXup3n-0#iAAddRSA{y}c_;4^B_J_y)gW0|qj{1Y){=sNAi#Xpu zijEJ4z5ZdZzuD}At~C0f>rL|g}@-rDNBCaGd<@z?(W1l{qScyGvA)Qd(#jJNf=WELr``r zkNdZO2UP$FkRT=5?oP7X+Ov~32^Ixk2Zt zY&l=dIR6dJIDZlg&M;`f89vB@Gu%C1--7c<hIS1B-=0@R zJ9-B*sHhYI=Q>}8A*xp$(5`QJ4o-OhLYB0gOYPe@&j~Fnkza@0Dwy(?=jZP(uc7rd zK0jCA)D>|LS6gW*jHr3-Av^T3H5DX1a8pK$a>OX|Y4i9y^Ry}uxi>JtY?4Rcy3t7U z=t!&WoMrWFj~=*S%ExYy^`ws;Je&D(ST_@OyG+{&ZcPRW;A}$3W~@noFg7hD#v*@- zBQajlj}Gqe=KLw*J8A$wS%}Blp%pd6ie^{G~W=bbic&w{_5_4{fN5l)z^m*=`w{am>MXD(xvf};ym zPIRSj`l2gQ2}0_r&J(k6uOF0F@7x-orXr_wTXkp7pBTs>E>KPslquX}!_ickf z2tgHmjEMpOy6#ST{b^7wy&5K2B{@3SfPCsadzTrm8#K>Y0UsMj0<3 zeF36nzevUf&rA0jBtF=Wk66O!=xCg<{e&JKvx5^FCws#aI@;Z*Mec_iqXUKsi^PLXL>9uDCXw2AtJ*?Bc5nmAwS&6{L*4M| zQvT0qakcn=F}1E~YHc@pRr|}yIkuj)D+nTxG0aZi?`#>_Fn28RmaLjTsVrH6eXuZDfmlvI#wvt`_kE24QbqF&m%?bUG&vjzq zC{L;OUs(pF558{J2;_sCXVz+9YFdQARr0(^sHQtOFF5#Oo+XLM<^Pcis| zDHF?NU~g|dGK;Yf>mkZX_?Y-|5&vKKBEFjLKlT;;?-xYT*j8&^zMJwc7_19fZlkCa zicgN*5ZH9%+An7 z6LppgrfY;iz9E*7^LLlFW*3U|rp&OmL_3)|X7rX3X@j06EAY8dpV1MRGpU`BZI&s3 zrvoCKivWAr&!`%v!BC;(=eDW};%l~4l?1Da)BTNSr0*sz?tecYv45~a>iX34OtC=t zl4s-t)Ho~IEKh04K9HEEsodUpMtG?!%0unL+ha*mJ}PLT26v~S!G8V@ilku722mLIgfWgPCsTc$wNq`tL^0 z8Qs7Nk~*slJ{`JWooUA!|HExiw;|w+kI6#JbxM~6LKzAc3w>p8K{+3{kiE)tVx4si zLj54Ap4ki(K5|RpqrVKqcsY>NM6Cn}2S1yqCC|aGiFe1D1*Yf$?A*3duyrMWDLa;4 zg(J_sI_Sfr-Tv^nzk6`d-yL`pG+LUF%#0>ZIaCp@(jjfTX|OOClbgA0UQU6<^=*GQ zkS-SzEuo2cQ+c0VIM z%+}cJM$(F*dShUvd%H!8da-l8n<0r&MeZ_n$n7K#s~(yBTuvi;?&KJ=4AS9Z;YqG6 zc%BWfX~kP&#|v?1;{+5k>^Ypl|H!rUHEn%k7RT}Ea6F8UN4rOddq<3(91KR|qnPav zM#mGs!T4l+vbVcC*gr`Q=-znumeCZWV=Kbe zNE;$<8+pOEY)1j?*_N7~d;Np{e)Y6Ys-u&Gdwn_696D z+1=fxql090Fd7}~?kC5|;Bash)A;Ccd^DoRyL7LD946Lsav4G2t4CN_pTQ|sQOYUi zrt>?R#b8%nU0WeKh`_%e(_29)AiLEq89p^i$nL@6TkgDZwH^;b<$N3l;SF(_J8@8W z@dt0}N`%xLvx>Br$U4M@yN0C{4%0YHT`_b`SXrVhjvt5e>uK~{ zRGx+{AlG%s(clg>ZmTeHn)_Tf;GQ!)7#<%FheyZzgYn@B-AjgSG#tn5Xf&en!QM$6 zAF#ph$!yv&a^1XVC=h`qKCXypl0ZJ%>=!E_6i?E4t8Er}h_-vo~)LKkcXO@sOJ- zLoWd*b8?lo)G}=pn|+socOqezCeOGAXY;#)7qGq))S5GR^;wtxHrUTBxPP8qy}Nk# z?Wt?85tX~X=MG_TQ5=g=rO0dP6LLRjMlc^StSIefgNOR+CfO;Kj`L}y+f%U2n|kYz zYR*C(%_n5@+3x<~$?g^=a4@)_(mADBqAjwpOD?YnpXDj^jjA(LFfzoqaI5T_N@=v? zV{n&%r58NztafCRg+sDc3$rZfc+6urLo@Pz4!#?nssivJp}sNb#G)ve%te-%a`*(w zL}<)R(%XV15ch~O0M+P?FqiYTuCbeHh4y~RAZxGdw30Ac8cQRrnGs7xHnElX5TNEd z{&3AA$~01^WY6lD^%a^r$-l|PrHxpgSN6b}H=}9K1ODp!>u%tB{q;wz zq_tZ$dM_itE3W%EC4)Zv-_Ahy7Vw1kcn$lAU*6zS#ItZM<`aZ)+UUrj`0$Q`5Ki3` z!p)=>UPg<*FfQ39wZ+f@?FQ-w!PG>7fFQ6MoDPAYDGsa#((#iBdrGVa$US~L z4&O&;BsFEERTX(e7y2@%>%w*UmFsfQfeYBqE7;`_{ma-Du46kcWLLYAebP(Wt^l;B zxR`zNtJ&7e*{8dnZMmRbN7i4mk7`ETRt~sL~ygS47u^PLoza3*RFP$+Oh2vDygcI%3FZ7D>u3ETE9dCQu+Xw9MSZujUhwK?4RE_c365@v!;H`lPEYkLl_mMmV~+b>jS+caH9d>#n5Su86}y#qhy;d-9uqEK3+U;R|=kCaVlyf}rw&(gHAPwLw|UkQZ1 zjGa>YinOy?+}~U(Nq@%3ChxQUwg$M>2YT5{F!$0+AL}jfs!}h|`}w;U8bv;~7t~}% zvpG%EMc?HFd}7MLU{vOeB^>%wtKK@Ut2slzb=2RHK#oM$f*0Hsg7$OA3Q4!BiYr!d z>Ko%a+|@z-7Zjmn3rv`06Wy#2{+tz&F(eq;q6);v#B%naHE5^FJujF}2L&e~Zr zF)d(6Y`uvgnAU65lpY=|%2%$%3D+dEtI{)@>*Yu-Ra#I*ryY!<3EZhR*J|`P z{Vr1P{_dda|CTN2RtnWRXaOHw-!}U!EMhLnjM0o|lkq&oT5Mo8Te3w%SJ>3$1v#zU z5GvOU0xJhAZQv|!gqfASqQ(MjZn-B-66@xozCClJ?#~O6{Vy@9YIjYUQ<^HPDnxo< zU2hd*9t3AJS{lbT=(IB5>552tRHAk%26_l&A;!$Z+qG-=3L{0#+AY2`MYRx|*3o8) z7N#yuiyfgYIu zGoHe3P+}`7SUfMlCGuZlWX;!8H?mpl<*~Y{8ziG31Y@01Jqp- z^@(?yy__>+j~DYY660v3I6=Z?S@6-^2m_A8llB>{aSG{}{uNwg^P2_RvSf$sG3i3l z4@(4kE1F8ku941g+uC~&tR!i`N?kckR)>4SQsxuX9UgitN(|h|Sf8Am+G#{CvXXuz z6Mn}eneik8|6dy`TF6o@LCB7N#|n3!j>WuyOqE$V?Sok!VQmx1Tq3Mz`O+~oDJ$fT zT2;}%#7OQuGnT3d`*4Y&-<*=(fDFixe7&y%6!c0*A={!@D_!c+yg_Ltv zT(Pl#?>Z^OTq)Jg_BXzQrpYbOl2aoPAQTSYTuwCI?^L{ z$F29m0patA#>i^PpxTPDrLrH>)}m_$z;YMCS9)js(;T78iOAjg!;IvcQrTphP-%7Y<_g)&%cYTCHS61?6Q1rVH2l z=5v-c~6zXS8hi{W(fk!2E}9K(6bh z25;C4X8M$*(yeVO&0Qmq1pFUchv7P3tu&A}{jqa2&0gBa2(&tVG7W4d+B@rdjm}T2Hj^OR(rBy?+3$LUZ@D_?*OU>-RHJxvl#!d26R!z}h9z%Dlm9>VBiZ zwQh(fbpwv|oFV^sE6FA>e5G^hu=%Y}{puQWF<5JWLM4{=cjQKVsc=$4Ecn_rLxVvF zg4!iu>Vr>qA+vy+VNN?peXxK&crMq?&%jEj8nVQgCZCZH*sebnvb++a{6KPAPR;F@ zQ@C6;0NLF2X-1!JsO)VLjpz%BIi%V%@#_wf+otJA)7wCrh zEno)KTP0q`#xxCMG}TBUGl=c{1DTgR1)mU_5r!Ftnl&wJ1GLWj!rT`EM@U%7Vl;@G zgdf=iN^LN&B#7L2rYIqb1YsDC2iZl&^VH23Vp2bRe=Kh*pszF}FUv*{zj+2WRj0~d zF<07_NoJzDlhb*bi2H2gSyhAY2l(!NcCFvFF;lp4U<*TPOwP`;1pE~se!^COH3k95 zyJglNWVYIP=H1~^eWL+s8EsP04;(z`BIu%T?&KBWWlYmXMywCpZmc_OaBPQ51%Wv@ zi;Sr4p0JopC6jMsNRo{K(QwpsDKKQ7_cwqAy%Xh?8WE&e2cNYbrt2~(19qTUWK)jy zHZ~yZjQF@Xt=Bu*tn!d=8SB1~RUiu1d=;6!n^uouav{9O+yTvVSr&}WOlZGz13lQT zgW?i8QQLE-y>8M4*#x5BoL`cw>zgeXLNx3ELFFQgr-jJGT&4>XsWYPStzs4#CVv<4 zEi2#fY{Cj#v}HJOD^g;-jZ~c^Oy^7am+CB===aDpx7{SK=>H7CN6-I5sWY#N0=^v2 zB}@MEc^`{RUIC;l-NQNP?7EFj|D~qBMq3EMn&k!hUE#-gwP&jU+syDOE#L-tN;7gW z+$G;El=fyWJYK%L9%yX0(QyPKAuG1?GLz@JE4Z}PCs@D_TJ1ZX;6Z8EYAKVP73B5* z`|=$+%K+n{@zkQ}Rv&sxKVIaQtoTm*m!6V?fx9G00`96hM+{F=2K5f|g57bPU>cYF z&Rq-I(FbmZbxw{{h}(IN6N5fbvCf&R7EH?TFr{dcvU3Z@$&++S26E}>3s#!!Dxt11 zEwSo5YGSNWS-kV|B! zeR6Hn6q#oV-=A3_z%>b1u#-GWr-u@mUb;6oZ=^=f@u_GI04U0{n=(Bm-oA#&Y$OcT zRl`A?#gZB7$U)Hrg*&GbRqiI~GQJV17@3Gmk?BQ>vO$CZs@DB%P%+UmAoKwlB z;y63nSxFR_bjvJllj#Xv^%S;R`2s!BxKP~`G?O_kSXQDFnj@)PpWj?s83Mb7x-xP@ z#${d?2%)u>k^1D_`z`PPN%!7idJ)!8GLu9HbFf-0n%ybo)rncx~ z1{-*hGjMyUdGb0HlQ&1Kq+1()gZfZvpDQ6%@%U^4CwI79+B5P_fb$A1)nQ@6X||0# z$JD&*kY3oX$YMvSfXrVyN&`OECf~YGDRlD9yfir_6nzv*KC%{+wj)R<1_b(5WJg~% z@B>9Ty}(6}kacU_P;Zi^w5@6O&3rrt%lpq&?x-ovGL{;e&-Dphu$U>HUc*?I;IT;_ z)CQ+1nNi>kUGtwA#)Le)SNCqrafotzSBU9=XsmdK-eAcE*0AGD{=W@uLbj>q z3NedPjf$|WEI9g=P2xr+Kw#^QrHzAv7%ngiMWu+W#du!MX<8>MI52~=s2Y)+(px6$ z3$@hw%hXhl=SnqG?aiiCtV>C|O6A14hijiKE*7~NloTku%n-ER@LnTF-uovn*kn$N zL~Zbk%WD>IyY=mO=6;AFa|9LYFgYqBSfLy~lGcWivqB9- z+f48_XMgu#pnKGZGH$Hv%Zn>42_Tge6H0pmO~Cv(F}``od$ff!9QS8?!BhfeAyTvk zYG{u08+gbzZc~YA6uxe1!fD(%0X@)VkKQt!_Sd?&)tC|zyAM?8>oGx{0{5=6%>!1Q zF@R5XVFFirfSe*-<&5H7d+40w(4_+mA>l#@k%i#9hE>`94l=*E#$(6?LnhO>P#U7l z`FPBBpl1|aPKW)&{@(vI`B@knpBx_?jmEpXd&A=)i`jTMNKQthIN2Q^9q%2F_YRLw z*vTl_-QPbLv4rg%3=R+J(cUgQ-reg$&1`lW$6}t9PE-Bn3}5)6WayPyzdE*lY|co! z`gZQXoMvq|V*vnoKj*XvT-bS^SueA*vShLp1q5EDtW;tRa&d3zVuiZzvCTi6CXJyt zaC1Yo!s`ak-74iPFUeTwEThJr=>pNhpk7g>Wa-!gRSG;)(eU9~Nr9PhsSD@{qx`^~ zrNX%H!TCgyV)(12Xg9xAQ?;94OM3GLuqCP6p8{MnmHWC-*G%oc68L7S_gcp-Dc{Yn zCG~sDS~uabtqa{N2G#+{4UO#BHLyfKag-+hyjaZ;@=MYp04J<2E2O{GYAF%42C0xj z#}$*3fzT4&%bC>2GX#lM_HUDjV7;AOQh8gY5@$dS3v=9$|;NLZ=m`p zRi8WEw`6>H1pTUf75|l~SkECwT2gaV?|k=CZ&$f#KUb7LG(1lL8Sjtc{gd%%FiM8W z@$iTq#`}l6gZ(%@irLBjUVOAS9u4Th{>dRdI%Wg5pTxU^_=Fx04{35V?nLerN+30# zn;>btizMmY@bl8%6#CAyAwZ81W{mUKiqcGwdTq?Imi)}^TYm}3o~(C30JirjhGm;T zhRY_{jzlgibF9_=Gx zTveNEY!lcIo+j%+B^s{$QG23nqqSqy6=Y(d3^6 zFWLJn4k3)6L!N^*5qG}y^7gosbbi)4DQ+ZBZ5f`Q!R4}IIkhHd|Gf4+SmzRGb9H^z zC$G*47<1pSXZ2hwaArXs z*B`EXwRfVJ&`ei&J|#T>UvGobiOxBp)j5NQ=i~3QE}hNK1moxr-}@Ett7MZGW2lZ{ z&VrZkuJKv|?-#&ar!U(~koP9*Px|C<#$E_f@%_J9JIdet@-E)&f4z13H}!RdU;kZu zZf|Ydo@}P-3%JMQ*@Vn<_cs3G63wdydE=bZOsT1(`b>l~8Djdr z;py?`)!=z6eW zcAI%&T@v;Na^o*we*Zmw+NaHw5|TUb-ru~s?w23Sr|V-d7z_^g_u;>T!Jz)%-Tl42 zzYO<}_V)*SdwWOwe;Ew-hew0IkipZT(Egjtk`{j%Ji4#?;Ql1PUw(-QA7i4R%|2d7 z_icGEa|5wOHkBk{8vv`>sy{WhGyB!n7WoY&?SD7*S>zmKv++Dl7o?z>4#P3!#Gp(Q zGR$}4zLp6ZN;tvQzjcGTdUf{l-!Ts&cg)8o19g?KRoCg(PPCOp>SoHaT7j_G*8kN= zRS68iZ6cL|%xH1T65ai9XNbTq##JF2nqkPgBzejx+!~M3kq)^2yG!y9tQ&^Ocw>{z z0$ocm*VAOq6V~5QbHq}~niDmhk47nTW~ug~U@2Wx(_v=AOnR;LoL7*3t2CtW+*PI6 ze))xzyi6JCpHFE~_Mz(0Z@-}=^&NnQumJSa(+_^Q=v!1^Y@eb-r;996J-Cz%)3AHN zu7$%26X#Mq@J^OAOO#m3nsfLl1S`PqeAMUSfn8`oNb!w-7xRJ?4EMlYRnYF2U(9Ew z%ANXhFlx(tn9U z0q<(VGib9jK})FW^}mM<)HwftRAXm_?3a1^M16Fh|HHx2?qTixKNuVyd^!I=$M2V4 zcD~*?2b(fhWJLE_$Q!8lC6!)^3v2}z#s0?EJDRH|Y|Jx8dU{(zqaKO$+q~deIVQb- zlhMD)p2sh0OyE~jtAX_XpC0M`*dxCxH8G3H;U4^x&#vd=G5<(Bff-A2w`(8n+Bhu!jGJt~_%$><We0 zM{&Z&lPPoo;XWTsbhRN9blkH?5&ZdKLt6yOd6AJ1K{QTv|NqnU@u77lbQfkOzC!HC z=?k*ix44sE?QJ}`&ul4Dvm&F#f^3?}`=2m%`27~?RWQ|IYNKA7Q{D@_g=41K^z`2( zw6ErY^h-LiSVzu;*Z*y1AIJs?&rFEBm&_Duua*p+>5)yP;ghe( z-@NC4Cw~iq{rlDi*bGiLz9t{MFFu@V8&ey`tUnMe7FzIoS7y)9xW}V;4OP zmok|=Bh$9`VMFJ9L*Hp*5raUD+E~=f4;fECC>F9oD!e;NxxP>v2R?Ap0as>A!pn9> zQ=1dJ%poA`^abHr!akBd8C0));yP`HRhuB0+_t;!>aT$W@hQ+%O#oHn1w2V();@h#Z;m}PXlNxM{LC= z-Mb!Z7(t7l8Fi@Bqt!cIug?IRXk{6gwWLZuNpo)c9E*bRY*Ik6kj6?hZ>kSG))*S_ zVKmq#e;f9PCu-!Y4cc-_(#u$RFN#~9P5QUTaN%?}9I=uPdp?70_WpmKw9nqdsjKS) z0couYvI3EFT2AdgZz1pg1E{OCE5vkx2UV6=Z;LuybEnA{3T?W&B$)IDo6QIfs^Sv!=d8nBj+?Ne#Hg}3^) zEvCKti3Vbe5eb|$j()pawg|LSPb1&R2U3QD3ZGajo5A!28O?c`oX=$`X6LG#s<8{n zx6!F5U`WD1L()@=u!ofGk$~vo4&Sl#xkJ{H72LP?)R>h5S#PU{U2l8K7R|ORjxKD2 z1PC_Wu+o-7b5c()mHU)wb*;!97LTm60(7Fu($KElWbX%Ok@~1397)hQBzHmZNg@GsWZH*b^&HN zrP9#LYVcoW;$DqO{iouU8N(Nw@V~!8vgNlTQ5w=_DXvQh((R*7RDIH~83Y=(0c~<; z)sUdDx*f)yexEo48epmUDg&`g4j64)Zc!2YUy*U+jOMIJv+^~U#%<&bR!0>T$rj7NiBNcPjlV%qq62Uc+6cjKE&^u|_{Y5xQ=9!HT*l^qtxY`TS%#}DlVV#w?0n=@L% zpIX9^lj#8Gv)BTHJ&y?&pO8)5urnaKi= z(LPwr!~}Vob%LX^s5y+&!7|-dAm%a3~GQZ?qv|)wQTUYcBt;IkK0Pfr)`vsi29ew#)Neh*UanN0U5f zOo;;ymoYCjTfOHAW7(Zp=)8B~7ENYl8Zof1OlZmO=_2&rV*#~isbv}FMGz5gxEt-W{j|PqR6*mDYzFS_+{Pqrq(-(3QU)t4@}0w`N;Q zkB(PMmu+yIjZ-cx|E(h9x9XM^&s@H(VQNuvTK!ECijjug=*!I8tvW#NjrSL2H zX)a1_iE?r@sLz{LwTCMG&aZp_CzQ=ZCRzCi?SIMs9}W(W_V;W4KSxJLU-bXa@_UT_ zuMGgirWMmAHbD0p(fIbB7Kw!Pfwbf!OgO5Qe)L7b@4ja&uj=<)7GlKUuDvYg%-AEL zqk2C|85#DE$vu@sXA6KrU%CjI(^dH5<+w*SjblU){xk#D9=PW&>RXQ0v=j9g=tL7T zt48E2#iA}TOBpyi!F9*!3$hstnlc$Pi$t(x4`BBYnT;rlJO)eiTvojFC2ZeoR(7$_ zRk)1LXsc@4Rjkf(<{NJ1BI6`Zsj1|*9+`C@tTu?(vQlW@6?13m=79*T^~r7J`Mb$} z3Ju@$njl;LCCHfal=Ln#P>KCezf-8!N1lPWd)EGQ> za{It-m^85MWa|iFqZE%8s?R=o#lfN0WCN-&q9oztF@ro))v!g?6w!?$$x0HMi5IXW zpZDrl7R^6p&SJdLcB_B~3b%)r*jlS%opn*e*j{c`%)qVFjg3OJyVZxK_;)%>NniUa zl3z*2F z7w0{MN&fa*ujN}TDbPs8Qd=H@i7iB$zMq%4L@z}m-L}sN%OF+*qCQkpoiP|T-;CyZ zZmNU=m8-b9bu~>Rh$)ft8Sp-HM~xnjJ96`5K~68$OOBVkV_*7x3(th3F7MkBM(3Y^0r61^um)2 zj^=r~h%n82RAt8P7-3*V1|E6rFc*oN>!Q}wVStA79e4JSdW^q~^{*j2gd2y%k-#)} zpDF8|Dl3z-+06qeY0lPQC*TEsIZsn`2yptUzd2n4hsN+igR5sLvW@G>eICAL8bgY*;tIQ}E$kKesPCPCA(~mYj)`K<{z?+z=X6l`kiEfQou`R#^1G${j%7?r zP<7nY5A0*L{8~nUnAEmN!Dzyt6k^DoCqT_G->8u-(g%H%@Z!ZzIm>Mv20otAynSaw zanQ43(zUZ|LSi?ow96;tL^xQ@iO>P2^NcqLKP}7rTUJZ#F%`1(S9yN7Zx6vLT%Zp9ri-INBwflW-w(mEvG;GuR!Q@`ocz+C~o=-Hl8xI&A+?3@pCe%L43z( z;;;lWsmK_5qk^+>J^M&o_CTfR%?oxjEts5&H1REZ4k7#XmOjQgMT12x5kKRjGaxw;zo!)F`klVYoY3HjC{{#M|u;_{yVJ>LEUE`9ocmuG(-+3{NX8W0SO*W^R{moBMEk1N$wN0*U}!A6bA?)*wC|6v ze|-1;<*OgxoxOdvQJc2cg_!ws4a`elp1MEx_Tg?=dkG(5+A5`<_A`+{TvY>^^NTkZ zKfL`Ba5{VY>iY8R{4?NW46c1^Q*T4;{LK&7H?OYVzPkSI$Mg5^USE7$$L^Hu+|gnu zdTFni|QePNK_;9uYUaQ{q;?=duJup zpsr<%Y{IDXiVn;!-(RhY89-efv!-J8D!Y4fy~-NnT<+3VCeAIGey2j_B6~omD_*C%Q$-UYQMKhsS$G(dE zDC%`cS_8f!p_YF2nBlkD(VN!hl`a<*Hs*OF&vRJKk?al6<{#hZjRGeDZd}L0|G2J| zv|I)ZcS8*uCr|9C4L({lN!G;Eg{7VLFl+0I81JuyF(FA&KPuIVJ$v(}`i#DqyQH4Uhe{b6=ftH#`bZ0GvYM@X1c|ll8HDh=;%r zne(Q)AF~lTST!6fhVRIQ+{sv3)eKZz%z;%3yyl1NWSw5!p^!@h^`!^Y8Mx-ULY9$g z5y^#&+!pI2eaniBrB9DH!d-%Tt&yI-+U)IoP0p__qW6TRSOFY5#r&k-T)uY8)N6mm z+T6Rc#wZ^LJP%|2Zy{({#G0Ml$jOK0YTTx~#cSd>L z@b!Q*2H_SWrxWci_YKDwAg~ZGJ#yODN=&ooB}B*LYRRikz%{O=n`dZL<_Z8NnWz=l zALU~*HkB>2dL@2cLfC;OopTgs5sJx9SpY473HADQnZkM@96%2Jq57RfR0{u%I1hjb zFVA*}lv_Rjg2 zrfI@knO>Dq|1Fh2frQvKgFKIBRQ}W`8tG!i%6Mm;SzB)0LTGPk9wb-BqqeFg?JHY- z@tUVBxUAPf7fR|frt2Gx7=iLMr65pWL7(_Dk<3#j8@Q)@6xHAP#8lJUY|(wC=t=Xh0>*Y`eezJ?-IJ)TPz_ku^Z=3vmGdvQDS<#Yfa_HDDE z_HG-`+E~^STk?Fwump4cTQdsqaBnQ}F!Jrt9p*-G^O%;wx~5BJuF9}OSpuWk~W8w>5AO3Oyv%K^PpjxZp&HA;lAU(Q2+{> zO_+ZRpyVCZ8uix@c(rn}THdL~(h4qYcQC4v`73yH*{{oD%f#KP+qQ2W=${L8`G=#` zKiWmNwpV6;^gz|F#*=hA3-|Z)x_oM9%E*}|NDivR^IwMj{=sj5C5a&a+cV$%2Z^p5 z#sN*7;g7pevWNU9`5*s-j0#3?$*;d^Kg{9auRf$iWbCgVbX}~XPU>p6d<7?nlPb>6 z-W|)zn?=r~r**1tNssi%Z@)#6`u4>yzi1%c>+osqPmdMQKf|sFbYf`xnJ%1`ZB!U@ zRm#(EXL@aETOo1S(P6DtXq^xE2l^js|2Gsm$P`$YK{P?p!g9;A?tsEwaou6URzRX6i24Oo0eu1soWd$odJ?Yh?zLKh{=5>})Oo=seTXvHw9 z0+;{9g0z`rS;-1>>>|OYLYB{^?f{fq?6FEfXo?H>Yhr{OC;0~uCW6fR{M)PdKV1HJ z_5OYLzU{D58&Ka|y!-L;?B=^}I2rGccowq7c+0b~3O<`JR6yqPl`U3jTNp?nOA6H- z(gjI*cFPj-tsr?JCIy|55eJ`Wh$FZYx433ayuiYNl(3vB6yt?jx${!r*prmsG9stW z%7eH86ZOm`IP;4P3e{5XMn)%GmW7Z`>9gjZP&3*m=OV`{Ng7=&_ve6u@`QK+C5nYE zBYV$mt_7{n#Th4gI-l^2NP&p5k1Qs+;tW!H#rB^;EP{=|?z@Vrt10GWXD$oSd#!>F zx2X#C`cpRm&}`>O@4*-F1>BVmcQUE3gh+&6*5A&ulJvg%#jNVzyl#5rD`)4poffk& zVk;gv28WhYr}5ggeRo*+G)9kBdcXMWRG57>pBw?D${CTW}&_D%RGTkEW{uzE|5DBJMMG44HR5-daHDuth@7Vz#7E*exsMD)x+sEM1U$QQT@@u%H)OSce_u<7oWlc&^{4Jx9|2 zN+t!%Nzd^!ByjOG%EvwO>#ur-q7qhw`hTb8^RBacoy)#Yz$;sr-ecTDKcjPK_X+k8 zm(f*yKUco+a>uV2ZCO18D-P`8oBh{aPudjF)n)B>@cN+r$~ z^Q_k#wYZ(P-G{ov^`yT2wT6e0VJ4T|C z%xE?Nl>-bD(JS)&|D0|r;UT)XygB>k&8zF^yNh=>zrv%-tM~ukzene1@6N9Nee3yO zO`$sfhnmT2G0zgx1VltZ8n7&Cq?luo&F3A+KCkC}A%uP8B^lHnk9mj&hkq&}v}5}? zDwtp&HlgtXA$y~5V7Kx>SDja<>nEAdry9z7^WyaS;0f_n`LQTS#a7|;#X?ga8nUV0 z2NnD$QSmEoN1k=?{y-33Bg51)Q!)hPi}QCEcn7EJYtoEdxbD_O3UbfX5T2Jh3qJ(9 zL%19WCn&<`T$yfwp$$I7?jVHKboB=~tAd=rw_~uyTgASc_bPa173`-ulVweikMsE{ z84d=1p2r!RiDIE%yyagsr4>|;HPxr(`pMH8*gCIDo0p|KA}@F1jPF#prry2|Y+Kz- zr=~Tyo~8G6VfIj7Z~^m?QYqh=Xtern@>=!CX3AwrzH*W*)qs#5Y9eT#jtdTc2CgLP zSD1TP@wq0PcMmRPr+!NR1FHK4@@~W}%T|GEzpp?#E9TpR#_X~+e`jaQ3ZPmE@33TN z!Rto8`-!~No61iKbXrtEo8gmdF3*eov>FL`lFe)-Mm`$j<7HgHK} zwm*GvNwPz9wL@709WWhDb-1;sz}GEUItZ(nH{9q5+~=Q?m&SYSeQ|CI;gdhljrbZQ z1&w8tkBMWSY&Bc9Q#X8%zMPmL7UCpyX^jzC!3PzHuq4;V$en!j=WE9| zm{w^u;_6H^55#$;Y%^WCW;#}GDDez*ih1cO6GkkucwQ7NE7JuE8Ujjps-@4QWRh&M z{-p01Lbhs{1=H1Zpw^nZ#*pnbPg#JyJTyb(3i%;BXZuN#MLvvsR#|a^2_v78YkkV& zcyRu-g#Su?V^|}&Q7f60j260*2t|JB?9}e;lkGI>bsfikV#?l=k)$ocvMXA1rA^%x zy4krtKe?~ia{rx`2H5KAq!xOx=*J@$Z%bM^U`I;os+3EdF9NDSqFAP2u%{M#<&B-rfHwNVe}3PhfNtKra&c|%%G4Mqw!Q@3b|#Z(O-QoowaH$I*}Sx$)cDQ zbpm%zZG#(zjzQ2h)Gqj7)Trw=V>sI{2Iqexk&|8}K$Zx-e=eP}UGuhpvX1J}J zTefKSvNpk%2xv|c)zGtc%_5vuwL=hT%fs4Aw>BA}RXhmwunG+xoh)>vRH5BsKv(Y2 zs$F;TP^aBeGk0B`ujQ&;o~gEDrUTZ38u(>c1(Ss?OBLFIQT53Z1lFws5G_r)zr@lO zNa7#1xP^PFWyoKpvqt9q6)k*$jq?eUrgo%E{jVSj>S1ZILCFhsq3KZqL;FFiub!F> zRuVVN#g*6K(+UP(gn<==fpr9c#)CDI{&uDO?Y6_1w@n`x#rDnHn_3oB!<<|Q%{HqI zv(4AKC2Qx>{G84||I+a@shrs?Pie{Ij$0OgC!umW60}I9KA&bZ?=R>q?E=~O4F-e3 z;r>4ScQ6>#|2sS!4*oLSKic0P?CtFx?f+%4yE`}-{DlnG>g9pIxl$1SGI(@f^}+o~ zel^LansApdszzVIRTy08>spbi7@1;`EsJL7>;Au_$a)5bzS&pXZW{rD@S^tc=?l|? z>Cb`ziShIWDcFR4)IRuUX-ayV|EK@;&emrC>#hI&zoDbAdI+5KzWQbNH|REsqK#U% z$y=T!r{vu5)D4qlQgH^$KWg3osu*P!lfymjwQ)TkkNHQ^i*!v-o5c>l4$#xKaHQm~ z`d2JvRI>g%`xd~Zbi`84gl~^!MDzUAO<7Cx9IWD)g|E-Wjwj+*Dn_$mPKz=UV-K8O z1tGKn6T@LzhGyEp*v;|P+7KR--mqtG;=!QO-P{ZJ-DogT%Roa=XqJi6_0Dk~oNjb5 z*8K{&?#V2Z<^uWcH&}ss_N!{DxE_BcrTAYG^SiIlqd(=ZoBtOgW$W|%`fmyU-`gJ^ z`TT!)c(i};h5vt!UqEfbKsL`oEHBtN<&$aYIfB)BYcZlRT*r!n|BSb>x5vP9EZ4mf zDGM-M?-s~%FQ2Eb!YY?@I|vUr-G~Uy`L~6b=kR4jdcBRB7kNai$fJ~>J64SJ^9ks~ z5m>b0ANRD3ryK5e-gq!wm$<>|aEB_0Yob(Bb&M7wONC)HF5NgfKNB?6}rnO{dbu22`$+@U7THBG$z}5_4#I5ce-?zmm>Gao!-wlyWpE~ z?mO#--hICLMc)(6o0m=Uauom2v;2D>$DjSTT>cyJEaBPY5n|vH`EP&!Xt$>S5B3JT zU*x~f@%tU*zi)6s{k~$LNSV%}V|Ymi{u_iijIs+`IUoIt#ieF9_>mv*v=Ow~t`SPL z3OPRivGrtvD6T8=Nfy>0K@NSog;$rZ|5$79Pa+Y2LN@k?kc*#gxz&eLEw|Ri_VA_l z$7FJklFdKiO8Wyz=ufxaf`j@4ExO-Za(kLzxBRb3_ec})68V4ksDA%9Jlfwo`Xc{- zj^Cp>XI_XIE2nJUxG{9D6`e+UNxf~>kPTkb>FwRl`yQ?(eBygGnX_1Rq+M|@E>Foj z%r=8g1Lx-X1|iZ5OK&2Ui^9ltI-NKx3m&6Wj(X`aJcru3lK?X>L@8pCo|2pMOL$V! zV#3Nx_`dpRBj_^|he%kxvmCk>PqSHggfF<+)2|DWUci8ZGsywFJPK^L4)BEJVRcZJgpt>rYbI;<}5lHbD}WTpLY z%9?+g{l7On+;8mvgS{{N|8x94h5Wyk)L*xW=(WbPNk0|^6S5zR*-o8tXh3VrQcE!l zdFegPl|#_cw;d4#?s~hmd#KgC;exDc#cmsXZ>_$KFy;$dGg`*eHx98vvX>?Nb@N-G zJN_MYv38avx!{?R;ZRm{r8l0Hthl4;ii^QCubaWAA`^ukP~}0dBU#-3)*yVrV8(ei zv4nRXt>UNHa4cV=cSQQCi9_SX1273@&RB^#RI}KW#DjCW4EEE{=&~L^$Gk4X;gip< z{R7pOYOhCTr~eUrUBCRAzc%?VrqKvOdma<`p?^#Dzx{){|Hr}Li~jdnegXL}7#$aU z8DsPYB;jifv{)E(4^DxYg{f~EUk9YrH8vnI-xL5c8KREc}|MgjZHmA@AA)AT|Y`W=%KEmQp z|0#;wRM4cU;KMT8BI7Ud)sN)#MI#w` zO#70R^Snp;-E1BCV+&`-^dIME*R_-ntMFt44a0?fc>Qw*#`V$RKFeZ+iG!`R`<^X` z*Y1n>8UD5M|3^!G)vuHP5BCRqb^HJD@bHWM@ALc|`ES$XhFhz60PB3sb z$H(DTXW2rx+CAJI?(bKva5gWL*vZSqTUy+P$UZLUWX7`crl9dH&n6vH^L?mVT8K*Y z=Xt??knFPHGg>Tkl9dj~FW+4QU|cOX1e=+PI_sFKP3-{npvqNVNs-JbCcqJn= znT`;<>1OtgGh#(D??0T(`!zD}ueBh*zr3>7iDOY9E*WD9)|wS}tSETG2%|;HSz(r- z`9>1SN?eCHmQa_3OYqo}Ig9z2SEE{OHo6w>S3IXPb;NGQf~HKyPT)^YXZ@L)6!)aq zs!s2bFQzmhjPh|mHZ1~NxelumX4+us76Jb4z(R8#e5Yndfh)x|Jhb3KrC+z)m7)~& zI;7s;GM@h3WQz;+^@8*~LK~EVm1ezh)**FGs)r~D`0dqf?N;3CYL(MMZJh2#wlHo- z8`!*^EpRnj8j>;PDd`2Q9QS!lyd~^gYfuu> z6k*d)5KNr$^C{&S&n8x)&P3+$1hwEHWzQ|ok_$h>^SycU+xIpv9|K+6ru8 zi2~o1Q-n5UX|8&6bHxiSn3MY{kEaCxWD?*(Spi)j%*%}3-yo(FOjaLo9`LK{A#L2p+h&{KCkE-Bahv|_`9?jL<74}(K@z~2J73RD7_H#!jP~}F5rQha|HJ0n&hz1AWJ!s^MXNxu}D*K4LvDW+bVr|7oYC# z9i6z@4!tCszclkj;zlyGa}ZFyEXm1O^SO9H?S-;XbCg6eg~}kOv!Y!6Guv6%6}8TqVv%KKLF3zR&o7KO4I1Lji)a!@o_CJDWB{g3 zOZHN8u3jfp$46&1eBRQJ9VpG{$H$=M0`JDmPbO@IE2#dX&y({hi*I%6K>b<=JZi~5 zid750tX>P4Hf*5as5a~=y;fj_Bq%znJ@h1*ihIJb5ocJpK~8A_Ix?0>vmScSpjwe6 zBapA49QPF2$pXKF5;1)^r-Uv!4Ej@CBt5lrdYX6k`T#A`Z{V49vEUi0d?^W)B(E3pTE0A z%l36ii*lZyr;KKr)v5PUoaK>(7LmjzQLNhdRm&_otuV=Nzx6`w*SR~lEE8#Ve)STZ zJB>vB5?|};OLPJo}au$~d1Ysl=&0ZBVf5FNPM;L^X+W zY@;i`z%!zs0nf>deKV&L*^g!|ibWaBq2-iHf}j(^OUuy~+G>ust>uAnK~yp?&7oJN(g)zh{*=VLKNEVIT3I;N{MeDu)>| zd(GhOP}v<#=cdkujy`ZXtBx7yk_S*#F!jZXd1gDwNWw<*35o|uIIK&6){{~gzi4RY zOD5`xRaciY4D6_P$BL1V%!oniVWgkcDi{KM{idQ!Plke<@z4gXZ4FuX4i$M^1bH&$+egm0RN0CFx_*dCj6llCtCx6d1 za3IoJfXnA)RU!+uSL8(nQ?mf&=UD{|mM-!jZ5G`oG`*(_3Ct&BcdS4`(I}sZh;5V} z7dtH50VkMp#}rrD!CrQFRu*FC8U7VHeMY8FT>Vk5OXVwarQ+Tx#vUAd8{xXME7W(g z4p6Z7SRC)MjG;h_p;-KE8;zr88IQGChh`e}*lUf)1n}l^%6L(A^)VNcCH=~Lfg(S# z_E9{$desQ9oJd5Ir08kx4_|B7GZWkqnHuPop-r`V_x|P;o=?D(056g2y6G?!k&&}E zZ}jPMKV^j-OD+;nMbP%8IPE+|+=JMilHO@&I)z@-F6A^bB+?W0R{sgOYY~0KsyoM` zGDRB+-(D3VC;+2Q!9LmifAGEf0-}i@Sgn)6t=aI9hn!NL|`2u=NY2A>ZAIwDb#x#IdWgYLW?RORCvC_r{ z@vphDt>%#nJdC;Y_qS;ft+LTW1aqjaIlSF8%cXx`hq-zQHF`Og0Wiu?kwme6+y&A# zJa%LuTb_n7kSh<}p&Np$pvgBhRpNNj+wxqJ-BxMbZ}+V2t*1I2lJ;@QAvR_r}>%2yYimL8;~_V z2-5-QYUQbIL8Ft@P8aJ!f5;vUa5HzSn4Fa~=iaWYzii)2UCB9{nx5}rwGgOo@Ie1D za&dXLPbhj$@N5Eirh36_gRWFv5z>NrRx9`x4O{qq-(ki1-M+ufUDsFF5aQ!<_y}AM z+i^Lp<8s(#l&Q3NMziaZmdp_gDUqz;VlD}na?Xf|<9Q)Tg4RGSerfaVb|q%>?2bx) zXD)!qj4qT&uKjVq_F4*4zfz4gXN3d-zSNEhv}8)cHxvMIP|55g2F1KZ!4foBlG{w& zr!1K;)SD;($O|s4##_v@Z6XC;Q7Kdk7Bhui#_q|*r6D4dWS)af?U^YUu5BeWRbLl; zGJ$&Iicpajibwf4LTtfe;=F;UtB8m2)i?RLPJ7ov2W^av?wiZkNFgJMb7{!>SNQk} z2rGfIs_~5G)x8lE7MBZIvRR+}kc-R=b{oF+SDmG`@$?{4aV3{%+hi*4*&RbIfMyFK zvWZYL6N@ZkG2Q^`6_9XQ%yYGhM+IkN^!0c~-dHA}zDrol@hZ#cas`vDggJEJ!3-)D?o)S(585an_e;?4YZ{R1A79kRsoSqMNF8$2GC-$;<~QMS)%lHP zGdcwmY?{fWU`kdYWkF$&j+M5pwoYYAo3Vt?XFYJA?9J#$ zKAX>a=pQiUlPN27IpjN*ZtH(aX@FPvQHB>t#xlY)i=LR5`5bnvei9jMxh}-#5?Z%8 ztC~38SIh!+K-dg3WTLi?cE&0fIge>dNlIA=$6jlUAindT=?aN??V!?~xF0zeNI*}w{B`an; zW7m>04nVx)LDK-nf3pb{qF1rv`>9~Vx$B$XvIZlG>z14h>j)%~Nj=eIc| zGNObU<6sRJZOF3mMju|VgyiXb!eMt6Oy(k!Tq!(iV&+-Gige*hhj+YOpy(-uIeM6y z1BE!zqk*$pIxnYhDa5B} zf~e)8p28ZL(T_Ih1{bbA>`Y02p%lEb;FZ^d`c|zqz0zDzjd^r>Z`XOzMC=9Ic+oNr z-fM(?=wbn%JH}q zW7JaS5)qKh1Z}Bh1A4oI0M0+naM>v!1^@t4Y#;>V(1lT*78hf`wNiX$B7xv3Sl*dY zc+vgjV_DOD?fF%jz-TdENek+eGfAl0C2&h!usmI${)*C%{h$zeuAOIKg$tTQA%zJf z3|Z1q%H>phCe#r?r;cj)uhqT;odm`g+zLKank{Njb=##z zrU19dXj$8F8MQsR8!lOiR{#{n7S(B`CYYJ?$p`BzY#t)LWf(I)nbvVu&z=BlfHP9s zgok>+P~&jz_XSF)Up`CzB*+MTFd!q_kvNywGY!!IF6lw%JlEr4Vb# zGK{gB=h3(jaDfiesMC@0#HtKxUqhRMa)bx7oL{j=JbHI3xKK5_|zcZ{Fv zq+Rzk2YAgB{h_D1^(%Bv^rfe{p^hf6Lq;9ht;s`e^f(^&YPzaZo|FQh4g34*sai3G zCND3sU(m}%#=tY*5d>sF3P2w#X6`T|tyakZbF5muRq~)>DB7kynWwZ+TMlka;8vlG zr#LAX|DG~(A(i5#mUK)DqNY_uU=cH-P^naug7BHzMQ|y%K}`F|X&*t0kkgKCe4*Z7 zu?hQFAqn@FTGO;~d0>nvSjz5bR-!FpH0LSES(MC}oPv0b&86#k*|iUX{^o}|7p(1#mfeMZ*}1G99uZjJghY(;Tz=ClGPVHS~JhkTYd&n-wmr=!Qv&<#R|{&@AK4O7rh|I*DW~0PfZyKyfDmWp+=HZEtOkPBH}X=hLFc7FFGptX zRgrh-a2L-GSLH&+(^S z2Uh*id#Pj2Uww?3loyw#@Xx)B3VahWcop$H=>8doie4Y+v-Xmu&gB!rHh}}sAWCeD zP!EK_FmrB+U2}uveHQPYU0&GmwVDGVkIMQb22Llxp%Y1dC8fBc_y0?ZtiBj(1C#Sn z#>$JA@-nKjUCY}Jq8yX{MB3{HEtD-; zg;u0?%13lW<5bL(PszuZc`P1*XM$BzkWEVR<_M!GK%`fHG{d}<#&O4`PJ8Ce@KMxs zve5l3AR^>^Ank83MAMc4Y|G(5~@U+TNxl58a|ZX0^U3tLK9B)zZEH-D(b94x%kiUA4}_-*$>Fjr|OM_|?}JW>K3Mb!_1D9NBeWJM&v1g)#AB z9&+{FnOAnfc@~be$pI-W?YGL+JJKLQ;%vZt^wco zkqU-;I9~zC{!GlX@{)S>ylPEu+2XZgD=28HM^Tj-DvVJb_HV!KbT#yPsB71&^|(S` zp+WG!VCpsR)};O|TU_Y?EaNX&Umb;s?MifmRox9&>Z}X>7IRZ$U*GeBP3E*ne45(F zYwYiCnpub-`a@jLYnrCutrYAzvhAX=ZrFxQ7wm`5aRrlE>$-+gq3FC?j++Z->D0BB zinM^0yz|Qb>F>#`ZbNPVZj~4_J2@ZA2(zcQO^Ist|J__eo6r`kgWp}H3?pW2F zr;a&ar^^j%DO-*WB2~g+RHeS-Ik;ZPsF!BCGfAeB17c z0Qz&n3l^7-{O;3LwRs6m-id@=L4)Nfbx3bSv*ey9<@7CNp!A{ut&Cc06BM&-qX=_Z z`sYh4h>*BG8ZG&FG%8kz5q9=7*+xJsYl?^hspy$DTREV|o|Oq0lXaCn_Js@QayBN~l^#)y_q0}6Sak{K=c z4?iC6e~W>@!9{G^m{4VJG;IL77murnOoc38^Mc*eGz~rs?<^t9XslcKn=16_TIWE* zAS<~w&%EKXBw|eTbDQOwmL-j+WR#D=GSe4ilh5)L%!3l0B}Kw6g^6wSa0VKnufJAZ zc{bUC3}ny?jLF*M&EO0QtKN~R(O=Cob!NPTPhYYU-FG}{7T6?0@KItK1@&7@UaH+x ziYf&@+6IEj@dGEv3RM6Q#c*djE!fY|h-Zmsm$vuy71cuhVA`;szu{Q|<$5%VVS-l4 z?HeYI>XkN9CcYn`dX1DZ4VUbZR`6>1*zo-KnH5f)j$m74G7^~n7s4I{A-Jm1rEL=wzCqd0aH7yW zHh`)xG*I>T75MnAWn6AcLsAL5PBsr&(k!8=$TZ#wEon}b-T~@-Is#_8eBNB3q&KTF zN*d?&x^=+AVixkVTD?1)kHqhDg=8kHWHMRWdmOWr8Ecw{fb*sU2dC8|&`4zQlFOWy z@zlrS|7Y*tyW7T*ePMY1_NTzhWKPGuLRpe;8Sgh|J&xn<_U^>-iJjTcIeYJufk;SV znSsJ>KlVH9713FXvqgHs&i zN#Pu(F`JnBTFp#>Or5@0%iIi3Vsr;QaXoMy{ZX8h;GT>El_FIy|L9YMLRYoAWNodw43#$7r`mJG?sf6a*KQ?NWyON63~=aOa4k#?gm97) z)vEC>@TDz+6m*U-3N8{IPyNG76iueDBO2g4L>6An6fI;es;c^$V5mHzLY>i`pam)o z8$1Azq8(v;wF0UVS6WVOrAWNl*NlXbeV3&FC@i!M~! zjb(|ny^&-N1X*rHjwo4bPDL?`MZ37Ofdw+omKMmAnp~jKq3toATnq2|HyElW$9UpP zk9(hs%7W}Pv$tBqF`m3r4kHmtg_8i8KxV(*vH9&T*tLFF&vd#sZ%`Z?!2uY~Ky(CI z2@eJ<;Kv@S52cx+h=oC;J5(Z-eJMoMNg|)`9VMF-UM9v9VQJEOy3Z4ubPFrV?fx8_&>@XSRiC2s1*y97PF<>W~;ZV@4$+4!Y6sO@M_9Q(Jtw4VoUEA@A)BIW+cUu)0|Gj;u{4UuiZy3Tl$+bJ^Oy{FfjEWHv zl$rl8;v<;6zdF-s8HNS6ENahro0`2-JpmssFaBQ;;u(w*ARmT=p}wj{G)~|x%3v0N zVP2c0sZEed;!ss7Kf5Gi`8*SNWz^nOqj0m97AGtI8RQM#A+zJ3+ ziKDBb^(4$;FT)@xM%#Fv0cVViDsqSdE9Qx!`8#J%WHkChROE|KjWUPZNAhxL(U3L!TNEE~}_o`6$%E(8>%P{2Hj)gjPZ zbVwcTCD8-d2!a3X|F@W@@D4^XG@6!!Waz+8lZZ{{qh5e#Dgg1GQijOh zYaGmHD3NBUdz#iPEVb>#5kRMIFaY@cxmUcivt)~pQ*>BrQKE-ynfWfoj+!Ca zOg~Kk3_}rM6~-F(xj}Aav*=)WaNzA4^FU^C-gv1tSzOfkpQ`LEE_AD^NXKeqv9X(H zUs+6jBR+B#9$8HT7E?VHWb1kXVRq@<4!*hYEm{<+)-j$130h0TiU(cLVVrGsdL-A% zij<%+A{Xi1kwsSitRUqp9i1DF6?%WVjnWT^(6i2dCU~A+yrx=T);rv7l=^d-#}6hv zlOKi7IpU(W^ozafJ#D!96G9;(!hAJf1C>HZTYgIYoEo9Fq}r}dhyqkk5C+1Cwr4~W z&CE+>28WexHHV#Drz=o6q7=?fviO32ig8>r4Hj9r*2VwT+By-=RA@b}lztFi`tLKN za{k%!AysbtMBA3P3DH?uMLmo9tS4Gyw|uwii+?v9AqJ%#MyaVr&dt1#$XgvI7R>xJWoQAtTHawk+OnFepd;lvW{}>NRms|l-a>lY ztXdkg<7nmCakRwjIQj~+qgZG2>^NF-b{ut^9Y@Q|j-w@J$5D&fQP@Uvi8GtWEYgxF z>w~BK2MSJJ%DpH1T`HX7>vQmwrYPWf+)Tnb!y^0~lFs2*IJ~&J5_FAWehL{Qg_?@< zRaWHj#p5~3z63B$c>~qo88TD0qUp)ssRy3PA$aadf>MZz&ssU?KsFyHL7L%fCXnb1 z(la$IHuXxsyu6i1U0Zon-^!yUTY1#n%A6=?Jj{!yrUDu)GA*BYFhFr;>i&~3o>pO;0`%QxXV%5WcsCxJ=4-wCu8$Kw~{6{y~mLgup*=n2%vLe0< zn3a^&8BqcMbqV5pA25mYzstn=uS*dRY}$c~bkNfRrLspt{~kuna_eky>MYReBAt25v>{6z1*qJz%qAx;nz>g{ z=a}EAJ{*L^TmvBqex4;LHr0sKcIds`ksaqqdeNbVHaV zc%DcPjw)W?41tx+vIe!j6l_7=#7mCtH4F(bLmR}QSf?)m4=o^vcH~?h_N|$Ej}mnM z8o@A*v|B)lGs5%up~}?EnN4#=_83_xJJ>4b7+IJGx2@?_F!s6RG?`OOad=ui)AHHG zb@93xRY}L<$wjCF4#hz-hec^G1V)pz5Tx8Rd*WX;Ggk2Ci>uw5oTqAa^uy{ zR|4N&Rrnl?<_sj*UZmh25u~&9z?B$94b_Dclo>eMgY9)}Y>OsJ?njd}8xTJp`NdcX zHRYEZhPp0wu;jF8b(XF56E;e!2+~(EOx<ynbbk>Zd$cy%mTnd$ad;I%D&)Ilf7k z=P=FrtCbXUrcxBlNyHYsmFN@er6jtGVw73Cqyz_Je(czrV#@aTpKT(NiohELV`eym z@IOlkX8gx)I)!|$k*=xl^BUAEPN@?4dr#+XxubH{?qZm{TBMND=C>L2DUG8bV(}u2 zxX6oxDExu%v;5xzUTq}km3qObs_~Vj;v6nirD|nQU6K^_z4q{#nL2nQqAWrdC6jae z=wj%VEYDPh99&JV+kBt_ODnuw_$S+TDPWc7vxfGE36+P&4+)oR?~?23oQ3#4G2$NZ z58(CXwZ;$?&uaiDU_xMk#`73ZRcHr*FroU$Iu|8?k=dC0TUIG;~#b||J zz80w_pbWkFuhugs6Q8T@jrM*N7EwGWkU4p6cK1Zo6mNRW&|9v7P@E{=2YF{%q8(9xE_Qus+|uR-A**1X zDD%@R94cVFo(di=>&Y?*d_SQ8Gb9 zT~6sUPR6b>C5=TUC!Sdyxn^EVRKkS5N57$fy_ev}=q%gv7#{!5H(mZeBJ%hOAsP8W zMj7%p7ZXF^9#fw%y()WdQEzd^6x9<|O_Xvgyp_z0`M1b!w39+LuH_8Tsf=N*)X^fMucIT)ueB+;lRufoX^-BXvReaf zRi9`6+-q68vPKYbAjRd^pMUn~U2yWE|6<@3MPmgA#_s0Q0PCvHi&{^qrJ)b`w$*j$ zd7-MIw`v%VxyC)G%$FWjt*a1)UP~{mN?|5y`Al$-oxxABjGMZlZK?bc1K{CtP3`*tuzU#`(6=TEoEy&apm`49Z zM4ou=20Q#5dZJ7P-okWeh8PSXgC{!x$a9AkrbGRz06utwRFJ)1hKR{4(G+C0C*TWb zUgN&h@b?8M)##wm6@S~Nc1e33p;;P3hUi}QGI56&d$OBnFzqeiEMB&be!t&8Iyeyj z?f3h||MrjekN!3|I6gS&@9*y)AN;L9?Dq$Qzk&XGo9a$;${_h$f91N0jr&HDLq^!* z%eswE2^z=IWXkfO1YGWLVbfVom=n#H6Ro4PcmjS!NXB))MaoVIQZT}pQAS{@sP=y2 zQiNdu?{E}?5kXMk6377RbO*RgoPaNx#q=|l#^71+rzl3W_cLO^6W)6ji)F7wkFOqY z7xZ?)7ZG$_9QF)gtK_SRvHJBNLNw#YUG{+Mf4D!`-!HBI;c&bDH<2D>{lhe+dzlb; zEhf=5Vhuu|G%!5~gX165vb-#2Atw#jv6@NV`2woS?s{oDf6WMFXrk_{?B7l@$)qoixHKWrtSCzg zCqli<6{p5>EbJ4dF0K%GLnj0fG zA5d{u;hDH3Mb^|kg?{d-tlK~yaMeTu0#h@nY~DGBbB!~^60eBhIDR*0S2(0*-X{Ph zbWRXR`3Ig!A^zx{L=AiXCaa*cBE09=K4*NxnWEs9&S%z5l=SQYPkT3N{Clq;MdFn0 z)hT>@%K~2jox6EH$xhQnwap^)ndF-|5xM9>1a3BCvS(iPfy8-gO8KWpJt1Z?S+O zCbWEbQ9FvUCBW+BY=v;tpIQsp_A-VdcUBe6-~?UGIVF3eD6u7`FxWsOpLt|L%~C)3frREDb6s*zib&^S;RmazKY|qb zQ3(1!xc1R!#n)&wnoodthsX#EpSow(m!A5tD+&Tnu;GDcfTnT8ghR6(sKzJ*cCGDG zFc;&AAEP@I14dwgY!cn3`O|0JrvX)UayF=s*&r(Pb@c!q^ zL2uai`yS|>!4!&+))At;U*{vFjsZROUz3&h!@i*e?uNVU{*84{IJTyFOa2X}hNSMa`_owi9reeIp2l(RSgrUwF=mbGYiX zv4`P7=S`uiWhV|w?o8cPYU#hexc+$g?)CY{%hR{#1{rZ!{)yn3J)6X;e2>N_1?%m? zy}tcX6uJ`AMqrR6I7F9lhDywwUA(#Y@b;tN>GbXS_0{Rw26)mJT)DYKmBM!Wf?mtp zr(ZB-w!)^m^TVt2_m}54=hq*v&)@&^;_Uq6FYm5zij64xNSIVR-JX1nar;G;c34VYIwb<%v`w zdK#_BPT*Iih&C%;bDCR=is<-I^izTv4sd(|ZqBaiI=%AlqT+Pb?lO@xpnsRaA&T2W z;l#)pc@rh`Pb&V5Eqf|vW|0@0L~(DdxQrPLT^UQ;S72D6_QX_@EWX z0E7gmMIr8k(>HJG_v*}T5hrgErEr4urH~G`e}muP34NEG6N2;0oI4!PXEGK^<#LnO zY36d9=`a;16*oWSB7FaTCnCNIcd?49vd8V#H94!WCa=Rm7S0(KZFY$s&Cw_w`!kqU zwVN*J-k9!<(s3yR!6}?5FbKY#-QY7VpPFQ;jf`yU8k`QVSq_zpUoMn#&j$y~Jj2Wg zFyibwo=N{@=h6LGY@@3_vj_5OtIAaLMTb50pT;y^`9j|*L$#f`y6ClY7j4p=CGzTz zYVMNN!Bwx`)A$}P^b|}Ee&9-;4^-0%Jc9$uWxhy*1bRor;v6xxcR-qewi;@;Zv*I~LLyQ{k zG}Q;7+Wa|L5!YJ!Sz5x$Iny$)>AZaQlY<3E_O|aM(27JUdQ^v>?688`*2X8+wR->0 zGn>CYM6C?#sIA6$7(Z6lS*?hds+OB*>G8+Cdrp-gH#d2ConXGsOLL+gnI}3Ll(n&X z=3#e{q7(31gmlJa@s3FFQYSNo{WXjEWinG|bEeZ1kYI*ReY?Vo&oX6R=He$ulIx2L5 z#{GV4gZ*u#dizfu`e+sF&qn+2!QuX~ZT~qqKI|WF?LRk>R<{3K%LSR!cwFhf>#`cH zv`TBVK$PW6){%`Cf-YmlwOz7Rdqgj59$R7D)6OOBORC*V>> zDU{pTnf|?GL|esoc7s}dce>_&R-0V;8dHYllvk%V7vItz*h>CGdBj|H8))|bDcb)J z`bYh({NF@coBVg*M#z`|O(I?ua!C3m?oc}I1`T&9MT6SX9^kkqYbI4^qrYj{(Q5sx zkcp&>g1bu@HOtbUFx z!GmnT`!Xk`4@>YP_4a&v_KZ zS^q~z#rxlbqwV_NNGhypxmsPTR4q`2dDXB$OK0$M-CB!w>zXRRoT0XA z98q7Dl@r*wmdzJ-Swfr`{?*w6a7l-+J!TO3R)eG$E8v|h^SpkfSU4oEu!?>5~TAH6|f&ZP&mIx z$uu??3&m{m+I{ zVMXa-FFv*uk=$HpZo_DiJGGHEr9z8es(G746HP$~CG2Nanow z@)dAc0L0N43Am85XQ)f;6Lg0NdyfJg3!EQbVpM{6NC~=TWuH#;DIc*sl|Z@j% zQ_O<7^oxD!^qsY!9qJaH%L~7oBYXu1Pr&uf>HC`xS0As>-d|kZfJn$iKm!t`43K#O za3Vt%X6`3Fz)xTn5gUL;iDDUJJ^BNM63Ql`iY%Au*&ou|<__N?8&F2#&Zr6W98e4* z!4K8AI8#j74^&@O3nLfl8kd`D2pSeuqafcHVqS`29Mk{bjyWl$2(Y`x8cqeeP@Ft% zrj3HqaZQ_|%XRgHaH1tt;3YIplwpgBQq2mj!Yc&ze*bG>Ygs4q#>H0Uo?GRAUhPKT zv<#~m*_5+mR^bZ%jvagttLxu{=cDkfx_E6lwN^R1uEl#f*POaLFgF;ox(;-D-L>|7 z&PRV8&d&|hmiB+n7e(0xy2A`}JHZvaVZR%nxW@aRHMjsYz5gE_9Te?<5BIn4e;Y{- z``?ntXf0csb3ULyK#f>gi%UQ*Ue@6i;H35y90RJ>zYa~k_i>8i6cO5E>9Pg@P4EBx zK`H*n;AngQyOG4FRfxt>k}E4&RPrFk^U%u-0H2D#!O2VDO;CbJ6nL(f_$Y}iqaitq zRpFPwgZDHqr{Sh`Vfe?~h-T?5&U4fdh@%l4L6Nbgu^#=MRu zhzdQ(=se>K@4^fs+b-IhQ=KVyA`sY8y9T1CjOQ>0-v9G=>WIcKDXB4%)OLZ_Ww1Z2Nzwf2Sw> z|0)|mP>N~9Fj;7BD>BmgcpQDI`pV#>ek9F*f9I+uyqwd>_{=#F^JE4SI6>hR4*!F5fk;os0(h1nhvwiap?wMSsK!ykjt+J~ zAM65kqxeL`$(%DhgW{$!UVsqAh#~Nw0Ve1R@9_T)6DlK?Q7nTFK!POvzlbe>!3fDm zl_x-P0Y(dOrr(==MRLb|x-I-O8UswqT_VxdE^&x%V3aUg&Os65pVg)9HG^zU!Lw}R zoB#(|gIY}`ezY&lCC40kuqL))vr6MCRjDS$4c2gW;+>C)k49t5 z4QkD+B2N(m>f47TGq#X=F2IS7E|J%{M+J!;>t@&J^0e5~rA`SW8gNB%p~O;oBs0(6 zI0}kGS|J`<%n-50Qbfj>%)pyh;NnW#!A3X{ka(|tz7l1Xz|GofF(B=SjJCF|T7(GX zc{zDRfR4U?7qLZVhAr;JsAGCodkEC{5NZQ&DlIZ92W?HA%BBb~0uvg`KE-1I!P(`N zlvc{5gMxqEU_ta>yllj1KHgUE+f$*-Cb4R_sa^{-aG^EmN{F_b>zS)Wd6LUd>Ww_b zaTG+V&GL&<0Pmv^l`~~s@dQYCMX`DK;_d-56!KoDLc2H<{}ORzu2gwB9KyWn2PTJt z{?ORsfOlV@OuK~akXfWrf|M)53=9=2H@d3JTagzZuxG#gjkC;z8-vZ`O}^MBkc{92fqYze_tSYW&8sO+*p>UdhA+BEf+@jC^apCs z+tQup*zDbtw_Z}TR7-emxk{oR8?E7xY8KyWi>((Lv`hI~vek9F(h9RL&Sb9saEBMt z9&MG5c8bgrn=p;gCx#N~)n26+NV6sVqqyOU#0yR(e{F@$TIAO?2PJ7=|O| zixQE2*YiX5JeoDFY1pI_a@%{sld6MuGc9ei$PQeU^ zsJHWE=ZO;epe7$6==XUrV$keqgd4X20@CbRWYOhgK#);5*#^@dqfJeWffMph*N{YzQ1|E!KMa1hl1_@&lDpSBp*(yu}ngzL%tzF!w zOZ=1|6w2Hvf@(uF5f7F>CwFZypogaA)bM7 zj8qU&EsblK+X0~bHdVz6olAA(WXA_i3&s|9i}~SxDZ9lL1$E>44;1U< zU;ia4dg@8yzl7TNh^V z(>7l51wh+2p6-SKZR;4UW=Cxk1XnriQM=5dXSD5Fa|!Vscmq%2(V$t%T9@11EjpQ$ zFh#^Erj}ecqwiWvZau%sGwaVk#ne^PCif4N6Zs2Z_}{4vGr2ZRy;=UFG{%b=T0Z-O8(b?t!umwg$a_)k5;N%cl?h+WEo3}tt#KzN=%JJ@B~~V z1VS88fD@tXA!1>DIWD-O1PIiM^mej$`-1M>$$r%T?M<*CJjMjfFhL+h3`Vhd)*~p5 zqX61SScb8N{3^Sw5w)bQAFF%v2|x**6O`XBs(T=u02(EeSeb;}zM%Rtjy?yYg>ud& zIF9*$RUsi~XYi9@;_-6O@Bf{5QUFB&>oyn+LZboC^#QHbvQo<)_}!dc;gH(+H)`1lJ3F2U+)q&g zvLl$9+j)4*91K$};w-B#41VZ*X1OLyhXL@kccU89dj%;HAt}8Q39eylZ#AuU&(1Z2EEVy9>cxEB zmf3#W?0VQ}?2zvUE~vJZ*HthWl@J(9a8L#;@*Bpy8nUS9tkZL?kUEf}f;);Eq^JZB z>v%I=b+XAxCKg_kuSA(2M&#ulo25#^?Wvzw6y*~eVdHVL;1Rml1{6z4~Mo}3@ zC=S&XsF@0vA@)a6NCYqzD@)iOaW%cfjOrx8)9Ksu>#NhV4e+FQ-TVrriZL;I%?xE> z!+%8!2VWu*x0n}&57y!;#T4fWr(D#-*a8l5Zj7co<}*7|Y1E70>^+VVu(mqg*3R@z?YJ{qf>;bAzQZuDi8Xqu@Ptbw*v4HO)3TzCJ&De|}?7*$mfp)wbmP z_4!YyAKu)2e1HD)#kf^yAr^cOPCq+*~ubarQ$i zF4_!Y6(Kn}9z&B#oUAm?w=bxAocaY*<{IH&KfF4Be|dg$&R59$e_ouOfBfa$b*U?? z9lk)d(~+P|wzRIHKJULf;MU_sL)-Q`%u~n$H)A81YL%Gz!w))P* z9YbE1$`IA}WcLWwvpFoORu4p-$MMW>f(H%+(Z)F3Mm_T*Wt;Y2OR=v@*o+$W&yki&vn z4U~Ux!OR^bdvP?{GqSg4#qih@+)x_ZKWK;MD)zL8V++>GS!;N6h{gt`YCb~Ju0h=C zI{4)|%Kc-oYbsNf)VgwQ>H~8&MG1?f=WA~^XLA_$Xd1b7F3q>d;KK<@m``zVi&!Q5 zVMJQhCWu`NTC28C+O@d1MXn-q`en>m->?(QRQIA;aLzqzAR%LbiQ$#5HkBCiwk?k{DRRkH! zt(7#DoPC3^OF?y%C=HCl8PQ};W935u)&+iSsLNI0$I7t4iGSPy#<<4PwoIuJ#<+pn z(lEvu-3l0E_mV9Gfs3iD{J)-;e96SSvY5VnA&ihvO2au9#D+~mMoQRtKot<>K8j-y z#E?!UGYAG#X?UT-pfrMzuYv`hwVB}*$9S^1PPvpn!wF@?fGrV1r7FvbW7B>bWZ#8( zYfeVQ|5xmrxy%-*M!B|I-o-{SX`5I^QCE+-WgvB@J&#OH&%L1W$+z9s-CXxdDw|ocAt}}K~lrW{9 zhFGjIg;8V$wg`9;hRRX4ZQ0^hdcWXMN<3DXTcKXq(sEi7o5*o^4$(`7c`B^QOu#6+UqWxhOd; z5Ho(MB=sPEDck*KU8zz2uLAt7QiJ>-_KynjzX!*M{oz*rZz8P||DiqBsVmaHICN&> zwnrC9&?Ub<{1m+vTcA+1gCF-56UO_>L9I3&C4OK#Pf(7GWpW=E``6( zQHGvX@S~CMY6{K8^9tMsafF1w(ibo~IzUNaFLj6WOB;H!jZT{1%-dLt^)DpmDgvPC z{b$hM#((}=X}R~GvIACk#FqTYMs3?gLGrj?ZPo!NrtDfTu1>%uPPjOfqV7!pzGJwv zX`_P~Vk8Qrd5&^0`p1#<_bL07F-Rszxu{tlaQ3rI_fC1-Qf-^srnd4QN{xA`ZJBAb|@UK@_Y7rR_qk4h(NA`oE*pR{qbF z^7a7oe|S*B{~a9lxA^ZHNncn0H$|_SVNo*a1(+Z#WqDB`D?J#Juts###+w(qig-8U8xfj`fT(-c*fb#UYF@-;SrU?SJjYbF$7h} zHgUQ#k7YX2de?cU%N3tTrZ~YwwLW)(P{0#r#mfvAL1My0Nsd}*{L}{9zGQ8_3>&f; z@5{`TJ}kkKJO=0U$G2zCUs$E7+W%96#&I;6GBW_wl9zxD`~Si5erf+7?r+b38%c$u zMmFrl2Y|gFcYZ}El~DFkBBCtIHLfr8CnzaTmYpB>fWJ~)sOp_QCCHb|uFYbqMOeO? z80hW80EQ6_@EszH%4$mCkk=9=--_)IiZSj}9F~LK`@j+6x;~h7_EsVl0rcw&D&kSQ zVmdl`tcWfxd?hu}%wJNtri+;smT~dVP%Ja(O1Wz(&48{?Ghi{z}$6VsR{%t;!@?2slb1Fd!s1XL%|e#|7~Qj<4lP=gei(+ z?3p+{OW~T9!+4d@;wsnUx6qYz+R%}HVD~G-{0J+M#tDMq;@<#`5lX>eYIb%dSUv#g zQ!W&WTor!yK>%6lx4dralM}Z6(8^K+++K}d|5!P;0+NBokYtrHE2=|)H3R``5t^)4 z7`h@2ZofR}pITW;4Dbl;+py+?ns#$8sNKj#2huW*G1 zzOVXUFeW&0H?cTOfByMzRxL%fz@#h4{@bRtgAxbdp1Sa$O(^IOMVQvgD0QGioVw*A z)zwJFR?+HeIV{AhTP|YVR_y>=wZkg;0BVO@KW^B@x2n$9S9L66Re@1*3y&!xB4`Ok za26v<;{||mjPJoLnh?m4ubzV!JQJrQIxHh2)|umqs79j@R-+TrVca5=0&%|! zMu^=bl<1{E!5)~W69T0H2dLLls!`Od6_$Ej^bAuz9s5RXi`uH_g6@s!-Y6ZnuBN5d zv<<`|)4Bq2tT&#<(t74!J`hKDRrlV`uI0*hl?cY0y16y4Oq$RCs|NsV!v8xsF5x~V-{Jk_f8uTQ5w?`^nR0MI7=@9>~sjQ@FbxW)h9 zNGiW^>yiIoeBg69q-R`2JWG&km3e&c^yPus+sy+E-DYt@c7Y?1h%n2l5*hDJHmdbA zd!BZ5E}lZ7ZY5J(IKUQqLER_t0$ektwiu!TPF;YK=buu7D9y!(pTSg~fD3KrB1+2> z|CMg8S~9cSQ=l*3Y8g`ksp)nTSSG$mFmczD^9|a@dvA;7&@E1 z1Hdy(z%$Oxvqv)OySqxbK1Y)(TFqE=seEf@jfKPpn<% z%o6Z?XTna>5s4%J)-;^8dG+LiNhn71@y;@Po;5aV$$H%F-^?Okxv9++tYtMdGvr)O zUwhB|o>E!=lX~q8(Wwv9h$3=_$lk{(ic>^rkEPv}z^41Z!(qR8|97y}|2C8OsuJ+P z2zbt+_a`Vp!W}F?gwY-hXHnt@cs9d{I30Kr;9LA`tZhXsQ|t7Z$k*|kJJm|i4D&yV z)qc(pe+%_;a=nb4KmdkwHhqi3yh=$zk#1r=rpU-{HOKt-*B;NVspa}#DF{Hr`X3IC zit&Gk`@@6n`rkw{)Wv6}qsu3TNCM;kz~nZ@Ff0f9G1u9gqSLF3YcW-JD{sb)5~tb1 zTnBKd>!Qjvi`Nz=pff(P3*5H~Y`G2Uvm0z#joG~(vogqVk*@~@e69gKE&&&>3s}3@ z1>Hfn+Xh#7NF4rF$n=FE4V7^n9!q$NZ|G9=FO<6P|J^~ro8JHW`$hk+{iDO}{=bp* zJ?#HAz~Spr1J(#0?qp~k0OHQxUCv@+E2;lFsipj1$qBe#{_h_j4@>92!QnRk>qe52 z|Lcye zMZ-#d67Fi{nf00x$k0SNi%|8KHr}fX8EV-V*ZW*oI#9P@v&t!ZDOciEe6YLC16``c zH0;(H-;GOk`zC)yD1Hl>hG)sDXzktYZk7PTsdV?QbM|hcSKuFg)({d;Q+vWVnC)58(SSyhDUV6t&8&JfSmdG=^_cQprX! zw?OE6nV@@K@0?*jz_S#Jpm9Dy3?=+uF9+a%>=^y>L}2`laUA3OD4Bp;v=Ct*DPWjy zuJS||f)N^HfwBjg0mcV})u)YVG=+C6^dqJ;8bxu$7JPpWaFU=v1fFDAqCJ_8(<}%B z7K3!o6z#p<6w=%-^^I_1VpvkEd4`CM<)54)FH9Qh{II zUEf@uzCHhVaaAl(j!01zkHQQ$Azm=}CTAx5I08dlZlIF;4XqDw7oT##0UX#wYk*QPSO>_%y(qT*MI zuWxD_gwc3=ZYe->$TPP38 zB(4kx+aXjzMWBMMl2X43KeT?*jhmXt1T}F9mg7v%jIteVm%g zkb#VyYeVXsYG7)Mx4dFY4Tpg?wzT?jr=peoY)F08Uo|-l81p)g_eAb8-;REkb^7{T z?PoS&<|bYJ)>T*=?YAHI)JO@QAvQ&GD#f|a^~{&;HIL#Bvw|eyqWF|d>O^ogj8uCi z#hlp9N=F7+|0`NJbdP%QdY%Mcyt%e28M=7AX?CKp@YRW=o^yKf`uy_d;^u#UJbm-# z-P!5Q#k1M zINKPfYLVZ*;4(&KW8v0aCESuzFG$kkTNsv@OA*H&fMsNSxi*|zN5hgY#$sMyM@ zMI4746l`--YOQClac?!aHn+|WT$c*eFulSa^KGg7o7Amat$wB1iC;?+Ku-fB)4KF? zv)(o8>Ls#E=7M5cN<=(|`K$Ds;_j4aFT zVYRb)Ju0$U#ro7`i}9`M{1sK_We4o*DQ*puzCww+y%Q^OeL7s-!dSmPXV&(Y(Cr+1 zam%~f8sS>2lr6IgzAbIcWPj6|SzUa?Huv%=!M~w^AuHg;*NxofSa7~05FG%ucFVfK z0V2h?9i;$%AP?eKe5=j+Nh}8USEJ}{A^Nyo)c$JNp6mG~=)+g@B#e=)pGayT^y>p+qIF^wp|;JL;tE*K+P9Gb2Vs(Qnq*< zkrVLwLGM+*&;4DVzg!n8GF4od+l>{g2ta})xZ$TXj)I8A3*q{YLJ?v9xe?bLC5%Lf z0z8%-A~`G(4^hhJT)kCLTwNEniv`!9fg})|0KqLm0wlNucL~7>?%D)*g1fuBOC!PE z-CY~^?tS|G{{NhdbJKUbcI~cObFKBvF~&qx$XDVQ3n-NqVqo<8bXpY99Up;1*(LBD z;n+^}%`FjWmR=^pAVRCSF`^+ECRLEo)ExWyA3pST3t9G`$JAzI$=y2N5dFGUe?cxy ziT2J3O`xB0_rLx@r(nA(LCOvIDXRT39zhwQn?H=8Im_tdC4x!4*S~@vwtZt#J9G)I zdCPySmrG0UDFR1n;cw!`L92041>$jCYE!_MBKc}F!Az(qnzia zi96&PI8N2jhGiwY9Ok#sgXSC>e}D8)3*`I*52_g2{!E7+WX7Kp(KXnLR6J^QEosOp zx@qy(oAjsWXa-kwq~ShiTAs}c3*GP!*+?Uytp&}f?t-`PM}9V^R~B$KIBAu)UzdWZ z%mwh71Bi4^oHRKrHFe%&4%X3={-N-7!JxAaWBL+FBXzdv?-3;9XR6ACMsZx^hoC{5 z8=o{E@1Z0!=Kj7w%;!S4Uv5hdqw1XSBCBg>11nQY2&RK0`608L5fKDC`U6y+Y~P~x z*oFexW5o&8r>IC%0f1|>!9QRXLW$G(fR`raH7}@Ec2@Cr*Rf$;L0`Rc?^8NRaV z7lfEP`HcQ5uW`|qMwYHzRGsNnj;?r>_ZGNOhfp{kjWsGy9XY=0b62Lik*q{X_C)Dw zbYRXmWvf<|A&z{uRBbhP`mH_0kk=_6cr2`eM*dq_Zvnh}8O zq{#9%$d=aIhyMjE^Afiw*4s$0v1(1pD|dR2baC_O8FKs7A+pH0RqqfsKP!CRh($RwH2OrUl*V4i8gpEKlPH-l@k-0FtBx&agB*>` z;Al4mXe^P+-uUAhD*kWogx=9Hu7G|GuB#`qu2??-f4TV@6L3Nn*RY2Zw8c!;OZ#>A z!!jYo4O`{xzeb;vNlwz5^I&dyc`Sblq=6kq_OsiJtk3M);vVikJflJW#n&omK2}my zUO3Nl%1uyE3)KbAGhDA(>;_wb+z0PA1>}AIsm>NdcOHI@XYxOGrF{a!g z$>A4vAWYnaDXS1@!)6<>7u?NP*p|&}<}NGNmdf|E%KVxZ#nLKCJ6`e3GBqb1Zy#KS z+vaE`W8u|oR$IL+_d#lOnQ;iJ5Sg{iNI=&cGe;IH0%ogIdxFnSU8DS_a^JiASz_Hm z8)&WTaw+pN=ISxF*{S>WxUfHa`_dNWo`+xqJ`PZNaE|_6D8=H3BOhaX`f1-PKk-0> zL}g2k-5(>Js+J*RE#E+F$D;ZY3exlf1O&-!{-c=`AVA~XnxE#O-1@?1bg!Q%xQoj) z*GY*nGYZA4e)y*(&bNT?JB+^N9a9;5i%a{JQp^Vg1&-f1v9VRc8m!o=t}A}`1s19$ zf*gqT8?FC1h1)mB^M~_Ff;1HGeu{AwY@i{9c!hmOShQ1!cU?J{prTXi>F;{>Yxacz1{>Z3E0F2j8={a4a2OJM&t(la0)JQ^*YzMAJ@CcVr3I2UigsM=%!yR8v zB(o;6=sujN^?QhhOsl*>QQ%u15vwRkOi#zgESDbiwMp08y-gndZh>RFQsI_1pVE2? zpfG^9rq%~GE(Q;%D+i|4)&FD8Q%XaCBj5&Klyck5Lf>{6Ej;BOaH2iDE;?3qX7Fhj z7`vpUs#3ZPhW2JWj0yRV{qtZprt}Z9R5T6ICo{4&-%+FNBU~V$ck& z_Q#%=0rBAMc#_&vtXTqdl@nh=J$g{7P^qhTc*$>R^fKK5BUQy)RC7f8RvSJ0@V4}c z?kttRPmqvd(_BriU<45XcYJh&JubS(7FSS{!OHSq&O!0mR7XR{dj8r1uFS8kFLVyx z6(*fT{OUH3`swzpC)w--1P?yFN=WSo`U&`uufm}9^L4MhQ}KrN;+|$*&z8!j`{lm5 zkDWh}0n-4;IMj+nzr^24T{e)t=Dc!+Z=qTFY+bkRLVS#&E-HaubuQ92Jc_Lh&C;_x zl1GWSGS8$Q6^#up@TD`lPhQpbZA^F(Vnm|W!=zEGYqSZN^=LimlAPnI7nK}yV#c_( zx$(IikrDsVHS3-9f&zD2kskz7%r@ae^Zc?tMi}%PHS{PBV8>+T(&nlVeV!W*Ysd3> zQ}^#tWX5*66_IxtxCy_@LWB06K>>;BCU-#5?h4|zd$#Y2pZ`idzGQ@=(gIgrq|I>i zvyV=zpe>yiZ0gP?UQR@yr>a&P zLFR=q>pCpweg1Nf{J?0P7Sf8|Z@zJc3g|L^-${`0<6_WPA1U6i87Ivdl{$aU-nYe} zYpOcCtIMnpc!AJ91M~eb#~<-P?+z>M#B`eP6Ywte8okyqRp-SEjdSIX(3ZTC;K|g{ zI?;{}1SLP2Q$&W*-~L7Sg+q}6C8)T^M8jZp*Qupi4=E(~x*(5frpe)@tcY$`q}!g4 zYLWgCB*?N1I>&3g7fJi?Qy_NI6~6nJ3<#Wlf6$vkrEh}&26U{D&ep#1j^4TJ&$U_< zOXWl1jBc=?mdne+$Sjfwu$)lg#|td}`#CCm)#V)j&6_M^NV$YEh_?%bVgW_S1g7nr z)wXS7zlYv*3*t~l%#ifgISa^s@Gav^?B!B-3ESJyI3}BWGXlw#9R`%*1C%%|nsB&} zfq~$@XP~$H4rWGU!3^jO0U8dSBDK~C15yH{=F*xo+3ye{pyh_+nwlSD-cinX;iq8^)O^opkcz z>8fCk4*6(4=f8jo(Zrpwf>JuQ*vb>^r6Lf3OxZue4mQobf!`RrD%>}2x$`Bj?##KlR|%aDJr^fPF>&7@VhTvW@_r& z(eNrl5j?UP%FSGC3fnQs_)1?VA=e?<_z^!41Pt!c(SIm+6{4GO zf8cLJP(q?g{^y4B>!Qk#qzm-tixhR|yIYsa08JlUvGkWN1R5;;P{}+ka><=QhScYD zzBpM6L9gG5} z^_(I(^H~(G$sJa1+w&~czj(n1Chzg_OvDnV^xNJLS9kERsFbe0j%&K1BOA-(7fe$L zGBZoB6ReY#ZVrea)A$u(d%$#Yj{5#0pEYrWwcN6}9!+NIR{EZIBShrS`vq=ahKlN8 zcQpv{^?GigzfBuS+w!S?*>uuJUx%QhK=Z`ISw$fWYabVn41tOy`Sz7Ng(le1viP|$ zXNhqnQ&MT@^7(^`%jfUdH@*W4Wek=Vl=?y^t$-_%k6Ovmi|ZuY8gPq;*YpfW%zW;! z9j+;Mm|l|02U3^mjMNz}=Dgw`%=yd?s1cUWir3hL@w!-ZU#0U=Xq8yPMRfXXpRht+ zHPm#TQmreUapIDc0Fd~8Ar&Uh;hECCt?VE$K2FKH4SoknIt9V)06?0w&STaHAi3kO#Pp1vgq>n$QZnxjbw%`1 zFS&%e{s;p^1Q#oT$b88l;N>DUL*w6fo3fBgKuAHT{7b~GI>8EkO6xG7&^7UqX9akh zvn0MV6my{*PZ{noG;XnVo9$gYl=s} zx$z(Fl?dI#CrqWqN1SSD7+zG^oe0{%%5&COKH6VkB4AFsNZzoipXJ(KP`W`(+T84o ziuMERQy8D@%s5L%yVf_0c)71>e)?L8^%eK(GHK_xm{<`N{jlU2&MWW$H;oD(HeMaIPMy}=AT$e?>Y(|8e{0LYT)mKOW&yPSl>*p2U`10h z^9<2QIK{ggd~{axT&gs2^32;+9`5)E4sgjzx@q+6Z_0odYP}8Lq!<8g<$fbF{}Tjk zpzJpgsu)dje= zn{YF5O`C*FtTkc4A6W@_I(WVEP2ZtSUT}F<88*R0J&R|@8AZ>PTuBPFh_D<3&(Piq zILyuegY@G|sE~KKI7&O2ydf1Hkbp{NW>niAXyJdMp4yT86AvZ6keSpuq{S1dGo*Gq ziI7ksyOY8Of>Idp(10(k7|f`4#)PF2iV-ha+GC&CHq54rO6poeo0JO+ooAowoUibO zofK$4vN0?vCySU`{snrsM8Q9g?~^);e*;DMUmN{-xETwAZe#~z_$;aA`r8zdmj`&6%=KuA3cR35=3A94v?@V zhIB}-H+~e>3!`z%AfZsBA|?A0APosd!H0^}#AlwKDWUr7=%4WS-~V?L*j%3qCxz~8 zZDIZWc`Yc9K`xoaudyBRjigHj7b)myZ^MEO&zjlzqLSZGNcQg(=fujZiAfd{tcy`& zPmRM9wGEpoBMns14N>XjZ7GzQQCEk!&c)ooEyKIK#2b$9?O!Fn$drs$Jc}n&EPHB1 z1BLx}6C#SEZgi54`m;|>k3*B*GKrTh67_K2=886?|29&U z-A-jU%tx8o}z4MUG*n0icn2HbAQd@;yS=-aLxDDfw+ij@+4KWhr` zfsV0ZlSTmLP53k51F`}dQtC^Atk}_hEpv=;FJdYxhLtIwviwhnkpe4Gx4fzc1orT8 zsj%P~RzFCdVv-=)C;N!9>6qrH?0RHI=*MMvAFF4{z8e3zGGU(~L&4+RQcX7A=7*68 zMdq5Hqj<-sdxX#FuiidjL-kb$9H6qmN^M-(BwhLVS%RyUK=@ur`jW=KHOZ-FhT>u# z@TOW*$8C!>YMJG-K9LuwWDI6I*ciMBph*@yP(DL(%+3?PmZv)4+lkSm?zn3Y?B)K@Q%@$frd^>NCkoI2z+65fl>TmyRyR~~<{y85r zL}F0pcEwJ}&)zPh-WQ;ssjY!vc5ir5@gLkqHc#Tg4V(^t>QvBC85}LAI)8mro%y-% zg`Z1Sg6}AyD@bfrp~@vka}$~q5XN4rRb3!faW(t{V60rFA;{@9?Jm}K%+q9?V-{N@ zw!}~(-|54qD^IPQqSgDZHlwSS&(AWsPw}@5cq^1JUDf00YsRGDhJ#%z@IA_&O|kg5 z92j%Ny;*DkK1ZR9JZX(sJszmoM&KO;V3*k;fCD$#?>#^wb_5t$MK0~Z50#S*p5?j= zO&#>GTKbe29%E)>-0)IP!<~6JQbmMqn{t~a3vT!a2nq}HGaiG`{8?cG63S@MXvq5G zYo82xB&(y;GOixX1arl2|JXk5205Q=uVrAxiytk-n%C``hxrlK7!=tPef2;>{etj= zD9`sNwT`eqOL8YiYwmZm*;;i>ECy7WW5R`quR-+3@zQe!<6X89-|CEB_)gMG_IxcR zc&pE!RNiKi{F(^0XY9`^3l+W3{fDerGv`|2QMGoVvG+S!OBP2lOk4o%>xa*BBQ}4z z#u~)7G~ZH2*hxN-W{TuNSgu~Fsvg;(^fE+%$^mH=)OYpy;(ZVh?Y1c(KkJ1QB$YgcEh-b9=qdcf5pH zaHp8k{hyqRwA25ab7B8cNlQ3>H6?Ht`*WL{DvG~+Gs z9Y91neeUmWwx^SSxVCdC_?i_bD+?vboLX5|?lqK2z7#OGbv}q3oRzgk!M>g`w+ecD z`gl8gsF!Xs_?g{dzJ)8h6W-ev_SF6PFZjUkw@2)mamVjq+kx%5wgta29LL4X7Ch1_ zzQGkiOe-x<^9HN;1Wu%vPbX$_JWKcR5QL-` z1Kj1_ULSB4A&FnrMOQ96*CXjf=Hxctv!LnUt*dLy0VP9Er9C=Ni^N`*RU?pL$Y}02 zMn!nmKs%?}lp=eSBztp5x9vqhr|dWe$8d`YO~vauo}Si(3+}qlymgpNP(^tDz+nad zUF!Gq2zV4FdBSZl#@xF?+)I(~-&Pf`xclPus9mCm&M*v(D>bxbs98SK1gU;a{mc-S zAPa66vUa;+i9vm@_alhYpFxC*ARLKIR!V0GU-U(H*h$5>eeQP}4+JlnL)m{-=N^SKZFR6r$3tEi}mqmhmUU} z%X*8IKZTbbmwU*R#Qc4&E+}#C56MbFuj$o7sDh^COxndiYwR(* ze7E`{wEo3{<+kwLO=^M#S9#Fy=xKePvL@RnyT1Iz_7?ueI+#W+T*|RH3_tgw#Q}4W zr|5lA&`^@swcNL@!uQ9NjLzDC9-hxfo(jO<|21sna>@m2OY5u&oJ}~(R{TAyIkU2Kd@yT2R+k0L$>U~fu@w%JD4OG+Bt68%Pc^FE%F`%D_7pS z@5D#^C^v)yvZ|M`=PqO+K=o=`O~A_2v*+AbC3><_nu5-xY2=ar2JX}eMp^G>+^3;S z`vuVJ=x@0wQ%`k(!1Yq}WZZW#* zV3*w_z)zZzY{#J~$QVA2(pS$%7RI4Rdm7VXR6!#a`ELFoxr`c$uG zVS^5^x4>Zh9`i-#G_C zlZp>Z7($UDM+aM3BRfQx^)zKqY`!t>uYL2pZ#P}xn_l9}*WP>Q<>=&h@Me4v4m!(%C;>#mtr5oZDOy zv>7c}(QAX=m$)~uQt~-$>~7~jUn_Ey%|$4m;BfE^fDwX#jO~Ay^=s`k>O-J8RqtH` z^_%e72N)OQAY2N0$qNHaW5ofDxQ@eV15M<9pC7K$oA{-%f2+`03;u{?A39bVj2Pxk z5?n!zXz;xIgAPy$7}O2`r9EdseUxDEd(;CP+|T@o$Dk{tc8V$+?kSw39(Nn$ zvaAqXu|Ys9sU0ylf*y>{MH<4?i3RPiE9sotejbiDCRVP>Ne)HQmJI59lz`IB)Z^ja zb;G^>pH$g&P6Wmr$*$eGU&aNzWkU+~ir@ciGg z*TMt}t}C^)p|te)KJ<@$b(z`bW0=(5y7Ia@kz!Df&gOvgQEjFs;kzj8)RaYs*Jn=n)otSMdDE5GOyJ$)x- zdhh!`p)Bh?rF3A@Y^IjkfIXFzoFC&*2N|45>(UBD$GzkK3n$XoN>7t1X=jZuZYp!I z38Rm>#Y3)!wF725JrMFoox=X>jh_U-FTfo1UnAkT9Y~YJ9AMxo&HAcQIo!)<`W9&- z*?8TCqbb?h`9}`*vhPP59qRp@H>DH#^ZEPv%j*)yk!-n6QBwO_R>S|oOs}=qWqjD2 zwrU^Zu}*7aG~UdL?qB0#zvQG*7Rf4mDc_aPalO}{hqKK^4?=kC1& z!`NYrSln*F&EXLIVH3#|dQK${rVf-Bi{DqevX3}iI>I39O{ONO$5L=`_LYdEm7zbb z(y2#a#K?6D3-Qg35gE}(vKud487mTYjsx^)z{9g{Fy;Xe|L4VJkTtEh?A6BOR0#J| z*K+`Y&fOG*@RdHLQ5O3te@{T_yidZ;btu7u_8b)jmAFb^5AFiLc|zvS2x*zkG3ikW zHckO^$Q9-9RY;N2a_YfrwIP>yUb_tF<-608T9HQ2W7ovxb717`h0}Qh2o7F(P)w7K z{tZl&4}L$C`ct(HJ^W)f{-f0Z1(jyQvLh2saAW0F=5iH1El$K4rWYc3i;>`QzVe+H zg@6QyEd1q&%+a9;_#e8C90dCPIwTMk#5~5( z7s{^#!MnL=lHPW+N!@1+@#Q`FNriOZ^B??5q;q)Ys0v=LQRvo0SH=YCE?gc$jqw^(<2 z4*pk6DmXgN^!J2c1(^(0Xk$E?fMUyrkUpSD1w|2J};n?VaG zJ7gOw>_s6zy4WYOa(%UCBcAq&0;y#9DdFi5V%_FBBj1L;8RJ~AL=u<@_5Ga4ri~fG z%Gh}>)!?+=G)dsx)H1(f%E$Ebl+@fe?`ke| zNN%fj18G0C?iXYVR(lf;-@kE|ci2q~i!KMQ4}x2bEeA$2UjONw&(aSoBWd!rPG(W# zB~$O3O02miOom8UaSK$jtwN}r@XXD{XLDLI@ycFLY=yTf5*M`zfyz#FR^CmdHPU+ zXvm_Db>zhIcP%bNLFrJ{>f@CSj&jB9{!0_>scj9Bp-XnKsUv}4|V(7l!EG7Jx{xZqQfeB5|-$0sX)1!8C10^dLDJWoXC zgY#di`swv&c&mjYjQGS)LO!oLr9LJqMK+aKThal0pd=S0+gU&sW&rK&wSLKhBPvE9 zT)=|;`Iq4Hlwn`BH=BtI8;Fs0v6bPCr-af+TW}7`oH(<59v{T0hX!5a?a;3AWbgzx*SbLteX)&@%FA`#x95dj%q10-AWA z02q8#?ZERe>QZh(cEP>;Rw!ERV`>lJDD?Y6#?0G8C)=>g3Rfg$xfDve_-=lmPq64r1e`wDK;99lX;O1|Nl#Wlj@-_I#>YM=kaA@;|Z{(_lC9K?~G4aN}}=ERtAdZ z)_N8hMqoUAA4RXJ#V3drgI?(`uAH9g8U@vV;2j)=-ozvQjUym&XZW%d;PXU~-u_#e zHUD+MqTns^;4Ky~A>s-r!0Ggn^g|I<$U)uUOrICh5XS%c>R#KFWHY}Z1%>T zgqtVYOW)=3bqi$K<|Omj{v^i)B2|ColNb4Ti%wyD2|Lh6fY+Pd9`y3 z1a~vf%tP>thEd-kN91Fde>5z2W74(@ixnJ>;F(-!pk2MZanU$V5G%a z0j>BUJp>cd!%(Ga$xx2YjH0eK3b-IKh&@x*{61f3bLq%=pGS%NWKOS-4#Gg?H-;2_ zPyAD#sp`1WXkDkC@xXeCxzdM&$ylB-v3hC~6Ev(}5c22!!6f0o7qAh2J=o3?-nU2e zQ7Jisnenrn!;u#+Y{zt3V*z-iwL*MpOdU5g#8myYY&^&4>hhCpTsFmr?WGrmZovpm zWBW6rG|`CB#OKF0FGQstmp+%Xg+RvGFEhxSi$gzf?#_t9El9#7&g~iC{Aa`VyFb`> zY6?*X$s~4Y4)GPvCy(NfGpyQVDL&t^3{95LxeVwU;(@X*F!wVkX&lrG?Y?_yin);= z1aN)cr>!z1O5$@hrNn0wskyhR8Wq>CB=LtEcpGRVQJS@}S%2gi1`=q&a*1b5|gs@qJ#{Wi>N^0Z$cFKWDT_*-Al>hlL>$MkYAfxUr&VQyQc)&mww3`=pU^*>x z1*FiZ+uIYGcP@keX{<*TUB+&fuKLkB*3Kra@^+_vkCzxinI*m$uB|G`)L|lCS)kF+ zZ`!`D%J@786xjNa?*U41BK)iaR7K`ju>xNhFQOkXJqoa+Z12@Um%o8m*D6B5HcJotpiOfIElo&(LVwJ&}qlB&MxmX`_mUt;QW#! zl6&hK>A7*;!7pFA2hQFLMCod1v{p579CH`iK_mA_pKw4>1tAj+B9em&&7a9$7KML2rVSfjIB@Jc zQ5I@BQeK;teKAk7p`$8yzDw`>rXa1}>ncZE^yg5WsoP4=q^N4Ppa7HqL!XkybaM6Y z@l(|@=Cwhe!O-2hJ_E73;UYi#rFSMf99wH4v}tst9Cvg7fO00}ZT33ren&{u@IYI{w~65>-NqXSanlhO_|Kd| z`Epba9!FK&F{yyu+~&Yv%u@tLnyvgo+rpEeYwIYQkz6q(OP^b6gz&${w;(ilU`?W^ zQ_ca~Y6I>=4a@KnQLpw#_nT?eTsaE$VXwtjWwzsglyGGtARa66n zZ0^t+1K1bcF9Em2gUc&0Gv5w3@%PrsopcWpsR_l{@{zlGcFBeIpt)IH-h~eg7T=Hs zB~|NK|CV%-#eC(ou}u8=Ms6b>GoeA$VC20D`L`l=aQs_YP7WrLfXA{AS`o@#{E-Lr zky@$-6^T)%Q!Tw(L>(i$0$8#I7M)_W1aBA^)!0;NocQQ4hUKy8MLd;qSzRkmdCavr z6xzDuQTV9CWlO#;|IQs{Ov6H$J`4?9+tCZU>#8M{h*jAKL?I^kb=ZRL7$uIZp#Vf6~zMZcv&OAytndLh^g zM?|H^mf$JAR+mDHusfhg^e9lA>%g%B**Q*jJWhIG||2H+uw~812Kw{O@++d}ARNpux)`rNNCY3C|lVnk{ z#ATgww2I@@e9J)S2YbH@+43trEG(-wGj!EysbiNbZmmBdyctgXMOWPfI&U3qd#S@q zpsh^T*^J!MeMnIM95|B;a|t9YIpUTPc;>^PWs+_(V2V}4DMI;9g)ct|LN{Zi=O_4_ zViMa&(?dWULLc(#wPZ+KJfZ08ijnu(e-V!yU)SmQ73=7Jq5YNq{fZT92=UnV_PNqW ziInVjLQ`pbJ^%WEw_6 zlL?ZZtM__w`0!ZgZ@EQY82gzg%(Zad%W>H4?yYo-X9@FEsp||#)0ORWTFuXEh+AB$ zDNWO=u-ZpYQ=@*8@5D(UNfPg)zN*k=ZMb2N_F^WLWo_1uiQ`K`u!$i~wSsl7VtcQf z!JyF{8+;DO$ZUT|`a#y`s@EdePi*%h6IX&)Ftb<4QyPb)NK4%uuW9@K+OAF#lRJ_m zY0|Z(O&f+GrDqd}?h2du1%#~j<`8|ab7%xgA@fKEtm1QuZYRbSbN$Z8H!lboHQ!3E zmJJ>TVft<4mT{Mko>>VenAsI{7T?RX*3{`avhYjf?V?J~1NUI0Lf4O=;hw*knFTWY zlqOrdqD-44m%x@fD_{n?rvp~%1hWExx(oiIRE<>2Qrup|aFxWr`9pfm4N0YKe>_uW zxy@yH2CqG4L^}M%K827b-~RG~dv0wxB8kpYB+Xa8Kg7Ir zz!Vzc$^t|b&YLEvVPK)+Ine5|*AQ^QGO+^%zyA;ldi<>x4ynjoG4(7~-_yxX2z)7Z z5}u$|!wAwUCzus3UVe1|S~o;2lbGecfY$odv}5^+$DHiC?q<~BQ`uhP+b?9(EreLd zCTE^X-9h@WbfH&Ozp}OAo$cnUJRgz^0CuM^2bWh;wqF2d?wL|B+s;8)L<9Lsk>4%PA+DJ!N%?+6&Fg$ zu8@3zOmbiP^3SQZ_OyjOQ!mxgzLvxO_~J{bZj1<=GRo} zg+6w_zeQb*c;NZkLtS0pA23KKbDq%7^7vI*=@f<1zK}@b97^hXv`7&z;V_4M$UZ#Mokc9|(0o%4KO?-H2w5M1Bs>>}0_g9fi=TgIeLn!k zt78F+>bhHH;KV%>?^e6_&F$?l8p|7T;SUurd3e?G4gEHP-|n6~{cRUgBZ=SK4y4n? z(&q3`PTsf_9e-CjhAjB|Z{UV0toc$MZjsaa5Y-?^s?hH?r6P0EE8!I#H3bC*@9F~! zS;PF(U`w=$6S571Xife$k{b~e9DPukm2%np4<$Ymax=Oq>l2l)Vir{V#Cr&Ks~bl?u5!FQgn=+cDu{fy^aV+X_Bh{ptAx&t|cAaie{Yy|(-umCaIBXLjuz462A9H?h|sPV1oo^G z%yI()zQR$^qiwntfB1WM#QH;+nWJZ$2auNvP6s9~n&(~mlj;$TXGvc(e2CH%Q^A{|MxZ{K)5N=gI|1Wy&MI^}L+Jo1iX`b|FwW zvKp_QZT(5$KJb7ePj9-}AcLU0PHRGd!}zUs0bMFBNq0gaynb-zaHr7fW0o-S{7eFhMEd>BitKOr%LuR2S zH7-xp$>cV>;R!e%(0GR)6A6enAau**|DY?8^@Sq+!_FRtk3g=0P3}Y@io#_sS^?-6N5Y_F=9W_C zG8uXMp0X56Lc7F=9cj)5ZW-vUFiByB#o0l(fEDL*eD(gwP@)+!;cn_^(y?2kGrSG zS5H^F+Xr#sC)ci|8o04GbL?n?D<_cqj#shEoJ$I)*&AT@`;oodt;eI=t;@^ry}p$P z>)rG7g&HT@$76f9b8RQ#aeTo*tFXWquiO3I<{X+KuIZN=*!1Z0>BX5e^d#cx6IG{Y z+T{G!)Yk3PP~Y6`eUYugrxQJOt|z9N7(1qq0%0RsX5dnTUQK$Yn1W>bJG@GTQPHAJKCkt`r5a&MECS$Nn6r%zQDup=;XlGJ%E?e)$*)!5ce9 zXNIBWJN+JA*Bq8_=5bOXY}6ANbwBxtuJ>&letcyT`AR9Q*2ygUfVbB#d%3OtMR(13 zrJw%58?)qa)-H8pTq`~7-vz0R#F7tsE^sFoA9)1*W#yz2$Ez6!zEh2!ccmO!)W?1FEX|>I$I|}I-C>-**0Ig3k(1+6Y1B0MJ(u39N^fL2#7-`Mjip|2});}2(P5M zBk3WY6#kP*7#66zJ^PKffNADSN-vN_|9J5F1!PrbFaz)!JOFiq6Q@9%W$GkxvQ^vK z%H*Xb=BV=8XwnUU;IffeHTwrNXIy~b?#8Jw8<#on`KXBX=9G9}ECwpfSsoA74? z-F|x3tmAnwkg+^!1Oo5hq&r9~e*G@$un zZViOTJ52Wy#ts$@Bh;D$kaP7D&`q#E=_5o7zG=Q>!AonbRO$80gFQXh+sCh@4LCwo ztnvZ>ly0(ZePJKd#%sgQRSq!iH3$8F*4+>Hw>}fMRuB1&(u-M=ei*`!qIL<+9{J={ z;PWCx<5l>L&B@Kj(jgrTFla>)^>H%T!u#Q1!Rp4)0=gUY9H|kdi_^ol?Y=kpzEW z5G!8rAb+}-VJ@C}e0TNVG2(?7%O<2ATz zNtAWKO%B(i0}cEBNJWuLUOqv8!0DOdrE2IVRbnZCp1LTXizHT@DfDjy4a8JYw+Kmg zVvGmdK$kg|xj>=eSR8|Ae<1OPO`7KH(3fYLl#V`(O#G&n{$qC<$0+IViuYLW@@^xuCVlDIBm?I^3EYGiH{Eo@5-wqu$D7=pGFXs9| z=wmG~=W6pKcG_#TVl{Xa>`q0|-stIO)tmv@3R(aBMHFhXVdvMIQYSr|m5F%WvX|C! z01A;FeSP@@jQ7mK54bkDy28Vq_Rrx<=IsO}+!m8BLeGUixonbG)MrM3L>|#Ta`V&3 z@%`_YH61%8bPd}*3=wpNF-FQm{8p!uL{#&GB3zH!K5?8kcI4Sp6LCMQ56=loeizCO zUeD|(AC^6x$ra&!g1)Ek>CYg)?!J%5dc;bYp}b*;;uc`Q8znTqi2i0g+%tkkcdW&6 z5l^rBey+BQ=zjjVqb`wtPrTSz=Uinz{4nH~@JS>m2Sv@Z{~vJ6**%anj_l0-*2ZXh zWBDD<)0dUJYH(e&{UoJfZK!_-Y<=CFt4qhtv$>6Lm9DpAY-;_^ko_&*J>PxfKwkG? z!l~xl9a@&)cg{+--{LZp)qT!T6DWn%x1$hLECS}C5Q}dCK&sTPsEmhW{>IObZNK{4 zJnSVj<>bT4R;ygG#)k4#467}ITUxl(i*Pao^XdoKvqF$>%FG-*;iJ7j=YUR$G1KpL zOhCeaWe)zCPDGB|(9Jn`q$idlkBL4zr=M78sITL+R~Z#g*V7$$3jdv-NhB}Mu|Upo zYFKVjjc&EzDX;bQj-aWr>k^<@GpdxFc`WpZUHkj*U1cm#dH1k;}Lf2JqM)Qk0{%i;g(f2N!kZ->dE4_-S;T9+Xw zOdNW-Exb+?--L*pqLoszMZR-mQ4S2g=%x92gcKi;LM2ko~xPzEw1^%E8o?Nz&Xe< zW|ytzpfkV71UOjq@VZ&phJsrf;DdaY&%v_*DDgmc5om!xccM>|^g6d^YJrB*t8a)1 zSa*P-r>ABD(1gl%51zR4%DDo!m{@Bdz$VdsO%E+UAmG}m4S-aXgnoVyU2L7%wMQ^a z{z|%=82bfYv9-fdiV;eR=84`T6k6lH3$^^}+h6$PJY@a~*-59lN5g!yxpE%~z}HM| zL5v>>=Hf>CBuMucpZ?O0k@Bte<(`o2H6V%N%d!pld%O&s-^sol)Cq#rVZbXC5DWjS zM0iTlQXsH+5&2l>4o}?8oj`&CZ|}erqO5=h7@!73Ca&oYf$%esK(N;~0)Fq!Dmp%m zh>x4^y{jim@IsvZvg5(DtUyO!?2Vm__uKa zDVcY?xNoZYO^0~WE26tBIE3cbv;>IqRdCiPyG6KPSYp^&=-$fqCt(E%^uIQc>BqSG z2btnTq&*HMAo(|)^Ashs9iMwKA4nr&@wP|{%s(~65sp8=sPD8GpTOn}02UnHvpTo#icTYkv8^(NY-wz9lcz<^5 zk)4g5F|9$`15HGlV3ss%nSQq!l;aL8KvXJDf`MPj?!WfW|0Toy;qau`q@PtGBZ1H3 z@@N%-?Z#_L-V>VZvyes8dbFo?0|&8`X^)a3SZ5;s6~|D}|Nium>w`wXOUVUbm{ACO zE5<@?-r>f8lo)G=EFC0)BHF1p^dmKt2@^f(Gj1Z4w;)D!1nJ&vQtj`93M=&oq7lPm z=X#Sie?jN+7bccfwuyE#4ge&#&j4lFgg1&5=3pBeUYCGJ=0VDt$g36D^y#hQKnGSY zz=#iJpY6m1NPG7-SUu_C8`MCP04eLn=+z{9ei-QrbrV$&4 zpDbF$e06xU&3pepAj(P;8h5cHi(UClC@6agNTMQq+615(-8OST8TdICxYx=QDT6|^ zkPrYY21e5TS~tx^cJTFeZVEO9;M^Kico04WxL8P8>!UWa$>MuO5!pRPP$D1F z#C6%nN^o~=BjBjZVI+y$@*ir=Xpc{j@-g)3to!?9;);I%4jG;hzyGi8Z znU45$Q(?SqLV)d@lPy+UM@b8Bp_^lEjB}d16^002-lFzrKB@i2eTB;OgF>AN-FZhZ zE-b#ZTQyKw+r1JD>Q};54AGIPd1E=}_F*(Z z0>1f^tI*Gt6l9_ezH1oUa}K@KQOV>fM7EN3O8O!9XNg?*>%pNsG&7VkLKIO>fDdeykOK4QpuOs(L7&UU#(*8wKJwIcZ zQn3+_z*3Q~`ShlK3o3IHv7B zL-vdv2IqMGgL!%3zm%4RBl4V+29?K+sEcR`d5|3RQ!+P>qr!z$kB9s9$4=@>#*{O} zZNlA!;&u}&<~J?+S(OHmmm5Tt=&GFo^dh%!G#{A=U|WwRH3nD!8p~e|me&85|Jk6e zOK7Q9OqNo-HAeVzu+c(DT#Z6ZZoH!X(@MM!;f$k1$7>ahr;bC(zR@Ah=s0)4Q z2jSOwy0=CYk*szy6}3XPJS1MV%iAo6ze^f8$FpohlZA);gb)hVaKFgotwk*7_$L(f z@dV5hPG78}V=jB0$_k3UKct;rF^8ItYQZJrA1f#r2pvG8)97fs>|uZJ!7sM3b5^uK zGZv16^oS#&E1Nkyzkf{ulr{W)=~NI(Z_ozBb0nnvx_>%H$N;!*(>a8kJS~?C=h46Q zZe-%YZgf+?dFlB{%$;IK{f|JF)=X&^edhlGgFt-0w#5WXa))P!=ckREUh$V#IKoLl zxF79Wv?C9MlM10svG|e9?6=5^cF%Q!FX#TW!Us$f_W&}eI@O@7*}T>;LNc--pNe{O zqM$%;cF`M#Lu3I(bwSmRqYhSxz1m2QopUaIE2s#f(4Y?0Ozl%{N{F2|% zx@4C+FyDT6lZ^<>$WU=i61f3E-O!0=ghJ3R*Q@K&^s%?GVOm#6`Jdkn{K1xo)^kgm z{@X&5r4x=r0_`OQac{P#d_?g<38Rh>>&R?LpTwuP)PS~{T| z?x4HZjZcy=Wi*kOkrJ-~N*71YSB6OK2S*pjPICuGbZp_UO_A=Lid++4UkD1!eWQb@ ztfRON$#+0Fb5UjOKgRy&Pe~NhNy0dJdK=Rs|Ih8MYW>gQ&hE~O{qH%Ruh2P`N)m@~ zVNC((Zb}j~%4h^ep%e!3=s&y%|Fu6%Cq4Ba`=_`~dPR>)EXYy>eiUop z_~I^I`^F#Po3(Fz8LNLYPA6;M{C{g-p`S6QEEDMT_(ZJvrU=cNPeX!xx;bb6Uh{87 zz(Ugdg0Cpd{(p0NbaHli@_ELXzyF6jgJE_554N{o^1naJgBCr9DGsIty`cd~L^aD$ z=`n^eH1zu&^uKYEVLn5{et)a=qp6hXL9cgrcjsdm#%Fxei}X;U2U%^dPA=YFqQkRe zboB1*`1I=Z-PtAj{@n%o>GGt5E>6xb-W~sRq<-!|tK-wltBccDKdE1!gMp8Z3AiSJ z)y^jL@yv`oB&IluP)x8kS1aXNfNT=5B-CGltveG$akrGSFoQf(HrbVG8&V-T9c94V zut1?2l7wh9Lzg-$l|Ta|r<`SzDcVPDjHKeFAqz4k1XkfeUc#lTbU!>^^up3Z;CLC+4y)0JN0f0f^r8bnLL-870?|u8})0JgoK+6X^vwbXOTW9pdUS;kG^Ld;7Bu`GC@Rv z)qKJ28hNG{52hl}I^EEpvOB^%>L4M3R6x)~|GT5k!vJT3sCK3o{R%L^kv7YK1kc7u zWWm$`)=>v2On)@f&|~P^#mpU5)TA^cN;mZKh$&4~Ph&ckGj;X_s_XUb{{OWB!>N;5 zBi?qDNw}U-YXE+r!uCiv(1;{tOaqFea_x}jXE=}7>5MmTTCO!XQTJO!^7>fEii#4xOL&0*Xy>K_B!PH>}B!o*A z93f6_DJ*5jjY#Mq65$c!_AkcmGP}DecPC0Y5hRg-eT?p=EP_peln6`{95t+YogZ61 zH7;%c4yvNhU{6uASv%<7oEn_OnCAPFq?iMxD7?TlV!}x@Q;Nb3AZ|nxppyj0WWz2x zO(fxC9Ka#ban8sbsWqS!b_g36s}2@0bH+EWcy$ltTh(n>CCxk&FgY@|d54z?BELMnnxz$p(S#=tL)82Jlu zyy9pg_ZA7|xmtP*SRzsyWGoZW48@q=DAvad>Bx#)M9@hByq_kpMu6BxN>t3sJ7W@I z|I5t1NI0s@?TG%Jl$Y(hbP&qyL8HEh6m z%Jgxq1YT$RX+|{k(Q74EsbP=u>08MPU7B3VhE^Mu8E2chT$$itiW~$X#X?3iEyaOc z@Gq7jtR%dY$P7o8{O%Z!!aJ&Djf5p#Sb0Hj;m>X`#eAX^CpN>8oOQ>XkPf1plUo)j zMqWG3jsB+wwAvQwC~*)>`87^gu=6wc#B@3O=p45v0}P^fz??j_W?Z0m{ZuDV@{Ka)o2K{XP>+A*Tn|XUU z+}Dc(E0?V~6QTu{bk3ExR5uNUCy5v?x}lL@P2`Wz_5xt7sH^%p7@Es?w)}+M;UpEUjQ+1vc&b zr-?7eE)}3BhME;@`RIbUmLVU8j=>4haJDKJ3Rp_5Y*XS#bEG_25+yd0kY;g5(~**B zsGPF=L@uk%`Ur2~WSv440)!N#6%(RYdCa1S-Rbk)@~(rmT(8>DGtGoV69umVPwN|; z1T>{YF)dg0W!y0n)+UPKe5h&?-@-9!#~e9hYQs$-N-I5znw+Qs=8A+ki)o_hL~D?8T3S83Y}%}>IP3WVz?2nKx|l|h+v`ADc4GGJ}Gu9 zxE+WC3nsQO7Pu}jRH7;|7lv7BTKBJDzNpS+!`)9mU$1=9Eo@3=Q zxmxhda>k`^02EWIm_23VLVm}vl1)_=03WbYAsChuR5BY^#hnfNn6f%ueWN>~dCl8X(vjF>utpnZR0wMnua2Jgd^5MoiniMI(v|tpdbW>uv+@ z%SM)BDO4wB9xlj?qmU}8wIt;>NbrSeui?r_cjMd@v2g=5onqUJL0O!&s3NX)F5gPf zpBmb+<`n?cZmUYCa4vNREY_m5qN9>oCf8Idnm}nmwn5o3Hvw8#Eu=uvxk&ZFTF=Mrwt_n$CjaW70Xi;zETAx=@&5W1@U^)b&yU?O*Xm20& z_h(G1kMi3aIA2CgD`jfiPC&g=#|VHXvXpQ^LZUB%)HZOI#0;dR3vD2kq)>?_oM^(I znH>Te8M!Bc!{UMQ<_O_rg1Np|s_Gu*E?~z;S5^QKzV-{Ta&*Xmb4o38J2yfK@#aEJ zi!b&X1II)-5{>8-K{fhM#*v|6-PjVXg}75#os62wZL!!f%m)hwzEyfjGa*@w`3#_; z2?~h_I31a#$dwK{p>_ML-A#7g%xTbY1ZYg{`skPnP@M=@t$x8=;boR@f*jP*Oe?UU zc`FsGU<0s|PcDvr zI6S*Le0BQf^y*(gLf@ZWot<22_klyx$NAyK)#=esZw@ce`A-+;?=DaDX{&DwBN8cH zO{6Rl6mA{hW=3m;Wpcr3%2~>(63=16W0Zld6zH$uxQ@M4TN{PQV$fAAyQTs-yI=v$ z)nv`o%{?nvW8I6^x-zS2Z_h_>a+Io%-cTLOH1pA^I(ZSfRkW+%(0wEfMPTfdQ^NSn zF}2v6EXlZZO$G^>M07%ufNXT~+wM-ul$%?A7Sj8=78C>uNkm5=&;f80&V0a-EeIFeL>P%2ru$)(od{`XR z&ZhWfszmqlcCB6(&b@B4QfM$`Oj|+0(pkD}2b(LxXiR{gbRdO9Dsd7JJ&9DCK@Int z0o{=}p)%i(`R#3FVMlBf87maXEj`6{l;o?gTA&D+wE7hlrRyHzqaWCv(uA}snIjDF z>2zGo4?J3u$hi&4Wo~mV0!Cc(vtpzL8wGel(kX6H3XWb_iX1X9HesbR(Xr;wYQyXO z4!9ZTxCzOaB%%Id%A&BrbdGrpoX85-ITnlUoN->oV|C=%`=6O1M^@?Z!M=RE)ze@ zX0zERbf`TUKzRc%VQ6NEBXo47GTC%oM^Ln`8sxr~8{euftRA8mfIha2+1!fnG%@NY zu*95_a?!@o_Sp!mWVmFivjmK#CG$nDrpEudJM{bT$ug38o6KQ+&DLD&WC>puJSs{J z+9dBsirrS=2DDugQUbvecOJ|c;bfBG2|*KfOL$WC=rdN5LQWU;dHHK!u)q7uQ+|y9 z|HaAS@!JzW4nM~jbN&A}H@Akh`j5l@aQnso|2dwoOm@_@wZHwEXJ#JwgDros|J%CF z4?*LJFQ#yi`;_%YIGm84Y2G!hyCp;S|0CoqBHxW8EW6_O40E!9{`Tu(nyxrV@x{{P ztgV@VJ1P)MNn$;yawp(%ZUV8cOyFXWVy>NV1PL;(q??4uJ994$rKNAJn|s7?ID$A` zP_Br)1KmWQ5c;^aX$_3&TdcWni(IwFvK0`e2l?fYMIsQE=nb9`jy8K+Q0q}!Zq_8n zxxi?kv~$tW%b7Kyfsy!*C_Px1&UQ^#k_4dpufaD)uNim1PI@n$%XGxfw zC^QQEwNqIHnuW6j$234RQ3AMW2)&GEl7MR*O>(QQGd7m!R)=b>xnZghD4EaYz@iYH zzU!2xZL$=0ERh66f4Qd4{5XxYUDaZ|Q(cN%nk%Ofo6x||XFjEqX*63S<1r1WwZM!c za!*HKH~ibLh7!gEOVG4$)oPNvV!LpBXJXzmLAbF(LJAkd)6M@tj+SHh;;jdv`NA}~ zwq5&aGTB&L`|2xn&Iw39f=VLR*1kbMW+R19NyGtq|IhE#-re#0-TwQvZ_p1UiuJFX ze*Zmu|C&fpbuJ}V>eAZU6`$p#tuJVc9?O>zG%*6jU>n6W$sjM|+DG)3CiEs75%dvV zl4#t0Yup)s+!N>{I*jpuSb|P|yhI<-YsMxKL9c&2LF&7JGqv;4p?bOY@t}K9`~S6% z=-0pfYKK?_#Z%0s=*3t_!Yx{3(~mE1CmTg)Aq#}Bzf8Sc@fjEO_`%JUuE4B6%!$6X>ZML@W!R9?lZ| zJ{pt%$@mkK<=Wai-qCgx^m|5w8)O<4YMV{DPzt9xSX+Dl{{7nD(Ue57QvMlS+-gAb zyj1F?1DtJchcK;6{0?=yd5wqf)HdvDS7;b+?Qkp!M}>S~dLm&5w9)|LLDGnEttJ`n zYc9>rXH%tuvo-C(nBRZ@T48$Vbp}@~N^4&o+Z#SGQsYQ*#6qIj@IM;zb(JRn&l3Cn zfkf%r+SQbx5fKvIVK5X=h*Vfi5e3r}{4HdrR!*0U7B{e#L|ET+IVEfMJi3fq+XUwvq?L46__oY8ljN`i1ESvMp~z9OM|?JEfK6xrybjnMjt z-hc2?79J*&9-6n_!3WP89*#i}y$q%#%p#ghP9bpJ{ComexRfQ{!LJ`Ys9|9A;+!%e)mHL8{r2gT!h;16w!0~+ zfG3La=-I)I%tth0EK(DbJR|C}Q?pyaY^AA4H_ek4JKvu%c|mYEyTUY)dSQi58uJmo z_YxKoXZyex-Gs?5WJ>qyi*-YCqmUA~rHv%Zz55DQkT403Uo%7UkU88(zf6?|p%b!T zbgPIC!7ioNUFp5fCeVceZ2qmTA^{QLh;YA**7rd0w&*K5%-f+m8bvk*Ljkc8ij)XU zf;_6r`f>qAO+S($=muq}LFbJa%~+5Wc}$C?f&3r}TPONbT**eS{`KzY?9|QX;-fPr ziFNE%+!A8zOpct$SmxBX1_+HrU8M^Qtfo(;P#l1Eai~t9QpT9|_xe;aK)&Aqo=k9P zW)aa59$|gDE-?|^{75xNC*|qr{&Ykf`EgI2>D=12t`1ETbh9Ub2vC-SWC~gKO$}c? zcTGKCi#%(%0lGPTPJL?_sLSoGK4`Uw3Fad_At+!`q@C^Eg`p6a0|RtW$|4%f5K$Vk zNiGCLC8YZAC}P1)o)_E(*XaaB6_C-ZOzUPv6l(>@yc=UegtU_8Cm7TCa#`gzG<<$+ zsXK3N8Uj_5un~ik;53nh-{Ppu54PjJ@HCGxuN5?PgxSD66yp>Tbr|JLr!nu4(mIPn zU~9My=fJu8)i4Lm!E^+I{-}zeDNaH$#WzG027(E=Jp+0aYIIPFqKsBZbOt0G#x%JE zW%L}&X&DJlc@Lwn_MpA5{sQdiJWcwgPRpVJ2VYHi7m|ofVAtZ5n#oZCA!r1QzzZQ% zpR59*YOnvh3Y^xg(g3254o&cfWN5^U@M-w_;lwK0?`$@xMKiKSAC_F{vL59*Z5qnc za21Vh5s-!bFJ@--^jhm9BJsw;u5D6%joxOd<5K~=#%12D9QMBASWZo}1;e>5R~kcC z7b-2rWEwybCy~tbK zySKSF-rU*SC;OvtxV5!CA|ct_?(gj2-OVA{8*X~lSr}MWg5MMyn~xsbXr-P@6;S5) zUus%jaZbhu`af2>FAFeAhv@|@2}mkMPvo*`m)ug=0zE7Qoh03qglzKP}O{8%OXB^BtWufpDd9hW(vKp1d&}iCEe} z5_%mEbV={PgS3{aciqnsrwYr_VHmPRyi1~)*YRu)OYgvgjOW7p^jnp7T)dY#`m0%P zgrm}U?`R7Qc$l~!8ut=&x=BHzF=)Q(6IYM6*?Q}val9qX-jgAF|t5g zNA@UMgYStpufPS^vg1{&xU~rjrfkR~Wy6Moxr+vTfOKdJMq>Yl%#1bA!6g^CyVc*{ zaqxI_2nHgl+8+LL=_XjuFGDXb4}ElUgaSTGC7W=ZPG{C!WbP-IP~hq?ip3H2U<>)ZaIItpst(C|egqCZOf#n2R zg1N_9-Ab#fdbOp(9s|*mJNt=8g^Fh-3=CdVO-<^}=bUh<6q*Y{LL&gcegD*eEURzn z=4FLzyfq58_Q#|CC>(@)gI&B6Z0!vDTS2fJko~RAV0Uvo>f`OL{T;l!NBU$d42Jz+ zAMXuzaJW16YMfy;jjOGoa4wbnRv#dtu5i2RPz$s>GsueST~me21ta_k6ufeM>jlTd zq4Tz)mDH%+O3@Dlq;(1PWy;iq4Hp;PO^BU z7?#qL#pT@O)qf-L`q+w13i*5;A zMOm0fGZZlf-cDKSUPhgs>w9qvw7ux_5jrv17D4$D2WZgu)&C6+_WFB+PN~GK?@GT4 zXlSz#|4mLUTo({+8%SV%4yn19;M-mXFhNwipabb5S&xc<;y zrra@pW6n9D)UwjwkPa830>HrZW|-gA3o?m|D{J@aao)9J_1f|QSEF;UMH}y5(fa$^ zC2sY8bcB=ej)rn-iaJ%e_GrYt1DH+6Gd-BUKRMIOJ3+S8lw^pdlE#WOu8z*ZSohQM zx#QMqV*J>h4zR|ObRjAL?xnd>7z0fZPA0u`7V3Ng=;Zhct)E~XQ6eNdCMo9N=6FRR zXQxS%4Y4C-u1%o)N;iktQ=K~MVl!6!(TF!*^#&43(xX?eE?}MkOD4wg#pYU6(*wX8 zJ6=pXb>z}y%(0L>3t-Oc5J{98pG&T!UKTZBqra;iMMG=a`WBIRL==UCEAx>pm9CfM^|@{BI>2aSw*G;+ z7mTAxYU(DPM>rvsRcu%hus>O+UqPg)5hKto<#5ZaAOKFttsrU{%Pqxb3a?(DpA(`E zzH{vmpsPPN0JIoU+8ClnwHpG=p{BQV43&G{;`A-PFHV^4;nr|(ukMZ$<9ixsv6WcZ z*j~m%*r~aoFLlk{D#>vv7YY_*NdsMyR(1XA{Cl0O3;h4IBhUN1%lA$J9_^7+X-|dj zii8MD^j^Wk8I$kz#WYK*&R|n;U4x`*Kp!=Cr6u=YKc_WMWXk@ zw>2g)W}gm z+I6wItp_`sdn+9zigsv}-;}or@P>e>u*lbfJB|v6|Xrl6TPwMjnZ)g?PxJa zPt@YJBEi_MB~(+Ne^{x{)qJ{|HC>%wy!)SjY1JR#<-|nevjovpYLxISGAo-0!ztix zkfFwZF~!>mC$IErQZ?rlfH>LUj7KQ?`OV=OqT$zis8KrB(RAiy^3kvT-|Ts%&J@LI zi%;C-Z2ABLUqJ)YQN)6qbIwNdn59B%0KT&(k~HOPWchmeI7X6!i>)HYTO8?eY)R+3 z3TF)3N{b6POa3<-c?Tapb-aJ;e<-ExUUK|1h-)Au3h&_8-%3B5U*KLubre#i!FmUt zxq=D%!*FYBKiC`%H}?lYe`{-ZZ*w;s4fnS20B`q)9SOT>-)Cc$}n6CIW}-Bspk`@uX*eO1S;evUOitaqe~L7Boq+S z^F2+dm?~Xru-ETblv~$qW%7jDlgQLEE}3>t$Edkz`*&uMI>zBy?|WUhN|;o0Y9l$p zjYs+mbMRP!+gO`Ph&Y*K5#~Bu`8p>XHjk-J73CTpA@8ou@fhPI!%;LVQCRyGN;7#a zaj#T7Ybi z^DZaOv^z}E03yyA9T@TlN9{ z-VVL$_SWM;;Zag8+f@LxsyU&sB2KMJQ zFVq$;r<8_$e40>+@>_m%q^aUClT0t9{Z?nM5$OLeLQtHs?9>_}7^-C0Ooi%O9kwu^ z3YeotuM46RN*&}VE*4PRfP;wOSBU)D z$F*f1V-mCEl1Lw+Uk)$MPS0K+pr3@f(+Dspe=8tb0vshW=Qm1^f#%d?Brc)i037WW zf(o_-pN5st&Yu$cdq&XdaXz+biQZ;H>Xg9H!bGj=T>PMasV!sgc1$e=2y4R01g_Ht z>J%AnZ=1TtrF^tD`0p(d(+=dZ8WGe-bXU`z{ zp)E^|aZG?po5Nv$Yd_q^o8#gB_U_*3DYf`U9-A`{lcsAm z_OXz2+}sMuIDuamU+(_+^QCI7PB!2D0|hvkn!W9$5wivxQ*G63{g_Eo9P#-*ff8m6 z7ZQ-OcWJPf*?lgsOYOPZ2n+U~JHX1jt~S`RJJ20<*?s2@w#*jU8*C5u_6CF9y{-Ou zXCH5d12P(n1F}0B;b41nKM1x-f4Dyk2Eo>7bAPnAk2eRwa2W3N2jSlS6K)X)^kp}O zi=mZv!@Se%!m2#ErUTjQwEmM@tK9uj3WHlb_}nwi1AFW_r?)gB6LKN~9GO@JnsMV=sKy8j8W`tcSzOD7L}D5hvW@BGTch#M(AVT%l0?v3 z^0f{%(iO6-d#}>wAp_u)3W$w~Z5K%5aJB(QD)aQJa3lWmi7^IusAXLT%9DoI$Ib;$cIYTlcs6ZgVwPe;k7Fds*tD zMcP^!lEtz_UWvwhp>O$0p<*d#F_BY}3GlSCVtanK59XbQ++D?Yxz||ZZ=;BfbRI`j ztiGvLH{fB<07;XHuQfY0&b66>c`5uEj-!nS;7V(6P1oClraUYn;5a4uhFN!c%tMFQ z?=A?K1ZXm8^su*klIP8gQMfqtmZGL7ftb&S_2LhP@e%7;J1-wFd`ZZAI4BJa`jNmq zFQGj>{GXfbo(AG2Lajb4`+we5eu@qAxz}|i7~2C9D;8EJyaO+yNp`O<@8E{iEPlh~ z=w}X2Y@Q6*svj7F*o@5L(ztEFV=8zC{%)_ba6+1HCUbd2ze4Brua?JG9>393u=T>c zBjZ50JfJbY|0yX%oZ<=@c1+1XtCtcUkVImAF#=eDTS#;95#x}c%yk?#3@rE1FgLw$hbo8!|3i1;vAHL*N%+uchTfOk9H1nN6e#niwW52%LkaHj zxs)C@GN%lNjj#}Bwc9IChdwAtTDLQmbDUtjRT(}f;M6QClzEnW4CW1ZR`_`~j}nqJ zVzVM_tZl?c8e&$R;^(?hSn4ie^{DOn)BK)sNZIbj2z8LI;%@suIt{4KxD6VV;$>ay zw%wJplpG)rB*g?r9&~#0#*XWH?rY{;&w$(fJnFQd*a<8JN^|3<0!5w6=OtUj=5TX&Uk&~)HHKqt zhtO=mge#bcFD_dKE<6EZd_#}`lLpJ(f(R51w}qU~EDSW!b>eJ90v$s#tgiN*HPy*t zlXNn7^ufZ(APhC*AS44r#voHS3f&}77B8Ei^{<9oJNv^8?O|@m)*gg9W;QQh{^R*Y z;Z<8WCgL3Rd46^9naSrtAU%{$fLXe;FdjOUiw(#ooJXMOlD9fNvI*WSTy_j%pdZX9 zL>3irxvuR8^;B|5tosiqI(|j79BjZD;ot_!^yyl|ktvyKgJyK%cp(8A<12?o1j>|K z-$dP!;VR{6Ekl0wJPQ`|{5XOpk0p0-A`N3&bpQ?sm)?PwClJ$;@dyjDvxP_!FvXDBw7hTznVi;h07VcE)!?4) zbX0XHi6O7{Wu809rUK|9-P-{aY&(o1$G=8L1(nwr`nH#FqOu>#PbL%_iwRn%KJh!I zqYWJm<>|k?67sBASAMK>uBlRZboQMAiH@6GbGs;}#;f=MX#++~LJIvWROaqDiovB5 z2*QDFrxD?t&=ok=b#5;sZ(SJz1xp9fB9yfJz-n=lM>T*!lklz` z+2T%g&>d7q)ybrFZR3Wnbi_SNwAfb7D?K0K@7Jl6JIr?u`sY+`uG$Fbp8I$TJIZJ4NZTLk=81(nIJ5{G*?XvG3cvBL^RhQu+T=?qEW!cTX2oUhmVUsJr z&9ed(ESB@uH)pycCWK`Fo&Xxr6H@X zikog^A7Ue4=M-E*)UEjth4xFDpb*a%pQ&o-_FFu+a05_8vFN}oiltLD4FUWvSdv+T zORPx5M(4F0zDZbwu;w|+b7lgPn*l}Nd}~%ol*bKfeluOf^2VBqLYU~k4T=LNzLzT6HD_o(%VHB)v?4BMYiC%Lrp$*Zw_2{ zxse&N7zO&rdHcAFp+P47VXIv{l&wy7PqkBbqeS1!Ae}1qtnq zXwqOqg77tC>pMC-MI)MEJ~P>H7@xTzbbdZkFvV19vo&Ltv1>aKd!{Ay!%{^~T2N7g zrBODaiSW@m69Q8DSvwW#LRu2_zxYmcgM_Mojw78p5p^}!q(S$V$f^1}WlEh&YY<+6 z6}1V*Ljb|1ECg$UPEA>a;u^EF2Gd?%=65?-Agt#{Les|0Z6DxF5GT>U>KV&mY6^L} zgB!CN6(w-;TTw;lP`|mO8!qm?%5l158WE5=Z8}A`Y^72i6%cuW zi}kVz#$81F=uou*&s7}3e(N-SW0#DYV8Wt_S&pKOLsKjne@`RrwBA6+GENm8cS}>6 zL(!(Jl?^e5_003kIW~7E#McF-0Rkce*hvYIez?S5DkFcz#NC{0H z#7TlT>2^KBH}4G|NFt!dZNhY(OM{mpM};=^)>tD7Ayl(m z5hP@HiDS`9CVvkaD6nk}hv=?`e09CGFVc z1yCPB5B5vP+ysnwOi2V<0f|#NbF%RibIFoA&hia-0p^8eamEr`_h_0)MLK>Vyij2( z6o1W))xsgRJWMOU@3S+64<+PNy(N~nHl8-RlMzwfTC0d5X$_RQlIfUJSM3XZaB6); z=|>D@iMEs$*{lMVB#=Vz^-*&!uzocc*p%I&F?fc+?Qui>N^`!mAjo(wf94_n3vw4a z0KLWc%`i1(m@-aW2C`t558PZ}({S@PNFV@RUyPd?L%9t;U~!tsA}J5-qI^_EHB$`y z$yDM2E%oaLJb!HjhcbsZmRHEs@Vkn($%8wN!$p6-~@eG)w?wO>$462rdL(Saqu6 zN~lE!998}68WZqhs-(v#LQ}?W%q*b;omV5}5a?vdpy+xTjcld9L&$vLn=EJ=9q&wl zVx#YGOG~PR+{o(7@UpAaksC5Iu8(G)nCQolfP{plDF`p{tfMoEQeg^UTk+gj3asDT zI=K%>n)`+5q=_sc8!!S~E!qf6Jvue@!xVHr(wkO7$y`PBBqWe=PRT@2ySO$tA33$n zv?~krYaB~U6JmLC91DZ!Xx3m(3{Ce)t;rOUco>E@rjtuEK^r7nTA*gonii;~<>CcW z^D$+T-8r2mMk>2wJQT12ELZ4sUGfm+)(!iE z8nl)0fEO>lMh;TTc%Q4rW4nhe3RA1Gm#3SPo+Z~S@G&xV@dWY;)E`(;41VdDzo1T_ z(RO_BEff`2rwB^Z&6Gqb0+&mBpp7ybg5R_-u-M!Ar3rUS_V=I>mY1k%CGf@E(pLo-9$mAb6_kUEGYw`|raq*O5dE5&3(rwbcL><$^j5P+aStN=k`D%GedTw#Ih zbjQ9m6=aJjKVjO#<<#N>)Sx;SpMf#%uY9^JAYP=eb&o280@{abaf=m!KP<6LT(Mrz=|G}h|a#APv>k%@F zdQQ&)F2!1uNDU+piU)iSn*;~b9PY}vG>phmz879|9FTLuDGM7_PbGI-T~~|L>U+ph ztn_BeGNF{UTE1y*Xn@K;Bm^u+jNN3ZUP|p47%;H6fO}X(Z%GBv7~db0G2tBK1=H~{ zWRG-XHTwPjd^~X??OjY0JOC&F)NMXzVBnO6a_p9qW;< zMugIeaL9w6C>%xcR4c_gtVSnFnU)qf6J2qfa);(0>SL;NfQ|-Bq5ZEHUJLb@fIVpd5d-I^Y%5rJNk$ zVA>SUqrQQ3I~qe)yaA32P9-E_I5cVSwGl{SF0-^Y1iPP=!vtV~UPo+X0|Z#&+>Fq~ zrVh-xfDveP&H_Kb)9Y)|``u+%-$$#1hVkmwf-WpWe5=Se!n10Oaz7Ti*SIyDfJ9Yh zN4hY&PK*e-txGI)M8*utzG&A{Ds`zhbp}|@h4p)>&RfA0>O|QVq|SA?-wg|o=!D#% z({nfDQDurk=_T?FO(ujFI(fbqEz3|puNT{3!}=65QG^2I_8;ppS4M!1LdZ$Wl2zd$ z*Y8xjq5=j{%0_G)sG}KLhxuI{ouiA(s|~k@?qE(ASj>`O%2}eBoVlPF;oxS%S(X@K zSJ#<(jU~Cm)l2!Rcx%j|y0BUPtJ>3vl28HRSGv%EHB>2CS9qUF*+yVQG%-W!)a$x* zh(g*Wlhr&&&J`UAL6ssN;wn{xkJK-Vi; zmftQTD52RZtT(kbg`0f0(38=KyYIce5z3=q|zjW-2X`HZSdpdrkvpohqpyWH;uB>^V_Xgr>_;8nUlv!wL-5>UjsX` zbyN%(MLh^}EuzUI}e%kk9*?emL&2AoP?~!_a#@iOEu!1Z? ziB9lF8mb3VU3{PAb4rfQN6vp@+*w}ej#IFxH0C8ya6_*aC-CVVf~ zLhE>|SEwrZ4tV{AL@GwDCRTK4GdDBts7~%-U@j;!*qb_njs-`FFj$P zMM_GUvlGC6Yn$0(q>7`@kYG`k->>EIJ@@iji+;9LSj@sK(lJ3)fK&&mt-(H;5E42? zE^=hO+07*t;P4D0AadbA=_Le(EXeXmR%4oym_|a&?!;UKn41WjOks&iScQqIr_E8< zP8m(n`wEhdboKNsS_3}QF>*^>*>IeQ6ho}Ab%1g@sCMWGHp{x`yI-e*1VtaM*Litp zHjLyXNicnp(DFaOYV!l~)Yqs=DF)0t5J14IC1-{-K($Gh!E8z8uq=R$o!^jI-Cv@X z-28@UM*`Qy!{NDt1e_G^j;2JW{`CyUqCDKaoH)n+{}_V>t+2IS=cf_v0e+Pp>gGj8R~>Yrhgwb#J*XC_e;_!L z)1xT?$En3timZL>R!MkM_!tG|>)aq>3rE*<9{r~_3N0ZC8C}OMq*&O5pdvkFRWem> z6{C`QEthMka^na#E(F>ZpR%w8do5-OmJ$b3(=*(n01xg9PyMfvoP1}wG4=5C@wOA7VQ8qhp**z_tJlipwF1 zC%JT2L4k?uQ?sHtzF>_4H`EqWznmVvMVuM$W0Oo09R`6;{trVaa+G|gbAWa-_1K0#MKG@^Wtk`uj?u=ii z;_cw~3s^uW{4MqXazKs0soq@ubiJ#Vdo)ZvV4;=tQt~Bc(U~}~aXK;{A#nI729-u^ z%KPESCc(*3fgZ9)(aDjY-y!x)@ot=eYYnEyVJ9H_schIdV0LQ3OK{!AHpnGz-;_EK z-ak3J0R}|*v{>3bu5Gz;PA(3X@@>oqg6DK^IhB5PMzSy z)+!p4uiE}+*l@Hj-|2s>j_$)%Ut@lT%amKIJbZ~bw)w!PUbixwLaL@rAdbtq$y^ju zl?L^uG+IWs^jN7?3>Fo|dX0mC%v@H0-bY}amyKn6mvQ&NZ1*ze0rz0;WvrhCuq1Q~ zJQ9F20k#cnIW|#?Kq>@_)Kg+ZjlvWXHI)=fhf3DdIYqvrr($)Ic|lV)g#7L~}#^6v8TjQPc>QBB+phA-P1I&yfjFL`81 z`OAq^al#ccazN_VeYLj*id=Q{uF-7ZLA~E>bw=GmkF*HW%KjvmwhJDWsTtG)!m@gWOcgdI`jw1p&Tqn*)R<=!a`*Z{ajJ1;yrKVW=cc zXRQb#6&}*6#G=Tl4yXD(gIw?Vf#HNP$vDHe ziYsW|I!!E7Se;y zJ2&&ZlIwa->iIlQMrEIJl$T8RLpLgIUmFa%ZLOlk>v>RYx-fpmRJ;c3z6hG(52s3) z2)XX5mp)TeEpu3F``SOhHNMl{KrEEN$)C01kjjK%G}(r(V+`rE90CshLIu4yA;Ehd z(?f4bbR4;s9IANeEMgQ_sj5*=z9S6_K8dzbuBea2_!RmWi}mKphnq#^+v4*mlQOTI zrierMsBC6>*TpFFASA`A$H-6|*P{=)nxTN`!~{B@@M9YHDfS8egf= zG}ca!FNX(5A5KoSigxku3;sLIKh+Oh&b+VcT>F}+6P(=xR}}uu+&j)gwhg)t4^$x* zxdxk-e9xal+$ZlT`2FZ+Y=#;Hz|u2wU6a`neODg_3@cw8!@JVFyUZ9_h|=PtW+!*O za1v}H*HEM0LAR*sGfzWHYO! zz0ePc@y>Dm_dTXgV?T#D2KWoAzqGKP;LkR75h#cPK>9 zxvE3#q7UdDQYfn7MPTw{8A;?hFWDVtWso-)!{;S}bQU(2ibz zV>^KeZUCso++DbX$xrkv@2c$a0=J#1ND7|>c( zd~?R&$H;G6&EDL8-FJ!J{Dz-WMP4zAWee~YnkyS9w_Bi{^^5CfH6rQHQ?X>e`4}1( z+R+UZ#9hp7-_J~Z8~2jGe1EZbaq(W{$c()71BX#TZ@}+Yh>pmimEn!3xy_t(GspE< z2VXX?lJAaoxV_$^cglPMX%ChA)vbvE~Z9}9EKRGKBd2t*)9U%u623?Dh6BV}# zq&bZ=F{!#`zKpTXq+P@yq{L{a$ya2;xZghb=ncF~Wi(I4xGTrB7-lmqcRsG>eqE_* zCcpyqE>AUa=Y-&H4z~O|Di##KFU4uq#U7p!rS6Dn>sDwek&*5;-mUfB&62vY z0xo7rmd$f9Th6(RQO7QJY0`vSAD5I~&avs|g(DyJ$VTxl`5sZ?Iz@FE(`EOhf{M0= zeEOP_n+38U@F#hh6SXLMs7LagPHR1o2?rrd8qZ)O-XOM)T|bmrSas}qROE0#8)dK0 z9)H1tQOZDK+BZH9PTTQ=pG}Y4up$tJp@yg|gU0;jG`Ypy^m%}Bqyl%wjH*byC^q3( zPM4@DI{gZ8Lp+)dxu)T0WMwfmu_oTZbLb7Iby6UQQ(@YBUcE0a? zDB0Lxgx^y_Lnt#M7xH*pD`T`E_t7ObcPf#DWkX!62(Ed9LAN6v^A3`Id(IAf{L6}O zmMD{?hE(P!;2BW{F^_?}Jx*!w6`KuJ)e8<{s#!MPDY2nAQamjX9ywu<=u_6*s%>8? za@N6ZPC}kwVQPsi$iU@z;QBU=PZ-liDhcL;p83flNtvI++~=P1%uFNNfRGA^R|ZtX z3KKaVsPHQCDJszfV5*^G<^%{;|9Q*w_bM`MfB(;rcz6GY)h{?WI5=Q8JjaD!0-gN} zdBf>1raog==*L0m-%bdhR~!>l15R#UQycVo zVcPhP5p z+kXl!r|H4Cgn0a+<=h4?qol>cb%2{B0tbOSgbr{xa7K7RZx9PHaq#{crH%-$N5;fEaj(1cQvdQ%@{pdyq~pC#HSNqr=l7*L)v=6>*myreR_$ ztEiX=ho*;j5yBaTYKl`hn?!ty%LEFLiCZTWuF|=rrcvi5PqbFu*LE|wzW9`>p1sf; zxlP26mx@g&PQHM?S2Bz?Fh|*&CR|is8*3r0w#_5FEX^!(6UQwO?n9r7PoB)V1H=+Q zsy}GOffUf<$84#7noqZg!%Vl`84Oz8mZA4M-O-?ho8w-m-!*j7>G$vekL$QwA9ZnC z?~ZYA)HnKrPP;W~b=v(_Q?HW^I?SkpQNwy0?OJ1y<0|t`Wk6=AZj2+0fA1VWD<>6P zPUtd(J;vtfKMHaknKtbCqEM^MF_tx57|F9#5Ldg|?y$I4fXK17Q$#lAG4rs_F|jeM z<0KQC?9w!zB)@G=G7I~6-_A0NJMfg8W|E^>(s`!X9GdGqqmBJvJSTLu{cfkzYC>a4 zvXORNxO=3VaXn{T!&$0VKm!zwBns!jD?&u5df55f0BdP6B4Ff;(u?m`-Fmk5;&@n{xtwi}fpKJdTpqvr>BAowVLFT%CU$Hf^M1=H)2j z8yB2{i^jpm&ce&b!N%I0>k6u=!Lf8JF+9iB_CIR}@84@*zE?Cav=3tNf?qmy>~qHn zgi8)w`{WZZ7lcG-p~X3=j& z{szfCRAU36Vn8R5s7I^t^qU&D{u3{LHwiRBt94{EA1-bG^A~>U#61v-T6UF_t!T5r z59!HEb%!3q&W=CGq|90S3#UwJnPXGO z0V}xddge9#{fgW%tanB3Tx@#0rYD^l?2IQg+RVIY%6!M*2|$O7!(d8mD%_dz-!@PL z9eF4oA1@uLbd~oZMhe`kd{O8b;`cbR1S2c9L)bISu}XvPCn_QM0NInI#yg(J+0D*@ z6}}Je-@NZLXI!;de^aVhxC?<}-~*uqNGQ$SFpUD+rqP7hiyKt9k<;eMnPS~ox!LTX ziTwD8gf7mpA1)js(eX`&Ma)OK>!lu;9|;j_IV%E!_r$+4-B0$F?cCUhfVWPLvI<#V zT$!#AC{Rg{f0>ZIiu4J67nyNH%u1VOl(Ml8_xqlEgH9!x zR*n@m(e|||v1VFDllh_dwK}S!2KsTYjegX=r(Vq5(v}oo1$M1CCqVXQNYe*nLmW-W zlLZ??Bwl9Uj1r73*VE ziV`q_NJSF|6ZEYZG?M5-tpd$9W`aegJxLVj^A=D?zo2bkDK>uQS@up@G$4fJ62y^g1GH-=XAB?EBF(kjhF?{RrUz@iNqG>Lq{Z zfe5-7ErI=17vXMItSWW1|6+yel8nsyPC`J$zmzH~;Dd>$Aih8yqDLYLf!?s>E*9}c zq9oHpULPA8Gu9XfSVW)2gr{qBgi3gdX(nf1FWNB9zsA zsX_e^f{lu(H%gFWld3;;0(f4j-VkGxSPXJ7$2&g&B>J2p4OevgSs=k?mm|%2WKZ@+WTB30R_^XfSz!8 zaG33zQ0+|A5d|HAOu@|0KjhYR6fa>2Y~U}Xrt_jB%CdWUu~SG~gcdx16h3(zFLCmC z9i0LAemAGZc}I`q<&GY6+YQYeXRBOirqE2hKf?MIv5jT?dqNZOw+cAT=c(|V|blsfr@*+mIHc!T6HL@E0e9}e43~7=tsAKu+bUlUA^6H zjJrB+^g7L6w?Ak%M`L2(dT-FxyZ0exmKHCPBbo9=@?(7gBS@_*VPs#H5ixRji)4&K z9pHn>e7AEm{0r3rg{^)(o`$fb%#1>;5mRQ6oEyKU3m=?ptuuv(;QbGAU{&q_!JX{C z#64a>-Te8Bs-L4mjQ1noRv4O3+~+YgH{tLYnkkbzBfO=qjyausAV0^v)}Nr0BOA(U z9*#MaW>XG!sgpyF_X?y5O?$97;|L=_ty>Vd$;H2%`-U9yD!v<`xxjHlI(;_k^+w!J zL%G6SGU$auNxvcM}2W@>#ibmaLQ8b262gP z5L<`r94FxQ5&C2tT2LlSM!{jrBiOiulC3<|kfQ4LB2~9VdrWWLIU)KVD%GGWYiu!7 zIVTIaGPx*Uy*4rElPl^_==_i|b%tXTc&I5iM2@EMrTnC>tZHZ&!B#ix^a&BzM3-CEK%r_LLX<+?C~*r6{yYaRTK`*0tj3r9`^Ni@=V&|Y6YzD$Ye_;=o+I@w>{Q%gS7gcexGy*8FX8?-|6-BF|IcUoz_4f;SnZn(&%*h zgV8{5ZBn_&gKG=M>m4ML04fK5`1LHbES^YiZo&@ECEDpIV;o(Cp(Q-A)fO1G;wR2S zY3Hf&q)1tN@CA|eag>uPf04@=DwPF^jEACZeb!uJo)ZRimkK9C;Wpb0n6P#H08Q~VD*?a@<n;#Wf_w(iUT74S@L zbaxH{H&XqGw2Gl;qgK7o?h?;~q`(GYdy+>ef59*)g`sKlDj<2o;#c0kjj;b2XuIRu zPZ2d$8<7ClVmn<_i86Ivx17+ZO&~pBO?PIjdcsM%NtSg7a`nk;T^9 z+sWCg{LkGXgfRKat3gvz?BTieHZj4J>2Qvzxld`1*>kEhO|W7~m;^{W#Xl9Br7p+z#S6esKzBpyT_JV|%OE7L_b2{<-Y z3iShJp6iyr>pC(kGnehWY!m&>w(byt*gcBmL3zfjH<`Yuy9EB$rbih-51R}Y8W1yx zemy(qyT%8{BhEGPDzVZ~ItV_N2%4R)^4q|on25TvRHqG)NeCl-%C_~x(-V5Y3VDG7 z)BS+`KbewX$@I?T?b**&mgm%Tt26BX$x9J4x_HLHEuHU7-*nDUofkj$(E^_OC9?zZ5HQv&~w%ZllAKqjNOF{uT1+BVZo12prP_2bs2EUYkaUEv{b$ zuzhy$p+K`|jzNjPXQ$NYu-d5C;J>{-KXJ-#z%w4UC!6d?H$D7Dv(6jt-rxAUdE*}& z_4@w)UZdWYC`~tlnoSnRrO#fQVC=8ChodUFG@E6`Bi$ZOO4-w-7BfI8 zE|GL|n_}DWB_=V5AHa^o-o(nR23-%-nT@bwsE9(C0eWLLK9@ zPuUt~7UabcLoIdoYu`t)*9A>}+RsVXs!ncx?gvX*{N;4c)x4Kw;lV3H+#^B-Ej`Rh z_si5S@+%=OHvx->k@N!Q%Ceid%g|wF^}Kk4XPz_4RwZOL=(495w8NSSM}#ffbY_D8 z-2-DBFMgV25x00kE&@U6%yVw<&ZGSB@1O+MUvEv@poiEDp0grZe~EPr33SygmULv4 za@D1zk&=5JL_HC<2^P;RV|H%+eq8p|QW z9q5bojHlilL**Qe1k-vl{lfbubJQx(Qn5Z4rY3t9|BBGbuOeL|+?T$lKCun@+%Fyu zLNjneA03>Z2C+r51;Hl8BZDPl6Z(C{xnNYa zdR5uvE;?`_Fo4cd;qaggqJk`f{b0!PM};0~3}=?f5)sZB_rDNKR#!tW@55f3m^%@` zM#Qm~Kzk0tfV*XJ4#t)#Rxq~0f_WUM$m|MZ$GgFvQf8NBz!ZaF8zTEKs<%i~#gUIh zcozCKbVhjwwo~S=W;i@!urGZ}REwrkCM^~gko9R0sxk)cE6iNX#1-AEphgz|fcxl( z{g%<<=nmbm)DY>JSj(I%F1J?49b@0~l3MI8I0nf`17_ij_1`1xh{iq!9y!-Ue771p zu%n!qkY9lrbqE)0KH;s1d5}lChJH3}Ql0Rej@;WvtVOI(O>)f~Fqp?__Ieat(6M#S zNejT8zr(>q6py1bbc^m=~ghwX7~>rI>O-OC`xu*Fw4N(a=w3T9RK1yV#G(ca`$K^-1u@c!Nfk9SFi&hRlpC)O6>X68? zoY5dw4*`}3a-~``oRK2prfmj=GpBG8;=MSLk>dn@;9>V?GnwUSFPOR9SH3DAs~M?F z)xew)5E5}>+}~09D#?^c7MRAk7EZpyv{C_{LB!*YX9hup)IgaCy^kvhOS%ISm-Sp=7%l_XOnc%yIhM(u{))^WSj@79~0 z_Nb*d2BcYUHtOwelZ^X=c5g5mbz7~5(d~8XdYg3X1Ebq%jG6;|gTWi13=Q3?uY0B& z$RG~A)7E>$Ab8Xp8>DUEZl81pST|aY0UkBmc-(9^_0~8i$RnCxN_dB4(Z)jh<)?Vq z*nT;Xbwc|i7P*d*oJ7k9ea|Q75kGL;Q~^FexL}_h;sRZdM1Mk4;ytjj_yDd0hr7L) ze-U|Keg`&-&>Pp|8M#<(bRX8vZn9JBMxqN5B!-QuYWLko>AF=bo1f9V*iS?;f3d0>}a*eJf*6#pVi3MY%e~P{b>j0J=gy<9jG#7A7TeW{m7?g>Yy7hG`-!{Y}DIXost&esVT zFl-;Te;GIce^l9JX`YN6#uizA6itEbrtZvK$A;<^V&?OhV}&kL<^6Jal3C@cGs`OT zBtwfQ*c(wO$_v=b)0FDy=HUZxG8gTp`z=%!*qemRu8~1@0n$%Wodfvebl*8XWK~}b z`IAjd`I{`GLMHK|r->x#^r0e)?g}K6)I_v+-i&BuPYD@hzHmy2C*Kk51tWrktl~6U zt1g-mw_~kL#mlMgXB>^NWsdL&L)_<4;+Qn(w+8*u2;)IZAGC~muiozJ<9egs>eU+^ z+#8Mce!JgkHT40h>v+)Yca8CYjC%dfVALK^!HIADBvsrRG}?N7Fz&TUzuBz!yJNlI zZ5SP++3#Va-Xo2=PFfA4r?(rrQ74UNr_&`JtalrFuRWqv{|Y^lq^q~PMsw5|=&eS- z-KvjB)1YTMy@`!Mui0)l+Ji=C)FSO}quFkCx}%YfajUNnI_-L+SEo`PlDe9Dl5(qA zZ;bl5(d-#|r`2wcTMfNG7odamb z5d0MNZA&mWw{Q2IUv7TmPbs~eI+7(74TYx7-151Fj)eu9*bV8TrHbb^ z=5$p$%FQRdwnAkA`DIJzwzj==ZgRW@tLJ90j1KMUq+&D`0S z%GfHKT%3Y?eVE~sfX*@Qo_-PFAj~WiM*?<8&>fqd>V-$U3ey4yy#|iF<~m;RE5p8H zqt|Svo%o;J*HS~gXild15yaMmTzWo51DH;N)S7``gx(p<$WhRYgr8^>22fu~t^wFG zxI==^*anM=7ipC*Mmp^TZAwkeo_2UD%h-6yVO^Q-;prLU{RPwAA6f+4nOWPeOcx!V zp0VZbv+t$D)1gbZa`~;f6(Fmz^CJk2j(cS!nxNaFE}mM5o;G7ONH+0E#sg(kn@l!2 zmw}P}vP>^SV13aonYZ866@um^jrx>$4yqgUtz6}b#X zV$szWcgiCyz$j}wVt063OE$G^#?6b+n-FbZYj%FnDybBlTBrVlHa87t@@r(-dE8kL z&I^G^9g%P_MISCdDFG1Rw`3dW!Bq9xI z8~lACjVlOSH~5al%-H0bisWMXC&ZS#$J*F4?Z9*PUa`NbN{f(Ej&pAFC;2FzX64g+ zl0@pnUSHzGt`PIc*fJ;6Jcl!|jozDhHMr=3>?hJmZlnrx0P@ zH?fppJQw(GvWWsFr>J{#j7ng8MsoXM zb@Ml|^GshMhGBi?^= zM=?)v6215cDwC*->nkwk3V?ukGoC9$$z7j5EhUmUL~o%9eT|3jB*f)Wq_3hVF%i+O zbix_`Y1samM-H(*&HBz~yu$sBXYxA1U#nIA8if^Aoxb>$xw;2Vx`CXdHOq;o?Q5rw zD5)&VUr>1*&py3pJ3$qSplIJKi(jsKj+LY^!+t=#m0#yUT~*h@HYr4<27VJ#Z4xIJ z+R`;2qD!y2{}|nBfjXme=$W8*J1`8#_CMOz9o_qv(Mm*f;*sip=rEaWpv4X1nuMuXk%RJ~ey1H9bBjJqbG-3|&cY;rQ zNk-k9{Z>8smp0pMo9(@sYVXfNTjaCeuT{2458{?s1sdI}fLqDPTVyzKxtUk9Cve1$ z49W3`HDg<)?eMyIJk>$Q9NoKau(iW?~LT;u0ZO`-r(-{K!WVV_UdW*Nr(lJL<`}R&X!sol8N13H4CK%&u2Mp7YY$20E z7I`-(LwHf*GPxF`oZ?1SsCvWHgdz*&=+4Z=feC3HfoZ%61VngB zsYF#MRyPB><&ChOU+6>B4iff0XDsVYSKmU&!~x6hdMFYzq-$%^vxQkC#ZD_X!;U1O zWWh<0T_?v*Hu;$ofXVnoIC$r>hoV7AioV7pg!zjLckJs%t+&Uq@gCRp?!A(Z098hm zr9zbM=B$(KTl`n(1ULyex&Cqgn>NLsLI0&kWdMj*p!!Z?$msBsex;**k9n3!^}(O4 zX?7k`VX~;D7>DDvSidtt#)N4hA6z}b9XVuL@FMOUsxfRSUk;u`Gi}-mLfa;mny-hY z-K>hVn~+$YZYl7fxKcxBj_;evWHp)w|M1M6^jG#8^ugDIWQ<`(%884^%QGpMnH2bq z)tnSG3g9>(A`{M@e!M*1M~9*35j(K%DzV$ha0qjg5Endh7Er%(%w z@iU=Os;RM|HOTLJap&uS_3@f`pl^v6?J5)+3f5tTuH4zbLIYJFTBtg*iLZ%L3X6Nn zW|b%d5cTiy-N)Z)-+n!L|2`4bN`F5;_+6`LCufJl_a6^`<=vJsu*t!lA76a@bbd&0 z9UUAFKmK-netvR9|NQym@2AJ-^s(d1UrvtLFP~11*w_y<$FAa-uS<>9BG_iD?IK{? zPc-0U-0tGR%IPn~a%UxmSWOoh7R&}6Ts8dmJa;A6+ZLSqD zcvcpRT=R69{5?ODY&^g@nN==7))^$kF-xw@aa!KgfNHlHrA0W{JAN8YVTI#D&>8I*ecN%tK4|2m`05wgOv z8yy_4Rhu=Mcd^!#fh6k?7wCEMyezCPGMTxKhrK(Vzc}O2AG6I?b<5l{eLp1rUZXYW zLeguIh==af+$eka{seX<`*nagRE7iHK@`&tG2s;yOhcxWxN*EI44M3D=p8+Zao0Z# znr)^S3RtZ&KO{9)-;S;j$$#O_5^234wYO5e*^kmB)zHUaO1vA>Cy)gC4*aW3<||Q? zJmMsoJEVaqP-1#n+6gEKZQe%Xj&l7RT`)TxwtP^o@WIMS}Nlm&!Z_?;!e;LZOIWEB+$$$XuL)w3B;65~&^F08>Ma zdI#O2rZ2OWMSf%s=sTzQ+H^uM?*#Ow(X9I{Cph{~)T*Of)be-Joy|FQH47ZNVm)S* zuk{PS=8&OmLAEZY(NJ<8^78^@E%VVEJwlgIC<-d;DQOUS)VY6W>r>CM&A-U6egBmC zW~IHHqo*?5=N-h$XR{m{#2Y)_4195aITWo>WH>f&^Cnm11`^FJct@lgCCDJY?wKQY zqI%V=*L%$b@nRAA3A)@q&tI)@GffPJFhdN;Bzkwx^&DM%MMymEJ4~Ano4)MMR}==I zd1O7@ z0OFlc_H(*=WOBvB1KNss-AMH|`Ek|lV*vZdFXG)erbs2~ z2s%87_2r6WB{5MM7n?2Hz(2OQ7np6=S?6C<#Y5;y@W2C#wJn*;6aAY;Ea_qFgV9r& zCw%9#mrGK(n}L-3vWy7iljZbZv%bGZW0Npk!N7qmm#%i8!isQ+Vm*fk$P>Ar0nOPC zGMpP5@;av3Trkz5qFPPxDuZNd&hbydXa?S$Bn2Pg19rtOCsGG5ZX>rAsrv1|Diy2O zY)?+2EJl6u3BtTYI5<}j3||dLEk-2cdrXGEIrn!^s|NXK>fES_OWFPku8us{vQh^7 z^8G~>-(VTU+&LoglR){HjF_F5C%x{z=&fLB}H1*BjdMF1SNX_*8#0 zA_3k7HwLH>#Wfis%8a=yJ1D@`6*~}{o`GEK1$XK&eAp%hzu3pDsU7AWSd~kXz{y!Q zvl@uAs-f^{hV_+O{BUrnlmr6C(QCVj)^GRae+b>}EC0p%;a_ER1ZcwdM<3`DEX>c9 zL2MMMMb9J}Zgx5~@qeAQb%V{|XUF?hlw8W1AHQQ>YVFrgZ;z{I=O6$3-_^r|(}VMW zBU3Fq4eh%w!BB-+qog4bUsQETOP+eUD};qZn;Y6=zJ4Eg$p~;x=Et0|6WWo%)0xf8 z0L_T+b6@!pp)>OAe4$=)&kZeWuUT(2TZ|LLvVOIl8=IS=O;V&pj{=`4fhw!CYDOf` z-#h;(e;)jYf8+DxgQE|}wV6?yIKj-dHrhtLUaxoCZTPoduP6WQwCjz3G}^s(yWVQG zdhLJI8?9EO_YYLxXfJYpLO;OXKk93@l^om?`T6z@3>6mLeKklDTALDV5Kluj^!@wJ zPR0YG?w#q_zhjRcALcxKO+4Rp?6=sM5cXKcLlh;{^+o5U?P4iYiH~r=D}%N6+AO97R1Z6Whoh|bQH568H(@r7YC!O6J@j8uW{i;v zC~CvDu>TH4+bep;uuwqs zsm-zr=*+X8ygmDwejTolg*{0s5x9f>&WZG{@R4z667=q?~St91~o zqRZRHERNI({T)+*V5|<47|Xt_x_0uh5*s$Nf%p|MNp!;A+zFh>3MV;UNq&lJ(>IxO zGqRkCsn_Jlr{-j8-R+R^m>xTMoX*%Hw-kuic6R>bvoI489MDfg!QQn=Zoa$`JF|yx zYHW87ed2K~NybJEZox;69?IzbJ#et|`2#~iy5`!G-JP9Ruh5xCKvn6R0r7WsepCz! z`{--NI;0qdFGRKmzwZ19HpPAP_5b%1YSrprf$%T9f-YnVA;!+mr6+TyI5uQoP;3{5 zN%7k#6q-J$N{kvEG&Ajx_GM>>h5pgz!Nb%VS3htV{VSB;J(%IY92*_~dV&5%zc|js zBIuW2k0E4G_Z%t`&;h-<^Y?yrKlT64-{|vyd=^bC!+VxknMEB5e$P0antwgnjfmyC z$4?lye8#N3tG-|5w#6#<_TSq@(8Ku1B?s5-@KxW3NwLwsMxSKe?%^AM^Q?>}$-3Q} z0HrF#fo;B@vH80;C;tk)4NuFRosS+nKw@*es!YxP6CA2onKNi^2iyac97r+@tb*>Gkedfx z%i*dlE|%kU)TfY1Y=@OSmw`E-6G9LD5`u2q#S^kTw|8rqc!~;njwmj8>8^b6#l1@t z4=UpM9kJY<9VmiL{6G|Gn2>;S*+u3UctZd7gOGk%c6j!$;9C=)?a*+>+z}hug@yGi zq))MJ6Du0GPcKIU->sqF>GWVP?LgQi-2oiWN0?4{rqZ2Q&WL%Du;Sm?nmOS60r7mk zGb4_z#@7T6^gNq)Ozjot#$yBUNB-dpXKY$jI82Bg?75B~z$B~^+pLYSKV7qp1?N9{ z^h=!oy6tAYJpVn!k52+rbrA79a%%=V{7=_($rziK_}g|u+b6-!&MRia6OK}*jShal zK*y&iaFnR9%nFuy#SAMrK(FzQ53XCUsnFbcg{Ig*7^DNMuS3XfThcAX%@L1w_Kb7J%ws@Tw} z{u)gk=L-2Ib3!wHNMT_UW}f##d*_vs50KTGok0jMOABa0%sLv;!=Y)L!E2tbk5cgi z)3RXX*8~~Zo`9lWju71LkdMby2J4uf%%Y5FwzKmJ8N?;FL2NKvG4LErnb8h2Gd1>t zq$d-rrb8JP_{18sgAG>=(#EViaDoHhb(acGbH-|fvTzYrGuWi#)-gLQV#Kqm?bde8 zG5Y)&Y5#m9zF5`AVECAL#6{I(RMpYzgWoTz^s`nE-yNKs{!RZp{CIl$;o$sNcIox5 zhW_Ixq}4U_<;(xs38uu}K?otDPaX97h*$(Rsranm-gAa1qemy;;pqwb?d%Y_RyZ;3 z*FYqmCAwyxg zNqieY`dtzK42^2UFoVRHwTVrF6GLOkgxD1iyVFa@q2gF@Rx<-4yy8%!Tkp2&gU+DQ z>Gt8SW!hKtgMI!2f4bO)m|_0O#0S%`Wnv$g7=2y#DLjuc_EmpSAJ>~Ik8ZePm)_MI z9lg<$OcGCNBMcOoFVc>j2LALtu_wWl_PHLrPO=_XXN?lbE1v-GA7)RFcb^|BQYyOr^u_sEnkvn#zS+ zl?FoE9sN7iizyWKzaXBO!8DW3oL*P{ZIKB$YO4Lf*OTOXz#DKx&bTwfw^>(BJL9T9 zb#BsYHE;rKWjxJJUE)S+q?T#JU6mSKyfFR#X8BF!BMWU)CU1wF`XizuYP`ZJ^lSW3g`aWC474_a7zBTE+W;FfzZxP@8yixiA)~`}M_5(s8_j}V$51yqTnA2Bs>%vg| zaQ4Q-0eQpK(a?2&$VH7mgbDQRs_zf6>;Ciy_htJ-t031ge)``(w12ve@rU;Pb7S^p zcbDS7H?Ct;!1vJFML(i$J>5S4L&n_rBO)%~XUy_+s#}^|SwBlU-@ZX( z-@nJHcw`LHTszR_@La}7B<3*f+|M3}EU_KP>*r*`Cvf70i>Wyd(r*N?&uGWMTJ$f( z4Rne;4dfp4O;8X>mQ`-6A}wzjAPw|siW5CvFY z62qbLhp%cV$DQ8l6HjN$B`JS0*7_a3owv%O3FNr5_$TL;A`@MpH=M~^?32_~Vgfex zIFqoc%gRu)HnDB)Woq8vr9U{f%t_YH0@vTO2v2A(hRiqv79$(B`Dw58@feTCFATZV z?-RMiF02Y&1|@VUp$q$N@%`GgthdB+ZY~|TZ`uiI#`&#&jeM~fwNsGJR)D0LX}>X5 zl*D~ThPoRLdHsYHkrIVSjrzS~q!ha|(NWGv6Knv!KtaF2*OMpC1}ep}+3>bF8)o?S ziL)WK$R!&Nw*)I6o_#`}z%5p2ze}*Z9$4nv&ErGSg@D;LShBGpAyu0D(E`a&1z3SBa-F8eLdceXP(QoV(^Z{OhhsOhBFdnE6e>nK> zeA=Xg^?Gc5e!#a`bUXcayZ6%6uA4l(^cT#=ZmJWDk1oyf=u#eCGMDVUlgtOxp8NQU z2b&eirgodhI_D%XZI;L^0Bd*e8^SJP^Qz~YCo=q;t#2b|n!X4|Hb&P;nR=D-ji=n~4=j3drA4HREb<_&bcqslf7bcS!|4fJSBF!o26*sL_P zh?%1BqlDONLF_Got|i2NHVWrNK;zr9pT(g#1P3^tEt1%Q$%;M%WQI&zw?acycVzkQ zp@@peV>%L-xk(Q zqW?q+HP>?{Ymr+XaZNL4^rkiGz$#VZ=lg%JhEB_GQCMl8`WBnk*FX1f;RiTtH`(ZS zIyuewPFrtGxByI4y)g}flJKcK@2qm(`R6~U*q{DN!0DOQ7uavKx_Q%iyX_9ygX!fB z=B1yU9{K$9vuRls{b#(f+} ziXJ?g&*Hv}iAzPlsg9{@hI8g$OO#zH%D>v|!FTKz}2&A$I_Q$eK3^zqWx8{P^UQ` z3&mBv35my$QsQDhP@<>#HKpbwee_*&>Xyq;9Ch zI1hkvN(D}dZ%TYq;v05xB^6Ft)Ec(X-fEA2tl6L!tXp&7*d>gh3??Dq+w{YMvEw&{C-~N*q+;pl!!N z$r9Kl4tg3m$PZ^orV%WGPzi*dBM^Grpt)8$UoN14o)Y3bFJ_LVAX_4APIv5pVF67m zFw%#{X&dBhUN~aAJr4^AaWTW*mEqjjTAJr?&wfrbJRrBhYJrL|%u)jFc#i2}`o@)9 z?b}boWo#R*sd09eIC~YG9b5MIqHY|y)5h}M(AP6-L*ls;}S;c0YJ5EYwP{s zUx~D#rK4C0oFBEHsa5c38pQj>H3rem83tV3eAZwmtyNqN?Q}}CQ=*+`gm#j?VR?nGbB?Ow=Pc@n0R$-vhin_KlS$ma=VvTmaggd1T^|8>-1Nf57 zg*(e6Q9vb#dK3_)Kqxi!)TGoImDv+ssK%&7OY8fbtq7MM(C4f~J|*(GH$_j0e4Z%s zDZ>s+?9}@ABm9j!P;C>kot@p*;YRtjVoMkgp<`z2OvFW&B(jKlii% zW(jp31nQ)m#8<>RWx}Kq>pUl{BMpZo)_Dl5Q>F_rUG7UWdvJ!X-NszVW$V$l=Q2Ldx z39QQ4xfS|ZqNgW}o>B^-)!@^hOtMtMr{@Ttk{;zHe0r|%sdQK`p;HN+*u@e$t&pCw zyOJqwupsZiw)vx%KId~WQ1h`c(ES$?5txKr6FcySe}*JXR_fa>BUxcA@^(wG$T4sh zc|<4XH8Dz+POQVFYx%Q8CNIXdyw^z)2MD0X3VsDjs5kU)Hf>5+#*d$O&qS2_L6 zcuNd)h8buok=YetdBe7fC`I zH0DT*Z2~BxyMQc_+$k5JpdV4c1Swe{<WxKqasbqXm@AltF4mxpKYjKtGy)T41@RIg_}Eg$I*>f?Gd?~zzP=RVraY4Cjy z8N@b;fjshONcf?bCn7eW(%AC@=i*Sl%RN1YPS9=dBZvjLK;g*{30N+SpS)rxVdm6 zm2~L$kE2P`vfdKQxw&-UzG)|RSv5X%iFP(bN0n^rj$P79_AP@}YNLOYxKg=?^;oYeKJ#@yxXDe)>bB`yZS^JST8;$NK3H z?eg#}eJWuG682h!(OX?%8Z)G!6;3Is&z5;M$(aPI^T4xVX+g%(JtCWNZ;LZ-hHqaS z<5EILGVbu9XB?MZPlk1w`;}zh(L>L>C(6F`wkKJ5ye0aWle6nKIusuS&WNQ#W<5XU z?ND`;Dw$FxQ>tW2mCUnJ$)xO*E9qn!%>`K*N~KJxlqr=m%h4*8GS}TwDf9GM`b?BE zTg$lZSITTH>z;;EX4~2KG?X&kQYoW$xKzrNN|{nAQz~UjrOfszWm0}J=~_2MbTWfd zCsXQVN}Wuplet&t1il@XdYPxl)@P!d*=pu(zkX(`+4nSbG*5wrPeV_mI?tT)qgJV_ zDRniauBO!0l)9QySF>fhnzRGWO3Iqng1p?NvZhqll**drXqC#ElTWsOuubQ*(>9-BRp(#2?uyUoWs zcq?^iA2mlaKakhgIFK)0W^}MhoveOu{&9SrGFin7UL`J;^{$@65q{q0{8;(;IFd5m zAvO$;_%0fSoevd(*-9PO6MnB)av8J{@?cRZ9IXb35?Le@!L_Q_*d0EKE2xsmP zR=5|sfsf<~Ei%v$+--N`c8qy1F|^d_H`;Z*G*jGT`OuYMQLl6x~QmXRNmQ+v7CkJ-Z7ENYUthi{)IVXPtKdIWyAa# zw{T;sDAv%{>!OZ4hkiJ8Jn@L{mj%B|mDJ0@7ZI5Q9-FM| zxD^kC{=j03y~*fJquZ;XMyFmujYeblg?Z`RtM773ueBOV8MI22@)A%=wp^2HrVk5( zfIn;~cz08DuwhUPv!MXsjgSh#GPMy>baa-ZW2I2&%7@e6JcMs(cZsatn1|qq~6k8`piIA5p*5e`V{xErA5nnYIR-O64X)>^RbjfDgBTg&bG?&DK6L-L$RFi zl##M;d&itJm)1-Nx5eYlUay%M+#VBZ$NN|!>(Y1a{`>iG*jjh&fMFy}%SN(~nu019 zmo^f(wAoJJ(v%vlk+#hO@>GkVr(u;?K{M=K8P1KZr3J*9W10G$mRh#~xec^Trsp1L zvh$axlX5JPznsz2lzizaHazRY&%^3!8=X`?7N31OrK+|(z+^4{*haCEX&u)7A~LDn zW*aogE=bj()f=)=ENQd8Z}ghQ+Ev3+vWG1N{FaSe_G|rfO8($i^i;U-v5RhP`H>|P z9+W4TwN5Y|`SVFw2ezc2sp((3An@x?0M@2;`YYku)`GOWC9ZuQxOTgM)96-WJ7oH3j=Dc+m4CGMZ{9u&qCxIlce_&?&EsS?cGp(kD*6g>u%^1-LVaS=ohm7C*ys5 z-Eqk-+CwQ#-MqE{e6QTv${1T)w~pbrZ_tB6;5%nFWq8@loygndkdeOtwl1*hj7~q~ z5#M!epCI}IdUJ3+*)7i?Yx-$CKC&-QAf<-$5j31D!SqIB0ZuPfoX-PoZ=s4aFUo2; z6=xY{RV2)cYdFg|t1`~&<=~9uHm1Gmwnuecl@1yl_2AwB>+L?)Qkz*;omDn`?Nyf; zb@I|25+AgjYNNS|;kHpPVaD)7%@e^?vkj#Z+7umpJwZ$&#i*^I44mQH z4N;2vG)JUA2B@5wb_`Soo;jHi&ld_SmP~1=W6K&Ep@->Yzb|#-Qf)tyda)q3P0i(1 z)raM`+4#4i`&Rb1Su(h;{5G3kH_5$b>%3}NoDaHWJV!^IzvW@@`Kz3_BKufs?mtJD zm(oGy5meu+oDsVVYCD!5D&^sl|2z|aizM)S>HZc=fk4-DnR_@k&oo4J++p$RrZ#MvM zy9sogGJv#J@#|HoAmRSryzSO$_eAXTA*J(( zeYK+aD|PtY5&)K(BP&8M^*b_ICa;v4%3csc6W%GKo-x9s3=b4W2nibUR zR#3gxY42uvq%_B!UWdFekCgkwW8ID5u|~Znb%J&L!T@=5gMhq% z{eMMB-Yg+`3CW8BMbr0#6mre|diUrhz0Ld(JM(;= zY~DM0n|Y$*h{Xqs&F}-Hz?SkOLqbVT9Bs=HEAAV89@^zGtE_nZq7GRi+;!a42XQ|U zVaZE5HK(7^r`Vn>jDMOomaQA%#w{ybH^O4}lm#P9yMeK#R`}poK~5Ox&W!x@ zhc?Eh^@sL=PVx(d!*-s3OyZ+6;z3o*^7K<0nO@fUr;H61uRa-Pts=IemGTEQH{d^C z28X`n)6r844qYl4_jU(tE)%Tzn3(J6^a8m&ND)fhl`7|#QGw<$`nbsP^YPr?#{*+9 z9%Q(^zv|b!WR&!-QSamdr&6iB0p!$PEunN-Gq1!y+o#W69%4O&>UB87w?mIyo4)DT z+vOB}FN)ah9q;|9Ww&>{Pr&J&DN)Zk_eyA7>LZ_}K2mq=fMK7g_){E%#@5F}W6xYf z*+?MDW;=l>Q*H|Fv?>lTW3M$2N{JOT!`_wQ+^B*e6?3komTo|9dE(+_i_+Y$^3@=^ zIm1>`Vmw8q>|oK+B0UkhseUXzS#&nwuTrXHpYxIA(eh=V!OZ5xU& zXX3CW3J$dDK6C1O!y_zK!B`@3ZdOv=CGi*U#nVJ!Pd*v$ql2xd5oW#>z1#w@WthJ1 z*f!Av)8;jqQ+c>Nf(^Q#^Srl>3Tig%6*TBT-rHs@@9hmXDWz)QROPZ_;TLt>spH1W zf?E$9Td@+}>NMu#tw)PH-)20<*9g~_iv_P6_ZH#p^ylxT`cWWqrn^)Y$Aq+8 zHdB#`w-co3t^Y?nXLEV+le<%y`DiP>7VZJRCi65>l&D*D?G3SO4lNuITfgIBHOnK| zy=7^yidCr`qyM@%m_7hvWzBv6j=p`PEp9z@#jfcS@0xgsa~-`ArM7IxC_{Aa3C3=f zGWNxJP?Sh&<47t)bGaInS}F*+gi@SUC6wA?D3vU&SVF0n0;Oj7wuDh7jC!FkspI40S(2G$qUt7qVi4s5$C z##cn}#v?)K*+V_1o!&|7+CBRBHMUGc`8z8^ zZ=xh@1z`wjcmTk|8Un!cG!pmzM%h_GpKP1x#P_jxhkot*=or2aI_KY~L_8(pDG^VJ zcorg_w037j$kUz=c}h%!N=)e%yx%%2gs zc}70NseC;taFdT|02uuA2QQ>^N`f25yE=0$Q@>m6Pt1`F`Vn>O4+v-IlF9}$Ta(m0 z%}tJCO7QX$a-2UJcu~docBDDiJ%R&**fyxW>eY==tR{hG5Q``ekY?M6r#25=L#06K zk=oGIO)mbq!J-*1|gN$sKiDO+|LplmDp%q6;iX_S_K-_ zOK4O=qvsBd&L{#Z0nv(p=*%%n7*xWb5(bqpX!~GLN=39H4r*>7h`q!?B@WtZ9CYd! zS(0T8UCt z(xa?Y%Cp%hK}rcyo;gT4#WMn3FHy>Bh91Gc5~Y+V5591gK%X_??=A)aEu$+XRYF@{ZxAzK`Cm3W9U`alBD)ERfQ5YW4J9fZFJMmYP6UA>mF zs{{)Ae8*m*je5Oa z@3!0UZ@pem{M%}@Tb+M2+P!wW-fFda?SIsp&33)>4^+R$am%0353u)-`r2(J2lqsN zs1(y|h90>@W9x6~_`&}+n!Q@RRy0=#_t zmOp0tAo?3|y-xnn;kobMl~%G9J!8`fh&R-y*tFx&9wkS?9!)-!elX468h^EBvrx<0 zGzi?G?$|bg^WkuYZ9IvwS`wn0yfM_%x-I3I|Gz*2^xxXVaV8eQuIblwXST>j!v8JoAuPAi3q=Y#>7KU%sCnqClMYe-jT*7wN& zE~)Pm^>E00ID|fAc8|Zymj1kk;jtgJ+`C`qP>1Fh5zikPT61)Wo$3O8n#+IX!RUkU z@dok-jp9o$lOF3`frb@<%Vu~L8#5`77xsAQksHs1rnEgeb^Sf%95jCjbMEHf`;v1f z`;DxpGg+s>;?0*#>?e<#IZ}$!tihMaUZtp@T;flzCY_W{P)T&oy0a7)v#w^YJf_#P zu_d;!g%U_N4R7dSdop*W&S8pZC|W>`?5#2O7N5Kpp+|sz9y9U?EZ3c0v)1S?)uBf7 zetR^aJ?bylrSAQ9Ng%_*9ctY#kM{SAccszHok42~B|q>8o()aIB13xgbwbcq)iWe( zvZ?srUo!DqN-;~pGO>%`+$q6UFufmatH4&%y>3hN{Wk*P;@zq9g?%dYH~KSl0)oDO zF9?X4ykx^TD~541juNr{DHprxBLf>EXaXbon38(=Oi6s-Mf^;>o-?6WWDiPBux#di zi8C)YwaPQYJ)ar!m#FgQgP#*vub#)LVBuKMs%HR3`L8E<2Ji?r?n>Za0{;^Dm%zV3 zmrCIOn7|+Y{Sw!```PAqA?cE8`3yVi$Mch4PEHTr505S`V-|XbW-g-vr4VQQkqe?b zw&A1i-(xm)Ys7Nwfz9vzr;E$u^WoX~$KOtlj*pW4F^+{~JoB8u(H-k!hMyS{5?qm^ zq07Dkm!uq#&8M=ourAg};!LAEvzcQT=?&OlEHaPd%Kf9z!<0@o+c~`%zKu|+cq5Z? z=97zPpOZgB;s^d2@uHWr&L(-!CQmBK17YZsBj?6uY#02CTwWJjI&_O*J9JODg?_1N zTZjdMJQeOtIL)fw$!+jku=xBxXvat@1S%Kgv+ z%OBo&*mVvA#og(` zo`M)LWXx4u|Cd^s*629*;j9;8^z(I)^K57Q5!ZC*tI#zULx`8Qca6P0FSPlGX98@G zS?T<}Tf?u>-`Cf_rmrQh#MMmd-7lHz?zswoa_d^AZU)?tmaUEk{eLq{yybFnxz(Cu zQQ5YonrrxZS?d(Wzg;VJNBuVng)r`HJj-^2HvH6d*RX4{ix(nbNe!)X%}YKVe>p!p z%-ly0Tr-OB(tc~H4^bJylg1 zoW|(Bbiyyb7afQ#-zbjKxh5VJ(9-=x2?1k_8qOTs44g&w7}mkmOSOsRjIcE{BqSfs z@U7x%k~)v(*rJzYPr4&Y50us^ucG5ZbSM#vE4BsEo?|^QugNf*8tq=EUa!~Fao|b0 z$#yu&?eyM~-b+^AJED*N{bhuitrY)thiBFjZOo7VYBn0}RQy+~*DB+`9^%J#46?t2 zkZBZ&`PxB&DV(LcC5X0f2HDx&hTP&^H+SuPg#`9fw({2+cYdMXOX zlDFul4n50I$mE1qF~^-l@P=eN0+9Cq|`d`jyYXsiOGD zVL#y7lpYI0+*|RT;|G5Hj$~hMJkS5f-n)Objb!`c^Xu1tMUCh?z#QAyypniMW?cd# z?HeFIK)TP|PG7n#mF*g2m0DGTxYL}!{kv+{L#2m#LkLmUtZ6Kj>Ro$(YCj90N!ud! z3XfYA=7-9#uw3$nEg}T=g2j4ZOPOh!?;-?MR(+eDv)n~*ZYzh%r0*)P9=Y;w^IH_n z-=?lvT(0Fg+Y;S=YhG#mX26?1(^ZZ8G)NA?LM{KiKzMRC;02Lt%a91W#k(a+;ZFM= ziHc@v6;))0W%Da3n37f0;uwQnQqAU7)mQ_r`IQt*wkk})tEaWnioUuVz20RVC>m;2 z_CTS^ekSC%23NV_1x`}5vc3)XxSPYnwOCHslK(E=44EUtmhodS3=0=WIcM-L^DHdh z&Bx)aWz9q{*_Z0yRg6=a`Oo2;+UEVi_+)kc*W!wEjpiSME0*lsYgSmZ!spKljg4^6 z<%AWHI@CrkS~$Rqyzb&=+6}0{7&TPcG}xx+DzwZ7zMYP#cU!UH^)y(v_PK@&?)js+ z1-hxdf>TkY{lTpa74nr(lrQ*i4nBXuY%Ron7;puf}I8O(XPi z)aF|EbP#hET4pScp~ieW4QrK^Nwpm7t87|Ywq*Y1UXs(Pe=&_KBqcExlN*{iJ_8a` zwjb;jXp~K@ z9Qz}LTq~<=LaarVJEChH(76Uuj(t?wCdzin|6Yb#Vei#z6r`q?8F)1+_`yS)bQ$9< zEsB?on(^&xv!`B3Rdg#Gt&EoDDbQE4%F?Z0X^)keW5JP@z0Oe!mqy%}GJI_#m-^q_ ze^vHhEG7vSELjOKp9~pJg3_y&eRYjs;FsHfZLF?$)(ZAt8=ciU{`aH&gZSS#ikQH8 zzmH4udJIzB`Jj6?# zCR*)wn`m`oqlvo970GVAt!y~xZ)htdiKz7Dw0k&j{h3*wl7NarZ@qCu1f(!BSvyqP zo@1LW2(o{uAnK6Fy^vVTi*ZE43Jd8%9=WW$DifKv;EzUlG%BYL(s|~Jnd6>EqPb4) z!OarQZ8)u6E79C-a^bG7+uxO0<{mJO+=HZw%cVK1GsW2*YWtnrd}sLlE{UM8#OJvO zw+85&mjm?gC=GOt?eClg`T6*Cc z%NN0E!y;)M((r(LhPucN;k1Om2+_YCP~jGP_E3 zB=J{Ia7<4E?ImJ$l02P))^X)#pZP3}1bq1Lz(VzgvgqOhefg3Q9)h`gjKD<3#~|yexo^q9~%fehctX+XB|uL%(=9 z>`^I*h*(g>01p8Zd@RVAC9@}w2@cZfkR*tWP=01=I8cir9=@M75cqb1z{~pp0+}eI zMglbwcvK{S&oB+an(cwn02Ci#f3AVgQ^5iYDC;UZr($AUTM0+y*{TsjjSwEbpEW}G zb`e5%^Ijmr6?VxrM5rOc11Ty1CnSW=B47DSJ&KaSsu-R+Uf3rB%RPn;VT#a)a>r|s za4V3&;#!+fLxg7l5pHbRxZ1r9M5y%%HAK)a9?Z7!Qkw+%@+72FDsF4la9Iss$-v=> z!;jtVRpf_~79mapg5(S$m_ZtiYXovP1d@>7YYb9jknaM6lD4wj*r)W{zE-I%QnLIk>!2M4f8u4+7&1^IbJ5yofZC7w=|d_Vz`lTpadxruE>0>_FWi|qQ~LV)?vZEp|&cuJ$E zIlB3wwr&`^_i2vq$%oy2E2jzBX+i^%po2RH-|ZIZel4)61vc~hSvmmESO0Tw@UWzI znS&44YJB)@;lrez{_5L^7dYoQpGe8Plu1hQFTjCo~iD=K$5Sb9m+*Qhw0rd3Tp0JbJv=?KJEo| z4tw3KLn+qm^#vzM;(&;ArtJk0 z`p!)sR;%Z7ZLNk5&lNg6fQtWC!tFDX1k@LgfE9F0PaZ40Wyv{C0urDzj&>3z7pAuF zuYtld1PafGrIyvjb9ic<=%{9?w`ZwA!s2Q^nh?xc^ayNJHT2}UsAQbz5c*m(&pReM zubF4fJRkKw`l6b5u6?~oI&PNlBAs|fd^OkX6Je_lBIHInwi>fUoCJZadENo4MBrr7Nc$l4Ok*-t+&(R8YI*p;YovpQrO!$vg|rb z?>EMPtIw=;C?6G_h0R&%UU}|q9dG*w)pe|1zmCJB<16bZo$IF{o)><6G79mSYXmXE zQyR`*fAac+v-JuTAJhtMTNm3*C z1y<)g{|YSJ5Vl~QN5SQl{GO6zcEdq< zZ@gls^FiyJr;)MSb4Gk=hY}K`KDlCE=TDkMH<#9L3aWuS@3K(CPVFA~OnkT=?IsCJ zjszB}8M$@b7)|OV$yd2~@J0#wJtdJZ=h%%TC_x{Nf{+wAg$=Z|Pay~tI^G_jqkkQ= zwzl8rXc*hU0^9yX>_lSGdDhSx~!N%oq%yYo;W*r!y2FHauYH&Os94j>Z z`jdC`uY(d)UPdi+hx#NhS#mActL1vOp#A%)$@R`Q?d1rmJ?oaQ z1$^c~wSaF9I^C?jqrW?JI)??;0={dY ztZP>phqEUr#geqjp;XUEnsu4o!2?ROO2og$;F^RvB!O5 zk17+hTA)=BXw^1mwLq(8qfeWSmhbTMY-?)E@0yQ31RuTcJAApy@8k~uco*f(`l5Vq zJifjtKS>V%7zvZs=ZMSK9Y%1Cgh^p<*3yTi74T6e(D?$HE?*gz~TAu){M%S;UIo?CljpZOnZgnD77bXy(K!_pl;^`W@2z=n&3m6P?=4?*=P}>fioIsOUy1n! zgbNyhTghW^V5hlng$?gyU9Nd?&5OT&KOc`5KZdS)W1g=1MMknO(^da?d^~uL8tTof z;6-U7=V_?xt9^|wZZAZi2oawo%6g7h=Sr5l{5FPfH%1Stp(hUr@_ULSK|`|C zX>T;qysPa=kR~AGJ>kS>QNT|W*;b6WzS>q?ZC4I8|3!OPkjR%~x*b?!FV+IoF;{6L~b7PKikBq;^-J(C+3n zVd!R^SEk0H4=>EAhcHIUK)EK3CNH=!?%G@mUg}W69lWuKF-?swcw6YIgg4*=@-m zVjjQUcv17)n%_RMeu&2ME0HDSBls@XC6CfRZE_WN?4 z#bfQASaahC;KqNwj=4q?LD|Ph!6w_exIjypM11)hV9PLlwXpfFe0Y7%{(2((t>(ke zmk*b&#q${P#ue&nIe%OH7!Sh|`F>zNozU?_991UQo^xtB4am=$?-q`E&EB6fdp9BR z?~BdXQSs-pcP9k?!4V=gqpunLlj=&y`&d!?i1%Q@oj)hpD^c|Kn_C0DWeLh;*j z`67L(X7Y;a*wzcLb_n-xal3amV$J=ZOhTNpEnH{%>+;_>JBrtX!L2oFdkm{K+2FTz zoi|x<4vx@&si{OUNzjx=sko!!d-XeI{MpWmSVX=)+pO8U{C}ucobQH{ zpO7j3i6opdS$FrPdMsw@hy*w}RV4);X9vs^WEzJUZ1PPXy^wNYHqC`9MPbwF_ak+B zy@;K+HqG|-1k=yF+-EWMPaVGm)A$*SII_?|i z5Ux6ZceR_xuVxIAie^mfmn&OwE8cV~c3W9pcYiplzZZeqU(=V|^!>qr>v($YY)lwn z9_nEV*vH%WaU`Puv-R^I>gk!?3ajgli^g9b^Pf*cnod_nG$edQ@wpX=BZmwpfqBvj zU$iDd#H}e23H5nvIBT7=2&h{?XGsZn=k&-U4OB@ z-dS5)d$InP&g%NcM&~c6^B5D5a)Fb-bne_%ad6+rKY7%>lM@=nsc>k`$q5O`lqe*p z0HJpR0ikH(@S-mjTy%t^%qvHM{qkeu1N5%=B0CG-tM+>PMRi0L)0}g)DYRI1%`uG* zD&9HmcH5nH=kj(TxJYKPtF#<*t@FZa;5Bz)MXATP>v5AGKOu6@c(aRDA=SRNm02&my=*gLT1p zh?hD|wA$@9(dx!V6Lps>(3!WDO$7QI+6qY`TwJd24aM<=bV>zWNje2wBK*l#G%I6< zB0n!pl_k5?Q!%&LMS&NQfQrJbc_Yew9R7>o&c@Gtr$3O0VJh~`fN=B4~!8VIVbeyk0AS0ZHf)}@=uXlaHiPzptvJ0M5;G(c| z~~NOVS_0bA>2>W8PeR@-BY);p9a2(q2P< zU0!aYPP^0T-cHzMsD3~4*_1|O4*h+j& z)<>1kMp+ew^w`kF1^V(u=Wy0P)c(zef-Wvr zvd5;ksAQ{xqf!KRbRT^FDD{29IXc9GprwdKt&Pv0voK-H&lmy3I3z-lmLFoysXw0( z_$e2lIw(|xKU2O<cX6NZbc^`&xHkbM@WP3sAn|I<^Is7u`q6>QfD#u9?)wq|lJdb5t-2d2R~b`W~MvP~YRT zclABKzQ=$2_xJ}eq3CuB{OIafnbrJg?H=#)Q~bHO-cy2$OXu;l7<>L!QUGNa_Kk@F zp5-`eT z2uDE{*lgR~uGa?tH9D@*agB~qjgD({e60q)Su3)uF>*P;Z8b=~!j9}_Ah`k&%Y9UQ zRL0UZNVbFg20?NSj|=d)c^%ud8^YyhV9WMYZz5m&=J7=A>Cl_`0{QypQQti3n@4@~ zsBa$M#?9la%jCOr?i=g(dEdC!-JEu*?4LRN>uOd%MeKB&DWkiC%o z`8#6KQicO#7A&i70>L~9$w(|^pwRpUfxefshAdK(!|9!-Lp3gTF2|G*2sVA^{$|b3 zMZTXR1#}%?d;hAzB3ONJ{onTBBl;+}!d+15W4IHo&Y_^M?9Xfa6YXT1pmr*%p?3|v zop&|#uA%q0p}c$&PDQIPtGQD5UU7ZxR`gxs`r57Nwle6-u~iT3ksORFd!#{rRkyyT ztC53`Yk#8}IM=}0ysLq84V=Gy;QW;QjppL#?tS9t+T-ZE#LqQyzPrcK4Uly0d-Mp` zm8Ww(c|!h3mkRXj>q&h*sjnyX_2j#{o;>CI$5$8Hug$x3tlsCPqc+BQ#+Q!T?dYik z<$HEOx&=V4U6E>6q;KF*JcR4Ttxikro>aRh)u-j!r{%F-mTDnO#d)uVEVYm&dshot zzH1@N4dozD!ZB&CEaX)!3n{HjEepxs*N#b#?U-~~Uj6UDIq7Ejv!N@LO-kM%3$1n3 zx$qKlMs*rOVDBFHCuEAVwMcS5JPGqX6!Q8J%}IuJ?ONlG%KW z4zGXGx&e1bIWynQJsp$J#iIO_#vhaLXcqYuJvWQ&kia7Syn2@B($A}?=hd_`*9;la zh+23lm+C|%pTEQ)qG=AAdsc71FSb=>H`x?^`I9TQLv9M~9=XeaUHWh&a1`Jq_z5Re zvh)9f1}bO#-nN-$)vFad?{~NPXR_($v8IbTGLqch3<&oV8k;8XW!t)D=Le?Mn{49B zZa>zRzRPspdFQXzJO3V*>Q*w*i>vLl?&nDStZTmQi8!zL{%ahFhnnS@eLU(R$^`rO zv(*oEZ8zE8NyRr03tOtj{6sch=KzjCalbp+cwbwibx~Ga-RK15FU8pb&2u_BEI6n>p(6-(MTL8z8sL zM291#A@w45-rAh#);+=WGcWg9O#M@mSONjh{$NoihI4fKumRBC3k2HzeIgR-gR6IL zs~Q@yHeTIa-~PWp{h^+oWnxkIeNM>fk-$o?;WaKAf2sdHjekB3X*yjQ(U9KnlfQKC+*WaL-^jm(zpe~vv?3R}(cna&7DFUS$Y(0d&zQz!glTAgM=Xsv z5sk)|FQ^S-eBL%Yr)_ploRA|B_o0i6MuUzZDg{~*(-?MHOBYw$uT2^HCt3-}*-Dg# zAzJ4jNz$7VLEETiOE&!q9Xv7k<{o$yI(qS5jw1Lq1 zgoXsE3Q)|Esr5`!+<>&?z&w<-RMiYESkm@_45n7qBDOov9ha`!JAY3kN+xB;`b^PON z?}sn)zZbo#vYx5y?qiaRMMsFnD5TLT;uCg`ROyom<04yISkN635?E2E2m+S%q z71_E161wG}sV`qzh>lRi1X?1$mpA2*F~LQGciRjMGngQ z;Y;#x9KT6lP$~UPW3XJCpeA?*k4^aQDQ<``a3gW)3a-T za7j5+#?TGb-)%WTvcIOUxp|TE)@nsWNF3aX!*ooe*Ro_pgq<@vWxY}OVuCI%%3td?dSg!!T5Vft1|bixnQzI4MPbIh2A^?3rjjTn zs)Tu!JB#`#Ey?X@x;8!~Z4yZ^AD|_c*yrk5e{i!bv z0uiLtVv1gZAreQebJP+j!UDDSY=aJmv`4Gzi!C(xaCCh5;p1`t;2mmB;iQsC$Ys=j zc{FZKG5@`XNW^6yShK0->mWfWBj`d{#Pe&Pogp!jlc+uvZ&`ZG*&Yu4q2)w zyChZWb;43X%=@h%NC@XN8mpJBb%f!+n+R8v0<%B!w~YCSYRb;Y_Aq&q&|nNmt^`hp zNvDKL1@Q$5;2j#mr)^}h>ZSN}m~_e%?SbJQ!W_{kpgxwJ9?pQ}NSa9^pEMTar9nPf zlw3f6+Dg($&?#w=C;%h%MOl{|8(OU5*NZoWl(OXB?(xaa?%S=8d&fs7Z~J?@8vPaO zzA^s%?%L5QmcW)1GL@`UE|-7`0SQlrT1htFF^ESsxWp6%tH!3ZD|h&g8vU z-n`?4oKcqYaE7Kh!eh1XR3Dni$EiHi`nT+D$n;eg3|{$!#;P(gA)G*!ZS=G3VK|c; zT@H>+W13JOhlmY1NzOF*m|!(aRol+&C`3723DtB32>S`++^h&(@|rNngn+R(R7eGa z+c!37U&AwK62&BubdDn~@8bom0bT*<+=ven@_R}XqUKTVDm1}Sz}1N5G$$-HOPCNG znssce4fP=kXUI z=RRZ(f$a4miSU$Ej7h$}`~q~H%a7Yt(`4VQLiIeIPpCgZA(gwFsyzj(ZRlaSo9gO* zohz6u?N6pGK=?mCU+W9q=K+h;aL&rMQD5%CFf_Xj3RUklqU(!@yU&KiXVYBWYG6JV z=s*8+areX9Mf4{Ugj}o3WrRRd2NX265BhL_)_edi_7Po)h-e31E$%{G zBy#5|fFTdH_uig&bk=RJuD9g9?Nz7aHQv8GI{9h$@TmXc;PnqnmDIu6L#Wl#jV#NC zed5iCEzDYIU2)(l@tv}h$W2$M1D_k2x}qF zW%jl5R>(eYH%4jX!{X{DPsV~QEu$}u|L>PykoUt5#3YZ9v2ya>7P53P8}~?9dAjsT=4BwSZJD{#{*x{=T^Ep+EmbpS0S| zv*2PEE&jiv7-?~i0BPAne|?R-jv}O1lzb%T*=4O$inLT(&3(z}8q zApwGBe@PkvZqY^t;S4G(2&$0*JQ|-X_BtV2-eF2j>3AYw^MC|E-U z3${CuBY9&s+qmL<7}N%chM&?HYJ+MR=X4m(kgZFfvcj^{kN_kD+A#$7F1ZzF5pS0T zm1z_Z4tS$t2g$z5L0@?ym?#|!)FPjWkCG|+a)CbmL(R$-M^h5X$|W@$vNO`WR5A-3 ziX)6dDnv+-I44-%8WkFZb1vJKq&I^+MwC_>P!n+`(N7u&vaAHDnu*wXc}qX%*L=RD zc#*ICzbZNL!l&-ac-}#8D0t}SE{Ql6yLz^c4|WZ+8D1x>4`#)DpfgTsv@>5FE^`en4^n$%VAEXhbu;?_KaNLV3hn1#D#-4*+dt zwbuu?2+f7JauV+u;UaXQ#=T>Av);=VaTqxW;y^g%sgP5vug!nGD`j7LMbl@n95LNJIXVSUm({_3Cz&c)Cj`ekyWdO1Y7;H#02t6bWYSoUoeYV%L>UM zk#_^4cs7W+LDSa)4l3_e>e@z?NQVSX+XToM4Bpr8wWP}+u_RTXSFpxHx$U+Z@wt&P zLJ81=f|yGZGu0VYys4xW=fo%>LCz6pQ$iX=`K7#%u#i;A8)f5LA!kiF=xoxRaZ-V% zcqSnS`5Y_JzUq`@-Dw!eH@bEmE1C{N*$0D)^yV(ZCM}VKS!|;tCU3lFG*Bbr5>6Z9 zheIl6jRkePk~~~5WQ#{wv_SYSTeCL`~Ca{zUUP7-_s4MXHkGtFNjbRX%+kA}WXk|yq8A)bnLqh`&!#z)^AZSsI z54tX|a$LxT0XdMBbI>RoQDXrO$pp&_aRTCYG?3R4SGS?;0Ie0E1@zrcOD&TeSxC7+ zMUBs{JRtzZb8D7gko=6xbZVMO31 zi9|vbZy?Et$SG`S`B2Q@@*NRh&@(D#T6GbSIAk+bWJ~r8^#@z~ZKIl1df9-SnL+=v z(mu4IQ~*v5>YN}Pa^~_OXYlR@V{(M&l$XXf)_OQFI!Q8(YT<||pd(MR+TivWG_Ck5 zLW(21bD(rhoTo~Lq>g9HFtq__!qkmEzYnu}yl+Ve_a`Js;r^&ZV@<6c^$~|LVII1rkh78o-(8O@&OrG4;#9if`gRNt|)cOvM zM)WfY(EipoSL|F;lx)I>ERFIcJ1>dF{wWdMfCWy}j3{!P5XEANHWFj0Fsi>X7UUey zVT*UG~;l83D zmV5|yj+219GXu5BS(WGnjw@W&&hxJR)|NH6@?iIvmKOU`{m)&x|}n z)rC1qd5Xif>X_-0kyGJRuqhUL43;c}Sl@5eDp~swtQ2@t9Le#+D2I|^nQB?230u3} zUR3rYYAT9!FG>TaqCb(J3e*Y~(IRS%y68{z87E_oT8X?6XSD<*bSn|euFkdXQqD*s z4lAuwinh-sOcS!A5b(WN{;7Xg`2TFkzw`Eg>l>T3 z|IefRTR?n5!ca*C^=0(+(e`TRIyGbSS<7z7}99PtHVw74MUrx{!=@6zU0ke0{JJ0N zYj`^sqL5>~dH`EI)4koj-Rwnxox$k+?y0FSd=8V3lhkQsvf;nj)%pFgUV|Q}o#-cvi@_m*@f*afbdgqG^+xmyW z?%~$)hr|0HC5uUd1xqTLdg!s5rnAxN6MO|(Y&b_XlTiS+hQsbDy~Q=DKugVIe+T_g z*huz)nF!bE?=4(`I_3m>1!`i|9~HgOYSBCNqZKLDh|<9pX2RXRy2T}HfNA8n0SU<% ztfOflH;kA`;wEpf%eS7s>f=~^{@9Z_r&lc{b*h~1>JDEq-)1*gPPsK|QmvRtr-a{m zy33@Y;?-B0^oqV+W8TZ%E=;|?v>&-F6fU}!(UJghmHBd%$}1|%w9qta@mb_&{ClnQ z55>VN@c%icqBUYkOOepK-vq9}|J}{i)uR8;`ir$1|3AjRt8jb<0zr(0{fW{$T3BCF zgIvOmRb|@UN8b3ic6JV5d)MUU#jiajW(YaSs&e^f`?h%O;-byZ{NBsX%dY2&GPXY) z9Go2Y_jf;hJbvx1c@6vbX2)wZd>n=+!jDgk&&kO-6_XP|r-Y@#nmUBc#~~=nUVA@u zJ?EJ&`P%zoRa=TjzA|N%r9IR-N8S&*P@ZxrlU{jnVd>y?*6P_5SyZ#>)6c> zlB!AvPf!&3anHY||0?VgM8If^X&l~b8<*1mwe|J&?s|d#uf6EJsOkS>{A(Bl)!jG!Wb;W6Rrz@H44jYHLx%izau){$Fbb&jRm9q0jYWBeTDplg6JHn zo#xc!vq;b=m1hvpBxO-UYo93B{)k2a?V!tuoEuF#e8by~1@snFQ+OJOq=&lg7fsY{ zzm)&?YR))&XtCRVx!7m~WSEY7pc`nl(5^DEgoh|(<1vlK5{W70ewI223U6C|{257x zjLYc@$r%ZiGN@RI9-E5MX3g(mKAc9Ugmdr=lvUV?k;E~C8;oSYsXtM6^Xagqte)T* z!W=D;_PC8s&p=7hL?k+6vnC3#z%dpR1g5+p^=He=)Ng-9A`^*a#gG6$h^M2FtnLQt9EhwGUp-mPdA5A$^_HrBPU8aM(m~8it4y zKQSsl`5L)2yOk%775sNEmo7*oKEQ6p#?ll%<21kSR(dK|^gbK{*^49J^#B2M~b1)7=L&LNcfw8_*?$Aoz49RL_ja|7lRyQ`T8j3O%(AI|?uuyads`;B_ z1Ymz0^iW41o*gox5kYw|qDrfy{k5kti%2AZ|G7kA+q_xiNC^afPjN^`lmzg7yHSu$ z%C%B(u&3NbT`~x_5twIH1Rj7&Tz=~m!coM8Vpcu$<)WbyInhY%?TT6*q76PRna7Aa zP7@(w-dkB2Q!z=0ZJ$lG7}rR1{gAFGQ<|0T+N(`4v6Bd3N+Ll5<8xv>8Tb0&yXd%T z$Q3=>QqyTec}cR6D#CHjl2e?pGz!}2M-ooWa^cZPn{>={8$y8=o|3lO@N&=CNiudg z86g5&Rgw+eb)?Z%elYe)&CE1}jw6$t&g0N#F$4c0Os;Mx@nKe$%C!Vj$A@&@&rPp;F(EvkW>rBQl)Ruf`pEj&%BEI+k%3{inAS1t~sUGsWzoI=&UBYQ^F@(F;(pR@|np# zXkqik4H{HXC9A|Ii5Qa%pwp4tMB6se79oh2SbIvugaxntghl^{4fA8rwcUIKtucw@ zULq}71;6QlR2biiv8XkUl4e^0S|K6e+!Caz+N%W95Yk}4_O$3 zASqWj_)O-F$G}Wdv4JU$mBu{4z^oD$h96R)X!L-|-m8;W-50n(wACd;E|N(DDz8Nd zQcrLySTch!?poDwxI6d&4mARg-RIi930}!7$pEfeP-5_LZ|`LAVXwdaFL=FRRwAHd z!X*(>fAo;8ZKwZk_vjd?11CH7?Z=~C{p!f9{niK~$InVD+-_j~N)9b%!B!;bmh%W% z#I*xzsUvF%+gB`7J>CTqb;|TMZXv;97P9f|J(=}T<}lc%Y(?IIARS}m5DVeC-M7~3e_fSZq^s`%=V4;-=fN3Ob z3&#*xFm2SRoN6(R1eezyGU{1Cm2W3tK9|==pTvT%WL34u8HEe|3e?iVQP9eoUuig9 z=`~szmqfeZ`DpIvSt2(Z!zNagCi}6 zP(Z(U+9eV{y!K2h5YAhfchO1^@m9=&mVURg06$vlF~~oHh}+|7y0w)#@md1G5e@<+ zE^>&TLpjN3k>G7x9Fhl@s>21UgOhPORd){fek&PY^Ggz)(S$)(adf7G?VDP5qqEB@ zktY+(q^8P}LVfh3e!8!&Fe>+PCSj2uwWg711z2Fcjo^DF6@lZvGL6KF^WHSnL-XDo z&tlR;J0`?~ewz>+$ZMcwc3EQyi}6@R$3wEm$IMRoyy2d)FrC`D`APk{Y<|=S`|jlY zA(ind=Xp_jI!!z1p%Jyhk9-g}oe`TbZiga=C1)jp!IS z{{lkOnJ(ADJ>+#)*VeuK<6#f|*^-YC5`+uXb^cy;{$A5VJ0gAx$6L-X`7Fw)K^@Q- z&;bS>x`_zI))pAd7Uq4QJXuZ?vOwE2KQ-Ble@2HJ(Ci|EBpj$4#(OuoAdaSll z^fxomy!a2UrCB!{^7mn`rwv|MJp*_@a;0QTQXT7yDd#8E*)-bXvP2Jc%m;^sf{29V z3`Fd4LeFSO#)QN5O#diK|BrU}BzM;G{A?t@xx4N+Ej`K)3n5P6;}5asp8z??83}u6 zk#`nNP&FO<5xU1?|3qk~bsYfCUi?+WN7GT|&86%32$~#lMp6nH3Ze##0y-LzM9w<6 zYGMxlF4{p=M|ThtBdSql&M*x@$gaI%l=4AGPXpSx2;Gze@NtYm*FuRNpaT5P<9Tyt zr%K&E;2oS3gSlW>K(~lM%8(XZB`D{V89i?cZU6Y;=L7c>#SitJfhds#@+UM5jNP*R z_I-bEFaN2Udd*3vETAI_0Ti7Wr@V=X@Z0USt>$3&_+)EmzkhH^UFv$pQG(C)V5;jm z-1_;_9z_!IOIX9vbc$p9ZGW(RviD*8eg0z_*&xzwNi{hQK)IvC3NgLUK<=c=wMGdc zw%VhA9i8ld*!j4(Yb*X)JF08Be#Fkf|0|38akMQ-h#-VENti5u)5?teJQ?ZI5X^GmXAyufjUa41M3Z_-Xg>u)nigXh@&yg0^l?UK7yL z*7hD>1}CayNCk+CRYa~E_u%b^pAU8q%WWIS<~U*F1W%R5+k{?y*WbB$OGmrM@A^A8 zZ0X}ITl%P5x`f&SHf{Oigr)Is1@5FGgUABg@IE8Cpy>cHlB{SE$}A#P%O!{FqxmA@ zBoev-Q*`^s!w(;hbB_kchgcR;XDvSCz6e|Fj3nSv&MQX)Wsjif2U{{5 z*P)r-T;xHu`6TdPF6~A$wy{S*50X9B)JEGm*lN;9Z(h*4>07kLhD{UC zG$A9VVjWP9LV8NVnTh|a>QSa9MB^Xmx;wJ=!?Ew0chFaWl2Ty(wi zW}=#v~BSm1U;t4YZFms~brtA=?gtypmaZ@E}=7D_IXvgE4V8FIDEUb@zb>2)6@ zbc&OiHt2R=8Yb`#kOu;2(KV)SDnJ!wQGch0w6$fYRq=o3pNcm@A{>bueWEOtZt;n- z^t!=kDJRL64%yq+u1VK!w}C@C#6#?dEDcIKL%rLU@6c|3-L5!FLmUO?G!PRVYYXrY ziv^w1KL|SB9snu+xHGUZK$MLPNECI{EYJsnhzFRf4k87?PH7a-Ga95g)S*MKil;T^u+e!1G+ zXvGOpfleR}QFx85@FN{hj(i-F{=mongy^!$Iz~eeL}T?%QVbZ+1cF(}&l;H(6-4N; zW##Zyh$<5bHc0(UTfs#_eF=RcI+ffr3K|P`6Pa&Fua10+1e9S-n9sJG#Oi>TYn?st|%ao#7B+ zp`#qh7Ij6iFwiseR1X3EI+QPV2o6FTksiv|YrIDcn@)%hDm79S;t-864Y^yLNM=gg z-$SdsYB6F>2HXYFvir-{r2N_3b+OU7?5&uS2<+wGC0L|XuvA5#sjAb)^6DXvh)Jhx zHT&k>pfMcB#Xi1yH$Xg%W0pX)MjDuC{r^B@I#kiN&`W5y3#lIT4nEozVpBOXaixMl^~oi-pc8wq6Zy-VFu>Vw)-DE80HX z;cdA%S~@idaa1HLicHD|47HDCsVYhmPer;zxzEl>Qlj5rxW9k=5d?5hLP^M?0QI-` z2WXUFz@{+&EqO~MDz%M@t7MZ3DU4Fp{4gHLMkTZbongfS8#5MU4YB223?y%$1JGam zJRuSK%~tfAq%OKOMV<0r$=6UJ36Q?nFQDIs@u;0JCVo>x*Sdx@3P=*p5b8U^hes6#Y9eZde>CZy7N&%RcTOv=&tFShVf{`-Og)A7^ORET2XYNY~1DL9D?Q)LIMSUp6~iu_qy89k&s?!vI}XFvu~IvtV(`eVZog2^}n#j~s-=Pt3ay1x4IpW;j5Gw96F%kz6=5^S-&Uv9@`~K_6@#Ut^LZEbeEDRW!HcI!(%=H=Ijn z4vlxMu{V-OZ7Bvr8uelsjt;yu^V!{8d%2#Ca1=5uHrL%zO48TjDm0IYtfvn$M?>(D zk}TY+dDRJS>$|yQg%B{GXJOw~NVLLXN>;SIWQ7dl(Tc2gr94TUcBiwtAtz~yj<1BH7(R@Zs(2@2O;i}U=;gAMaMX%yIMx=>CcHTr& z5y%6#XUDa0BLQfZ)(2y^2N^ z?3U+T#kCg+9gj(|Eig3YgxJg;%EJ$$`$JbHoh&%*=^nh5)%K8w!!T=KsjT#64w26w z=M9aPL@;AO-5(f&pwIfQE^6PG$or77aM|DtEj;cIoM7M%*afyz-cV4Z+E3=A+*wym zxN}G#oTQ4)X>|Z_@8c5?Xagp+cTR}~Wn}<7xWN7?T9Qn688K5!sM0h}SwawzA5qAb z1ZKe+EiFMmmk}LVOr~YndW0NN6|YpXM>)|G9WIRGd=lYifOUqgtI={MpZ<07>pPf@Nk!y(~P&f;?4OH~=mtSQk&q5r%fvTaS zx$E2DE%HO=pCWDY6(?+H2y%Y=AVK|8eHlK(VOs+AZTaaSVM9`oLxco0Frk8G*5g;l zJT|GwX+(uJLA3fnS3j`eT8S<+7SPXIhX?(GcRjGVQHj5BLjKwSUE`a0q!f*FI->$y zXf?>4`hxmXb)_k^tDL5;>}W+Ve>Pz=-hX_v+kze3+TJ?YI{a6D%Yr^QjtPcS<=HSf zr|FQiU^jYT4(V!R(NJkGL!3tbq!_8H-B>{TO#8r-&(=e11W}4?ioEHR3hQOfMrcUn zz8oAj7Or%TTZz*!Tv_dOSJxV{!*5ygJ{^*QIy-t6Tpf_>B2i9XBuU$lMwzt*jkK&T zyGeitqpGFn!~<@%Oe(c&RxO_?v-U|U0(Ks?GdZ1hRi`5~W9gy^{O+VuvzyEMd+ykb z8I-%>rgd+WG^8Q{o2*DhSvOX8fg5~H2Nftq`-b|IHc2ovW+;u6RM{X#tNku=!i;{| zIQ@|6C6-IC;vZ*$$9WqKR64o5b3JMS!ZCm2bKdeJYJQGF97QBFKgTLnP3w$kJ4x`f zPlPfaGribnd3L%5-7tzV2xmtjBTXg|)Qh2Gq-&OHjbbsE*khtRoK=~279Rm9urVhv zhM}@{Ec}T=t+@{9>|vDWy3|&p2rwSd94C!H2H|8NOLf*F+0GDi${n-*xmmp0$|oK4 zYDzT)SqlZioTpP_$7T@)8|5atjkaVNBR=;rC(YtFP_IO~YWWoZ&sBYl6L2xNW!lb) zsh94W?c-CsDk_(ADG@XJEuW9zHzxr#%Pw^)XGKCJYS+=OozUW?DT7n++u!wF;be$U ze{M=Hd6Y4e+-xNTgL7xX@n0KaWH53%=aVw9OqMuAvx`d-W*R}C1fozqi$>ZVBeyZH*^1^VbF0@0sCo#Z|H|5j zG|Hw}J4CoOyE$4F)Ww0~6B)~bfVtTQ&t`v=hMH}mbF3(u&IC1MX)=csu~dLiP#$wP z(uLzqqnFwGXBeua;wM0|QGE=uJd2BRL)rK}i%z;Wm26~ebaQsQWb8Aa8WB>dKqfgA z*Ii2raIhUwwK0^ZO)0%1hgdzfjy8?rRM^=E+8saygrMm}8Un(tWSYw49kMM2iUUeY zp6NVrq!e19W{DG`gBGc7Sr;VuW?r&Jlc$EN*b?VjjO#8nM``S=+dhtavW-@*zBwEA zl+4^TvRT*7))JYflp~g18mlt}ndj&OpJOsm*%h$fa|_by>5dTKkSy zm6*mW*BySL@hfOUrYO*>THPtR*<>?2G}$kDdliUCKDbTRw+TB(Bk*p4`}-ItLwQPl z7KU2FtMLr;{WQs9%$jgT3su5kBQPw6@9A*ww}vba1>bEu;-6APpla!%?y7c4ROvHH zJyw+d(yl4o6X*ty0MtLbcH`b7OPR2zA@t4d|I_?ohQ>(i&E^ZeqR^da6;# zkrE#nLTKY``3YtEPkkwHs_dy}^Ea8+$=iI~Zh$w4e@I852i0O#k;#oq+k9gxw|NrC z8~3rQ*I9~VOhbq(i6)Gl>Y=Jcb0Evm=J9e>72?2QSkl~!Ygba%e+D3A=v4_@C2cYm z%4TvKy=to`~qUCY3XP`c{Z<>e`Z4E=h7+F6`xF4l742*LpPlr0$TcyFFV#m(4 zPo;)yaUzk1+^1^0Wi0E+xcFsP7A?6`6ZSz*0vI!5J7w9hB{$XCn>0<)^A-?$xl~DY z1w$OqAOermSw)o$)-ZF8mdIzH#5Uci5}>n)EZc-aOp;BzM$ijj>R_|3kmf>$2j$(1 zJ4ut(?Q0k^|FksJ?9(?hv)E0za6v0NsFX8INpXyp+w=(5R9N)p$usYnEWX+!Fbk5V zm%+j#*@fzLa966j``1`0IRr^KDpso>>0949O9Bq7g`=5fWL!^lCX~a4L!(8jxz%%2 zAfN*RH%B81(4m#`t0n)ZoBieH(e}w1F4+1Okiy8Ad37N>4vo%Qry${yXK_6 zZYn>BQHKS>I#U^fjDf&4F&GypZ%`-ar@3`FVl*>PjRi-?5}+mdEqoBC0tEy#!TrJ6 zI)phUoG^r_WhKyLWPsDo=0}gh~J;&k9Wv29hc{2}Wf8{wIJ8%1~NczDmjf+0AK$LY$0= zll@n9`~6G4E1UQcM}aI|X}fJ?PBzcQ6ep+9kd8F26q+!vD!H{TxQ~<5T<{}Zp)S&htF&Ahtr_;2}$w9c)R5hupt8C3KVY!H%4shz$(IyHQ(R^kLNc;+A zD&GKoHNo+e3Kn#VCUDa;GlrERNecRdJgdkIKUHu+17k5q=Ohd-T{khm zO>HnLTr7T7$HGf1R8|LB0!pQFwgn+_5r_P=y1`<9cMAO|m|z*zLg~V&JfDIl3P?b+ zOsevtFivokhBz_(Y$BtY88L~7fDJi;Q?!`X^uW0EXt51EbS#Hl>))1gI#ONv)App< z$QubOeN@)bY>SMT1bv_yRh|fpONtEoLCZ3a_m0#H8lk@KkA|E+o4W2Qf8V@77aC%1~V&emuJLr-rsMisK8t*_U6mLg zpArO#0OT#n9U<)G;mo!US$$`bb`UC#yRE`9T5E3&OM_;v&Z&<2JjFE9v9*m>OX=Vc zG*LK@@=Uabg)@Obr7dZc4YZTp7ct^A8iOLR>QiHM*)LE>u2vKZISZ-dsv{eiFgN9T zk7mUy0#KPtj_&Z@8|P%}D2FBllu_@`34(QbP3178g&{xyq08$~-p{U+h_j^~xtSG^ zMl67s^ZLYs?-xNo9v=@Z4L5;`DjPJP9O!yf@XTws=(Klqy$18mp{v^qoymZRgmde+ zIoP<1*}Lu4_5WD5em1$PZq|B#aQV;*W#?2*t>;c6T(2RxEIUz73YFg^fMrEkMH@~r zcPK$9Dm&u1HmJRjgAOG0rOMqY^KxP2uwpDOuA2*Ue8QV&#_pX z>pGAnyID~Ng(r@?HD6hPV7M(cNFxaN@8csF`&&I@W=cuqC$rdu{>|x$5*%@rmeGn- zv(lHGuw7dSshHVqw5>)-C`bWl%!!X6fk;BeDNaB+qL>=IE4WoT&FV}tphtr!zxuyM zT7$~TgFr&4w5?#Tdv@Jkpf1qn~nld(p#b=ZMK2edB@KV|D4!Z+>9!Yjkc9XCnNSJY~J^ zD4m(V?h4X8M z)pVv37|No^*JZ6!p7HoMRp!O@Wi^ELz*JhKc4Gl4wUGulJ#7-))Gan0K`w8CU9m)6 zD-sca$%wMMSVhLo$9N^md6kzgfV!qt)l{!441?-VetvWus=~Zz<(2C;Y64>EAWe`_ zO}oDtC%4QC=S0g%&335(N2f3OfkII_Ed3?-q4zI2$`vjz04YZ$+YK=n)Hh!`Q8$)$ z5Bkf+=vURDI+Usp0wHY$IF@Y61fVt!BfHzH^7_$0T3@)ky{e0X4)Z69<#jLTYkx>o zRF?iA%j4x#2qwMwoaq>eYP|pL110NnLmByJ9t}|Jh2b zBMW)NSGNXzqb-AtV*m|!kTMk^)3DfxoQE@OUblPDR}oO?G5CdMDQ1jO9jtA&(P0{4 zAt1>x)YAriiiD#b?#cgZv{T_mr%c8W8v8lhJtL#a!qf{n1lx*W(2(u@aHiRiHrL0| z7__rcDDxZjJMem*+#pT2fYOJy_tt{Rsi9=tf~Pn!KziPlhDzTHeHAL{gH%vcIExB!Y>V<^A$YBf3T=UPE~#j)3??+ z8BQ2Gm4qKp51GCg=s9?+G#P-D(qTjd>hEy(Rv%CwZ1L11RYq$anYJm&!jGD)ZxJ~+ zn|cBDr;EFkOoMWV1J^_AR?cDnJbRqu|av}OuWBnbj zW;;uyk(+-wWlN{8&z9@?e~9^)$N$m=*!uYhD16^c#C2Ar_>r3P>#vWQ^+N9&Mwlge zS&@rnuPoir7@#_Ynu%U?Y|PP3geEW}GjB6%btf2rE5B-2RAoTL__P%9?Hwo{^VTh6 z8j%}>NxTenwi}Z?V0H23@%8}a4A69%8&$>Dpx?IIB%tgQk`>qVTa`7fDAmQQmoHvb zCf)@QH=+qS$6?rR$e(ZZugZv3T0d{nsp&GYMRj(ikE zCFR_E(@=lyy(xiBTVk#h&p7PqqTx^nTaH=@V**7yoBTq0?mickS+K0F;E)aqVFko0 z4^Z_0e3IxG9R%s5c}Di9()AVn4fuYLjSk2;%89*Zo1MTeaZS{>yE^@w>2^ps$ zP5=lt7SK{cmQ89uu)TGVHenAj?nZWT?}x z+!S?L&N-)m&N}BADUeA#XVVW}nb=M#QCKA556H1HcV?eWl@nrNfjZK7^xb*-t(uXfg7G@XTD-WHPyDTFc zk`yN)6B2>rZeHnzhb$F^zJX*^{n@L~yDP?Sd@;;;0P?~m7xs?wOqbj+4Z|kN`ei_) z(M=fr=k8~4;?)i6huQYF4_YXQc<=X=B(r}g+w!fgtu6O;!eZyA@ZDc>J2^k8KXu>A z$H-#TJWlx*3e@)pd z&5IWDp&I|EtmYt}B>;lBmihfgBlICA(Z1<5OQu-3p&y;MrMRgDXIlxmG7h1eKq}R+ zHgM#~Xi;JXC|_-ETx}MV@h{VDWAmqVX)4uxg?W&EwXaA{mZ>DOEjY@RaMH&?*zAN! zFho)=X9k;d%SBciBb{)!gd}PwZFvwKW(r6QsZRNv9O< zdULj|RT4z>GYXjOyiF>o^_+@A>Tm^-y{_5d#vsXoPqb>X5XePe<7ANxaz<{tRqZfW zz)iMY12=>lPR8r4udc6qCa#F&(a;~c#dIBV-^`i_b2mbf&Z4y7j6*e~V@|;qkyS%* z8hB%qb?7$DAdKUcu1Wj+#*myDsECf+jrxPLO$jbs??4sdeaM8eV9ya_RYgBO+brlg zbSOfIfumbh09f5S(&#i|=aJ4!hG@Xc@_UK9f0HYAO5=~J{5GT<>F*fF)|imwXs$i( zz!l#NNM_*cn1)&4t?aG>73UPp{IE{>0fzZ7*XwI?CXV-xoIRytM>Aa`lzZ7x7L>xY zqnlL{pqCxTR7J&yn%mK)07XE$zcNw-;i&@*+PT$UblPq=G9sv&llvfV8)IC*^cm7R zW5Ez$CTK>lSZ>ZxU+9fvB5j+{OuoF1=|FDkYN~$hKm$Gd4oX_3*4|N38f(v#yf}uu z9N%0;%Yje9SX%zZ~w*6|>B!jz%_GoSA{2bRj3pO6S!^Zfj_ntP=UV4J5=794{qg zjFTXgghWYAj{bdW%)bl$jl7H4pGbK!8wU&*iK~olqiH?9Wiv<1*F;8rz*O5}%tXC_J!Ox1E#n!*skgqHlk$OwD zper{|d&ujc4(g)6udJiLYqL<<_AgqV@~eF!XGiC(>T{lw@6Es4My`DE@6Y@z>PXXLDI-#(EXg*%NzS7sxtp&g znGxyknb)U}4H88X5eOhCP)pCe{O#}5y|*@?z(rCg>BQsiSxr$ILP~qQoo>MQJmK z`lH^p2r_V>DWD4}OwN;!%VLm*qFM;bZbDlulq+x{Q7E8J^kB%e;QuU?V-BA(hp^w zGzbF)HAvU;WqEpX{WZw3CKQm8Gs$clJs`;oz>V<=!?k)rR6$I?(PbS=VsAQ)61meE zYeN&PAUF#Hx~;xgmWI93C8jgJ&H>DIsGUE3#N5Hl7r>ECi5&RXWJQ{#aXNbhm_v81 zmTGXxasyU?Awi0`1|T^9_$)(=-M$sgAj?$1t(~m^>KfL7i43p}CTSvy9DH7Gm#7|5 zFAU-NGxNB+Ua&>*FudjWvbW7j?X*|@aFePJe?f#d^@^O1pAr!ik(dIOQ;9N`ug^Bn|oDE;tJ5i$DSLLirQ9rKFKOX z*EL!7GCFh4!gJNwTck6>x_^<}l_jk;$Cs7{V!kWcy*BYnR|Q#qX_7HW!}CbwO9*Lx zzYJ%9Glk(#>aFqv&T*0scpf=^!~A9nnymC;s0E6{wRZF?;+#ZMp2Lji6P^@=zYn_} z1f?mK5RS$|6+=-v`oeAwHXxU;Stkf8kD5IHd?|A}C(AhgqRt^v(sS=Pm3EkfYAa13 zWQ!o=Y-vhTMU;x~loFq^JW7FC6JbcKgn-IgryhkgV^1EH<(uO9LcxyB@?gSQ2AqzT zT-0#bd1+g+-uza+h+L2qg5lQQ8OLQ3ZrHOcMBI$kk#RHTCFEY$gLO0CicRoGCv5b- z2~wyHQ}FkOTq`wYDv?pB`8uTQXLwn)b1I0P`Sj%E^--N*qr`c|3%_i{j+O`2n=~yx zXle<^dXg`bp14kv8=$Q#-}oft@gM7EU3Th>*KLA(^AW>5&1_YpcX?UYMis(Vi3=z} zIpDj*bo!Wan>I}|hdSytS_cnQW~m`pN^_<%(Ob?i)sIw4MAt9QR-H5~Y*Ypl3R0Gx zXkdibouk*sw#J@{!gWw+xWXWzPyz(`gk2>{(85IoBL>3|OF}79W;rpGD)0C~)bm)g zo#Uh96DLb^h5Z-%7Z;FNI6Kh#gQz>eflYJmaa22_Z~0>uL`b)rbHNj$Ep|`0+GvTP zAfwBnF*GiVIZukn;#sv(6UrxZ zau!wE_R>Ra?VwUhY1tNZ;6yQ&)h;hQm~BG7$-;OO=lxzm*zg=nk8! zNMV%+VB!HYj@0!KCjM5FS3Ya32Eu?7@L=_U z-b_H17sWnRs?%;$m82|;1H9ykA?!5%ZQL<4o;OJb)lR-h)lz|$Q;3`k&|fDfOit(@ zcRW|#J-`shtTTnME|+mkFxg9O6n-iXBEb-B4l~{xrLPg!r@-``yMdYSuZD`C`?!k5(&5^hd329=BE( zx#n1IAIsSn1|JDY1+4Hzu)N_HTaM_!-;v0xXTr=r+E=K5xywolP<t`}88zo4`&;@S#yKvEFrJP02_ zwN>Q$CSD{r@glL>pdQmD`}5N3Tu2f%6~k3o=aZJ~ep=LB6hQ32f!)MUeTy3-OcM@| zeSu(fqLuuD^ix$~2An}^H{`1SLRUy7qi@x0E~790QK(D@w%5aaA#9ZuMED8t>&!`b3JwZIp8gq9 z>$}cnjnInd!R_OAyL4Z9&Ptb?lpSBb&a?xa=F~E3Vx=MdN_ZZR3cjewXHW(lXXH6( zk{6x_7zCnrsaI+qvZR<3@d_#ahe*mKSW^|pO-fIjm80Y}ZZ4x2bQy1MxzVZ3<|O4= z0XMVIl%mR>WuSr5;oOUd`F}ub4P1aDK@vK>ZN4bowcYe3N4?KgU+1j<)c^dxclQ0o z^||Y@H$MC7gBAC^of=ww+({B;HHo5ZBPV@rXOzv|EqzdME#BIBR%_t5gs$)p`aFc2 zh;$qeb*_ia1=${ml|Bfqml8#fKI6*yqA+<#eSAe_yt3R06yfzsSL9VCVxb%dVHPly zZ--DZHp!M<)@irf3+M8JFJORn+DFG%)*V$}zYxES)8nfMTR+W#&#`VssoO6%r9Rwz zydG^dr}UE>PAdKUuQ{u9hrH;t(o$b=UTK-no>(PGzs}53h5S=YEj1L%#(z8z6?qy9 zH`S3NZ)cRxx;CT05=l!HM;FronP%fUK(JmRcqu&zVRU zoQdVQsUWrB_@4(6*bKiMeyNaT5Pz_I{($j^7W<-@E}DxVJN!aNc)>sAahL5J`sbHL zLslM6bZezYtlpdAE;*X|3#mtvS(H4~K3v428BAbNklNRdHeT3^1zww{md40flR?^f zlYCn`GnDyUNf5kX?N8d+M@Y-Iq-GHdTLX2<-Cb39LwQRm%}*_e8lcnSLD~B<$-^&l zetfyT1D41y`>lq0vZo(JE9TB54=XhBBk(V$>^_JJ+4qARWNuWc7@)VBw)B?++Nok}%A& zg7OS0m7@XF!V^)>u+ax(X@>x{j)RN6?yS~2Idu)xx=n?QG=1xg(mO9tMF zeh|0i8z6|;>70N^Re7QfVtCpr_{Xq2$UGA<$*ULaKuV9Yv4EFc_J zgEZ_9WI?VYNHOJ1osAgz(Rj7D};6atG~*BS#qE-%`gBwRnE+ss*@160iLQ; zrKOG*#~@6xJQ=)BbNY!W+L+#2W-5Tq>d=+#KW^1@z@G*~L(}deZSnVm4@7evWz9t( z{?Y_|*G80G1>!Hg8M$9d%G9nEs{}mcX<{g^<@6MdUAm1MLG=NR94rgHjFQ_+seah# zDb5W!S1qJcMbUkkPHriDOwKFNjv-`Q?dUtrrc^C<)NV;m>bvw-f!`~{b+6DaliGyb z(r|*>ffTUP`T$|k1g9oj>6OzhFl22K55;olD87x`w+`SYDcsg(p#h3zF90ukn%iu>EEelr{$VKy}su>BTPw6N1}`&$_{hy zh8d9lb{_CWnhbf-YTR<389EbXvRqe8mZxLBR(eVJ0AA9Vc!h99m zuwE5erHZ|7H+27OP_UzfRqN(k{N*XOndRxjqYVjXapc>u*^ONWP#~HJ zCdfIRcMsSO3`hA7WoF)CduFKbAF!P)$cre5E7#>ga8kIJ6fuCF?rU5ody6ay0DHD^k+Co%Yem=__rj zksC^5*AC84LOj;J`l;Lf+4K0Rd03YD{?X957jC+Pufa%3^vnAw3FRRS55e)#HIHWV z^GHnOxw1lsb9uxP`M@~M5h)6=NeEOO^@M5+BMA6NUSIR%E1~PFWy+PBNFsASmE)d9 zZVR9y;EF!9zix{i7t{VSc;q>Iqj9H@;i%P!-$3hqG)bUKup6R|WCQhvysWM&r>|bW zNAgfHiI*Xlr(^zr|Ab_G03z3D2Zpo67%8|M3b zj+iF}Uk>)r^DmsB!%EoJd|fRM)*h2)2#i1XLWapo8kOC|RQWL1>KYC1EP<{^eEE5ceP z3J#fkyOp}DDyDSm%Apw-*L{J4%o zLqj>N#rBmE3NTbx9Z@#4nUDiHiHVA%R2VMTY!PI1+Qcg;piz?)Z8VQlY*(ZygNk|JgbbZpFvV4sqC)BDCQsWyrMi(J+zD}tCqy)#Qig6}J@?U%}W=<5F%d+b{OVZjs2=C3^uJ=}7^5|zc# zBr4=2w9;XWB^4IC04(@qo|hUJ=EM^6QFx#Rhk~s&jPA7cL;|H@#IEI03zD!Q_o5^e zda{RH6kvbHcLU4BD(iL`CCdk`_=qBy+^W2T#x4@%p%dW|mO5Eo1Obe(k%6q&fod*1 zT52KHbwOWS)_@u~38X56NewD(4V;2lrqyn&SAjejoQb@7RgCtBBK-mi?GbGScZ+GdwuERoV*i<|^Fr_58noi4= zn8JB|krw*khDsk4ERvu&V4=tl*!*#vM_4=b$jW=B*^>!Z0a>PKmBO#@n$IWKm6-T` z*?*o7Oqn?D547C_8*9n$np>*)P~_*4$N)xsV(4b>DRZztP?Z6fVSgY`kU=Jvv8u2l zQpBwBKnND-s`dwT7Q)aUx3l0ytN5-gN!N=+j8qh(8in7#6-;03-3K{m-$6_x`D{!K z)UG)tF$`KzXWWwP@<6hCrEjFBdomFlFa z30~0nX~OeOa?=HZ-SaqZS!JsE(bYtQ)pEy=>>iPcHLPA@x* z>|;6z4ukugs;eV9ex6{Q-s$7Pr{GkU8Xt89D0v^Egg0jde4!{+ z3B)6q%p-n>A=4O>WRI9~H$b^MKug8zfx+|gy;+5=`4M_=ptckUf3P+h^G0Q3zHSa3 zAP+g-%>Jx{A3eGNX;3O&QcI9(9@mUxKHY#>m?ByeRgrCFc|?>6&w<^!-EJQMBb(t` z8(L6EV8j7Z4?G-CXh|4HNk}*}s-`eTq@ z?L6K4-x*F>W1&NvPj4AUl-g`7ZzIhvOQSqn0-t|sO>pp{ab-KQ$zP?m0TywZRtGGI z?}JA)yd@lTvQ6DeDm3~K%Q=kXx^TFQznWI5fN&!k85yqhb&7bTs_Zlx8jisa#h{qZ z%RUvyinjp-LrIPoeqkf%g_0l*yHNEcdcbXJv1|;Ajf-GYX|G1EIcoS(Yt|#y{Bxnz zc%qp%La8Zz$4Xf7=IAsPNxoR>%}{B4h%_&VMzaADjSq!pO9Yxqe|Y%Z>e<{j=W?rO za`W@JJrV7u(wx;yZnOa+ITb9i00;tV7aWdZ$3U&vGtv+5IyeI<fgyP^ROFQMue3@DsewWz03w@O3y>l(1=Vmy*-#E`4m7 zHx$5yyOg^`SDT8GA4?xNu&uOm0U^2^#d6OFQ%+D!<~a8kSx`iV7@m5cMe-L0wSb%w zn+0~N+=B7>zPxzDXZ)edc8DwxM0^GjVCOR(O8WW*oLY5{;z75h3E?vkw&8;J*kN`) zy*^H7T{ox~!yzm1 z**BxsH~i6`fHpT0?cWwdHQGyCSw+D8UN#Te*igxV;JoknC64w6Tg zX8JJXcZZ?~(dWcTbYez*F)3673UY*Wo`Rpg+2A%Xr%3N zvLGY-v&Q|TUeKM$+H8-O+I=j~6rvccbdx=0E;CW&JXm1iQ5bV4_lF{lRjKg)xv~d? z-@?N00d)#aWb!yCyFw@A>FS=g(D$fR^0Zy0E{FY*hisl^K(ZC&p|VaqG_^&n z3BhAY2ugr_9NIMJLCABX2B?I(%QwD56^&VfA%GS?OsCh&#R#kLU7Cr@H|V$TQ~n+M zm21pjs=^n#zGgL&Z+j?xEKrj&ph*eLgs6Hhu7CLGkolCTeDJ;tUa}H#gt^Ejju;2i zq>N{xtqKOcLpRXE1h$~suov8g_o2vxGyR%Mr7jERrTz=@8BoCsEu)vuHh#Mn@1%@% z;uj>3yRZx|G$skW_#Iuh5J_m+RuE~aD4L6;Xv!@?n@d3o@#V@V4i`yr=sckc?6UfM zBS;)R2P% zAl;K!ht(#u7`W@54UBC9x$uLyn6usha2@g2fFLm6yw&eHMOVo*o`m#a^XP@p8o`Uh zU639nvu4oLR~!D^|GLb7Z{B}7>tAow8nuq5EqMpF1g`VL*14Dhgb+~um)Gps4*)rW6E#4Xff83u9G?`eDUA)UcB8XaJ)N*7(~|85x`BeupTyi;6u9( z@X)Tp3p&=IL%SAO(DApC&JMGohIT73L-t!Iog;+rDyN2Ql^pV`riaugh&(Mt#FHe# zSS3wlt3;97RFNkpi}+G97^^0XY?m@pmo)O!v=MLONDWX3l<-NQb2MKP?0g!6#;eAy zffBL$?xyrG<1xRZjHu`?iusHylymx7HG2*(FosAaqo{4+i@iL3F}ei2DLA~OgXeL5 zjrkpqyX=){ztWkmHR;PnUQ%y{cf;58M@V|ziZ!U%( zKi!;Nyt2{A`w0qoE1%2xE1}_+-w!^(VPtS|bM^7s=}xQqQgFHY@6%!~U;7~6lOm)j z?TEOQyGtyKJg}7Ae3{7Or6pyON6l1L?yl21I%>69nw#fCx^dEKJFS_TadKelrW|TC zY^^t%s-E_x_k#~+@3!%{>@fmkbqc^Y z`Z|Q+eRl{;EZtUk{bxN4|SjKK!6n?q=i8r?`ctiTphb69M>mbnkE%el+p2 zEV;p0m{6E$AZ}-kFbN3ybtk#FFR>c!AuqtF= zo1lSJVFPu61J4Z|cxG>`i#N#cHd@STf{!eZ>CU@%r^lsK@}=PBSPXI7kbbJNxHpI# zyX&;x98wPEA@QOd?rN)B6UAcEgc94pi&D?%(UCu=SO-64Vr+|*((V@fsc4iG!tPu0bhfP^=Rx?{u;Xibyck)JMo9- zDV#0yr3S#DVGCGLwn<&XXd3 zJV1m(*}Zlaz<#SC?j}Qc34%jQVVrV8J|>fSo+i;R6$BnwmkAIOQzCdiP4fjiyB@G_ z&sq&(-u?cqxQ4(@TeeZ7s_eKn`b4WioH3=?N` zIcx@yUqOI?s0@OJhv)rWwkKEE_|bV8lwb}C1>;BK&PZmm;G1+v9auTPgh}-3|kMi1mB=`ZaNUN}G zS#Bis>$JgX>KcDV?N9O#QD28y2P4bW1MVQW3*so0J5gv&(J*)vc8ZFf(x8ZDN!VG> zbkGkZOGQC+S*QK(#OH6sfem2=Y`jdu*eZYkc%l%iL;Jd2X%HCmJDvjwK7`z=X~fZRk6MMu2n5!y$N}OKs5qIk9?MnU25dBm+}G}t zW)Uqo4)piX*y=ft@;y~~rOv4*ze7uhm3)Yud=+HM*r)mn)g z$EQiR$-Nw}0}I#?)zElxg+tmAlNEU9Ox+P*$}HEL8?(;_Z_2rFFw0->h}54kvEv7?ss!|D%mEP5Jl! z;@kc;JG;0U^*{8_dZP=ts-J1KTJG}~*XQ+5znnxb)TEP2S*5&}-(#65J~HL90)0ZN z-!nc}q96ErrBZl#=S#!-TvnCL*g>op*+Jhz^GF~=3{6)oWFoyi zesct!32z?Y#nblN4qQYbsxRO`=tsw^f&#Fs(I@!{j7wlHYh-Qu@vTamqXfS#{gpBh%@6}Dw`*a{h&28(&UDPFl>oh#cpS2iI) zsu_{%nUFj@NL#ZYZOVaU#)-v%ezIz8 z+{%8hhAqEDO!07;&$wZ>s~-#fDe8rhU}HW9U}Ois0U?hKAB}=V5UGv3h4?qALRL~B zAQV{&xk_%#GLh(`l@KAm&aa2q_YLa61hC8?5Qbb*W&M;Gx>%UPbgkP@z_fyop2L$} z?L%?RtqRZtdc+{^?5UVEWyM6e5CWO}gY1v}mIdNSqp+#x%h`9m>u)cbR~Ox**KgjH zK^RE4A6*U)hr>%cEn|++ogA1&3KeRxJvfkPHti_^Yg)CCV^V0Eg@)~!DW52)qb&WC z%(-k&*>3keya&u1o$k(z7Ya}>i+=jSL!S=b_l6fM4j%4NV^=GEO|WN1lO~=%;4WQK z=Zk;)Z(Yc@7uOdz{WEnGDa#6eS?1i91Q$GVdjIFs%|)%0d*R5q7d{C;4r||!qj4|} zCULq99YNN0pTx`l``-KB+2zMi=Z%l6W|_gci!9hsOOJia;C`NK8(q#U%7jJ)h+1gMd zG?_S|$C^`N7UX03IVWjM2+8*G``a_aU9oer0AeAZI6J!0FHzoFA#HdYWf1iSB191s zOF_Yd%ZvquQTZvSRmv2%QFeAc7{b#-ynZI%DIb5Gx@y89e?`@8r?MTlwu(s65jW>S zUW|Ew>$JN3ow{mx5?{BKFpYKS+7v2ihnBWlzp`u&dgzGrA|I|6S;jteWqmF@P0!Rr`v;p@Buas`B41;ow=W9I>~b9Ng!XCa_X z2Ub-&5q6lH^D}y?ysz9qw3M<+!PW&wPK;Hr2760Y33Ap00%CczjsEgfZ`tZG6iXhY zM`Vt0%*Jq09hxES$M9xoeG!tuDO4Zi;xa}k%tC1ryIA2d2R0A=vN@EO&pMxE1B!UH`?w1<`DokNF@UISRG;+fUpR!jL4_p0bkp0mz)uIwnzcAguOvq6%NW&k2+t7yEz2Tst04Iz5qR0i6bLcch zrZs-lY|6N%z&mB2L$%NySTJ@6pb$dVLNvupe2`AX38y>~Ra2^3Bn^ttNdsWTqa^ae zitFT+D2St9aNZdD-P+J6%;ZU;;u&s->yPIb{p*>a1k6}Sq;>ji+En!QOM(MpxZ5cj0wi0FAvF(MuY&f-h{YiV_xO1uo0-2rhMKq?Ect4i{{<+~d`Az~HUrAlA;+$Ma8@7iHnFst7K(e(U)v zw2%+42d|xdck}V%sC02Ky6K%==utCH(?V`r*@r0B%vo_daq^6&@*b*|z;dkKK@i>| zSY(Pv>OPN(LNmBn)6dpEoHDy?=df60hqQ0#d#$i?2~vj4%AqjRfTB(?;>4XSMUgI| zUks+2wKV5ZRdStjc=2dboKU3VnSmOe55>7WB#s z#bRu(AL{PjOhGh{zo>#}#6DR=G$OWC5z8+=M@Q7Myul8?i9m-kUR9lX>kORVqJC={ z@QNVmWe*fE4~GvIHRO17%?i~ERP^8u@{DEB0eSrCur;Zj<){~c0yRE*gA9Tnb^Iq ztf!nf{M*D=@AyBlciepLe{8?_-!Gq_GOf1sh%4$5Oi=}F*JiUwr+Tzeh9K{z*5^8w7IgNf0lvR~)Mog5u4V=i`VqDRC;kdR+2J8O zyB=shDb&*y1umI~Ej)@vaLbv{slI~ecwL=|F*-Nmf+B-8wi3vr+yKiuuQ&TeAe*Ub zD68ZmIvKKdT9yo5RY{$0HFjCchU#s7zZ~-)crJ)Ld6~#15Z;Uu_67L23ckqVpx|HF zB#2{i(AZ^BL2T#1%Xj-$us9m$K`tA2N77(Ee+L9!i2Ra8vPXkiAiG!AWMpM{1U~M0 z)d-s{+-(q1n93>vtjly66RUI*0$njfFB@E(-D(&sA)6P3cR@1Ytp;|R+NB5fk;3$} zPN%+0AF0Ox!H5hhgx#Sj%HX*Y!zxy=u`4^R*UKmK(_^xn;5kmP5aFUUmJ$>5C}V-{ zRKq2-TUQ@_c(gD_^x+iekqt*;=*975VD2>FOxGLq0Vgf5NrM4Y9`((tOvQM?4=u8p zg!(N|5#EG}u#<7hqI-irv5P7TEDXG;gl`rIJvvmR2N&8MrBHK7f?S091H3JzU`0d9 z^8uI_jpSx3tTKJ{AjDNV<2*MNftS$=MvqycpZXI0t{|<@16q+JEET-kvES-Zw2S-V z0UWm>_bQsQ$82q7D#up zB*_o8ksxgRVi^}v2F6Ns=q6g2>bz|oot(6e z+Rg_WuZ7`Kt(n9TFx(mtpaUEH2@!~Fysl+2hb6A1%NqemEWit)-FHvEgnQ&ZutP7R zf`C$Bst~?TB$${7a`*<5JQYHZ&=%{{9v~k-u=u2R*$!e9?yRn)RzqoGAPc*mqIsE! zn`SdW_n7W3Vyn9?$SiY7p;B271!oqrmR=yORm}g9jakky%vDWuRpZ>{r{U=0=IUbj z-DkPtUfld};eb`FvDR5@gS)8P<~zrL=Pl5-=dH8ot+(khrT{_K^&2LGn$9bApRWTe zT?mLAPLG*BgL~y3a~$6AgyZFAHJALF~wC}lny`3Di8Y1|mQs-Dnq5A%Zp}c(s2y@mC1}8I8 zG81Hx*#`ng)w8Se%o+au55v*Nn+sU8 zY9@Nk;wbB4^`E;a+RLI{gu587UkG(zS^X>${rNmNj@)% zcSM&LznXPSR}+r81LbwU5R)Kw!X?#nJ_k6A)SMiX`mf1)mzP*Sieh$FhtZs)58eXq zHK>_-IY#}}b;w_*As;B1YZ9m7MIlC(oO5)9g_t)T@Lnf-SBv|xcXQpp{VB|o;t*|x&VTERzLv{craz)AwNM~B=csXNx zyGO^T?~e8nR6x}QPk-|u3CT1Hvt)3?qD2-%*?5Kp0v*-)TCM?ql&3e{J`P5GME-Zy zT{$DGi!)$-YMDhIOsCPr1_;JgJ%Y#x=ga`|0MA`nRwiklbCIPKgpO=g-14h7Px<2F|fqJ%2d zWv}&NuRKCy3wxUN2Rgfh1}*l#oEbJqwTXbSU+)jP?s8)JFG^=ISIyBceMocm?e`Z> zS$Ntsf!7RNP_0>-&SDPn~mDZsr?(QSa!g^sJZgkiNK&wAM@d za(>bpPw6(g{+fAIvZmIqfCo%0Cvz4E%eGbuwcRB(w(Kv(KTkF>wa`)Z?R!-psw=8a zl0J4kvzHpI)@b81*_6*hH7B9+ImmkosyPFB!oMsudbi?1Dd?*P^ycaOf7``_t%wL) z5ff%dg?T@b>6VRfaB4sEdORHFL&Ra*W8$!lQE^yJ{98HdZL4MYDRFPU$hVcTZ){cc zn^S#8Cx>#}+q2tL7y0JKzPUPye-W(4oBAV8>k+PMFs@dw?rR{$YDaQy7_H?%sm5-& zYaqClcv2|1eK(_ExXiLNm#0RTd{fSkn9qXAV;6q+;@DUo$*txd0--ErffVjR+L|o( z-%?0Tf5F*a)Z(oJ61d-j{?gtk+xtY@dW}58GyIF_aIQ`u5Tm<`u@Ixz3EoC+bry0Sd z(F1FbOMzS+Y?sTCzolqQ|(H62VG?TyI5Rru1 zB*WBk%#8OEQ8-l(&SD3eB1s3jSiNDvx;4@Q-{7hlRMnZn zo;A#T^6Y^}4d8h}glXMM16)2eyI1}lsivxAYWRmDy3pC~*xs54tYP;>4aJvJg3^&u z5wZ)(xmf_%o@>7@<~+(7f5;-bFIBO9yRSYbI`m|!`X~}?hlaoonE#U~hS?z1R+jV0 zGKbj2Kc{1DR;Ms4XFg#p3-Kw+@0upODduSbZ$?%i=_)ci!~;@7?IBVA@YZAJORntk z>9T01)8<&N1YsnKJQ^>RGGIj>QSfGIr4W|sU&_U0elO?yy4wL;C4Q9shYWSjhzwpPvcfxj-FG^;Kc`gp+sA~Q>9gD+V zWvOan8FpvToi5vHvo`Cn-yI&a-)RrDeB`GK#7X+ux+Xv36;A5D5KErl@Tu!}o#p9L z9;&VBuY&f}Bezi!c9lYaVx0RFj~Fzg^1Y_B>M*=-lQ{Z}7Of%{ExGEqaO(ZR65*~9 zm6nyDlIpm?V$qrewVYo{!1`Fd3z``}sx5RqhbB}#C}{z!>xtZyD=Q0&))VP0WkX)k z%J$0ayO!jaC5&X{h`kNF0T?g0>V+q8W&S-n!;V#CTZW026gy?qT|Wj@vi+33l2h%K zTBA!e^LCJ=_rtlBSK&(!MUFHKaEP>g7gojYwF%xO`ZPMClyaVc>B6?YIfWP}@bk*) zXFVmxHS|6GV+7$MN?!0=fV_=A#j~nj4L*Km-BIA*rt+?3=>;2sf;VUc+3x(+8&q*1 zo%{%RneKRk0)^CEQ(^(vLY1T_VIMP|Tp57LMNm{C`m95j$NYz3Kz2|iiC4=D;$RA9 z&ej@e@<=Hpp2)`9X4t`38#Scv{J63;)l%x)W3}j5waAWpu5Ai3BW~FSH%v?ezyT7B z+yFyf1W{~4U`hV}PaLz4?3Gl}6A|6l1aP_xoRGS3C(T>XKWscBAw;Iq6`?x zz|7N?Q!bh`Ht9{PA{%w%>xQ+XR6$6c4lTow+WY%I7Y^y_L9iB!bVYcQ2b0tvtnd`k zesof1M{rZ*oP`0Y5Gx7u###pXL&hg~Zkt9)=o|rEJX#AD*B%rW8s?63Bw7uZ%JwP? zsQEB{3{~w)-WcQ5y9cZ)*o&~LA_=y~Slzn(I{a1q^RDZgbhT%Z-?s$Rb@xkk_?qHt zI{l@)eN8P^cfGp-ZPMrVZt=J5?7DLQM!j5DyuW)(yPU_`CD6*;;HBe!gEwevRHn&Y_6477%~Mg_q-pVmWkE4l-Z6_eTRs4~ zxgFDtG2K8ctq?!RA+ZD?JC#UoRq_DOdAOf&0-wdFF~bvUsMPanD}tiL-Cu121~?ul zn`L4pLEK-{Qcntg?x;b7=3ixfZTN}!Co0H*pFByR{3 zFgK{{+Xg?Ww`)dqniixStR7%AfMC>sb{E7V?dor3#)F*v>dST6VZKZV{_YSTy*nyT zF!3lRMXVE-SjfdBkH%8XP$TTTia0!_ddly{|i zIZ>u*Xrp4t1c(k@_!qV;q8MUAf`oB|`l<3PmKvyo_fzFBgcSj~>7i7Gypha+h=MzW z8KSW(dm_z4l%ZBUfccm%V;i_bVK99ER*Z~LMP2W}U3lxaOu(jUap2`kdD>E_BCS}~8kCG7L6(D~?vyv)<003aA@dpr7ja|ow z8<0l>Ko2!!=a&c~=$cSOOZntw$BRi2SD>lB9N0~K{bSZfF^Q#t8Fy4Tq z8!F)p&g}Gz#^I8mzSOsng0;wUjJv{@(Y2?UX*F(o9OU2uo(Bm#=^U~5kMi`U93JP_ z!#36S00T$3ptJ~_?B|I%qoTlROFNh+4qDDTLRyfgYdMrz#&h=JPv_SdECUNqFq!LW z+T1)>!9zbA@ccW9FYU6Ewml?S2;r&())Iv=2R48#=XVi);9ycjclKDIKp*f76F5ek zrnk!sKMck|O$d=z4wyK)L%_~3=4V=r1z6N&ZLzlXIWH8@1l6ai}8sr(*7;~dG^1k#+jDqqpo z*J7E=p=^PRr~oQ4Pjk5vjYgLTHuZztECGcIEjpvorHTNI1TLs8Hq>}Q>YA+YFFa2n zGzmwrh2lgwO=&_ycQm>bR5>fAqS^rH(I^=eahEys8gj0&V*+Bb26Yw*CFGWastGE0 z7Ee=Vqh+bsh&UaqjLS5kL5jLT69t&rOUVpqUTbNDoVF}EU>}D~45B5bAS^L`c*I;f z_tVo5l%Kw|M9kAT6f7XnCJhZkOBtbM35suv3Kqm^GHbCLy_y7gzmVq}k;;C+k10D$ z^%Jo*oAAzr-?RR}&SBTpSCX&f=#B%-n_mcr85e4fCO8$G%J$@nb4bBTX^!YuYG^CS zB@ES*wWY%soD)?D)hG`Vkp($V3JgNCG?n4mXrOfnEEZT-L_=~(nWqclNU5F{-I~D!e#`+u2EO??guRp^ zc`ZKSy)iF>{f7HMxhbXBrIISw_+$n5|&6JaXc<2e(f$$saS-D3PM_vOv)^;hl#peecI8=d)#yhjN1V2SYwN zu-V_D#C{Q{MleoM@xWGER-OTEDB!+>eFP8G{_ZfHpp|lXNoX5J#&g*avYDVa=lJNP zO(oK%j1y}(=-(jVzK~js56}c20rTTb#pdDKLl#bd-k&Z7p#+LNjnNuN(yZV&h>)## zQ<-|m?{2Efsd${AKQLr3xaEYut3%vMixPHr3wohNZ2}em+gDi^0W0?ysE=`&fJ+Z5 zC%euBqgZYa0{@00Enz4L2ZFC#7~ZQ`mF@Qc)5SI(1I7!R%_q4$A&M-TPWd5}jH*kw z(>iUv{$FAq9G#qY-*P^E_x9w?czSg7y7RWfCw$szhwsMYNq97U^Y-=I>Fd+C@A$iM zcyxSxGUg$FebPQX4c@#y;%|>$ud14w?7?J`E|bD~l2tfaw^@PV^=e(w)%z8z^MUm!^cop+Psx`QZJ3|-w+rGzVey|>?G`&(c zJ5|d+ZeZUv*sD>&rYXUFDto3agp@%VQH9{~)DcyrxTm7w!?u#bVipOamrK>*2Yi;Y z#w|zAuaqfRm}BL!8O?H>aPZa zy=JVd^w`>g?oe&55M-xDu9!72M1SQhP5g6mHGP#|1B(DFp>b9ScdC^j5$FUdD}{k8 z3X*{Z1%{V%LEAGVi5dI10wUOMCKrLYHJIKUdPB=RRE0OGX@|Rl7tLbMo8>#e%^Aqo zt>SACAD+>F2Cw3uxfjbAVyp(5!`ySjOPyI|<8N-Le~>&!0hu0;C&%xmB`FeiW*2M z=EmDKjw4Ap9{#A%o`6xlcw{@TVp_IJ zWEfP%t^jh`sDSz&tAuoIEqk4Ms6OTMw=}8o@(gt98U{rm6?(Lf z`0Fa48R9dZ`QV&nEvbyey2_V7cvg3#Wk1?Xpg`l#w~=Q?VYWY*X19`wDcNX$z2QOl zV;&X!V>0no7+(jRgDop=z3Jfg*dOVvSNl=yOrFv(JnMmTSuQ!HM|wXF-3ZpDfWEmI z_FC-XjDfKyo#jC`e^iDjp%PskS-1RggaC562%5+3cc(imsxw@U|I8p%*{8{O|^BvOfiy z3bhxUUk}kOf&K+B*O9YLC3)}h)~v;Tuk3}872o>3wxj&9CGIABt>5i;e=px|;@f|u z$nE_DU2>^rXdcSBNaH&WzIfG?@gw;0qGZOFneC15574}-DzAcbs*swL)u%F?SqI_! zI^DPJx19q=S!mg2AlVjph9u!5J%!f)*V1SB@ZmzP2cl543l_%6loyjZ#N%0+PV_#! zb50})sEkoHJl`3-=jb*w%$ImCQ&bN$_z=a5 zLwKeoe{ELK??Dc zVQyr3R8em|NM&qo0PMYMcN;m9AUdD`6qk{wZ-@#x|``_Ww{%G)b!-M04gTems!SUhW4ThtGO&NO-+DMg-*~7^GnevqwGu&7yw#{r?DNGN4?Md~oX^Sz&{*}ejWC>q? zf=)O9qY+p+L@Z3CWtPJ*|89R_jg6%+05{X>LB@jdIF_~(PuRRjBmAe#*K8)%DvjCW zlII9b8rLaivo$k0Ph+lQ_I)uEIu$tqu1ubpB3d$TSiTgD&!mNn&~n9ilBh?PYd)XL zh|RbWF;gk~@Xr^YOou7Was?3QGRcKzJZD#YEi^ms{cBn!_<2&8TV3E>M z+4Y&FV2!H~3>!{;w^a!`Z>$hAMV2X@Bc3Xq%SEAOx?qH&BN_rkgl#t-X=RYuBF&{1 zjHcINGL4cVmgxdu@+?c%08qt(&7~HPJW0$3VK1L@p;MmxsPuiJc)SBa1$B9(E<4cC zjl#lVLec^FD)~10IGULX!Ge9q=1Mb%oj+ZSr7G=~dzg8=?H2t-$rNA^9XAMcr6Qi( zh*)Y7x^fRYEvE4Lv+j+wQTo{qLA$QwrjeYR^;h_b5m_rDrJ`YgIYI z*oE6~xj|?=jTyJhG%pM@B62`IhOqtUyPDg-0HhscgPN1r9{c>IJ4a%(-LIPv?lYuy z&1h#aY3Tx!l?uVj)b1J)71}l{@nE^XW(bxA5pg(>OBpSx?R?FQ$bk?EpNRx_ukFmZ z7K|Gs7paI@uISE6WBDNCf+tL*ai*kQ@fVKtB{kgT9DATUFu6L|X9(%qhWoU-4T6bf zDn>FW4ZFflknY%WmPAEMq>Wu3Tn+1N=I7$=XT)}N; zWr+~nb0Xb5a0P5IW}2fz&0S+OdHkdWQpNzS zzCW?|mVS_tWi44I(}nRO{!HMq*a?dm**^`rR3>*Xk*772seMpHz`guh*i{ryc>{}n z6-8f1#^=b^B#1VW>lLK(g6PZiYNC~$sL6OFLTYVr*!Lf&Qz5KK-1stTX0o$ImSLw? zK2P6&oH812w-X(70I+nV?L>891yX8fr7bOZUdmU{m9RvR6=BP4qXzBx#!a-98niDP zw$cm4pwV_aj6nwgOM7dB7|6)so!m$j!uB;(v1{-;l33Eeo*s6borqDvsYPlC&LXv1 zsnp7X_R@7*pgu{E-g#c_BU*<)oRNg*!(O-3tVs3xod(an9d}xZ zliO)p@R+GISyvx*c)Y^R2766{?g39}DAW0q+6%b-BxjG(5;rl*y)khVe2m*6tk5Tz zv|`{2hk2HgpC5$Q(!PK|DHQvr2ZIr`3Ic3n_p!;|XvsKe$(%5SP< zc>JCx_JY)t=~Ss?cX}j>$200HvrMUEM`GAPnH$y0=QwUNB`)mo1IfLydy7PT3!?D~ z#Ahy>OhHi-&X?Vyc(Hlp!t=H(HMX3%?ZSMp9cXo)-wY*E$kr2SfT33w81E^u?mqCO z5G>EY2R$$>BXIe=Zed;f1x7#Rzzc8U#|E`tp-PWS z!@=L||Nkrg+hZSOBG^KtR)$BJ0u(Sw(!ckozJJZ{#at%hzq5$UdS z-BKE6zt{`P8@U@G&_?@*V5jx+RhINxt=1kZvW4bWT3Tg1mt@ggiX?+qoi@|}Y@UjV z)D&8fhH~jFdDlF%oV>N??q9eAQmT(Z? zEF3NVR7g!1Mk*fNJn2E++G8KU2+LPlA}mij?yzC+#Qs00TP8VXZ-%{-H?3AIX2rq^ z-FvLtWtSbJPt+rm2B3i<+oEDuyM~Nd$=r^f2@R_uOx|%{0Z^pU6fJT+0Cr7U z5Vz(eT^f;tV8a`ozf%ZE93V_e7Y#sr@5HzhFOojeQ)2F`x z1pV8=r9U$#=ivg1G5gO}OV4;z-w>b(v&*LD?1r?j-S=?p&cFy_Hv^aks;|fvBOTh9 z<+>2|$W=BDhyyGu68n;fw8(MY?GKh3^ne!{8=4mU&$LLATWmeH07<-S!^f`e+eKh) z8t*L<_gx@Q5S|Q(vB&;rEatpOa@+b_`#<|V%R&0sru_{>2t<0y^W~Ve+uH#{zeHx7Zc_b2vZuoD^fMn^q19QdC}Fti_z z|FOl`pEA>c#jMaK-yH+nrKGXYPQ_)Jmsu*EBR~V1LdMxrE|!*2@my?9AwV{q!)W^) z0Qk7oBF(p-k9{hU^Mp71v(IU=u3lJ9OMflQ5;n!E$P1n@UgS&rtR|Na!2NbQxw*7B zK?XAT2YEkz1JsQ0d`@2iGD; zBzLcu?66~Zf+(kMZ+y$~bRittpDj;<uuzT!Z_FT%<~ixaXt4NG3&Om1Lf--D8|H#*@(l9Ju;(tz`zsOMkW@imjMw}^b1UNt zEfwCWwEaw@pS^I&sllB+;EJC&Z zn6)SKPb#0H*IgS$B3y-7E(BOd@E>E=HcLJ_JQ^Pj*bKcE zr%#p&nTpTST%H9#F)y55fLr=)v=nh+AC42eP4VZ;ClM8;pHY|PDpQGCtiKoQF)LL? zmXP+*W_JO!WN72MB@@?}eq?OL^JsYmp0eeS%*xJPo@KQi1lBueCTp0ay>G)Ist74F zW{FITrx04M60aAr0C7_qKYc53pv?}1YP+v;W8Z0FUaIe_T@v`=%6=DA!o4e1T*{~bf z{;&H{fNVBq?N5qUTKxMI%yq#JpA;^)csuMJfsesE_j0zcs7y-*PSR1rjS1ZjtBc~= zo!e$;67nzbi%+-CAO>%OI%BXx`_0ajCd+cSbS>@2sp)1a?$WpZ9{kb8pFv?0r^cUU zht^pca^!i5VLXmeX%_IufXRxdT=R3^e9V6Oc@rG3F(|GV1$x+E|1-VVv8PBMq*f_d zB_Ft!RuXkkF4KqSfY_5c<@u7q<>NYiN55XP%{ z_x>u)`@wfN(3oxea<|UJm|Z|nhtg~Mss)eji_zbU4P;`v>jn&$BW6_pbekv0Rv(4TFD=f`9Kj zs+59=ccY^H4>E$vx}c!03LR?p3xwyqE&WQ1G!`13tqCu!2-yBzt6AQ0CP`3*il=;2 zxq)B_bmkXjno%1IANCI@+uI#p>o)>?Jp@% zHWhLEWr}&6TX6X{%^5Gj=X=scS#~LyC->A_X5VK+j~+*PI!dMuI&Gw&V|`LL|rA zoDc;E38xJC0+zdor_KN;K?TEEEa%|dlf!Xf+^|HY3ksxNBYYPLwnuFqxJJ6Z2ClK)r-4LXp3F1R2_<0-6JgM+i2H)VEH~|x;1x#Ax%&6#IGJOD*~Rtb(=)K}*=d;Ok2INPI5%fMK8sOmUqV)fGiD|p4ogbJ&)HnsmF3>e=6Xi))JqZ1%WiCwPY@qEeH2v&bmh-xCk&KK@ZQu~McFw}uFlWU%f#kz%m z-_oD!{ zu$En%{TbYz%CXqnZ`}UYBfIRkcW}=M4&<&GYg-}i;dN-)+*HL75n<1_Fl;9BMywJb4S=tiFi<%lz0b;JZPZH#){Pm_$wD{%R<>jLO;94oncqY z?WLVojMjas<%;X|83w(FAKfJY0V-q6c`$U|joy!caxrG);XCLy{6FqL=$MO?r}?Y8 zpdZ<<=z@NDujp17q0cCxh|6rU^SCXZ$QhsUC{abcu`}@7x&6j2tLyf{QJV2Iew1;( zq|6Z@52-AdEBR-^?#`#cioaY;gFHsy2V%wA7T!Q$Cj}J`T&|RV3j&6Mv?5a#lU3&O z;*Pz&2vRAvlD(GybdB?= z(`s|VGM#IVL2>qgy#>#aObfbuKxJ>I`TqUQyR9Cp=pWe-f^OMo= zuuGw`v0aYTBs*+{@8n{68}UR;rV)=I;}^&>C~u+Y!DNQtR*>dPX>hn>#&&C!-eo-|%%($$ECacZVjjaxJIQ8(Ie+elU*VTs^Ils@pOc%)~>zp$9D zeDpVs3JqGlL~tvVQoyhkP({pQ!Q&3&;5T13$YgX+-heR71pyqh;h}L@!1~z-%>z#u z&nX-Y0@)A{EDT`gex)hEzi#Y@3&G<=ree&haIM6qirin*TI5>d{R{wk!sc8iCIpx3 zHF`me*~m04Mn-HPToBUTKer~E-L|fa3&ks6#YUtMAMsK1ypXvn3_H7-Hp29Qd}G!Y z`Es!7)BOJ9v^85~bsQmTo3f%wSXq)I{yP(^nTQRo?|B%I0llzwtNxTjpZyKTu8m2% z8I0?0jV_ZGWFAYaQ?oGJ$cWl!q$64AL2@6(QcrEd&TlSE&n^yWr=|%{>ud$tBn6WL zx6f>=Epids%(TeC!j9QiB!Vc@ui%*rHvktwJ*`y! z4W~|q7%G^!+Qc-gKdaV zBS^DsJ~tuq6cy&O6~!UuXrA|qo;0vC;U|B|yZJve7eA8Shn6Na&tC6zlRd&rN@p&0Fqk9(t2a2(05sC7<=r2RVt!t{%ZWR|q zf$-Ui%jjq{JUBpH&eC-amzS_`7hjbqD8(oqGk5RV6#-70%pBd14iEQ_{=!LrI=kC} z$SKc%8xjk-SkCMpFAr&(hJ*f36D`FGeTz^D_ETCUNe7>;LjSzcssedF!OTZ=859@(LuO)mZNu# z{IlKV;2)VJjQCR!EL@uQkumj19}{?<#3~B1MD#`4H$bgE>B#zGmd*PXY=3iw2ED;x zbZD1o#j}fb%2zVFm46mDmT7LMFghryIpd3k7U(txvvAh#ROLQVu0f=K;E9aATZR=i zQk9AhOVneBtwanNFlp&*4+3>ojxeTXTae1v8ALGKSBrnLG$I6{&=v-dKq+2w9}|o` zp;y(IwGU0ZVNevIEc==#d|_Cwj#-;0 zNjW~6DP5jKm(|)?#&YF?2_{p==ZJ;5yxIQy#;r9|DtYI`Co&jJrfkK{p9-OQEP@9P zroY(OPyiA4lj~GrVK_ucLrfz}`Kg`V2j2Q-2}TTf2Y5Y$mH#a;kf%(}qkHz&$`bFG za!`^rhVUsZn6RC!44JIKMV^Gfw}9t6Cg)z%B)f&rB`$MRjwC#{gkDlAd%1$xX1q47 z>?MP2UI1*i&bTow6*;A^r#lxg_A+<_BlfhjEw99aN9!A;$Fn4aobP1@mAmQ9=YRPl zCXxoRMTkN_)klBmrA`xXsxsO}3w5L@2#L=F^Gl!&<7330WDtDB4vgDGmCU)bB znEh~d_KC^(4YK%IHfM=i$cX5Mp_3a^YoK%^X9nZXcG*=-$2Pc+#`)k8|5~s?|)?bWe!@t6PE+ zr;n4zoNl0Pg`Jej-22#i8*pe7+6&#F_gZ`G$FrMHlTRPV;AaII+K6lM|Fpoq{63qb zad`_em|Tute18!xY_h_aT5VhmAbb(g1}uN%WI_G@%lpeN?BMSC*{8FcKUTLa_yA;? z;Bczik6h;6xzb&DnZj;tgTHTRfoC(cSSP$lqa}pwSN!Pr*tOC=hpMwD&Q(zc-bQM* zlDSW&pyq5Q?7p1dwDw*M6zyk4lJrM|;b^~Q5&od`_r*+1@$3*4Lc3oWE_D8BQqLiu z#%w0j(!&N)#oD&z0|}ye5sHgrA=o!yCfyaZ{SD(bmPH<`$Fx`KW+@|uoU^qm-e^(U z*=dXU&E;dCFX%Z7=C2%7_YW@5{rRT}YQQQOfrl{wnh6Wqc~-_)uTSjc>#b95MVSX`^>b$SM9IAbWNd}LZ` zcYvKI7QoSQIq>lsWBBnMjoL^F+H0MI%oPjNLo<~cRS}O=(B#-SGqSQkT3pk9> zjZ>tcT9IWgHc-{l6+7cbnjmiFjcM4cc4zc3O9a?b(HtrAjva^_Q>=uao0llmyh7+6 zJA?FjWHO1k5uJJ;fNLdPTt2-2E1>VVUSKv_YSRl=3_pfzcFphos^s?H>M<4CEM-=v zEdK_cO;IYX5Z{Zxkzk|rnlwv(Yj>CyR%%ZnP6FQ3F5xc z?Z>cGq5aP#gQ1|Mm=%z5eq-~yqv*5I?a@B5?83^opuBssJU~8(8aJxFD%64wyuu+U zFAwf3EpjWMsMNjO)SMl&n6F7>aLmPa1Sqce3@S&U#S=3!i3D@{tg?I^NGKpCtHlSI zh%xIwaNXBMS`Ye9WiL?+KZDzQnXyNW235K@Hz-e6 zq}`+hHigO6%93+CD+6zID~Hf^u{l_Mmw_M(;8i-Oc%#b3+;J4TQ?`Pi$&{e0EC=W_ znU*A`h@TKL53om3m&bTdlvh^HbslW+lKS%^p=*mha^z@uFW8^-mYYZwIp{j=F%NUk z1mR+|%sv3gaV5+plB~;P;5emVZ|sKhIlA7Io$>L3Q?X3aZZ-q7f5JYnc|5m<-YKF?P_WkcEN^3m9UFxhxK77)Q(BJ#qKc?7>tyCXemOKbvld&Op8AzQ9> z9fS?$tE|84^lO8^z#B^Y2d!!|Qg*Z1VJ@V;u7@)=Gm%?gLIJZUxu_(k354r6e5gRE zxlf77DA?MCKe1Z)6AQwhh65k{DHYNv!2LnVA|hWwmmfbcpj*oHgbbC>p2NkiuJW$8Zf2;QqQ4=uH=|rhU)ft z6I!HJS&^5DK6r1qaa((EM3)@I2aJKnGy0}sVs9wrO!Zcz95nFiE@=<0D)s?eWUNT> z<}6D`Ih!yr{yX*IpD#W!pNBZ4={0|9AZsAy*Zow>tm73gzCCs!GA$zKl{e=P3ZBce zY~J%WI_GrPV|Oadk0Vn|#oF@2-QZ{&7V4(aUEZY{rX>B`qT0$aV4ra>(o)es=`j+3 z9OG}>HyQbV$h2xM2Hr28tVBNtn>(p<^HN{EvCR)xcAM+izVz=9Zm<-0Tw3`%N!U`U zdzvc9G^j(NPz<}ODCzJd+3*s{cLuU)PL4sjF>X@wTAt{<;oa^4?MeBVf>egU^>jg^ zOuHsPHYt#~L(gSD&)hq*CVRMq_{8f-s1Yvrm_1N!3P)b?Y+Q+N?gTlL=%;oMl5rZh zX8<1Vn+`LAJg-EOF&`rg@3KNBv5T5E#Vk^*6?ggHYR;`F1_aMd(4p{+WRm4odF#SS z%cl})4679bOjE*mJ8gT5SM#J3-D2S%wH#=bD`xl_vS0=l}YHZsx-)3Y1q3F{xT_P=m7t1UP&Fc`ZR5SWJtdyOC zWgHEwHA(5U33<0+wRpOwi_8$AOJyLh9U4;UR#q=Cy@2frLTa4~g3_B+SIho?_&bch zbwk?w?6r$!Up|d=D;3r5?L(R8Nvl#On@9Hq3Yo5Go9T9437#6rR>^b5Axur=45~}Q zt;xYx10#=x$z28{_u9$B@^wh3)?Q%SiP>A*7dm7`&SF7X_8$&h^|W_%&P1(^E>c4x z2{C3;6xr?I{Zl$#Cy(ZUNoa3YNe^bf&&CqZ7ChwFyw$r}?wcVb)lvhrUD6Wj83K4#FZOk1~lPu48+ za$D`S@D?R0<^sB3xcS!15KAbenkza^NOV%ag2_b)2-Yef+sdBfViVH-e}K<7_G_>L zkU_PKDEm-K` zVh66dzOUqyB7lJ!p;8CayGF{?NglG2Mzmt3^uv9BVk%&ohHR+1=|*$Q+0ewVr6|kq z)upeE`g~S0gf@*|fOEOjk7!f{E1^qEIa?F=Cy#+9p>1aeO)tP=YJuB}+uzAUvvI05 zXHBO8{XLvDdz(2M3DH(drm)w^H8$A{xF8okYUkWz6QOGsfhrR&-FGo{rV|jUgxIs| zmTw=E+!@u#WFV4Ud|ym@^h^JjF16E$*;b zP<0|`XGQRZ=4p{|?eOd{XKa}(D{Ekp*E0PLDNY>*PWwTM82B;p1qyw*yBIo#sQkOf zq|>UpdZUG@M6}!@P>>dlofuD|4BWP0C~-H&-PJ9AkSUuGJ|xUVY83_@uWVZFS`U4(M=;CFM7StEI%R-A2LNSCKj>PnE$%*0b=HQ3#AsIkY2s{dE@YHut)G;L2QC!-Lw0omnY_@ zpL^H^5+jqCP6zzfe;_9R%wWIGIOE^)(z1u`x4O83!@BjRa=Fyq7O5}AbC*xuIiLEP zbsD*iixvfbFBsGvv4=98A?)ed+K+Dcx$RE%HfrXT>UkLGd>h6n1zS2$rForc zs$wWeK_?bM4+Z<~?r!Qiw#$>%IH2qDiQr&P+nq-Y#=G5Z!0K@93|K%>5jgZATPm&pr?pai+1ZGrHc(a^0j6daHDFGk)HMjQcwNzj&GDye=FN>J+ z_)r91-IB?!j+qu{`UQibg5(0Ivde@{);)GB1dGG^iBwoC=Q07tL^zeEK1ZH$;5@lC zilHp8)kojPuR*lG>F+_}=`K#vX)ylf?iS|$fhgukD$+==eL4S%=}7a`WE>*2otCw1 z{mcow^o6Gkps06%;3IITqO8ge1st&~2?G`1$_ET0aWB^B3|ArFl)Obs4;6wI4CTB|T}*3`(7FOEM7a^Y zoLn(M174ntd$Fd4DRHiW_K6YZq(pOB)Cmk`+;AtU8u;Jdyh9vO!S_|@UX{;tE3-r8 zFq%y1xW#5pT1iDDjN$12W?^Y39D8#Ah|o7~#A|Z(h`mV|hnY+*cL`zjD2Kdwkg70< zas>-#d*JgNyiIwIRn0sOHw39nH_<*s^R;Ie8%Mf!Ly_{JFhX}p&TtVX-er+t)Uy3r z^66S2JLxJ79P|YqbfFEXX!7rc$arGe9P+;&C=>_qKB1Mtak9-WV>U3sYroN_BjB5G z(t30pwz_qI8T_|BgMT4|N4#6XNwx>))f4xp_t~kxo-h1XvkTMZi#+OA@6}yr8Bl)L z75+6W>$jS8$oSmT-+t@<^{`4(|5K?^_`O ze2CByXT)5*nG27#bfx;MJwIU_YTT5l1o5fThmzpc=wczOISV76T{b?-5C@_Vi7qbM zvJ40NO6q;LT^dB=`x8TT(5V2(Gq2(APYkOx-dq5&nG*3b;U<@n>lvi{d3*V3@~)nG zuQ{&^CT@f*Y-cgg>}}|>-@C}A%kzw)i2LS)D$ewKS*vL`;}Z4Hv&^aO{QgW z#Q-4qmh(qL%`Ts;NHCe28g6c$pC+W=w|6v!K_h@mvL)D$7yerv4B}s|G#*(?l4x`` zoj4;eY#b*yK`67r^t|pSPsL-h_WqWapC*`oN!~$#a#{Dwd0E2RHhZBKDbI5rEeQ_Z z+V(LrFzwpa-RMKe*dnSpb2_QMEC`a@Dfm%x1p|5PXKT8KC~kzO3lQL;Q5nLN^M$wU z)Mi2kyb5yv)|RSQjTOP5g19|y+YQnQ8=x7#oAQ-tkK6w*Bm+QC5fT57_J80kH;6l@ zAe_nBHPea$Wt=M2mD4Osd*_gKhirqt*cXZST%d~2urFOS=Uw!O3<$siz49~1i{uGd#lAeS8o-Z zu>DPxg=F+34he5BcF>G~eGpo*(T;2ZyIeC#M53JUu>);-iCu;pxe6B-&0r zRVf7us-)*Dl%mN^rB+-5^;#K+AE{NA2rGa7qGnXx3aM=+dlV`2JfZGqw)Y2_O0%^4 zb$BxH1+tpUnNcxZS8+GPW-plXNz|`FqWtL0?h^ZUJ@=J*L*qUW=NC2eR({%y z;kb=uK_OEhq}oQ_k~S0teVwIu=dz$IL}?BrB58)8t))LgVFaP_09V1MX6R5L>=$HB?)sLEjhi zxzNnWKYJZow1h+$ZU#^%3&L(AAt9e7Ch&qxA;xEXC_|RKufE7JUFV+)Q3xC&sBItk zkvfoNLuA@8#6Q~~Z{?r8836aLPbFvZN^>@cnv?;XhE&(lQuLhj7|h~eaO$+9)f6F? zFS{Cj!w%c;u;UIJ9(LINu)~h_J8U>Q?y%9}VTT zgE=4U^$yAWO1zvD>})#D?05MD;qf#e{aBtU|3jC>sTu#N5PJRJF~s5Q?CdQ3tW_5L znMdJYb~^=s%4ijSwZyNC|3_7T#?b_+5$Y57I;W*bR_y$0QlCP%YtIG=6OP0*uYYR) zThnwpb`qUD$~qR|jzzO$k^7H!0Nb;h|J<|^i6<-AK|b8-wv#FQoQd?>A+Pj`=bGS0W32G`%%nC9Z1PhSIjdp^?Y1C^g#Q z8c~m$Gh_1#?*OOCm63q`qGo`SgA{1x8bP`Cq}TFrD#}w6X`WSBpEpvY;&V7KmEJc3 zrV9DZ;5?Lx6P`mx`))y<_%20HZq|>t-@blbiJX5erLeD=ioaU9?Q2k%9%XgC5IIdY z#Q+KSpB7od@ku#m|Lxy~6_PqWpnu(@kZL!<)Iw(TQS&)ZIg7bj&J@=%1vHcp_Sk~j zSS~9;Ar&_F`B{PS!rEKe7_Rmv*Tmpx5#YY%%H3$mb#D5(76OkE{XmWOjEqIZHKe#J zhsQUM|8xA@fk}||1n{fxMW4Mpog)zS_<@Ss58GR|zc-?!@`=UDBJV4{k{uX1E#(zS z{d2Yw5rJLEbX&`~L^qRdvXR_di2oc>8(>R=bNjCBk}p)* zCTRVu_S-9W+6#M)=+gsY*q(mcopOSm%2Z0ow4cDrvBUPWyJuYPIQQkh-p&I;Y}qwu zMZQ#;>Kblo1EGlBEiL~#_m`dWKea0;cN(TqLdDHOTkD?B@A(V2`}elZ8v~9L_hS7! z+$c3H@IRhONEP>2dZ7T$Jw&qF!y#TZs+^_vE#&l}lnbP$F!K_k(=+8^hR*i*V03WM zcBvYD*tPj)W$SyHeZltUP`Pt*;d1t5Lg?GAafQ>+5IGfPpkff>;x(=qKSIv* z5U#|jawY^91FaACEhX-*ZUgBbz2Ox>gmxzbj0DTwI5aHUGEW92rj&AbE213?wt*WW zPzCiWtNkVz8%MyDdxKs(+lQs@fVNdo|khRy>!rluWY%b8ozRY~7T?|S>O=0lJ#^MRs zp%x+H8D>3X(I+ninuV6i($Y%N7DcWqx58PGtFE_nhJDNH;72U%f#wBWh)ykRuQZgh z^D`{w7vd09UMFkv%HruGZ4~b`)R+*M|8f3VD%=f*z&Y^P0QEm^&Q3UbQ3~b)DYrFh!yDfaS_Tdm#z6^_EZ-wSkXM5Cz z&Z!RWcms9#+70RgdxZZU14EkkFaj6@iNnSFNWE)2_JJodmifAjLXoLY!0jmT12qbY zl@3l1D_euS3%r%n51>Wh0`XRh1=n$683~#SrM6r_x`ebm7w<|6LGDsYt?eiSX%TT5 z+i*@&nRGA(RtgrzLPPHIU)0P$9>`0y1Ux~%td7f?CG10^s9fnCfY7oLFPigQ)ye92ZS&6kwiah>M;3DP-wpu5=5 zeevji;JV(oRP6quW~RUAoI|=e0s(iwj#+!a25iXwp?|>sf#Rs_*gui<{ImbXQin=E zPmC#qz7g|KC|+Q-@o;PRqzW3`%QPPQaz_9n_)4L{yeq3;x|OrU@GI^d&?#;6t||M3 z+kImKq#UJ@X55IQ118c)Sw=9uy!NiQB(_x9a_9~O!GRiURo@HbJJ@U-AP^W4?yVGF zH7Q&^<(jjLPq(P)E$vw0K$waxe`A10`z`Er#Ne}Vkz%-W@JJ5^m`nqq_g9ZG$<7=Q z=N6&uWw$BNRIb7@#Q`myd)Gi&s3tXU3GYTF2@5RE2r*N!sa@uPKgwMzo`JT}CEByV z>^b>dTq@C9cmiajj-qBcFFp7)Jf2Eg6YlZzC@?F{$*Q+SVsjl1YI zMIY-fR7WQVhezUIHi+Z>;mL3?81VVwFg`hr21iE+(aCIZB2J>i!*~#%#HaK5>A|U( z3qIl}2eWuS90tn94JWE+-Kc`+$P4Mf!^t>@r!XOS^(2NK98kf_K;FzoV93x{UdiKn zjM*>@BM!ZFeE%%rcvQXDj+?WJ&uTw0A544!MKo@`@6rTwj^fXkPa-N@)H?pxWx2{! zq84j-dRG~`m6dCTI56tmQr^R=Jr5p9O@= zaM`Mo#8Jd`xP|uTW%DXiVJrT0doLa>wM%whnXmh!nn9}nXUuTzy4W-OB{e*kW)8V* z$LvCVQn?dA!rh@_;c{Yax}{OOzsLs-p+TfWs$$XK13x!f5g5S!P+y|zD9Vf($NQtf`uQ>v z&HRZ<-8Vyf*0*yLP~h81Fs3TLkVY4v8hl^G3rO~hAqTEky+P&SOHa`TIKI`+Tc#8x zEz|CZ_~LK3^po3{m@CCfYBF75(591%!r#iv>p2Q;V?Tj^Z?lK*PW?+q z-)CHXo2X$KHlzWAg~dvQ?!4a8@8|flo9Eno#0S#R;o<&h8{kshYy@wbVPoMS`=q{6 zD*xc?3RZ+TU8HB`lS*%(6np){7bCR8E%>>DGyWd&4BbYh2qchLt1Ogv&aSSu&C!L8 zY`Cu0lILMxJVg*|9+U#dFx^s3h7SSMV|H9FpR%&9(#+-l>Q%O>Z?Z8Wx+UUi^=X<+ zmA)KFLr-yC?! zR^Q=Xy^7w-cUQNiO0>wABF$Y5U{Y6CvjPP=1ZVD$hRUOs*aT5JfjZW10T(>OTu=RQ?xO+-+GI^xT%~F`3kL5sSqmHYKy|D0)1xyXh4_0mD9EX>e{Aq z42QVS0tm%#cyuq2d(zsuU02Fm!5UK1*HxAXNSVhq)Dz~W>{3$?Yr&#IYb-go&-p!#s^mHvJabbsSr0_Hl z(A@QRe^Q350|x+pu<;=O-|ZMtPNGb5?;=1}Wk^j;6OsmHpCJDj=HGSdu6`ICRRVn0 z-P}jh90iiVX5dQ|Sw~B++TbdP9uYlMb z>B4r7QP~!yQc>%#>yhYXreLhN7lb^Crwl7nDmIsC9Du9uoM1DDn<$8KsEaDEjhd;^ zN^gdklpOn4#<0|eXpCinuM3r#246<_y;&jjjKfB$3xe+S(DO+q8bHxmKRMk;bh1pV zc@sYH;YEZtRDdN$2!K!uT?rfDap%ehxA0P#dPxEMS1Ui;Njw_cR=mpAz5Wy?t z%Vc{dTPqU8JW**yGeMUrypAL#55>nrP$#Q00{A3!d@%~2-!2xJNMn&kGW36$-*3b3bkZD-+dO>4uy=zR@ovlF?dqyM_GLybGO5C#eTS zP;oXptH2HQ3uJOH7qvr%mZZGYgZHgQr&XDUdV^pXtjY2qW5GD-6)9%ANPQW~O|^%q zzS0b;9xEIi1PZNwfiz>|%Fn)52^Ihv91I4v@0B{s<iQ-$mz(vVuh zG&GmFSZ%;(Fa|s`?fW#+c|!vRL1$y4%9cg}lu}di43y?Z1SR4xpi(ilQ|pp*)cg** zh5QYj4tCe5`7}@EOR9kb?xs1b`6d2EiZgr!+Lb~j%U_`u4Spb{K!w`niaM1+;OJ3v z^=NYT*vZ|akX?daVpb-`+3yX5_=lQj$3P5(h);*dM~C|d2g7+R;sbFU#k0Zb(d>98 zj`;p8j$;uY@=+WQ2PeZ3A05wz^XN##r-!o=ayda(k1<@&ycho8JcolG~}iuh#)UMKsFaO5*h!8tYA91|uKJH-0hRY`FW> zorv79jNn%zccQEqv*BPcSXF*ri4`2+;b3%d9ei>4HUnvfaddDkarSdA`3= z7cn0kpB_a=zXPlB6#7khjfeUhG8+%`FXlEiNUvZwuQ+OMkpC;rn%fF>D^^&Npps8U zXskAtJ(P-b`$s6vZlvJ~oI27???g4PKBtg!&pIT&(jlslukeN{smmkt`#HJVG%@qX)n+bHje+0a3M)?wnQ$G*85o!u4B`rk<9 zV#F7nj9I(ie7=Ip@Ad6OpPsc~Znu6_S&px^jzv?`g-oBeHqH~%CD7c@za+azDg^;>=VnPA9GVb1UgVz#=qOl(nJ7S94 zjBGK_6-&7W@NpT+gea*{2;ODWnu z{EMtlPym3bzlf zrq6buZ9vr=-Lf>E|GkE0B!_AdFfeCN70?=yc7qO2sgHcoVgtio$g??{oo7 zA1rUq&ZgaagK9%iG2)f0TuGwh%vZDqNIog7QZmHkK*Z>kL59M zzj)3AKLv+gI~OJ&3`UiVNp+ZsTJ$MTM&GV(*Zz?4KJ~4EuFjIqXV3dfv^&iG1}Q%I z3VsTXX0>hjA?)DTM(AZ(r(^iZF)n-XEnZ}s>{kIWOpWsuM6K$FF3DfRD%2WJv7nva zst-4K_w@Mi^zZ#kY68mTP(D8=|?k9qHJ?e~a$^@7NtU z(kb@HW$vz5tRIz%$8u1WmgT|xk0|-|S{oI(O#7S1;v5Q@A^};UCg=v_90= z#7#z3%QA(z`zq=lOplTW6)%uX@aQMW-YFStmh8wk#P{qC)P!#j55aZJx!eVQH;`ou zY9>R{b8WXFsz{*@9{gLTv3!tm!4py_%ppD3*>xq=(p0I$LYu1C!Xv4rJskAl|N1Ay z0BXaoxVc9u_AeUMvRy1SFgmCVbM%|e?x;4qc{~`5$Nk~ppfjvxkG4{$Iwr{?cJx zHXQVZwCI&@tNJ3@4=P^@T^r_Tr(uBjLs)>5!IptekE%+j6`iqJp-qk}1B?jH9N0;K zt@)%|t`-+Nn@;@O{wy(yVfHwRLdeyV&iwbD1OntV5iqEYeh}4JC!UQLiF%p85en zpPm0fZwmqbd3p=(n10?olU<8W7v>gRBw37g)ZC|?pd$d;H^3nqy7(+^!tX)d$wikm-m;q}mx*)=zR0$>eQXZHg4 zaf@`SQro-`n#aO264TlX9zc5y4SZocJLr{6@2^zElQ1P><%8uaK_M+kSLBt7?#ZLy zQVrAr5Z&lxk9N0fg`l=u4)Pm(Q1`Ajt1AfF2z1P>++#0aWF?`m1KbHs^~%u5=h#B6 z%h4-JoP{-}F(XP;-4m_*lS+Lj(y0a4ny;T{sbKdERNgJ&1|ElyNfCRYf_dPf|f0g{x@NERL2bP`d)~P&YZ87?d%=S)bd#M{G@|+!Np3Yw<7Pg z?uE$8YTM2#`O+}pA@d^i8gTHvDS?AhqR6~Q4h-gEjPj)xW~mZTV^B*R6-C40;E+AB zk+E`iY7$CKh#%mlbuM|b@w&twU;13CZ|FHO9u7u_M{m3}#$G6`y)ce7jqw5c=BM%a=Z5A- zWn(+$dtd0yg`4@v;HC*<#r!|NmuYODi}+kmMxTUSEH9*qtX#5Dt^I1mQrlprG^T%r zgoC8DLpfnHtONjjCP%Zf*Gi6I_Dxm%L6%@Q0u=*n>U!9p-LKB6%=7O%2(I6UQS$<0!xixz$f1rRuuw^V-* z*tz}pTVExGUBC0^$%j?L%BVR*zlbulOQbo3hVGSM$6lbYINS>I3olbNcOUJptGT@! z5g3Ub@)nK*GOp2W1er3vSSq2X9Ac z{PFg4|KrW)(BBYs50H66#U`Ni`^m?<^Xb-+k6ttK(Q8INs*NnbHvEz2;*r-Gs$uw* zE$}nibch#O(6^t??(lt1%K(NTyB7Ga0dPUy@D0Ngc>;JDvovRgH+(AWo11HR@sj=# z*3Z-+fgafj9l4f^h0q{&)aC&dKF~a6`5)TQfrp2`+#!I84-p-jx+<|WSqnA$g{q~2u%jr9aZ(XtuG90PH=ANPPww$dNgXpQ^6 zdK&xxV{APR{tpL^0;`6%t(@Ui4Z5~0k&(=kb)`5*sVfG)!NEpB1_&#;VcHqWa2j{q z=5RGENSbjkVvq>|8U|klwrZZnEqjNhvGEK8&0PMvin4Cg;(;;}I=L z`JSxNOtJ=EWYNWp;0aEWTf91My3n*XL&9}Mt8Fo$2}azCKp3CuG7x~j5RMtl8}Z5& z-AkDj6ms`Al^URw)s9q_Zs82#* z>?GiZiFZgf2KnB>yEdvkxnM$6e{a^>DVDfts&_Ms5xpshVl^xUEsRzik%$d;pd8mpCEIDFAT z8{d0O-#rd1`yQa-(L`$@!LMpwM*^%CVx@Bb;6tGg1~w_rJ1jQ3!UN#a-|A+0%33`ggMqfyiL7AketfT%&c`YVW zM_;h>PNw!T%`;OZZVdpCGiznsK-M#&{$xroB~7Wp!u5xa!SG`{lE;fc+_{(ycd))c zG0gvX_Qu2lgm|X?Oyv0~@yjg(Y>Uax}fUPFd z2eoFPCG?KZOCLW6n>EZVmk!*e5dcrO#qTIi-xR-4nP@heiH3-7uX+x_%PFYWhIK zaX{}E=#1_`m@}o4M8Sxh_D>huldmJ=hCPZT=>=oD^D$-@_^*a>XKVI|l~)|8%4zq= zLmiU>l*i5Q9#_!P5{y)Z-sK-d87indwE)HN&D4WGKi;aJmicd?WET2Qx!b@98q4jE zZ38%XA7m=J3rfpI6=0nCnnz119xy-*9m&ESQzrwA>wV;0bOPvpuilpzOK?8ohR;M7 zAB;hx8Fyv~HHvADMN0V^3G60vlpAi#aq9Yk-)-Hb3{p9M)oLcw4ztH1|4K)@<8Ddt zSqbjWvd4z3@u_=TNi%2nTPbq*P>%-jhJ->F9pWKC*2$Gf%hlKnq~G%y@4RsB+!5>W zOs}-Jf(m{x7@4SW0`#g_V!f^5S-$#xY^|#LMxW&RV}imSXucWFI#M3SS)hC^X;ji;q3@F zIMoUgM0d0if$7bM;W&d)Bk?@-(fD$1dp3h6Cm0eP8V8~$M|eR^raksa2ok6+>qF7` zp$*W4Ochul5u=LjtcWEg1qx;5J7?1IRdI`)$uw61^8sV0aH=}WtLr@z!EixGzQcI( z$k(V^O$CU+yITKTkXj$d=}XJA`g{0SHy9OiLz-4bdP4s@xzG|S?zw@@>>K3T$|u(( z?sBhc0@IFvAd;Ux%GAgr;mzgT2*5%JVPD2b&rF~~87P(8y;j4B<5tUORcp?uMo*j# zJ6uJByF(_m8l1)~YCC06s{!)a(>ATo4LK^erlc&BQC1UCZp_ywpd7WDlTU_ZY)(A+ ze^=7UhOm@ch<$Tv$l5w?M4L6mV(tj3DZ~!I{i0@omV;&Y(@VfyA0I+T?&mM0sccG7 zi8tAAlAdyh)RawWDJkE^uK6N2h!LivY&nlpwDN6McA>BQ=kjvo=qXHf)u4s#4Jg|0Vx`rJkY&9AE?kxMbFgf@_}ULC!gJVsNHX63-um zHZIM72^50jX&d38>@si(?nbHX&Lw5S=rXfTqprPxyD~H3Z^^8?;+g4M8Mk|XV!B@9 z#EbT$=5wBM7IU+lDX!y&i{8!)TUjYiuHd!}I-pjCZe=)yKs+F5T|f(NJp$Ud=dlYR z#HOEXA@GKyAE?nDX=S@}rMuxEg|hE>S`C8~4CXI9O|- ziU4TH7HlPqvD5Tb$kiNCp`dZ{u4@1Ehd*}zubwvR#^_=;l|D!nUVcWPVRwot;5_d!Zm-op(GJg zq0dW*rc#}A#h;uG#C*+!{u+$!OhA_OFm*7iH-jCsL8wwdN_}^C=M~X*pc3|1UygyO z;EBiv>@8h*?{K_w5LcSoPq|^tA~U%be1(I{7%wv)sYuZVZdB-h;cPo#gACHDf_Mz7 zh)kdg#OK}c=pGI1>9XU{dTbzhU;$V1s zIE;@uKRk`1(c$3eU^F|N9Uh#Fj>Snl+!w=H9Pb|-^5OpJ{1lwa)$&)R3Jgo{$1ocs^8Ow`m+7L*yZ+Z!bMmll zslyr*ht<=Dc@e;;DW_vg2DevcDsRqH{%kU@jg*xYD({fBGHm~@N#u>?ROSJjM9o+gOf?T&`%4NGPDR|_fqo_S zt!>#hYl^_7=_fbozxTq;>o$MIPTWTi+pb^VZb_(qt0`yfUL{}bo=fw3 z;B&?91vy?1K1v@P9A=2!+sFvM& z-ZF3#x@EDtbZe5Rn3 zxyDhJE|t2_k-pD?S!{?eV=-zg){E78ju2x8u^JbvPEp$~nxf`{33He}ySTV~d;Rv^ z*~Qk`#k=dv$S?fe|~!X?)cT4vvZ61j|?%*l2Qe<+>z0|B(r2PE#dHL zzx~?_vKtNt+L)T!SuPFm_tihH-d&zvz5U_x0d|%lfdg5tV9$j~GxYM}8`uIb zPA}iQJ$Jg(VqX%jv;UHpQ~B99@;gaFk}@}SH*$ALWtE$jj$h0(3l$HHTSXFZ$=vNA z91g=i;YC$GRxftLzSEj%lq4Da6(X;U3_gZCGaDPLS&QPLG^SY< zuV5d`h_}BycRk%XRvS{UdClWbin`o0<=@RW#T_ZkD6RAxD^hSI_k8C_{*GqxyQaGU z`azddH8)hhn?xtAX%<#=g{el=1HF82cNm*mJ2d$!`BweeR-e$BWhHkOzeCGIU0Uqk zc}CoQ2N$a~&`nl6elT60F!%9=>GFnY^M`q?N6aI8W0@OGal4W*Yw^yruAqB|hkH9U ze2%%O00uAu1ds$YG{y>kp0|T=e@g|ZZ>jvBThENKF+j2yQKreRJ@W;?*8pw?;b0d+ z?<)OWJ>Cn~kg8Nv&J;}_l!&o@{WRw#RT(Xu-B@Q?Q~`G;ZeM@-U+|&V#{qi*C+d_I zR?@HC8>Jb2O@@`ZTafjWDtW6qJ7RBVNvTC{4rbWipnuau*K}(c>>A9^yCh~kz4g9T z-=HBFQY0MLi0{HII9I+gF^}MmM*BdmJ!|~do(WWTjf(BK8^6MUtYU85YSg?3EJ53* z5T%S}3f1)oOmz!4v2x=oSt@77JX5o&id!}Lc16i^{TSmjN?MqxN(EIZpNwf#inV7Z zkP_?@B4sQ;9+#{*%aYOuM4`OWtnd+?T#IHCCdhg;FAA2G>0%QRZe{n{F4`O6nz)S+ zV*~uu9glKc(Tgma7CcLSZs4MUU{`>`7@ft6F)wE1f7%R#5wqB+q5e^ z?E3Xp6K~rf{e){O3#n34?Z{O@ru@#1U{J96oW?445|S3Eg>(J-DxeVRr2u77n*K8N@b?7S%OSHj#|Wrt>11RF9M|+=b(xty&=W2c38U|GGI4XugwG zz0?6eZhnN9t!Y=av_Cnv6ZqnI6v?gp_YGTU@4!Sj_>olh`FY971cIAO=Hvp# zqN9aQc?^>mm-38>DXa&c>1$J+8ah*2vB}Dj@d7E~{SGTig?&+2IGYs*AmC~li6d%h z&S)T{scv~l&c+J4O2PcaRqAWq;L$?MGK1-9YLttZqb6_HOWw+7cZpz|gl1I)h^#je z=5w_}njEiwM(rW_UGVFqphaIlUBI0Lw=_*+xf8|K5{>CX*wJ!!bQPUj!x@v4nqMqX!wyvpBUXP_Sr8tRh&)jX47ZQ+CS=fLLjr!XbhXs7(__ zK|5p!t)>7@71jY{pJN{8=LmXVsU;#;AmTP7n~3_NJ(o_7F((P&hsup6ll$6T7L>`1 z;Y5E4jcpzjRW!Y>uhu#3S>n-DVuf~_JP6uasafC@2+`7p;ig5<$4J(8HB!u=lXQxMzQK_666|L)=j7z{ z^7`zXvy&6$+Yc!KX2^d_sdCF22?d}?@BJE5y->_pun%etVIX{RWoer4s9hUw|FL)6@UOCn24eRBW9FLeFDWdA0DnD9N?45I^ zLS3pR9jTAJh^0-y74qi#2Nzcxp+;1Mr+gi*y}ACO>P{WsjiOm4r$qhIAcCD-z6#fr z52=25a{0;#tUH#b-)HBwg|=k+G4lt>F#)&jt+Ns_jl;tE~CRZ@_QbVr8%JQVI;Sk<+qhv?$@@jqpzY?Z*c27sU4jQZa-Fa_lymY@@*xc{JW|d^LEi-a?R$5O^+IwfDT{RzVHBYQ;wB9Mw zNKyNV6V%@SLULt4M7LopI3hY9tmKKfJ9BFKnM0Yu*cxIuXQD$AP2jS<|&T10>_uF>=~N|JJz zg_t(i1Kr&5{4`Grgmrv%euaI%raCYK{7UfeQ8#UMy;&t}CNYQQ+P0;E!3T@Jf|5t( zX2&%GYs4q$kqVM*UAx+8+bZHIDPZ9jvOhLL3%J+B2e zc)!0x4;od|pXUX$D~1R4Y7e8~xPNeXKnI5h2m8^%xWBVK-r3(7j&}MqIvj299PS-% z?~I4hVSh(H9n#VGU^LpLJ zai7Jzd)vd&K8<&G_t^GeFd9&{eYm^7!$#Y?gVFw&H9MK6$%u|>iE}_qGqWclHK@c(6}L{n2PU+8xvF{%B`7 z+-46tn#$K=J{~6@oMUAbDOoVU&Jx-ST%Y{wa~N?elwz$vIwHgS9e!6n_xhd0oW=V2 z{lqN(>fQ56H^brXpIf%W-Tt3D9eu6-{sX)ECS18{Y=O6|Y19MGx_`)H?jPuc+hx%C zV#|4;EvIR7dn)^%q4VGfNrU0R{S8Tvv>`bz<|eVwgcc(?oDok|ngH7#@$E^Kz^S)8 zgRFc$a<&typQ3!#LG9`$$-y}hNQjb_bD?}Z=Q*Keb@EWL%aW$JN%E8Piz_I7h0jmq zH+6e}!>h^G=Vw&Ec9juGQ8c_#0==GYh-D_zFJCi zyJT4%{na7og@ElQSqFi2=ouu~LET!_?R#GBh;87oK+XWfHiLGW0XPOF7Gt`<#N%k^ z@J9#9I79vvaWXZ69icL-qsP{0HXvku(&65*H}{Ttsc}^_<2A@5<49^Xc;iC!+U$mp zv?x6aL$a}bKQW3VAuf)jcZPRhNjA_VeRz@`YB%g&QV4(_qfX%8>_phHE?=FfQuTf6 z5~5SIu?@CDI7wrOLes}zs$PI~KoxG$!oF3>d2C;XVCc&^kJ+`dvN(2mc&Kdw5H40F zqcZv@fC#7v4WNs1QRM*;S~Gcu438LqzM79KTSJY$q-bO3o}8a)$7_`&$@Z`lbOw+Q z^#*}TRN4*ve@@~8FpWe!!y_M20S30>TypXpM&xiJwGWyeUfnRLKj|_IcGO?3ZwmtNe%3oLiP!d- zz_oLDK=`~Q9uLH4$UY$$pBbXx*j}Z!H{0q|w>eoBr+)t)7AIRyiLed9%nvX21td)N zV*}|c$w-oyxVgy%AWt%wE%O$0xnaAdrlrdTcb9M9Ue_L8TwflaoSIoP;=GibfBubJaw;=t$|EPp50)b;`0`Kl4Pug) zbe8LUl6OT?mL`*%B}8l;(5dr?^tQ@bt_7cY7sic85U*FsUyXPO*>?p|`S_!`DETb; zxk5y=HaMvglJ#5%P;((yg8(IBqe6#-an1{N1?9DAL6&x&028^?%XvE!`u*xms4rGx zVl6M&I87$ghAyrTD+LR%KqX`E0(+ z$j!*Crjb|0pHw5S$UayluSnceC$E3_7^U3M@;cr8AslY%z;tcr31{N`5f2nq1Aadz z3OG0b(1%+^#>)W0hS9*N&IHv7!2LKVcv`10qeAb{5BXfdg$H>`m2=ZFDj_&R8dI7} zZk`$2i_TQzBUhb@G+v;p;G{^vQTI5Gc_!Xw3OCd~WI4yHKkAXJnxm_q$;>y8@z!uw zciWk0#Z#V3>mi3c|3>x2LF3=pL8BV(-?wYVZx`d!SXTFR%Ft<}Fq|DM7eP?+@lW6a zU9cdc(UiT%Q&q_!(*?f0DA@Ig~89*l!iOy%URVN-3X1sSvF26D(|{v2>_tRbG#lenB4E+DjF_k;o;=Q0Nx4NJR0B9 zEMnmrcAM4{F6={1)zb!g;g&B{k6}t{wEifRACu%0%GJ`sBZF(tWTzb;7twTYN11u> z&?!iaz;Xt4jfiQI6KXoO$^-YTjURK;wa|&oNgCIY4O|q^Jh2jnTW{9jBzb&s29S(J zEs66rrdhLuI;5%8-CJ^<$P#*52eQ2Zs3aKp>c%|+#Y1)wTE^gdUZdz~ikqx&ndgGmhyQ;xnC#LD4J4WgW& z8e>gSkR5k+fv+VMWHeUsmjDW8fI};Wbp)opQbuyuV@1UXe2ivWGee9cym_Sl##5_> z%cTmKpJ>@WQLgR57^R88A)5N%_x$6 z**^6u9+TYC@d7f~ABKa2aJai04*Sjkjh2Eo>efVQBDEt6GH%m`3Pij*8{KhUPGOr1 zO?}sZNe*Cicu}z~KSDieLrzjYOG=doHd2C8K>~^?mD86-1sB51(2$%dJwO)UG`ASC zvK}JZ_PUugM-jC!Q0$r|TCiFqu3F6i^j39unOfa#0W4OJG=`y7h@MzDj7D5qQp`Wd zl^xl!BsXozORUL0S*;!VeCB0KGPobv_U5L=ne9f0!`;#Dpnpi&;Wpi65#1dQXcP_U zaJU-{=#bIf!5-b)?GMM}A>AFs1G+!l8SNeH9SmY!xzFaj%<4>t2A9$zSwTyUl8hD$ zIj@o|O6PF{uh`q?n;5dMwt37G4E|ko#Bbpqs9=?xCXf;awOGJqRKr6Okv%V~EZm!9 z#3DKutVL-`1SuKh5LKEj<^q+?&`KL1bec*>^CU%-z;MkxG~nnugKf2ogB!dgXQlsC z$hMjZGoR|`P@P~?(V%wtT*;~)}c^^8~8~$O%E!3`-t)IRM_BZg2HyK3~hRGIo(%VV{KF3KjHn;R8P{q9cQllW_m+BxfBNd z;m(^?daHiZXFADu+h>T`6zX!XMT8kP!5DI(9Z60_L{rBPTbJ|sbjV*^sJnLa3&`>7 z*DK1$t|9b@Nfp20EG)T`gPV#4EMK8IS4U6Km|dTha~`t`oyS3uGw|17Pf(ZA%5VbC zxhB%5jrKD`?#JWH^Rx4Bk8E=tudD@*KaS=_E@MWcsZl%unFi_I%ttK1jCf8y2T@@` zQ(^g#SEd~bS3_u3rv$J#EhS+>)}IY`_6~;|2rr{~!Sm*nX0bBJ!;oEEl4O>rP&b~M zAw!(*d_&hYg_!m+xXi-THjc;w<3K~M0T#8PsUco10DBaO2{;cqrxc(E2}`s+FX9Cv z$12Mz(lnfDOz?um5S6XWAc{SOAG@hix2NhXdpBhOYHoW?#Y~ji&~pf>2UU z<6xwU2g>&k{N*#6_8j7;-(PhTS92pAv69xVT7StQxypRI+RYYz(P zCG^moplx24JT|uQ$Uz!zd}3k{J7?PKm!=2ogZq`nFq3i`Q(eg_?I~kOtec2JE4XJ6 z4tM_NhGx6LoE;_hlpUvF)g!0Ivy1NTYyIp~ccHI)&MuscM;?qN2Vlvo_f{}VI+R8u zEe$OE`}R$~qU3Jzo(&!-bzZWq%q!4aa$kq3h?^=|i}l)7hCQnAYIHhO;-*5p8cEBw z%x=^-!*+rTvBb6%)$GSy|hMJEtWoeW!)OkVhgBS0=#yB7At_qQP;}v z<1$Wb?zt^6c@Iy?d_T|K4&U7l?_Jw}*E>X2x2%Mm*E-D05%ln)vWB5Y?vJ8JR>sjI zEuPAC|Kxj#;fHuA`+Sr;y_89ppR&U~QD@z{hw`J_)aIk?dMUd)iC+jdBLn=g0qvNW zEvT5?(tQaCY3odG4S29F85?Jo`o$HUms6INi3&(^!^G+?BownBMsW)DRS#S&Lqa!Hp+pN!7-bEsp*H@U6@fN=>AppuHF+c}lQc!7?Jkm-T#;u? zr^K`7&XR#?Av#p)9a}H|&v8&4WpKYTHP0PBJqqo!bvJ9jWP+7FO|o76T7G z4gk%$8vIpzXvuefvsiV1%O-Sd57jDYA@7~v2F)ENaU#f!(JaX(<9Vu*UP%pl$rAPX zTR2{EIjwwVDnB9uGY2z=;V7=P7+ADF1!h#W^Eaw4F+N#fY_TmuCk4;`Hy>5WIH%0Y zHJMd8qaCugYn3)=gZC^gwI?oAT3L@&ibK^ZUb~`&bBHp3!ECDF&RYQBdS(X+8;56)tnCh4Sc2D5s@%0OT6yZ|An zT!2O_<#*P-X9HIZtAkX`I2+0-NBjA__eWY_fi$xu>0z5 zX56#Jx{ne;dTI*v;KC|PQdkXAZ6yVZ<^}k0|BH{zMUZkubk-C4d#Mc7a$I@F0x{(! ze3@7d_g(3M5xP$kwWmaV;H_e>=1kup@p&2WaWImSAWlSCB%`@j1}yJ9<>X$I6vDc! zl5|nbuNQ2?bUXM(rwiGCnDf_}(NqAeQ#!+CYi{l^HMAxxR4P7^H%Fw`Cw(#?UvKS@uY0z0%733C zrr|%WXL1nV;G#YgV$O<7Hg-J^CIz3%L$$U1wPUL;a+757kyZ$hjPqXk?9w2qzY83x zL-4(w7TagE2+LH2QtF4e^j=sbTp7`5Sq;{3WslU_{-|wZ-3i9Anje&ycrH19uBW=% z-*hqCACuI*I!Vo^)3AT~p)4>H59s2S3D{!n&R8ggYy_JXJQLH!poFBOy9e|qYy=Wsp%Kai;%D!o ziG1sXV!+4hjmMErNCkiwN?p}NHKimYZ*!KtsUUS{v}}06S-Pvoih}+>&h;gd*Wv|{ ze+8+ICb8ABo=Zh16Ui-mE`^_R=hm$Q_n^t;#R-`vqU4i;&gzJ^1P;qb za>XUl+A5uCF|txGZm(GzN)vY3>CZawvaN;wdm%5kTo^WPQCq;0JG?18D9rvV--nR) z<1rK4cUyVPSs=9_Vi{DwuKt-GJ9!Gbf~~u%Qi=o5_1a=)L1=-TVw}9kL*cwSngud5`77DHr7>=jD5n({ifs7$9ysUC3dU z1r#D@<;#q|+;k$(AqrncnRVxY@u*=7EG9Scn1}lbQ|Q=O8e>V3L#>@RTR~B|QC^HJ z_A~+A#5T3%C$qvW@s+Wm>Hg?wl&O%;7<5i847-llos`66y&@+#8II>A#{unxWodH* zY4_ytI&wg&8vXpfE+qQvmRZetsg#5638p3x%o@<{Xe#)T8LMhO$i=Tm?ucv^^UMT( zLebk{eSwLEh|07IQ;eC2ie!YLk z31r@3PKF?{_DuE!FJh#jB_4pvjOVHCcB&CSzCRGx712{g$pKgK@;A@ma>vR&TFm8P zOJmr`>cn(j#{4c@dsbxz{QErJXQ;Q7--oH&gVum!~egLT(iTLZ8m z{$X)cPk*#tr4iWBHc~FC02Itb%`x4xN5|azQSyt~YE7!JvZ#6^ksI7Chr~kuG$E&WJ`gQdne|yMaeHtbCnh z6IPfUPJ_OkCl}*vgsdcH3MS`Yva)QV-lNdmw9$nXU^OimdH&z>ICEMQ@a1?eSp3iD zA*Q~)1WK2xh7&lmt1<@GL=JteZ^21_mKW%~f*<1riOEfF5<8@{fP1tl&B*RxNM0`F z=}qZhr?1Yh`ik34yncs3^GfWz%EXDP3a-A?4(9PDmFrGnI>^(toXR9;1^MQ`0FFR$ zzh0fA%K-=;8chwGb~3Uz^ut+x!HVycm);TC?b}n5#NhO&pn;M&Wst5UFW7B@15Beb zxwYqla+iSnH3h?wa(*+As^En?ZmDLXM_EO+}O(iclxU$9aGs`#o# zJZxEa(BxP_-MnIBRun9*n0N*EO#)pq`wpCtazri@sm9cDf6N8Wo0ygqwQerQLl{&o zxtf5QvsUFN#`s#!3ptf77!&P=BBs2MlIZ&S^`@PhMsAjXd4?99>+9Frk4hsLh2+Yh zQ|V`t-=A5*!NCJ(u!R|>P{DYnrtbCiYoVC4Zl;?JfF4b<>oPqe&bo#$W$YN(ixYwB zEM~lsTMnuwsN7kJ>2e#JP2Vu5e54~Sd8Q^Q>IMN4s8+9X2}ko7*w>Wb$l0AzjF_JZCnGsxuRDCMOulu`JgDU5ywo@mvVSB?F0+P|vLgt~lOF0-z-X#bN>49v(j#S6 zS`}1_q^WJIK6^PIkHPZ(a|IVQrCG*O-RE<)0~ah}Ql{59RvEMm;(=V?G$k_%66L2k zo3pFrXNI2j53kj}8nfI=?Aj$`Di9hoAfiuAd}ct|{;R=_&o3csW1)I!i5z7UBc5%g`O&eA( z$?OktX#ms?Y*f%n%gS@1HWawMgM9=K)c)?MI>9LA@R2Y!jGPs+Adk*-F{W0 zo&8iRCWzW?g?K|KxKzkde}=DBVWUOwYM*(v)8lHrx;VSU1Q$Z8Mm}H>C;~RkiFTVp zfu_u+tsz+}BLG6xt6={@L0xfM)=JYpjGZkDo}zJ6wZrm=0=LP=-7wLG{I_RKI*ki7 z7+&<_qBl&zXB)q#nvBJ{6GGcU)tdmwWZznL-DLtl)%_3LPy%yu&?<)=>lR1hWP~uHBoz{%BFy)q*9;&@)P{pHdWF(wBo7kmDLa!>NeUqkD%t@o;C_w(W5PJefAdw*|d|8VbMxU)MRACB2@usc2&#lunDXY}x( zzdvG!`$PF`JUAS)!Du+x*&ndo;mD=l-qS1fwWs6s21=ud&$H4hs@@#q3%4(EU3r+m zqq)^>U3FU$(<;_>+w38LcivVB&n39?nZC*)$7RVx$qNVxOIaz83aA-5@)MJ`evf7T zZWU=Xy}_FuMCPB>pvzY1*@@g#70QCXBe0361D2ZarC{mUA%)wRG6tR4HxHm7Btqqs z<$5ayKLE*b=+OB@F>Ls&<=fD|Rr7A>UrVlv2C*f1IG%!BGcU(|sopbB$4cazc{^$q zx8(28zm_~6EpuH5?zT>JCqHHfAv)>#t1vI33=Xz{AtI9@l{Z!hKi=vCamDQu+!Eo7vX7ToL%y#zo_O_$=@L+GSy+7O^4*H{mctCe|_XYz3kiS(n|vA{cUo|L6(2(zR#z5%YcypPZ$R4wi9xuUM+?Y%ZpUV}Nb>$Xv# zj6aZvwma`2oLvWiTr|mc*Z@|lpuNW$PMr6qy-a!4L;3j4R#E!n?Y1`et0~x@O`EN+ zK!?|umQ)@$&?4&RRhGHJGM@F|7<(+LM3Hq>L%+AY=|;<9yc$7)=H71;&x%5n1h|a3 z7flRh#~YVRM&logq-1Zi$j2~#uHgCZ#klpQgLg#kr-4}DRsYV)$EQ=_8fa+$&fR!l z9j=lWC&#VwA)>x*Qh#;B7O?x(iX8uV<%Unp1uWCctK*QIo)EZc;FE&p(}lhTF(~~G ztsAzuMr71N&|s&3xYz4o=V}htb9XJ`vpQT7s866?{&3Z+z2n7%X35XWkBbQc7UY%dzoj6`@gGE_+dT5-6 zbrw!S@>hLX1;7^JUyZT(Z=tx2*2Awij{YjY4)E*0si>iiO;dA?Gc@KGOz`xUfg_l1 z%4h*jBuO?Q^W1g?JG;QUJ!GKvbYqxMf z@;puO3KvkMEz91qxm~DDS)jL!X;}vUw}o}fW3I#-yEVPq^b2#7x7`c0Hy0%>{?vbTUG>KOL4F@U1|%6HcGY@_zCEEyk*V)LH^{o&8BGCLIve$;+GuLN z+Snk!;x7LWo!?5#LG2yS({w=!nyHvZostt$9ijj@=XW(YeMo}{epJS%@bdKd)jtrL zGqLUsG>m@*f~*t&sSN!_kG-Cgu*|5&FlK|ei&ADhgRn1yR{j94mIbD*a4(I{os zDAisRETxNTIP_@fL9dmbCl#e%EA7lbc2zplj~_{ylqnYQC58R?QGcd0#mX<&zTpL-*@BGc1q4P+S(+e9R# zIl#yxi{-S>vaQ>XAIZ94GpX6SR5!vm^k2M?#JkEQ8I;+Y;PFY;`p4bV@AGTy|L>igyZ!y)m;L{9{62o%`g-jI%=MVn7-JCt%2KUMTAdP=k7c1; z55l#tx0F8WK2g?c1VZ}TF_$}#EvSpycmN zu_uej-ZuO*nO)7t;KlH58VbBd>Svr z!PkX6=BllcFFE(x4?@j``e-?HdSqRmSjku9ug>$ok-vJ${%vCo&cH`&Uz7LF7w?ah z&7_TE7EZ|fhLYVt4Sp{vd+UCG)ZOGwtfGgpry5)~&}Dn?*NBx~+gNxY>aErm`SN|1 zr0=B&StAwS9qG_t$b|zRSP0dX8IB}nyP&C!iJ9gQU3>I`Bw5TpkdXANS8nH8Wd>Cl zZ#UUxhxY8Rkp%V0Q&mj?mF)#SSLmWPj)JN#e}Sb7MuR_soA}AG6diflNMuQv-(Rk>2f~M|#+^JrZ7`ZXX(7VW;`lvCeL?T1Ieh z)st{-+Y68N(Or@V~zR*y|e}%k6Nz z(T2&i^ zlCkoR7dJ^ZQLS97rD!rmbUgYRk;n3pdWl)R0=PPZf85bBnl|f+6A{TH*rK%>gN%?S z(L-y2aPK<%S}73lr@9QrKU5|(t8)B=$18H6MXWo(?E3=&X>5M|bwwU!gjX?yMy+Oxg>RE`bGOSsW+Tt=DN|N&oMn7 z82Vp2eK*(1ZLDrYlx~~Z1`9M#6xt@wL@N&w=v?|C?2CzZwzSx)jh~6na}JbhH^o43 zob^($R3gZV>C2e%u_@^S$j!4dN#&VAf!^?WNv8Y`fTNtCZ7N zC*4i*obyyzZ%30nXH4oJmXxtx${DYa>D(7IzGX$32%O1Hip`JI7I2rujAgfc(OIG? z`g9>SDVPuwTCzL3@V$2gO6^%{1dx8=Wh5~H-%dwHG}T$7Jr%dJtfiX$x2N?h~{JhXEjSEJg#-0nYbynW#7T#w9FBB--ckgyttDEXPSM9l+^pkZ(&W-UgP;Jbh8 z?S@+Pl+e@*^Zs;wQ^B|YG-US!s&eOJRmt+@)+}rKqvO@mY1{nPl`!6ZXzZ!KwbuOa z^IQ4+H%b5u=OM?yCFj3Ee|Jzj{|)y0{V(Ug&+&Wk`A@%c!+^}aJc@tvsN>yBoN|Ad zQyx#5%G#pkbVrNVYUx_wJX>p@@)(ArBNo1LdfSx$_;J~Iz#Zr>LKP|ARq)dw;j)|FOTnzx_r2e~#Z{?0?DtNDM}w zN>>8{c|@a|J6gm7usCU%j1aw78U4@~0l)j6vHTUw3l`Cm#TNx1F}Q05RGYx6s9w*M zWn>T@kUJ`ff(d}!V=6D3RaG)3==yacnJF0Q{q4mdJm`^ieKFpHKXrqZ2j+>*`i6bm z+Qs?{bfWOxv;^cUxrtmLJAcDuPwrz}3JmlxKvF+qK~( zJS%B(Q~8yyv!8sO+mjUp=y=g18}6;^m?kOdon>GWa|5G}AVDF89Mw7|f@kF0?@w`< zo_8|-TxTce8J1KWJhz~x;QC!?+GZ-L@HTA}8!cp=AvsOJT~i}nRUA3&~APj)i>5 z%4^H1ERxxhRi!s|)en{kAjGp?TPAUp{->JD?%rVDyUC8c&g52UxrzZ{uV<;R)_Vvl z`}Nme%eR>Qqk-^Jn;xElEqI!~otHR8FL*5Mvd;+1AQAv#3S?0Q?hT7?Msqbb6%s(@ zh^*Z_bkP7J7Q}o8l2tp!pg$e?D!f+16TYN^UC?q$dJPhwcl9=4#1S$=%xA71zpUBz zSk;0s!@Njtlax)E@59=L`PV_X-4FY{$|3O2aroyLo*1`knp4;;6DGp%=Od;zrn)!w zeLhGsUTnBSB*hTTb8?*L$Hj~n&xM>Da0OX%(wk?{e;JE=n9Cg9)*x^?5!S@FNJccn zBo;Ad!k~gccq69MxXJjPLM>JmL4e6Zg?eaUbBkV*8Sbo9m^v;tqK@vTzpzh%@{D}*yWUw9#x{_ z0)+Sn6dYDZ_f<-?2om{G$-Q+?on?V1#DZboYLJYSrnP z!gYLt#|(Rg@}S8Cq+@Yn_<^k>bj1hwc7HQzHNumnQNg>gf`97Jj6}*~Z*-_io)q$Z#WM&sm3Df;|PJ-z9d+O=*AlwugfN%3N< zoaH7e1Ru|6-Y!=m?elRl>5{9pLq+#SMReAOMqf?KGXIvuVP;OE%&= zMq_Ig>v6!f+#3}M8`t4D+Hfc3S$uJHnl&7(4w6{7kte12-&LPvv6(%uhC*l-y zDX3^pi<5!%R@u=Y35BU;clnA_qJ$SMs)MqPbsEkbHdkJ7H3bGAnrmeHVGzKO)wr&& z&M))VH-A0LziTo&^W@>Pv2)e9b#yNqh2r6v(d{Dt%ar~yr7ectiSmi&bghzyPHIon zSaxgc64+tiA6&gVfBWk6-TCpG)3sWceN*t6+s|+eQFq+-&%T1V9n@aJM~KBE&tzf7 zV|GqwtijC5+3T|(-n;{zj^CVKT^yf$2A;HCG&H8~HpWg~|8RAEdimz`>brL*Z_mFu z`?k*A5!t$>#a5b(jAmBl?A>b6{r2sf(>Jfr-ke=8Z>IL|`lhA1`u&kgaT;P4(psrF zxlIHwj>z-D^VTE(flzJ+-*MqAPBUwMczJqxetLa+_3rBQ^6zISr|-Udd(~)!GqGz_ z?`6Vl(x{7#4$dy#Uara+P+gs~rh0vv-9DXmUAMtyNvQ8ktWs$*X3-)_eLGjioUfxP zO|m4Lyy5bQN$*4uWl66l{qz5Kfh1(@r1YI{^SrS5B8_v;u*mv9Hm-7X?DtZ2hW^P4U63jC-CZTl@ zUS+;iS#_*ZjuWTTA+57$&|hsDSz3(eMyG~7qq2$n%)F4Ct+|optTOwp*`22>As3D9 zA8V4|snr*jw3x86sS!vuf=qR+ zE8U}5@?Kq9BfersE&b{-&2P1)Hf@e8T}euA^z#O+v;V{+*y|*le|VcWvaNWeah(hI zNo$e1f~yt5L=gv3RCtCTbL`1R}VZPrSU z{)P!bCrlftzoBV5qS4JYf6XW2Z3YRT&3CsvozECtH8!0Sj0e&RdD}b-%u3D_So!(z z2e*=VF8KJ7#7VJIZ8e}&xAWwQ?roMX>M7Kg3k^s7wo6}yYU*zVoJWdzrq3hr$yW1| z`*V4Jzk+Avhs=6Y-IAC%K46?|HGH+v+xnWET%HAQO*%oS6frYj zUVH<=+~^RdeJE>VZ|fSPeC%-yKx9z%Q*{8*9d|j;%4EhuJA-8}DiYq?@TwT2d>qVZ z-ZsBw&y2;^D6iYV9dG0Wu=-ec~uEG)U{Oe z3=u&SNdU2MAnX-sK)U{XOvXBOZC207sB(l`)P%KxvISdbUtQFOu6~ukNrS*}vqxtoaWi*vXg|B%bFf<^xts zK&AeMzbYi`#sx0YZ{0Xr*zhP#o(Zq2DCXHpBE7jQl#x8xODPsF=P*lvy%U~|UnRvG zU8rkYDxOR1Pr|s-jan?&&YZmR` zZMkM_M!7N!uEJc`&2mr$z=#n=4jETlX2Y<;E?f_J-!( z?#hy&Ei**>%$8q#lcdZ$t?$DwEEyr;=1sK0YN zQx0#lL<@VG?1vK2%!0H+u&>jVQbH9AonoGSyh^+6`m8r!Lr$t*k_#5~yj!-CU{Ioa za$DnNRRAA`rkMBiZVJ!ZMAi~p@_fWF$9nx+-3suFZ%lDN^X=3gu_#89yla(?Ciy+Y ztdbt1N&Xnt>n0pH#^&MFn&#yl6a^_?;c)Z5c@=k2KF|v^Ut7-9;6REC?EmL=^ zYTLefjP;9s$aztQ@gk$MBwE1;Hct6n$|s$RaI3Y@{U&$wGUxA>5#rHay|o^hxgio& zxta)7Bqky&=E+qMQc@{lB=BVxF*I$D`e*5C%M@6K2={&8;?6GHx&#*E)mFT|xOm}3<7Av&5N;c}2)3vsg zt(e&BsIZpJv@Q!=$@aUF0oCHM9s&+)T_CGYMZ?fdlEr6&^b(A1ta!$Vb9END!hx>a zg?d4NQ{ctNk6qu{v19F<)M^YtYIzo;j`voW_IsionM&&Z_)t~WPA_|?$9P2noPR~EA(T_o9rd|xFzkOHI1efT5h zD$NATN=O_FTQ7Fll#BAYP!+(L9BZu5R&@&Gu%=4bQJ231g~BVWPrki;`@_Y%%eQa4 z*KLP!U6XowcK+_-`1-qUI$08qlFVm9a;9fv7JN1rE|1>j9=cd{>Ustd&!VJ|3?f~S zG|6sQOupqLFZiUOGcroRt2+@S$!_@#&RK*`EN8RRgfi5+JhC!#F4u(F6X*MuC=keu)w6AmeMF>{_p3NroSy%{eS zD#PdIV5DKMM6QzX}&mGzaR{O-5ldZWZ;QVV2 z>Tn4xS+75}qu2Cu4%8Za0bjrs?_etv>L!Z>_+|a=EGtRxtB-nC|LRoJBVSo7$F8)P z`59Yr!_hpn>^hCtw#mN3FsV3t^uhOwt5L<-XLB`zfjq&<`rEl0t$cz8%mzzvm5WMaR13Q)R#8oRD_?rq-H`E^$=TfS@h~q&oR^|3X#P!-vZhjfN0Txb^CFNR1oDgj_yxOE z{f$~QHcV|(LK<91pRRxedlnE(V8$biw|Z4d`Ihneg^Z|R8yi;dHZXWtH07lCBTY)B z5SyU{xT$#-hM}X%Y1p1YD{9Xtz2Y`44CHzb;-v5|r?zhMf_6IfG%)mj2XopdsO1<1 z6^5QQ%lu|nyp}qC{rcV2_3`xzS5n4d^Lw`N+)TL+)AgGL`MY6@&i=$7&rz1OxIrqu zUtWCk8}cnh_XBwU@$&5Y^xet%8Q=-L`|-Qe^LLl0$FKhJxf%f)aiE=RgS#oq0@yrP zYsZ(H!{67<;g`edALwuj0tDk{u1eYj)A=pVrCp(y|K?F+Enfd^_quj-olrjrmqNQ8 zW>Uy`+@`ENK8)x-@m7CKXTZ;>oqOh~Ji&a!i|=(R2C^>Su4l~3+U!l~ut9pFERv|~ zZLC-v;Hfq?NXIb>oHPL8;CG;N{)}c$(Ma^o}m{ zTFZ-s!+4}rh;totSYLHcsUBHR6H$_{EGVrS5z@m051R9%A_2DyJ8;v@K6(D&Y`}^F+Yg@a9&O zykPKD6Sr+Na>*R02^E!~w!$nGO*_)k!?b!-3&m3;l3aeRDTPTc>=Sj8!>p90tPMmm z1>W;V>7~n2e_kHqyLP2!wVv&6f6f000tSc z@{Tc7#d`Rv=SC93*tcnFcC-ka<>lg4QXG+wzgl%)bI8aC4tUJer}iB|wunlTDQcuW z2BxWsiFeNFbvu^|IVJ|>nGv(>oS z-n)LUf#sd)lOz`EPHRNW3Ldx63Cluc;IzRDbju}mU%*zMzmATm`3Baypsnfm9kFJM z{A;6T`CVyw)Xc#5SRT-dcBj%Ls{_@ws<7>huHgE+jLmjNUCGzZuNV7jwa!&=K@a44 zB}kwyK%kD9>q7^EN)bG;vQ$Joi{?eavNBzuzQG|YtDO2w2qwrn3n!sv@7Snu=EW51 zV67EkNO#*eNyX-W!~7fi6MRClN`2j6IuPSL7CVUfMz zF*_ptoxW{wPD(bb*@D2&#t(9+2NZg>_SWsun**Uw?wGGq_9s=|)^ouMGD{}YlHAb@ zE}-Xvk?Yr2t@_)FsEM7JiTJnOSbTDBk53DP;%_@jUT>!5r?dK?SjRx(!zNq>>M<|) zzgSc<$29%h_KwGz9e4(tG?ty3q_1Hns@Y4#yclPD=6=1Y_;CR0|hO(K#k z!dcI<67Df{T4&_2K^()r^xl~>K;u<|#o|qMM5ZOV+)`_I z{WxC(6kZM|+%eJ~Ye9|tGOoOcuFLRTJ225ode%o}xk=?7` zUe|DKweYnmG|Q|ujBOt0EjX-85m&8${^`q4!=|%Yp3;&D9TADCHe)KLBTkE0s6{ZN zdAOjn^j>xJ`~Cjj&JO&y-|yG|JM8c6{%NqYzq8Zd-rw2Z{ZoH9?C)*=iS$2NtF7N$ zp7a0Ie{@~-#{EHlH9=VoxGf!Jp|9XZ6Z|q%Ue=V4bYj+)Nwf8J_%Fe;o~EH3G^BLd zM1r7$N>O$6Lf4?{Gh{$U9=#w1o3IZmWa2nYNpJoChF@=OtcPE3{Ga~=6@Ar1;-vT0 z$KkI~Z4d-&HHg%kB#V#8i59_Y8W~jzKqDq=)&C-;aTbxiZRLY=H6M?Y52P2U{J92t z5x@5Irzv3_cD@QPS<0wj;kkJWnE=X4k#sDf4W&&SkFIz1%&uZL4hh46h{F+a;p?UIc!RI-A8IWFYtrjN|5Tj6wH9~G#F;dSbU^ENh+6(@1N6Tos zX3O8T2annkmw6TXR0VWS3MPb9(h8oYtZ10TnkAHZ*bI_6Z$9~KQFU7e>Dq+3Cy$PT z@kgCiRc9=pQoq5Bn$VKn(Z%t_Sz{_$uRh-#Qk5>9Lra%V;-DIwJRyCPhr}D!m^6yhXKk97$3Fq;D%nAMJX0x}; z{sX7%-d<{JPKos^1=Y1-#_^zun)d-~aCK?DoH$ z|3Am?(ZVz@_>7fPHg9;0S#D)kAvLAms1*O!H(oa_wYJ;E;P2H+@QJ;)M9v~vk&4$l zyEr1}h&+j&w}guxc`v^Fp7zRE8y17DwJ9Jn3ag}{Vr+$}?W5 z234`;3Pr=N?;hh&Fqo!EHZkL1JzB+n_Ly0KOkXy6XuNm;Cm(&NohwPSY80CXeD7E; zqy6+Fx~#^}F|Nya_~fH&{y=L;wblc@(pNWQ|BH`aSAnwnuN7CU`PdrY&!vaA>3kD~()pVk6gd z+Xq@;YgW6;y$`Amq;GshOWGs782*ExI^EbdM=FD$?CH*4tjVm;bNudD|9Ij4`0(GQ z_P_1^c0K-gcX#+@{eO<1IV-FYmDc>Hhhdz2lr7yF-Z+((FW=^Pnt*D)nVW~uUcDIFVoT-S5$y3 zsXdBVQEsdS+9m3%cjV|rBgI!lL&3^<-XmeRm_~WmB54to^W^xdhQzpvjMdZ-#ml7^ zo-nx18tv_{EJB*t*jl;o*@8Ibz8EK;=GQ9!AFcIOzfSo-*x4WM?bPM}-u@T=pU?8M z^uKjSdTy)|0rU~mE|FKtQg#c4@tilJ(ajw#VnHH4%W0WFdd7v$y@VJ~_}$BV{D$VQ z5F_s@`I%kPGT~C3^~1iuwD@Vx3K|12RBudE!Fs-eCn=9^E($(cR`43Ldv_E%yEuLW z@74Ac-JEaU4T7vtG(0nohYWj}C|1JAQ7<>nMLiKgjaC!=2&5 zfxpyowos*pd&9xbPE`sA=S*smNx67KiyNpLyfms(w>#8*bu_q``q zxwn_-&+~%)AlOBb%xJMt(5GFL55x)JJO0ZiHoQ8&0{%{+<<|wx zL{1Bq0ibD}Q$1np^L5HHG6)aI9Tkv4EdjXonB^&7u-Klm$(RT>yJf|RoYVy)y}!K} zgaE*IltJy8$}xZHoMR)wXPXP0ksMh02m(C5wm? zfs=B?FqK160*898@(l7h+@k&~$lqSv%7sry{Fa4PUck?z@+oaON;S)FAlDn~Qtk}&v5AWukS~u_9YeIg1acOQ0$GkvZ zGR9&S%W2AQSy3c0Ba9Yl!U{bF^*4eDR^mLww)mRl*~`Em~-? zgYV?%NOC2=f`^9Oji;|R?3p6Z?sZDNzh+7LH;wD=tLp{nIUTK8@>S=yvregNP#s1= zhtF6`9o16Y=qi=dLN1){LXyL%>@EX~x3dJ!M$?C6Op}!Kyk&KwYfI3})lzao<@!%z zlmcX3*1Ac6@@BOctj8=bSVT(}Z)_6P#M)C{5Nww7d_&d|@vKa;ISYH9o0)de*_^s4 zf#;2~Ei~+z3@P_szw|E&^VZmyxX@YC6%`~CWy#5uCRvhAjC!2$%#sOm!UHPnO_IfD zg7lIMI=B*rkov+Rvf(Hh^%`EZen+b1p`7RMQSmig*)6NOH(?nok|?-k<+Mfa`S*h1 zejwG66PiEyl~bfPWoa&Jvs2D-b!s4Y(c_rO-vm4_kI3_nJu9DI?}+raZfOBYT&*mCTXvaEf}d!ndpfY<*XL{X zln{@tt0Jjz4sd7_Vdp3$Dzmky(m5J871`4ZJ}-0^hU5$$$T3G^udhfB6AhA`5iu_q z6d3a~<##}`oR_?iLO99Dv@CORw52SMVVYz&TW-EY>#rm7OMpH#0shxiF19%YX|>_npOnti}DZD;Gl3r)#AYj%6XoC=MbD z2}X~|b9aKMpxUiwzOCmN#ljXVe;D4d1%4H=qFntmQ<>lAp)Q&to@Hf0qnmF}&a`6; zUL5Eb!6XVCM;mh~0y_#V*()WvdYx4L?id~XyrCaDSenrfk73Iu-p!etlgMa(kVIJR zCnr-D-6-gK^;!k~t7AzJ$r5gM{uVNA+(=oVEs^rj%`wq3fs+I}+X*t|cO=0=3B&Y{ zVoD1*z+Gh%_?#Y$YQ?j!c0<}QB zfoHa}e$kG0$^e zlwc7_7nmm!$tr3i8r`rg4#^KDy?w!FvY_1B)0h=HKf56>rkFxgsmqv~T9LCVkOLU; znN;lM81i`uZ&h0tK{ZtZm@3eiO}wIh2I=K+@Dn%yID^_o!^L4zg^o=bP#0k>7y?s9 zi*m$h8I;M4@p-xGiq(6#spdOP=^6>SUVNs)2gs~OResq;Dr67bh8|UyCel_HtkFl+ zASw8%`vsi&lJvw)lAoMkT$Qw(i>s0rNS1MvpBr{s zX_8-m?fJy7b=Pl1CidCM@HqHsOg~R8|EFxvA^$Kl&343)r&Cv5 z4(%g%zs(=x2zura$4%wDAnXJF6CBoAT!FfxuvY@!G?m@bbgt87s^|w>vZ|PcE`0!x z3OY@BG0#jT8Hw3wK0);WI}XzuqG_k(+Qk`)xtfW5VveiJ1qN2syJf|Q3#Qc|`7lt= zTv>qh)vLB;pE0tY*j`7Brsed47v%;yJlH?fBXGrVHeH`wfSWiRjpYM$TEfo=3Mg`X zai$K*%JK_ItT`+ihH8WSTnTvmR?a}6rTz}k8QpGB#amlz>eEOqlkd!jz5BJNY6z6k z76UKy`u?$%{RT6uwj$?g5-m=%F)z@vD0lvzZQwwrl>(Q~%PP}0o?cNF6-W4Ek8MNuCi#~umpBj%I}yJ1LSM_{W|XC?A7HPDJraPQ!GVETm&FSDuwG`JjqCp^lB_P zR6N2$veDsrU$aWt5=F&4n9IHdFZ;B?LaD=;%Y73q$a*=Am3oQhBKg=UjoTIM5#^L6 zMOD>@oC_9*l^F$(9>f@taS!cPEx_!k0gdCLr*(^?RyPLAYv?b>;9Es2dCnf$oMc%#K9g*HqC-6(JX&(ysM+ah*cM}MP;woCk=C-hNOUu+>JxB{y*{2yD{gM+0lBqNmNI^8__}*QPhD* z^#)FEiqj*H{idxw#IoPCN0zjAPGnGE0VeH@+gHZ~Y)*k-IW0hY0VRZwN%b9>03&E%#!J=1*Gfik!f&122?pG1HD~Ur;-kajk zoEvkFs#GFesi+GCtB6NmhgrR@_Ghz(mY?0+6X@lulY*fE%{s~!aS*A;T_kO@aR*ZC za+qxoS}{7`H;x^g#xH3q4^u^N!*PJOUxn#@s4PvS2dworHgsI9WtG&%e}gwwxAJ>h zrKrfymDxFXGThhY>!-ah?bc}=>`G`_ZB%NWDTG>MH>9}w<~v!`WxH0R5jF}MY6(^O zEnLfAs4qH+>;4vtEV?fSy8NbQBdbw;LU?seIvoX7OnHzOY@B>x%lcY9dHwR(e0rh2 zB)?SJueU-auw}(f17)KoxnxFa$ymlp-7jD;m!wo+Y0!v~^K}kFdsYE+o(-+}nc}+& z1i{O(dwk&U2OO)Fhqi@{&aSqqxG(jG2mp_$w3mto4X1hHEcyD&_O;Z7z200zK9Y~e zbYH~)W$y%}ax+1xbXMGs2^2UI-GSp;+m5%Cf&% z>F`N*OGR?4?*_??E~LJ%{K&v8Uvg5g8NY>=k(?C*P6ws(S)nD9#|Pa5pliwl!HAK9 z;q4>ZvdK-x?@|^|7#?LQ5Xg&!8zV$9&o+tRczY>XDOkiLcNx1QXBWB?nIQ8V%&pI$ z4qBATj7C%Wb&*UatPlh`D$v;3`8Yss!I);ffv2nJp77Pnd|dB)+jt9QwE6bs#W&bP zTFp;{?$*D+$CuEt0(w>!p3%IzQY4W2eIZIV3&{^T&vauq;ahjsnZDLeKtxEXWOv#o znesb!%kYRnvjySVgv*hMc$TpUFNf6(h!auFb2*DgMZ(7D2K0=)HbOvt7qckATTXpY zESO*=jG;vzzO?JOO(;%S@D@@vTJj}EC&oA#k6EFonwEcbT(ZK9dwnp?Fn0}T&GH>( z3F+ZIwp4hH>GKC6XVKl1le`QG7wYWA?=qsUzfaE3YVKch@X$q5Fl+!84WcXo z%^mJ(fyGU{g1JkCIfcnS;kT@~E0Pkg!W`<*Y?oZk7@Q?x)uL4mnjn`z~9OdJ%1eL#bypr|fi+Vd%`PCY! z!sl8VXjRbs#^0{GyisCCp@YGqnN0qF_TK%uZCpthJwNBKz*TZ;;;B%U9Y1osH&xeh zJTv|#alE!?&-dNky;+EaBpg!&2LSD8lKJ0n;Y9)@_>yJCnTS<0u}GlNcy%`#{h&z5 zDu7cc_vl0%<;B)1w7Zyr7~P`ST<8sAayNJZ26GhQY(9`?zk@magy-3OpiD<*csfJs z218bTq5ove057g84J}{@B>*QmdL-j%CU>lU6BulBwheC znTYqsKf#L@GyK$yuoz%9qBWz@+fKk5F|Un4)38lqIAtJ09ML&WkXAljpIqoK^7jkL za&xu(1XIQV84DUNp}YXfv&b}HkE-!Vl7`1nD^eeR3?=q;>*^=jHF>L2;q$VX$M4YG z?P)&~wZ7y`fajy(DA*Z}{#)LB6AojbI5(K1IiU-IxfmX?up$Ll$xrwXY3?)0ZwpVZ zUx0)pf%*IV_*$Mm_05`*5=5s36`8{{&;SF5|3HDnr`l^zcWP)@g4+B5vp`J0FGs`C zw>B0nJ-Rm=nGwd{p(zX(mn7pjnU*+;_#VWvKtNTA${bZ-G|f=iu3z6*7$%VbA=DVh z0C@+iNVYQekRMP4(m0!9xw|N0DM=U>2OcpoSrQ={FKp@X7W0J?JsB~q2Z=clhy&d# zd5IOt6TlszH!tLT#fSsU!9<9;LW~3Y_E-%_UR7Y(GGy&Sx){lXMCd(~epPxv#2dLj z=I~SQD5e&zW^^FQ=3_*~@K=j*2?8m^iocVII#y*&A;6Hi@DuYZ6%7^wYQe%p?GpjS z0Fb~0-SWXWuwfMJ?QG(f7ALhiiKLgJ+>ePlp(|6WPrP(g&lxT^Q3=ST)3I#`jv0Vr zTT6=ziqd$Y4%|vy%PUZlrrHopZb<^8z<0uvA`#lz~#w{htIOk%uVd zw<+aOak|x=+!^jlgDd6y`9hF|IZp5#|B?3u>vO&}Oxg!j%zlWNmTKK~$3wMgH~~8< z^vKXGVrK=*MeD7qxQ1P}acfk!f(sQUixN~_wpA4j*@Vp&qWkPStymsT%V$)Q!h%CzhIUI6H25xffS#uhKz(#V*YY) z#d*&*yVEA4(s4kY(Q{g>0V`{34a3yJ3F9!1Wqbc-c%W8`N$VJtFf0#moaFtI%s_~f z5u&+kf>D1e8Lr?Gwt<)mQ@|;aBO-9gS;gM4`1_??OeSamo+idcgIlmfkug#x%wp-1 zY&sKSsCAYsVRAOHjcYOM&#R3d)<_=c6K1mWmbO-K+P>Ue89-Gy`m)?Sw~@6tdMh_K zqoaq{8b%#LK@Shi!!#&nFQ%*D@_-WwZD+VA-ij4N_3&b@+Lej~k|612VhIAwBLyfs zJ!CFj0(}l-9^zP(dN1TbK~S_3ewxLQiY+Ivc;qz*4`*spRG^6%fiosfiegEJkODES zMA-`%QHYB(6$N-Mc9FbAd;(1Qz$zce5Wca1E9C>_*8#Z2$Fu}`?0nd^I#bONfUrUXFs;kDJf>P&^ z&=@=c8lGiqG?0tJKL&QsJYcPr?T$fJePo=h^x%Y0`lm06rC*_;>f|O-Dw=#5jvXG_ zE#FORqATSI{Y(SpT!B`(Zh*DudQRRbvGr0Z#`MVLwnQY*Vr`%`XC;E(0A^s@^p{$H zfBl#JlgM17N)?xJd~&vDsiiE9AV;SsyT=hsIim0I z9P|Ic@c80PwXO;TDBKO8DiXw^OmK^#W9L(Uf)wq*JEo%#oPH9g{<8~{hUJb0RDB7M z{1o8SYf9>edaAAX&;);ai(>1pNx?QQB(gvdm{&)%}1a4h(>TDIBJaUSN*)Y~9y5lg35raxgtNDLPl^(OC=ozi zB*pIkOtR=9N3_lQ@K9PA{%8ouz{yDINXE`I)}Q z%1^3S`2~V>1k{3f01}m@SpF?&dzfJJa}q-#D43sij4bm`fRw5^GhDwACesC*3kx}H zN+%#hdTE)XQ7#0vN>>}^sT#Q0H6zK_{T$Mp(uS{uJg&J+l(FbM#Z9cbhW7Ni-$RhS zQ>w==pHB1Yq(WZ=7tv8-PwRRASk_imGu8dy+R-8l8l?td+74#}(LYnFqwa?66F%b?_0UMco zJC)>wT1bAu%W;cHMZIGu$%ysN@9C3Dq*P+cF1PzA3F$&A1HIY+%Y5D{$rmXC1DrAx zmguK=RhozjeAkT1>k(qrk|2k3k|q2CI*Hv%MQ+gICqb>0a4KE}MO-mIMrGK4{<+;$ z&}pF@n5|oj9oq7>Qi;%3i(^67^}NXM#qw+(ic)Q>k2P&B+nTqXN-s;g(lWYWaDx{A zltD$PXC2DPxKp2-yIp`OCqL{t`Zs8CseQDJNnv?)P~-j;=>lCX5<4~4gno&1*Y4{( zOwlxhG;+r@f8Aq$H;-8kQJyHI>(5Uxj-^49x8)!&7ff`)I%Jw)FFVHt%))8oSA(G#_ekp68lgOMHFlvZzq{r(M z4^%|vy1gJu{qO55S;n{a3nR4WUd_Z-@!nE_T5qkJ3mt;nf9l+_6h^TS_Jbl~B~GQ4 z2@7Zz%j3B%{TIx&OI63&QkFj_C#Lk7E_^A<)`Wwpkp@jWmoSOQ{HH9A%|XAwKz<4) z;#DXZh5G=QD)vaGvQXdjwib8Ik$J}uhW!}mnVzEl0 znzcv50)sJ3qB|V%*?So{*74BH&m5&PULuhf3RDPMcQ4n1@EyO#(hBH5@6NLgMN(DHT#T-m(Vf1y04PktV)RbOG&6CT~)!Ccs5_wQ3$N97Z zqN8F?9IVgfEv3E!l-dZrZg2Mjb%SZ_kgH_5wtjP)2lZ_pbZOIHzr$dclU6Q!}C|mJ|JToYCz0efBzswTBGv3Oo zZxL6PO3r9fRU}a0gUA%}Di&1CVQrB^i?kX_*W*pN;o%$|GK(k_{f+5pet!gGoJ7t& zLvFoLjGC_<747ejH#mu83NVeLe?W_b85Lbp@kuM4BiCe7d{!f43byQ#TJU1|6H6*u1!UB?L@uX<9QoB3LEANk)*4__F!X^5>LmHU+LQVn~dz)8G6AS_!MzYE1 z6%33$>)8ccLuYd9SzL;{W1(^HE+v}etf4+%FINTwX~w2kc-~MT-^%8u zh}YLzu1O{RXpumX%RHvN6r7Aep~$4a*B&5CqNB!7(J4E?zS$ZooT&_~FQ=kyCM-yP zYWKOtc+S_b6Wau*UVF6eJ$z@yK*?>-J2l&>+b($jAlR!-@|Kj6oE!RD5rr=DGTsx2 zJaK6_fp0NafQlL#sQ7&;Z901_qxv{Gg~V@#n_(O#5sXQq@s1#eDdZ;jYCM)4rG4?* zK*3;MgmpE}3S~u)gT>q*z_n|0dB7aE%?{Cax`f(kZ9NQ8jEpYVLBRUbfP+=)9%w|2 zzQrtsJe;{$M2rTJ{!)*HRs9}FXcN9`l9HHAONUWo2*~xrr{Z6vny1V40XHWW55uKe9fAgod`BlHu%TJ zQ^*~4`7JPRL{4Mnik(cx*lnopStW5&Y{hBuHq;lkiqLsd!1zG)RDJB8BRrkG#VjPZ zh%N>VOSDw9EUz0~$*%T*i%daxftH}ONI3vNnhKGDq6tN8)-!5TM1STxlE;sNTO<_-HnQiFsRjD6!BCm-KnYOpy*cjcCZA- z+tU)5N|#G8dh|Ue(<>SNLC7ttv6xH)6%s;11q9fWf5G83E&)|B}I zIB76{^zXZyR}2iarP0~N?VdJRGN=1jEYKg79xEkLRbhAYiVdqE?t{ibBN_)?&^YLX zMxl#Q_K7O-OIfhiwu>rFgKX2-W(hLo)YPdQ%=aU0YxqK^MtETb+Ga1rj7m+@HZU0z zhtj!Rx{uFg`a?ar8AAX99l!Cvw8yRn`d@=VT}L!Jjbq?ie5mUBPQm}Wn}w%y3FfWd z8LOLD>>TksLT|M4yY7P*GqHLSRm!7VuLaR*-N<-kCS<>Al_D5f(aXxg%SbZ$3CHMt zjRlGWQ0$PJHj5Z&Mh~h&iX4I4o#D<)?IbGG^yswIZnYy71W{U?I&D4yKn7>ayAa&X zP!h;2JC)wd2;&0UTTGn}jrO%IuY?<8#w%))k~NEfCfYbju#W83I+Ug2{w4I>4kzyp z!Itx0-&LB?yhd?sB{tzCkMbnJs`z!VCO+OnjiIu=m3e$v*^WVaZJ95nj9>{41n;O= zM2R{vnMymS&dWVZoS_oH^H&w1unFZzhAcfpLG?wbL(%I(~N^PlSa8g8B-vZB#wzAd? zdaLHUvOy@vd)G|ERv%RYBE<}qOsjRCAyfQ?a$j`9LRkqMWbQI;cS4`A4_kh+H#qgzrgmav&*6n$mRno(87GYk^ zi3G*#stT=Cr-RFgz9BQ2F^*Gwh3GAk*I>$+KyZwsf9$^88Se-yC` zX422b##RQHR&kz9=tmWXbC`#mD5sivk;h3HTTK)ZDV#J(8s_f;Jz3Bi3)xU0KUI}x zW(u6n^*XLO=yl}oUFU$z(9&w`b-O8~^xEYc%>Z)`QY9O`vyN!2~Vsw3z zH>tF+jptjDVMxzsDaFvy;plKQ*c#@!uJr2com)uv+hhV$U`qLBN+?^YX7c<|pqf9* zV4QpY48avb;6F$IE!Qc$g*b-g6jDykx+&(fY&;CfT<1>TR+wy$V=~^JL&g!^eoMk^ zjuK@9y=`F4qe|b7JjtY*CIf)apNBObC>kQ)duK;=?xb#;VzSC@sZTm+lh}T;&~KOTWTNT? zNFn6_CtwnjyK3{IaFEehmh}y*)$%Z-@xM!$C0gE$O2!ZcIGK<(EEuAqSSuC`(K7+A z-htdxYldKiDC<>N84H_UUaHv?M;zHN15t*Ij)>goGVG2HP_52!o{s8@%96QZr?g;H zWL;}COy~eKLdl|2FMD-QK<(MP0+BAA>)GWSIJtqXOZHb;>iFUe+@QA2BOwY|>;^UM z9a(G$Q!E&3Cwr2{?g(CGf`%AQDqqQCe=vuiRP5mS*vm_0(V-~%9)1$?!27YgpKD-_ zVR)0JUefEre4`4sZ%fIBX*p$(~0N`N@V0 zIFI|7Pvv5#lK!=zmJ6K634l?A#kPg9Ne|L;e8`2lz1_XN!ImYCsUqHcCp{nz7VYbr z$ILruCfhrYtuuB0mB%aykzVabVEY!*?HG@ZG{$3QBr?^zVMw`KyYPilxYQm%86wZ(G4CO&eNL=w! zl0`m$2G7J_ogF3MTqox~ClUHhMt8c*^C5}PPIwX>{)x(rJROt#*EZ1-rXT&TyW)0x z%QI?D-Y?r5u|!EFE_q5+1NVZExOxe!U~K;goJvD~9i3B4hB&?58Sd=8Fj=;g!UN)% z!3hG8k}Qd2kwfs~HVCYyWbC?u#I#qNFXSz0ml~1}iWQHbF)(q?nD#iUi*JvYO2=mE zM1*P^Ling^YZ@C8LP)#z##$W*_g)SYmY? zbXXlF7Fm#*c@}eQ5gIiH&%_G`j$SLilD}7HIr;Skc*ar`iZXsAVaAC}Z;Vt-p$ih7 zU0g`G)-*qZoYPWE<@Kr>8i>s^@YH<`V48{!>fd=d%zQ_)qrbBOc%I9{5}+cY^0Q(5 zJ-`;zBtdg>#bsvc{Zmfo>)qv0H<;-+m2f=2Bx_lB0|23&0X&C#hHu^`6i=`%gv^2 zwPY+vDK@|q2V?QIVdK_A>qyv}fc^W$l^3bs%L%4ip>&J}mtrB-$Xa?*QY=L!6(ZC1 zWwr}Qu+-_u*Sk@KB4M4_b$t z*;|fM_u5^&aoQ0t>TJ8JQzS|kwtX73cMkVqNirL(e8_= zjYDlSWSl#cziuT~{>`gAzH{DG4_9$*SqI~o`QFtS5O5*Rhw@^9kQ=41)5&LL61J3* zDTQ-8!?ei|E168guW$Bq3R%94hN@eYXpoVvb*e^QGjK;0IobU1*PtI^;NA z*sdR);ng7axe~*mfS8i#xPGM-t4YYLO)IJvj)RjAP)%4k56B`sTz4Wco)%p8dBp%% zd^N}nZ7-!|sX8zh^1fCAy!rV;X4cUSz5wHlgM_%76x<<-OpzhDkh5qap^^mU zruOb+4|;aCLl+hH<7t{tNDz<9{;^Hg8DV@|{OpnuUgi;_gmBB(QT%kr zGo1{@%YK52x(89=CoYQ?^z}%k5%qp(N_S+_0=3&1CT|ugWUT$t1AR(k9AX|X@{HG_ zI>6Bnf_aO-Wk}qygjX2_tEtxO3%~fN#A$HtCl252#4GlBWp#8 zewo`a*TwjGmEX;lwKzAg*opj-t5t@-OS=nWIBHCSe>DXy%}(xKpn+HQRvz%OP*VeM zbb*R}x6QJ0#S=p^tlc$~Y2_TLATOhI`bDuVeMOLq1}AbPfy|QUhx{IXQbync2~oBd zICu?oCOB(GgQ{Yr9)R{{5^tSbL@qzqX^yskly<)|O|vQ~T62d7Gn>enJwzy|;GnID z^=-=MidTVul%%FsJAHbFcK|SrmrR6+^c#qNYO@zioJNPM|$O>%Cf=u#$ zWjoR(TzB3;mS`V~3lizr#Y2i@;zZR>UO>uKIt;R3QP&96)VM+d(W=Ti7iZcU9E=)! zCa9WJAv9bM=4CW_zosx@DWoW|{UV;`3p3A@IYpd-l%fztC<&3Gwn`bHSpzRXRedQ; zyF+iYp3|5WAip^ghoM}ONyx5o0xVp#M^PfP_B(DytZOF>QG9!TB|CB2u@8xRQ`=(1 zk`IxNEQXUQqFV1|j!!wd+F>G=g}jkVo4~c>T7eQJ>=OM8h1_HfJINUzCzIa=>lOb| zStd_F7KF76!4I$%v6l7xHen}ZZjxpWTm z_eXLLKfOg0L@A02kZ)0p@(Uh=rx?OW7q#(?RAE1=jo_ES7AMy{F5!iffb+PfeN~}< zODRPsFr1avQ%X@#4T@W>v`l;C)51z|m^UbhQYAu%r`nQD8Y1ytOjHaPzUFhHqn1Ei z3aHuwunw^f2N~&Seopu$g3&_CLBAs7OeMbs3E|3xTnR!!*}U8fp+3;`9I;sdGd?Sv zP23REGn8{cn%`=|Cc*s&*PCZwkrpi=YfILN%1+ugfDs38nv*qYEHb{w*N?4->gAM>y zKV+pVuY08jX-!W1-r@NX(7%%6=Zw|8Vz5wAUXcgTJbwNrZo`}MG6>)K#p zm@7{I{By`|!=qQDS383;?X1DTVt+mnv8nl@s&kE7S#*)$Yke1;sMNmbSc)eTA(Cf| z2g#A=8^={#`wgKP9bb-3N&2tnrpak=z==TgU&ZHn(tOO6(Is9~~3tu2w z$WC>TZGlYFiGV3&{Ln3NOqXxKUCO9>3>v_SVtODNfIa~rj|w8|d9q0=cpeU0RVj;t zF_{k2JQRom8k4C9WL~nLB462%%Cz%?V(?IOq7%?-p~RXAAtdXMu9Ck1HS|HML+mLy z{lqEMk#&^no=NAPWC|c1V@@Gmi1|tpm04Px%!<0+@X1r~W&zSnDIYKgkjqk{8SU41 zV!|H10GR*40E`&{smXWG2_UzKQXCV6eJSXC-@+UnnBxCHRGn6Dcb?qfBswYv;K>|u7(ot?o&ccEj7}Ci z{nomE(|N0h`9+&(#6VEZ9)T|cc@vnf0lzOm55-<-DE_v2R`wX5Ei_MK$PwGlub*zo zVq49`9H!DSZ`n3RqtWPKZ%_U^8jZ^T?uS@Ii4F_pMqZzN+n~sLE4HAGB75DGfrWuF(3X*5Hn5y zyd^jSV~U`R-xSVZGL;%(Z;d1HB}eNyPh;?W_!Ev18~%(q7)bxhnhm*KfhTt8U<(Yl zz!xx~WG*{t1prMp)O7Pyo@V+VK{O``L;L~h|L)7t&R&K7?;dRE|2m!rq5m*V*>=tZ z-pWOEg?I}Sctq46fEbQZtgGF;VgXFk3bsIWR7O^$3F1PCCEF>aJRlQOwx*P~^WHIG zDGHC|<#dcfPN>32hF5uKp;(V(&0r~KtzS{*dtt66H>S;&}>C!ZM0LDn5upI?|)zjJg|znSu_PipjP|&?UT@YA*qcoaLz~&3 zQ=OstEutr6o@Xk%%{#I zt~=Fi9tB1G?l}O4xO$tyb2vp8SsY&}vvT@Y6;o%9S)^Bnk>Ss7|xr9_tRwFGh+ldq(pX|KuU=iZSS7AL+8 z%35jh(#M7JWqeT$fp1kErg;&&c1Y%Pm_$X#1F)Sjx;@5;%V(wK8=}STr&DIv`XLBa z2qBu8n%j!8dXLOMI8}o&WGKK982wP@h0-!HzobXwY-**%E}Q#^&tPzi=$Oc?d8LZ_ zgQ^Gy61@R<4pIX|sBV9Qy@66u&sgBabS7;p+hF2bO8oCyNAQka5UT*fWgtx z&cH_@#G?bY>FllUr?QEG8Uj_cFy<*97S50$YrkAyUsxX|5XTus*E5RPjKq-#racD3 za(TBIWjc0MdrRklatga}SQdteF$=35>nlz$$1s*QK6zXFd4U+;q69Ja*PXPsVRlAf z`El;BHr$q)7YBFlsqGn~2uAq(o-%g`9(2x1O)WcVD7m#o2_-cB`s(WA`G>csAJ329 zpITt#k@6=>=I%^Nx%m=Jj!Iq$r3(%BqpWlxr%Z;oNl1jw;T%(i@`SErZ%advY0@s|%* z*X2%>J%Vhgy;LAo80972fZ4@|%dVJJ%|;tBtK;>j$?fV`eN96Ysl1HNF3exri=?^v zol&{WtW7SshI?{JcR(#Zo| z+EcSK%ec58%6zHjY`nAUD_9yO;6%rFk%LjR6t*@*RirD%dz~-_AfhBK6Y&5Xzk64n z47Y0TluMHLh%s?a*Jt#fU>uKOcymqOktzF-oKi}Pv-K^Bv$;wnSG(PmQKh}z<|fD3 zQO!ZTT1D{h4@tZ@Qf`nnO+m`>1cv<@^HnOEa~87OT5dzoxvBORK3AR1VaACZVIQG0 z7>(0OFo$Vf$Jv5yPuTW2om2`?lESHu)*_haH90ZVu#IxN(eo`HCE$pb)xz-MD@b7B zKjcAK6qsAN=)6NG3YlMS88eRMKKk0TN1$l7uFk#G>2h@b!`d|W)~I_awz2TjT0XaQ z*&5JWqiFu1L6NB4Obx9#j_=^YEWwmwB57X?nGA&C)gU^h2H?4jn((Z`_DZ0@K&QBs zKDi;q9EUIu5(*@1kuukD7>Z#&FZ-XlpG`Ye$20MW{U?{il~d`O+@Pcb(7bv9(W17N zH(C8Tsj++kRtOl{&DfzT-X)TU4k+s9uRJJtig(p&Lnqs~98r^EyvNe-+L~AqSNiU{ zC~Uudh*miW z*k|HJijKfrOyw9ZK2Q}t*NaS*quvjl9Nw}Bl{j^tXx2uj$w<&VPeDRBI+7P+vD7F` z!5@ecFh?+9>gqVj=3_(wW&kIEgdE0zqLd{L{RGyj#Dw#M312)Z;5ko3DPk#(ceAq$L?j^~#1&E#vK5 z7dmIjFEvs{tK_h;1pTg`X8TW*zVklTpRM-)yQ964YyY`(xWBRgU(a)I`_Gl=3BAq( zTE1VU)u;+@^t@_iXQ8Fn{Cky4wc62c#-_FQe61}RDs2_SWSfN)rgjj-a)HVv(fw4J z&G8hvSl{+Cw_S)LH*+&gbRwQ@*_<4`-1=5~EuLK*fpe8AT(R{N^S)xCTZeb9 z39r|IuXrYl?;kls0%H&wv4+;H%{5cD=R0$3g~w1muqTsQv7Q_o#_8u zOQ;V+|91~xR_OoE?uP!a<#`0>za`E`Wrst(Kyfl1hJ+%*h9Q}6m)VR4)cZi$5x=~a zEt=P`ANz>2Vkg2nXNFq5W5<=IH+OKkXj^073P0`Bk9%|0dpmjNOYf=*L9RUYJ7|)K zOz2O2I!!(2LU~U1CKPKKE$j)4r&R6-+I->9r*rh zM0Mb@ib>_e68Naod$BwMvpD+6X?6VHP0)V72rw=Df3#mY|BYV09BugjIvx-IZ%*#t zTuR?!s$*Xs{l&+!JH?2pW>2qa&%ij(@AUdarqYX@$u(|bvWS=Oh}fGwu;550#n8L> z8;D?4xBpF=MwsFtj3HwWxc~QFj>`LgcV{F2ujMHjBk5^BzBtP_yq(p;@!UPWIMchC z4S#_Q40PpTqKuw|G=B3+imJCe+d7@6HY_VCgqmtAe5@TWQ$Nu@$gpT_wE)c2{v$*{qIvL~G9s3ibN0 zu2nm#$=c!d3t`p^T$BBUp@bFVgc;|lWs~q~RAWkzkO)FV*qiS)#h`MnC~PPy8-Ifb*@jmZVS(YbK6K2swIZ zwPl8knP4D|g*tYo5k`H-`i+vwu>U&u$cMFG)1nF@3_%gAm1~NS#edS3>l@ zEs~dwnGD?(0G&?*Y08JwBQV(c$L`SjZ{QL~MVJ2ZkAM8*aVm9sJazJ)AgwsTd=(*J zo8`Zqot@EPS^nEQ+~|MS@|5)P+|vAwZ8>{vIBWt z4hCjE%TNb3-@LD70M{{OGk>Mf`}&LLtzJz2q$c_CBBh9Nk`6_SI&^xT0c%tqQx6*` z#ei$t5Wa9-{UT=7VDJ=NT_0aw|90{5>g4k5;u>JdGXV=JPC1}i0!X5A_UHcILvT(a zH<~O$J=V#h7AYC zHHACL8@xxvlOEAW>f2vO>=PNv;Owmv)}}7p%}N3f6;e(A*h3{wUiOsnsXWZS>lL)9 zSOKezTU0FNYUrXK>%t!^q7=nu6FTBMds_9sD{ujAx&PnU+1)Su|Lniq+vtDS@p$Zi zD+IAKg@)iytHrV3R~N7gKzw)qyHoo@*<(zA7>~| z5oJT3E^7eRX8$#++JEgF?r-S-Iv%lWBQ(KDA&Q%+ABHi>qCsu|{!IP`N3X$PiV{R| zIB<-^bFV1u7>#NjsH*%L4B#Cr>X~FWrZW5^qo}#MDA52Q#$z~!vUoEbtDprgiOT&g ze|pk1WKz}m7EckA=LKuWRtk9R1An7?$ z(6+#!&t%!it^-$i$2@p;UL0#jS0K^_;g-d?cDyZoeCXSY-^R_e1-5^Da*23G6MYW` zOjAlF|3u!&my-A(+*wLG5le@;W%&i@6q^q%VJ7=}Zb@fo4`4|&S0cnazGd6y(^ z2=i!~@tHp5C_JQHSc{rOTv1Carz~z%8O<{bq`|{5Qr- z{c#6*I5Rxa&GQHb5oTgejD_*Z<=X)$IH+v^RV`^1eD0m^ESbXuPEmA0qJIi35FP3u z(BOH3JOYZZhKcoH;^BV*IN=9-TVMpXfL6;t1)L~_IF#!8cmX05BaXm-hJ>OoV!;19 zN|;LW%?RK#$N{8CB}2r?Q~($wbu;-CXe_{Z0ZxqdPM|?P@#`o`f4YjFyo1W-B8EqT_^ zgLSbBnstI*rAfUgu5%+Fd0EcoN2{~d4t2&=gJ*~X{q46Tw`Nn~G$4t|wOO>e%_N8? z4t=nOJS~rOWl$o_LLrYXH1(^_WFC1X#$kC%Ysf=~6(aXois*#UIe7O5oLv~V4NMXl z$ov>-t1eE=#)z_{~%dGmMtN@QF2uYHlkmFm-7rD2ORKGIM@~n46Yj9OJ zend>!x7AMCiUyU>5a1LhELLMmCIEty^9x0-v|SVf|8q?w(Eky2F=xemJEQL|g+5H; zzQd+REi~cwok`b3wA)(GJ@TrHTz%4pCMk(=h;^UU7cFPr;Rsa=l+3|}uCJy;S`q%h)l{$_T6-Ld;S06xtfU>Ph_dWabVb_PqEh45 zQ1w}BeTS~ttnDM{+1O9PZ$)>S2UArZmina!tbae;)vw+Ol)1F4baA{cHro`^F`Ob$ z%!?R)mW8vTneu|Y_n0@}#TH38qa?w9pzgRWJ!l?g?_a#ll%k_pB3dg%5_9q6OotM) z1gkCgUJB|y;cLlWH*uwVtiCv>x#q(yStz4U`}KI5rU+5*2N>NV$}vN8{9 zm6n}0F9EJ}8m1V1;wVv}Sn8w;Ox{|Jywx17*DVfKwGou?57>%`C zCQegAVm7qry)<<=nHoA+S4>k*Jzq`0T8g+UqOO#+Hrk6ARi?kFMf2?i+*Y>4AH2np zlq9sc&|K2&sphY8$JG>RL0v2_n!s2fEvDaJs-V{1&qDT%DT-u*p~en%86HWSYQHqj z1CHoaZXZ9IyD&*emV|NG7@+r_B9yhjabBNB}3xn zLy96l1wRp5R#yRY5e{tv>fZW1K{y z&wa0f+U!3^2W9)8-Mzg{{MWTSkLLd8jappa@HG&L(IuLQ;)ZNAjKLECs#jojJ!Y9= zqeo8y;5C%(U>;i>?w2x;-B@@2HJ?`cA3-)76G$VrbS&@|`oFtdvH#ya*g4qH|8+cd z_h`km+cKUsg;GHwj$Q-fpBa;}anP(^J=;IZ+{XEJwMyOlEQNgbLcu&y;j<-Z-H2&2 z2O~Ycj$Q+brs&fpN@EzJ<2VL`=l|dE$L+1>!ymW)>%U|}&jt!O7(DyD`{$rBU{^~B z@>26(0H;|Jf`gaZY3@qdU=4zSkDfkj8e3n^kY`iB;{vMm$uO~-`G*GH$L+mi9$9{zw=%Kz&y%lop?u8i5lb$SY} z5CRbi86b%~>mlj{AMz+>aROvmu=HlSee;TK>!3{L-{F))KZnccH)K@iRtx@Zm#<6}Rp8}MyjG{s-uJxBB0SqV8Seu01ykbU)%wB-;LPt2E zB#y88vR`iQV1E64U!2U2{N6R8jwV)y``y=itQ7DOQe+>Oh?cg zs>*zZ=pAMVz{IpV$I}@HQ^Wz|S$G4YOopxEGn9*VC7kv(N@PCPdTxa}pD7e&pgfL` zO$ZAUmkr%YIk_Os(iA1v`WH6~X6lGizcay{6L}Gl%RQps&(ZH5kv}7i)X@m7@LyEpuKU_pj^|IP~q1rbvG!uQz|BzeIxJ-w z%IBC)o0f8YG$$`1aiZv%sr>cT)yMM>Z%;p-AHP4fqjw2>exhXVh9Z-ZJoOcb{giZW z?nhbaLT3CFJ4@Ogiqk*^89hi6r{njhR~N@8Yrx5H-9l4WhnSqbc7*a&g}?s)+}ti|{|3Vn|&G4_ky*a%+KfOK`JLK{|&Q4B0{_^3fG87JnFG1~fB&fnD z(*Lw#cJbk|D`popvVDiW;RLp5E61|2iu#I4a`x7{hyLH+E>AyR{q{x$T|N77?%6#~ zFWMk??E^;%On4Jk*Qe*l=hxlv@j>f~iLu9$h8XqeT%KNi`0euK^yAN$AAY;&fKx48 z4`OapC-2Tqy*3iWjNhUdF0>2!5jYsxLxL!lr)2eQ$Nt9g9FdIYA7AF*D1s6G%MMV(`0RHY9sni~ z#~DS}Gm6-Z#F1UoAMQEu9clv6Q46dLc&pB0EhlOd-SD&K*#z7Hz<-Ey+q%sLIAV&%e~^dhit`s^ep! zYYS7g(E4I+%L5sop@d`Q`97RyJcIF&rPwcX8N6kI08UZD14hCd#B0%yFzwWu1a>81 z-M4?re9F%jg@`QRR|BsHmYrykWUyvV@}G5hibCd>TgJ?Q0zpX%r|Npk(_Zn_Znmz@ zQj2svO`B$VJWYG-cTIrC(~gv|GXEa3jlVT-@&j+`gJ#8|8=Ait3JpmQ8d4tI z6P@Lf9n=N4_bJzG`t54h#Fyf{Xerp9g0mzKVk3%4H?SARRcxLy4#o(`SS2zO5+m`g z^4))XekGSNAd?)JcrT&oODz2%N|@=ZwmSa_Q^x;^`Ro_fKdV>eScZkQnt@WFZvplR zsGb^?iP3R}44C6s`~HAcWe~8$<+=<4+OWWzM4)FbfCg)OaGzWNg&mAP7eI~COeF_~ zTyWak@I}RQQQij2MJJZ;7)enw$^`keED3T@(lP_;JaKn8jzJhhHdDwT7|xWrgvk!q znt$UyX)y9WbCQynOcz(Fpv@;FVVqjQh9oJdD{|yvwa>!*yR>~Szy#8kRiST}vU{LA zQXFml>h2=l*nFG2UQ{SL3bL4ZU;^q}ITwU1~Xlpj(Bu=#j+8s=| z@!-CGcjcR)@|jTmwmYldoZItLbDI3Rv*f*}=tiJAoMM~KurqzivPUiLbD&k$XFuT> zeV`}CWxW>LWe$8z$Gv9s%~$`i&V0RIq{!DN8$z{A@7eJl-`Wmu4fLj{(h-4P8iWq| zgT}F6i84XW!&@2ZgwREo1=e~fZFd>jq>1|Go>u>lltd9`G?R38oJCXA+YzMA|9@|^ zQ}O@Yj&>{ge@2`5Z|iwB{9n=F&f(|2M=@Zz$aYO3?JA>K zgt(IzE&d>P_X~5^JJ8+tD2sI82j7!O@&Fs4JbarNkDKQ!JgxGdTA%mQ0JX?}qr=_3 za{Q;!%iWFqw~nXI`K6@JZ*o@ihE!Bh4(i#6@eq1M+Ie+n`XPnCXDAPDSMsA$H?%sM z&tOm*lrY9f`m22b`@7}+zdPFO z|Ft~J-TzfRWr}z8)&2dFJD&lfBOfU z{NHPNR;l7BWW~B*Grl-8nvQ~JAHmUUnV`4b`N5*v19ZcNa1Q?<3A|&&kj$mZI)K#5 zY*=bfQ$?E&cj z%bmkfnf@Q_Z0P@5p06wa+oV^oFq}+0ePvi2T^A(o?iO5wyF+kycS*3|7M#I?yAvD& z1osehg1ZwmxLa_C>7Dm`cK3hx)6;jl`&QMdQzwe1IGWkmoNOVODp4(t0DP^iD=+(tHEStxQ7>29Pgqvi1VW+~RR(&Geg~%KrG{-0HyE`i zuNCS6_fOcTsxv_kDU}92QMoA*n(Hrpt_li5jpXLG_spr}Fidj3s;7EcGH=R6DJMfV zggIkT44T@9=hkls|4vw{okWXXIC+8%=smc>&+5KdHf17XlQ(V}`L9{pd@)yEL+1#| zD(^#0_P}rJZ(~m&p9?oSpmvuiU-ocP0-*lwh<_OQ{)19fsv4^Ll zWfW}b=XUh$)k&1;V(zn;E%F4bZ6VtKI3%2J7i2V~W0bcOF4bI(oW* zXfh7tvZpke8l40?47vBm1MKnc2*T>+zia%Z9AXn{PDWtpP^EFV5V)|2@k}$_D8fY% zba#k8@L<{Qsi%jwAt+dK$pyl=^|^gN;EQ^ZE(m_YV8Fx6O<_y?P2ym2i?W5%E0mdI zvCwdmBL^i(ldSqbNc|?_6XwZDHWo0Q?Nn^%_1_f**xplV%oEVK@BI7`FBk_phL3l_ z-OsMfF#T#+`~9i!T_O(D4pq`9n{k^Xtw@IXd7fp{C#ooYV^A2DhpHu)!^B%@0 zl#j8r$C~F3zbI{F{+w+VZ0ts>?@z2Ih!FI{i!x|&SKqDG0v%V0p{{P?d?sl{L-Gt? z326u7QxSmB-~Urma8eB^K5{F;deXE(rum7rrJesmUtfufdVq@w_6c_{TO-f3m_`Owg#O4qjI?g z9R0+effLe(f6sNyMt@;AL357$;s6m=;J8uj+Tr@MdVQa47fIRNKHoA)3@AxM^eu_{ zTUx|=KT=l?Q9%ykoHGu zAUd!wDL<|+;`~xU6n--vWy%jVQ@K~-_GQYzNY@`(AnB!_IaQ)yJO9LY7sIRu8C3@F zA%koa%e&GUVEAKL;ug}kB$3xX<~fzR$s+;Igl_n1%I|hC2DwR>X@E>LC-cc&BUCYy zPAc%%;!n+)p%~IWroy9rIm-OfxbZ{)l3~0i+85h<%O%@!SeT&q(bA;VbEhy7$p#yQ z&Z31~ekS+%w3s<2C-X~U`tkYk-;4N}9GvH>o+*mhjXsF(F*?&n_7Lb5iHG)b*e7P9 zeZD!?{lYPcSF!IQg8q$Rje&84TaoW5le0o&C~uXX>;bL#?>E5;gM&OG3f3FlmnMhN zg)*4R{dAY9I7qF(PUr$XywT{j^Y1bmCdH5X$@*RQB3rE#=&Oo~3xun}#q|mgwKlevKb4Z=Vk(`^2 zq1KGU`CR@MhJ3ca@(HFS%0k}7YMotD)n}{%gh(hE`5{JdIEi?#C;*-$IN& zmWdSv9t8GuiC>xNw?<&cdq>1mDk`j_?O4dePD$aC8=W|0!s2WnF+4Jylx^j$w$xWW zdb3j~G9#wk@ZR%s)yk*)E$AMj7W*Vu<*^dH70?X9Dn+^!(u(C!kJa3YXOgmwT&S9d zi2m^w$D)rRmaFG;NLzFjAoO!iusZzij9nl#seSXOToa#ZPj647y1RT~D^tD5*1@Kl zbfE_GiuWr`hZ_SrcxG9*B5m%LlBMxqW!;3n~{FFy+NjdTrU){tF3GgHD_d zr=P`RaS6T3^YgtB_%d#ziP_X%i`8=gOCf*|0A?YKK)-Q;`8{Zm_`Et)eTvgCE=I8@ zu*Zlz1=;Po{?^y#3$s+Cg<3*_lJZ0EiK9(Z4g2`gPj#cTTE$X7sZ^wIi9)1NRGXN? zA}(wga+rPe&h1}*aDG-LTnxtDrrl3}A>yE+#CY2$tn>E2e_^&3T%tKAx$nYy+VEZ* zKTZyyf>km8Zaa{R73p1dqEIZ(-!~*5x~dY|!SS-1@xv+LhdTJ%!Ix5=CzpaRZ_{u1 zAKIQk{|sIwEn=t1-=@h5^o~GX3d{R=vVvjEtl$1+&^+hP3E%zsC>EcH=Czpkia4h% znO<<7a<%y783e#w)k6=#*C|V|Jpjy9198hQ+bwaY z@%Kub;Ax%_lwl|)xB*aRtI8Q%=XN8u$Z!K~&5uYM9!Vz0$fZ6RIsld(t z6eF-{Oj#Mra)z!qV(xZJCM&eZ5Cbpg#AUV+7NSFR**3{3%{))7{B0 z-s)1azwPl$;Yi0WD7t2-jNMh1NBcBKRLtFu{s~bN12ZgwQY>l;&bCRzsYQF_BEg`$ z3Q6FC3ZY94=( z_#b5To3V5bFh6vtbYDKv0*r0ZeL@_1ddGTdTfMV>tGm9;8l6Fgmq@55&AMm>oO^o7nH0 zD2tfo+qkwZrGJ5HM%3J7?=b7G|Q6TMxMI+*hH)S%^3 zcF+|Io{^H&Z`|CFu&Yb7`(1O#hc|tSU^;3{-aw03O^?YQDygGzX_=Yn$mGI&3P3#j z2_9AGYz4=(n%|;pqwI&9PI`FR-ptD&`+2Ks*T${6#q&O61=+j70-~(Jm%%N#2s}`{ z;vkGJja)AYQ!+;+h~{{lG`FdNutf>GL{Y(tF`irbSIY-fOWUs+1XRL=e@dw%dJ%?? zS_Ok|zMw?W>~rYC))k{A8I?_88n@`RH^Nm&A{vmE(WiZOABDOtT^?ZKX=6!r0xVUn zeCei`eIhov23xq&da*5zE`OEDWpfXF2z$JIpTG@#_v!*kKMp~o1BFYu1H^a5Y!uek{+|z4cs0oHF^Tx#4kQr(8IP)V>^+bu zFmrlqdp-F*!J8J)`*R5#b%e&N9tKq%m~RY_3Eb18!R8kWN)Sj8w?f`dg9PIb{x2Q& zvnm!$CW0mNmd3F)w8ry@<`3a~Ot>d>^5m;N{z2FGd(Z2`(4?cL5jO-RPUH+UeIEnb zkIcKU?!iA{f*EGzRTVJTep2t7emEPU+hTKs(N-2hRSHCa&YjTjCSvE7CaxPk4Q6eu zq|0$7J3Er_%ZhK3)1XPJS^a z|Bj)JNV9!{RF=?YVs%Amk-AjTguFpYPBo+uAy9AZwnYE)W$0Oh-(N8kvzqS7yN{Dz zpD?tDj$)jdtp>GR$yS|>Iz)aKAQrD;OawV5ui>rA=!3{j-eo6F`~gSmC?7;mYYq{( zVhp%%d;1*EG6_Yt>u7S7(W`hW;SD8}&PTyY6j=)zG>Z$o8A}l?CSWBhTXb`8vb#T> zA3xo#+yPI%um9Gg(soaqu@9*>LB5?ot@!+G;7EpzwaBBxmF^bYgI^EUkB2QR%!0(k zK>=6WXRpt@e>$7fTCJ)op+rwAK7G=WI>EdX)3=bl*<xKOzKHe=EsD|ZjnM4{gDXv8fVHi_*3PtNZ&7dKlaqhES8GRirre3#UKI2E> zr;q^W&>0D0{r&Z(?}^r!`-sMbR}qyvKWZSB&n9YRp&{V1@{Zr*db0LAdo_Mq?w6Sp zIorXY{GN><_ieOEO1JBXW{&n7eD7nd!xC>_%VGfbxhY?AL)YQaRij%?& zk>8Aq$`8Vo;a=fHdLJg?w>k-`?T|q0lf|8#E98ETx!v2djeia9mg*iI$26R3P2Y7W zh4~T$H0FHMRh60%+mCC@rVO3Nt{QrFy!P>CzICWt(DBsT`J(@i_85~US-x`}e85V+{Trf1PuJx%UL1La(h zXFUi_2=?Q5Z5b)j1wL~E6~wIwd{kr9bQm5O=*JA@?<9&$yJO@;bpl)3?tXR(>XZJy zd;Xb!^l3;T3At?#`wPXswCv z93Set?D#R7O|V+Z(ti4N?u>3OxiDJ15;lvfL{fnx8XLPx%Mr|2 z;|wt?r)@GiKAbMc|H9HKYRq(`sF#`dS&v*9`{eVg(7CbMB*me(wSk7h;gNB^T=P)T zuIyhr^bO^#{?y9LjvYO?qWU!K> zBdFUbTASHM>)6(N=2cPm3$+@=eo&UL5`qIzk#;&O>yqeYuIgY*qZK(vBms&Lz=dq5 zgSb%eDwOi^m;@LW`er{g$BCk8^19ToB@E1u&u;$@wzt6f)?t0~kw9-H%O znLs+mG2b8vHSamJP_+fgTfbQyUvSaM&6IZ;n!zI*wFTzFNWa@Y$bl;h&!7;;@0SY~ z?i7MMq{l^8>QU69RM!vz?YGs9=L!oL@s*F~a_PHT3xC%c_~Y%`+Bm(xVD78kHt?=R zoOnXKv943g<)2iUnFVs@oq6@0$>~aKY^kwlq4H!<-L&FLQaQ>h6~ zb5sS1bs9E>BN+l8>qBi(p7_6}p<+3MXf7%!qXk0DDJ}37#^4uTDv^6Ii@+DBk-^u6 zSc@w<7*3NwlgT1*K}qRy4XWQi4uXJ+5V-b9UTk`2_n58@#qn+LlLQ=W)Thnrv6aMwkwr_{`Ar9jvHaI7%lk{yjM@y<(5g z+H63QUa9kw$CJKuBQC!m;|W@m-wsBPqHSk&*OpaoF!yf9F}YIKujj0`*OOoiH3jj; zFSueg#^$v7T^g7px=@EG{G@f-TkH|ZY;#u%l4q(m6cmx`Gce;4Nx!5sVR=tE^DT1( zO?~p+G)T;L4&M{x)8Jd`IL#qVwGP;rMUaPVKO6~hY~E4qNZ81?SayC_UHbYjtvm z2s{H#CBT{_iSxB&{r;8Eue;K>O&*&zJTYg*0CEQ(b*?wcrR^ z?|33>T64P`h{?obs9Ar|#3+F1AT9V;UkNU87D}>yn0kvY9Une!92<2M5g*~*JSm`f zcb=}P6KeWw^+mtsBVE)y(qDm^#{l2wOOSFZDCO#Y7?k2pjWV5FkzWI2@(A=of>(f- z{q2KSD3?0}qo}#f>G=Z0q}YRd*dPAYIy<|*Yx);EZm5U&#}IQ62AR%{YjtcAq0q=O z{np((kOS36F%`$-om#^f!*9>UUfLxJ8-#XfRzpCwV9z(U zvyGd$SN=F&bNcacvFstskum0v$x4wM?*AoF?J&nVLTg`s>QIj*74nw!QC&=Lqf^nf zO1DNPvhNMt$LO+P8Ozqf@z-kBQ-816O0jz_sxk6;J_4?8P9ewrt9Zu@<8OichSuxa za*I&h@8;t${=wEp1wDz*T-hU^)B#!{*l^--k=SMUK=<%9@QeO>)JgZBh%!n4?yA%M zA+-e-LRWOiBD*qh)ylf*7~=R-F1$CV6y@KBnTq2wxbw??l(EJa@&{v0Z{4k7)`>Psd z!pZmuFH@LUSGNz<@pjzeA3tK*(FRp&A$20}Y6r*b_MnPi^yf>5SON1y9<#U){2#oh zH#{jF{XN9CqahLa6SmCP$`SlFV9fI&yhG621==q7Tz?8cei6;Rfp(0z>Hr!_*WeM~ znRa%fDb4iCWUG7eUXp7!+jT7FU-_;`@9hqUy@h9(L{c@dXZ|H;bvhhhou{4@@i1Wt zVk+U;rkBv0?yqx>_AfNpzWvtt?b??P`E z(;t4$^W{6B`<@O}&!7_$f>aWhm89{G)dpmKyxC93@)vM|BPn8*p z{#-MZZDo52jO&HgZf((twHlu({~^x>{_NvYoH@W7S^CGPF;5c0mOzOSg=MRy#=t7< zdy1xiL${dWB`)|Lz7+XmKQnmPP6;A8q!f|nAjn;$2ekPZP5}+z&RL*#f8`QTe+3eZ zFE(pQK3IQGh{FUsk#sP@7^dpfhgz>ZS}^aO9Vx+dT}i&kz14tQPkE>|;T257Ak96E zAtrYqWSh55$iI#M@JGQ#KBQh`>hg_QeVVzSl7FMh8vWks&Pp1~g%(5daXuU}ttoav z{HP@9d$EE15GXzDsjo?hr!IBt5;9^X?98_j0 zO1=>21S9#e(Jl!~6J(d{p=sa~R?t$pu1<&?c5YE=7eivoq=k*ch4a z&n;-KGsZCY3XFXx3bI|kx{+uHBhc5`x1mtbS==Ns=Vo^e56vth|Er?Sc@x z3bpqZ0U57QyI<}jv?kl5@TQ?QgUl)x!BTI1{;QWh7DfEMh(;Ec;J{8}tD?FL+{z#M zx?c)Hr9_F$NGB<$O_ZJl^_VJu#Vn4GdjTC~7x##g4WAFrhv4<9x20`JB(zP)4+a8= z(R5YdH2iU62fEh{4Zk3LG0Z~?y5Q=w=F&aq3@O>l4+o<7y#Jeb9^K&VV?2 z8DqbZ3p7Sn(7jEQl(3;F@$}9Ms~V64jy}3EfY9my$Y{Fs7!=l_b+!_KN5d68OAvWN zVi6!2KubIxko^S`5pbh5KUkMljBS~ywv{MZ%y=V3Tx$Yzz(fUl>?f)S=%r@ZKDhY@+seG4(4vbiCZ76DT zI;FYJ`V|+-Wj|1CNo#G0Qcv#SOFO)3X7FDJPk7qLqE&%KyZ>n6%%?DEEJZxdz4m1S z?6`rH>jpM;0c*s*Y~0^C2G!9zvw;K=T-lbrke{yqdB6-0-x@2cDTKOrAg?;-oI%43 z*kMy{4{$Y0PVW@?{h>j?*c5}xL9}VMf8pg(OY7Cpz~dF@K%2$g&8vY1IY4!u^#p~< zj1a)TAhJ1{adL6{BdUq%yOc(lm!m{qBr6tJ!wL=>q?+ICRreGIDG~7#DJo=<{Q^e* zROdZnuTe{XO`=iMLD%{L1$Q;2WZdS`?I}eP2Wr>rBgi71P4(MyD8P z(x4}di`7i4TlRDK{xs!BZ9EM^&UnOr$$gbP^;15SJ{u-x#fAN8>6I_lbTF`$W^TnR=3|T#R`wM) ztyU?I>8N}9rl_PF#%}n{^;L{6qp3d3Q}KXBNfw>rI-X{_%Yax{qQU}kpEmcaU8r$` zcU;m}8|MN-iHAKP|N28qJ|O>M^8!GviI{-J`0fqRWE0ZiJJU2X$3n;^Tujs4*G9|1 zmPOHfD1u zG3T77uIjZ_;+%uqsybqF)RlC5U#F>7wu)k{M7UEWoUBx>rbV`k(?r*Bg8&n0P2eF- z*dV;OeU{I^`fjMR@d099c{4y*kz87-AIkkUzQ(G4)kV`S03)Wc&EA<({|@xR5|bF@ zK>a>^jq7*)d!cBiFGF?nN8Tn@-V7#07uxe_sfx9sB^KS0Qnh?kxFPtJ5{8B{b(_)G z!hxpvVHf-rq;kz5m(Po1W}=2YN|(Hba`oTL%k!Nppbb`i%EFN}rV;xunXKB885 z_>a*lZH!`Ir2q|ks}Dx>+zHxAfejQ_DL;0laj-8Ul5E+V;dZP4krdaj{-`}-S=z>}DA=)`@CrRi!tRkQhH zsfOy&Mzpj25hxVAIEjQr@m(BU@7+C3{uyPmccG@D-^M2ky}td1QY^yzE-0zr4H~j%avz&8kb9KpSz*raO5k1N zkJRikAhupY*jE#&0`&ELk~R-t>94)s>T+e||NMeYYlUkYFSMz{;Y4)6jengwqA+xk zl(H9N=D=Nnk&J5%8>+{O%3v^7un!U+t}j{OyB^S0OcgQz8Kll|=l-Mg;B$zOmWhQ! zln0)~PNm{tjiY3T>0B2A26c*4iSmAee%o1r?9H00XimqQ}l#>D!4j zB6$VSnPq8xqM?uZz7hRMQ;x558M>_9YVO2eYBu6m-;_`mc=Dd&SUahoLSkP8Rr*kJ(|@9tC}n^91w9SHi1NrC!@)92U0-zO9unYVi$ZR>C#Wrf5pul_TMy_92 z;N>icwzkbGHpU4{6#w<#A&R6WS(VXZ|0sBVq_+Lc_;aE>)7POq!B(}}-kU4l)zsQM zmMg%Wha}=Vxg|Fx*F<<(Da01KvYQuF1W%v~dwjq_Ttf<&Z{Ezo8Li|LAtg+Id`*r- zNL~EWV*v6FMp=RJyZostv+gPiMkgxkrAsKZjo<%OmJ3Imq9`3#e$JQv-5E)YJkf$$ zU4Cz!KSt&(EsaZd;~qE8P-P|QU~uDlu7f_LGNmM8 zJxt_4)OaZ7d`27t^q6!lrWKrwVS_%vlJ3x_ADxOg?8m0Q*p*Nn@FMJ`KjJ3W?#XT05&ZuR*R8~mPOwCsTf)7YE;tMwJ40KI3m zgpEei7FR(R@2GVlLDuweQiH_gDpy{(VzaR%^(e%o;YT0#;l=wx$vYh;05irgZMvz1 zs-XQ4RQ3w)Hg`<}9N9GnA=6wj)`}Hy7jCzqM)DGGJX3gLJP(0Hig{m!`*P8{XFrq_rz(4w~eioySNiaOJ? z8|LSWmglOMyLUW?(RW)-yBXoui#8l>wVeJ|vYk1bgRry&U7o_P!$ z3$HqT(dwQ2t9Rsa4QH&&%?q2EX3?%%8wopAdA|`O zDOpWQYPBp^yYSM%K^L0&{}oqf2U=I-1((qLkEo47X&Sg1$@ z$o;cPzHTYuSr)uq{2&3mACBxn{lL<-m=R!MSnM?zMZ-y!KvCb}qV*$N{$6nHeosXXPm!4mZCpxQDL{!6RlX`!4+IO-m zyUtaQkIGGnM-%~-Npm*N?lUOR!-~o|UG;QGlC!t0%ZzK@^Upo2M7vQwjk~-VDFbwZ zyI9mnSH87FQHN3S4h>>PWx<2&XoU4BH;E?tb;WnFk`MFDUzI=%^u@)9^RXO1}&GNaa4mNRq!oT;I;4vz; zvqtJl_zPkbUy+BuZCcyi!{p$7_B=A%sK$V7#SYR_naMxhyaI|+8Z5-nz*^sQR7WWV z+ywc9CGi|uyeB?Ne5|XfTgL>32z+5kSX)lq6(Gk8oZ8g^!@=B;(~a%zZ7BQPeM)@< z?JF?Zy)tFuM?MOAlpxU*N~;S^NlVe2X3ZJX`Z5Vi@QNS79zwx+l&Jj(@^ zG^ej(+28L7Ve=)B_nUs!3s>6})~t|(!13tq?y6)}TFlMsLO7Y8?wWtSUQkgu?SSj| zpCdQ`dwZq0Au<?pUO##@smg(b;b@wF@de&U;n7{`qv zn*On!$zroOQ#f{v#6zqx@A@1Z%Dh9gxB6kHStjPNYDpHqeng}w^dYtqS=F&X=O62B z>Z1@Y!YDUkG@9%Nu4D@R2Se)kV7qW4e|qL2X=-6ck(v%oDz*CdA!)hq*+~c`Dai=P z(U`OFgNhcK^7s@!GqoqEQ8WPr%(xNg^f~XT@GTCEJ)cz&P;n9nDDbZ6@$9);z3utJ zN+fazXtauk*^Y$Rk6UmN_gdDFSStlCOVmj(J-pF#XG1VjwXOu@>!_HuTuN~`#o^H_ z(EF-i$CPNJxo`Bs4nD_<)c&0MV&>C&a zRK}}LTKaLZH8|_#5?dlx+BSGbmrdD~U?t93f#Ah5PsRKY2yaZmEJnuXh2llfG!|34 zJH;Ov8oX%~3uVGTGAuj0J=%l~Pnt*<`j+^_g7J%u!x*V_9c*D7#0`k5PW~dG+X~yy z?aduyT_+q~Q!ZErwtrGX-|b3f+)=v~FSqJD#Oph0CL+P8a2Pp&(VVjUxph>AG1(+e zDxI1X9m|dSKI6x?rfRQ0uk;#eZ=0!Bh4aui=P-C1Vgd32pj)dA`*fizu*>%BD&Xb> zY8Kvo@1ef5cB9-m*t#j}L{YXH5j6#eOU^&Y>++y3WF2u$6O&&w@SKJZ_#QK!+a0ck zzt;}p$$rs4_BPfkS&+9PV3fG2Ad&0Ps5~)qjTrc3t>LJd{Z19L+5eO}O)I&bCkx@5j2nN1xyA#gklNaJ6|+eKR0S_! zTKQ5XEn4`u0gdf9pfm;o@->VF8e^cYuS4D)fN;tPkqF4LxnPJqOHdLzj&}E%Snl?T zw`Tm5D=)pn<tzGNH1HwdPpgHuIpcr| z)Rp%S>JA+?E|`u6BnKhQsd@d?T>83|C!UG^;Ou18$>FO{{K5UFOScm{fHLy&MuHLv zK1b&5+Zz?;KhQl^>=P)Ud-84iPV8dS2fY5=dt`QW{|8g(`?mmWI80InNjNzeI|d5+ zuYR7G5PcJqELFTyx+HBM4Ha#aYTMs*H@>W9w-%elyTmsHA8HZsa|WELSlJuiu67p} z&kb8yj+nnOo70l|zuc{x$Rh6SB}I7P6@^}j2GOHvpNFAWIE#I#AdZ$tDb*T55|VWd zdL&DsqN zXvL&pe0E>N^I&W}%|TB1Zjs$K9mW3cH1DATaT}40o)1Hv#^|c@gpu{^=iX3WEj`h$ z$MMGmI295^pQ7Z(7kc@P{<+y@E+$T&pKwQnv&02XOid?yqI|XUWI;3iUBS4!g)vU+qA5 z=AqInsFSwTOABQ}@EllI+aNr=U>MS4J>*03s>RNMj}R=Dp0SUx)w>+)ay6HH_{J)5 zft=V4be!G9frz#M6_YUNX9i*(13U!ezCdpr;sgPQzyUsjQj$vQBwhkp`08Kf_97}5 zP1QdU3V7^j_>x@#Oa-tLe}M6;%>d|z3$1Fiwg7@@NaH-$U{-XC5I@d|pTw5S)mi_4SwS=CK z6o!gz_v0<>Dwm7q`CRv79w@z?t2}vKpxG_2Ag{VDzr*UwK=>w09FmW*nueWIm_vj_ zuvjo4Az3e=AFTM5UW?pOvdSMno#TNHf38KKG@XI*45iCLjM>N$d-jac zSbiOOqLb#`9zQB+Y~3H~_8N!%0@Yjr4~_Cc`I@gNGUV3!bc19ps)GSPVF{OEH6!~* z!?e_v2ur*orx&{N7(NH?2h!anf2#d}RqmOvTf`*4@!Q(PVXMLPxvF|~< zC?!drBa+gauxFT>5_3Q^QIGbiN}Q-7O;|BMf2@(u>}C(k&gzjd#ei+ZruP{wMUg(Q z$S_Fr>&$MpEOV=EHXEjqz{o;en@MA3?$)pKq!n8i4CtZ>?yJlzXi`k|QTOLa0WQC%n=mjhrk^?7?H^kX1K-fT-iCe;DpDYeJTiZy8>W7tZm%O*`|%McXTmOpmX^&S zF}X+jV;`zDF4@UhFdQn`6T)hp-C$O=^j&Bk}P)JiN#!R=fo7;7(*Vi{$%Pp z3TjHFa!eNc50UY9@3fC?S0)p@Y?l9??@NHb1{Yxu^p*Wi$H1kzqW*4Oqe+Zw5ob`w zsd3re*Ox5Thr*2eb#Wq^I;ez9+Xbg2ja7~AJqy;f?&jU)`8~nXC#{eky&A6kYT_SB zjC{)UxY3yBFY3kjgER4y$ZF`A(bJ3w38+~6zOk2@cm@0m+MblcH(K`2(h48N-?rhU zl0LGH!f!{TrQpaSTK5#Xsh4WO#&^(2h1u5-C0aHtVww#^=s+76Q__>@=uxyV!pB@= zQ4DtV8$5WFr6>AXtSK6q^JsB-6X8#Gx$+LSXD646|5{#unTR22<`RmBZln;3Mh9758mS1cS3NU1O@@U!S%MoQf;tB6VjFF5k=x4qv7M%hqnm{m? z_!b!r~N*m8Y7k+*& z^@{J1eO@OcRE(Py)DoK9r<9LduDWR$(OiJjwo7%wnhE3OXUg!*M-$_;Y4-n5@a#3e zzi?e)6~J>X@th*vRCX9pyQ`+__~r`LE?e$!(6y8^Ore1ea_eSu z(xh450jyIkPVsX47~@!T!CT8r27daQr}q-otMO`P8(;L4^-U){yT0XrqVynYPEIHn zY@|KaAwnJHp2W3wP7yPtP@oIzxu3t-LQLkL*I(vs=q&rIMe4_{M*}Q=~6g&sk4Q@1&WCzDf5ahM395G-^sPt=K3K}-;ImQ!D4BR1g zX-nBOGtzWK=e;7&DVPNMPj)H$;z_kMPF<;7N1$q+myP$zP)X`f>znm!(Rg{M30FI^ z688oOr|YuFV5%oO-nI?xnWQ*$kiI`iaoyJJF8^w@XCkCs-}@&l@9!+_A=8FX&6%wy zBcv_Jwh%C>U@evAJVxMpfGDs4r~h1BJt0tMU(6wZZg>us2IGxjg{4q)M+VYG*3Be0 zD<#I24s+iPFNVl$45}u>r1(&C_Pc$XzSq57&)=DBwFIp;Rj-f&KY8zson-S9Xd)~GtzaPb z8?q9Y@q2_bF$ma4^A6rDHjTP(+>KovRI9>H8jDkV4e-S5XAkNpw*BnML$xFT{9iE!_ixWgKswzL3 zUIHKp#E!w%yk>L|u-Ad>8&oOp+<(RHUQc+lW1o(N-YW0CMs{`Q6tAV8aL0J+K5B^_ z>@2^9vED{RZcasjo|&^c2E<>34kBrVn-LG9g=|U+z265Nz5DlH=xG7}3UHXg8*#si zV?22$Efd8@<{dbMivO-qtwYYwn#{=eqLC!p!REI2*?J+C+((1^FjC7IWc9CVzAsRe z^PKGd$tD)efb{Um&tA}7#bQWx^tk*loMswiy`bz*GIMm!-K1k~er7Bu8$xuoyG2++MTYu*d-`L($@02q&#{@|vTA+tG7##^1`y=b;aDTcJjA$22bFWM69 zcHP!II6ZXMen!`p7L}QzRVw+t>Sh1xX6SV}*7~q^bp=jpmR~pNnCW|W_NX}$NRgP6 zyy?Kvn=NZbF}z7CK%DIJyg6m4F8!weg0-P`+1Uw;UhWeHi7HyB>RFr9UQ}vtJ$oy}4I#9wXG)}w?H0VYgb;Ne$9l`pgwHto4hzoZdGtFH#A?+a_Y~vuA&iwU@_hSQw(W1Xb>DbT^t+m>TMPzS=OfkQn zz_Ms2cCN2Ov?`X4y}u+C-W5E&kJR?q%iC1;;gFYbaTfPOljHeCKBtKnJWN}-rB^Xwic`8WF$HS5O+a zxg@125HeYM8D12Bx>j&YrFNyQ3k|e1j0vTnCTW6~WHuXKTundRfeUl*oBRr%CuV^7 zC{nv^eC&|J6#)AgdGKblKRn?L#GVv@pf7;4knM`Mii@WJi)AEBgnDb%qRO-&Ovi<5 z!2idrnG2LXfxLXNC7VcE0l+3Mw}X(7tC|yY@I`iSg^COR9r;4qIW?qPt6k|R=Bb2K ztWU$0_ULvW_{ef#T?jcY%H@8)DMh{Wr4F=|NQ{mE-glEheE$ys)Icl0#L^#^`|-ST z!>OZ=kXR-Hnr>%yh15qBj1J}}3(Q|J3-ljmmY0MJ$CSL2BvR8ZYEj@PLb8c{2|E}H zv$kBPX#l8lPu{m)qc*=x$=Hnl4`>u9g8Vf8|GRsK<^2Df{LgE7K4<>_Qd8YuTnw;~ zT$7{W{r?95h@_f+2YJ0j9L?LCYe;&)6vHn*R z{JBB==e@mt$^ZMPw^{$|c-FT5OCh1F;zrL_;6A6dKig3pz@6(QUR!FJ(9j8eYFy}f zO7emcq1PJ_S`Gh`MT55TXB7dVON!Nsqd_Nh-Jzfj88;{RW<=j?plgc&t$5y2v7gz5 zO4LD~;f0=B7#h50QIr}5UQ@_eS=6=4ogaEi$Th`#%kkDqsQ%N!T-%%P)?XoQebG?T zuFpelK^4wySqhAjO=% zi@`Xd5D2MG&^4~DokAUv40MfbXH)7{PU3bzc}-7p5-(1Jb-^;1l55LG$!rGijL`Qp z0^dK04lLpo;7?>?rirKWuv{}WEG)-J>=4d>IlsKUxw|>P{^k7o?&{6;t%IZo)y*;T zp7oyhyg7Pdlkj4;)9+us`Ss@R%l&*=({e*@0`Rf`M+&@9pm}O*JZzSu4Zo*j4HpiRJW+@?-S=W1(JtZ?!Bp zZp4dgMR55DppH$>stQqeRd<@-&X}BnR`wT)yIn5?(ceAjcI6(U?yAP$BIfoijLc=| zO&M&J*=5=2(sMhjP`fsftk?9+IRB^7h!Y{6>iyFo{=-4>{QvN1lmB@=&wBkovoDso zig7{hHL!}Xpw1<+b|ElC$!9(b3UQ%3T8V4H8jt*EGE9rSMPfo!T#T=b3E?z9Bm6^S zXNsnt81o0v_-=pA2$t*SeL2QMtwL;j_46mN=JmYu+nU-XXl8aTEjh@r!lPwowb>M7 zZmYQ4uQ(afce#&7 zwJ54$=6t%Wq1Cx7q@6KdQstd``q=eL(nn^<|J4NlZW90ds1*Nizqg71x|Zk9lK)SQ z5nkN{T4jLnjnCm%7Urq4u2K@i1SG@myc(i}G;s5J+*6jbiXqfN? zd2rp1#*(tjjK8ogP2~`tyr=n7L`q$xb7z!`hB*fqoRjwoM@V~mZ%>Pyh~bW7-}|N^ z!3)4vQGZ=X@7dwNXI5PK)?z;Ye`4_OCilPlh5Qfw-d=xW|69wmUj2XO{qL2>2w(aJ zbCocua%um<>|=9=@MK}KQLewdr^Nq7OgZV|5sBogB0$aM|A)o+AHDwWM*m;S^S&Ja z8z*v1B1v`Jxy~e!2@X3z7bS*1t1OL##9_Ep9iYDg!?L2Hz3Ny|jtE&AwkT(?&#~QE zZLZKdWGwVwp=%qa&@5l1)-RF_;V@*62s&=VAk@o062hlSpGGHF7bePTEk|QG3tBrX044GU|gipMyefV|%M|cLC+- z1@gK)iS)9x7Yai*x(mqz3DxKG>+3hy_KV4qfP;V&A=GD$K>fZ@3R3pJK;E<7v)%L) z^Y4kgi?JM|7fq22u-`yU2zF8q91%=tbhljFs_Lw^B~OIB8-NS7ZQH?FSAQ}8>G)iF zxrzasU>Y@t2Wp+^N>u?eKpx;uDAvGPtAvx}Lm+0=}$F64AdOdh8 z)9kTw7hB$LA9JWNFKYsX z*hukCX#1bY^fiv~h;Zah$b|9f{Ju+#{L1)!$Z(JwNRu&$dm7)}Cj$}^dG|m#9U3e* zpYVc~aZlr)bbG(J%~hhn8H2u0dZ)t%r6B6uCxqWw9{Iw(zNq$G?o#eS&WZF|F?_ab zc)x#;uHleAI4eQ@vR^pC!PHqK>ZfPG{A=nrn`ibjQ~wJvnXpJK>-T4$+4|q^Ztt)Z z|L?HBvHz~+`4ja&8}!da1_WBWsdUKugi2ukkgrK2<}zi~;osAh$mMm?g%9o)>~O~L zSL}rXejWKKUkXw!u$R0e(Kw-F1+=q+8m^3dQAKRN3TU#aSqTPb&UDitdt)Z#)x}vZ zSc7_ZsqgXR-UpGekrIp<>wC(D{FTb_kGhJptC?siGK$h8rm{U`yshCJU@{?!G*tzE2n5}n6R3t zTWQ=aRk8R59A)?W2fMisLrlYjliM*TV$8ze81-}CAt4kF&q#=;H^gUAAdb=QL9R?p zI0d1szaI8-UnQLomdNz;p7XUns@S{{g3+bf5G#i;a|8!Z*HYFMzo|JyPY5^E1hU$= zK}&*L8JwsBwgqGNncyKgVW#@KWb#^()Gelw{E1A_2OFaXfm2Q=3umsmTEt{qTmJIk zk>QZ|@)%vR8-GlKBxR6=NJw)Td}W}d>b-nbdnM-FpuIw!M$8;GA!<$L7gQ6@u5U1$ zQ4Z8MeZx<|HKCzSR~fmeGJ24cO)nQ~yTp_=)b*kSA@VM!nkpT3*DDpnNkB>Dr?4A` zu#Iu}FZ#^1|E}l;$UOhAUaxfjn>|8qUh z8rT1}8!Wa_#dlOl8jaGsxjXedBrWrFweN4mDQecg-uAEP0_eQ`-_iblasRi!w~_yA zc|OzqpYbxO-vIupH$bbQ`wZ^=*ejq8T8bAxHSAzLN7%a4ruRU>yoj#J10|2>ROOp&?Pc5US@gg*q9W^4du^XshD7gtva zBwUkS9?F&9wr$M+pKt+m9{=Af-~T+?*#Fk^e5w5ZGr0Wu*-C*Xw?A{IJAdx=&3Sm- z+~53!&m8{04*TE!-r-(R|L<+||MfgyhW#()Q(wIO&yLP8J@*Ev(I4M0ar>+O2B+7R zlep_*u^V&xfFclTs^2azBbzN}}_i#zvZ zdRqu4nRQ@9nrc7wgaGlwr|1RxZRt);yB*tB*7?6%X-ABYaAaicN_xvRSlOk|CKDFj zfoy#OPP5^u<}UMBL2Yj-p7rHl8hnzQuq-AVOU9dBhCRa)-$=#@^28rulMAHk#Q+Op z=}^_9k~pbe+N4uzp>*B#$#-@|j-oY#nspM}Th_VlV0naTv+CY z``=nFfd1uoj2jc$-~E}x|0R}Wn1oLY0Xv)j@9y@G%J)C|M;rdXj_0$9|9WFcZB_)> z&uk;`H{SrPCj@Ld=T8Cki9ujFi9_mRag25s3<;Y;Z*+*uDr%k`FLp+V*R+KU_p8Cs z%(-kDbcXgt*N3g5zoO6uhh}W~*UDBZ;;{5-kI1KI-cZ>dg-b z>%#fe4jYcM90ApChK)mCE;#M_LeqZgz_b-%X{&OpX(re4Cm4f?N*##$Mvv@Q~BYNT|d2F{McIzI;MtO%_2@mK4k zug)4#Ir3`dkmg2Rt%_oC`UzOQM%HPF>Ezbhy!4Sw zRi2KLFmU%b*jHPQ*DP>xznuJc!Ofa=Bl%tv9Q?|uByS?0I2u*vMCmZcKN2GHLD_|F zd|Ca(g-_7`xVta?_B6zL_qCE9oHjQm>reZX?7!xE&q@M+nP-mu_i(pg%>Q-J?{DHi ztmS$CzWXh*bB+QMbK+x30>ol1wJ;|rViFAqjYcRDBtYMG%{p{=vrM9hgm$%pT8KRJ z@(~NSWg4M}-Olbl7@fyhpaCHf;$*@evabgn^gZJ!AQID1pg1I05X8w)M_5s6o;dDy z1Lg}Sz&VM!P`RtG1*!pblX%2&K)PRzNjPbnVR;2slG%Z`13E&Uxg$3rV(cLg$J8WH zMV<_Whddvve+ZWz^0FP}iFl3Uokg0sC)27H@@RBg>ZI*-WGFg5?kFGtlQT=*lPP*6 zoO~hkV9}vP_fOBn`2&gMk2nh01K|bq)D-%1s4hR+(TM2Uc$Pp0M9 zy5VdM<(jg$?Ps-FRi;tn5Y22>%OrYWixpT+zd7nyqFfymMFQLIoZ=V{Xh8_-E+ZI8`B2DI@7R zaDXB^=&DAXjHnzZ11Ot8md0_Yd^ZT$pgX}d>XLVO5{IO!RNLo4w-Tm1Gi>uwz}7}B z6G0ZolDlL}=9tStbw3AGKxFh*+RC)rpQ=;LR0_X>C=@#5=eU zA|d>m4C~mPV)m;1h(t*D`oifnBN{ozQtcu*m{RDFmU-jM{^v2vIz)34U|)6=5q8D| z2ZW1`4&KWjz^fnUw&S}(-bunE9NKjG zWg>Dn35g&lR~I)RtamC)S8IU{gP z*9;2J7`d-F8Pa#idr&U~nLH4F$|f=91bP3}>pbuDye6votiJT6^>6<9;sM(GraU)` zkEjYqpKM4Koy{Lp1;21u1&v0W2yx0H$ypdWn+98Age7^z)03-<%0;jE%S#;M$S1rL z9$B=j4eA4%76@gG#ZP2v>mn~ay3(O*9gnO6A23B+L2FQTp+Q%p`9Z@7VRrp=DC*0( zf&#rdLa!JOkOdT#6>{5;MyS#VBtzdQA^(jx&uMKoiUAQiwp|IiOQFBuvA7LR8tg`g zoU--qlL3Jd87iKTNbW$mB51@j$}jAqw~O;qRoUCwF{KNn{LdG=o!xy8ZKsD6`nQF| z7zLobq@dPLcXoDmO0;h#v|BTq3f%Jymv#zgj@V2mc^8M&r!t(TGYco<-zfa$CVBR( zF5((nC)f&g>$Zh;jl%KZk&qL;;=mz6d3zX3sG4{aT$^q zKsbw_%F!Cysn$?wJg?Kr^0bsuJPp*e%IQfMGCjF)TnA1oOk#{?;1IY(Z zURW;%c{D;kn+#~ADKK~XUETSM|0z1?mLVb}9)whk5w>@{kpyVVG($SFm2M0=q9_;QG&HR7%iRR{6 zpAFQ+$3rx0765tUu|cbp9L zA9@^Hoxy*27yh*`#-pzK$Nm%#Q8#N*ZDErbfj|A$w;k~qZ++Vt;QOs_J947_W}J?; zzWsl;zCyoXPFW(*#o4*o>X?MyTS|Q4t}f2m?^~S*;j@5rKVzO~*8i)E)AP%l^H0;q z?DgM2-0c_F|L(!z?q>b3<3aPDlNkGBf?iRdM4}k$Iro^uD%9`vTIj!VlwdwZ{a$as zw$fP2__*7Be0=O+=%&N?s2l38L>FQU-=1H;zCkCKXXy0J<=MsU#hc3;^!=M_^z+Sm z3tgXIUB5Z|`Bc4bL8-Hgo7?M)mp`jF(7&B?l0;jUn!lQt0snMvn zNffA^6fk7x${1&%mJ`s9?ofNLz#cN;F%v{&SWPF~&XH$Y@n9$dZPOiHl|2$}H>U~+ z8tK1VN*?++5wJ})t>{mH0gm($0$7{a5Q)Se8^BshfWq(xQw=?awq49TQbkRSqisre z^z?`^ja5rSI+Rl-`+U{(_CfD|?m%}+GHb-!h7t)b6KW3N7NoE((j7D)5gAgS;xOO3 z17|kn|6+*;CrRor?(Mjcn^r-WP)kB zK1qx@P>R9}3}Zq#38!kKa1V$Z&E5W%G|&LZl!Aj~)pfsP)zst0DjNfH_CBee=#q>~I$3QtmGiv{p6 zS~Epa%Ddb?SmeNjCYXk*a!7>~Emvfvs*sopNhZQ&;Z%r(C=ud=j5H5kW_hb!t{~1cvioD;N*j8uAgiX3i3xnA{nY~ea2&^#kEp+o#m$)QNM$JP->Ox_B0*7)vVBs$!KM0 zwQ@7#EHjrY6YP(XgCL|>$Y83qIM56J#S(;-h8Gi=;LwuaBjaK4NR_S;v8W9*FX#jO zZ2M!(M{485rZ|+-_K*|OLX>mzzW5QB zsBws=t?W%qxE8en-WbKg-M6`Fe#(nMSuXWhA`m}JX`wNGAfV-0fM6fZhQ=*akT7hSf9WJ_z5R#GBgb+Q;Ll%bY zQOkGByNoldcVPmPh(0H({fc`#vLF$Q6_*yWwzYR*t7|v0-hpE&1-I& zd)hVtxPXB|8xyXE2`(G3;<(HN7cv@raiDpm1v`pqrSoq#erl?{%Qv?dr{^AmKo|<& zYT21Sl*;Y&q;zxF9o*0;;suoR(Xm!DptuiX$W4 zjB{4Rh857XvSl-b&Em9XE8<$`(xn9LsjeMsUIswvv??csQ?1))6Rk=sI?9=4(w$0S zCy<+v1K8}ClK{O}&9p$#K|eal3Z z(W>6SwLUMhH8W}!faws7ZbGZBfjxcH^)H!JmD1B2kS_zKH)U$sj$nJI#0Y>Ul9+Ho z0-_Is)G~0U#B`*!3vD2kB-;{=IMIYZH7f*mWaJ(39TpFaH$@01Bh2-=QgQEL&H@fQ z=+-JAqNDvntR5XO;G9yc+|G%RLcBRp)9Q;o#=sLI9F0b_vWu?zC*#P_ur6$g)lw*1IIo+rHPPig83Anp%Ds*@HrirsYo{+bVSScS-YC-ycuawAp$g} zjymX!3fMXku1fuixx&jdT?8qpgQ?!Y!p>W5u`)IQvk04)%nH`ZCd{mTk%0*po<$1y*#HARmaRj?uAWfseZ==S3F z)p-kDzPW5)Tz-Fjarwjf>+{Ro7J7Ytefs0cYxKAz^*V)E;x=ki#b*5IShD+ z60ns5{bd~2v6pIVqY%ji_9~WLQvsY^FrTK|WX;sgIV)IW-GkQhW>(YQvkrQdqEuCS zMfLsSX$M^>$&1K?qFn`tZX;qS1Y@Th6UL{Gsl}dTNyepXGKk11q$3jfWT%y$cDHh- z+|=?jm)^Ivq99N}LOKA24uBhRCPaE}VY`$F`%=K^c=h_w+%qRW7)Jv;Wg)ehOx29T z)Zz&q4)2kWEROMrv_L0F z6yPT6qxOObhe?zvHy{KnJVAUmnJD6Q@u52=Vy6Xks1)>~AC45!bv{j5K4T z0551d*(plK(KAbtLk7kstoBTFsQI&6@Or%iZiXpt0x~2~plgg-7*v?fF`ob@vdVRe z#cVkzoM)$H#&V2>AY3gUV?=G0?Z$(tQ8uyxO%(<*oTkeBqeG33+L*$k3Hbc-Ov%+M zH#qoya&>ind3N!?kJS`{wIGhesc~O$UH8;C0Oc_~OF{_UHmuMxZWMWIf>o;-4GD(; za%MNz%69TYO2R-O68Rw$n&}TXh9Hp0d;c*@-Vc@uBkiV^nDm7Zz3X#!(jByY#-eXh ze*tHW+Q$E}gJ8D~+f*@TNf_w+9R?1wJ8;Cdb2h8iikLP{Qs}dPtIPScP7E7=wqh;|K8zV|8TE( z|EIUV@&8}T^OecFv9*gLZ91I|)1Z=K|e1yG;mJnLpI#*0#N4w>I&9a~v z%a%{nKB$wwUQYzV61~Dx!qHxLUkMsxx!IB&rwXHi(vHPOi?=2;FcLo!wGS4iu_M!z zBtGo@x1f&MR}RsH1%&5^W0Q}j!$CjZ-d?rP==$mudi@Cx?{Q~q>jXvQ5xt^O@($e- z9+419;*TR1ve6Xz82tUo%d79z>|lG8oJ2utqR=SlY+cCgqFFGF@Pzt^MoIxU1)-I} zR1$EFqfu(rb^68)<=CPSUA$@KhHZkCw=9wPMAzI>GJg_>+OBFb z-YQPT15G!lAsbP@la72$N8@n1MTSG_Q)_`4hU6U`fZgyPzZpsx5-ee-{h(%(JZ8&< z<41GnEfItpD61F-w607af*48bbrlhS8 zXtNgchY>U~3dQaLn$ReL@a$V3&}$me`(!}S2XsTiVf(dlXZ-1zKp)V_1pkLc==`S} z^a1_A*eE3Eho8=os^@d2Rz5mWAGbanw~tHz-}-=l`^Rs#i$zd8#$1Z-1Pe*HMeD@0 z(-9A&ovg8P7*zDG@)Uzl1^E7%fVp2Otl5-2 z6+HYXR*%YzNS+Gb2wH0UAxnbQ!iLk!ua!j_YJh}<7e-Hjp5ec(#3H3S~*iHxis;1xA4IJM+fiU9{sQVPwp@Hr6kSm&*+0vC(sAI@H6#xSggWTgvD!iCpeGnTD568KN~v{MdaI)ew4nnVbfv9GK=?Q$ypu=kTOjx} zIMPX44n5K^v>_NWh?P>LRAAz#x4Nt^m&`&Dfh)CY1|_jU=e-zAnIC1b#j~k_SXK&K z=lW1w=|(UA_2%^Q!i_xEL6=Mt>)5NfCETqu@!UdVnNxMsC@~6&I!ikkSWTO1Lvakd zixVY*a?#DU-)gC3fPA|HJelCYj3T51JiuDIHW-L5eyWP2^Zamhd-_Hk`RSRs)G2mK zO`Vt`=>C}iB0xzDnkl3OqyKRN0%_{`Mx@DuI&LRm9?LEDk52pcvgH80jIwaff1BL%O29wrXa8dV%JR`oRNPKNx~m+ zm}jU5lb-N2lQy3fG-ZU@n~i9KV?>lRPq}twkU?WHxz!o`3VrGx?YE&mF9!olG_qu2 zqQAlNyFI-!JMkGkLKv@9ZtwRGKy+WJw}zkVb)+wi=t{*Y8RIArV|-6UX44sgr#eiC znhbr9NYP>~Bqlp|Frm>6Kz)VfIFAA+g`_btbfJ7l{Q~UhFpy@{5J^V^4(_$^Eg&Ho z0i(q+HG`u9ZVeK!+s}niRapc=RbKzQ2%OduRsmuMotXPNiVrfgU&wI;wSM2&V3Tu4 zv>Lt(jWuDoP;h51SeCk3RJk7Z%o5b-$_m^3mvh^nFBZ!|MYjh;;`yN4ENyz$tM%89 z8Sr|F(_(o+uwY*^=Q7uwTXLa3Y+7Ge84u`)2+c^7htG$kzk4uzHVFEIphxiYXT75Vd4AMa?}oe2hh%rq-`zjjB?tY1*YcF`B%%ggfoddJ?y@RG?ZeSz3(d1@ytsAODy8;yOgR7Mfg;gFa-iU7LT@+2O4$KGz| zS?9oOd5Iur2681EOGq+9T?joUC;V*e+d>PqoXglbyZv0zJV9|XJl6l%ZD?N8R-5gv z&my11QglVSiE5Jv3M;IOg`lIT9kZaV`sse9{uL=;3yrBFQ+&n9ta08qMGA~avmQP2 zm<6JPifxWr7zp*vGArAnb*U%TZ5d*kr6&!kw$_=8GKs~#=%!&>0X=CuUE5*X459m# zAhIpTq+R^d9x~p>s``ScEat*}8XmL5mcIfvGY}TVDVzqK_;8oA!1VN%O|y=c2b=z5 z&t*5IWoiAhv2AZLVD4%BQ!*eSk-re0IjNKteBGxFaEnf)BtostdtDnnIMrtkiN5QO?+Mbgp1Mgk z(HW`GA=VqiswS02qf2XJuhKd-yr~%;;ZPgapfYe_9RfjhOowoSXg%~Y15(R`ENR(b zBWf#`Z7b5&o3DCB)fWv^z9WCn-}4DR2=;@+-Mziw5Fb9@5Bht1&-%kdd^FhWA0G6F z{k>-g2Y3(+@E#fT_MZFr;Q8}|{r#h-sC0Xz@7*hSiP19ssNDj&o^oj@DYxTz0^C_ znJrvR;`Ag9h_WDnwfWK=gyu7*g8@J%7nrD`#$=hBRn@9ZX#Nz48uIfM_X>I0a~RnD zfof_}Uq0o4a|zok%*;3L_f-SZWE0m`0~tp`g2Qp;tux5KCIUY3+MbC`c|rRA+@9?IDp7Api`VH=K-Hf1)s ztQE&*z^pc)l%-1jj{i^Cc59eUf&ebaRH-XDRo|3L%-uDk^`>W1=wb+t0(R2RE^pje zHn3}rlF2~HR@2Hh>5Mw)zYOxhUG1Np|4MgF|Llkdf4lST&hdY#+HGC?pXTn_POAh0 zSOGW@EPNo~D`H_DOi{=fxFaXA>n(C|r5)ES(DsO{gV4DNhYUs^ag26*9reH6<7d5R zyDj7rRL9-_DWIXuT>L{mf&Vretg2wk&Sno#d9L`0i}uKSv)j`8}v?uEeKZ{q6v;G zEfXAkOM;8QhQ|N@tr9i|5s18tDKEna$M|C$1tG{a10p+vi|v;zAlD3pSN&RaX^>A$u#N(@e>P#odXp;GqxxPWO{CHdKT=k93r3kLwf>f_BUta4Y^uZ`D%&Qu368XeC ze(zG^0RXkbnH-yt#?5Jll|*GQx2HIDU^{BUJU z=iKK&71uAA>rOHl#U=^wRfwaa9U(s>El&`i6Dd;Tx0+q6cbOta@p3%RJ?%XU277y* zM-XW;4GQ!?IXELJ(1C?=tHD~1^gyv0`^z7$t_V>QQ`;WU>Ghdm;)RjS$FQ~|s$T6% zg7c&5)`}yqQ9frN!R)^Btxyd_W--MO0Kvp@V6&tGQ1KA*{JzHV zYy2)#ArAWc{b$e04$%|*j!u$^RY}>k?FVl)QClGBWP1UG@Dca zuBy1*-uf$`I#r-yk7|ZrkrDQ%N=enLth}nzu5HvRlii7%I&c7B&KrT@ruvX#v_M5d zV*eg(LxyM_ve6_jR+9*sn9{48;nap^Qslc0VC*P;SKmK?YpCf(Rw{J}(GW5m>Z?R! zqC+&~5+oSD2b#xV8bcTnB8N1TCJNV>Xh;j^pbAUjz-GEl?Glx`6)1=H{(#LToTgxA zD64I+61#mAInLq1!QNq$skh2Tfds(6!zwe13pu?_aD1k(0IQACwL%p7fQBK%@^ByS z>2!L%{z1NXxP&9@w2fqb{zHQ#{jm^iAQkMHW%X_{nI*ZT`%hoY8^5EAGE&+awzz>{NwR zTDnDu9+QS0?Vw+9NCR^RK#QG-MWls7_Sj0pi<>F!6v6vG#G|}H#lvCf71yK^Z)&{{ zp}6F9G$I8+bOutPc9B{59WEre#3B>##d3=h95t@)q5?m18dD#Kx?Q_*t;CHcAs;3! z>)WBx2+Jq(LOayUliMQWiwGT!SJXVTHBdhaeXxKO7qzj7rCo@|Qbb9yeEa%tMX`t7 z!@Xw<2`aTVY}S8sU1Ne{v>ijbLH%K;gZ`KB$7G`OmmQZnO3wKXMi|Sfz8Dh^vkQ0OGJZjbXS9T zsG}+v`Pf0f_5N+8rjl%m-)B|aAiY|Q!UY5a(`m^3`zy`{vsku5s}EOzOhl2Gvw@W^ zd8GhJ3O9vd*MdXck59N9k*H`X$gX{UYHDUu5 zhG-10J2DioG3rc+9JAnsnWUDv#ihA`&Sol10AjVQoRAl%x`q*kb`xNZI7omv86_d+ zI)}|RCp$K}y$&GiTDu_|gN^(>!BK+4aGImHS#DJME4`LJ-MV#We$}Me;2=;Vv28mu zuBJ$#Ln+r5H7*b(axd`>Cz_{i_`xaPscUY5mI{rel-T$fvM})2nk;RLvrf}4wcl!1 z0Ad(1h#pKw(Zu+;YTLSwynrFZ%_llvOJS~FZ;p6>*6SI|k1B;Q1Yk&$SL!%_L~VV4 zX9F0KT@3-z@1eU9XGzJ#YPao*zonKsef*i;*)j}MZI!MWQw$JpwprE#?LPFqB5Tn7 zK`MJvOaz+&w5WL`vyABaeMd@nW}8RK6^iB&1Ckx-XJ93%fVpfZDS`cI%_XIY%Wn6T z*YQO}B}zS~(5a@1lSDE-k+!bB+APrjC%cpD^ks)ualx`khSgN4>grpSv#EeNW`S)% zbcoX96vf#D>O%`ZBsh8*4{v0hc{GINreUZx+yF}qG^MjNqz9fk_p!$^~z3$8-rNIP-wDk;)GIOw1^ z5rn08G91`&60eCEw;(d=fS?|t!`v6^8Lae@PHr4!+qJof0W^8(*sRm>%mzYR$||o} z11in63kQY?5#v=|;dPp96geR)-o`Oay}W~(GFl+)l%cnEYjm#lhkB_R*i$3FR1J6r zDv0z0@Ilpz*9jlZ)VeSqL8v;I;kVT@qncDLzO5jjx_-~2hgsc{=z(&kHK_;8sW~BA z6$rD$%#D$T!Ul{mB_X7<^n=o^4jZ|;A?`yuB>vP7Nk!k;H{+L>Zdah^ywBi_KAtqb z<%jlkhtK-iExJM1fYF4eYxs+$^qC~ofOc!fP({&myK216s_e63(>1TFrF)s#L6chn z&xId7O z{jpiwPH5ir$Uew)GZWM$RdUjkAEnM2PA4D_Mq{v>tUedmMr*Fr!<_Z!cChfOD|Oa% z1-iX9U3YG0%ZY{D%r}q@ZjZBs#I@Z^rCTTnw5&H)tLS{DsPMpKe8uSl4ata{3m=E( z-kNb~@o}v4a!@cTcmZdzcl?`o^6Hgmv?Le0lGv#Sa=CfPxM34SOw?lZ#auH5?CO~g zZkP37YOD47CMMBq^V257Xwa>a)r<5E%wRR$PD(ce2Ut+wc+n+NSMX%nlUvXWxPDZ0GL<>&w6$#K{Dv**ZVqSpNe z$Dr+gor|Z9LaovMl18h0;%QA%1jIY^Ge1t}E9D%lp_*$~afXQN1tu&TMhT!p5$+I|{r5tCs& z>G(1gQt5VXs0;L?>dg5pTBgb`8Y|T8nnDeFO-1#TpYlZ54fEPPW1iYP{&p$AAONKp z8`4?Ko=oj)WY8||)wNdBi*TGS=k@Xr=J6TxS-UQu(7byXK7*Bp1NxcFeA$Ke^8A19 zW%n{1uaVdIS&#oOJIgPzVLtb~K8nZ13F;O5s#M;A7lm>DfR0D-?$YEpICejCvU+o8 zz*7B0TYU3i77p)44IYOo%^~*iO&&}{lULQsBlr`$sDHKoc-dsBEzR3jUtJ7Z`d)VShlT1q`rtVs>}nU0v=Ry+RS($Snd*g94BFX=6p9rlK+%&DqEDI|nSzBhAXPZap%z;;9Sn`IQ%*)^Zw3 zXg1;s@<+;dyiFA`?-7oqlll7C13wiIV6G}F^V~*P+85Hih`DWUB@js@=S7a@q86WN z>v?P!KbI?DEiZt2bcuxJ-TYpr0AS=MNKvIl( zAFq}ZH9Z-Lj92Oc@_W@THxUx;1BO}R-L38#gJe<-t}*L^GT9cCr*D4QNh7c^ zc8+5OQW%!4PQ!}nz*?*{zx-0HM9!=%tfb^*H?Z0V9Zcy^RN&A}1E|raSdr${clO41 zDU6xVm2gEStZNY}gNji~8hvd|0ZzDMuhZZ8_sz!+0%WZ$9f1P1wDei?I4peqbB)D1 z{nf(QMaclQ-QV8b*ByPIkewfmPk8oIz7XZqrrCnkR)nt1_^n_H)%qX)i#EW6F~Efin!azG_D*F6@bl#oG1>pC5IZC8-vUy3DkeM) z0C8B3ZPpq>YN!mjq2Nw75|Px(4h7R9A-YP+-CAe))hpQ;)~yTzuRQmR(@&@yZ&U7z z3z3E(eL+lUvGyT?YWd6S$|lRWi4?*!R3n;2nt2DFEtHGO*@!DK++ia2rIr&ePTrXa z@8zsu3vQ6PUN%XJ^$c#syu*G19P%-H#q&(QGQnB2vzCr0MxamYRSzS`j%>&iaU-HC z@mMneI=ZseB2DR+HbZI$fS`RCMNW7cCJB~T9MCo%TvgefHX(za>Y zjGbz+`)L>n0;kCV@1}tiR#=fSY7SMLn&kst{xcGf8*ug-rk*PrzfC;@)D2ivC+>BF zYf9KvRSF28<;07XQ~nc(MBw2o-4ox?uCKNB|1n5iP=9H&Qz5u=Aubw;3gHUb=5=WT zCt(qWip>O%!+0{zsk-yMiGyy~N=Jtve@wYvw{B3W*{capGqaB199ey^$cB@V3aXqc zm5cOJj4|;;{{l&)VKzUe2zl?I*WDkqsxkSPE#n<{QxVOo5%)#)fa|lXa)wKho6}*3 zO<6Riu9oiLnu#(bVd%xgcvh}xl!ddU@h3L@r)g9gv_AcsttrB!)q?I z=BO|x^}L+-SKnv&bH@r=)tNZc|B~ZE5~G_%h*a3@o@R-RNCyp7GAq6L=wKcPu`*RM z&7spA8?2~A0SQjT3K+MnG+t~%r~={$Px^d1y(luA7qY)PoT$p;xZllh zQ~hW#Fy@PT9SL_foO&zV@PPr&Fg}R(>w|S1>ak6EJi$b}G>-vf(NJrddW)s#<`Pk> zIao7XP|=a0y$&H;v;ScI!2nH2fxuc4rP3HwgaXFVs2r&EgtoY7U9E>%(}Xp@gI=#b zwz(3A7pGU|j;u}HG1yoZ?Ayxeg2dynGYaDdkV%sB-6Q@@Yt~}`BNV1sj1mUY6fKUCeV?IUK|oEZ@RH0$|qs0I_yF!1r4j6&k7%JJt`Z&ycaqW2oR3 z7C@SvXEmUBF!$^QwZmP9{dpXSXH4IrIyqGV8;NcE*haDO<7}4bb=)p>X~~Kvj8u~l4)bZtSULu0 zCn4KqrGW#H`LL5>k#&MK_ELH9S8XZ7TMdxC==1{cb-G$~lSL1qoD2`hJQZh&t}UwGL%cGBXP?~J3JH20d6P0lSw+^ zYA%G=tro(Y%6m43*#pmQ1Nu9O7t;6h)J~DD2eG1Xr^C=Y{?N=*Q(-d_bBQy5ZX0ff zr>Dzg5hqZs0G-l=9BD1izMLg_R#bn2O>A4$t7gjKcqDv9FhIO&80S|cx0Ej!vNJ+~ zFlU&d<^;D9-ME^=m_g!dBgY-Lj(%w^0K0DHQ4?om z$EfzALE$-IZRV$;G-5k2lLo)=Fl&TkAJpn-(pzC%uFVXhu6WQg@E9{)jHXjUA+R&|-Q>-cN6UwCy1PEvxR12-6^LY!)=~|84Xa{5jGIz&o@!*TZ z#$;f{P#KF&XaO8)CSMy{4+#}kbJt#4oO={$?%|Bcr?(Bf$N^>IRP_+Inc)8Rf^p1G-?+z#}ua`ecaJP?$AbnFqSjg$obP z;)KdkF1VF|Qc<10xB-lNS98(4R@!>Oe53 zsvLECLE*ZYiYQ?a<7zInQ65G?+w7QpK5Zwm;=*rna(F2uyyY2lUc6TF3Eu3RrLMQ0b8qqkJ7>EWBqmgW}6Ok&dKV zVNAo9!fcKS)i^?Bim-LDwshgMw_aU*cP5nL6H){)nG%fDMVn}=9Y^w>kzEQ{&@5J%5VJ7TttQ}|1oft6ekF9jq6+o9 zJj%iXI?EOR?m`Z>DejBfMk2mF%P27JZFU$tOdu%VH9oeH@3!eDYvcQ@UG%hV6hN3l zymd~fGV;;oaidMwsxN}-6w5JfPV=P}acC#Tsv%GsW%%RsE7N*m@GJCg)nS)wyUnQR ze47l9VLaIiVg;#8^xM`q@Q*e=F8Um+i&Q?$J3*{2g+3`RAvjZsqgudRD#m&tTIN%F zlll5pfKCDm`hENzwcM5?<+=6JUwzOg$Vr;Qmq7d1SDi9jxZ;mvbtGp=DwIMQxN3kn zv{?2qst|<>QM~w(WtCzhaGL1K)~rN41*oVgkJ+HtXK&`2R(kP1I5|GQ>JsNI3`>GS zH8oa|tk&F;3z7anrNNv+W3tF(*`dk8cc_#Ac}_otTcO1ohYi6gtY zoH)=%T~-V7MtMdVU4IX?wzVQ2%3NvfuU5Ss4JQDUCIT4cNXpwh!KuW!I$whQ2%@W^ z@J>`1o$-fbF&1eG0tgX4hT5fWwoSL&T|Q2!$c*2vi63AT7-}ynLSL{H#@AU?sY?jX zFv|VXcWq0HWD0|7TPD0*w+L9wAT@yEsT|Go6t(O;QCTYZ3|_af8(E&}EkK*ZmuX-^ z_S94hDJi?YKC|G3S{k}f!;B0-*Vku`r-A%nSFT|SugXla-$W`QK#o?rtBp-%Ow0TF z`b-g1PPkW{@ygI8sW{^Pv?(D=e*>kCaDmx`7kfX z{KEvjjpWEg`^(tz^n|e~Txm}Ml8~_KM92DnyC}=QziMObg1)(ATHRVe!W@Y2^zx1P zyqaa+ohh&CLj@77d>kPPE|%ql8ttVcbR@|QDVLTCOq2$}WXpRj1_;s-jHcd#LR7G6BH7J>Y zv+@9#lmff7%(5y1%(|^AsZc>9T6>vM{BbmAuc3d}M;Gk!>Uz_q(C#fE!PPwWr>Ttb zkRyl7i2JvbROT^B&j`!+mS^Ig&)2~Q!w=X5zaRtv#L>}xz54x)Ogcs`kCe#}SWXOSu+n8!+F89{xrk6Qh(bx=Qo0ZD;p7Gti#jDEYPSQL&@4iFu8L<`o$ z5Bl?au0U=H^{V3&u9rZkq!4hMvgIH@81@SnMYSu&I*$6pIFCqVivs|7V5lX*!^v&A z^c)ZFic)hpWTzK*J8w?k>OHt*Yv{Mwo71@0t*Vss))WZV-7bp(V2&^-eS+28lypOSVE{rPIT;Iz4<$r-zU2^zf;j z9zLbhKklh(lV=o9td3J}xQ-@PsH_lw7>G?RyrU6ngBRJ8L ztzNcH)|1O;F(`0cqD5-iJe3BBJd$K-BPR($o`Hn-_;Dla{jt#M*D-Xxti04Ol7~d3 zA*AqGAhg1VWGTooTNVZdw!nn;l{9*NGB-L1Upe%%+l$ z3Gveubs$-T`M&h?(UXOOD6_URd z=!bU$G@R@n!bWw1CGSE`PtW;GEN=Uf%)w6POWnU`6mgs6LR_6*DB%NdsYR^DS{!Ic zfS-!IUYuJ*H34xa(Av~u-hR<1NGYzef)ip!<{n>!v&w9!7Kp*1RvLCuGc^2Ixfo>~LLUDguINwGK<-v-VKf*g-LH9&=u z{`(@wu6G}%Vv_ST@M^p++79GOf)2JHy=Y5oYW2E({8sx6v!*-mXB4DetHgW>sbJ?a z5T`aQrYOZ61}SA~Ekn%LJ^3X}#alfU>_P_p3yDq_Kck%Yg*4^F=i(q4Z!-ORN+75ok$~tK?Y^whFMdfxs=%t6{U}5N z2LDCTb6F}Q1s$1SM;bnrCiP!rtP9o+y33ca07zO1_eF!w&sQLB zV56wl{UCUhO^>Dm;^bB%m>KKioz_UE@G$YW9C!yFmRfLLaB5L_2j2eyP;|7qh~PhPc{`XAnQqLom`Uuv8H~}KWVsGI z=J5pXDtMuA-DP}YwUNpYP=>DVRmf+TvQa?<+(G^1^za=^CB?d%YFmfCkFXffgkFwW zI>%c4FgkR}&TZk;@tL^HICG=%K% zd$q-9{5Ki5#Vv*^7@peqVlNr!xHOt&nvV#MkkE-1wu#_~fX681N($ z=~*}nv!6q*ud%wIglX;2d3xVEKkS7`cOW)!C+CZh0<~oS9GF0)V9HTni*%*{I}oPh z3f_TtF0<3vYk7FSdIuli!ts9nr2mKb++Pmc5W`9z z17_Iz@&Jr@`Cv@nGjSIkQXO{zy%1!kLw+sHOy~VghaFNAD88arYID1BuXTz9&xW2x?AWAo0+jiKoq{3=egQ^8rnzDQ*ZnlV48+Mh;?HYiM z1AiFwdwjpU*WVtDhWoo>r?)@o1-qON_Iv4NXM1rZNhuL2vXs%j^qs z%nS*ZXc`M?C(CNKTCf^hmTfBhTbtCsxCuGwU=Uwf7yR(;-`d~K+TRB3+w0D^;@1z~ zX1{*;Hv09$xACv+!?%-zZ@>AKeS2r!l|+LmI4;YG1L(b8wI+kw#P82U#vznbj&Ynj z6~>a~elgBWC_hb;NzXQ!P!QmL1i7BZ=%)=x30II##!YQ2Fu zFqEnTLc-6o);pEn$h$n>m7Le`@1FM&UI(a%H)T zVxVX)-F!hMtxr*jLIfbUODQ{Ut;tyJf^a5oRv=B57k49N0(o?fa+p-yF6rHRlnqWm z;m}92O$~kqh{u(kd@h)y`rm`*SV?Mi3b;biC*28|P0M3?!{gwlylg>&#jQ}Pwz+EP zpN!qN9{H!^#65NmeJ(_}(zZ(L*|g5U7u#*U!6`$+S z2Gy{dT%t0HK%?-h7Ntr>YfL8s4rV-YQkmSDtl(C4T%hp|?bKo!d*>(DH;2dXPS3rT zclEa``a7&YH>aZ}a{;A~6|nGT4iW={-gtLh=6DSzk}|SHB<{dHXunfSh%0fX1^4$! z!)54!B~t7AUC)+`Rf&I-p?rCD0^cr_E0^^VbMaQI$%BRag-GB+?yz2Wz#dp%VUTfT zYLsh!Bvdb$^1D#x>7t$Ry4UY23>Rhp&bGVkfo-eJMJzAagZ(wOV2N*s{+ggHy-HM7 z@f9X7Fl4PRE;Skg7gS>Y-E}gY0Dcc0s*UBDv4NtlvWejPA_bbUBhM>|++SW2*&W7e zCFCcdTRMR#TUfC}iEQf|psYL1+xDr`!-w(sJfB^sxynTFgG|)fE?UY?Fe|QXASj>& zGyH;0Wuge$$OINXw8t{N=V>5|(IWbSr#>XKXGynNCQUX2k=O{fryn>i7y>*{PN@#hnQ; zR!(KmWsG*nsojvX z?f3oB&ffNDe}BKb(-Xnoc)u^k{+{UVjQe~r-sYqI!C-fX4+nzx1OGF4eB53Yo}YfF z+u2><#AzH4*OQ}1<91J(D7S{id`gQgR9dhM&qgdLx-LPfWDv)szm@|dRo1>$MRYrNEXzpb+@5X-pQHnTr>qUW)magAN z>-<-FIuYJMuk~0=q$W0+Adw6P!Rf_1Ni`?M+lAzS6&X4ua=)0HVs*jd!ZK9D+f%mO zLnG~V98^xZh&uU}E&cfOJH=kZ$NG$>qNedL?s}9++aJ|O` z>LKOkK)uK4Hb|#InORehalfZesS?!T#pxqgFBPYP*zYhl!(Jfrl!b3C&Le#^0-E{f zirtGSs`2sywwacv=CSW+EiYiFxjwsUu+=Q#`-!F+XK+_Hv6gwpq)WTgRyEPAZc2~n z;$Q}%r(bHh85;#;KaZl)7($lDXwHlg6N=}}W1s5cHubbpKfz!-=(I)$@I$SkvP5ZsWjw@D-nC~L-jl1r0g1)sxZOdtbt0m#+3fd)+(clG4v+k zB{?NXg4{38bCX3)iV@_AQBZmZ9H&MN*|7)W9IUOlk->4r% zTdM5)FctR*=d!k_VIZp5m_DwPTc^e$);cIm@^Xw+O~q4l375)C6;0{ox5j9gSDQty zX+9c7;-&1iNNpX1Exx(w@~|@e>IbC$8ca(yLCa8ipkS+#T@Py`05lL*u(yAE$CLBY zjWmwreIzHQ)P2jNB@eN1fU6YXGDP}uFD6J zQ>>lVx)_Hs*6VaCk&oc*EvOkL0>nsLLL85@YKlpjIOf}izrnhcd6wiEKBLmmVa6s} z7Ns_uTEo+_sYuWlIXJOTSIC6f8P%hq`g5q*NaitK(6IfZa4h_}Z%R8*7t#Aqkm%)| zez4Qu!2spM*tH)JE;Gnebe?CD!U$LOPw)s)0LawVv(#BG5;*A7DMiRB4P?kwS;X$mSFN?YIH+Gx8m^-$~vK`f>s z28`5leNjHr7igKMrj^$D^FacU{QV~e1F8&RZNsc6n==$rP=u8v8F*z%65_c;h?TQ!#lv6JCz2`1CM*fOdX|4 z1N9U0aY}3DR3LK8ntH)R8tU-sww9>&WR9#*F2mS5$y4ubHi_ zr0|7IGB|dD0TMnggjU2#Vo(1e&x?(?XObke{d4nWyft%YY`2YzE0uDRN6w1rlB zC@1jNc)}nLE z$G02^Bq3DRLCel3S9(F7pc0i9JE3%~10iGp(6lgf#^)ksyJ#tE=vYUy-XXrRR&33Y zXo5sbq2Xw-mG=ksNi4IXM3!UJ=RWAe=TLU*BYcDz(;xM~e1yiJ^dteZqHhRhh3YW# znINPuguac1DbR1B-W>S|n*;%+5S75ttN-Z!;&04wZvM$kkBUESK;ITrc)#`>u`%4o zfVtJCnySsRmCgBSlBr4}6-|+qsGvgCf|u&^sNc7|w+en+B_6$1YeG-b+Dk&ed{C?c z^UGgzHDG7l**(m&sZ7J)aGSZmKvju$<@Y~m_BG$%c_m(24g4*fd2>iDQ=p0?=%>pw zx^7;-J-Oa=0zt}J%lZ>x+BZKxdKjNMj;4L{>Y`zyqk9PuN-;|MWjLc-Omrrl7E8EN z_W&(86|q*NL!a?HGx$%zlLwEu`oji~+Fv|)aKm-*dRuRa{iwfqr66|UR?HtWG|-qC z8*K9r7#X+AjRO<$h2<0f>`!y6dDB4fl2iL$NdJ2Elf3uh;E%`FPL^_V)emaJb{|jk*K6gsdY6kvFsYTV^JTk>-y*0GF0Nq%(VRVSHteGzl7N}FRbTh zU9FkSnJS?mjG9v20#U783SF{?(x z8TyM;POnN;Ys=2tS}V=hW-79DzC;6l!~I)19v3L1pxtKa+~znGD9z34a2PY6V=kzv zO0_}@UblK#Nf&;6^|Df%OA}^2x1^cAN`h1--oXd&@a)X{^;64B^Z2kNUeKd+8DC17 znZzY{_LCCnLLsEkg;t9q%2r#b!fsr^J-FTLZ|~S7O)5=tdg0YuHIyo0Q;S;cm^PeJ zdb%x)G`zO48F;^2v}aqgp^UD0PQ;e9S4Yn)dQ&tCZ^^N32Z6qdC_`K)Sa7Cgio9Av zOr}d&k!kiOACEJdnN<1X*OH0d9M}yIur3b{?K@4mx64u zE1)}&{{?$QgRLmQisEBOg8Y@%Xy!+u{@3e7q=sq3WUt$8;_)-od80!Lm;dpy^Ea#B zp&oVs@(2W!SN2+jKjTr%rAW)aRs~J4Y8}Uz=|&;H`q61}Xk66zl*qQcSr!$MpuiZV zF63dy-O5E|BV|lnpIucEgsMBDsmmRjrAp6h{nbs3xDvx1CSqS|b?xHhokcHex`&9e zrWKAupJxK0Khy9||NU0XQ6{_<^Mr@6QOLoEx}fp-W1LrLfx#d$Q+Jo=*;K^(62M^0 zIH*IFQh#+%ZQ%h04gyG4Q^Irsav)Fw)#ufW$2r_B;n=02?;V#AOjPq?>Ja0LM)r?c zD^Hk5>c_HqT+;tesb4kIF8m7RdLVYyDNErrcaIhdy!P2d#H$;0Mr}cxrx#9~$dj9G zE>*F(Dn-S%C*vP`?R>NZS%if?0iA0L7Ic6zKD z90OOkVPXy*%&owg$?;R>PxQAeEKAr*`nRG9%e*mZ16~Jl=BGG(FtJ@ogCzvnVGYf= z3XAlHQg!d*WU7Xh=b1ED(>tiLlAbD+i}X^A(afQL`I$#y5N2}&=HVUmy8DAx6}$FE$Ki>BMR( z*oWeHQTjv?4I;R`XPUTfsz)T!3@hpAJ5;}i5^?qZ1De>0@0@QIw_P0TCI6FFo8>_@4;G3X@ zTThHBNL&^=^j9Sj%1R*+*-x$G4U96cNV8JL6A^NxizJnIVSt8or`mrilQh)q(p5YX zk-TpnFPy{jQ3Gr8BSG%~v<<$LNf?$zgLs7r-hy&E)B$TlNJJ491tJ;|%k@?HgNSAf z??W2jD5_9xGe4E_|COVI1vI!@g5e0?1+ELC@tjrvl;%(CRPIn3IB~`^lgL<&;=(^# z!2%YGEpSj{5q@o(UFG)nUnv8y(&eUkG6zHjmfblkV8YB>P}RZhVk(Lgg1yEPzmZU; zTy~f;@sNb{yT180JM6ty6=C~_W7D5dF^?w1gLNB+5iD0Ne6Upbc?#V9j~v-ZJ_1ti z03fg60R`hh3{5QBYAQ2$-+@Cd4U^dnwlmdf!D%SrPR+s~4ky#hRGJ-!smk=Z0ToO^ zPaexWg+e=VHbqo&HIFm?&|9iH)ht_NVz(*D}xGVIl#*6Lj_>H z-1uk6c|=Q^UT>I3Rpints6`RYSr95;<|zOyB%deD$FDrE%7)&9u} z&SN35xh)o9cg1hrPOty(i@<72Te>C#jxwT5JUni}+PI(lCbrB{xl zf^Owkc1B+en9Ea|s4_iATji;?0kLMpShSZZ!7|Y9Jju_j$RcDMt z9VELD6BHLha2l(R)+kgtH(elV8d4}V5?Y9tr6nPJ6K>V)IM9+iq_{$9g*L^yP$ucG z<=`gp7<~BEHJ$21jQCjW7S6-JczA0bzC>(m9@e5Okno>0s&xT#Unrz?QR{!fcvkGn z(}GzSESi^!rK~A+3j&n@$EO~wB*%q}fEk|pz^!in$3^PcE{6Ls~9E#;?E+h}tu%@IF? z7mWCE8he>=pPx=2AM2x;$aoy^NXAR`Gz{_q_d-aeY%z(RjF|>8t*(Y$4gE1F`! zdS8h+5U~&CYELuD10ClPVDQ^g4?NO3;hasmGPSoIFGN~+AtKGO{%J0A_CNYmgCcyT z&8*Kkvd)@w(SCXtaxnF`+^*>LVGBnDG8XXKN63=QlS#@0f!W;mbz)ADc0UTqz)XOb zCJu-0zIHngtLLjT9}t%!(oCT+->}@FFW5DwJls!EvAiJEBDZ>E-KOrkNwJt*n3a^W zOd9(t~TWYGqi^bN!axbSOmYm+}#L!fnS5FF|smED-k$4(Clz+V- z3*h=QL|D`=`!5h%k%!g53Y;J+zdb*Uw5p+p;GLd~a#@=+@F*IbypcwFF<--RO3Ux{ zM?Vcd>O=eE?VZYGDn4$O+d2Zfj1wGKZf-!3g%C|C**y<46Q76(cd@uHT9&be#48@6 z<%e2bCqc6p^mqLM4+7pF?u(sZCm4@M{`Qy;d;5d^uHW~E-QH-_-xkAue=rDoJA>Z9 z-wTFZ1pE9YwSLO(UNbfGu!4%=DE#o(i#&=5Sz&1nJQ^j(U@xue1wBNdoIDd%rkbQC9NB*%u;+>#SqY#(lzbb)W6zuKazRSnE=>F$Coq2LOrcFiB&iOdBZ+KYbBKB zONb)_dcsp-#j!CI@@B49#^Yd1rpDBTf@H!c`sRdsBW5*IeEgZ@0eizEEs~`rwX8l| zk>tUMUajAea;UAWR)`GG4OF;;&X8(yuLUtFg*~+89gv?59 z1`=AMwZA-`P*WcpjX)^93cZ=lUN#m7n>k#w6ooOExWu`&7~zYqsXlTjf|1a^oysnZxd;;*XV2~aCZH-IGQs7xu;sf2a6zKw1>)~?SwH4 z!c-4{)}T==3?S!~{djRnx5hh}3VA2eRtW&UCfGg9;hC;x2;)!s*4`&O5GdufpFP*LHsgTe{m}N2kY^Y{u0s!u^2HGZLVtWs-$)5Z;AB z&Lc7!gRp&Z_->76FJz#JpP}|zD6ze62mZIUN1CW*1Kvq_Jb6hzhV}0E`dw;x`1$%j zT-5(@(Cr=^Z1uW3w*SKy?Z1)U4=+y7^jZ5RPgO=EQ0xsHgX^gl{BZ-0^m{lAaOl8> zgwq<1FdJTP5uFb&PF05;MoKbF2&CxzOx}u^jdIB0^LfJkFq^N#>3?2am3Z9g)R_Ex zF2EX@V6g~kyl+otme@?i7!+8Z38RIDg}aG7btW4UmKt=iYSoz)o4EVlKQ)I zt}mENygp!Y)B_?85wjXPnM9!~UYT=tb$)o= zp}e{XJI6IgEz?bSvC=c*a+XA)!Na1i`8+1ivyqx0L>1d}`imUtX$J#%!u5HX4; z4P8;VmbpKLzz!QCVEvIYbrbPGJkwVY@(F5On+S~~KC#PnxQ2}wj=AbOAHLK&AAViu zU)TBPUFWxZP2yT1P&&P_>RUNWo2VQ?AcPi(;nJ(f-f*25%hcZ!<$#x!WpIk8P+=gP z+pnTm>7h2)En}w`Qp_QI0|VbED4ABQ(+7l3hsa&=;A1vGxm;h-Xlqf6V8{djRcs-Z zSr$35&;Ujp@j1=HjOB3_!abXUj6cFiQ0kH?E0l$LvdsN^aSFy z-Rty+9o8=%--%S|8R~WVyZ=rS2huQYrX+(~)(Zgyfxe5;Fs>pDjZ#xAf0QayK7m7G zqe$VCg^s4p-F~>1(l55 zeM2S%aL$!Ku9qWT^fA`@)E^6x91DGhYdz71tJW^4AB9NBWo}+(HfoyeaQEd9D?03s zxtPiL%J_ZD4MNt_+6^Z7_KJ3}nS4Y@w)G+#|8EQYe_Ia1uroyDWQDRCh7x#;FALD9 z9{@xDw>M!NX#Kch%n@b(H*-2bZE3f_tL~Ym+(tjP14sq8h%jysOwG4xzpqFyJm_`% zgW)S{FW2I*n;{C9N2u7V4+jUoHoQD6Uhc3r^CA!eLfZ2auhc_-2} z7W`SC#rl(xOffMTGO_8lDr_J%!l@XiLQR|EbhfDk=6i~KDM-CimV4W1DwK=>?tl?Z zs_i7;Htd}BS>@Y0y)^{A1!O4UU_H*LD(x7+J3Wz2yVXh}XMGH8Tcf4* zcwU>D<*Yo5z~o0$$rOIKvAIgbfqw68%CkJoWUkoZ<;9{VcQJ@#@e(AIDn(jvDflUdTr^W1l^Dy2*;yXOy=rv zf&*Y$E8KNlekwr+rWH-N^cwlj$-bM(;@6^GtyMsH*j>oke;r@2!vqo%^lVcEDHa_( zC^9u(2NKGDX!-iTjxRP_Mpk~U3B0-ZUJvmk<;H4ELbw)wb6ZrxQ3irEyc6jw#RN~I zd4c7@v*~6F1ZJVKwiu7~_4-=3O6`HwRkvB{w$#@c_y;LLg#?8#qaeo8z(%_@Px2FI z7F=Yz?5wn?>dkd*1Lb*i+j7H4&fc)%i)$ymuJi*s<(zGg9#UgaqQa3B;TVY6lxi{S zz=^xT(vZem zMJh8`Vrh2CaxK(Z(q5mHY{T zR)AR1(pfc7X3>%)w-^b3jcky?xJvl8L*<5uHkcFe#Ww2|5Qsf-J z&r7JNTd*zyM>3hK?Kfz?&G-zGp6}Bz%L+*tOz+U+ zvdzo(W4%=cL67?VkVgifb`ilfD!$lhSW@SuOmN-mE|zk=rb`pS$Iz;hStoyMFW4RJ z^!y#4?+o^a-Tq)_wC(ryMZeqcb$5n+G2YwX+1($FhTGe{V7NQ%`a5FS-4BL?-l)It zzhM3rcn$KTt^71hGMmTc4|e=r5ePoo9S343;KMyJ*ynz*-P`A*{th4acl!SJctM_5 zvA&!PFFQmpR@K8!#g{GbVLS4i>K?@qB{HZkqQ}>LSVe9*d>K!Y!*nLoi&X0K#5?%i zL~H*PgSHckfT|+fq6UUi<&b^^6P-%46{Z?EAhD+Ok%iYKoA}2nGnhQy6#7{3mI{^0 zq=u5KvMbydkUO2EqWCB9V!i{Htpe>XlN3c4{wD12cA?@nW3Q8x3Q9_)2TQ@>vRP&7 zxz#$%8EvMdG9wELDtX3n1x2)z91zR8Gq2^%#0(FSUbp)$qy=Fcuu+2)dit-02W;&P zS<>ydFz~W%`D_>Sw^i=S;}CXu5O@b4ysN)m-Mo8${L|Tq*YeI!u5S*H-<_U&E%?Fx z`_T`V@84h3KQ68>506d&nI}oZyD$Fw&RX5av zDk1I!R`(R0-j80l=DS7f*8KjYb-N&S{&&y#tGxs7_O7bmh8XJHdUKoPXM7@#}O!p{uS9ZE9zZ6Q>*ouKD|b<+WC!xPFKei@Oy+Q#~l zyZL0Z%vZqGbR>BitSpUI^`XHidk5YmJeV5Qtz%59pTs%e3u|R%sMtWes-KyXyG-ikxWBJyJ<+_wabTd`@0e5G#<|YFVqhMc$EHO-ixORY@J$2ImFbXp#T zBR=Ag_I_N^Z?}hCe-Lzef4H;1H|!3_!WX@+?+OM&--G~+urtf#{I#rFUGy@xXXj#cF+~UV7T2M?ebtS z7>ey)Z`9*rdw;OIBSzbU-e`9$wl&q?@>Epm?)&|5cW-}>_xAVpcKy9^cV~ONv%AwD z?R2@nKib~eAMS7OjQjq6cSk?%^U-*3G}_tq`$G}zc`XlWrH6i%@~#m3{rRkW(Z1Lo?Dt0d!ESel@4cX&Z?E>2 zr}FVQd_d7~t*R~6HSXy2c8O?l=W*v9RkHva(#rMyVkU!XU%ss6!1m`kmV<^as2cS@ zTXE2(ynXK4pvxQoE0qRyd-6yN(OS!9shMakb#;wqUJ&JesjBgKkoz^r)iCaROIWo* zyUPhb+t9Ou{3?WdbYoh8`|Xzjxc?tHIwRHSv%=liRKfKS?;FPFGoanCIWu3u?#p2J zYYfpdf$rC6!7Sj0?P!0ZiPx>X%*;O-S^tUceI{W2Cvx**xcW=mPsL2$L6wMWQysHv z0l0)$jFAF_RIn9dxRn#^j|NE)0jB&;FisBtx%pO0m{d-nQ)Q!CG`s(?8QnjVC4m2G z=L*1rY6FXFMO1100oMD1&owK3H_8@|s`qW1Tn*sxd_hNvOs_FY*15`fmN(+RiVW2h zU&d%xF!?>MpqNSa3P$7=S-&CVlPejsSGdwn)lbPQYdc@HCTru7mG*<(dP>V9TrYy! zo`Js@i#$Xi6xoSZ0A`~+g9vK72jHHf7$Aki2Ahh|-0g>jwZB4JQ*&!?9-Ui!y0qG@ z+b}sgzreA-La)YABzW9d^Yb=L*wOg~Zg++A<-^-~qU8rW*W@2*YV7hDYEYB|p(;)2 zyVy5xt(4zh#-CDc;tz7GIK6twQpHOLFpsH%%Y_Vn;h8@bh4fGd`X9LBLkr4~;X5tZ z^$?F0jwyMPrwAKb=z;o)UZAFE%*brI&T6Jofk~WA*Af0gZ9TH7$JT4U%F~JP4!r*0 zTd!3s;Oq^$-+D`nI9F$*$pee!PgHXXZV5dj#F4#Eb6C23Z zj)e#yC6m&&rIX8xqw^dK3?`u21OM^5c%8r(iO(pS?JQ{b^M+(V`-{Ud&_{E0dVKj# zZ-`pWQ4#{1UW2-T5yi!WIooFIlVJ$$aI{NKk1uVYVuv6mlnQMM0l?S7ndo&K)~N8U zUS>@NQQqi`}^6padQ z_|NNtzui-9biPyc{foHXZO5wJd>Q9^L4JL=yZvUf!qe*IV1(9Gw5i#mwb!Krn*sPO)d>Bsh7hPP2FD#$jKRwx$Jx>TvaX_{E6(X8~j|-!umRu`ETpT9k`0qii zE>dyC{b|!YL-bE3A&CWpvOc!k^qH0`+P?nqBc{S+vfjV~`w3Q<^$xsqNwS=<2wD0( zE@M1w#WHIHPMY_rwff_BDx)fe8CRJ|pZqx`)wYv}$6_ri9SF~{wy`p~JhrJjkllYr zVT$^y1?ouWC=J25dKd&UR`26zuJ8WGn4XF?@dp{5inZ{>VBVq!jiwAs{*FhX{{86u zqRG76#-FC>b~@kZy~DMQ+M^0b^jxw!w3-|H4tIB{QuQ8*n~T zO~-%$7FK0DRWok((hE7LokYNeUg-kX1^_n6_2eCV@L>P9{Wxrc5d;A>+FBuMhlv5$ zXh);=j3=tC`_tCym5CJfeyuyLXNEe7u*L=6|8uy&KWLrP)^+j@ynp$<_epmYZVsbG ze(-K?W+LM^#g4g2WN@SR*A3{3ziQz+oruhEqkr-~>BniVvZKpm1>4x9CRcKk8yxRz zI@ujhU-P_{YW6;RfMxOe&nB+X=apr&=f}O|K03!aWN}a0i zvyPpZ#SUIqLUl5Zu?iQVS*CJUa=##17@YEeiHF3Nod645!c$HrIL-*%<@LYg_cvoH zq4+3Hp7XH9+Vrmx$3h`gVWW7uxvoh}j`U)|WT3fOsaw^7`fOn!uIcG(=tpzt$7hT9 z_{@PG>&)$QgFDt~LR)7lB1)(#UyGz*s~x6u|Vs zjZVYzwc~7tt-Bs>Qj+tE!j#0=L(ML2nbmShV;mnu&$T>C+Bu!^iMSLK@n9{@TcOHA zc?0CDW&cj~Pt-Cwb2 zG!?)p4GgZT2>{ZGha?pWD!^KhLtoAko`L5G2aTFwK!j>@R^UkKR@ZE$BknH-V>5z` z2^ElIX5e4iZy?|65KE05nQ}{YPacz+YVe1k%0om;ud^FRo$b|$m^dByicV- zT5Hq#J2s6dHeD7?5t90K>z*n@E5P;on9Q>oV`E#k=V9%396mDJh^)R)8&!= z>G<&I=KaqnmzSr<`k&vw|KQBH4af0|6PmI|iS^3cSjThXuePlAFUnxLko3p>?JOX$S zQ%{f`i*Xo>3Kf!%#%{K?>NGWHz@TPAO?{DO6A`b<-iL!;e{96%X6)XAZks0|R*h>z znkUahTeqc1Xs&Z$5RIUop8d6B>2$J4K@mT#t4(F_ouA71|H@Hg52yKP6p0t@9FlD8 z%@3v4oQ~i(kK%m&VqyUlHxsi&raYY!Iz@wVq7*RD_M>nsR4Ny0tGB&B1Y8qS&Q9Od zWDYwzJB3>*ew8tjv_T&{Eb5FvosJgEra2l6x~%tO~ej+pG`%2A1VP5A9Jt}h8R@Tv13FejVwvn@&cLA zB%%JL>32~v@AwLx$2?LXjM8h)l%2~rSP%A6s6@u9BGsfqFS$z8*Zq`dBy-a@h1n4L zh1flS7+@_{MpUNqv#P@kam0Mo0}r<4TP+txiv7oTY|!a-Tl!ff??q~Vxfg8Aqi96f zI$n^<#A_0y+6vI0v(lKEooBiAb+((lZKpBo<}{zeOhIG1m0Wcxr)sXyxiBWA10lBKKHu zLM8oMk)6GHR7FgM~V#sW=2GV2Aa(1NOlB%2snNf_NpY zu_?a`Wu7k5Az%0UU4@`G?BCgTmp!m;wOMC&f!^9*Lv1Z_jFj*ED^O3MBI}Ckq-Yaz zYC)6A1XWrUd+iqjHf#;Rk9Nw1Qqd7LkNs&X;CN%2-g?viA;cPf*n zw3A53GMzyp#M>j&iWZK?;lr{F((2lRZ%i3>!2+TDG#sH)`Axsu-R)P1uUC+zLYLxZ z=+hRtPfL;*I!NJI*1v8gsq}4iR;eBAWO)XD0yudEgmuzh`wW2-C4*!o zSR$+1j6I)2aW;`si7)-PpLrApVKzU`4U|K#yFW1D0N$sT=kqst9ANx-)qa3)`Ml$& znOB8&Po>P-_P1P#D?qh3hYBFRry^5tENTD*3s=pG*JoE1tS%SP#rC!1^J;e=)lqP@ zb0vm5OvJtnM8Gai-WiXa5pa(VnI;yFLmy7o7{zS;_gi7g!PA`!QV>`AD4)q#f0{{V zYTho@!#&LGxo>gupw2$g ze}%liV&hPtTwx?sf)aNbXd!f*fuuY-WU0Z#0BJ6kERgpx)MKs>^O_}+9piLmtQttx z)*MX*(#+DiB?Xi4jwj}pGmr|a+gOOW@6J7ha_JYJ-=1AWO#}6l5{xtYU5mzo!>sY5 z#e!t{j%mnEp*SQL8&k2Vymu?0-wL~-F>pIx>2J-5lGF3eu2g)%*O(Y*8_ zz?TSsI?-C8x#HuAzU%;{F%2ihqs;}jUW8N8e**wa-Q^ca`^5hKL2-9zuD)=Sb>JU+ zJG*`0?&tqHJ3MdU!(n%?2M_i6ekV#t4ZH`VNk5Vyyg<37rc#+nUsfFXcMlOqoS|!L zc2CTk6r`pFk&;awT7wY`+EeM%uWGre9$JFGO{fza|6q?!zbs{2_LpW_mR5CBY~o!e zl8zrXA`Bj442~0+V*;FhzCO7iU@1tJQ!Ok}h@l?L>vi=1x?BAnrvK81zj{T3E6+wn zQ;HM9PE75?*Sh6Rh~=2jE&h5WGQLSkNb=s8H%!ti2G&cK@#q#+#4rt5!qaT-c0<9% zVa5w5v*R*M3_Nv|EP>OD=E3SQ8mgW%PBZR5xy5&fM-E;i44i(pS!w;@!2XZ1`GNDl z5+CZeff1ky^UvPtH!$lsu{pI`b}8PeG~6EyI_Cen*w#G{v+rg4qrt;$S|7h~Lf8HA zr#C06)?Wp#{%UXd47)#X9(jjzFOav=L!HEJ(0_Z2Z&LKQH%(Chzj(@c7+HXBKoOGMgpQi?-42cDuu! z9r$mz+pYe0u+#1RQ*UQ?XQ#WpyR$p^r*3b1yFd6R)_qYf7W~Oo#?yc5KD(`I=l&vp ze*fJjvN8|KA$O*N2O{-Yhkg3AvC;5?K^qQb{0mRDq`c&1iq(C?gNeY`8eY=Z|ME9@ zlKfnww6Rf?Op%F*jfGLkaRx#zhJ9#t)xyQ6JXQ%u!y~yFS{&nXumRuLGgga%X}LQ_Y_#2BKU`m5wAkeG;s{#(k&kbA zXJg}##p0f!YZYAt0gT(d|{Lce2sJ`E?+XucuFW36FPs@OOZ4_d`zSAFz)N`%nuXv=MO+e%$ys@E{(rkN@!<+wOEf0^zqJ1J4drBoe{K z#&v3IGszgLyf|k1Ak>1{C^tqe%&_kb*er~5&CA9HW}oWjAsjUtx8IR`{G(PU+2M@; zCS!K;;}!b{dn@H66721dCy=%3r&1pY>`?!>@sES{LGAxG{=q){^9R$!W5ym!$YbK0 z8Sfd<>8QKOW(%af(z+t)Pb_Acx@a>+0Me(A%7E|(E z_V~Se`JpTp$#dD80HrphBECGIrS<#lk^C)BUwBz=Y`jlfbBzH~s}f$y1SFY5-Y~4RiWOhdJ}QX@cG^9fYjiwjdPWfwqL%PSD&2c*31p zYc>DE*%T@kZUDGUkuLP1a_F(QIhb)1J`s-}?afZ3Jf#nL zk|?eSy>qefMX{un7oFqz2N5M38`o0-sN4o7XCg8^$_Wd{FedunD$DiEqE@VKVXlSB z2%H`pG14-aK|_&nl0`A1#3Y!GCDujKfGD4igb)TZvQ|EW);k z!_J7S=`-6{q5o;sucH4AclyJx`rnuMqeRBql8H1G4`H@J|4hO}jCmNDf5$S9mB=r^naU(V9Aqt3x0sS{wt1$vJ%pZNAelZqW*yDCV1Z;| zMgZNMy#gFDz0_Z^sg$=&g&1-cDyX6oQzB}b#~a@`bw?3yeg;|OSbj8uvI%UYmBTO& zvsY9WR8vt|7)8+YJHY}TPrw3idk8^xO!2WkgMF?wv!e21EH}Pkfk;Fgh!{LHC_HCV z^iOg0$nrF+2JIl8nI5oAiD-<94cYv3W6>Pqy&zIO(FbQZLzr;PEqM)~`JwK&&rw`|yEz|MJ?*SX*)MXiQR(u=WXS`|Q=>FIR0nt?i>94o}bjq5paG{`~yi z;pLC`=+&mj{`ouRbv^d$um9ghHWl#(V~h!ZD%q=J5ec}Y%Bz9`#R7x$su$qV`6>JP z;)o?tJ_+MjKx83jck6J*{!tJBh{IHDjKdA$Ovd7$U;VGRI!foiYc1X?0I<)(A-SYY0@9zx1+W)@DpWinaD@R$g-(mZB5mZZHAK+h%p29DqJdCo_ z*gIgoR`E388Ao~3J78YBZ9(7KZO?fPeE{A8#05Lgr%-3D`ZV-qd?X{8YMSX}#9wz? ztl#UkSbs2RvEHUj8Y4ZJ=jN;bD?5xJ_}h68osF7f17k#V(i8{wo4x(+xZ8Kf z=$;I_`d7a<@O!&KV5yQvj|Z#=w&a{Cylf`B8+*65UQVkvX4JGE!*H6825(u zqR8DB@ZfFAgAg*pSuq}yGz>0eWk&Rv4cuAKwEE722bTt8-dz8?#>F%Y0uf({G;A1g z7`ok|{dXiL5YXuI!S5#3?_g{oV7K9y8GmSc8paJz)l}ZsH+m*B9yPp;Dx3MC*3&4A z;a8U$JiHGBT!HRWXScwk80tBOSnF0VDE+{$GfyVvBaxW}duB=17)rP=nwEc2E3Y;o zU})A$BvU7?om(jtcwL4S`YK+FAY&L2YkTfbQT z^tWQ%)S_OhjQh7Wj#VbKynYtO_0D6VgC)F*hXlH+^4aT@XW}*4vVnDVL+6ybfd%yY z?Vh^fN%Gx)Q_R9@GWc)r(}&*d*Ue2WJibn3(1IAfXp{XL8+OYB zF_!6!>&5PA(f9@jxBQBUpZ}g??OXRgv^(p2OXv6Bp|MY&%2ZM@hO59k^p=dd%_XR; zVa?q4DI8hmF0s!q#e^1c<%6qfIL_){WN=A&Cor_^Um1D#ie7t}y`X+~cQj8$P~X!E z$~2VDE7;CA=5P<=AiN8MoJaMO+q?t!V!^-zEzgoT0TS|Dq)?UXGw)WWRO4B9wXXdiD?&tLh z=TSImx>?})876~5b0x8k24J;VgqNT9jXxgq@%XFQv%c8V{hVS?>A_Rwp8cw$b?Ay%6s>aOC;1H_#5_^V z((+ZW``HDo+Hg0DRtqN03Qig==6`7RNLOFLzuwAiaii~XI7 zv{*Hg4Qgu&D{Go~N zU~gw<_p8B|{V|%)-ioC>tTC}#@9BTld%o&Djr)C>8uTuVm%jc)t>}qlYgg4Dr6g4Z z;->R<4VifJbIZT0hWV+=(O;zd3+~MqQH=f~L$GSQ|LGK>GPCRrh%R4MqGzc@qtYO< zuL{v}K5NVW%R3;n5T6PKS+AutYxSQJMojQBWAb z_eB4z*!<@Zn|s3-kem1Smdnjw4cq@agx}^P&zh8reO@}2{>;J56){LABEA_1e+tQG z!Dv3kVB8?^{h4|?3*)U)+(o&gk1z{2=tqC1j`F+7vW`Aa&-pWTbjBZ+b@cd8BA~xd zM2v9mCdo|8E??#IXUXS(61n%QeE!wc&Fbl+Z!W$!>Ua)8e^hi+#94@F5}BB>F!rPT z|Ht0H_P32AeZp|Ree@~NOm<@TSh6Hb^5NRduG@CHy`4B7+sQn0O?tHu2}u}JBtw8c zwA=I9?;j4Nz?06FC>ef{*d&N!q3U0Ss)7|>yeSgt^V?a%bg-Q;k52hn+Ik_7Qs1j-kRnU3HZHWb zpQ2GA9Gi-fX;fh7@#XpKL7{7f$Tks4rO4r679iEEj|Nh4BXfdX3Ye96n2)mh*g|Im zk3MFn(EM-YyXiNx+NG1yX*SfRa29QqUJrZ+?|QLpdpsp@8+tf8^OuG$kq3kXgGsZ1 z>`qaw=>`s+A*UbXa_oN((*BD(96UXV=ANIy(-Uj4@cI3YFVFe?Ou&W|Ip!nSf-+Xp zaV@m1q3fJp2&+eLIZ*T!qf8CFiUqvVCal?z*WTR7YjOkE9MCKIP$MsmyzjKBsyAi=U1O4oX>*qbUF!w9rZji0D>?!NhevNf2#|=jNyR!m zFFJBPjgK@w63;b0%Ed=1tJI7DX@72jq^(jKAQcE8O=*?V0BH#TNt=!|IMU!qgQI1E zqona@Z3#=Y_tO7(GKtt4Sc6<#^gVEDWIgZ_WTUCvXIku!J!ia zPGT5<4MQ84;vLo)N@FOEp_Xr8nh``zmDNOpC=H^D4x*CRyK4}&9w3SY0}!Q))F?`$ zs7*vss|``yOXo%AC}3X+C?6G}D6+*(5u|9k4i#8n73!K@!;Lk>56cz~C z#Q^%ZmV56Q={f)T@{lqV$7tC_P0dGsPw}*27J%h=;)O>C_;7 z7LXp}882e!?0DTac_b#Z?Y0&8kj?Jg2;KFNsA&m^JZh`(fdg;C^sw4FPNVLX_A|8$ zR%W{_FetK+i3gA)^7=+2rL;YBHmKCpP)S3j4T4HZe>n}6RtA+8m_g#u9e@OQNibd6aqysI^;8Y}6e-&H}SCHT*c#7fiTy8s%2tptH7_)ASO z*3;H1o#^6~+Nw0vTCtzqj96=les&r*Y1s5)CMFG=))Y4BAWsdOG;9(NHEdciY&uAw zrlf(YS)U0sO_dElML=_;zsP#G*!YCxJAF~>tHE2;^=`MCJ0QzkHGp2*^+=m9{3L*= znFvdOUYkio6&fug|AlOphajvEP#QoFxSsZcig#FhL1~DjA<|1jq=Uskq^S~wX^5mD z(po{JEYp;RNGpLz+J2FJQ|4mNquqjcD%>)6BbygaAh;T@sa~AQOGtW~#107`sDvkzA z0j&ub`I0lOecVcV^TyE&4FJ#>5l|Z^;H3= zm%rmC1T^RlIh3@&2PjD1LRqY{y@`R$&jkT8XMARXk4%K`kfn`Du?}lr{EdV)uf`XD zznQ9>LjW}c!c4CC;#N!GAbRimw*WhWny~9E(mP+n%hkfm{aMns9@G|!E;UeG7*O0K zOItFUv+Mfz(6(}Ma4uNrX;@f9Sg7Gh zvEWGRlyN3JQmbh|@+tsHHb3K=np--4xjMVPj`OpSmDEPCnJ6+ zv6B$dYBcT??JTGsl`YOY_NcC8-!ke-p@fxOdxf1)Ct<|wLE3MduES{1ylwZ)wv?%v z+6keM2IT!WHvT)ro^;^=+mG+R8BBO`1;%%&Yr6LPZ^q5ZWm=^X+Kl*YN7OgFsWx{0 z2WC)lQp=X9*yIp_>hrKMQ##?qF&U9PaX(K!aRd19>LxD5bfSqnSvJK<-nBMUmnpBJ z={sFE-L2{LrNv$}g=YmZ=A2*NHNZ)@AY8%J)|~l#vx{LT(e@l|&(ZcAZO_s69FTWH zI+H=CRv(iCLtAvTMMqn7rmIU^bnaT(qO<-}x*-;w!cJWAEjopry7jQ=6n*;E!=lsD z79F+2+M=T^I@+QGv_(f-bT-SPlk(6>-=;K)LFZ5#bhJT78+5cm=SAHjq%74&opqen z4KeH#dh&{I+$r?*t%reU9j0(Sj6AB_&V|&|w4p~EdbFWO8+x>%M;m%J$YK zvo|J%y0-LaOOLknOjnn-^rQ~0wWVi`r*%UtJ%ygU;#+zOJ$>t8=~;&FE&d&)c2aLgZ@8Cvac$Ep@d=BYeUQO5g|FKD+@aDe1!r(ZGUrK8ah2a ziKYslr|{UeT@x~tcN|WshD{nay)M{f1p}|mceo#Tlz>RR8y*cI*lM)mCn%#n5>Tso zP-|4pwS-!0ctA4!9kVlGs(tMV`zr8JVc<@N)rs>S9}z?+&)uxv#_A&&f}tJ21mqHK zr(n(SYs^^d{FgO>NT+iC6$8_0Fz~mII zh?-jucTL4eq|Tk=TGJhjy*Qv!r<(U}exJ&mu_x)Ku+uP_;tF@G|B353$fWoV(?{?t z@4H5u+VZ9GrpB8~w|v#Avz*)QX}tL=@aF0vnQHm6eAkOzAs<~~`u>}|K$anrsZ3!$ zf@CRHFws!qtzf6V%N7ot^?XE#zEWNr!(I?E<21K$5oe-Bt+t#`YIr40j+MGM~cY8t#05aaG))3*_O8(A9lOg)CgrhgwoNLw>3a0!)lJDL&=3J zn4$3o!Op?nVZsKdyf+< zGgZ}cC%Hr%VWjMLS*2#T;!ROoiructJe9IcIl-V%&R%h;FdoO{tW!p6#^R1ShnD6{ z`&Z!cX7AU`Ons@Hvt;w3HXLeyz0CyXrt46Fk%qZm<1l!o*}`&hX)S?E>x~31P1)dT z=~H2jJk{&=)37SsK?CUDTJF7Lq#4AeYh&}#NbOsS9;lHy>ABiac9Q#a{*)<_+>81Q zC8>UD8not=(cTKI#IlpnM?ig(f74D zmncX-Q{=BbCte9APM;>s1d8{@~deVg=`XcZM^${FI zs21~32GzXcm2>eOtLLewDQw8<9XZ2zQ2=y48+HiSR-R1PXn)|8zbx0 z8F1HOV>IrX#ET>M(u{&Rag4k;BR)48u}$N|k;mC$ta%25Wu(v7m1JZeD~q89j-^)N1pxICdhOhi?qo^P7BEZDPp=F+6KEIWg{Hb7Dw(g zw>C3CH|D)&^XZBAU?Sw6LrodZK_dydNPZ;w8=!EJXqSxqfRBjhIs^gs0oXde>uqZV zW={8#)vEs;P1ZgX@X>-61p^2hd0fv#dLW#qfLXM+W0eOgpK@U900JB!segBfxF9~M;8uumi8!732x z06Q^6N`2hxA)kb%GLiSHZ9>~_TY(Q5vA>idbE>viWZ0Y#7^i4?R>P%Un}x3plUvzq zGi5ZQUYo`5o20BMoF}mei~=`e&cUgiU#&@QzOlOyiQ-bUzlokY+OKBajPA22n5{8a zk7~ynt(nT74RI4mqQ=+mCNf1JnDdak+%aN@RgVs0T;QO=wnQWQ85&ZFRp{kA3R64$|0o)!4X|fX1n#m%UlsQTE2< zznCv^V1gsfij0%YIg{NHY@vThFq`0y8Z&RGhf5q*g%_H(k<)d36Ah3<+k`?IOnw)u z^6B*Ws-LOIasEmu%-9hLKjzxp7fcL$U-)|^&cf?wfmlAEbRLLRn-sjIH0Oe#w-k-c zh~Lz86uc~YqLa$KB6t@%)pYi)4(wz&&iK6!+&Vbi0kysQ4%lz)fNG`L*v@jKsdt^sd~E#+z2HVIA%zaCrRl z>>|>SN_fGy_V=pw1VoQl(mZH1_V<%T)JnQ0f+o~xesVNlUm%*Fz-?hhJYUy%UgP;m z@O;D#7KG~;TA$#Uv6_mS3VA{=^%+m>mvYZ=?&`guXLyn4BNXeS=Vb97*+rfc6@-k} zN)|I8oC_3mJ~B8|G!v&q(a+-k;8%g8bu@h;_p8#-!ua5B-8_uDw}fYiDM#*f8M6mAXe-RUKamV{I2I1n4 zcMTlx~4WOgTt2(sn$K z8Ta=_L8)*D4WNH(x%Vm~NCoK|sjW-VgUm5K?af66Hv3x0!~8bqA;>-6(mC&!`y5T-E{< zQbW}Zg2};VlmtH{8Vpw~NlD{vMGeDhvna1z1O8Y?4F1C?Q>8Dfr zZ5~$Dm}xCAQ-&>f7SL3yY1E`q(>kK2Lyel&1T`IM)TDM;qo&PAO~Y!s5ZgIXVC>ay zbX0y=?Z%UDkiay(`x~+q~J?-E)F*@6u1D#DDIM$rSzp-&R8k@}m zzLMc$i#%nY5nt6`H@?c|rNfjJjDf^h-3&orAuk!h8jEl@cqWLO;#P{iDiMy1TQVkP z7JwEeNX|;0JSBLOy;x89w)RPnSB})yBdEU+y(|DyvoJAT$3Z5=j=VBFl`_po&|>mj z<~OeGfO@^U0}h)!zi~a5-}oM4R#Ta}2%mmh&wb5X0Wl{b` z26J-5A#0-$-AXNHN<41_rwD}y&t`q>g}T=51AkCsmO?18Y?{ECQ)qj;wVOJ*<# zY)J84MvDAR0!sxk8I6TY1?lJV0MqMnUTdYJA%ycZqNW z?1>?Jh>4g`c+|!U!dN}XT8~UjNjsxC0|3fLa>8z5G-X0+i%Q-z@|F3 z&O~4{omx)`z$S9-)aTjj2f$t?>PTax@L@qP(i;=nHUV2C7yxM793~NslU~Q|H5w_& z7aA$0+k1JWlr~n)2$foML#3q{tER?Ei?LN{s1#1^ra&bwvu6xQ8Db+J(ZF}wX3Q`G zmH?5IhSvxwX`rNm(rWvufzoCIrPes0lrkwD)Mvp-`}JvX(gGtPUgS_uqoI*#sJ_8y zDDoa{qdVkK()N*w@Ex*7U?TKAfcE=u2J0UC`wrUJQvS|LrA#u0avdplIzu zQ3QhKFcZm-H8x6PBWW$V(6~t3iZm(`FElDjx3>x(q#0q+n8XDd76A>5HV+nQW6^?* zMH&)mNTeZ=e4!yxy1f;oayp#p*7)iI@~%$qmc8O@<45NM*dS!IK~C1Gyi6%%ln;nF zs(AlR-t%;U=)LRTUb;3mAICdjOBe)x0qS# z%D#({NZ<4kqzDKxXuR34TAkRf7lwswq!d8)h80hqA9$8p1FCipt$m%_z8DxQZFZUs zWYxx8|E@un23czlvNXI}47}37N&~AU_frEa4Xl<5tdhp7dUbCWTvgS$O5>_c$5odM zK4~;HBbvH&EsdcxhSC^HW2gw!@k-4x71RIAPcZfe@SNrRhB2RGNqzr$u>@lC<8jhsCVZ#2Bo@J2k-@MihO zo7wP9y{hqz#y1;|Z_XTx&w~ayGXb1%`iO=&8scb(Bc5r9vwREAOn2PYYZ~EbgtOrY z=K>B8@4ALKvzhB%u9aZ0jUw&mDvQfn}X*+&ET75N0atnPYKJf@FgS6I-$ z<rurE2F*{PIN8yw1*y&MaeDpzWDa_ zqhn_DJmd!obWCo@7=74LcZ7VX{A6T8me^(>$VMjRye!c^U*`wDPmUFF4$?ex2Z9(XW512f{Q__3JyUxqM{gb<^MDB^DOuc z9t>&7=nBzqIPQIUuNul3gSzse5&O==<}F8o@@qL`?GVYR;>@U370JJ+{!tssGoz{e zUQ_=V_J+MtWO!Zqy=DnI{ypqB!&(YajBQ1&xTRLCwo-4Xe<&%1_ARx)VP9fX_J_;i ztPxOCa{qYbKKO*Fk4-T<;by&~!9S=K4E_*L?;@d6D?OKfSk;f%Kf7IQBeE<0C?n_2 zecUygp+5A=;#uVp4(ut~s8*}hR-?iHuU4yx|Le6{qxnOvvEOJ^_x2n6 z%^#}udZSwV0aRab+|f@!DD;1*&fQjWaBK48xE4Ap0f4O|VDw!=|5K~)SE`k2rS>1k zEo19HwrfJ$at9DQY%iF0Kq&G#RPXtSkg|MYln8|sn^#E4G{UN7pa(g~=YKpsl>zR8 zieQ=*PG*&%h^rt6c5GyUXU5*jfQg4AVDMt)VX^W+Y_4)xx7eZ3vRH49>o|z3f$afwU@sgJ`(c7X+O3XM1n|E@iNXG_^jx=RBj{mLG2OwgXbU}1s^C{UM0N5&D`lyQ^CSM%!9GKChkY7A`&XAx5`Pm-->`|c zY@*GpGh)R75QLhjh1FyHlq|}>&nP)%ivSEDHT%hWI7x-mv@2^!f6J@P`gXX_#B!FQ zH4r;6yOk?+?_?+t%`G~Fjhd7CXd@^OFE4+(-yyYCS1hbQ-(i9`Zt5l;L zk2uhldpfIe6I=cjbb85EO)wtp-8JIOMx6-BA|ev6r8tE;?H`eI1P;bkv0ty$T4O4y z)yLIx$Z9zlS50eNH6ec=QORCCHGjxS%~g6@Ta!=g(b1?5)anQ0dqAj<;NaY{(G4CT zH=vBIb83$jPe_tJf;R2XCp{Da5hJEQ0jE*_QJrQnR`4hI9=H^#Ll`A;L^m%LX(Oi_ zI#zb$qt*dh7S{ly?SmqL1(T!98N4by6N@+fIFz;2LUaUOil1?Uv)vydIYqrMCnvM( zpGYc-PybksRP+(F9Qq{Nngy`}F!oypTL@ zSaXWW$4guz({(HYo}VT3v^yf#&Ji$9K7P5rIlF3KUVZ+0etLE~Y}z^tcfzIbQrC3t z&%)*t5^!q21fCeS+%b~x=6pT%Zk(w0;kudbVBk6ni8}k(jSMONJm}NHdDt20y+~6q5tJQS?kfl=%70? zPiv9z)QQM#3q{6QJ8tF>pX3$iXlIz<6Urg06@njfc>P0RA8j^(7!rVFHKxqQmK;nP z9gcd54zsV*jBk~#ICZvhwlj06Er{D@ILN@BGl3oQZzW~y81nyGJ&zLj68 z4eO7#9A($dhv6f7U?!vd$ic|;F4wu;=aA8v(zT+lL4Gk8JZgn~-rE>x{&-y28L1NY zntc>~WhJK91);HXDn-ij^2uK10Fr@r@~{ziryT;fFU!FS#hL!SX-gdvt6%OfB2xEs zsww2i^H6D%wIM~YTgdcXS3%dScnNufV}UncpL-s~9Qk1^6#Nf;jWedlpij`Bflz+j z539BKznjH%5oik}k1R1Q4iHcnU>%es)T9d-lV(&_Rp8hExY3j9V#sqFq8#7t4wr~O zBfMHIiz{+jGU05KFZV7;V~hwz=*Kk>J!->qN6u_3%XbaC^X6q?uvuyIkE?=^5oqck*m2`{`R_Xj%~(2$UmQ zQlCrAJh0oHyoZI`6=kc2!PcZe3!?j_1{N1;%y=abQ_0*dA8>@+%w$du zsQct?@+mN`sA&Yw0TzWqJ*m6=kbh(v_v<5rNBJjh&|TVFNBI+W6YE8FO--a*_E2qLIH8- z(<3g|wk_-2n!SLQL@bB&Mt+C2v>LqE^`BjRx2@`8J4ZmAnrcxSaJz!*_u8n)b1a>? z(t+;O0c^GF$w9&trZ3`@a*jWo*y? z;zmEP&X`|uO&B@15X^b%(jmDvEIc{ny`yTL*<-sbsC>3j5GU0Xonb>y zj;5?`z=;zCdU$oC2W$m1lTT-{6SvE{b?=ldHhsUM(1=#&oj3-W^iBU3pMDV8 zraL%S)%)ijQmxt&yiF2wgJjW~$_!-oiZba;T_4}w)Sa%eJcx1dO5oHDJxS0KRFDGg z&NQVP)>s!)gbQ{hgD?pgzF(hKx_i5QjEY&K>ynJ5^1SCkyo^3_VL;v_oU@N_UK?KJ z%sf3S>p#4e(Z7uw5lDehUG(x}dkCeXU_PhfGDv6A#4;yjP~Ef;Af0@m2+0p&y-YxQ z!hldP-OQTp49@b6ZLq@Plti^w^Y8nqhCu4{n54MjgiW~rZ+;r3h&z#r2Lts!YvJ59 zEyiX`^m)1K5qJ>UNPc}dAl_?5;J2P{43A-*k~!OXxx=w*)}{EgW4=m-byZ^`5w&)i zJuw8G5xrvx3IKZ%ODD33`ngL!fiJ8Gb^+Kg;><(sw5Y;>bwJ2cWAn4mdC~AtwZH-p z?)=ulZ_{S&_%aA}x^l3fD(H~d)WDE1(ixdhX2kSL#elZ>tsHHe&_zHy0O;wh2t2~Q zAhta<@5YT_O+)HFpnS@q=Lg^b#4Lez2g=UVSv4}>{ z>5kUf=E(gzt=0j)rxiNz1r};?0fN1|!>i)BsVw`#zIw30ECIgL1TOAaeiI>lo)6lF zNKyPc;1J@kic??$58}Z?1V3`s5Z`eICDFat`a_&AQk7_;5G~2cO@kFDEPKy|HC{pq04*=qhl?ELKR zmE>BDzDu6`-Hh+V!J;t#6;7^b{4V_+Iq|Joy@>rNLiBBGU9GbC>XUL?aR1$<_qE-b z_2=&U$W%d1t1HmytD-Q=&8RO>H#Wf2EI=|&k<2EV((^4au&=YFq1U`p;~i)!_owAr z1AGc%7WLnYG%05m!=P9qFd)B-BcwM|5;bUr5O9hBD{gR6t~Mw0Di2yE+` z(Q8u+P^+ug>AoHPvlUWE{3~h~X#_jw|4zreJ z0oDWH`Oj4k=wLfZ?K}(h#}2l#f+5mD2y}J>yb1R22(M@?rzkc4R;4#;y8-9hg4+UU zEyOzuuB&}!-`?=QSdb{JqQ#`~(T_)zyk_IjO6wz(#$7wD*w2W?v`nE5l$ewNf5yPb zTlTyb`y8htrW$V+`W#E&PQ05gHZ--#a37PeNpe;QTCpsf2n-&DBR2@hRJfP_SxYiZ zn2f7U|0m9)6k4q)?H*nfT~NFTU_eijS~T)&MrhDjq*VMn8d+Pz5KfxhW@sHn0L3K_ z`APu`9v70#0B;1C|jTub10_rP zlD&BSpB-Q^lGx@+1{iFd53EWyC&zUe3TvYUuSB`G=v>k3tkOv>01O@l1|CJh+}6=* z^(}de8MSBCg9V1-nk*owzf%Fb{knjICsWsGSw5#Dy8Jw&*17P>8F}J<;bBc1`zcfi zNt>J73YNh-bAWl57pSBoOgK(l&K=q18@NGZF zkHL#QDl?q0^hY*p##R>db_C&d1V)O2k5GA zH+deOSDK;z4Mj2i1^i*_ztmWC{PyS>@@KVh5KZhWY+2FlkT}gw20-x9sLp0~nTXNg zSl-{0EnmmNFqF0djHv}YL-TXaGVmS7F8u=#>3DG=IINS__b5z7XiNwb_2_*@A1oWL z#W8?JMo=8k!rb1H< z@3|Xb1*(g{VSRdXq8cLOD3r@`BkdcHZn0x&4!Ujm_olJIPu3DOqf*)mCRhUN<>?M( zVu2}8g9=KSy2o$Qk2UXK)>K}V7QV-wc>CHUjSwtRb^``YpnO#_pg79m7QwtgYlDIu zK+pE~-R2d>?Wv$?JgPVGPrDXgiB%=7WFSP+-K~hfgdfqi&)=1*P6IgKnJ_qYRMpef z81M!I2Av|iGWa@^s5?#ozokm}t0i?6yasmI04um>A)JOAo+V8bH`9|E)6<9p!#qS~ zAiv~$s(C;%TEQS%fjKVEbhC(uw~yq zeQBH_tu2MWoK|9qmktpQ!Kfb=9;Mz?D8Rus@Jt( zv~Ob%=|OzNq%r_C5Uo*T!9reBkIGXbYLcOkwGmlIa&47XEmiX%e6l9e|O5=@o+)X1=-pZ~%>3D39gyT6; zuxyC-Qk~lP-r}>PTO9z?baAqy{_K-*9M4(h^L%phkStrSd8jvHLFgz;&T>(wAYwJ@ z#7m;HiLT>V>`8kxa?I4;GXsk|G#CaE2SXBMZdXn)AT8G~NQ%oh^K{u^WK4AXUM@i2 zY$Es3^;XXXIAdW0bLmE(NFw2M&7sqJvyz*V-G@DmcUKy**Co*jaA9z4Vj)DbU-=v`lCZO{ zfo6SS=cBCJu$|u~S}nf1Jc-CYMZ#2KVJer)MW1atl{4DCK`xU6_0AnLS1V#J8oFl9 zC$N{l8chKxZl7!z1ZU@xmqWQT8kPbWYje+IW;kzmLz$5s&zMLqpgR^%50yI*ZAT@v z-C71-y^YNIOG{;w5L1@ns6%ZL7p(R60tIFE{zK5PwW{_k*~GVxhmNC;_@yseg!7Ly zcKwAJ$z^ng|0qK-=J#A22dydbh-9}|o*O$B?_5TY1y>Ape}MN4Bg#d|WMv8yPdCYq z#FJKpp_f(RAcLBueddBU;vE;Bvr~TZ5FJ63Pv(HOA>>Wnc#D5j-hfBmQ{_+20o|&Aj$KyC<3PEh&;(|KM-Wou1KmUro4Ibw+0OH2j)pSf zd27G*!9o*UHOtbDd+Gfy4IBFM&b0xhUx+7tj||^2*GpBmLN9M2^|15I*(N`5uP8_>nW-^yjhzc?oWprpLP^B3vwY8 zYQ(U`fz{m-=xUD|5XSkIwg0#uVyPu;YM%$2tMPIF7911u%E>8OS+72MqMiG_VjN01 zf#)#cJa=utV21H)zfOdD9qHezgaJW&Y$K5Rwyj4M`!851AI5M$B9h(-z|YWIoZ)*Y zKSuRkosC^HW6IroutAVjCq81WhilkNR;pPSZOMJhA*et9AL=>(9C8i^%{SWBKgjeS z^90E?^pmX$C_N9crxxky{Wts3D4F%`_z}Z9FyC%Qw}f4EJcn3)GCaV70P%kysNEFp zJTV9DL*8t-)B*9@>MZ0?jg+76S2Zmz;ag)qm zo22G!+=m)sB&#MNBvM)<$fTovDGzcSvbtFyXmHZR2$2j^j((moOz#!ZYy~lEE&2q6 z2M_uaV}9O!)02ROal&>61prgQYBpl~jNfVSU!B0quXyjG26r`cr6+Q84iDv<&_}yD zs<_P%jUtUwnYoZmbyEj|A|c_)?Hyo{(`EI)_{2yjY_w4zP{i+2ASR@-*8kB51q@~r zfOz0?bf&%zQ7B#A-Om;Ra{}^tF~$M+(&H5;TpO!B8MYtyMA?o+2j#I38~YF zolH!KBj^`MwDrM!APAMx#e<$TS5M;k_2K{lWNiAU;V}dJfKgCqg_)Z1Q(@s)PByYI zF??>JXL5f9oRNNdx>-R)81$tN(TT3&$-Hb;Km2cpRFP@^M8|54^51xV(9-v03U>W< zo~K?TUfD~Z&jwP&oUZuMiJw0QFs)0xMrX#F>%4~xn zn>l>YQk)?MTz{0#3+#=~W65x3w$JI*%WPhREm7S00C#)@GQq(3?;h9$BYnQu#N4V1 zq1i=2r(`HEa>3Va6u5p4)MQ?PwjLj*jyjIb=)pF};O1;~1ZM(@VsUV!Nk;2mgvThY zS_v#@2H7zOoYtg-FcMZHml?5y{AvRs;R;Tcdk-Acp@m%;$BXYMw80ro-52(&4NE^F zY}stXFK#*F`jz2{cg%w26c#4-6+>Y?zD=iEgohaG4M(F=i!$HC{`d14`hH?(Md7xU zCSH%3pUclAKN{x2(@ei`WivsA0|~~`+)`R5+g&7{-Mn@(TXhfNJMM-G$|qYfOP`qA zG~%$81YLA=75Oz;T-GTZ`q7>|7Ty?+cSE2K*6>~S z?dsDQfD~8%G!QT)thbK2!AZ@Z=T@G+ZeZ)tg$?Ly$Yxj%FsuFSow>-|-p_;PA!&{z z>zCNHVO8EA@nZMQ4#~2jCY34{*F)n(88Jqv5!BLT-Vh~)64p_e2+MhB`Nd-N;2D@1 z39T%!{oB#wLQ#YV&tl zjbo03WQP|SKEB)=^A!_W>$Kzibay5Im_&w{EcT71{EtH@IAq#EFFXf*KEmy)Wfe~} zyWnfhKeEp2*NE)aUA;a+&S#94@Zu^i9Zk?hp*zBavA5+&1S3YDz#&QpjRh_v`WuiE zQ7q2}U?pFd3x5Ol4`vUpI0uoW?4R=j*Jmi2b5hVG!^@|jPJd;2Ta{VOK_FQJ&HnFY z^g_(fw}8c0$`}aKUZuvhgoa=ZgpqykVY8>UX$j0`=#qfQlFD`4{5=#^?uaj5-gX|2 z^q*tFPy(LUm)ycm8}7{{(stcjH>R!So=;IEpho%C{5_+#b5d}6!wN& z0k{c1K}b4S-0%-UG+*MYIi_e@7zsjwpSgIcL{#$Md{I}n$b^KL_*+L0$lVAfFzvO? zxfXbi5vQ!WAP5_xsXw^7tV@rYVRe!hY(~ThCa>IMO?WR7;!v4x4+UM*#!#n#E(T;T zi-w^;g-BZeI;ZdZ-pHW9N8vBAu{T&LJLu?oWZ`eu-*kB;blv7%K+AEERs?;9@Zc}* z_`pJ}Rll&Ry^Z8{MrwLKLYFU)CZIt<9oUaaJpaz(oEboh`leC6@7dW)0_>WNwFVGk zrRb4?>9a=^7$6A2i*y3PNHo*qolp{f%P%|xD6nrZ2StN>ol`w9pziv}Ze}v${*e*Y zIPGA5O#vLnVKrQuZ7X?)H+MrArT$91pVuAO2lD_$*I!(Xq)m}Z;P!xa$K`gHE&(T6 zkg90rv*5;E;{7{n@^njj;^IH5rnr~XJqX%waQhV&>cf1%jdqX!&4v8TOLoVLe4P{e z0y(;lw!h4{wC7V6_kD}>33%v6`OfK(qb7#zX;ImqY}lI|&{Vz$9{39~;0RKp4qT@~ zk&I37BeBpn=Y;5+=$#XZw-9!lxt9Oa?eJkCk`@?6A(+?0e1_V*>){m~l42NBcNTkA z;!PO*UVlI2Dbfke9?u%S`%(1QXdB2zAm|ytx>c%|G~UBrzD4R+=Wf5pU-Tm>&_3xL zCXK+xOoK*6t*Gf#xXBf`S!KA%CAib*Y=s`2yq(@kRvt1(9y(n18BXiO1qh{CU2r|p zVfb>&f+AC&WDT)3sJ`+?Q?eE7_tiVM)b#x36}8_$5;P_u=ifB=3Od+ zH_2ixW#cYnqtEd$=5ljpdKm?}2P4xcQ>Ud+5G!~YWx6vGWYO7i;c&;v(o-R^VM5@@ zJJ~?lc_)h}4Umm7rX@(Vp?RhJzUK^t=q7-C4L^3}IAU#;c7*b2U}2O&#eCwqp5eM4 z;X3Z|l=2*O^mlNS*%!%bi{f+~=e8eb6UFgZV>zp!ah_u-^Se-N`uN-Q0=<6Ss+j87 zRD88J;n;Y5t7)*|wKIw&iEwT^&^Fr45%I7Ne3W$^2jx-pq ztIdU;&-_o1UltlDCM~80lN1$}k%;lvu>$x&Zy<<)E-cjThcis*?A31w_nnXf?_&3a zW4Aa`Ri){On;24wBwQrurbI2n3myXAuj7o_ijPEM-yh9yJF^kb^ysH(9=A*EI;x>x z954d&U&vAK;Y8yu=HL|#;Jt;*gWv(H;F@&sQanL(Tn#!e6zEGOhP>jS^>4!yfYGL8 zYfBG;vCE2U3dYVekLoTZdqBrM_Y=a)tMWeCbx^jJ0##9;&#t;bgHs+ znj^JwXg-mbnJv)DCwBv5%f9*vJ)S=cl5bu~!{&`Z1#L9=G%GT6$(} z_DJrZlV)gJR6^@N_L`|>owjhHS4g*zIgWc*^ssdwAnS}Wz-6AsagE`#4`aW&q1V<3ZmY&ds@bf7l%xOpNkvj=CR>eM{ z7E@f<6?3?y(&~nZs~*cOoN8EX<&MN3i{*+>_58LLL?Z^jYu>$MX@6Na#s?T3h8bGm ziRMw zSwO;%+<)7I3?Cu6^CKz7=BK3=-jVGM0Cou=VaUA(qWSse4MTva@c-K5+kS zU}7I%mADQaaP9|jG5d73wt|VfPRi3pt@+36W6h!^mP9t?!VMSDQ1rJsur5Jp$Q3g= zkR)ywt*|Q`m$?N;yDMvQD4gfh;PyW!WLJ1Qt`HA5{_2^3(ki!ZLkL>o|B`>uTz~Lq z>6Rz#tNW0;2?YyaF*%{dUyy+^%2D_62C1rN9`MVyw2rWG2wrWHPqBgL*MHH>kiLJa z$%87b-No62z-6F)&W;)tIe$a{O9~S`oy@*&>q+p%bq7(AFQ$nk{ zKis5|-!z)WLr)The(WL+>{WeJ!?+~Q-8L?ob*@Jp)bv#b)D%8*8J`XP&lUwb?=o6g zj`P55`M@+5`!v2i6L|bmt*E4&YIs5RFA6;KLVn$Hat-d;voIA|og{Y!qff&_k@rrn zqJl25B0$Q>mDC&OKwUN8BC~Czuei-D`L`zuqg{IhrHZ#qUn@$8N4Hvz+5|2k+e!DrR zmwFN^BWcFf9+*qz!7h4Fr;tPDK&=k!fr|oQ937b!R|33{+!6n;%9lg|VKU4_TadCb zReSb*J8UYhc{oqqn_TjwaaF8*jM{s5<5lwz4ZzV+6KSVj4cWu9&$zWUpxI~WWoRbSdO zEX^=8ThWCp)g4_cCbaztW~Kzus2kEk?JDa+?^eDEowIw{F)t#7QVsUQ6VSb2g?XZE z2fq`n<}@1JM(DzHGUzT2W$y94x*c5N-P`QSi&;M)=vYQJjge|*R8D<=capUCUM369 z>#JtQVnuuC+B_PcLpUG)C4Nc^nbbTGh4bfq?{^M1VLOz{K?QngL3}y=A{X+qx|6%c zC=KQ^s8+RQmic-=$KN~MoS`23?h-wDN*A!N(of8meXwGuoiL|tor{; z|GNow0Tk;3#y{2rSB%Y+0&A65R{JalYo+oZ`Ja}f$vHY!|MN+p-QB@^&7N= z)(`|lAn#ky`Kl>CKr;bFPkfBT2V!C@MBD3dOd{?i!a?Ei-n08UTp{uK6v zoFz>7$Jv~_^l_7j&SC!Xku2!;E28ZEF?J|Uv6U>e0A0v8Zj1*5Ttw50|AP`-nM8J5 zYyLl>1l8zk#`Nx9P_Vh`dJ`TIf*E@)n1m_VQP8#lc8~u!LVPwaYF4-D6usPxYs<*k z_(1JXWgI$VvXv?;+U-Xt$uc*FWyY*=M(JWnp=vQ7H z*b*pB~4d4Nhgtkw(?07~H36Dw7KY+w(95j8dAEk@do$Z(=+CTS0GH{bPsQ>*p!;|>d%D0Y$8c-< z3utZMgKG=YJrUh$&Y7*1&e1EczB5nsT`=Z36mJ(b>+m4TxmPo-k)$Lvw;tX?O>aHI1R6q6Dppx>*4n7dilx=1gIK>*a{AlF8Y(9s*@4-#f zubh&XdE-9on+^D7iJf5Zxap-5(w(U;uKcE(I=xhy{m; zbscH05hwSJt~-!GDzJJ_@)r?y?{H~lN*K8bH+8_!kKDG5LdS%LMl#rAJ4C3t|NVVS z)z`@*t#AIyB9wmXS~YDEk!!L2c#B^pn3wf{R1bpcHFaTNbK~xfqC-=oh0iGmYCk4Di=kO9Ib&n`LNv{_`VJN~UB6L!{29;=vtFdk8gy$sq| zmI)V6nohKhPLtZ8r%+BAt~WMkEFxa)MU!U4Pm|VQ6dy1Cn(MnKe!4lqXwm9T+1T%i z@Jn)pX-M&Kz!}HrPEPknGoF~WR86X3@mk1@!P>KZln>ys2>tA6D+pHZzi+Urh~Yba z>;%VQE<7R4612lgkOyb(bXgAWtdLtO;=91@N%#3rUmOH0CXhR7^ADYP zL?$m-IGnnNqioK2B_2-?+07jrChwLm6Tk4aWeiPQyqyGSqJC2u4+K<>$*yllURvA5 zm~X?Ibzt4F%1NW}>5N?_l~Lu;>uaKJWNLx1E2o8i{>FJW+o|$vhq%IOF?A6Feg2^R z1<_)Bo)6JJx0jEclgaTQA+ zlpgsFns%VLQqFFlo1K3nr=Z`G)kvE&lr|SFkQE zEuYqokDqQbm$8Gb$>W4+{B?XD-A1}-+qInN>hG_^i?f#p>Q-nztnRTUE_`PO*+?&| zbs+B4kpj`x&L`vs9?mC2tbgG-B*=x&b;s>^cYmfZJ&yvz!IAIkQAYjaz|xhc!SX?* zNN9WHjEtrP-0_BNVicA#gef&KP5BENDm%-Tni`rK&DWCedJ`#A?u;28XsPzs7G}p( z#mxmfc@{(Q25n_0J9(M!Ar_tHlxX{Af&FE2YWhbrOjE#~?clIS- zci*w3SnQZ!`}62U%PO{w$9RNNu@Yq)D`1y3MVRG^z61un>3EHV>Ct*#a;|-EGc9*L zz4Aj*#v+%CFCkRYbT2r-aW1n)2<-9 zrLHr!yKPCA?uSt){o#6tNsmkEkrChs8y)NNH_7LhwhxnZ;2DnJb1F>gnj*axNbyt% zXu`eB7?ZtyTK0t-)~a9z{gif?UnMc(*lVf}nms?6wG^O1%9C+uzv5cpxYF1Y7jxN| z9DprYhbA+W4paR?>)s-C@lx3Xsnp;-lm39Id^zs7Y>>E>7m?uCI%Kq1Oog4)`It^G z6TzBX(QSOm@mPFW?|M_^ep01rJK1~QO}znX{9Tq-vk3TG3HW=favt@PQ+x6HuHs4E zk5^pG=0c@D)M?aCprq3WOWd<091jr8-d#Dk2mbumkxA_WFGaJ!fx?;yeWw0+C?)w4 zw)uV7f@Z+wxO|VCSEYK&HN5I~d>!E+ZUuc}zEJIsiFML0xtoZ=1iON6&E&Z0GakeiFoalm$^x>OW z@Yvz#aijq$fdwQah4*5;p}!y}w(FtGJ1#%eieHWq0g2y6|M+idY8D1z4ZPYq`DflftRm13V$+g;x4h^1pQOwm;ss06*2oK0ITTmVwTbykt#kEwDAiwv)hx z*IS^a(~sH$A(rFl4?m3`)g=mGcJgaMWP9f@`EArj<%a-8Sy^M>_8$8`D+1f|LaX-L z5+#V8h*o59h8f63yn06Q!u_{#7Ke;z>ESUMa(B~DYer`Ec? zUSBWH_AZVt+CJ}Jh2I}O&N|~--#o8BBH+gW?}?v>_cqsPm^;tgy}Dl@Qm*vA(Sv3} z=5KU95l!|DW8^t>Hqp~`Q&lqSKW}+5zwfq?)@k3YRN-0$Hi20eVB1;*Tu0CYXG3HV zZ!2Zq#jNQvsq`zUf%#&=$4oIWjGn)}J?bB$K9YW$OV$&tZGEb&Ut(HCmfCQaOCxS@ zE-_kOsnGWSSe_AY4R2~uh2Kl4yJ5+#>{xFhiN}JB1-b~|Jo?B&A6YLft#np8k_sfb zgu9BKD+&Y5m`tt4q7{myAbmg&>rQtZAUTa;->;Ks3^`indZ$PWy>31-zciZc7yg13 zBn8jdAz9rA-%k$EOHZ`OqmWle{&~$8dZBDWKU7&WIKXhJbd8|gv*3cYYW055;^OS? zu=Ml~G>4lJsEwhPQVUa@U9^OpyR_~Co^J23Jx)249bWb^WeUS3%Yq{11kyk|;Y+wB z|H6H7rN8mTUxA{B5AYdv`Qri=6djfiF2JY7O8!F13n0q%L>&9Y7VCdET*5CbAfici z9${$r`ucWscAt`QAEC?V*5gX)K%pt}n&H=Z2NZuT3dA1x=;u}9ZLE)#@(e z8=fW~#$OBo=JQ&)G)Ra`#(v?;%pD>h){FY-_ek>}Ds)&SYMA&&dQAGp_3oh{?8+z3 z4U#PJrvU@jZb1Wyhc`6a=M|!pcHQ}@rxDy{%lu4;`hHb`O%C`ze{`pc`aXw``cAq1 zi};1kc}*;6ymESnDt*BrDk5&sSTm4>4K+2TmIS!`2|(<=8~!wkAa%foMQI?dhsJk>7li_wD1aC$QbN&Mk`-@oPy@zDTAR>2LE{rPTkRtMt> zSPaO8+Dd@(I`@>g2SDZ^rR3h92=R1)n*ee*Ux&~33sDY}9qk$2b6C-h-gr+txx<^4 zrqGC#H+!=|cA5vr=M~_%`DOQYE0y0Zw5hm1?ehuSv5E2)`U;#lzAs|Z;Wc(KRbLCg z)eR{UrJR`y%reW{IIn0ezP4jIozz@uG;4h`=!o01#6Cc46jHgtnO}vA#|L2rEdWX; zvFaeNL#Ro`BCGJL{p%-{5=s477a>RK+=U>0n>772x0|x zjRf3vj?hw8?i95c@~0X`PSpu!i)d$yp))e87>#p!~aSM-^CXi6i@Dt ztxFMYjdtl-+cUzQIKD?dSU^Csmzgr|XvC}U&z=5ax&=tMf zbiH0?Jh86f5pG6G;BPavp%@GqCfkkuqz}jq{mvCo{%;p6F+D#KI0{K<|>Bf~oJDuJZ)KT5RW zGq?~{2|co}-d8R_vHwyI`xn1hgnZC%O6Rr7=KI&qnfUBz0DV2`=hGSG&}q}vII1*( zOku*WxrkYJ$gxxss^;(Y(u#eG4Q3nV*pz#`1$0|qZj zh;Xdpm1OVv?E!hs5voF6z*Kpq>yA1Z!sH4p;3eV)qE{nr{egDrYNuMhfNfmdjH^;E za@rhl{;M@Q%-2edy=nsg9d0GUumEmC;i;dG&e;?2F@zw-hyET2 zg7{|VOL6C_w(RcN&lnAXyYp7W3gm^DJGtzCIlj9bIO=8j;#RZ(j}tep%(8kV-_Qu3 zE%Dv`b0uQfHgn-~Ho$IuBHm5z?p1tEuu5L80{MXKz5Pn;_UGlt=Z8(qT5AH{3K zdH7#}-NOXL_$%!EKekP%O^qZ;16Q%FNg+P1cr{v-jU=ibPB`6{UD0a;v=mpqw?m#f zXcXVTU`+<&QD7-l{Y8BipJX)zz_9@=Sag7t5Y$8MC&rkP4Q@DPX&}KKB8$HEh1$kU zf!s+wa3I7Qxbalk)+dQlZqAl9_RchKZ}UwJH3+)t&gQptdfe6_Mr;%O&Ax}85;$>` z)abHRw(_h*YA$lFZWC>BNx&FV z>wTRk2fKMY7nI;BaI>3ma?wg4MNuHmQ8FJ`?)^wQt)s*7MX31%A*Sg?3{s=Lkf2TN zu;u<@OW;oQCscmh0j(r8XA^RWQKqX?3m_%Bs4$*I3F2q5*)TTduYtEQ2yPeA7N$lT zK1^-`)ECg32e_`!l++|c5Qq`|q`x*x_SZ90V&l{)a$tOVh7#6bC*1y0mcPtmuN{|I z3_Ar!P}AoWK-Yi=j8DjKs8y2vl>P|iyS@72?^$Ns{_z%d`L<2YdYNoqv!SysNCE3m zP-9l558gYDqAY?NDs3%c{IZ0q!qAPSj#Ok+Bz$>-Hb!{Y6U7yL5x7tTu}D%Ot$?Z5 z9+J0ElX#uc-&sE;#OKS{=4Osvl|cz48ofN&^CS;MiyYo2yp68M?mB&^&D%xh0tJT~ zc>^}k5ax4P+2b3J*BXD!n+D>Bc^_j&M6lIVf8msz!Bp{drFefxyzmK7HM@&4<%@p^{~;DeHMY41Zqt!Dlr-1!Rr#SQ99 z$!xrAYu6Is!PoPhSU9)?Wmq^<*YfXI!(l7g=|2A{d@}@+zAAdIx|szFNuo9XnrMuF zhzAd2+#tp$OG>Zf1?-gd5E1MC<@~od9-hC{t@InofYVK(D2`S9G>?y-bntDa0kn@~ z3GU3#yo6V94@?G}`YV1ZpB69seJa2eIFxvcT5o&}0Q~bqvT!y)VqtApNoX;4L2jsr zys+f!3lE{}16`2#*!GRu{iQ3FGJG;q>TN&$aSjX}v2oT7mgK%xGx6Er#OYla>}ZlI zOxTt){L_OVI9nQP5XbOF{<*7I4G`)BCRn#m^VpImYiGl_{~mS3+E)4FVoF$rjNS}P z8=RBDndl)cjYPF?o~TWV&~x~hr23W$J&RGiEkw~%syRPJhBveJBD$@JLz&YeX%BDUE|4ThV zu!`u6YkUs{RQ1booC}7Ali2^$PiPRkQ?Kx~Ofm0pT|prxf|CiEKwL}ZN#26G3?H>? zjWyom(>NM(UD7DTw3F>i|RIBh2smcKNcALAl z^&UW^GEO`Ae!K_xp6~eIE?xsJU_Q!Sj)Bq~M58l9lh3Tf-kO01>su=7;OldHD;5N+ zJu{BJgsdQ2^7tGB0aA26!zv~HkM#b~#^uxcjqbDr$(CY+NqM#bbF+jl@an<8QaJ?! zNRJpcN8n22{A9hkIbUg<;D{n8JYu7goquf-ej_uHG7)&TJo6Mob)fF=YnztgY1|T&tcE-dyV`u$jMmmB~_GMsE6N$#Bc)^@$FKfi7+-Gu4l+2aNBbna)Aoj zt7VR$6Z0HeZ4*-?H$LF3quK{_$K}8=a1nbNQQ%`s_2MjxLSNYSJ(eO&*QcVN~c89c@Pw)>P%9dbDUCL$BqHqt(!$N&X8 z?EpZ2YV+E;gjg$mNo%o}X2Njr_&1Yuc`^VGg5_Td%$n9>hxDmFMczir@CkkpxgYyi z;l_3?P?Tb0Jux2nXD|)g&_Hm&$qthXg*pz&2cvG;gOX3x?I)|5Z4pTb)bPcoBKJmnkqA-8%NW@3^%r#G6`tVn zFgoyqfO6jj(`-L-)oNt^?R@Vkj-Yd31Dh6Y&z3Bq`=kX$qUcWMB_^~~?2enfCNcaA%!H4B)g5xn&!HLO3k-4Q8d>fsO@OOnP@qWz+PPpc zZH4X-;q`%Xo|E+SJ=4Jk?|2OT_4=Ug&YZXF@MGZPJ2b?rfePtHfa`l;I`t)o?4A4S zd)chX>0?^Kdkbhzw27v|Ujft0$4j9auR+4?+QK7b4w(QmzJG;@oQS}-K5B|ADjrJk z6&diMmXtz?dazB%d$o!Kp1@>GFMj%V_im7Dcv0r{_Y*#O18xG4LLRdha0-klXhbFA76$bZ|dI^O3L zo27lQ3u-yCR+sE!$J(ay0R$Yzl4*Vlbif!vu9VdM8s!2a6t^=ZTn{(z zHHXn0ViA^3m_hdHG1%DRe$60MyX({K#lg}2BC{r4Hi}4QK?66)DKg!f%g8Jae87e~ zG*|fJ$-&3|Yl`fp@N@4T`li0X()Z0?xw6(AZ)i97@ujb*mhyv z+C9JY9nfl;JRjTxd$S!I6>r)%@VjarMXqgn-H|!=Y~D~Ht(dUs zUiMcQy>AN)BT(kllnJ{$Qv19-+@0>WQWWC}y4ZaadZbEQRjzJq~qL7OL z>3QjlKio;H!FGx_%j?VGerx5g#O!rtnLK6MOw+4%hyH~4`%gkKV-MH?6swhEr3%{G zTkdHKp!qk^wC=!T-&)%}oU_=@*tiH@t_yNVQ=MX}HBgdny~Xpi#UZ}k>8E*IbJaO` z>6OYT>Bax`Q+5OMhHjd!FekbD6#b^)F39FJQ~ufzCUA85al!@MkFU}l(bX}yM* z3)oUAHY4v<*Pk?e2I9uW5|%<6+?XB*bY%XfW;>Oa%2x}^&Ps@XN4|1 zBOmR2#R*$ni8O&6D!OCilkT;91bpzXp3+HAJ^I>^*jIORx2p98>C5+)cV+48H>0kfZ7=ZZ;BON>>FNASB4+Rhfm)r>0W+{}J+ghx*9uvzB=8Q15o%Dw)> zZ+fo@>0>^*bcKXdj$fR>>j5~@2Frg&=gE;HF|v86X6E>xcNsXoeU&6^dmz1O!6CDw zqWLQ8xhe@rjteiru>`@Xcgb<_-cEUZcUyUfD5ReGDsAH9pCt>y@SyXjXAK)jt z?9vfAjCbz_a)8Bp(8?Ytcb=kiE-Iw$NlEv^9Ak(uYl{ z%bi4}pTJ@1jcGi`POE|L>a**b$)C9CSsX=%0cT*e}TEhrYr> zF!InZDD*^d1VL>mEcwwr-qTbqd`hfBsCRM*h4EpW=B0_2gjv@~!_d0UXRnj^h3m<< z<@=56?v^yZ^NsnvTDbv%OHxoD`K@Z;6DFf8uy(9I=RlRLf_O!$)5cA(ymzguEkOQ0 zh-yXHa{{#jAn==+an2l`lCW-k5V-|lw)hFI#!JLU_gN(A z;Ob_F++lO4a>eV9ycMDj)*NPKnt;pxq7CbS-#)BGlJDnwY=XxRx(2%}0EWT|w>}N> zgFXRML6j#DCF4D4iK7Qo)K_%r`}cnVUO=J0;|fyrk@Y5`;w|jZZSF-vn9RctvZ5Mz z=dm;F3J-kco;qSHtF+OK+{gp&*;lL7TNO~NMvs;7h5f&l0Ql~aj9zpCpU}yBz&;ty zF_N>%qZt6{yFL{ak}!O?k9&Q_s31k@At;?y$57871F!t3RFWsn(ReQ4APOaoPN8{h zT})t|h*#hfB7II2LIVMDy+rh#<6+ikv883V;}iJB!QTS}&QDWqe+me9)d@ri8T1To zJ7mw&J0kQd6k*=t7@a4WXEoN?oYb4maYGR<5Ynr%$~`aDflATMWE}UawvIqmZsAkZ z#SQ{-^C%xNk#Xn)&vlSPxoB6{?j(HkjsRik_#QwTcQLZ~_mxt@=E~Mez}zDd2CFh- zu4VCg7Df02e$>ytRSH4JajB5QN8st1Ess3S&Z$)q9XwWN7zrabb)Qm?9PRG*FzpAO zis=rdc{;RGn>OARE<(Gty~7rF9c18UfEIdfGZ-Lkmw5F?oAKLnJ9)ZJVj?E+Z`a%KlZQy6{BZn_(2(lUrf=U08GP5 zOytuZ8tNXnt2R-Iny65lo6X$H0MWi{y*GW=`9E$aJ_cFa^dl(uki%#Rm01;J+5w3) zz!_r^Ycitqef7&pmUqUErjRP~2cb88&xZ`-a-TRM?bPF|Q-}txbB$=Fq@w3n4sX!cY{va&4O%$YOQ#SkSmr z9C!Z|VqgG0;R#?tF06dlwm%0{@aRjI^ zzp9OJuf^$=ZdxwmK~^RM?-8>S*BO}G#@54kh({zoJ_pzPMA9_wvQp+Um9y0cvFbAy z2-!>Ip1z6cp(WKNAi$5wY~8o|Ovqga={;57Ls-9itGYbTE7Jn}^sMQ--bj6j`c;Gs zN!4d*k}V&7YNbrAvIAT`VOn?&&ZQ)0O$-+1NmeR-`4ZE<6{x~`Vi_rYiH$^Fsy#=l zEAA7}RqO$kF3;kwtA4NLvC?mK-6_e=A)?c08FWv#@5Bmck9V4~_PLfz|BA)UYfxA8 zO==)|C_v!qv-Xvwkrsa)6=Et1@4=PC;TA6sddEy=>1x+phi?GrE0KksY>+Qj_tR2| zhCwmqPIa*>)EO8$XIEp=hM=HdUF}*Dzuvm1Q3zLE7d5pPXR4daxJ&Q$cHl=BAA=Sq z&XirAhOL1MPPQ9_Vmyvf6XtDt-p(l=%YvWU;*e;(Mvhl@9bU|q3%ql{_k&`#<(DG6 zPYMb7Y}q|!Mle*)v-?d%^vVSHuLXLD;732u(@VULjBG&Iz>R>x2Oz79BT zsWr3ZlR`^ru_VAYi4knb>@piDU82wS%?H<&f=s019!v^(k=!S#m%9tQJ%DK@?VVQfLq+r*ekR~)D^}I#(0@&0I zh}NCNdQESe{2Y@E;Sw;zTV7vZPa^&~bdWSmSBK*98YYE_4cGV1kumdw@p&F$dq za(K0Y7TzTlEBFI7rkT$5;HQloW%_!fWjMta3!d9=hojTmi;t%t!jF^8B7yhxF0GOn zjC6zzC25|4l8wrBr-cxf?D&u4+sltZW*@O^kqOEsdy1x>7g!{-Aew*xP3z=qkQA>g{_yGxA-M!=Za{ zGJ0pJ4Zva&Cn_ogh(g7RaWr2VP*SwN21@^&M|WIrIG)jc*LK#~;Pm$6kLTCd!?W{B zMYOIf2GR?CCt@!Lrx$7$BH@ZjQi5(AVbz|^!Ml$?U7cUo>o(Epc_C*7U!dE9!Owj^ zJbQjkwwNo6M6w< zUNEGxVR3yjUt~&TB~@UGp8jzC@#9VKXmoQup!EYyh#H%~^E_R3)k;NW+LiaB09*jo z*cvE1hN2&BN!PAx)4c(FBu+kk%Xy(N+#W0I#Vk&W->|)F4#-sSjF82;5RBf~R49g* z@UbrBT6rl|X$^mV6<{akg$Fz$GhqQ9tq9;Ly5N-dA*n5Z3>bafW7=)VU&WGHW;A)> z9zrSuD;stUC~YC85&mBjC9anNRa#ktotqN{dULq?`P-lXXg`VC+YHi zeHcMcs;k+BI>x1f5IH`Kor?hY z@qu6q%Z2Fbn+aB{w+jT|@akeOKL?OFpLY$$Y_IN3*YbJyk3+r9jbwZ}JiErE5sFPj z`5;6F_G?kJb_^82l%CLUHP=g)100Ra*u|m2Z(>T!7N~|_mJ+pHS27mYK)zy^K;?k2 zkOOR)%d8rm9zyIaM9E`b@}5zrh!1a-uE3IpeyNREwFAF!u+|Ke9wc<0Yn&N+w9H)E zYQ$*VM@6#W#frT0{g>ttcn^{X1JUBZxGW;dSR%9GS)Y;1?0&c5|CoOW8X_{DmCyPF zox{H16LhY7#%D_v~%}O(uMT8SZN{1K*wMckDbIwcA%Ov6ZIZ>weG)HuO875& zHlCl|u$Sk&NE4w-b|!LOl*>Z2cGyj_5WC>`wwxigFTPn8EXnmyt8gsIo{RE&621LZ6;l+}g2|$b2KRi05i)y_+Lm6f0)bgI?rd zuQjiSfALXiM zydYuG07YnIoZ^cSv5cKfA;N>zYYE5Q&mB*9!Bc_&lE(?I%Ok$IA;r}qPm>^`j9)wdr$^yQ^(yi)M4ju7p-deRr zn-=t|zKRA!3(^H;VN)SF0C{L%NFJZ?lxLAB*l>i`3Vnb~=;3hWJ68oYR7iqcrMp#2 zc~Ck>i7#B87!o2lY~xClb_csp3UH>?-2yVAvEo@-=sw{#H09*|Xe0oj4lT{>^!iNo z^x%+oYLxPg`y>PJrg#@j< zs!;Ux@aXVqzHoJz$wF^>fxA;>aBhe@qgcRiJYuCJp8bmu#vsprYpVmKqh3gIw^xETXn)R#-ZVq!nF)Gu*Y2o@#sU` zTPzK>A!3avP4ekf`OH(O7h2I15&N8@dA{Sa4>>y%zOskBY5#_{*qZb_)O}KM*R>7^ zwIC22Er>+5$9-+!G{=3mr&eljs`e)Nv{hZ@c_F&q1}LXYXetYyQ=}20V@CGy~86O0)PQh)vmYF%bpuV}Ujycz}Tm zLN&hO^U>k!!?$lg<6NI#^8AuNLSWOE)};%O+)FWDT8IN&BFYRmNgDz!JVv7OCi*%y zEDp2Gx*;#f0`aq!m&4=3gV(Q-mqE6w@bVNF=HLrE1*I6tV`k1hJtDBvrW4ce$45u6 zj=!?eSA&}^IyvLzx9MWUD=fCDQWy0r{l6-jiv{`?p%U!pY?-DVytazsms+WS^1<<| zw=hUe?5nM(h~8lg@A_AL4LoD^n;>`N9;f$%mpS--;fvkg7d0Kp8P=fXZs4Y=>+v!;FAn0lm-@jOpr87YU?xF@nb1--RLI|T9@_IvyLhevvd7Cb*&WqgrDL=Ph>C{jyx29 z?}7uTX?;QgMVwFOqhJfeD*QeafCG!5y4LOkcYQSnBL>_9te!#3|C$)cQ>x_A9eb%| ziCrcQl@#-tm`<_!GaNeFxieD1PjYDG=5TTlxXOAu&SpZdC^=Y;d0EFfUn z<}SrFqhK^slE8`~7f&Y2X#xpD=*$I~gH{a^g3P`x?2&mNL;uE&yR;ABw3 z4X}aFpMTLz-lse}0n)%|aAhC8V^J!jJ4SAPc_AleLk_18E0gHX+~|1P)Ax^4{pqNX z6H(DUr2?#ODN39+_?^JY3+eKJS|3|$1NLn~JH8wAPHTt#G`PMRUcK*wpA}~8V#u^mkg zvfu-d=YqqkYFm6OxS7IiY=ghAZ-HkMv{$7+R>nSRA_0QbVETa`S`bUgW|A#4v?Lf| z(t12pPeQkU*#sMqqAAxykHFNcHjp=$OTqVkjTUnca zuZPeNU`s`FB%~WH8CPn#5VmbrqL9;|qkC+i0J{WDCJ|SnQ~d_$YDpJ|56}OA^bIcn z$-$QCc_W4|{V}`bcXm`T341MrI{O?Z68Y?9j+gGPipgdQp`~_$srPaM)Vd5-!RLRW zyTa{+-+lJR8X)_og1~lgUKOImG^OU|Ca3HTi}{K~2D7>74}psLda}~OE3dr?r_Xo z;^ckOZW1aDWO35nxqd4HZ*(n(&~dRL)2-28YC#mp%WO*VM#03~vKBg1){>{paeW4` z-J1F&$y^sx#E(zePp*ujE|2k?a7Pv(UAqbHdVji1>DXcq9CtKI;kJ^?V$De;mnG;r z^)mMXWxQ}P8fF`SWOgM42!SlYvUY~UYWA~ zL$blvCj5z2!k?HI{&cW!qn|8xmFttad|*=`1$u)SFD80-h-8|Q!kpwN8AZ#&fl?bZ zvYjT~y3t`)(Yf|j`*TZ|hl1}dkNR&Nj~ja z8=Y~w>#-Z@gWe<=JLnx80cTjS$;+s1j5E4CV_W)s2nK=XW zaNcy766AR$(wx~CVYrtqlQcF_(`q@P?2wJlttbX~*G8htmCb3lFI0=)>QZD$;u3N2QGS03!$}n z&D1-NaT+ij!I+j-YHaH@-!^H#Df-l5Akr{cu}rhjJP!UyHM76PNa-f%jiX_-h8f*9 zA7l|L7%iTy=pa+n(M}o2D~pCyy20pqrWde1K}fApK@etHI9mGu;d7{e?S$0l*>eX= z-+UVT%_*wQ-3PZ{qgAm!YIu5@*y=#r?C1Uj2ufZuPN@wUq!@)$lY_4YMjm@fg3WEm zQ{S0>YVCNootVAU-@*s^vShIU!}@S^{~B=7g;Kk;&P1h5vBadLtsS#5lcGpZ2kW2G zu{wD)2LvERu_(2qfdpwn&H241$w3u@DsM0#QGd7{X^AFQgLR}SBR#ry0~^c4N^Mk& zcW9Z@T0G{WNWh)R+K;?UC8d+VGVuVCl2v0miIK?n%!Lb^Q^wi2m!%bOF&!MF}v81wEyqm^|gNMjR3%+x>znWfT8Dk zn2uf7Yu!Q((2=eN3%g|S)_Jr(&{m6NQ_d`SaR&oUp#Ny11hSZCo(f*_;x54JB7&Y8 z;hek=#;IN##x*i=DOdw+(7;M*tNZX)1!S74L~@O_nc-|GV#g9f^9dlOB7K?9YymA9 zLYc-luyYwaM>MK}mC#^KPFA%0lgB`l(6+UMrWIfjT3~!O{*62|8=G2j)-)Q>-@;k5 zR|jGwMq8~UgSk$wv1vWvf?W8hoNdM9Jg|Po#ggg z`cm#wjHMe1q91|F1&c;xTM)pu6r_r#3ak8{Rrsj*iWy@;?J9=xYjKCgB2HXVV=aQu z3Z5-fUKl<*%otmyQp*~!3w!W4q&PJk80`lsV&I|Y3*`H7cQJGfS^2Bwq|*vrz0tzt z7Gmk!+)#YdwIuTAf7dEK~$N|NlK|G81^oeCbk#a)*B0H<;2U6c(=s9kK14zmMEkcdY5i!zd zKfj=Yy@@D!F9-~K(P8#&?FGcl^=4AeKq0+&@k?#-)wW0QUqNoXW!=;Bq*tcu=U;mG z37{R5m`)3PY+ukOzoD{kQ&0a}9$I>_eXE1ZTdZqODg%&irbu-tHXS}y=Y0BBt+L2W zT(l_gJHa5Ch+dR_3t>)ARy?>8-at|&1!h4&gD$5z z>WVkupP9=EF?@02t!zRRH3($J(_jq-+h$62$lpp60KaN84RpTsW0brp?WxkN&NP!T zWSO893!#UC{cv+LvOBiH$!e_7d~!u}5U6(R8om0)+f^7=$DXb)^*RI4KiAT?c^s90 z**NGOzW&!;8|D>|dS30r(dMRA%B~@v*ub%(^n=#mlIwx&RER$ZEVco{)IygAixTvt znh`H}1m`lvd-yZaj2UWdDDZbM8dfE1UnxN0z>tX~$y~02-$ugzn>u8?rf+r7_+9l6 zci7ZI7Nh z3o*o}@3B*CrAR=1k>pB53{nOaVz%T3+ywAYgLl>YiK~`!M-?UpM$-QpH504nAOp=F z8eqZAM0dT{4mfUI7LT^&scm9wTzfV<68)4E;=TTojbwZ{lCebxAmImpUJ|fO*u*D4 zZt8Bs#_;Ug&eJUjMM+$sD$mI>h?|GeE-aPuZkc1+sD-}qK_~k-1^A(nX=pAlB-8-O~P2saHMw^pH`1BB$h&7t^~4^ zu2R85pW#9mg#r~#`9X-Br+S;i{jUcK#eKM+(8yptdHs_<+gILgztN||+c#mQ^=LV) zb?X2#__tkyU%9~}-z{$?>xJ{|hTGM7rs^Ne7Jm3MtkA8x@{}Hp5Jzazhuk$ zR*m*IK6CZg@48i!^jTFy`B0({tN#td?EyT=r`x+sgN ztc?yea3h9fXl1Hf&us9pDtWmCJLMSuBGI-_zUdvRvE$hvR0kZ~^^w1)g#_>+LPwlK zX5!6Ec&zSMN~+qk4aTbaO+Y2cPuM>Mf>-GmO<7KvAMtF^_y{2mL?IGgOths72fHQp zzL_o!qVe5Zb%ioCB>>rQ8~*TCv7m5$07M-U@jT_KOd|882l?~z{A##ch2Cq%bwS`p zKw%riJlCh8LBBVVOXsJD`tsRgWL7^vJ*1*wdHyls`m!HjSzHT*gc^=q#zc=G_?Ghr zMa9k^wMZ}=sS0nVomWHB@9Q&~!l04BIoT5Q%QO3~N(T9NBaKT|cS&?O7!8e)7bcF8 zn;?`~B0R4-$useguB^Z1`PC5Nmy#O@Pn;Ixhirp?(l-+8xj<>0VP2YO$Oq-+b)w@1yJ!#tmY_90feHj`<&^F- znNkb|^zRQMrQRJ2(G(!bAJiUS@Ly%t6?d3P$ne&E5Rm zX*tP6$%bdj*XhJb1kRcG2+NSMT#_edTimry~}) z4N^ieBrzBbdshDhJNsO?;mbBUlR`Z3H0`zY&v*2z5iXD1 zDh$jYd~PBwOt**brwu&?xydwNm5w*hx0@Ux1S{&eFHTzc*TqRq*t8|q>TpfuC>2d7 zg!Gpu6H8&s<1%br~M(Ih7<`)yARs&Fm zPbEg}kb5*8@x~pb&#!OZpI^C5pk6LedgUhrb=f_=0+ipgZIn$W#ivd5`eX`G zG@;2%i$9<)b8+>NT;!?H^5mc7gtAp(?`cULMZ~g9>GOg9`dyMGYOd$s!P|YC@TxgI z8D*?BX>oG|BMvi_Jz<(B(Y->6@XnbYb$u5-wdr(yV?A`wpX9_^?P+rP^){yY1mr(} z&c?kWYe@3>Jj?CYX+D|H3?54LtAXhTo4b&)diKJnJ~J5%gKzyDhK4|pHWo?fjyCyW zA#)mzPj%a(#ShR%TEw8M#%_ax;^}D+<`u*Wx5+4oC3jm5DUqqtljU?O3Z{}@txhbO z1F(f@0pz`cFxp5YfKQ2lT!8$cEP{gzL9)L0qD1)3KQF~nU=>~hde1M^kaPuc6NW1O zLq8lRzgo3E&Rq))r}@fCHiaCM-nI+S)zMt^j58Rt;`RRbM%x)ee&~JHwh)L};l2OV~>fB33Hy?%TA>g}rz zdv*Bc_)P~e2ajBfu+L9<&LfyaZT+Qd8u7mnWsyXx0z^=|ldZSAPV{MvsYX_NL~U<} zb`$!I@iazxrMJXF%tZzv?x9VXPvo+!@CK?|{IlQS7J`z8i5@cT0ht_b;V^d)!$BX{ z0M6(5GE%Lv(HJw{`6Gn8Q-$=J+|GX5%>i=NK!eB5M_^%6@dq2y_|D~ss z_cMtW{#)JoLH&P}OVA)H59*-WaH~U_i*&(GFNW17bh~qUUTQHVcU47l4%isRI`eDuP$-tap|0#2h2Dq zQHf?B6;carVySd50kU_`(x~2d!DZPLhiF@BgNe0up9ZI@r*3fsERuNRvq>r^dkdaq zdjgk9Q>kuL#Cx>o>U&Kj3n7)R=a#yKUaH=TFH(~Qt)_%+a8Tqi3`(W%aE$1SigRM~ z2ya2B$u*IP{Yg%MB}2*6vNe)2*D96%{-WwmxfgMn&eqz6!p+7SL3{D}(jm zfDkq@Q`pbEyzgC#hOFm<*Y9p`7oz01P71rtWqhmUwp%aHJc{7OOqA5v3#o)RQB2)T!E`%P{``jH;9 zV1usL`RV$C!O_TGzCXX&^-_qttu>Gv%+bgwtGZ(VpVV>A-J6gf{I@L9|Iqb^#ciP` z@xbOcZWaqd4g=8u*>#eEuCo0^Va;^Ua2bB$c&}~j^`2fTOyeUvO!Q{G4$HYx53(R{ zstH#~gkb2TZ29jR040iHHkE(l13+9>2B3*|jEM5KdWx4tnG&4gsR&&V1X7AI}qj ze)}6eP=MziG8ukh7!QpkgG}Frj6RgGJt_(_D zL_NJh`iO}YW5`lr_g_u%$X-a3s zhNJsqCW`>b1QVa(rczX{-$-JZ-yc^za0sm(U_z-@)O?~we3{*4@*$&i-7JY!-LpiG z&1WrJ-zE7cEPo1_IEQBjgC`fF7_W^J9QlUDk#K>BUdW2oxMDmAImbiz5vNR;5G)LR z{rZ*eiJObDC;g*$yCjNG?(IHCc9o_csupdNZ}%Oi1fjc@(GCXBzzN~0f_lMdzwqkD z8u7Y{)#-WQRp?=9&~1mj8B0l50bLD^SkPx|SklBHaub7I8}Za)UBf&2aRwFi?K>!G z-K{RhRX+i{rdo`ZsjA0MAfPCG3g{z#FMvOl1G`0)dMR;MA|fdmD3jSdU155zWdVLW zguYB|*1IJc^OTodBA0-|Yja!gco#MkIHPZ7Hgzrr8KI`oyJTZB1pJ^9@nJX2Y6zkQ zBZNNlEsxG}O3@R`QU<5OU|GtpwOsn&y5ry{Ow@tqg<>f>l`uSK_++O8OwQ-?;AK)L z>+nMJXSc8->d2zf-{b=IskJLY|XG&uJ6)DG(sW;r&{02ECf;oM8Q<_gFf_1>GgJ+ zt{Jedvr0D8;!UP*z{m7#*p*}3{abI_o~&$mgO)G-B-d-H87OSax+qG@Yum4}4sW|& zo?pxGKVzUr^BhJ3eduC;@ZQtcl^J`_(-kLU=9>FAFi_MV#u51WkoWp?8JE0L=1I?7AKTEK-8XHa!C{hd7LFSSMMMb`a7k z0}JD_04(x9$%(x@kk_XpJVZaMjzPf^`YzB_b6LW7o<~^F@n-Sa#_`gU46>XD18s}= zM#M!DXUS}CV}%fqF6Mx3Cm>nkR4$8h&K5E&=LFWc%1ZtS@Qjw|HuiIy40_LVMc>oC z*!`27sJ$KI?9s&L?w?6|{>47gy+f&-he|C)aV@64 zP&~uz;r`U_CDJQ!mt=9@rY`~#-dhUw<=rHF(+$=V!?!qdK&Q0MTgH9kPxo2_NI6P1 zO}G-rubIdqsW*br`K5KGC9x&kmVNgg2=*&5_w=2>eFuy6JqA1@!kw1FLzBY!V_9%^ zb~Q##ud`$M6(O`*`9i@SZKtr&5rfadS%%@u-X-0uU^w!G-Y>3Wm=6pQ;}%iq!>%sS z1V^ERETEw?_Zmp^)THKh^sZ%^GSAYC6muD?%3%)tqujONIcOUVaGoZn*U86aIg+ue zSAw*=&=wDn7o3|YmeBb*)jgeRzD_@UIyt#Gzr8-c82r(9c=BAHh8M$6mlcmE+yXpa zy66K%FO5S~g+4h&Io;uzE%#}BPOr!2{YDQd@22qta<|W=@n!O{yTe81J7++$Ed>yl zjl^)TUReE&`J&Gb{D@!Q5yyU?ryN(Ib;vQTmhqtSh}pQ`Gst%_wr)v7ga^gP=Z_*< zngDbB*JY*5Wh!SYxK)RHwHAXbHa4)=j0vJJG}XcVr^$xL*xg&z<#}#G!TfMt5Z90c zrg8v_i)5zC0=%)pE-^h~J{Uv!Q&&9PFW7=Vj_<^S?rpbI2kkXKLa?X3UlEMje4>}* zr%drOQB#1O?Xxp^B}*e)__IUC!oXM6JNc%&nQL^KV>SP`V9j|cFDy(j$&9e?pJ(?~O3(96qk6XXP{Z~mPA4^Cj8&1ERb2H~54=^#h!TBZrKdBJ1BmaZmKMWy(GN-;xz@!6OjnR$t@CRzwfvKhu#8j;6;<_@n-J-BZB@mzPC zop-nT-uduu@ZxRi4ZUFlViyc7CJi*}bxhAs@v&*=RK3T$&+*aGtHX7Kog~>vUNzIk z96$QDd@W`9&ZYniR5-;l8>lOpT|?IN>WfcG6oxnNalkV^k9dwAp^5M$khqY!FYgR4 zF4nctM0nJ^QY$!j_${s?2n+YJc4I`X(}1Cjk1EQJf!%RQaAm;^Ojj?MrnX3}M)Wwu z)oKxyln+_w9FeQEGm9Gc>frFzYya9HRT)}IEWA6<$dMJ3BEYGVWbSZ)6VXR)AT(6j zxHz2Jo|*&+3`WCUXMS&#G@2MQQEAFIh*b3LK8J*NrVLxY#s3|cM=;xPCbOV5rvlLJcmb(@xpJRWG{1#l(XuEoJJ_5TF|Nr{ zGLQDZ^!x?sVl4bJYogr zjF&u5c_!G8hiC}&k`>_!Lbf1rG9?XG_ffBEqr`tumZZ{UvZi7FfpV5mB7V6n8^!@` zrE?SDXu_9Wlu$0nPtZ7kz7)M#kF{Uzt2S*Fal%uZNb0}5x=(m?C#O?q)d0F>v1-_c zni)wl$OWr~jww%4Ep^xH2a=5pT=GY{R{#ZwEb`M5O(1}WgcwEf6O^PH(;O>Gw2LWg zK)H@*=gV9aCdu6{F?F!NPb_I#7#(yWvP=FLvh|aZWO7k-i3V|}KP0wH_|+8RX*e2l z^+r|@WaYgmjOiD0VIf$C$rPrKSB#5)DgA76CNUqN5COD30MeT_v=3~*x<;JoDjR!v zC$A^)HDd2o$zc=RT?W8tD@Dw>eY%g_W+VF;CL)Lnai+>;}? z(UaT;${c%=Ks}}$rq796VJ}tl{`a>KuChT6**avU8=g0{(3NJz)H5hH z2eGiN!%x-)pag3DRW)ebf%;-{JTIC_Jm#1@QnG21#U8op%<(3(KZ(2mhN`IY+<=%$ zUlsM}5w~N1VR%ZVipDS%csrB1YH(A8=gkVC4Zavo7X+WvMbF|vG?1dT{`UJ<$WERY za@xcXym*qKnhMZygan8s-%GH89yeZka0<_*Dz~8dbTg0lk3q+>O!~p$2YLaA-Qe9q zJ`LA{&T5e$=BdmA%>*5$a63u}=MygvUP`N=25>j%*t`)IiY^wp$YPO2iSODnEGYnj za#eHdt;W+r@OTAR4$5`oITIDmnJ6^})JiVdpO#+d0=A7~40mM>7>SH>e#lw50A(_wKg^`lBYLuQ%|j!SpHjNh}yAy&{D}FEg7lvaa?} z;Vn&}>M_{CL7*t)p8yf8A3U~cMKD*-{_Fky%KIQCvU}VmP_OE9X1yzDO)ZlyG7YE^ zs-bvNibah+gF4`vsqd#zQ8pA{5Kq>pURhJfqvA9b8>loFA}SGof|bCAPNm(>QE@5g zE|YKQPq4j4%_1_nn^eONxSi&#;&S*^iZi?f>XAYv%io|D4IYqEAn0v3qDE!l`EXRc zIGX%8)_HP#8s44^PCuMqorUfk&Y`1Tu;$z0Bihu92iP`j4ZaQA%7bHVXH?A)J$q3I zEfLnJxz_OF5#3-sZZaQlLozT3tuqO2Psq0nZL|$BmL~Ti6H1K=IT6h_CQ}6Rm15lFM`J|@&DoLOYe>0x0y&YjpNss3ATP(=q0drS23@@ z-L~@X`s3BjR{M%Ax#h-U%m0=;i|vqay0uuU-*9iSG{1UtsZe^x?(&S4Wh(h!v9!!o zs2ZmHga85hizqPHSAOqw;rfR!pw>XMJU@-B?rhKwUfh zOpTl1wzhNf`ZW9-_3%3Kt=?j)FIu3*VavkgX14iVU9UrOYa<|8lVk~M5!12JoM$u4 zzyj9jWNPz%2P;6c>RAR+f>3fHm|9M{28{V3s(b-BsCQ>m={zwq?1lB5-Wxg!&8F?QhC7X#-QH&|cFuK4ce;g;jipz=K zN!Ac|QnbG3FY`U30t8e*>jVm@K0ESgjY|mb#ukX8X$tMs3MGn7z+Fd+*?^gzCQ}iu zA_I%4;De2mPBXO$vTTpAYEwD0Ux+lm>kd(>76Cs&R&Tk&XLY3r!?LEC0MVv%N zx&<@RMWV0U0qqxmX;Z;=|L6AE^~cfZ{H)z+pI={pyl(&UpD(CvEV5Pe=g7`&E@Mr> z^ZeQKKBuxCryD<@X+XIY&9F4C|DA?nB!?El+rW&8jH8lRPHA8%!ye5f^48cmut+q# zLV8IDow^>xozMZ+7n6Bfg1-(rC|SFtYli+l$r#tiFu;-k$G({dKDy+2kgrQG-c-&g zpKq1Tn_>x@J{Z%C>8vpK4a&?wsel(IZzQdfhXjx^EbIe9u9&12N~BYphL%E*F?&H7 z03l%=r-t_$#u2c2-aO{|*!tt(@*;qKrLHIgy?vLAPdrV%`+Cz7V{nQ@=`t3WdO}rR zipLEv-7;@Kxz0V;1H)ds6sp|cKMe4Vsx(tM+apwqJw3Wz{UGOi^lgQ7*h*TTJ?jF| z?lAKV06F;r9(hYMEbG7UKQP;d?>JfQNB@=Cxb(u;e37|vFC@Sa$mSMAt?)&cbKc4^Hsz_iv8A|Nc0B9d+N#=d%jO8wOXu&Eh_5AMPK%>K^QO_rJe6eAPet zzJK(6cmGX)f4@zc7cMP+g}F)CoJd~c@t2>YBL1ue%g=ZBs+5KJyxVJ;k^@^1EwJsV zhzIO__LbmCDQ|=duq`^6Rx~`L9&_v*qFx3VDG%c;_M4 zAJ{F}FfR!WYndVpyShtqmWgtTX=I#lv&*I;GZ0pD8Mk(9I=^jF`MI1rW*ba0%7xq7 zu~{;B7K3vk`!Kr3JiY8v7DC>OqJz$aREtA%GZsLvmex+C9&Ynbd7etXLRb&AE*8zv zk@56O-%-kC-fPk3dL>U~mO($5j=R?VW(^)m&KLc9KIGwuk$*Bn_yDNSq#&+bo!0`c zn{C5hq;+k3klhj|8RZPiB_izw>K+6$DZTs@*iCThC&}I@87s!=$QH!=>@{R$Zyy|i zH<A&jbx_UmH*MW!ggpOOGs}NoiXssTvVAIu^W4Zf5eXa6z&bHqh-s3hK&(SMk4ur{ z)P@N~u+dk`+&JHR9lEjouX}4c;6FxV@UXP)=6TZ9>~x`R-a+E$G}9-|Ly^Fww=2r# zWh1MZslOf-7xrDmQ(R15cH;qDR|cbDi|2{nPJvm+X_($XoQ&Re5r90&y9=)V+=bgi zE6Fdp`ZEw~$oabCd4y}GGnwh)OHuGx=#50RcDxJFPD25kR!&!Xkz{ulGUBNZU>Lm6 zyNZ{_Dxo9tLPmGwq_2Ao)BzB%Xk?Fex2uJqwiym`1-zGcCNru@$Jt1<&$Qg54`19$ zeAfmz6PmJxp^?vQ3zbifpOIk9&+v>OCs8;jT6b@QY)qt6^Nux}y-xRno->g5*3tEx z2m$vHze33YP9Nhe>APU-bKM;1BxF?Uts;236372ToE=v=1HL{8k<*&9xvGu5!ypiqR7w`$_q5)38VXNl$w7$)u`_mf6w&bfu ztHRi;{Z`!{YCUU}zHH>})t0Q)Y1Mga+WbMMmKXAI<>$}P(ilxbKc`}AhXER&MGEGH zAeDB9wP8Af8h|XxZT8Yl_1z9@=e#Hrp4Oi0D{EASkM(B!ynBn&xx=5(sP427Vz0HM z9{{NHwVxz}Sf-A_yp_Ki&kl%x_X7ylcbDe%#`^UuLaMaLr!VL_(LdNfJUV`1tugvQ zY3=x-sacE{&=)`V`@b|4KX!$6ohLRen~5N^!M;rm#(ed^o+MeUuZwtHPYV;SPsvRagHOV*(^ed*n@3qo5(E6qv`XEcNYk`UZHZou6$L6VVE3^CejWh}? zeUB$i5aMA$mP!ja<`P;vb&Aka0T1gPYqmjMNh)U_&00eJfCC z9>#)Py&a%(_d(CPiYL1go{`uvujv>f{Yt+rjI2t12BIEmqgX2Vy$P=Xfdj_fDAH7~ zg)4$?`6Tl;Ovc7)j=!Lq_3}2&7hxQ^(dVDpw!TUK40~mtzSm3<|$ayH=HNz8m0$3T- znX~*8J`?)R%?r5klKv6KPgN*^9@z*TWs%Hgq5!d@(hkVSf#xZ_|Dg>X_Hh5n4H6jI zsLumcRV6wzu3r3<-?>s5Zu4xxbGjxz;*NceU-Th?B^Guf6yU7zVZ~q4!HYd?pQ}N6~5Qha=U2sYy0^);{RLe~jt>IqX5cEmIs0 zoo7@7m-I&Z`+JA4sRsRLyM+obR{@ZL@7X0+cQ}c8o~Ma034gpYl{yZOj(X<*?`zr% zFi<^@`OCqnCtAVy>Sw!^x*q%XKgL#l??0?K@~j%xwlct@8gy-WnnX#Nu7Xq=PFD>3 z1_v7j86dRehDb65S{irEVvq@e8pcz3wrZZmEq#V%v9cQmnz`(8$2}#o z=ItWMmXB6oQYDY>%pTDKfcA8SW|9@`MVej2?@qCiT=Ug2&4r?s780)u8g0!1H8A2@ z1j3M011bRiLRhEQZsen^OagiY*Fs8Eh*Fp_?yzL)nTEX1 zLnE9fh1;)hA*$vnr`{(aFg6l!L&H0y8Uu88@UD%5D;G3~QWEoM4%>)zDzkBDvS5={ zYscsXQHWlavWvWeYi5^7O;bMWfqv==*tte-P}A{cv-kM-+57wK{coPV$D3v^d90XJ z+my(%*IGEV5dV_rV!P{~JgIXvmk)hEViTV7EYi0H{qqEV30I$su5;nVvHc$?lQoc-Z!1cU}T#Ljq$)6qK9 zcL5MDV+n(_R6>8Y+cE3p}2!~2<3&G72J3m&?3}Re`)h7cpE}oB=@3tp_t%B zx-u|RNQjs7-3}}np~|k9PW9d7rLLXog>Kb#2VEdDBVgkF7-B)_W|NcvX5^Q54YWNP ztKuwCIV3fTT-Ngkf~pvfO#gzNcR13QX`ZWPYQ_Kv8M9W-6#$u0?+-_GQz{7U%O8LE z(5t?$YqES1i5nBMVHVbhw~E<^g9ly+_5(z4kon4aeDAnxDnm~bbKS4duCA?%H|)Y& z<}Jq3H}!M@7jM?=5ir$6b}v^9w1n32d2Zw9V6ysPQO0yR=bnkj`61IPq2y0a0h&&_ z>6;GGH_1k(vUuPHx%4}HF{5Td%_VwwdyKo{PVHhZ`B=dy)mLO@6P3l1V4{@GwBxx> z`ziVBZkWa*U0sQO?tAFNzSrMR^fS5#Aq+}@i=aeF^QQ~t$=8u_#U4bO_PjdH`slMW z{Hvkf$%;K-o)ptnuGu~EP{%lbx7_UPG3h6Dhmoq#y8L4(L%_OG3s4N-MBdx=W3Bp` zgS3SNSLi=wP6H*VE;B#YRbc47OES@&5z-pvYcb|)9?cVRj{#!nNaoL&YBxZ=)<@1n zCxGtv;=~;+-uj3eUQ@r=U<|5FnKeVKQ3!J^GJ;?vvUTPN?rqI->e`BT*G^If=#008 zoFrL?>19#g($emjQxbeuytC7NQIj>Uy5j&jPR}T&Zs7R1g9*Tx;ON>BBiy%kjO`}_NySBGzo-?S~Iv4@EYHe2w_#QT0kTf!vCjPlWN z3Ufr0*Y8G!EKwkFA+mVg&q3a{d|8f@{1&#i+d_cg6yM@xPo@xBF-NazkpV_&-OkVUrzOx&7{c*hD3+Pis;JW zA5g`CLNo@c3H9{E2X#jfU#2; zRUJX)TF*o~$(POe3nboi1Xwq&in z7E|)D)r=?UcVjb_-;8eA!tL!;x6V-e5i-(X!T@Ml?$|QYdp^c49a=AWjJ+ zT~M*W`G*&ghBdQye}HS5LL;pA71U4`OI7OE=a1ku9STmSZ9e>h7bSq65`^Vva%mgs z78?coCJI(J;8>(e%28|O{fTejn5^{8T2Gc9d-<-FA4ABAjCn1euI38`VF5x5QUJUSs-Ke-*FNIdX0$NVcOF{L5 zE^;SujXEqSEDaP%6?%b|y2?2LB~{fu%1+g*edgDlquevn4NhR(ddU z=)_=5r6iu;i$WRXen%97;%OS;qUf3%ar_4 zbFBAzz0cMlY^u>Ts!SxQN{ri03x0yEwO-}BfbFJZA z55gsXye5!{ktj|bMHM96T<}Mu15vlRC~m#FjR{D1Jv1H6>dj>PY~NQYU{C#Ub7K|J zx*|vW)@E3sUa+0W_Ss81@OH62SBXg^ZJXRs=Q3AiA@~9-PhvdGY@{MZ8<<+*`!i$P z0UM-;lnUZ8s3LNKDiDjiVc9+2*Q-m{L*r3n^4N0evXg?8B4Rd|Ipn(LMQqe^k6o(@ z?t%kp7K13Ji$j~{g2$q8!kEF$xOmfaW2ZSwU}w^fOSuOPkMx*<5;oRA4GCWX@+~%+uW8NIMkkoA2RAHep9@`sgz3uqK$uYDmGR z+>j)Diu$zLCNU(QdZ#0&YjS#0HW&edKK>d}vVk{m?RP=d^>mV71nB3dvyY)QN|bv$ zKt0K3UEZ}%Tg?z(>j1tQ;k~NhUiP52_~5i`$t?Cvi122B@QsjLHDJl0m$$%{^vmxy zN#?AAT}DV`_1R<+>#R$GX$%R2Vj+uBApvg0M6sB;^x3~0p-LgilG58IQGXSZ3DMfx zpEBs-OvLRi`pf^CPBI&LPtMH$Y(ti4EcPaa?z57_R&xny*8zr|LhYj@V(P+)s;m?VdTNf|49g|J;8e-axqD!S$9 zU4?KmEFs^QIDzzYS&2Z0T(MMUGm7nBVGYKH51vg>${JfpA4NF>gWdN9FpCXoN)?RK ziuYo>o@2}^E4;?V)G2iAqQYpYgtAxO;b?UI@#f?0aI`lZ-QHXeuEwLm_4(CJ%PHZn z&Tno9XP3h(kN8glk;jsf!cHF8WLdIBGMkrh#q{6)`@gZH-ob%Ud8U4PNejR!m?43;x?CY%D4XBsWb_V>z|r~j<;Sa_J3aO_;VSzlvYhMB-s$f& z2~En{)9&=?lIkiuo{V2CGY`8CR8U3Im72NxgWlm`Z=cD+m5=GgQExwJ&D714j^oW3 zscG7JUvv$h{-cx8J16`2Xv6*-0lxu*H%xlCc#xIJAb7|u#^u?vNV3`3g3}IXnY543 zA4LQ~kj`!szzBzjvc5zF78+1;RuOqoXe^_7-S)%S-CNb=dEO7&WSjB#*aUc&$yj_F z?n9L08&NDO)-&Mi+$vcs%$d|b){>IRu7Tzb3VH}f>`Ioytn$`(jq}M{BvI6`$XGbc zf~L7z$86q!*z9Ol@tRTObP&sWM{h!G{*CaOeYED5?grO+V5w8~3Xi#W?!>BXWkgrD zeg5YqPydRaxB~ZNCV>BSj}c|8&)Qeg0CN9z1fG!IgDZ(sNW47g9RoVquBWWs2qj$| zss=D=Yg>ba!=&%h-=0?Qe5j1P-n#S2YSeYU%6oC90R5ZZ?d`yiEz7gw?rWJ8q;&t=gnP${awzm~Da{%WwuY))=k+x6V)X{P&Ps!~$|ir6=Xk7a@>yBu zweq!oD__|gPdU33_gigdYkcTDLvj22?~h+sP&Agx!2n>K2E_Xt0E;cWG4Bt0Z}upR ze2)@u?(JA*V;9L{+?OHS+Gz??ufWh8^bU?7K+ehU^!T{fLaJI&84}GVzz?ha`twqj zobpZtr?E+INMUg{y54;GAMjzLCj#~YPSiOsyi8n2cO)783p;e`ZpB`nx~!>mcf{V# zlG1FsIjCXV2m5z*49u{WgCmQ~`H;k-ZI0fL^bIP4A(6qLLi`A3!4-M1#4-XKjqy}! z?bQCYb`%P`R>TgRg3mB)s#sd*7n=8g_~+{sqEzsVuvb4}j#;pm>VvBksh%0jjAoOI zF13knRVj1x7^5gkUf9@20+iHGraUTDYsZE=f__4!Lga&KDT-m1lud9Ejv0$fHBliBZ*HZ4=4{y~KcvJhdog8*^F|MOxTRfg#i_(9Rkm|>mDmIr7ew+b; z+e;o(gd?ODpoMdDG465*$RgNRlqNw$OejF@rQV{`Rq!!L(E=inCM#zK%4V8z-E>(b zGxvx*)<%IBHMKyW4<8ivV>OL-yG9M*%(jM>!WWX?z`wz)Gh zSs*2}?}(x#go?sL!*m?L23JW19C1%_Mg<{HP0M?1I3;{30^^Ha&S}%&$;#|y7J1Xw zs28zBN#3uQebmn$5+yo}XD&`d*PAH&Ih~L;xoR_`{*e4l@EhcQMUOmFAe;pEJWXPK z62;yUjrmIXF>QVf6kmG78MD)Y>!2Trmhm3xvxEKbkDBbXII+PUgH4uMoO%@ycv%ut zoawYSXMkWT?nMDWC~K#151|6+(1cMiZWGFgDS#%0bpY8Hm;m_&Leo33MCAna?K9Fr zY!>5RbUMJyA%OC!51LG$YY$nsOcnws`Uy0)eo>^DcT-=bbJnM4M^%XzfNirC7;U9- zaA_o&`RN!6Da(5P=ku&AR$oTlPd^=)Ef{BG*cSo%M{vw?;iywuDkZQ~rNzT3TV{HH zgS^fiI&oEnLBLs0(v;5a5@EqDY($vtVaH!xA)Q1KvV?K8H5zKlEUni|?^-~BYVXS2 zZo*holk>cYv3dh4WOv7x(!cAh<@PbHKy=!`*Vw`qd2a1O$I{1C*48s zp?O4*Apmbk7Q*b_zJ7BEoe5ud@Zs_P+XHxrL`+}6m8u@x^nkh&+_z+=gcl|Nfs%-I z0wZRHOmhP=7zvuWb|L;GqOy&0rk1H7ObU%Cii|(|S`1~Wd=Q0w^C0w^O(%py(vAz6 zx7YQ3mti&RCH2KFKGh$!h`lRGBGffCsZSp@;)>Q`QP}0prx5)b0YNAZQ@`%DE^j`$ z?le)@xHVG>Nt7=wZrADcS+7N&p621{^_ktU9z>dc$mByt7sN!UrdV3q`E}_oB8?}u ze3QemD5JPaM?b?kZw^rsveyRSnu~iG#a2i6HNJ*7r)RexN9Wgrn~&FaX zYhh4&ql+QiA}RAT^x=NDG^@oue`w#Wv8h|X)ETjn*fV|VHqhAC#jep9(@6Js+syN9 zGuvc`T{9z}P7~XZB=*@UVz*5Y>*k4<9=36c)N;oD#u;OuZ+qO@u4h%V8=_BoL+hTP`aJ)@Cx}(u1)oTqy*6z&aPUOZ>~EMddtFHLw@8=$jgw`s zNtKQ4etn|s#(cl)C5wMRFVL@E$yMh+*NDKoZ)3mL{ms9HGx&H}%)AtL>*vC7ilS+v z*hI_$)jmL+LA-jG_RIjeDCvVAB4U>`@OB2ahX^d;OhN(_wu}d`0CB~Rcsf!Uff)a_r~K3Yy|~}-Rp^2N?@qR zUc#No1d=CHLO1rf&~sAR962rDG*rFRP)B(pFzJ)^`H0Hn-G-z!tTC)0Tp8aevY<-( z%kMt+f^sq#pKrMPgtwg?D|dE5p_)Wpya2&ldStFR|MVAI$@}xG^XuWMxeZlm@n4sP z@F~HA20DZP@6+}9S}G4Jpz)xZDEu^D`+b^B_=HEPT*d(*?|Bo&i{Z)OWN>=%@zYsA z+Pm%j(_cP~4d3JceEQy}3#jFEnmjg++4$4Dcf&t;_d^#jSO|cSQpU~NT&=4!2jLq? zoHZZy+2Ql9oLk>Eo4v4tCGy|zh~@ED?VjKC2s%9aZp|TdwEx{kPg<|P|BiiW6G^@h zd*F_08}$V@%)iUa<=@f0a+4b6cMZxHYEbH$u5YDvvvj^V1h`7*A2t}c+7Vx-!u&$* z<#QuQpQF&JeDV!cI^SHI^Q{y)zw2=R0d+WkC+eGnM)l3X7pZR!4&Odsee;!?o4|+L z=GU3=VxosLk}09(`&xkar!J3C`)C2l>6*y-UY^Yq^{Wlk#&<~$-hV(smAqUka-v-3 zjF;}_LBYYArn*b=)2q=KN{{jRss5&V3lDg;N$Z*!HLn9^4?=EDGTwmPT=1ft2#&{v zdHjQU>T>PA+Bd{3_GzfvsG*;FLi75aWqT0RfLtRI>SmHvEYyIW1w=il>WDTwce@jD z9Y!jUvpA{ssF-?$iv>%?py}TOUX1tkS4W`)L;fuSQ7QyC#G-5uqFSL@LsD(p9iAQB z^6a3J3RguvAcB2mphl&J#=r}+HaDXvdX&BjO0jl)e`7F3#zHv7#u>f=Qn3cA*aWM% zLF|UpOK$?;C}{H7*ER=zDG zm$7exz}S*28H*dzvIN?2cxZG15Rc_@GFkZ(qVy>Q0_fttNO1VdNG3bT@I(Oisr}gL z8Y=WPMIS=;^lE54n<-b2@4}||0x%V-4FZv<^c(nJ0e(NIMk1Nvm5-4Jzb`nKlD&Wt zdEwkS3&EAl&~XmC&;(!LwR2dka!^9 zmmX2fGgt`dG?S=tva%WeaZiD7s=%9Oqw9FEiX9LzAsQr^B18gEr|MKtACX#9tJx$S zs?|{o@;fA1(wN`D1_dQNO@767<5I$}bt=OUt1KzM!kTjR@$7tfHN4qiNU=qp@*lGW z|2tgAOus?hLo?K_c!*cKG^U1 zzeh!|<^OjL@G~{Q+v@jh4{xv7GoNfy>}{yut#1z_?s?j`MiLjkOdskg8c^yQNqjw0 zohADX(dz6F{SWJ#=y>wAMpd1Wr!m^!e}=}$-=|b>9mH2N{?_j(TDl)=P*_RElDx#j zO)mg_6Tzg9_n49l+pQ%fQ?5HLgfqJ$l+@+NvriZ2RpPKWE1?A_uY4Ujs|k(@pPl}2 z{qf^X<>Bb&dT@GfXU#;)QXl^LJH6y6!DK3JmNv(MUln+N znVSe>sq|`4AVlms_(T}zybxn3Z&U-ibnpb2$hBN8*E3<>Z_fmMu@w`oyb#kgnayjm zw7F~)qKgIGCgU8TV2%-P!R~tDx=!oMh3xH}lxXxlAD-Ac;?O7G$Wdo|Dcg4Uc4D?G z{!PVfNA`>5Y)9gmf_C-8uaUGZtwv9nzY8yzDjeIoOF}Sl{vK}$t^t2L*95o?0K7$5 zMJCHG1k0kYbn6qO!0CR+VgNN$-~g^0cpv^!Iwta&vV1i6#asj;Fny8Zp5Rx z_>5PjQbK+Qd^;+{seTtohFd0&a9p2RS8upAd|4uila)26JlNoT%0f%nCxY_g01B0e z+3D5DW(&ldg2^dQYJLx|Wx?+RQ#Kf0i2|RSTRA$9Cqj|qy2Ty?dK9|iSy`;OvEaIy zhC|I#hkQKdTgcX6l*VIj##p0!SCw z%Y|!>X@tR^ENeFu$_cJn0@$PJ5^dIn(B~c4hrwD34`+84=1uA5@%Wx+k?6Is+l-tr z@-H>6r!C;Xy)`+0HtC?Df^d?N547@XgM<96U4nlPo*vt)foT1o(g|8)^UA4wkToqJ#7hHoXfDt=vZ1PGPKrvnj zs6g|6ba2oM@{);|m{)yW=nFh&J>alyWWL5x*Q_;{!7kh+8J>C!m~|Us&ru4@X)0>UFb9(g2BaQ+vk{XQ7!9JHpaxltDCmwGj_|dn zf{ex#iU?3x7B15Gl!*##^h0Mnwheb%yY!@acj7 z)qp(V!Vf#3^nviuWXe`@NnlSggg_M{lH?O(NqHZy>2`;JWWDPQL%qhXq9~f8tT6W^ zee`gHh)j=?9;mGdVdEFev`lhPnWJ+?W{K(kfFs?O(X{p2#AN>Kr=H_6$vqjb%MRWg z_72|m4v&s{hx@?*O`e1*G_8r!1XA-mptOz;kcTL3KBnQaoWn8Kv-RBo5;s7wq4nXV z{s`ryT|G(VA}J|HX+#?(0pY1R*VC6rg;dJU&>kC-9H5JLtZ715) zZo77g7NQcAN~;;*&0Kevsn^{ete|^jko&ws{M17qwA-b(i!~3jQw|5};ktsjt|Gqp zG`=~%zC0iQaH~(<^Xnha14y4IbjIG^5N`3l5;;&KH&*Ctm7mfpKdo72%)lm@ZI?ik zCP~JNm7Y6E7NyI$hQ!<0uN{m~r=uM6)PiFbpU8VK;1t5`#SD_2pri_jgERyzQQ3>q zWr6OniHP`8i8X>zqF5;)hb2j`n2S<3!w6=8J!vbQERz)R?|Lo!(87M3465#=2LE$S z&PzW@n5~8hJ7=nQO-5luq0y8kvA#YYI@2jWHCM>PqvOlOd*k0(0}9U1znMhP#HT#> z8+$lxyy?iMOR8U2noLEsio6?w%@Z2XGX`5z+$Ur_v7R$Zq0N2WP&E%$^KezWdr^5F z+PwXD;h;T_PS|YE%wYrfAlv@>ApQ(QNYtHF*XeX0VgZZHHB4%@040 z^=rI;ct02@F6a)HVbW*4o(oYHiMSUIXy0b_C$x0`8sd&7njfmfnNQPJIFd=3W)@e_eU&w~Zpt@L_~vP9Ch76(V6HdK^xF0m zQaIQ@e0{l1Z&j^%wv(DHdX|_^p}Oy_*}^QFpzs(O50G;e@icINHszX}G4#KZ?V|dZaSnz0Wg-ZZpL3($~iNHkpVWtA* zP>#9soVT6&hJ*PBHRqfG%A_YG%-GAF!`H{(AMPTWis1$ClyjcNq;!WN8(p(xk*82M z-i#slndy8>H&l1n_6aapVbYdh%K`;JZC?YFWlPh5mwM3bxFIIs^%LAgfF7jcFgm+P z7Kn*T+Eb)yIWuV2g@_>>np7Rc9wDQ4D0O&B_tl5F0Jv`7-6__ip!QOv357GqS{n9B^7??hLGbv}Ofas4@ z^0+&p;$3pu14s3Yr|p3F`G@gl;xspU6H)StS(QJiZdg@9b@bVO5B}TRr`j6yKfyjA z9`VZ?oF;f7c-F?yNTFY=$gue36*W@uD*C^uad$Hx`v2!_nWi14$|A{TzpO1Bm^L^h zPB24riu!j`a$xn{QGlUa`@{zSZJcQrC$DoDU0-t>Ho-+ldtLu{3~eH$l<>-C%w`;h^0*WA~o0pHKxw zm^Yz79uIUpE;@k<*@z2yTw;t6*#aZ70VT2>PUKmUBAf0oKL=Xm+3_O1h>_>RjP#&J zb~)`nvW{9&h2Cv(sBAr1D9!OFr8*ZM@Q9Maf5mo9d_ljE}kS7)h8(&yq~D0 zf$H^Gru>y{Z$OVPpzR4r`T=^p00}Uz$XpXQT(=;&J^XYZpKN$HbnXUx?goUe#ONl6 zs8P#Sly$ws{5W+T1|wVKb!vC|I<+-{o$5g&w=u{&ZNndfLQdh3HzJYMCMSA}Zja@%tvB+O-{rPuk)P6QL;~@z= z7=yk-R8~e|>9gJ=ugOXVwVz)8nVOi*0%Affby4d)UytQZkj*(`8Q#NRnrR00`B@(> z>G(0jJ38obLInwnuBTlPyoRIOgQ=`OXp(~k!)eT+9ta*osxma8Y>!MBW#+S>5C6(k zBX)hUZV{K}k7O>(b0n7DBofmGmWAPDZ({B|GB7=2@62ukqxP9Y0`+?!M~b=!lk!~p zNO4Y@Fe{_z2TeyEw9?a5jL+hY!9;v@KNHc#kM~AN8tig=pa% zLarEB)n?ejfix}h%51?(Ea!hjadbvodR^QZ_uiPI&k<2fgQHUMajco|VDDpwV3f&}xqGkN)5#63HNURWI@8OGV*7A5-6YgdkvIY`I7A0S-r z3zIL8#VUeX3}S1))&bKivx~yiY-JY}n+Hyq;~r@`HMx2wRd=PRCrz`IJUQ{G1EzA6 zT=lrqfjIZ7)XKkNTFP$XRs5ldV^DTHw|CANI*_{PNe3F$z&0`(Lb8&|G#h~0k0UN_ zVX{h@537uxdsFN{>gsI~AXqcjQD)U1O@TcKSQS|gtHGPCsxp(h0-W}5hRSRL(|sekYh_)>YYE z&BlO0;1Q6$wNqFTtnzYko8Pa@K~OtjpYyfXA7-m;ASBm#FqK@V zv$C#$a=CDeF$Akn)=*g^m9U%Vi>?;trm}~AR*ilu@9g0V_Ee3q4yg=!a;)}_)RB6n zzB>F`eYGdSDgQV}GQnTP-~1rH!9{&xZEdP+GmDW2^Qx@dEAvq6Aj zqUVIm)uXKaY!vM}3ZKh_&nc(H*yVQYcl|Lgy*~>P@gC9XS&L6_Yt(7$`^dhr&8f4o znxAQ#cT&gy5Q?+oLq50<@T!o2ez!n!SV9~Jm!IK&1R&GAEUdmYk zCqU`Mh$^|bk~r~?ujgWQ!eU~7$;S_do-VWE8OH+TZ9NoEYI+yT{KU4Sz(1z(@d5oA zJAs0?=mfby(#^Z-QqD%#E#PH(k^s_KZvd1PnX4?6C1r(ryE4U_hRb%TT?YjxY}bSr z1@S*o_!7nQ_JWkVRy9YIKx+G%_w@uCu(ul$3$;~8`poc+z3JA{-yhMVuenDOM%~*L zOh@~aJ_Kq=ykS(%)YLegA0lBT&kCUH(O%*4(mpLB0JNxp^_4hF|<1e|bZ=>qO9)BPN z^r`!~6#hu{JxYIWwLj8|&8m;TKilYBel7k;W%t$l2Wh#l`m}mmU%7pgo9Md`c~s6aOMRKfp;o08}XrUleb|3vDCfs z3r8SGWdsfrc;z*aMo3OVf|+Wmd>+l85lpQ=T)H^IUUX<2dm!*5BR@yB% z#sGJt^R*vlUx27I8!R(oxgnW9bI6cew+3=XrX~=L9O5w#zbA%hsj)QP7sVE`b>8iT zM&pK1jAokX0>Z?G?D;9gl}daRd}yqX4V?-V>ZJkYw60pWsj@StLb@q+ij(1_b|ntz zM(UM57)U>oBMIby95MX&T_Gg=cF(LXOGn1R<_Sg<2xbjfcRIJ_aTu#+KKRAYBX_J0 ztGXc8r9&+G@VdRg?AlIT-dt0h8at`7JG>hC;`PzdzrP+2u+S{~km3(-Nf_fw3QGrX zIYpP(kh%m$&_DI&<%Au4&__-Q45Tli@^`9sSq_nPT_}U}Ro%q0tqumze#uc6*b%12 znF+cT88=$YA?1yUQuEls3$KZ?nxYKe@qjpHR_79S%B&uL{np+#LeEK3M4*yvUtK_O zMbo*G}BUDR$`zApwZnv|SB!+URw8+z8anS$TetXb8V)F3OS5cP$76Cn*V z`vZW~jprZGrVU<1kuXhuVIcAhG_>zBz#)yGiZMqvz2fae=N-DWcSCuF9Tqs2!>NM8 zM4RFAt5s7o$*i}@hj_Iq-2EUqez?3CRjUb)RN|NClCTT;TJ3|plrVa=L4>yJVzQ{pqO5Jc<{LV9dUEeKivp7- zl#_eoe#(lusY3FkS4T2IE#9-SzLKdSDxBYZWyPGH6&Udg)=*q3DhNi=v%r4kp6O2A$kR0#sEo3#T_y#yRn3h$HjhD*i)(sLSOU+OQ1>px+C5Of4cTlS*=W^ ze*D|nB|;8h&hf~tgJD0Wd+ekZ!U{b?wZ!uXFR@S34V=l1p|#!)d#(OBIC z1}grWZ}0D>DgoeuGg$C~5%X7B(A2%X{mD|}L}a?#0nlhx+`9Z&Me7=_DWhUErS1oF z7E{gmPY#+UXxxd6a4X5b#u4VcyyKgeWkHh^ZG#aCXjU&l!qL4p4tzUDzGki7-i#26 zNIA){#`41&@6a8k*rNQ?Z_F=klnNYLjxIQc_^Exr;~Wy? zqpXlmji)wqMKpvIbohdEA_GxwD_z)?u1w(&$|Ee5o73B?U_)TF$YV9I6Sry`gixAn zq_MhudwYJYPWfu;FnX+}CBY~750&w2!s~klH&V+A32zqVlCmdtPm6KOU;(dJ2EYR? zJfujVzJF(&J{ZIW+FfbA?u}Hx#}{+>a;MW4zEGDXKmfG!9}B*eFl2kq_;IJJys%tx zi@nQBAax_GJG@RV-!?K2D*2&y%oE}Dk`|k}U)It}9$yw($eSs@8F@8^PwU|;@1;zuvz;&*c8g`Wbtxaui zvfm9N>p#9$85$F?5?Q-%7+r+M)PsnrnO+3qwZC;*lk!bar)-JF%MwM?f{zLbd+(R5GV@wjQ@_A3u5Qd^D5>+ZLcWMg z1E_Z3Lj}DQUY;xZpg{Bvz9V>`POGC)LNLnVB^!JgD^vN7kk168IbXm2=BTMrrX6L& z1ev+T6>qo-?hSIZpW$sP9IWVX7&A{_dR(nHR~OfqnZkP0C`Bv+MZl*yXV?^OXyi8S zy^^&x%O6y|4Zj~0bLG5H~hdxmlRb@l1}~ z3ScHOBGq>VkdkCT0j($C+J=-Z4!wAkHnJIlAYHQEWY!PbWz)t)z^=_ow4|GIC>GZv z5W2O#Bq~!$vNF{rECa#+)6N-(KV~WuW!h|IDo!0IN=8}Z@R!ORhrf*sWQ~HP z7E+U1;j>PNL%s(pm643L+WHjNqq>v7oL?q%*VY~uOQ|oRKrEcl;3gezsl|j!_=~3} zld>+HC`wOG@IkC4TnLF~;8_}09-c%t)h)I-QLHaKoDhIPYEdE)wT@on*o!)G&RADg zaEB{5&fE5A%0wF;rZ@d7mifCV(&>7qZSvMvdcK13*-%<%{wqkd2<+6CLg++9Guc^_ z&mvLy-68MIsSFjs7d^9-eYNCoCj{<&i^q|iPju-Ff2|}K{M$Ae2LE~zNOXifk{shX z#C4Np>?(D~KBBH2zOcrP+`^37Pat)*_OHv&dYU}q3HocOFFt22w%OcN56egMEQVM|t4dO@ zKBL`}qPE3fZ1_;QEiIpzzxGp_J_7FkiEN*ijh-BoMB+~xo+5K0P#;6rQ-YpgMltqs zOFJs5y}oU_#W^VJmXu5ZoRg3pPc67x&bKkHx?(pR$hWGXUt=9a<<7DnGfa6XpZ*~w zN&kFbQrY_LjORbhQf;rmsI61&v_DFqdotZtU*-nOB-TUZc@a_-iH*&^G;}?vQMhln z6KK)*`j;%RqL8uxA|pG=#Czo!{`H`%9v%W=|(#q=5*GK>HZ+jb>b5nyWJ6?EbXm``9j{(Q67 zdRA6*U1YzLJ7o{Vx69xZAPyJuX>dED%UmnU>!R?_bOy1s0nn zXO}k^pvFiuxOWM5!K4ZMW;`FO?>KSmsFW<$ueVrdW9shua3Vx z`u5c@vRlW}gYNqRWd=OieUTH+0`q^ZVfgXKbN^|wj??)F&YqcZlLa8N#g%S)AKp2m z?)hf?0o(h!C!fSUDT>Y&n3-TUov@e7I_B36<*Bpk=2E5w% nK?tk;>BtWL<;(BO@5}GY@5}G=`~80a00960#ow950Q3?7Z3kaf literal 0 HcmV?d00001 diff --git a/vendor/github.com/cilium/charts/cilium-1.16.6.tgz b/vendor/github.com/cilium/charts/cilium-1.16.6.tgz new file mode 100644 index 0000000000000000000000000000000000000000..3e99630f9fe6bdd8434f4a84901dda2c47fab012 GIT binary patch literal 204717 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�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 literal 0 HcmV?d00001 diff --git a/vendor/github.com/cilium/charts/cilium-1.17.0-rc.1.tgz b/vendor/github.com/cilium/charts/cilium-1.17.0-rc.1.tgz new file mode 100644 index 0000000000000000000000000000000000000000..a9598d254ca63780314a35758c8b3d7dd89a89a4 GIT binary patch literal 217110 zcmV)2K+L}%iwG0|00000|0w_~VMtOiV@ORlOnEsqVl!4SWK%V1T2nbTPgYhoO;>Dc zVQyr3R8em|NM&qo0PMZ}a~nC5Ai6*EufU^Tob5f5BK2jP_h#c{Np|a6lDU%Hvm3J$ z7FY$67!?aO07^1@KmPU?$V{M6#iB%YyJu%_$9J*QVgZRnA^{}wGm)7rm%AqmuI*sO zm)YNa|9`{baCmfZ0RKB24jcbFI@;eK{@v){?ZI$=bg(}>_`Bg~@8Iz0@7VA+z-8@U zX)M=&H~iIOH7EC96o1Wvs?-L zsPz3rWina)OU~GX&_=3!%pUgKpE+NOF+;}6v2EenN?`{0>p-f1$vccO_Ae}zrpWl} z3OeBcj7DJ95UDVUmW733{>}ZuS{qAY0B)hxgG>eEX)0YOp0Qb(C-|SzuGmzpRGzZO z1-A%I8s8~p(-kw8=PB1I`>~t~oeN8VYm;ZDOcsnAW*36-sdSJLnpKQvnR;Ya^Vv)$ zY|4#DnabJ6e>}Z1J*G6X3Lws8W`${N z`ovPO)>VjxjivIt<-|i z^mYueV-|wZb48%T^^~+7IgHZ zuy~l5bO63izO_D{W~N54i0{};Y38vDyNj`0<^76>S-{(|=%19#0S3`=jX)PF;n}rF zr51_x>rSAb*!7v~rm5T33p2-$eeNH z8mm0XS!o1IxDkeB@}BmBN<|;XJ-xbdyZOiSA+)=|N7nH$CtjwwVUXEK31!BN3A&?;jOTuW6Nq>gV@+rrp| zyKmMYG@hr7yTjC$h8dA~paDZ*Kl-j_?k@o823e!#dFr;keeTYY*lhdjCWiY2X?-)| zEG8XYV6svnc$qt{5lN|CvkDJp!!<*&9EgO&hFr*GL2YL%W`qSoWPBV8Z?mBDjPh2>Y)dO*-YY68=O?1ixe-Ng&K1fZsMn;u75uVZn*ebZ~oGcN8 zdrBld%OBM01g?O!gPCX>6El)Xh3koz$1e~^VO&-XyrnQ2ck|a6O&&jKfs`>os~_LF zdrLpa#2qa~A@jKjBK}n1vbYJ06pw!za-od%FOhF6CUf_oNZ|AeYvEQ=e6uY_^ouC^ zGBQ3zwl+bum0T|%RS-mm6A@Eu?S%dCX)+PQiNvihqxM5~Ixh>tqYeO;wzQk5E}cM1?VPlw1-F%a1zibC1X&Zd%qD6O$G0-kMrsgWwy@GO z#Gui(+l)~M086~JMhra2;ho${6~guzYGLksbznmU!oUMpa!>L1R2+k6~Mn$`Jf?#g=7eWs%`w>G~Ts(`vbaN7fFZ51%H->4VT# z8n~ikiUG(csK(=tTbxNBK1~4R+JH||uGZQSt~4MUvsBDvj`OBVj;L6}i*dsqMV7h$ zg^$*1IW3(`9v|?bPYMr25L5Dp&n1 z`2-X-@qF10iWlo!F5Yk3Qe(r8+bqmS>_DsYG&594;jx}c0|$C-f$^RatNsJeO2G;) zwej1H7eywc_r8DsrZVBQ1vzR8m=T#sa1X9ueJAIq*Pq-YZmYv6k*UTf-!9tptMt1xI|qrNRomlzC7hdEwjb95{U4^+nJsCUUPqID=7Dt_Anc z>7HXK1O=Sd1F`-=a<8Pytxw*Mw7ed%FTsPx%0DBgV&l|Fa!G;kq7z`agfPd8Rz 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�A!9uE8+2|rS5`FKa_!r|0?Jis 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
92(@>gd+;~K7Sa)X%qW2Qn~lEfDKB@h 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 z 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 literal 0 HcmV?d00001 diff --git a/vendor/github.com/cilium/charts/index.yaml b/vendor/github.com/cilium/charts/index.yaml index 7c27ffee37..f9aa9b5f38 100644 --- a/vendor/github.com/cilium/charts/index.yaml +++ b/vendor/github.com/cilium/charts/index.yaml @@ -1,6 +1,112 @@ apiVersion: v1 entries: cilium: + - annotations: + artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n + \ displayName: Cilium Network Policy\n description: |\n Cilium Network + Policies provide additional functionality beyond what\n is provided by + standard Kubernetes NetworkPolicy such as the ability\n to allow traffic + based on FQDNs, or to filter at Layer 7.\n- kind: CiliumClusterwideNetworkPolicy\n + \ version: v2\n name: ciliumclusterwidenetworkpolicies.cilium.io\n displayName: + Cilium Clusterwide Network Policy\n description: |\n Cilium Clusterwide + Network Policies support configuring network traffic\n policiies across + the entire cluster, including applying node firewalls.\n- kind: CiliumExternalWorkload\n + \ version: v2\n name: ciliumexternalworkloads.cilium.io\n displayName: Cilium + External Workload\n description: |\n Cilium External Workload supports + configuring the ability for external\n non-Kubernetes workloads to join + the cluster.\n- kind: CiliumLocalRedirectPolicy\n version: v2\n name: ciliumlocalredirectpolicies.cilium.io\n + \ displayName: Cilium Local Redirect Policy\n description: |\n Cilium + Local Redirect Policy allows local redirects to be configured\n within + a node to support use cases like Node-Local DNS or KIAM.\n- kind: CiliumNode\n + \ version: v2\n name: ciliumnodes.cilium.io\n displayName: Cilium Node\n + \ description: |\n Cilium Node represents a node managed by Cilium. It + contains a\n specification to control various node specific configuration + aspects\n and a status section to represent the status of the node.\n- + kind: CiliumIdentity\n version: v2\n name: ciliumidentities.cilium.io\n + \ displayName: Cilium Identity\n description: |\n Cilium Identity allows + introspection into security identities that\n Cilium allocates which identify + sets of labels that are assigned to\n individual endpoints in the cluster.\n- + kind: CiliumEndpoint\n version: v2\n name: ciliumendpoints.cilium.io\n displayName: + Cilium Endpoint\n description: |\n Cilium Endpoint represents the status + of individual pods or nodes in\n the cluster which are managed by Cilium, + including enforcement status,\n IP addressing and whether the networking + is successfully operational.\n- kind: CiliumEndpointSlice\n version: v2alpha1\n + \ name: ciliumendpointslices.cilium.io\n displayName: Cilium Endpoint Slice\n + \ description: |\n Cilium Endpoint Slice represents the status of groups + of pods or nodes\n in the cluster which are managed by Cilium, including + enforcement status,\n IP addressing and whether the networking is successfully + operational.\n- kind: CiliumEgressGatewayPolicy\n version: v2\n name: ciliumegressgatewaypolicies.cilium.io\n + \ displayName: Cilium Egress Gateway Policy\n description: |\n Cilium + Egress Gateway Policy provides control over the way that traffic\n leaves + the cluster and which source addresses to use for that traffic.\n- kind: CiliumClusterwideEnvoyConfig\n + \ version: v2\n name: ciliumclusterwideenvoyconfigs.cilium.io\n displayName: + Cilium Clusterwide Envoy Config\n description: |\n Cilium Clusterwide + Envoy Config specifies Envoy resources and K8s service mappings\n to be + provisioned into Cilium host proxy instances in cluster context.\n- kind: + CiliumEnvoyConfig\n version: v2\n name: ciliumenvoyconfigs.cilium.io\n displayName: + Cilium Envoy Config\n description: |\n Cilium Envoy Config specifies Envoy + resources and K8s service mappings\n to be provisioned into Cilium host + proxy instances in namespace context.\n- kind: CiliumBGPPeeringPolicy\n version: + v2alpha1\n name: ciliumbgppeeringpolicies.cilium.io\n displayName: Cilium + BGP Peering Policy\n description: |\n Cilium BGP Peering Policy instructs + Cilium to create specific BGP peering\n configurations.\n- kind: CiliumBGPClusterConfig\n + \ version: v2alpha1\n name: ciliumbgpclusterconfigs.cilium.io\n displayName: + Cilium BGP Cluster Config\n description: |\n Cilium BGP Cluster Config + instructs Cilium operator to create specific BGP cluster\n configurations.\n- + kind: CiliumBGPPeerConfig\n version: v2alpha1\n name: ciliumbgppeerconfigs.cilium.io\n + \ displayName: Cilium BGP Peer Config\n description: |\n CiliumBGPPeerConfig + is a common set of BGP peer configurations. It can be referenced \n by + multiple peers from CiliumBGPClusterConfig.\n- kind: CiliumBGPAdvertisement\n + \ version: v2alpha1\n name: ciliumbgpadvertisements.cilium.io\n displayName: + Cilium BGP Advertisement\n description: |\n CiliumBGPAdvertisement is + used to define source of BGP advertisement as well as BGP attributes \n to + be advertised with those prefixes.\n- kind: CiliumBGPNodeConfig\n version: + v2alpha1\n name: ciliumbgpnodeconfigs.cilium.io\n displayName: Cilium BGP + Node Config\n description: |\n CiliumBGPNodeConfig is read only node specific + BGP configuration. It is constructed by Cilium operator.\n It will also + contain node local BGP state information.\n- kind: CiliumBGPNodeConfigOverride\n + \ version: v2alpha1\n name: ciliumbgpnodeconfigoverrides.cilium.io\n displayName: + Cilium BGP Node Config Override\n description: |\n CiliumBGPNodeConfigOverride + can be used to override node specific BGP configuration.\n- kind: CiliumLoadBalancerIPPool\n + \ version: v2alpha1\n name: ciliumloadbalancerippools.cilium.io\n displayName: + Cilium Load Balancer IP Pool\n description: |\n Defining a Cilium Load + Balancer IP Pool instructs Cilium to assign IPs to LoadBalancer Services.\n- + kind: CiliumNodeConfig\n version: v2alpha1\n name: ciliumnodeconfigs.cilium.io\n + \ displayName: Cilium Node Configuration\n description: |\n CiliumNodeConfig + is a list of configuration key-value pairs. It is applied to\n nodes indicated + by a label selector.\n- kind: CiliumCIDRGroup\n version: v2alpha1\n name: + ciliumcidrgroups.cilium.io\n displayName: Cilium CIDR Group\n description: + |\n CiliumCIDRGroup is a list of CIDRs that can be referenced as a single + entity from CiliumNetworkPolicies.\n- kind: CiliumL2AnnouncementPolicy\n version: + v2alpha1\n name: ciliuml2announcementpolicies.cilium.io\n displayName: Cilium + L2 Announcement Policy\n description: |\n CiliumL2AnnouncementPolicy is + a policy which determines which service IPs will be announced to\n the + local area network, by which nodes, and via which interfaces.\n- kind: CiliumPodIPPool\n + \ version: v2alpha1\n name: ciliumpodippools.cilium.io\n displayName: Cilium + Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that + can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" + apiVersion: v2 + appVersion: 1.17.0-rc.1 + created: "2025-01-10T22:01:41.151165757Z" + description: eBPF-based Networking, Security, and Observability + digest: a36edb4958505bff7ecb2605050fa8773d194a1ea7846e3bcc7824a9a8f5e987 + home: https://cilium.io/ + icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg + keywords: + - BPF + - eBPF + - Kubernetes + - Networking + - Security + - Observability + - Troubleshooting + kubeVersion: '>= 1.21.0-0' + name: cilium + sources: + - https://github.com/cilium/cilium + urls: + - cilium-1.17.0-rc.1.tgz + version: 1.17.0-rc.1 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -531,6 +637,112 @@ entries: urls: - cilium-1.17.0-pre.0.tgz version: 1.17.0-pre.0 + - annotations: + artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n + \ displayName: Cilium Network Policy\n description: |\n Cilium Network + Policies provide additional functionality beyond what\n is provided by + standard Kubernetes NetworkPolicy such as the ability\n to allow traffic + based on FQDNs, or to filter at Layer 7.\n- kind: CiliumClusterwideNetworkPolicy\n + \ version: v2\n name: ciliumclusterwidenetworkpolicies.cilium.io\n displayName: + Cilium Clusterwide Network Policy\n description: |\n Cilium Clusterwide + Network Policies support configuring network traffic\n policiies across + the entire cluster, including applying node firewalls.\n- kind: CiliumExternalWorkload\n + \ version: v2\n name: ciliumexternalworkloads.cilium.io\n displayName: Cilium + External Workload\n description: |\n Cilium External Workload supports + configuring the ability for external\n non-Kubernetes workloads to join + the cluster.\n- kind: CiliumLocalRedirectPolicy\n version: v2\n name: ciliumlocalredirectpolicies.cilium.io\n + \ displayName: Cilium Local Redirect Policy\n description: |\n Cilium + Local Redirect Policy allows local redirects to be configured\n within + a node to support use cases like Node-Local DNS or KIAM.\n- kind: CiliumNode\n + \ version: v2\n name: ciliumnodes.cilium.io\n displayName: Cilium Node\n + \ description: |\n Cilium Node represents a node managed by Cilium. It + contains a\n specification to control various node specific configuration + aspects\n and a status section to represent the status of the node.\n- + kind: CiliumIdentity\n version: v2\n name: ciliumidentities.cilium.io\n + \ displayName: Cilium Identity\n description: |\n Cilium Identity allows + introspection into security identities that\n Cilium allocates which identify + sets of labels that are assigned to\n individual endpoints in the cluster.\n- + kind: CiliumEndpoint\n version: v2\n name: ciliumendpoints.cilium.io\n displayName: + Cilium Endpoint\n description: |\n Cilium Endpoint represents the status + of individual pods or nodes in\n the cluster which are managed by Cilium, + including enforcement status,\n IP addressing and whether the networking + is successfully operational.\n- kind: CiliumEndpointSlice\n version: v2alpha1\n + \ name: ciliumendpointslices.cilium.io\n displayName: Cilium Endpoint Slice\n + \ description: |\n Cilium Endpoint Slice represents the status of groups + of pods or nodes\n in the cluster which are managed by Cilium, including + enforcement status,\n IP addressing and whether the networking is successfully + operational.\n- kind: CiliumEgressGatewayPolicy\n version: v2\n name: ciliumegressgatewaypolicies.cilium.io\n + \ displayName: Cilium Egress Gateway Policy\n description: |\n Cilium + Egress Gateway Policy provides control over the way that traffic\n leaves + the cluster and which source addresses to use for that traffic.\n- kind: CiliumClusterwideEnvoyConfig\n + \ version: v2\n name: ciliumclusterwideenvoyconfigs.cilium.io\n displayName: + Cilium Clusterwide Envoy Config\n description: |\n Cilium Clusterwide + Envoy Config specifies Envoy resources and K8s service mappings\n to be + provisioned into Cilium host proxy instances in cluster context.\n- kind: + CiliumEnvoyConfig\n version: v2\n name: ciliumenvoyconfigs.cilium.io\n displayName: + Cilium Envoy Config\n description: |\n Cilium Envoy Config specifies Envoy + resources and K8s service mappings\n to be provisioned into Cilium host + proxy instances in namespace context.\n- kind: CiliumBGPPeeringPolicy\n version: + v2alpha1\n name: ciliumbgppeeringpolicies.cilium.io\n displayName: Cilium + BGP Peering Policy\n description: |\n Cilium BGP Peering Policy instructs + Cilium to create specific BGP peering\n configurations.\n- kind: CiliumBGPClusterConfig\n + \ version: v2alpha1\n name: ciliumbgpclusterconfigs.cilium.io\n displayName: + Cilium BGP Cluster Config\n description: |\n Cilium BGP Cluster Config + instructs Cilium operator to create specific BGP cluster\n configurations.\n- + kind: CiliumBGPPeerConfig\n version: v2alpha1\n name: ciliumbgppeerconfigs.cilium.io\n + \ displayName: Cilium BGP Peer Config\n description: |\n CiliumBGPPeerConfig + is a common set of BGP peer configurations. It can be referenced \n by + multiple peers from CiliumBGPClusterConfig.\n- kind: CiliumBGPAdvertisement\n + \ version: v2alpha1\n name: ciliumbgpadvertisements.cilium.io\n displayName: + Cilium BGP Advertisement\n description: |\n CiliumBGPAdvertisement is + used to define source of BGP advertisement as well as BGP attributes \n to + be advertised with those prefixes.\n- kind: CiliumBGPNodeConfig\n version: + v2alpha1\n name: ciliumbgpnodeconfigs.cilium.io\n displayName: Cilium BGP + Node Config\n description: |\n CiliumBGPNodeConfig is read only node specific + BGP configuration. It is constructed by Cilium operator.\n It will also + contain node local BGP state information.\n- kind: CiliumBGPNodeConfigOverride\n + \ version: v2alpha1\n name: ciliumbgpnodeconfigoverrides.cilium.io\n displayName: + Cilium BGP Node Config Override\n description: |\n CiliumBGPNodeConfigOverride + can be used to override node specific BGP configuration.\n- kind: CiliumLoadBalancerIPPool\n + \ version: v2alpha1\n name: ciliumloadbalancerippools.cilium.io\n displayName: + Cilium Load Balancer IP Pool\n description: |\n Defining a Cilium Load + Balancer IP Pool instructs Cilium to assign IPs to LoadBalancer Services.\n- + kind: CiliumNodeConfig\n version: v2alpha1\n name: ciliumnodeconfigs.cilium.io\n + \ displayName: Cilium Node Configuration\n description: |\n CiliumNodeConfig + is a list of configuration key-value pairs. It is applied to\n nodes indicated + by a label selector.\n- kind: CiliumCIDRGroup\n version: v2alpha1\n name: + ciliumcidrgroups.cilium.io\n displayName: Cilium CIDR Group\n description: + |\n CiliumCIDRGroup is a list of CIDRs that can be referenced as a single + entity from CiliumNetworkPolicies.\n- kind: CiliumL2AnnouncementPolicy\n version: + v2alpha1\n name: ciliuml2announcementpolicies.cilium.io\n displayName: Cilium + L2 Announcement Policy\n description: |\n CiliumL2AnnouncementPolicy is + a policy which determines which service IPs will be announced to\n the + local area network, by which nodes, and via which interfaces.\n- kind: CiliumPodIPPool\n + \ version: v2alpha1\n name: ciliumpodippools.cilium.io\n displayName: Cilium + Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that + can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" + apiVersion: v2 + appVersion: 1.16.6 + created: "2025-01-22T00:49:12.609546824Z" + description: eBPF-based Networking, Security, and Observability + digest: 99990b032e98124740138de055a473e5edaa9c5622e6be59b2f6d1733eb943d8 + home: https://cilium.io/ + icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg + keywords: + - BPF + - eBPF + - Kubernetes + - Networking + - Security + - Observability + - Troubleshooting + kubeVersion: '>= 1.21.0-0' + name: cilium + sources: + - https://github.com/cilium/cilium + urls: + - cilium-1.16.6.tgz + version: 1.16.6 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -2015,6 +2227,112 @@ entries: urls: - cilium-1.16.0-dev.tgz version: 1.16.0-dev + - annotations: + artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n + \ displayName: Cilium Network Policy\n description: |\n Cilium Network + Policies provide additional functionality beyond what\n is provided by + standard Kubernetes NetworkPolicy such as the ability\n to allow traffic + based on FQDNs, or to filter at Layer 7.\n- kind: CiliumClusterwideNetworkPolicy\n + \ version: v2\n name: ciliumclusterwidenetworkpolicies.cilium.io\n displayName: + Cilium Clusterwide Network Policy\n description: |\n Cilium Clusterwide + Network Policies support configuring network traffic\n policiies across + the entire cluster, including applying node firewalls.\n- kind: CiliumExternalWorkload\n + \ version: v2\n name: ciliumexternalworkloads.cilium.io\n displayName: Cilium + External Workload\n description: |\n Cilium External Workload supports + configuring the ability for external\n non-Kubernetes workloads to join + the cluster.\n- kind: CiliumLocalRedirectPolicy\n version: v2\n name: ciliumlocalredirectpolicies.cilium.io\n + \ displayName: Cilium Local Redirect Policy\n description: |\n Cilium + Local Redirect Policy allows local redirects to be configured\n within + a node to support use cases like Node-Local DNS or KIAM.\n- kind: CiliumNode\n + \ version: v2\n name: ciliumnodes.cilium.io\n displayName: Cilium Node\n + \ description: |\n Cilium Node represents a node managed by Cilium. It + contains a\n specification to control various node specific configuration + aspects\n and a status section to represent the status of the node.\n- + kind: CiliumIdentity\n version: v2\n name: ciliumidentities.cilium.io\n + \ displayName: Cilium Identity\n description: |\n Cilium Identity allows + introspection into security identities that\n Cilium allocates which identify + sets of labels that are assigned to\n individual endpoints in the cluster.\n- + kind: CiliumEndpoint\n version: v2\n name: ciliumendpoints.cilium.io\n displayName: + Cilium Endpoint\n description: |\n Cilium Endpoint represents the status + of individual pods or nodes in\n the cluster which are managed by Cilium, + including enforcement status,\n IP addressing and whether the networking + is successfully operational.\n- kind: CiliumEndpointSlice\n version: v2alpha1\n + \ name: ciliumendpointslices.cilium.io\n displayName: Cilium Endpoint Slice\n + \ description: |\n Cilium Endpoint Slice represents the status of groups + of pods or nodes\n in the cluster which are managed by Cilium, including + enforcement status,\n IP addressing and whether the networking is successfully + operational.\n- kind: CiliumEgressGatewayPolicy\n version: v2\n name: ciliumegressgatewaypolicies.cilium.io\n + \ displayName: Cilium Egress Gateway Policy\n description: |\n Cilium + Egress Gateway Policy provides control over the way that traffic\n leaves + the cluster and which source addresses to use for that traffic.\n- kind: CiliumClusterwideEnvoyConfig\n + \ version: v2\n name: ciliumclusterwideenvoyconfigs.cilium.io\n displayName: + Cilium Clusterwide Envoy Config\n description: |\n Cilium Clusterwide + Envoy Config specifies Envoy resources and K8s service mappings\n to be + provisioned into Cilium host proxy instances in cluster context.\n- kind: + CiliumEnvoyConfig\n version: v2\n name: ciliumenvoyconfigs.cilium.io\n displayName: + Cilium Envoy Config\n description: |\n Cilium Envoy Config specifies Envoy + resources and K8s service mappings\n to be provisioned into Cilium host + proxy instances in namespace context.\n- kind: CiliumBGPPeeringPolicy\n version: + v2alpha1\n name: ciliumbgppeeringpolicies.cilium.io\n displayName: Cilium + BGP Peering Policy\n description: |\n Cilium BGP Peering Policy instructs + Cilium to create specific BGP peering\n configurations.\n- kind: CiliumBGPClusterConfig\n + \ version: v2alpha1\n name: ciliumbgpclusterconfigs.cilium.io\n displayName: + Cilium BGP Cluster Config\n description: |\n Cilium BGP Cluster Config + instructs Cilium operator to create specific BGP cluster\n configurations.\n- + kind: CiliumBGPPeerConfig\n version: v2alpha1\n name: ciliumbgppeerconfigs.cilium.io\n + \ displayName: Cilium BGP Peer Config\n description: |\n CiliumBGPPeerConfig + is a common set of BGP peer configurations. It can be referenced \n by + multiple peers from CiliumBGPClusterConfig.\n- kind: CiliumBGPAdvertisement\n + \ version: v2alpha1\n name: ciliumbgpadvertisements.cilium.io\n displayName: + Cilium BGP Advertisement\n description: |\n CiliumBGPAdvertisement is + used to define source of BGP advertisement as well as BGP attributes \n to + be advertised with those prefixes.\n- kind: CiliumBGPNodeConfig\n version: + v2alpha1\n name: ciliumbgpnodeconfigs.cilium.io\n displayName: Cilium BGP + Node Config\n description: |\n CiliumBGPNodeConfig is read only node specific + BGP configuration. It is constructed by Cilium operator.\n It will also + contain node local BGP state information.\n- kind: CiliumBGPNodeConfigOverride\n + \ version: v2alpha1\n name: ciliumbgpnodeconfigoverrides.cilium.io\n displayName: + Cilium BGP Node Config Override\n description: |\n CiliumBGPNodeConfigOverride + can be used to override node specific BGP configuration.\n- kind: CiliumLoadBalancerIPPool\n + \ version: v2alpha1\n name: ciliumloadbalancerippools.cilium.io\n displayName: + Cilium Load Balancer IP Pool\n description: |\n Defining a Cilium Load + Balancer IP Pool instructs Cilium to assign IPs to LoadBalancer Services.\n- + kind: CiliumNodeConfig\n version: v2alpha1\n name: ciliumnodeconfigs.cilium.io\n + \ displayName: Cilium Node Configuration\n description: |\n CiliumNodeConfig + is a list of configuration key-value pairs. It is applied to\n nodes indicated + by a label selector.\n- kind: CiliumCIDRGroup\n version: v2alpha1\n name: + ciliumcidrgroups.cilium.io\n displayName: Cilium CIDR Group\n description: + |\n CiliumCIDRGroup is a list of CIDRs that can be referenced as a single + entity from CiliumNetworkPolicies.\n- kind: CiliumL2AnnouncementPolicy\n version: + v2alpha1\n name: ciliuml2announcementpolicies.cilium.io\n displayName: Cilium + L2 Announcement Policy\n description: |\n CiliumL2AnnouncementPolicy is + a policy which determines which service IPs will be announced to\n the + local area network, by which nodes, and via which interfaces.\n- kind: CiliumPodIPPool\n + \ version: v2alpha1\n name: ciliumpodippools.cilium.io\n displayName: Cilium + Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that + can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" + apiVersion: v2 + appVersion: 1.15.13 + created: "2025-01-22T00:43:41.296346726Z" + description: eBPF-based Networking, Security, and Observability + digest: d6cef9f20e13e81945974af6b6250c18ffbd23fd63b1eb2963e5e27748946f7f + home: https://cilium.io/ + icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg + keywords: + - BPF + - eBPF + - Kubernetes + - Networking + - Security + - Observability + - Troubleshooting + kubeVersion: '>= 1.16.0-0' + name: cilium + sources: + - https://github.com/cilium/cilium + urls: + - cilium-1.15.13.tgz + version: 1.15.13 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -4231,6 +4549,151 @@ entries: description: | CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode). apiVersion: v2 + appVersion: 1.14.19 + created: "2025-01-22T00:08:28.010045937Z" + description: eBPF-based Networking, Security, and Observability + digest: fc402d6f21ad6bb203e050c86bf96bdb894e6349a90d310594f8e57b037bc697 + home: https://cilium.io/ + icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg + keywords: + - BPF + - eBPF + - Kubernetes + - Networking + - Security + - Observability + - Troubleshooting + kubeVersion: '>= 1.16.0-0' + name: cilium + sources: + - https://github.com/cilium/cilium + urls: + - cilium-1.14.19.tgz + version: 1.14.19 + - annotations: + artifacthub.io/crds: | + - kind: CiliumNetworkPolicy + version: v2 + name: ciliumnetworkpolicies.cilium.io + displayName: Cilium Network Policy + description: | + Cilium Network Policies provide additional functionality beyond what + is provided by standard Kubernetes NetworkPolicy such as the ability + to allow traffic based on FQDNs, or to filter at Layer 7. + - kind: CiliumClusterwideNetworkPolicy + version: v2 + name: ciliumclusterwidenetworkpolicies.cilium.io + displayName: Cilium Clusterwide Network Policy + description: | + Cilium Clusterwide Network Policies support configuring network traffic + policiies across the entire cluster, including applying node firewalls. + - kind: CiliumExternalWorkload + version: v2 + name: ciliumexternalworkloads.cilium.io + displayName: Cilium External Workload + description: | + Cilium External Workload supports configuring the ability for external + non-Kubernetes workloads to join the cluster. + - kind: CiliumLocalRedirectPolicy + version: v2 + name: ciliumlocalredirectpolicies.cilium.io + displayName: Cilium Local Redirect Policy + description: | + Cilium Local Redirect Policy allows local redirects to be configured + within a node to support use cases like Node-Local DNS or KIAM. + - kind: CiliumNode + version: v2 + name: ciliumnodes.cilium.io + displayName: Cilium Node + description: | + Cilium Node represents a node managed by Cilium. It contains a + specification to control various node specific configuration aspects + and a status section to represent the status of the node. + - kind: CiliumIdentity + version: v2 + name: ciliumidentities.cilium.io + displayName: Cilium Identity + description: | + Cilium Identity allows introspection into security identities that + Cilium allocates which identify sets of labels that are assigned to + individual endpoints in the cluster. + - kind: CiliumEndpoint + version: v2 + name: ciliumendpoints.cilium.io + displayName: Cilium Endpoint + description: | + Cilium Endpoint represents the status of individual pods or nodes in + the cluster which are managed by Cilium, including enforcement status, + IP addressing and whether the networking is succesfully operational. + - kind: CiliumEndpointSlice + version: v2alpha1 + name: ciliumendpointslices.cilium.io + displayName: Cilium Endpoint Slice + description: | + Cilium Endpoint Slice represents the status of groups of pods or nodes + in the cluster which are managed by Cilium, including enforcement status, + IP addressing and whether the networking is succesfully operational. + - kind: CiliumEgressGatewayPolicy + version: v2 + name: ciliumegressgatewaypolicies.cilium.io + displayName: Cilium Egress Gateway Policy + description: | + Cilium Egress Gateway Policy provides control over the way that traffic + leaves the cluster and which source addresses to use for that traffic. + - kind: CiliumClusterwideEnvoyConfig + version: v2 + name: ciliumclusterwideenvoyconfigs.cilium.io + displayName: Cilium Clusterwide Envoy Config + description: | + Cilium Clusterwide Envoy Config specifies Envoy resources and K8s service mappings + to be provisioned into Cilium host proxy instances in cluster context. + - kind: CiliumEnvoyConfig + version: v2 + name: ciliumenvoyconfigs.cilium.io + displayName: Cilium Envoy Config + description: | + Cilium Envoy Config specifies Envoy resources and K8s service mappings + to be provisioned into Cilium host proxy instances in namespace context. + - kind: CiliumBGPPeeringPolicy + version: v2alpha1 + name: ciliumbgppeeringpolicies.cilium.io + displayName: Cilium BGP Peering Policy + description: | + Cilium BGP Peering Policy instructs Cilium to create specific BGP peering + configurations. + - kind: CiliumLoadBalancerIPPool + version: v2alpha1 + name: ciliumloadbalancerippools.cilium.io + displayName: Cilium Load Balancer IP Pool + description: | + Defining a Cilium Load Balancer IP Pool instructs Cilium to assign IPs to LoadBalancer Services. + - kind: CiliumNodeConfig + version: v2alpha1 + name: ciliumnodeconfigs.cilium.io + displayName: Cilium Node Configuration + description: | + CiliumNodeConfig is a list of configuration key-value pairs. It is applied to + nodes indicated by a label selector. + - kind: CiliumCIDRGroup + version: v2alpha1 + name: ciliumcidrgroups.cilium.io + displayName: Cilium CIDR Group + description: | + CiliumCIDRGroup is a list of CIDRs that can be referenced as a single entity from CiliumNetworkPolicies. + - kind: CiliumL2AnnouncementPolicy + version: v2alpha1 + name: ciliuml2announcementpolicies.cilium.io + displayName: Cilium L2 Announcement Policy + description: | + CiliumL2AnnouncementPolicy is a policy which determines which service IPs will be announced to + the local area network, by which nodes, and via which interfaces. + - kind: CiliumPodIPPool + version: v2alpha1 + name: ciliumpodippools.cilium.io + displayName: Cilium Pod IP Pool + description: | + CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode). + apiVersion: v2 appVersion: 1.14.18 created: "2024-12-17T12:12:06.952086209Z" description: eBPF-based Networking, Security, and Observability @@ -21606,4 +22069,4 @@ entries: urls: - tetragon-0.8.0.tgz version: 0.8.0 -generated: "2024-12-18T15:38:28.689656249Z" +generated: "2025-01-22T00:49:12.598906696Z" diff --git a/vendor/github.com/cilium/cilium/api/v1/flow/flow.pb.go b/vendor/github.com/cilium/cilium/api/v1/flow/flow.pb.go index 199c59e375..8038657a7f 100644 --- a/vendor/github.com/cilium/cilium/api/v1/flow/flow.pb.go +++ b/vendor/github.com/cilium/cilium/api/v1/flow/flow.pb.go @@ -3,8 +3,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.1 -// protoc v5.29.2 +// protoc-gen-go v1.36.3 +// protoc v5.29.3 // source: flow/flow.proto package flow diff --git a/vendor/github.com/cilium/cilium/api/v1/observer/observer.pb.go b/vendor/github.com/cilium/cilium/api/v1/observer/observer.pb.go index 7654042313..d2bd54a84e 100644 --- a/vendor/github.com/cilium/cilium/api/v1/observer/observer.pb.go +++ b/vendor/github.com/cilium/cilium/api/v1/observer/observer.pb.go @@ -3,8 +3,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.1 -// protoc v5.29.2 +// protoc-gen-go v1.36.3 +// protoc v5.29.3 // source: observer/observer.proto package observer diff --git a/vendor/github.com/cilium/cilium/api/v1/observer/observer_grpc.pb.go b/vendor/github.com/cilium/cilium/api/v1/observer/observer_grpc.pb.go index 362fb5b170..f9e149cf81 100644 --- a/vendor/github.com/cilium/cilium/api/v1/observer/observer_grpc.pb.go +++ b/vendor/github.com/cilium/cilium/api/v1/observer/observer_grpc.pb.go @@ -4,7 +4,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.5.1 -// - protoc v5.29.2 +// - protoc v5.29.3 // source: observer/observer.proto package observer diff --git a/vendor/github.com/cilium/cilium/api/v1/relay/relay.pb.go b/vendor/github.com/cilium/cilium/api/v1/relay/relay.pb.go index cb38575371..abf656c07b 100644 --- a/vendor/github.com/cilium/cilium/api/v1/relay/relay.pb.go +++ b/vendor/github.com/cilium/cilium/api/v1/relay/relay.pb.go @@ -3,8 +3,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.1 -// protoc v5.29.2 +// protoc-gen-go v1.36.3 +// protoc v5.29.3 // source: relay/relay.proto package relay diff --git a/vendor/github.com/cilium/cilium/cilium-cli/cli/cmd.go b/vendor/github.com/cilium/cilium/cilium-cli/cli/cmd.go index 9dfa1d364a..ed4c33a9b3 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/cli/cmd.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/cli/cmd.go @@ -39,7 +39,7 @@ func NewCiliumCommand(hooks api.Hooks) *cobra.Command { return nil } switch cmd.Name() { - case "completion", "help": + case "completion", "help", "summary": return nil case "version": if clientFlag, err := cmd.Flags().GetBool("client"); err == nil && clientFlag { diff --git a/vendor/github.com/cilium/cilium/cilium-cli/cli/connectivity.go b/vendor/github.com/cilium/cilium/cilium-cli/cli/connectivity.go index 117420aa09..25f61d95ae 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/cli/connectivity.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/cli/connectivity.go @@ -21,6 +21,7 @@ import ( "github.com/cilium/cilium/cilium-cli/connectivity/check" "github.com/cilium/cilium/cilium-cli/defaults" "github.com/cilium/cilium/cilium-cli/sysdump" + "github.com/cilium/cilium/cilium-cli/utils/features" "github.com/cilium/cilium/pkg/option" ) @@ -190,6 +191,7 @@ func newCmdConnectivityTest(hooks api.Hooks) *cobra.Command { cmd.Flags().DurationVar(¶ms.Timeout, "timeout", defaults.ConnectivityTestSuiteTimeout, "Maximum time to allow the connectivity test suite to take") cmd.Flags().IntVar(¶ms.TestConcurrency, "test-concurrency", 1, "Count of namespaces to perform the connectivity tests in parallel (value <= 0 will be treated as 1)") + cmd.Flags().StringSliceVar(¶ms.IPFamilies, "ip-families", []string{features.IPFamilyV4.String(), features.IPFamilyV6.String()}, "Restrict test actions to specific IP families") hooks.AddConnectivityTestFlags(cmd.Flags()) diff --git a/vendor/github.com/cilium/cilium/cilium-cli/cli/features.go b/vendor/github.com/cilium/cilium/cilium-cli/cli/features.go index 1532e5e86f..3f0e4b1028 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/cli/features.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/cli/features.go @@ -5,6 +5,7 @@ package cli import ( "context" + "fmt" "time" "github.com/spf13/cobra" @@ -21,6 +22,36 @@ func newCmdFeatures() *cobra.Command { Aliases: []string{"fs"}, } cmd.AddCommand(newCmdFeaturesStatus()) + cmd.AddCommand(newCmdFeaturesGH()) + return cmd +} + +func newCmdFeaturesGH() *cobra.Command { + params := features.Parameters{} + cmd := &cobra.Command{ + Use: "summary", + Short: "Stores and generates the summary for the features tested on a CI run", + Long: "This command will connect to GitHub to retrieve the metrics generated\n" + + "on a CI run and will generate a summary with the report.\n" + + "Requires a GitHub Token in GITHUB_TOKEN env variable with permissions to access contents. Direct Link:\n" + + "https://github.com/settings/tokens/new?description=CI%20Summary%20Generator&scopes=public_repo", + RunE: func(_ *cobra.Command, _ []string) error { + s := features.NewFeatures(nil, params) + if params.Commit == "" { + return fmt.Errorf("commit flag is not set") + } + if err := s.GenSummary(context.Background()); err != nil { + fatalf("Unable to generate summary features status: %s", err) + } + return nil + }, + } + cmd.Flags().StringVarP(¶ms.MetricsDirectory, "metrics-directory", "", "ci-features-metrics", "Directory where the metrics are saved from GitHub.") + cmd.Flags().StringVarP(¶ms.Repo, "repo", "r", "cilium/cilium", "Repository to retrieve the metrics from CI.") + cmd.Flags().StringVarP(¶ms.Commit, "commit", "c", "", "Commit SHA to retrieve the metrics.") + cmd.Flags().BoolVarP(¶ms.GHStepSummaryAnchor, "anchor", "a", false, "Add workaround HTML anchor to generated markdown (For GitHub step summary).") + cmd.Flags().StringVarP(¶ms.Output, "output", "o", "markdown", "Output format. One of: markdown") + cmd.Flags().StringVarP(¶ms.Outputfile, "output-file", "", "-", "Outputs into a file. Defaults to stdout") return cmd } diff --git a/vendor/github.com/cilium/cilium/cilium-cli/cli/install.go b/vendor/github.com/cilium/cilium/cilium-cli/cli/install.go index 7da5974bc6..c2cf4200a0 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/cli/install.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/cli/install.go @@ -90,6 +90,7 @@ cilium install --context kind-cluster1 --set cluster.id=1 --set cluster.name=clu cmd.Flags().BoolVar(¶ms.DryRun, "dry-run", false, "Write resources to be installed to stdout without actually installing them") cmd.Flags().BoolVar(¶ms.DryRunHelmValues, "dry-run-helm-values", false, "Write non-default Helm values to stdout without performing the actual installation") cmd.Flags().StringVar(¶ms.HelmRepository, "repository", defaults.HelmRepository, "Helm chart repository to download Cilium charts from") + cmd.Flags().IntVar(¶ms.HelmMaxHistory, "history-max", defaults.HelmMaxHistory, "limit the maximum number of revisions saved per release. Use 0 for no limit") return cmd } @@ -176,6 +177,7 @@ cilium upgrade --set cluster.id=1 --set cluster.name=cluster1 RunE: func(cmd *cobra.Command, _ []string) error { params.Namespace = namespace params.HelmReleaseName = helmReleaseName + // Don't log anything if it's a dry run so that the dry run output can easily be piped to other commands. if params.IsDryRun() { params.Writer = io.Discard @@ -205,6 +207,7 @@ cilium upgrade --set cluster.id=1 --set cluster.name=cluster1 cmd.Flags().BoolVar(¶ms.DryRunHelmValues, "dry-run-helm-values", false, "Write non-default Helm values to stdout; without performing the actual upgrade") cmd.Flags().StringVar(¶ms.HelmRepository, "repository", defaults.HelmRepository, "Helm chart repository to download Cilium charts from") + cmd.Flags().IntVar(¶ms.HelmMaxHistory, "history-max", defaults.HelmMaxHistory, "limit the maximum number of revisions saved per release. Use 0 for no limit") return cmd } diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/client_egress_l7_set_header.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/client_egress_l7_set_header.go index a8028c2e3c..8f90a9ed38 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/client_egress_l7_set_header.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/client_egress_l7_set_header.go @@ -42,8 +42,18 @@ func clientEgressL7SetHeaderTest(ct *check.ConnectivityTest, templates map[strin }). WithCiliumPolicy(templates[templateName]). // L7 allow policy with HTTP introspection (POST only) WithScenarios( - tests.PodToPodWithEndpoints(tests.WithMethod("POST"), tests.WithPath("auth-header-required"), tests.WithDestinationLabelsOption(map[string]string{"other": "echo"})), - tests.PodToPodWithEndpoints(tests.WithMethod("POST"), tests.WithPath("auth-header-required"), tests.WithDestinationLabelsOption(map[string]string{"first": "echo"})), + tests.PodToPodWithEndpoints( + tests.WithMethod("POST"), + tests.WithPath("auth-header-required"), + tests.WithDestinationLabelsOption(map[string]string{"other": "echo"}), + tests.WithRetryCondition(tests.WithRetryAll()), + ), + tests.PodToPodWithEndpoints( + tests.WithMethod("POST"), + tests.WithPath("auth-header-required"), + tests.WithDestinationLabelsOption(map[string]string{"first": "echo"}), + tests.WithRetryCondition(tests.WithRetryAll()), + ), ). WithExpectations(func(a *check.Action) (egress, ingress check.Result) { if a.Source().HasLabel("other", "client") && // Only client2 has the header policy. diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/client_egress_l7_tls_headers.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/client_egress_l7_tls_headers.go index ea551b0738..30525d402f 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/client_egress_l7_tls_headers.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/client_egress_l7_tls_headers.go @@ -13,6 +13,7 @@ type clientEgressL7TlsHeaders struct{} func (t clientEgressL7TlsHeaders) build(ct *check.ConnectivityTest, templates map[string]string) { clientEgressL7TlsHeadersTest(ct, templates, false) + clientEgressL7ExtraTlsHeadersTest(ct, templates) if ct.Features[features.L7PortRanges].Enabled { clientEgressL7TlsHeadersTest(ct, templates, true) } @@ -33,7 +34,34 @@ func clientEgressL7TlsHeadersTest(ct *check.ConnectivityTest, templates map[stri WithCertificate("externaltarget-tls", ct.Params().ExternalTarget). WithCiliumPolicy(yamlFile). // L7 allow policy with TLS interception WithCiliumPolicy(templates["clientEgressOnlyDNSPolicyYAML"]). // DNS resolution only - WithScenarios(tests.PodToWorldWithTLSIntercept("-H", "X-Very-Secret-Token: 42")). + WithScenarios(tests.PodToWorldWithTLSIntercept( + "-H", "X-Very-Secret-Token: 42", + "--retry", "5", + "--retry-delay", "0", + "--retry-all-errors")). + WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { + return check.ResultOK, check.ResultNone + }) +} + +func clientEgressL7ExtraTlsHeadersTest(ct *check.ConnectivityTest, templates map[string]string) { + testName := "seq-client-egress-l7-extra-tls-headers" + yamlFile := templates["clientEgressL7TLSPolicyYAML"] + // Test L7 HTTPS interception using an egress policy on the clients. + newTest(testName, ct). + WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). + WithFeatureRequirements(features.RequireEnabled(features.PolicySecretBackendK8s)). + WithFeatureRequirements(features.RequireEnabled(features.PolicySecretSync)). + WithCABundleSecret(). + WithCertificate("externaltarget-tls", ct.Params().ExternalTarget). // Only one certificate for ExternalTarget + WithCiliumPolicy(yamlFile). // L7 allow policy with TLS interception + WithCiliumPolicy(templates["clientEgressOnlyDNSPolicyYAML"]). // DNS resolution only + WithScenarios(tests.PodToWorldWithExtraTLSIntercept( + "externaltarget-tls", + "-H", "X-Very-Secret-Token: 42", + "--retry", "5", + "--retry-delay", "0", + "--retry-all-errors")). WithExpectations(func(_ *check.Action) (egress, ingress check.Result) { return check.ResultOK, check.ResultNone }) diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/client_egress_tls_sni.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/client_egress_tls_sni.go index 2a465046c9..2060ad3d39 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/client_egress_tls_sni.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/client_egress_tls_sni.go @@ -4,6 +4,8 @@ package builder import ( + "fmt" + "github.com/cilium/cilium/cilium-cli/connectivity/check" "github.com/cilium/cilium/cilium-cli/connectivity/tests" "github.com/cilium/cilium/cilium-cli/utils/features" @@ -23,7 +25,7 @@ func clientEgressTlsSniTest(ct *check.ConnectivityTest, templates map[string]str newTest(testName, ct). WithCiliumVersion("!1.14.15 !1.14.16 !1.15.9 !1.15.10 !1.16.2 !1.16.3"). WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). - WithCiliumPolicy(yamlFile). // L7 allow policy TLS SNI enforcement + WithCiliumPolicy(yamlFile). // L7 allow policy TLS SNI enforcement for external target WithCiliumPolicy(templates["clientEgressOnlyDNSPolicyYAML"]). // DNS resolution only WithScenarios(tests.PodToWorld()). WithExpectations(func(a *check.Action) (egress, ingress check.Result) { @@ -32,6 +34,20 @@ func clientEgressTlsSniTest(ct *check.ConnectivityTest, templates map[string]str } return check.ResultDefaultDenyEgressDrop, check.ResultNone }) + + newTest(fmt.Sprintf("%s-denied", testName), ct). + WithCiliumVersion("!1.14.15 !1.14.16 !1.15.9 !1.15.10 !1.16.2 !1.16.3"). + WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). + WithCiliumPolicy(yamlFile). // L7 allow policy TLS SNI enforcement for external target + WithCiliumPolicy(templates["clientEgressOnlyDNSPolicyYAML"]). // DNS resolution only + WithScenarios(tests.PodToWorld2()). // Another External Target is not allowed + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Destination().Port() == 443 { + // SSL error as another external target (e.g. cilium.io) SNI is not allowed + return check.ResultCurlSSLError, check.ResultNone + } + return check.ResultDefaultDenyEgressDrop, check.ResultNone + }) } func clientEgressL7TlsSniTest(ct *check.ConnectivityTest, templates map[string]string) { diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/manifests/client-egress-l7-tls-sni.yaml b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/manifests/client-egress-l7-tls-sni.yaml index 7e66291199..88ae8d4c95 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/manifests/client-egress-l7-tls-sni.yaml +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/manifests/client-egress-l7-tls-sni.yaml @@ -1,5 +1,3 @@ -# The toFQDNs section relies on DNS introspection being performed by -# the client-egress-only-dns policy. apiVersion: "cilium.io/v2" kind: CiliumNetworkPolicy metadata: @@ -11,9 +9,7 @@ specs: kind: client egress: # Allow HTTPS when X-Very-Secret-Token is set - - toFQDNs: - - matchName: "{{.ExternalTarget}}" - toPorts: + - toPorts: - ports: - port: "443" protocol: "TCP" diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/manifests/client-egress-l7-tls.yaml b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/manifests/client-egress-l7-tls.yaml index 61fe5969db..6bff44ec36 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/manifests/client-egress-l7-tls.yaml +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/manifests/client-egress-l7-tls.yaml @@ -31,3 +31,23 @@ specs: path: "/" headers: - "X-Very-Secret-Token: 42" + - toFQDNs: + - matchName: "{{.ExternalOtherTarget}}" + toPorts: + - ports: + - port: "443" + protocol: "TCP" + terminatingTLS: + secret: + namespace: "{{.TestNamespace}}" + name: externaltarget-tls # internal certificate to terminate in cluster + originatingTLS: + secret: + namespace: "{{.ExternalTargetCANamespace}}" + name: "{{.ExternalTargetCAName}}" # public CA bundle to validate external target + rules: + http: + - method: "GET" + path: "/" + headers: + - "X-Very-Secret-Token: 42" diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/manifests/client-egress-tls-sni.yaml b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/manifests/client-egress-tls-sni.yaml index 4aa7298600..6b597ae33d 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/manifests/client-egress-tls-sni.yaml +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/manifests/client-egress-tls-sni.yaml @@ -1,19 +1,14 @@ -# The toFQDNs section relies on DNS introspection being performed by -# the client-egress-only-dns policy. apiVersion: "cilium.io/v2" kind: CiliumNetworkPolicy metadata: name: "client-egress-tls-sni" specs: -- description: "L7 policy with TLS SNI" +- description: "TLS SNI policy" endpointSelector: matchLabels: kind: client egress: - # Allow HTTPS when X-Very-Secret-Token is set - - toFQDNs: - - matchName: "{{.ExternalTarget}}" - toPorts: + - toPorts: - ports: - port: "443" protocol: "TCP" diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/check.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/check.go index 0cf0549be5..cbe03d867b 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/check.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/check.go @@ -90,6 +90,7 @@ type Parameters struct { JunitProperties map[string]string ImpersonateAs string ImpersonateGroups []string + IPFamilies []string IncludeConnDisruptTest bool ConnDisruptTestSetup bool diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/context.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/context.go index a091d3cd16..053db190ae 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/context.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/context.go @@ -352,9 +352,7 @@ func (ct *ConnectivityTest) SetupAndValidate(ctx context.Context, extra SetupHoo } } if match, _ := ct.Features.MatchRequirements(features.RequireEnabled(features.NodeWithoutCilium)); match { - if err := ct.detectPodCIDRs(); err != nil { - return fmt.Errorf("unable to detect pod CIDRs: %w", err) - } + ct.detectPodCIDRs() if err := ct.detectNodesWithoutCiliumIPs(); err != nil { return fmt.Errorf("unable to detect nodes w/o Cilium IPs: %w", err) @@ -606,7 +604,7 @@ func (ct *ConnectivityTest) enableHubbleClient(ctx context.Context) error { return nil } -func (ct *ConnectivityTest) detectPodCIDRs() error { +func (ct *ConnectivityTest) detectPodCIDRs() { for id, n := range ct.CiliumNodes() { if _, ok := ct.nodesWithoutCilium[id.Name]; ok { // Skip the nodes where Cilium is not installed. @@ -634,8 +632,6 @@ func (ct *ConnectivityTest) detectPodCIDRs() error { } } } - - return nil } // detectNodeCIDRs produces one or more CIDRs that cover all nodes in the cluster. diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/result.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/result.go index de94e6b555..df47afd2b7 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/result.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/result.go @@ -74,6 +74,8 @@ const ( ExitCurlHTTPError ExitCode = 22 ExitCurlTimeout ExitCode = 28 + + ExitCurlSSLError ExitCode = 35 ) var ( @@ -120,6 +122,14 @@ var ( ExitCode: ExitCurlHTTPError, } + // ResultCurlSSLError expects a failed command with SSL error, but no dropped flow or DNS proxy. + ResultCurlSSLError = Result{ + L7Proxy: true, + Drop: false, + DropReasonFunc: defaultDropReason, + ExitCode: ExitCurlSSLError, + } + // ResultDrop expects a dropped flow and a failed command. ResultDrop = Result{ Drop: true, diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/test.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/test.go index ec6d9b1782..45e796daa3 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/test.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/test.go @@ -121,7 +121,8 @@ type Test struct { secrets map[string]*corev1.Secret // CA certificates of the certificates that have to be present during the test. - certificateCAs map[string][]byte + certificateCAs map[string][]byte + certificateKeys map[string][]byte // A custom sysdump policy for the given test. sysdumpPolicy SysdumpPolicy @@ -707,6 +708,11 @@ func (t *Test) WithCertificate(name, hostname string) *Test { } t.certificateCAs[name] = caCert + if t.certificateKeys == nil { + t.certificateKeys = make(map[string][]byte) + } + t.certificateKeys[name] = caKey + return t.WithSecret(&corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: name, @@ -831,7 +837,7 @@ func (t *Test) collectSysdump() { } func (t *Test) ForEachIPFamily(do func(features.IPFamily)) { - ipFams := []features.IPFamily{features.IPFamilyV4, features.IPFamilyV6} + ipFams := features.GetIPFamilies(t.ctx.Params().IPFamilies) // The per-endpoint routes feature is broken with IPv6 on < v1.14 when there // are any netpols installed (https://github.com/cilium/cilium/issues/23852 @@ -863,6 +869,11 @@ func (t *Test) CertificateCAs() map[string][]byte { return t.certificateCAs } +// CertificateKeys returns the CA keys used to sign the certificates within the test. +func (t *Test) CertificateKeys() map[string][]byte { + return t.certificateKeys +} + func (t *Test) CiliumLocalRedirectPolicies() map[string]*ciliumv2.CiliumLocalRedirectPolicy { return t.clrps } diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/common.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/common.go index 2306a20f75..0143882258 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/common.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/common.go @@ -21,6 +21,7 @@ type labelsOption struct { destinationLabels map[string]string method string path string + retryCondition []RetryOption } func WithMethod(method string) Option { @@ -47,6 +48,12 @@ func WithPath(path string) Option { } } +func WithRetryCondition(retryCondition ...RetryOption) Option { + return func(option *labelsOption) { + option.retryCondition = retryCondition + } +} + func hasAllLabels(labelsContainer labelsContainer, filters map[string]string) bool { for k, v := range filters { if !labelsContainer.HasLabel(k, v) { diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/errors.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/errors.go index 0ca5f8fa99..69a66c651f 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/errors.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/errors.go @@ -4,6 +4,7 @@ package tests import ( + "bytes" "context" "fmt" "regexp" @@ -61,7 +62,7 @@ func NoErrorsInLogs(ciliumVersion semver.Version, checkLevels []string) check.Sc hubbleQueueFull, reflectPanic, svcNotFound, unableTranslateCIDRgroups, gobgpWarnings, endpointMapDeleteFailed, etcdReconnection, epRestoreMissingState, mutationDetectorKlog, hubbleFailedCreatePeer, fqdnDpUpdatesTimeout, longNetpolUpdate, failedToGetEpLabels, - failedCreategRPCClient, unableReallocateIngressIP, fqdnMaxIPPerHostname, failedGetMetricsAPI} + failedCreategRPCClient, unableReallocateIngressIP, fqdnMaxIPPerHostname, failedGetMetricsAPI, envoyTLSWarning} // The list is adopted from cilium/cilium/test/helper/utils.go var errorMsgsWithExceptions = map[string][]logMatcher{ panicMessage: nil, @@ -115,11 +116,12 @@ func (n *noErrorsInLogs) Run(ctx context.Context, t *check.Test) { for _, container := range info.containers { id := fmt.Sprintf("%s/%s/%s (%s)", pod.Cluster, pod.Namespace, pod.Name, container) t.NewGenericAction(n, id).Run(func(a *check.Action) { - logs, err := client.GetLogs(ctx, pod.Namespace, pod.Name, container, opts) + var logs bytes.Buffer + err := client.GetLogs(ctx, pod.Namespace, pod.Name, container, opts, &logs) if err != nil { a.Fatalf("Error reading Cilium logs: %s", err) } - n.checkErrorsInLogs(id, logs, a) + n.checkErrorsInLogs(id, logs.Bytes(), a) }) } } @@ -221,9 +223,10 @@ func (n *noErrorsInLogs) podContainers(pod *corev1.Pod) (containers []string) { return containers } -func (n *noErrorsInLogs) findUniqueFailures(logs string) map[string]int { +func (n *noErrorsInLogs) findUniqueFailures(logs []byte) map[string]int { uniqueFailures := make(map[string]int) - for _, msg := range strings.Split(logs, "\n") { + for _, chunk := range bytes.Split(logs, []byte("\n")) { + msg := string(chunk) for fail, ignoreMsgs := range n.errorMsgsWithExceptions { if strings.Contains(msg, fail) { ok := false @@ -243,7 +246,7 @@ func (n *noErrorsInLogs) findUniqueFailures(logs string) map[string]int { return uniqueFailures } -func (n *noErrorsInLogs) checkErrorsInLogs(id string, logs string, a *check.Action) { +func (n *noErrorsInLogs) checkErrorsInLogs(id string, logs []byte, a *check.Action) { uniqueFailures := n.findUniqueFailures(logs) if len(uniqueFailures) > 0 { var failures strings.Builder @@ -325,4 +328,6 @@ var ( knownIssueWireguardCollision = regexMatcher{regexp.MustCompile("Cannot forward proxied DNS lookup.*:51871.*bind: address already in use")} // from: https://github.com/cilium/cilium/issues/30901 // Cf. https://github.com/cilium/cilium/issues/35803 endpointMapDeleteFailed = regexMatcher{regexp.MustCompile(`Ignoring error while deleting endpoint.*from map cilium_\w+: delete: key does not exist`)} + // envoyTLSWarning is the legitimate warning log for negative TLS SNI test case + envoyTLSWarning = regexMatcher{regexp.MustCompile("cilium.tls_wrapper: Could not get server TLS context for pod.*on destination IP.*port 443 sni.*cilium.io.*and raw socket is not allowed")} ) diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/pod.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/pod.go index 54c6c1a4e4..6865acbe98 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/pod.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/pod.go @@ -85,11 +85,17 @@ func PodToPodWithEndpoints(opts ...Option) check.Scenario { for _, opt := range opts { opt(options) } + + rc := &retryCondition{} + for _, opt := range options.retryCondition { + opt(rc) + } return &podToPodWithEndpoints{ sourceLabels: options.sourceLabels, destinationLabels: options.destinationLabels, method: options.method, path: options.path, + retryCondition: rc, } } @@ -99,6 +105,7 @@ type podToPodWithEndpoints struct { destinationLabels map[string]string method string path string + retryCondition *retryCondition } func (s *podToPodWithEndpoints) Name() string { @@ -148,6 +155,7 @@ func (s *podToPodWithEndpoints) curlEndpoints(ctx context.Context, t *check.Test ep := check.HTTPEndpointWithLabels(epName, url, echo.Labels()) t.NewAction(s, epName, client, ep, ipFam).Run(func(a *check.Action) { + curlOpts = append(curlOpts, s.retryCondition.CurlOptions(ep, ipFam, *client, ct.Params())...) a.ExecInPod(ctx, ct.CurlCommand(ep, ipFam, curlOpts...)) a.ValidateFlows(ctx, client, a.GetEgressRequirements(check.FlowParameters{})) diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/world.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/world.go index e90221f615..d886a786e3 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/world.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/world.go @@ -4,10 +4,22 @@ package tests import ( + "bytes" "context" "fmt" + "time" + + "github.com/cloudflare/cfssl/cli/genkey" + "github.com/cloudflare/cfssl/config" + "github.com/cloudflare/cfssl/csr" + "github.com/cloudflare/cfssl/helpers" + "github.com/cloudflare/cfssl/signer" + "github.com/cloudflare/cfssl/signer/local" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/cilium/cilium/cilium-cli/connectivity/check" + "github.com/cilium/cilium/cilium-cli/k8s" "github.com/cilium/cilium/cilium-cli/utils/features" ) @@ -158,3 +170,140 @@ func (s *podToWorldWithTLSIntercept) Run(ctx context.Context, t *check.Test) { i++ } } + +// PodToWorldWithExtraTLSIntercept is same as PodToWorldWithTLSIntercept but with extra host in middle of the test +// The goal is to make sure the secret update path is verified. +func PodToWorldWithExtraTLSIntercept(caName string, curlOpts ...string) check.Scenario { + s := &podToWorldWithExtraTLSIntercept{ + caName: caName, + curlOpts: []string{"--cacert", "/tmp/test-ca.crt"}, // skip TLS verification as it will be our internal cert + } + + s.curlOpts = append(s.curlOpts, curlOpts...) + + return s +} + +type podToWorldWithExtraTLSIntercept struct { + caName string + curlOpts []string +} + +func (s *podToWorldWithExtraTLSIntercept) Name() string { + return "pod-to-world-with-extra-tls-intercept" +} + +func (s *podToWorldWithExtraTLSIntercept) Run(ctx context.Context, t *check.Test) { + fp := check.FlowParameters{ + DNSRequired: true, + RSTAllowed: true, + } + + var i int + ct := t.Context() + + var caBundle []byte + // join all the CA certs into a single file + for _, caFile := range t.CertificateCAs() { + caBundle = append(caBundle, caFile...) + caBundle = append(caBundle, '\n') + } + s.updateSecret(ctx, t) + + for _, client := range ct.ClientPods() { + // With https, over port 443. + for _, target := range []string{ + t.Context().Params().ExternalTarget, + t.Context().Params().ExternalOtherTarget, + } { + https := check.HTTPEndpoint(target+"-https", "https://"+target) + t.NewAction(s, fmt.Sprintf("https-to-%s-%d", target, i), &client, https, features.IPFamilyAny).Run(func(a *check.Action) { + a.WriteDataToPod(ctx, "/tmp/test-ca.crt", caBundle) + a.ExecInPod(ctx, ct.CurlCommand(https, features.IPFamilyAny, s.curlOpts...)) + a.ValidateFlows(ctx, client, a.GetEgressRequirements(fp)) + }) + } + i++ + } +} + +// updateSecret adds another hosts (e.g. ExternalOtherTarget) into the existing secrets using the same CA. +func (s *podToWorldWithExtraTLSIntercept) updateSecret(ctx context.Context, t *check.Test) { + caCert, caKey := t.CertificateCAs()[s.caName], t.CertificateKeys()[s.caName] + + g := &csr.Generator{Validator: genkey.Validator} + + csrBytes, keyBytes, err := g.ProcessRequest(&csr.CertificateRequest{ + CN: "Cilium External Targets", + Hosts: []string{ + t.Context().Params().ExternalTarget, // Original target + t.Context().Params().ExternalOtherTarget, // Additional target + }, + }) + if err != nil { + t.Fatalf("Unable to create CA: %s", err) + } + parsedCa, err := helpers.ParseCertificatePEM(caCert) + if err != nil { + t.Fatalf("Unable to create CSR: %s", err) + } + caPriv, err := helpers.ParsePrivateKeyPEM(caKey) + if err != nil { + t.Fatalf("Unable to parse CA key: %s", err) + } + + signConf := &config.Signing{ + Default: &config.SigningProfile{ + Expiry: 365 * 24 * time.Hour, + Usage: []string{"key encipherment", "server auth", "digital signature"}, + }, + } + + sign, err := local.NewSigner(caPriv, parsedCa, signer.DefaultSigAlgo(caPriv), signConf) + if err != nil { + t.Fatalf("Unable to create signer: %s", err) + } + certBytes, err := sign.Sign(signer.SignRequest{Request: string(csrBytes)}) + if err != nil { + t.Fatalf("Unable to sign certificate: %s", err) + } + + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: s.caName, + Namespace: t.Context().Params().TestNamespace, + }, + Type: corev1.SecretTypeTLS, + Data: map[string][]byte{ + corev1.TLSCertKey: certBytes, + corev1.TLSPrivateKeyKey: keyBytes, + }, + } + + t.Infof("📜 Appending secret '%s' to namespace '%s'..", secret.Name, secret.Namespace) + if err := ensureSecret(ctx, t.Context().Clients()[0], secret); err != nil { + t.Fatalf("Unable to rotate secret: %s", err) + } +} + +func ensureSecret(ctx context.Context, client *k8s.Client, secret *corev1.Secret) error { + if existing, err := client.GetSecret(ctx, secret.Namespace, secret.Name, metav1.GetOptions{}); err == nil { + needsUpdate := false + for k, v := range existing.Data { + if v2, ok := secret.Data[k]; !ok || !bytes.Equal(v, v2) { + needsUpdate = true + break + } + } + + if !needsUpdate { + return nil + } + + _, err = client.UpdateSecret(ctx, secret.Namespace, secret, metav1.UpdateOptions{}) + return err + } + + _, err := client.CreateSecret(ctx, secret.Namespace, secret, metav1.CreateOptions{}) + return err +} diff --git a/vendor/github.com/cilium/cilium/cilium-cli/defaults/defaults.go b/vendor/github.com/cilium/cilium/cilium-cli/defaults/defaults.go index 91bd6a43ce..b4095700f7 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/defaults/defaults.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/defaults/defaults.go @@ -78,7 +78,7 @@ const ( // renovate: datasource=docker ConnectivityTestFRRImage = "quay.io/frrouting/frr:10.2.1@sha256:c8543d3e0a1348cc0f2b19154fd8b0300e237773dbec65d9d6d6570c1d088deb" // renovate: datasource=docker - ConnectivityTestSocatImage = "docker.io/alpine/socat:1.8.0.0@sha256:a6be4c0262b339c53ddad723cdd178a1a13271e1137c65e27f90a08c16de02b8" + ConnectivityTestSocatImage = "docker.io/alpine/socat:1.8.0.1@sha256:d95d6a210a87164533d444e8d7ebd586231b3387a27ee7c0732ade3d6c3b0f4d" ConfigMapName = "cilium-config" @@ -124,6 +124,7 @@ var ( HelmRepoIDLen = 4 HelmRepository = "https://helm.cilium.io" HelmRepositoryID = sha256.Sum256([]byte(HelmRepository)) + HelmMaxHistory = 10 // CiliumScheduleAffinity is the node affinity to prevent Cilium from being schedule on // nodes labeled with CiliumNoScheduleLabel. diff --git a/vendor/github.com/cilium/cilium/cilium-cli/features/features.go b/vendor/github.com/cilium/cilium/cilium-cli/features/features.go index 1403c54092..af086ea71f 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/features/features.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/features/features.go @@ -26,6 +26,10 @@ type Parameters struct { WaitDuration time.Duration Output string Outputfile string + MetricsDirectory string + Repo string + Commit string + GHStepSummaryAnchor bool } type Feature struct { diff --git a/vendor/github.com/cilium/cilium/cilium-cli/features/markdown.go b/vendor/github.com/cilium/cilium/cilium-cli/features/markdown.go index 74d1919272..ee69b215a6 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/features/markdown.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/features/markdown.go @@ -35,10 +35,14 @@ func (mw *markdownWriter) printHeader(nodesSorted []string) error { } func (mw *markdownWriter) printNode(metricName, labels string, isBinary bool, values map[float64]struct{}, key string, nodesSorted []string, metricsPerNode map[string]map[string]float64) { - if isBinary && len(values) <= 1 { - mw.builder.WriteString("| :heavy_check_mark: ") + if isBinary { + if len(values) <= 1 { + mw.builder.WriteString("| :heavy_check_mark: ") + } else { + mw.builder.WriteString("| :warning: ") + } } else { - mw.builder.WriteString("| :warning: ") + mw.builder.WriteString("| ") } mw.builder.WriteString(fmt.Sprintf("| %s | %s |", metricName, labels)) diff --git a/vendor/github.com/cilium/cilium/cilium-cli/features/summary.go b/vendor/github.com/cilium/cilium/cilium-cli/features/summary.go new file mode 100644 index 0000000000..efedb8b3b4 --- /dev/null +++ b/vendor/github.com/cilium/cilium/cilium-cli/features/summary.go @@ -0,0 +1,522 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package features + +import ( + "archive/zip" + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "os" + "path" + "path/filepath" + "slices" + "sort" + "strconv" + "strings" + + "github.com/cilium/cilium/api/v1/models" + "github.com/cilium/cilium/cilium-cli/defaults" + + "github.com/google/go-github/v68/github" + "golang.org/x/oauth2" +) + +type perJobMetrics map[string]perDeployNodeMetrics +type perWorkflowMetrics map[string]perJobMetrics + +// GenSummary downloads and generates a summary table with all the features +// tested in the CI run. +func (s *Feature) GenSummary(ctx context.Context) error { + err := s.downloadWorkflowData(ctx) + if err != nil { + return fmt.Errorf("downloading workflow data: %w", err) + } + + workflowData, err := loadWorkflowData(s.params.MetricsDirectory) + if err != nil { + return err + } + return s.printSummaryFromJsons(workflowData) +} + +func (s *Feature) downloadWorkflowData(ctx context.Context) error { + token := os.Getenv("GITHUB_TOKEN") + + if token == "" { + return fmt.Errorf("GITHUB_TOKEN environment variable must be set.") + } + + parts := strings.Split(s.params.Repo, "/") + if len(parts) != 2 { + return fmt.Errorf("invalid repository format. Expected 'owner/repo', got '%s'", s.params.Repo) + } + owner, repoName := parts[0], parts[1] + + tc := oauth2.NewClient(ctx, oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})) + ghClient := github.NewClient(tc) + + allRuns := map[int64]*github.WorkflowRun{} + // Fetch workflow runs for the specific commit + for _, event := range []string{"push", "schedule", "pull_request", "pull_request_target"} { + opts := &github.ListWorkflowRunsOptions{ + HeadSHA: s.params.Commit, + Status: "completed", + Event: event, + ListOptions: github.ListOptions{ + PerPage: 100, + }, + } + + for { + runs, resp, err := ghClient.Actions.ListRepositoryWorkflowRuns(ctx, owner, repoName, opts) + if err != nil { + return fmt.Errorf("failed to fetch workflow runs: %w", err) + } + for _, run := range runs.WorkflowRuns { + allRuns[run.GetID()] = run + } + if resp.NextPage == 0 { + break + } + opts.Page = resp.NextPage + } + } + + // Fetch also the workflow runs from commit status. (The ones populated by + // ariane) + opts := &github.ListOptions{ + PerPage: 100, + } + for { + status, resp, err := ghClient.Repositories.GetCombinedStatus(ctx, owner, repoName, s.params.Commit, opts) + if err != nil { + return fmt.Errorf("error retrieving status check for commit %s: %w", s.params.Commit, err) + } + + for _, st := range status.Statuses { + // Just check the status from GH actions, which have the URL from + // github.com + if !strings.HasPrefix(st.GetTargetURL(), "https://github.com/"+s.params.Repo) { + continue + } + runIDStr := path.Base(st.GetTargetURL()) + runID, err := strconv.ParseUint(runIDStr, 10, 64) + if err != nil { + return fmt.Errorf("invalid run ID %s: %w", runIDStr, err) + } + run, _, err := ghClient.Actions.GetWorkflowRunByID(ctx, owner, repoName, int64(runID)) + if err != nil { + return fmt.Errorf("failed to list workflow for ID %d: %w", runID, err) + } + allRuns[run.GetID()] = run + } + if resp.NextPage == 0 { + break + } + opts.Page = resp.NextPage + } + + var allRunsSorted []*github.WorkflowRun + for _, run := range allRuns { + allRunsSorted = append(allRunsSorted, run) + } + sort.Slice(allRunsSorted, func(i, j int) bool { + return allRunsSorted[i].GetID() < allRunsSorted[j].GetID() + }) + + // Process each workflow run by order, if there's another scheduled workflow + // run it can overwrite previous runs. + for _, run := range allRunsSorted { + runID := run.GetID() + runName := run.GetName() + fmt.Fprintf(os.Stderr, "Processing workflow run: %s (ID: %d)\n", runName, runID) + + // Download artifacts for the workflow run + err := downloadArtifacts(ctx, ghClient, owner, repoName, runID, "features-tested*", filepath.Join(s.params.MetricsDirectory, runName)) + if err != nil { + return fmt.Errorf("failed to download artifacts for run %d: %w", runID, err) + } + } + return nil +} + +// downloadArtifacts downloads all artifacts for a given workflow run and saves +// files matching the pattern to the specified directory. +func downloadArtifacts(ctx context.Context, client *github.Client, owner, repo string, runID int64, pattern, destDir string) error { + artifacts, _, err := client.Actions.ListWorkflowRunArtifacts(ctx, owner, repo, runID, &github.ListOptions{PerPage: 100}) + if err != nil { + return fmt.Errorf("failed to list artifacts for run %d: %w", runID, err) + } + + if len(artifacts.Artifacts) == 0 { + fmt.Fprintf(os.Stderr, " - ARTIFACTS NOT FOUND %d\n", runID) + return nil + } + + // Create destination directory if it doesn't exist + if err := os.MkdirAll(destDir, os.ModePerm); err != nil { + return fmt.Errorf("failed to create directory %s: %w", destDir, err) + } + + // Download and extract matching artifacts + for _, artifact := range artifacts.Artifacts { + if matched, _ := filepath.Match(pattern, artifact.GetName()); !matched { + continue + } + + fmt.Fprintf(os.Stderr, " - Downloading artifact: %s (ID: %d)\n", artifact.GetName(), artifact.GetID()) + + // Get the artifact download URL + archiveURL, _, err := client.Actions.DownloadArtifact(ctx, owner, repo, artifact.GetID(), 5) + if err != nil { + return fmt.Errorf("failed to get download URL for artifact %d: %w", artifact.GetID(), err) + } + + // Download the artifact + resp, err := http.Get(archiveURL.String()) + if err != nil { + return fmt.Errorf("failed to download artifact %d: %w", artifact.GetID(), err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("unexpected status code %d for artifact %d", resp.StatusCode, artifact.GetID()) + } + + // Save the artifact to a temporary ZIP file + tempFile := filepath.Join(destDir, fmt.Sprintf("%s.zip", artifact.GetName())) + out, err := os.Create(tempFile) + if err != nil { + return fmt.Errorf("failed to create temp file %s: %w", tempFile, err) + } + + _, err = io.Copy(out, resp.Body) + out.Close() + if err != nil { + return fmt.Errorf("failed to save artifact to %s: %w", tempFile, err) + } + + // Extract the ZIP file to the destination directory + err = extractZip(tempFile, destDir) + if err != nil { + return fmt.Errorf("failed to extract artifact %s: %w", tempFile, err) + } + + // Clean up the temporary ZIP file + os.Remove(tempFile) + } + + return nil +} + +// extractZip extracts the contents of a ZIP file to a specified directory. +func extractZip(zipPath, destDir string) error { + r, err := zip.OpenReader(zipPath) + if err != nil { + return fmt.Errorf("failed to open ZIP file %s: %w", zipPath, err) + } + defer r.Close() + + for _, file := range r.File { + destPath := filepath.Join(destDir, file.Name) + if file.FileInfo().IsDir() { + // Create directories + if err := os.MkdirAll(destPath, os.ModePerm); err != nil { + return fmt.Errorf("failed to create directory %s: %w", destPath, err) + } + continue + } + + // Extract files + destFile, err := os.OpenFile(destPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode()) + if err != nil { + return fmt.Errorf("failed to create file %s: %w", destPath, err) + } + srcFile, err := file.Open() + if err != nil { + destFile.Close() + return fmt.Errorf("failed to open file in ZIP archive %s: %w", file.Name, err) + } + _, err = io.Copy(destFile, srcFile) + destFile.Close() + srcFile.Close() + if err != nil { + return fmt.Errorf("failed to extract file %s: %w", file.Name, err) + } + } + + return nil +} + +// nodesValues maps a node to value +type nodesValues map[string]float64 + +// job maps a job to nodes +type jobNodes map[string]nodesValues + +// workflowNodes maps a workflow name to jobs +type workflowNodes map[string]jobNodes + +// metricsWorkflows maps a metric name to workflows +type metricsWorkflows map[string]workflowNodes + +func (s *Feature) printSummaryFromJsons(workflowData perWorkflowMetrics) error { + result := make(metricsWorkflows) + metricNamesSet := map[string]struct{}{} + workflows := map[string]struct{}{} + + // Process each workflow and its nodes + for workflow, jobs := range workflowData { + workflows[workflow] = struct{}{} + + for jobName, nodes := range jobs { + for nodeName, deployMetrics := range nodes { + for _, deploymentMetrics := range deployMetrics { + for _, d := range deploymentMetrics { + metricNames := d.Name + var orderedLabels []string + for k, v := range d.Labels { + orderedLabels = append(orderedLabels, fmt.Sprintf("%s=%s", k, v)) + } + slices.Sort(orderedLabels) + if len(orderedLabels) != 0 { + metricNames += ";" + } + metricNames += strings.Join(orderedLabels, ";") + + if _, ok := result[metricNames]; !ok { + result[metricNames] = make(workflowNodes) + } + if _, ok := result[metricNames][workflow]; !ok { + result[metricNames][workflow] = make(jobNodes) + } + if _, ok := result[metricNames][workflow][jobName]; !ok { + result[metricNames][workflow][jobName] = make(nodesValues) + } + result[metricNames][workflow][jobName][nodeName] = d.Value + metricNamesSet[metricNames] = struct{}{} + } + } + } + } + } + var metricNamesSorted []string + for key := range metricNamesSet { + metricNamesSorted = append(metricNamesSorted, key) + } + slices.Sort(metricNamesSorted) + + // Generate markdown for the summary table + detailsBuilder := &bytes.Buffer{} + fmt.Fprintf(detailsBuilder, "## Summary Table\n\n") + fmt.Fprintf(detailsBuilder, "| Tested on >=1 workflow? | Metric | Labels | Details Link |\n") + fmt.Fprintf(detailsBuilder, "|-------------------------|------------------------------------|-----------------------------|----------------------------------------------------|\n") + + testedOnOneWorkflow := map[string]struct{}{} + for _, metricKeys := range metricNamesSorted { + name, labels := parseNameAndLabels(metricKeys) + var hasValue bool + for workflow := range workflows { + for _, nodesMetrics := range result[metricKeys][workflow] { + for _, value := range nodesMetrics { + if value > 0 { + hasValue = true + testedOnOneWorkflow[metricKeys] = struct{}{} + break + } + } + if hasValue { + break + } + } + if hasValue { + break + } + } + var detailsLink string + if hasValue { + // GH Step summary prefixes all anchors with "user-content-". This + // workaround allows use to make the anchors usable. + var anchorPrefix string + if s.params.GHStepSummaryAnchor { + anchorPrefix = "user-content-" + } + detailsLink = fmt.Sprintf("[View Details](#%smetric-%s)", anchorPrefix, pathEscape(metricKeys)) + } + fmt.Fprintf(detailsBuilder, "| %-22s | %-34s | %-27s | %-50s |\n", boolToStr(hasValue), strings.ReplaceAll(name, "cilium_feature_", ""), labels, detailsLink) + } + + var printFootnote bool + for _, metricName := range metricNamesSorted { + if _, ok := testedOnOneWorkflow[metricName]; !ok { + continue + } + name, labels := parseNameAndLabels(metricName) + + fmt.Fprintf(detailsBuilder, "\n
", pathEscape(metricName)) + fmt.Fprintf(detailsBuilder, "\n### Metric: `%s`\n", name) + if labels != "" { + fmt.Fprintf(detailsBuilder, "- **Labels**: `%s`\n\n", labels) + } + fmt.Fprintf(detailsBuilder, "
\n") + fmt.Fprintf(detailsBuilder, "\n\n\n\n") + + // metric+label / workflow / jobs / nodes / value + metricsPerWorkflow := result[metricName] + + var orderedWorkflows []string + for workflow := range metricsPerWorkflow { + orderedWorkflows = append(orderedWorkflows, workflow) + } + slices.Sort(orderedWorkflows) + + var printJob string + + for _, workflow := range orderedWorkflows { + metricsPerJob := metricsPerWorkflow[workflow] + if len(metricsPerJob) == 0 { + continue + } + printJobDetails := true + var orderedJobs []string + for job := range metricsPerJob { + orderedJobs = append(orderedJobs, job) + } + slices.Sort(orderedJobs) + for _, job := range orderedJobs { + printJob = job + var orderedNodes []string + for node := range metricsPerJob[job] { + orderedNodes = append(orderedNodes, node) + } + slices.Sort(orderedNodes) + previousValue := -1.0 + isFirst := true + allEqual := true + for _, nodeName := range orderedNodes { + value := metricsPerJob[job][nodeName] + if value == 0 { + continue + } + if isFirst { + previousValue = value + isFirst = false + } else if value != previousValue { + allEqual = false + break + } + } + if previousValue == -1.0 { + continue + } + if printJobDetails { + fmt.Fprintf(detailsBuilder, "#### **%s**\n\n", workflow) + fmt.Fprintf(detailsBuilder, "| Job | Value |\n") + fmt.Fprintf(detailsBuilder, "|-------|-------|\n") + printJobDetails = false + } + if printJob == job { + fmt.Fprintf(detailsBuilder, "| %-13s ", printJob) + printJob = "" + } else { + fmt.Fprintf(detailsBuilder, "| %-13s ", "") + } + if allEqual { + fmt.Fprintf(detailsBuilder, "| %-5.0f |\n", previousValue) + } else { + fmt.Fprintf(detailsBuilder, "| âš  [^1] |\n") + printFootnote = true + } + } + } + + fmt.Fprintf(detailsBuilder, "Click here to see\n") + } + + if printFootnote { + fmt.Fprintf(detailsBuilder, "[^1]: Nodes on this test had different values across themselves\n") + } + + f, err := os.OpenFile(s.params.Outputfile, os.O_RDWR|os.O_CREATE, 0644) + if err != nil { + return fmt.Errorf("unable to open file %w", err) + } + defer f.Close() + _, err = detailsBuilder.WriteTo(f) + if err != nil { + return fmt.Errorf("failed to write to file: %w", err) + } + return nil +} + +func boolToStr(b bool) string { + if b { + return "✅" + } + return "❌" +} + +func pathEscape(s string) string { + return strings.NewReplacer(" ", "_", ";", "-").Replace(s) +} + +// Function to load workflow data from JSON files +func loadWorkflowData(directory string) (perWorkflowMetrics, error) { + workflowData := make(perWorkflowMetrics) + + err := filepath.Walk(directory, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if !info.IsDir() && filepath.Ext(path) == ".json" { + fileData, err := os.ReadFile(path) + if err != nil { + return fmt.Errorf("error reading file %q: %w", path, err) + } + var nodesData perDeployNodeMetrics + err = json.Unmarshal(fileData, &nodesData) + if err != nil { + // Because the runtime tests are running on a single node, + // they will only have a list of metrics stored on each .json + // file + var errUTE *json.UnmarshalTypeError + if !errors.As(err, &errUTE) { + return fmt.Errorf("error unmarshalling file %q: %w", path, err) + } + var metrics []*models.Metric + err = json.Unmarshal(fileData, &metrics) + if err != nil { + return fmt.Errorf("error unmarshalling file %q: %w", path, err) + } + nodesData = perDeployNodeMetrics{ + defaults.AgentDaemonSetName: perNodeMetrics{ + "runtime": metrics, + }, + } + } + + // Get workflow name (parent directory) and node name (file name without extension) + workflowName := filepath.Base(filepath.Dir(path)) + jobName := info.Name()[:len(info.Name())-len(filepath.Ext(info.Name()))] + + // Initialize workflow entry if it doesn't exist + if _, exists := workflowData[workflowName]; !exists { + workflowData[workflowName] = make(perJobMetrics) + } + + // Add node data to the workflow's node entry + workflowData[workflowName][jobName] = nodesData + } + + return nil + }) + + return workflowData, err +} diff --git a/vendor/github.com/cilium/cilium/cilium-cli/features/tab_writer.go b/vendor/github.com/cilium/cilium/cilium-cli/features/tab_writer.go index 88079fc0f8..c17e9b37c4 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/features/tab_writer.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/features/tab_writer.go @@ -32,10 +32,14 @@ func (t *tabWriter) printNode(metricName, labels string, isBinary bool, values m // Determine if "Yes" should be placed in "Uniform" column // if len(values) <= 1 then it means that all nodes have a value of // either 0 or 1. - if isBinary && len(values) <= 1 { - fmt.Fprintf(t.tb, "Yes\t") + if isBinary { + if len(values) <= 1 { + fmt.Fprintf(t.tb, "Yes\t") + } else { + fmt.Fprintf(t.tb, "No\t") + } } else { - fmt.Fprintf(t.tb, "No\t") + fmt.Fprintf(t.tb, " \t") } fmt.Fprintf(t.tb, "%s\t%s\t", metricName, labels) diff --git a/vendor/github.com/cilium/cilium/cilium-cli/install/autodetect.go b/vendor/github.com/cilium/cilium/cilium-cli/install/autodetect.go index a9ec0d2070..7685812126 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/install/autodetect.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/install/autodetect.go @@ -74,6 +74,20 @@ func getClusterName(helmValues map[string]interface{}) string { return clusterName } +func trimEKSClusterARN(fullARN string) string { + const prefix = "cluster/" + idx := strings.LastIndex(fullARN, prefix) + if idx == -1 { + return fullARN + } + idx += len(prefix) + if idx < len(fullARN) { + return fullARN[idx:] + } + + return "" +} + func (k *K8sInstaller) autodetectAndValidate(ctx context.Context, helmValues map[string]interface{}) error { k.autodetect(ctx) @@ -86,8 +100,13 @@ func (k *K8sInstaller) autodetectAndValidate(ctx context.Context, helmValues map if k.params.ClusterName == "" { if k.flavor.ClusterName != "" { - // Neither underscores nor dots are allowed as part of the cluster name. - name := strings.NewReplacer("_", "-", ".", "-").Replace(k.flavor.ClusterName) + // Neither underscores, dots nor colons are allowed as part of the cluster name. + name := strings.NewReplacer("_", "-", ".", "-", ":", "-").Replace(k.flavor.ClusterName) + + if k.flavor.Kind == k8s.KindEKS { + name = trimEKSClusterARN(name) + } + k.Log("🔮 Auto-detected cluster name: %s", name) k.params.ClusterName = name } diff --git a/vendor/github.com/cilium/cilium/cilium-cli/install/install.go b/vendor/github.com/cilium/cilium/cilium-cli/install/install.go index 9f8a750175..89aa8e77b9 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/install/install.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/install/install.go @@ -110,6 +110,9 @@ type Parameters struct { // HelmRepository specifies the Helm repository to download Cilium Helm charts from. HelmRepository string + // HelmMaxHistory specifies the maximum number of Helm releases to keep. + HelmMaxHistory int + // HelmReleaseName specifies the Helm release name for the Cilium CLI. // Useful for referencing Cilium installations installed directly through Helm // or overriding the Cilium CLI for install/upgrade/enable. diff --git a/vendor/github.com/cilium/cilium/cilium-cli/install/upgrade.go b/vendor/github.com/cilium/cilium/cilium-cli/install/upgrade.go index 526d8dbed0..a1e3010cd4 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/install/upgrade.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/install/upgrade.go @@ -38,6 +38,7 @@ func (k *K8sInstaller) UpgradeWithHelm(ctx context.Context, k8sClient *k8s.Clien ResetThenReuseValues: k.params.HelmResetThenReuseValues, Wait: k.params.Wait, WaitDuration: k.params.WaitDuration, + MaxHistory: k.params.HelmMaxHistory, // In addition to the DryRun i/o, we need to tell Helm not to execute the upgrade DryRun: k.params.DryRun, diff --git a/vendor/github.com/cilium/cilium/cilium-cli/internal/helm/helm.go b/vendor/github.com/cilium/cilium/cilium-cli/internal/helm/helm.go index fd92828a60..f560f0740f 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/internal/helm/helm.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/internal/helm/helm.go @@ -297,6 +297,8 @@ type UpgradeParameters struct { // DryRunHelmValues writes non-default Helm values to stdout without performing the actual installation. // For Helm installation mode only. DryRunHelmValues bool + // MaxHistory is the maximum number of releases to keep in the release history + MaxHistory int } func (p *UpgradeParameters) IsDryRun() bool { @@ -325,6 +327,7 @@ func Upgrade( helmClient.Wait = params.Wait helmClient.Timeout = params.WaitDuration helmClient.DryRun = params.IsDryRun() + helmClient.MaxHistory = params.MaxHistory return helmClient.RunWithContext(ctx, params.Name, params.Chart, params.Values) } diff --git a/vendor/github.com/cilium/cilium/cilium-cli/k8s/client.go b/vendor/github.com/cilium/cilium/cilium-cli/k8s/client.go index b8d7d57ccc..191600ba04 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/k8s/client.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/k8s/client.go @@ -350,35 +350,33 @@ func (c *Client) ListServices(ctx context.Context, namespace string, options met } func (c *Client) ExecInPodWithStderr(ctx context.Context, namespace, pod, container string, command []string) (bytes.Buffer, bytes.Buffer, error) { - result, err := c.execInPod(ctx, ExecParameters{ - Namespace: namespace, - Pod: pod, - Container: container, - Command: command, - }) - return result.Stdout, result.Stderr, err + var stdout, stderr bytes.Buffer + err := c.ExecInPodWithWriters(ctx, nil, namespace, pod, container, command, &stdout, &stderr) + return stdout, stderr, err } func (c *Client) ExecInPod(ctx context.Context, namespace, pod, container string, command []string) (bytes.Buffer, error) { - result, err := c.execInPod(ctx, ExecParameters{ - Namespace: namespace, - Pod: pod, - Container: container, - Command: command, - }) + var stdout bytes.Buffer + err := c.ExecInPodWithWriters(ctx, nil, namespace, pod, container, command, &stdout, StderrAsError) + return stdout, err +} - if err != nil { - return result.Stdout, fmt.Errorf("%w: %q", err, result.Stderr.String()) - } +// StderrAsError, when given as stderr parameter of the ExecInPodWithWriters function, +// causes any stderr message to be returned as an error. +var StderrAsError stderrAsError - if errString := result.Stderr.String(); errString != "" { - return result.Stdout, fmt.Errorf("command failed (pod=%s/%s, container=%s): %q", namespace, pod, container, errString) - } +type stderrAsError struct{} - return result.Stdout, nil -} +func (stderrAsError) Write([]byte) (int, error) { return 0, errors.ErrUnsupported } func (c *Client) ExecInPodWithWriters(connCtx, killCmdCtx context.Context, namespace, pod, container string, command []string, stdout, stderr io.Writer) error { + var errbuf *bytes.Buffer + + if _, ok := stderr.(stderrAsError); ok { + errbuf = &bytes.Buffer{} + stderr = errbuf + } + execParams := ExecParameters{ Namespace: namespace, Pod: pod, @@ -388,12 +386,24 @@ func (c *Client) ExecInPodWithWriters(connCtx, killCmdCtx context.Context, names if killCmdCtx != nil { execParams.TTY = true } + err := c.execInPodWithWriters(connCtx, killCmdCtx, execParams, stdout, stderr) - if err != nil { - return err + + var errstr string + if errbuf != nil { + errstr = errbuf.String() } - return nil + switch { + case err != nil && errstr == "": + return fmt.Errorf("command failed (pod=%s/%s, container=%s): %w", namespace, pod, container, err) + case err != nil && errstr != "": + return fmt.Errorf("command failed (pod=%s/%s, container=%s): %w: %q", namespace, pod, container, err, errstr) + case err == nil && errstr != "": + return fmt.Errorf("command failed (pod=%s/%s, container=%s): %q", namespace, pod, container, errstr) + default: + return nil + } } func (c *Client) CiliumStatus(ctx context.Context, namespace, pod string) (*models.StatusResponse, error) { @@ -945,12 +955,12 @@ func (c *Client) ListCiliumPodIPPools(ctx context.Context, opts metav1.ListOptio return c.CiliumClientset.CiliumV2alpha1().CiliumPodIPPools().List(ctx, opts) } -func (c *Client) GetLogs(ctx context.Context, namespace, name, container string, opts corev1.PodLogOptions) (string, error) { +func (c *Client) GetLogs(ctx context.Context, namespace, name, container string, opts corev1.PodLogOptions, out io.Writer) error { opts.Container = container r := c.Clientset.CoreV1().Pods(namespace).GetLogs(name, &opts) var s io.ReadCloser var err error - // rety request upon EOF to work around transient (?) failures on Azure, see + // retry request upon EOF to work around transient (?) failures on Azure, see // https://github.com/cilium/cilium/issues/29845 for range getLogsRetries { s, err = r.Stream(ctx) @@ -960,14 +970,12 @@ func (c *Client) GetLogs(ctx context.Context, namespace, name, container string, break } if err != nil { - return "", err + return err } defer s.Close() - var b bytes.Buffer - if _, err = io.Copy(&b, s); err != nil { - return "", err - } - return b.String(), nil + + _, err = io.Copy(out, s) + return err } // GetCiliumVersion returns a semver.Version representing the version of cilium diff --git a/vendor/github.com/cilium/cilium/cilium-cli/k8s/exec.go b/vendor/github.com/cilium/cilium/cilium-cli/k8s/exec.go index 9b2ec2937a..7a6d387e72 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/k8s/exec.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/k8s/exec.go @@ -4,7 +4,6 @@ package k8s import ( - "bytes" "context" "fmt" "io" @@ -16,11 +15,6 @@ import ( "github.com/cilium/cilium/cilium-cli/k8s/internal" ) -type ExecResult struct { - Stdout bytes.Buffer - Stderr bytes.Buffer -} - type ExecParameters struct { Namespace string Pod string @@ -70,11 +64,3 @@ func (c *Client) execInPodWithWriters(connCtx, killCmdCtx context.Context, p Exe Tty: p.TTY, }) } - -func (c *Client) execInPod(ctx context.Context, p ExecParameters) (*ExecResult, error) { - result := &ExecResult{} - if err := c.execInPodWithWriters(ctx, nil, p, &result.Stdout, &result.Stderr); err != nil { - return result, fmt.Errorf("error with exec request (pod=%s/%s, container=%s): %w", p.Namespace, p.Pod, p.Container, err) - } - return result, nil -} diff --git a/vendor/github.com/cilium/cilium/cilium-cli/sysdump/client.go b/vendor/github.com/cilium/cilium/cilium-cli/sysdump/client.go index be7f8459f7..4c52012f43 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/sysdump/client.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/sysdump/client.go @@ -33,13 +33,14 @@ type KubernetesClient interface { DeletePod(ctx context.Context, namespace, name string, opts metav1.DeleteOptions) error ExecInPod(ctx context.Context, namespace, pod, container string, command []string) (bytes.Buffer, error) ExecInPodWithStderr(ctx context.Context, namespace, pod, container string, command []string) (bytes.Buffer, bytes.Buffer, error) + ExecInPodWithWriters(connCtx, killCmdCtx context.Context, namespace, pod, container string, command []string, stdout, stderr io.Writer) error GetConfigMap(ctx context.Context, namespace, name string, opts metav1.GetOptions) (*corev1.ConfigMap, error) GetNamespace(ctx context.Context, namespace string, options metav1.GetOptions) (*corev1.Namespace, error) GetDaemonSet(ctx context.Context, namespace, name string, opts metav1.GetOptions) (*appsv1.DaemonSet, error) GetStatefulSet(ctx context.Context, namespace, name string, opts metav1.GetOptions) (*appsv1.StatefulSet, error) GetDeployment(ctx context.Context, namespace, name string, opts metav1.GetOptions) (*appsv1.Deployment, error) GetCronJob(ctx context.Context, namespace, name string, opts metav1.GetOptions) (*batchv1.CronJob, error) - GetLogs(ctx context.Context, namespace, name, container string, opts corev1.PodLogOptions) (string, error) + GetLogs(ctx context.Context, namespace, name, container string, opts corev1.PodLogOptions, out io.Writer) error GetPodsTable(ctx context.Context) (*metav1.Table, error) ProxyGet(ctx context.Context, namespace, name, url string) (string, error) ProxyTCP(ctx context.Context, namespace, name string, port uint16, handler func(io.ReadWriteCloser) error) error diff --git a/vendor/github.com/cilium/cilium/cilium-cli/sysdump/constants.go b/vendor/github.com/cilium/cilium/cilium-cli/sysdump/constants.go index 5da479d40e..55935d0347 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/sysdump/constants.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/sysdump/constants.go @@ -87,6 +87,8 @@ const ( eniconfigsFileName = "aws-eniconfigs-.yaml" ciliumHelmMetadataFileName = "cilium-helm-metadata-.yaml" ciliumHelmValuesFileName = "cilium-helm-values-.yaml" + tetragonHelmMetadataFileName = "tetragon-helm-metadata-.yaml" + tetragonHelmValuesFileName = "tetragon-helm-values-.yaml" gopsFileName = "gops-%s-%s--%s.txt" hubbleDaemonsetFileName = "hubble-daemonset-.yaml" hubbleFlowsFileName = "hubble-flows-%s-.json" diff --git a/vendor/github.com/cilium/cilium/cilium-cli/sysdump/defaults.go b/vendor/github.com/cilium/cilium/cilium-cli/sysdump/defaults.go index 86f1bd99fe..68512631f4 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/sysdump/defaults.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/sysdump/defaults.go @@ -19,6 +19,7 @@ const ( DefaultCiliumNodeInitLabelSelector = "app=cilium-node-init" DefaultCiliumSpireAgentLabelSelector = "app=spire-agent" DefaultCiliumSpireServerLabelSelector = "app=spire-server" + DefaultCollectLogsFromNotReadyAgents = true DefaultDebug = false DefaultProfiling = true DefaultTracing = false diff --git a/vendor/github.com/cilium/cilium/cilium-cli/sysdump/sysdump.go b/vendor/github.com/cilium/cilium/cilium-cli/sysdump/sysdump.go index 9eedb6868e..5a39e53c55 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/sysdump/sysdump.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/sysdump/sysdump.go @@ -6,6 +6,7 @@ package sysdump import ( "archive/tar" "archive/zip" + "bytes" "compress/gzip" "context" "errors" @@ -30,6 +31,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/cli-runtime/pkg/genericclioptions" + "k8s.io/kubectl/pkg/util/podutils" "github.com/cilium/cilium/cilium-cli/defaults" "github.com/cilium/cilium/cilium-cli/k8s" @@ -39,7 +41,8 @@ import ( ) const sysdumpLogFile = "cilium-sysdump.log" -const helmReleaseName = "cilium" +const ciliumHelmReleaseName = "cilium" +const tetragonHelmReleaseName = "tetragon" // Options groups together the set of options required to collect a sysdump. type Options struct { @@ -57,6 +60,8 @@ type Options struct { CiliumEnvoyLabelSelector string // The release name of Cilium Helm chart. CiliumHelmReleaseName string + // The release name of Tetragon Helm chart. + TetragonHelmReleaseName string // The labels used to target Cilium Node Init daemon set. Usually, this label is same as CiliumNodeInitLabelSelector. CiliumNodeInitDaemonSetSelector string // The labels used to target Cilium Node Init pods. @@ -69,6 +74,8 @@ type Options struct { CiliumSPIREServerLabelSelector string // The labels used to target Cilium SPIRE agent pods. CiliumSPIREAgentLabelSelector string + // Whether to collect logs from cilium-agent pods that are crashing. + CollectLogsFromNotReadyAgents bool // Whether to enable debug logging. Debug bool // Whether to enable scraping profiling data. @@ -163,6 +170,9 @@ type Collector struct { NodeList []string // CiliumPods is a list of Cilium agent pods running on nodes in NodeList. CiliumPods []*corev1.Pod + // CiliumNotReadyPods is a list of additional Cilium agent pods to collect logs from + // regardless of node filter. + CiliumNotReadyPods []*corev1.Pod // CiliumOperatorPods is the list of Cilium operator pods. CiliumOperatorPods []*corev1.Pod // CiliumConfigMap is a pointer to cilium-config ConfigMap. @@ -225,12 +235,19 @@ func NewCollector( } if c.Options.CiliumHelmReleaseName == "" { - c.log("ℹ️ Using default Cilium Helm release name: %q", helmReleaseName) - c.Options.CiliumHelmReleaseName = helmReleaseName + c.log("ℹ️ Using default Cilium Helm release name: %q", ciliumHelmReleaseName) + c.Options.CiliumHelmReleaseName = ciliumHelmReleaseName } else { c.log("ℹ️ Cilium Helm release name: %q", c.Options.CiliumHelmReleaseName) } + if c.Options.TetragonHelmReleaseName == "" { + c.log("ℹ️ Using default Tetragon Helm release name: %q", tetragonHelmReleaseName) + c.Options.TetragonHelmReleaseName = tetragonHelmReleaseName + } else { + c.log("ℹ️ Tetragon Helm release name: %q", c.Options.TetragonHelmReleaseName) + } + if c.Options.CiliumSPIRENamespace == "" { if ns, err := detectCiliumSPIRENamespace(k); err != nil { c.logDebug("Failed to detect Cilium SPIRE installation: %v", err) @@ -272,10 +289,7 @@ func NewCollector( } // Build the list of node names in which the user is interested. - c.NodeList, err = buildNodeNameList(c.allNodes, c.Options.NodeList) - if err != nil { - return nil, fmt.Errorf("failed to build node list: %w", err) - } + c.NodeList = buildNodeNameList(c.allNodes, c.Options.NodeList) c.logDebug("Restricting bugtool and logs collection to pods in %v", c.NodeList) if c.Options.CiliumNamespace != "" { @@ -286,6 +300,23 @@ func NewCollector( return nil, fmt.Errorf("failed to get Cilium pods: %w", err) } c.CiliumPods = FilterPods(ciliumPods, c.NodeList) + if c.Options.CollectLogsFromNotReadyAgents { + crashedPods := filterCrashedPods(ciliumPods, 5) + notReady := filterRunningNotReadyPods(ciliumPods, 5) + restartedPods := filterRestartedContainersPods(ciliumPods, 5) + allPods := slices.Concat(crashedPods, notReady, restartedPods) + + for _, pod := range allPods { + if !slices.ContainsFunc(c.CiliumNotReadyPods, func(p *corev1.Pod) bool { + return p.Name == pod.Name + }) { + c.CiliumNotReadyPods = append(c.CiliumNotReadyPods, pod) + } + } + if len(c.CiliumNotReadyPods) > 0 { + c.logWarn("Collecting additional logs from %d not ready/crashing/restarted Cilium agent pods", len(c.CiliumNotReadyPods)) + } + } c.CiliumConfigMap, err = c.Client.GetConfigMap(context.Background(), c.Options.CiliumNamespace, ciliumConfigMapName, metav1.GetOptions{}) if err != nil { @@ -381,24 +412,46 @@ func (c *Collector) AbsoluteTempPath(f string) string { return path.Join(c.sysdumpDir, c.replaceTimestamp(f)) } +func (c *Collector) WithFileSink(filename string, fn func(io.Writer) error) error { + path := c.AbsoluteTempPath(filename) + file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, fileMode) + if err != nil { + return err + } + + return errors.Join( + fn(file), + file.Close(), + ) +} + // WriteYAML writes a kubernetes object to a file as YAML. func (c *Collector) WriteYAML(filename string, o runtime.Object) error { - return writeYaml(c.AbsoluteTempPath(filename), o) + return c.WithFileSink(filename, func(w io.Writer) error { + return writeYAML(o, w) + }) } // WriteString writes a string to a file. func (c *Collector) WriteString(filename string, value string) error { - return writeString(c.AbsoluteTempPath(filename), value) -} - -// WriteBytes writes a byte array to a file. -func (c *Collector) WriteBytes(filename string, value []byte) error { - return writeBytes(c.AbsoluteTempPath(filename), value) + return c.WithFileSink(filename, func(out io.Writer) error { + _, err := fmt.Fprint(out, value) + return err + }) } // WriteTable writes a kubernetes table to a file. func (c *Collector) WriteTable(filename string, value *metav1.Table) error { - return writeTable(c.AbsoluteTempPath(filename), value) + return c.WithFileSink(filename, func(out io.Writer) error { + return writeTable(value, out) + }) +} + +// WriteEventTable writes writes a html summary of cluster events to a file. +func (c *Collector) WriteEventTable(filename string, events []corev1.Event) error { + return c.WithFileSink(filename, func(out io.Writer) error { + return writeEventTable(events, out) + }) } // Run performs the actual sysdump collection. @@ -441,8 +494,8 @@ func (c *Collector) Run() error { if err := c.WriteYAML(kubernetesEventsFileName, v); err != nil { return fmt.Errorf("failed to collect Kubernetes events: %w", err) } - if err := c.WriteBytes(kubernetesEventsTableFileName, makeEventTable(v.Items)); err != nil { - return fmt.Errorf("failed to write event tble: %w", err) + if err := c.WriteEventTable(kubernetesEventsTableFileName, v.Items); err != nil { + return fmt.Errorf("failed to write event table: %w", err) } return nil }, @@ -591,7 +644,7 @@ func (c *Collector) Run() error { if err != nil { return fmt.Errorf("failed to get logs from Hubble certgen pods") } - if err := c.SubmitLogsTasks(filterCrashedPods(p), c.Options.LogsSinceTime, c.Options.LogsLimitBytes); err != nil { + if err := c.SubmitLogsTasks(filterCrashedPods(p, 0), c.Options.LogsSinceTime, c.Options.LogsLimitBytes); err != nil { return fmt.Errorf("failed to collect logs from Hubble certgen pods") } } @@ -1252,6 +1305,17 @@ func (c *Collector) Run() error { return nil }, }, + { + CreatesSubtasks: true, + Description: "Collecting logs from crashing Cilium pods", + Quick: false, + Task: func(_ context.Context) error { + if err := c.SubmitLogsTasks(c.CiliumNotReadyPods, c.Options.LogsSinceTime, c.Options.LogsLimitBytes); err != nil { + return fmt.Errorf("failed to collect logs from not ready Cilium pods") + } + return nil + }, + }, { CreatesSubtasks: true, Description: "Collecting logs from Cilium Envoy pods", @@ -1620,7 +1684,7 @@ func (c *Collector) Run() error { helmTasks := []Task{ { CreatesSubtasks: true, - Description: "Collecting Helm metadata from the release", + Description: "Collecting Helm metadata from the Cilium release", Quick: true, Task: func(ctx context.Context) error { v, err := c.Client.GetHelmMetadata(ctx, c.Options.CiliumHelmReleaseName, c.Options.CiliumNamespace) @@ -1635,7 +1699,22 @@ func (c *Collector) Run() error { }, { CreatesSubtasks: true, - Description: "Collecting Helm values from the release", + Description: "Collecting Helm metadata from the Tetragon release", + Quick: true, + Task: func(ctx context.Context) error { + v, err := c.Client.GetHelmMetadata(ctx, c.Options.TetragonHelmReleaseName, c.Options.TetragonNamespace) + if err != nil { + return fmt.Errorf("failed to get the helm metadata from the release: %w", err) + } + if err := c.WriteString(tetragonHelmMetadataFileName, v); err != nil { + return fmt.Errorf("failed to write the helm metadata to the file: %w", err) + } + return nil + }, + }, + { + CreatesSubtasks: true, + Description: "Collecting Helm values from the Cilium release", Quick: true, Task: func(ctx context.Context) error { v, err := c.Client.GetHelmValues(ctx, c.Options.CiliumHelmReleaseName, c.Options.CiliumNamespace) @@ -1648,6 +1727,21 @@ func (c *Collector) Run() error { return nil }, }, + { + CreatesSubtasks: true, + Description: "Collecting Helm values from the Tetragon release", + Quick: true, + Task: func(ctx context.Context) error { + v, err := c.Client.GetHelmValues(ctx, c.Options.TetragonHelmReleaseName, c.Options.TetragonNamespace) + if err != nil { + return fmt.Errorf("failed to get the helm values from the release: %w", err) + } + if err := c.WriteString(tetragonHelmValuesFileName, v); err != nil { + return fmt.Errorf("failed to write the helm values to the file: %w", err) + } + return nil + }, + }, } tasks = append(tasks, helmTasks...) @@ -2432,21 +2526,18 @@ func (c *Collector) submitHubbleFlowsTasks(_ context.Context, pods []*corev1.Pod for _, p := range pods { p := p if err := c.Pool.Submit("hubble-flows-"+p.Name, func(ctx context.Context) error { - b, e, err := c.Client.ExecInPodWithStderr(ctx, p.Namespace, p.Name, containerName, []string{ - "timeout", "--signal", "SIGINT", "--preserve-status", hubbleFlowsTimeout, "bash", "-c", - fmt.Sprintf("hubble observe --last %d --debug -o jsonpb", c.Options.HubbleFlowsCount), - }) - if err != nil { - return fmt.Errorf("failed to collect hubble flows for %q in namespace %q: %w: %s", p.Name, p.Namespace, err, e.String()) - } - // Dump the resulting file's contents to the temporary directory. - if err := c.WriteBytes(fmt.Sprintf(hubbleFlowsFileName, p.Name), b.Bytes()); err != nil { - return fmt.Errorf("failed to write hubble flows for %q in namespace %q: %w", p.Name, p.Namespace, err) - } - // Dump the stderr from the hubble observe command to the temporary directory. - if err := c.WriteBytes(fmt.Sprintf(hubbleObserveFileName, p.Name), e.Bytes()); err != nil { - return fmt.Errorf("failed to write hubble stderr for %q in namespace %q: %w", p.Name, p.Namespace, err) + if err := c.WithFileSink(fmt.Sprintf(hubbleFlowsFileName, p.Name), func(stdout io.Writer) error { + return c.WithFileSink(fmt.Sprintf(hubbleObserveFileName, p.Name), func(stderr io.Writer) error { + return c.Client.ExecInPodWithWriters(ctx, nil, p.Namespace, p.Name, containerName, []string{ + "timeout", "--signal", "SIGINT", "--preserve-status", hubbleFlowsTimeout, "bash", "-c", + fmt.Sprintf("hubble observe --last %d --debug -o jsonpb", c.Options.HubbleFlowsCount), + }, stdout, stderr) + + }) + }); err != nil { + return fmt.Errorf("failed to collect hubble flows for %q in namespace %q: %w", p.Name, p.Namespace, err) } + c.logDebug("Finished collecting hubble flows from %s/%s", p.Namespace, p.Name) return nil }); err != nil { @@ -2472,15 +2563,12 @@ func (c *Collector) submitSpireEntriesTasks(pods []*corev1.Pod) error { }() command := []string{"/opt/spire/bin/spire-server", "entry", "show", "-output", "json"} - o, err := c.Client.ExecInPod(ctx, p.Namespace, p.Name, containerName, command) - if err != nil { + if err := c.WithFileSink(fmt.Sprintf(ciliumSPIREServerEntriesFileName, p.Name), func(out io.Writer) error { + return c.Client.ExecInPodWithWriters(ctx, nil, p.Namespace, p.Name, containerName, command, out, k8s.StderrAsError) + }); err != nil { return fmt.Errorf("failed to collect 'spire-server' output for %q in namespace %q: %w", p.Name, p.Namespace, err) } - if err := c.WriteBytes(fmt.Sprintf(ciliumSPIREServerEntriesFileName, p.Name), o.Bytes()); err != nil { - return fmt.Errorf("failed to write spireserver stdout for %q in namespace %q: %w", p.Name, p.Namespace, err) - } - return nil }); err != nil { return fmt.Errorf("failed to submit SPIRE entries task for %q: %w", p.Name, err) @@ -2534,16 +2622,14 @@ func (c *Collector) SubmitCniConflistSubtask(pods []*corev1.Pod, containerName s cniConfigFileNames := strings.Split(strings.TrimSpace(outputStr.String()), "\n") for _, cniFileName := range cniConfigFileNames { cniConfigPath := path.Join(c.Options.CNIConfigDirectory, cniFileName) - cniConfigFileContent, err := c.Client.ExecInPod(ctx, p.GetNamespace(), p.GetName(), containerName, []string{ - catCommand, - cniConfigPath, - }) - if err != nil { + if err := c.WithFileSink(fmt.Sprintf(cniConfigFileName, cniFileName, p.GetName()), func(out io.Writer) error { + return c.Client.ExecInPodWithWriters(ctx, nil, p.GetNamespace(), p.GetName(), containerName, []string{ + catCommand, + cniConfigPath, + }, out, k8s.StderrAsError) + }); err != nil { return fmt.Errorf("failed to copy CNI config file %q from directory %q: %w", cniFileName, c.Options.CNIConfigDirectory, err) } - if err := c.WriteBytes(fmt.Sprintf(cniConfigFileName, cniFileName, p.GetName()), cniConfigFileContent.Bytes()); err != nil { - return fmt.Errorf("failed to write CNI configuration %q for %q in namespace %q: %w", cniFileName, p.GetName(), p.Namespace, err) - } } return nil }); err != nil { @@ -2589,18 +2675,17 @@ func (c *Collector) SubmitGopsSubtasks(pods []*corev1.Pod, containerName string) if err != nil { return err } - o, err := c.Client.ExecInPod(ctx, p.Namespace, p.Name, containerName, []string{ - gopsCommand, - g, - agentPID, - }) - if err != nil { - return fmt.Errorf("failed to collect gops for %q (%q) in namespace %q: %w", p.Name, containerName, p.Namespace, err) - } - // Dump the output to the temporary directory. - if err := c.WriteBytes(fmt.Sprintf(gopsFileName, p.Name, containerName, g), o.Bytes()); err != nil { + + if err := c.WithFileSink(fmt.Sprintf(gopsFileName, p.Name, containerName, g), func(out io.Writer) error { + return c.Client.ExecInPodWithWriters(ctx, nil, p.Namespace, p.Name, containerName, []string{ + gopsCommand, + g, + agentPID, + }, out, k8s.StderrAsError) + }); err != nil { return fmt.Errorf("failed to collect gops for %q (%q) in namespace %q: %w", p.Name, containerName, p.Namespace, err) } + return nil }); err != nil { return fmt.Errorf("failed to submit %s gops task for %q: %w", g, p.Name, err) @@ -2747,14 +2832,13 @@ func (c *Collector) SubmitLogsTasks(pods []*corev1.Pod, since time.Duration, lim for _, d := range allContainers { d := d if err := c.Pool.Submit(fmt.Sprintf("logs-%s-%s", p.Name, d.Name), func(ctx context.Context) error { - l, err := c.Client.GetLogs(ctx, p.Namespace, p.Name, d.Name, - corev1.PodLogOptions{LimitBytes: &limitBytes, SinceTime: &t, Timestamps: true}) - if err != nil { - return fmt.Errorf("failed to collect logs for %q (%q) in namespace %q: %w", p.Name, d.Name, p.Namespace, err) - } - if err := c.WriteString(fmt.Sprintf(ciliumLogsFileName, p.Name, d.Name), l); err != nil { + if err := c.WithFileSink(fmt.Sprintf(ciliumLogsFileName, p.Name, d.Name), func(out io.Writer) error { + return c.Client.GetLogs(ctx, p.Namespace, p.Name, d.Name, + corev1.PodLogOptions{LimitBytes: &limitBytes, SinceTime: &t, Timestamps: true}, out) + }); err != nil { return fmt.Errorf("failed to collect logs for %q (%q) in namespace %q: %w", p.Name, d.Name, p.Namespace, err) } + // Check if this container has restarted, in which case we should gather the previous one's logs too. previous := false for _, s := range p.Status.ContainerStatuses { @@ -2765,12 +2849,10 @@ func (c *Collector) SubmitLogsTasks(pods []*corev1.Pod, since time.Duration, lim } if previous { c.logDebug("Collecting logs for restarted container %q in pod %q in namespace %q", d.Name, p.Name, p.Namespace) - u, err := c.Client.GetLogs(ctx, p.Namespace, p.Name, d.Name, - corev1.PodLogOptions{LimitBytes: &limitBytes, SinceTime: &t, Previous: true, Timestamps: true}) - if err != nil { - return fmt.Errorf("failed to collect previous logs for %q (%q) in namespace %q: %w", p.Name, d.Name, p.Namespace, err) - } - if err := c.WriteString(fmt.Sprintf(ciliumPreviousLogsFileName, p.Name, d.Name), u); err != nil { + if err := c.WithFileSink(fmt.Sprintf(ciliumPreviousLogsFileName, p.Name, d.Name), func(out io.Writer) error { + return c.Client.GetLogs(ctx, p.Namespace, p.Name, d.Name, + corev1.PodLogOptions{LimitBytes: &limitBytes, SinceTime: &t, Previous: true, Timestamps: true}, out) + }); err != nil { return fmt.Errorf("failed to collect previous logs for %q (%q) in namespace %q: %w", p.Name, d.Name, p.Namespace, err) } } @@ -2858,15 +2940,15 @@ func (c *Collector) submitKVStoreTasks(ctx context.Context, pod *corev1.Pod) err prefix: "state/services", }, } { - stdout, stderr, err := c.Client.ExecInPodWithStderr(ctx, pod.Namespace, pod.Name, defaults.AgentContainerName, []string{ - "cilium", "kvstore", "get", "cilium/" + dump.prefix, "--recursive", "-o", "json", - }) - if err != nil { - return fmt.Errorf("failed to collect kvstore data in %q in namespace %q: %w: %s", pod.Name, pod.Namespace, err, stderr.String()) - } filename := "kvstore-" + dump.name + ".json" - if err := c.WriteString(filename, stdout.String()); err != nil { - return fmt.Errorf("failed writing kvstore dump for prefix %q to file %q: %w", dump.prefix, filename, err) + + var stderr bytes.Buffer + if err := c.WithFileSink(filename, func(out io.Writer) error { + return c.Client.ExecInPodWithWriters(ctx, nil, pod.Namespace, pod.Name, defaults.AgentContainerName, []string{ + "cilium", "kvstore", "get", "cilium/" + dump.prefix, "--recursive", "-o", "json", + }, out, &stderr) + }); err != nil { + return fmt.Errorf("failed to collect kvstore data in %q in namespace %q: %w: %s", pod.Name, pod.Namespace, err, stderr.String()) } } @@ -2953,23 +3035,27 @@ func (c *Collector) submitClusterMeshAPIServerDbgTasks(pods []*corev1.Pod) error filename := fmt.Sprintf("%s-%s-%s-.%s", pod.Name, task.container, task.name, task.ext) if err := c.Pool.Submit(filename, func(ctx context.Context) error { - stdout, stderr, err := c.Client.ExecInPodWithStderr(ctx, pod.Namespace, pod.Name, task.container, task.cmd) - if err != nil { - stderrStr := stderr.String() - if strings.Contains(stderrStr, "Usage:") || strings.Contains(stderrStr, "unknown command") { - // The default cobra error tends to be misleading when both the - // command and the flags are not found, as it reports the missing - // flags rather than the missing command. Hence, let's just guess - // and output a generic unknown command error. - stderrStr = "unknown command - this is expected if not supported by this Cilium version" - } + if err := c.WithFileSink(filename, func(out io.Writer) error { + var stderr bytes.Buffer - return fmt.Errorf("failed to collect clustermesh %s information from %s/%s (%s): %w: %s", - task.name, pod.Namespace, pod.Name, task.container, err, stderrStr) - } + err := c.Client.ExecInPodWithWriters(ctx, nil, pod.Namespace, pod.Name, task.container, task.cmd, out, &stderr) + if err != nil { + stderrStr := stderr.String() + if strings.Contains(stderrStr, "Usage:") || strings.Contains(stderrStr, "unknown command") { + // The default cobra error tends to be misleading when both the + // command and the flags are not found, as it reports the missing + // flags rather than the missing command. Hence, let's just guess + // and output a generic unknown command error. + stderrStr = "unknown command - this is expected if not supported by this Cilium version" + } + + return fmt.Errorf("%w: %s", err, stderrStr) + } - if err := c.WriteString(filename, stdout.String()); err != nil { - return fmt.Errorf("failed to write clustermesh %s information to file %q: %w", task.name, filename, err) + return nil + }); err != nil { + return fmt.Errorf("failed to collect clustermesh %s information from %s/%s (%s): %w", + task.name, pod.Namespace, pod.Name, task.container, err) } return nil @@ -3008,7 +3094,7 @@ func podIsRunningAndHasContainer(pod *corev1.Pod, container string) bool { return false } -func buildNodeNameList(nodes *corev1.NodeList, filter string) ([]string, error) { +func buildNodeNameList(nodes *corev1.NodeList, filter string) []string { w := strings.Split(strings.TrimSpace(filter), ",") r := make([]string, 0) for _, node := range nodes.Items { @@ -3021,36 +3107,69 @@ func buildNodeNameList(nodes *corev1.NodeList, filter string) ([]string, error) continue } } - return r, nil + return r } // AllPods converts a PodList into a slice of Pod objects. func AllPods(l *corev1.PodList) []*corev1.Pod { - return filterPods(l, func(*corev1.Pod) bool { return true }) + return filterPods(l, func(*corev1.Pod) bool { return true }, 0) } // FilterPods filters a list of pods by node names. func FilterPods(l *corev1.PodList, n []string) []*corev1.Pod { - return filterPods(l, func(po *corev1.Pod) bool { return slices.Contains(n, po.Spec.NodeName) }) + return filterPods(l, func(po *corev1.Pod) bool { return slices.Contains(n, po.Spec.NodeName) }, 0) } -func filterCrashedPods(l *corev1.PodList) []*corev1.Pod { +func filterCrashedPods(l *corev1.PodList, limit int) []*corev1.Pod { return filterPods(l, func(po *corev1.Pod) bool { + for _, containerStatus := range po.Status.InitContainerStatuses { + if containerStatus.State.Waiting != nil && containerStatus.State.Waiting.Reason == "CrashLoopBackOff" { + return true + } + } for _, containerStatus := range po.Status.ContainerStatuses { if containerStatus.State.Waiting != nil && containerStatus.State.Waiting.Reason == "CrashLoopBackOff" { return true } } return false - }) + }, limit) } -func filterPods(l *corev1.PodList, filter func(po *corev1.Pod) bool) []*corev1.Pod { +func filterRunningNotReadyPods(l *corev1.PodList, limit int) []*corev1.Pod { + return filterPods(l, func(po *corev1.Pod) bool { + if po.Status.Phase != corev1.PodRunning { + return false + } + return !podutils.IsPodReady(po) + }, limit) +} + +func filterRestartedContainersPods(l *corev1.PodList, limit int) []*corev1.Pod { + return filterPods(l, func(po *corev1.Pod) bool { + for _, containerStatus := range po.Status.InitContainerStatuses { + if containerStatus.RestartCount > 0 { + return true + } + } + for _, containerStatus := range po.Status.ContainerStatuses { + if containerStatus.RestartCount > 0 { + return true + } + } + return false + }, limit) +} + +func filterPods(l *corev1.PodList, filter func(po *corev1.Pod) bool, limit int) []*corev1.Pod { r := make([]*corev1.Pod, 0) for _, p := range l.Items { p := p if filter(&p) { r = append(r, &p) + if limit > 0 && len(r) >= limit { + break + } } } return r @@ -3166,6 +3285,9 @@ func InitSysdumpFlags(cmd *cobra.Command, options *Options, optionPrefix string, cmd.Flags().StringVar(&options.CiliumHelmReleaseName, optionPrefix+"cilium-helm-release-name", "", "The Cilium Helm release name for which to get values. If not provided then the --helm-release-name global flag is used (if provided)") + cmd.Flags().StringVar(&options.TetragonHelmReleaseName, + optionPrefix+"tetragon-helm-release-name", "", + "The Tetragon Helm release name for which to get values.") cmd.Flags().StringVar(&options.CiliumOperatorLabelSelector, optionPrefix+"cilium-operator-label-selector", DefaultCiliumOperatorLabelSelector, "The labels used to target Cilium operator pods") @@ -3181,6 +3303,9 @@ func InitSysdumpFlags(cmd *cobra.Command, options *Options, optionPrefix string, cmd.Flags().StringVar(&options.CiliumSPIREServerLabelSelector, optionPrefix+"cilium-spire-server-selector", DefaultCiliumSpireServerLabelSelector, "The labels used to target Cilium spire-server pods") + cmd.Flags().BoolVar(&options.CollectLogsFromNotReadyAgents, + optionPrefix+"collect-logs-from-not-ready-agents", DefaultCollectLogsFromNotReadyAgents, + "Whether to collect logs from not ready Cilium agent pods") cmd.Flags().BoolVar(&options.Debug, optionPrefix+"debug", DefaultDebug, "Whether to enable debug logging") diff --git a/vendor/github.com/cilium/cilium/cilium-cli/sysdump/writers.go b/vendor/github.com/cilium/cilium/cilium-cli/sysdump/writers.go index d077ecd240..3a377dfe09 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/sysdump/writers.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/sysdump/writers.go @@ -8,55 +8,78 @@ import ( _ "embed" "fmt" "html/template" - "os" + "io" "sort" "strings" "time" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/cli-runtime/pkg/printers" "k8s.io/client-go/kubernetes/scheme" + "sigs.k8s.io/yaml" ) //go:embed eventSummary.html var eventSummaryHTML string -func writeBytes(p string, b []byte) error { - return os.WriteFile(p, b, fileMode) -} - -func writeString(p, v string) error { - return writeBytes(p, []byte(v)) -} - -func writeTable(p string, o *metav1.Table) error { - var b bytes.Buffer - if err := printers.NewTablePrinter(printers.PrintOptions{ +func writeTable(obj *metav1.Table, out io.Writer) error { + return printers.NewTablePrinter(printers.PrintOptions{ Wide: true, WithNamespace: true, - }).PrintObj(o, &b); err != nil { - return err - } - return writeString(p, b.String()) + }).PrintObj(obj, out) } -func writeYaml(p string, o runtime.Object) error { - var j printers.YAMLPrinter - w, err := printers.NewTypeSetter(scheme.Scheme).WrapToPrinter(&j, nil) - if err != nil { - return err - } - var b bytes.Buffer - if err := w.PrintObj(o, &b); err != nil { - return err +func writeYAML(obj runtime.Object, out io.Writer) error { + delegate := printers.ResourcePrinter(&printers.YAMLPrinter{}) + if meta.IsListType(obj) && meta.LenList(obj) > 0 { + // Print lists one item at a time, to reduce the amount of memory used by the printer. + delegate = printers.ResourcePrinterFunc(func(obj runtime.Object, out io.Writer) error { + _, err := fmt.Fprintf(out, "apiVersion: %s\nitems:\n", obj.GetObjectKind().GroupVersionKind().GroupVersion()) + if err != nil { + return err + } + + if err := meta.EachListItem(obj, func(item runtime.Object) error { + data, err := yaml.Marshal(item) + if err != nil { + return err + } + + _, err = indentAsListItem(data, out) + return err + }); err != nil { + return err + } + + _, err = fmt.Fprintf(out, "kind: %s\n", obj.GetObjectKind().GroupVersionKind().Kind) + if err != nil { + return err + } + + if listMeta, err := meta.ListAccessor(obj); err == nil { + if rv := listMeta.GetResourceVersion(); rv != "" { + _, err = fmt.Fprintf(out, "metadata:\n resourceVersion: %q\n", rv) + } else { + _, err = fmt.Fprint(out, "metadata: {}\n", rv) + } + + return err + } + + return nil + }) } - return writeString(p, b.String()) + + // WrapToPrinter never returns an error, since we don't provide one. + printer, _ := printers.NewTypeSetter(scheme.Scheme).WrapToPrinter(delegate, nil) + return printer.PrintObj(obj, out) } // writeEventTable writes a html summary of cluster events. -func makeEventTable(events []corev1.Event) []byte { +func writeEventTable(events []corev1.Event, out io.Writer) error { // sort events by time sort.Slice(events, func(i, j int) bool { return events[i].LastTimestamp.Time.Before(events[j].LastTimestamp.Time) @@ -94,9 +117,33 @@ func makeEventTable(events []corev1.Event) []byte { }, }).Parse(eventSummaryHTML)) - out := bytes.NewBuffer([]byte{}) - if err := t.Execute(out, events); err != nil { - panic(err) // unreachable + return t.Execute(out, events) +} + +func indentAsListItem(in []byte, out io.Writer) (cnt int, err error) { + handle := func(n int, err error) error { + cnt += n + return err } - return out.Bytes() + + indent := []byte("- ") + for len(in) > 0 { + to := bytes.IndexAny(in, "\n") + if to == -1 { + to = len(in) + } else { + to++ + } + + if err = handle(out.Write(indent)); err != nil { + return cnt, err + } + if err = handle(out.Write(in[:to])); err != nil { + return cnt, err + } + + in, indent = in[to:], []byte(" ") + } + + return cnt, nil } diff --git a/vendor/github.com/cilium/cilium/cilium-cli/utils/features/utils.go b/vendor/github.com/cilium/cilium/cilium-cli/utils/features/utils.go index 3b7e048406..2b2438842c 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/utils/features/utils.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/utils/features/utils.go @@ -27,6 +27,27 @@ func (f IPFamily) String() string { return "undefined" } +// GetIPFamilies function converts string slice to IPFamily slice. +func GetIPFamilies(families []string) []IPFamily { + ipFams := make([]IPFamily, 0, len(families)) + for i := range families { + ipFams = append(ipFams, NewIPFamily(families[i])) + } + return ipFams +} + +// NewIPFamily is a factory function that consumes string and returns IPFamily. +func NewIPFamily(s string) IPFamily { + switch s { + case "ipv4": + return IPFamilyV4 + case "ipv6": + return IPFamilyV6 + default: + return IPFamilyAny + } +} + func GetIPFamily(addr string) IPFamily { ip := net.ParseIP(addr) diff --git a/vendor/github.com/cilium/cilium/daemon/k8s/pods.go b/vendor/github.com/cilium/cilium/daemon/k8s/pods.go new file mode 100644 index 0000000000..3c6edfb6d4 --- /dev/null +++ b/vendor/github.com/cilium/cilium/daemon/k8s/pods.go @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package k8s + +import ( + "fmt" + "strconv" + "strings" + + "github.com/cilium/hive/cell" + "github.com/cilium/hive/job" + "github.com/cilium/statedb" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/util/duration" + + "github.com/cilium/cilium/pkg/k8s" + "github.com/cilium/cilium/pkg/k8s/client" + slim_corev1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/api/core/v1" + "github.com/cilium/cilium/pkg/k8s/utils" + nodeTypes "github.com/cilium/cilium/pkg/node/types" + "github.com/cilium/cilium/pkg/time" +) + +// LocalPod is Cilium's internal model of the pods running on this node. +type LocalPod struct { + *slim_corev1.Pod + + // UpdatedAt is the time when [LocalPod] was last updated, e.g. it + // shows when the pod change was received from the api-server. + UpdatedAt time.Time `json:"updatedAt" yaml:"updatedAt"` +} + +func (p LocalPod) TableHeader() []string { + return []string{ + "Name", + "HostNetwork", + "PodIPs", + "Containers", + "Phase", + "Age", + } +} + +func (p LocalPod) TableRow() []string { + podIPs := make([]string, len(p.Status.PodIPs)) + for i := range p.Status.PodIPs { + podIPs[i] = p.Status.PodIPs[i].IP + } + containers := make([]string, len(p.Spec.Containers)) + for i, cont := range p.Spec.Containers { + ports := make([]string, len(cont.Ports)) + for i, port := range cont.Ports { + if port.Name != "" { + ports[i] = fmt.Sprintf("%d/%s (%s)", port.ContainerPort, string(port.Protocol), port.Name) + } else { + ports[i] = fmt.Sprintf("%d/%s", port.ContainerPort, string(port.Protocol)) + } + } + contName := cont.Name + if len(ports) > 0 { + contName += " (" + strings.Join(ports, ",") + ")" + } + containers[i] = contName + } + return []string{ + p.Namespace + "/" + p.Name, + strconv.FormatBool(p.Spec.HostNetwork), + strings.Join(podIPs, ", "), + strings.Join(containers, ", "), + string(p.Status.Phase), + duration.HumanDuration(time.Since(p.UpdatedAt)), + } +} + +const ( + PodTableName = "k8s-pods" +) + +var ( + PodNameIndex = newNameIndex[LocalPod]() + PodTableCell = cell.Provide(NewPodTableAndReflector) +) + +// NewPodTableAndReflector returns the read-only Table[LocalPod] and registers +// the k8s reflector. These are combined to ensure any dependency on Table[LocalPod] +// will start after the reflector, ensuring that Start hooks can wait for the table +// to initialize. +func NewPodTableAndReflector(jg job.Group, db *statedb.DB, cs client.Clientset) (statedb.Table[LocalPod], error) { + pods, err := NewPodTable(db) + if err != nil { + return nil, err + } + + if !cs.IsEnabled() { + return pods, nil + } + + cfg := podReflectorConfig(cs, pods) + err = k8s.RegisterReflector(jg, db, cfg) + return pods, err +} + +func PodByName(namespace, name string) statedb.Query[LocalPod] { + return PodNameIndex.Query(namespace + "/" + name) +} + +func NewPodTable(db *statedb.DB) (statedb.RWTable[LocalPod], error) { + tbl, err := statedb.NewTable( + PodTableName, + PodNameIndex, + ) + if err != nil { + return nil, err + } + return tbl, db.RegisterTable(tbl) +} + +func podReflectorConfig(cs client.Clientset, pods statedb.RWTable[LocalPod]) k8s.ReflectorConfig[LocalPod] { + lw := utils.ListerWatcherWithModifiers( + utils.ListerWatcherFromTyped(cs.Slim().CoreV1().Pods("")), + func(opts *metav1.ListOptions) { + opts.FieldSelector = fields.ParseSelectorOrDie("spec.nodeName=" + nodeTypes.GetName()).String() + }) + return k8s.ReflectorConfig[LocalPod]{ + Name: reflectorName, + Table: pods, + ListerWatcher: lw, + Transform: func(_ statedb.ReadTxn, obj any) (LocalPod, bool) { + pod, ok := obj.(*slim_corev1.Pod) + if !ok { + return LocalPod{}, false + } + return LocalPod{ + Pod: pod, + UpdatedAt: time.Now(), + }, true + }, + } +} diff --git a/vendor/github.com/cilium/cilium/daemon/k8s/resources.go b/vendor/github.com/cilium/cilium/daemon/k8s/resources.go index c228323d99..9e2a89a1eb 100644 --- a/vendor/github.com/cilium/cilium/daemon/k8s/resources.go +++ b/vendor/github.com/cilium/cilium/daemon/k8s/resources.go @@ -68,14 +68,6 @@ var ( }, ) }, - func(lc cell.Lifecycle, cs client.Clientset) (LocalPodResource, error) { - return k8s.PodResource( - lc, cs, - func(opts *metav1.ListOptions) { - opts.FieldSelector = fields.ParseSelectorOrDie("spec.nodeName=" + nodeTypes.GetName()).String() - }, - ) - }, ), ) ) @@ -88,10 +80,6 @@ type LocalNodeResource resource.Resource[*slim_corev1.Node] // CiliumNode object associated with the node we are currently running on. type LocalCiliumNodeResource resource.Resource[*cilium_api_v2.CiliumNode] -// LocalPodResource is a resource.Resource[*slim_corev1.Pod] but one which will only stream updates for pod -// objects scheduled on the node we are currently running on. -type LocalPodResource resource.Resource[*slim_corev1.Pod] - // Resources is a convenience struct to group all the agent k8s resources as cell constructor parameters. type Resources struct { cell.In @@ -100,7 +88,6 @@ type Resources struct { Endpoints resource.Resource[*k8s.Endpoints] LocalNode LocalNodeResource LocalCiliumNode LocalCiliumNodeResource - LocalPods LocalPodResource Namespaces resource.Resource[*slim_corev1.Namespace] NetworkPolicies resource.Resource[*slim_networkingv1.NetworkPolicy] CiliumNetworkPolicies resource.Resource[*cilium_api_v2.CiliumNetworkPolicy] diff --git a/vendor/github.com/cilium/cilium/daemon/k8s/tables.go b/vendor/github.com/cilium/cilium/daemon/k8s/tables.go new file mode 100644 index 0000000000..74ba8fc99a --- /dev/null +++ b/vendor/github.com/cilium/cilium/daemon/k8s/tables.go @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package k8s + +import ( + "github.com/cilium/hive/cell" + "github.com/cilium/statedb" + "github.com/cilium/statedb/index" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// TablesCell provides a set of StateDB tables for common Kubernetes objects. +// The tables are populated with the StateDB k8s reflector (pkg/k8s/statedb.go). +// +// NOTE: When adding new k8s tables make sure to provide and register from a +// single provider to ensure reflector starts before anyone depending on the table. +// See [NewPodTableAndReflector] for example. +var TablesCell = cell.Module( + "k8s-tables", + "StateDB tables of Kubernetes objects", + + PodTableCell, +) + +// reflectorName to use in [k8s.ReflectorConfig]. This is the name that appears +// for these tables in the table initializers and is visible in "db" command output +// when the tables are initializing. If a table has multiple reflectors into it +// in this package, append a suffix to [reflectorName]. +const reflectorName = "daemon-k8s" + +func newNameIndex[Obj metav1.Object]() statedb.Index[Obj, string] { + return statedb.Index[Obj, string]{ + Name: "name", + FromObject: func(obj Obj) index.KeySet { + return index.NewKeySet(index.String(obj.GetNamespace() + "/" + obj.GetName())) + }, + FromKey: index.String, + FromString: func(key string) (index.Key, error) { + return index.String(key), nil + }, + Unique: true, + } +} diff --git a/vendor/github.com/cilium/cilium/pkg/allocator/allocator.go b/vendor/github.com/cilium/cilium/pkg/allocator/allocator.go index 07c0dc950b..6b327c1385 100644 --- a/vendor/github.com/cilium/cilium/pkg/allocator/allocator.go +++ b/vendor/github.com/cilium/cilium/pkg/allocator/allocator.go @@ -945,7 +945,7 @@ func (a *Allocator) DeleteAllKeys() { // syncLocalKeys checks the kvstore and verifies that a master key exists for // all locally used allocations. This will restore master keys if deleted for // some reason. -func (a *Allocator) syncLocalKeys() error { +func (a *Allocator) syncLocalKeys() { // Create a local copy of all local allocations to not require to hold // any locks while performing kvstore operations. Local use can // disappear while we perform the sync. For master keys this is fine as @@ -960,8 +960,6 @@ func (a *Allocator) syncLocalKeys() error { for id, key := range ids { a.syncLocalKey(ctx, id, key) } - - return nil } func (a *Allocator) syncLocalKey(ctx context.Context, id idpool.ID, key AllocatorKey) { @@ -1011,9 +1009,7 @@ func (a *Allocator) syncLocalKey(ctx context.Context, id idpool.ID, key Allocato func (a *Allocator) startLocalKeySync() { go func(a *Allocator) { for { - if err := a.syncLocalKeys(); err != nil { - log.WithError(err).Warning("Unable to run local key sync routine") - } + a.syncLocalKeys() select { case <-a.stopGC: diff --git a/vendor/github.com/cilium/cilium/pkg/byteorder/byteorder_littleendian.go b/vendor/github.com/cilium/cilium/pkg/byteorder/byteorder_littleendian.go index 0fffee1b24..7cf8ef01df 100644 --- a/vendor/github.com/cilium/cilium/pkg/byteorder/byteorder_littleendian.go +++ b/vendor/github.com/cilium/cilium/pkg/byteorder/byteorder_littleendian.go @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright Authors of Cilium -//go:build 386 || amd64 || arm || arm64 || mips64le || ppc64le || riscv64 || wasm +//go:build 386 || amd64 || arm || arm64 || mips64le || ppc64le || riscv64 || wasm || loong64 package byteorder diff --git a/vendor/github.com/cilium/cilium/pkg/clustermesh/types/option.go b/vendor/github.com/cilium/cilium/pkg/clustermesh/types/option.go index b00ee5c92e..fe746e82b8 100644 --- a/vendor/github.com/cilium/cilium/pkg/clustermesh/types/option.go +++ b/vendor/github.com/cilium/cilium/pkg/clustermesh/types/option.go @@ -112,3 +112,26 @@ func (c ClusterInfo) ValidateRemoteConfig(config CiliumClusterConfig) error { return nil } + +// QuirksConfig allows the user to configure how Cilium behaves when a set +// of incompatible options are configured together into the agent. +type QuirksConfig struct { + // AllowUnsafePolicySKBUsage determines whether to hard-fail startup + // due to detection of a configuration combination that may trigger + // connection impact in the dataplane due to clustermesh IDs + // conflicting with other usage of skb->mark field. See GH-21330. + AllowUnsafePolicySKBUsage bool +} + +var DefaultQuirks = QuirksConfig{ + AllowUnsafePolicySKBUsage: false, +} + +func (_ QuirksConfig) Flags(flags *pflag.FlagSet) { + flags.Bool("allow-unsafe-policy-skb-usage", false, + "Allow the daemon to continue to operate even if conflicting "+ + "clustermesh ID configuration is detected which may "+ + "impact the ability for Cilium to enforce network "+ + "policy both within and across clusters") + flags.MarkHidden("allow-unsafe-policy-skb-usage") +} diff --git a/vendor/github.com/cilium/cilium/pkg/container/bitlpm/cidr.go b/vendor/github.com/cilium/cilium/pkg/container/bitlpm/cidr.go index ee14422af0..b904fb8136 100644 --- a/vendor/github.com/cilium/cilium/pkg/container/bitlpm/cidr.go +++ b/vendor/github.com/cilium/cilium/pkg/container/bitlpm/cidr.go @@ -12,15 +12,15 @@ import ( // CIDRTrie can hold both IPv4 and IPv6 prefixes // at the same time. type CIDRTrie[T any] struct { - v4 Trie[Key[netip.Prefix], T] - v6 Trie[Key[netip.Prefix], T] + v4 Trie[cidrKey, T] + v6 Trie[cidrKey, T] } // NewCIDRTrie creates a new CIDRTrie[T any]. func NewCIDRTrie[T any]() *CIDRTrie[T] { return &CIDRTrie[T]{ - v4: NewTrie[netip.Prefix, T](32), - v6: NewTrie[netip.Prefix, T](128), + v4: NewTrie[cidrKey, T](32), + v6: NewTrie[cidrKey, T](128), } } @@ -41,7 +41,7 @@ func (c *CIDRTrie[T]) LongestPrefixMatch(addr netip.Addr) (netip.Prefix, T, bool prefix := netip.PrefixFrom(addr, bits) k, v, ok := c.treeForFamily(prefix).LongestPrefixMatch(cidrKey(prefix)) if ok { - return k.Value(), v, ok + return netip.Prefix(k), v, ok } var p netip.Prefix return p, v, ok @@ -49,46 +49,46 @@ func (c *CIDRTrie[T]) LongestPrefixMatch(addr netip.Addr) (netip.Prefix, T, bool // Ancestors iterates over every CIDR pair that contains the CIDR argument. func (c *CIDRTrie[T]) Ancestors(cidr netip.Prefix, fn func(k netip.Prefix, v T) bool) { - c.treeForFamily(cidr).Ancestors(uint(cidr.Bits()), cidrKey(cidr), func(prefix uint, k Key[netip.Prefix], v T) bool { - return fn(k.Value(), v) + c.treeForFamily(cidr).Ancestors(uint(cidr.Bits()), cidrKey(cidr), func(prefix uint, k cidrKey, v T) bool { + return fn(netip.Prefix(k), v) }) } -func (c *CIDRTrie[T]) AncestorIterator(cidr netip.Prefix) Iterator[Key[netip.Prefix], T] { +func (c *CIDRTrie[T]) AncestorIterator(cidr netip.Prefix) ancestorIterator[cidrKey, T] { return c.treeForFamily(cidr).AncestorIterator(uint(cidr.Bits()), cidrKey(cidr)) } // AncestorsLongestPrefixFirst iterates over every CIDR pair that contains the CIDR argument, // longest matching prefix first, then iterating towards the root of the trie. func (c *CIDRTrie[T]) AncestorsLongestPrefixFirst(cidr netip.Prefix, fn func(k netip.Prefix, v T) bool) { - c.treeForFamily(cidr).AncestorsLongestPrefixFirst(uint(cidr.Bits()), cidrKey(cidr), func(prefix uint, k Key[netip.Prefix], v T) bool { - return fn(k.Value(), v) + c.treeForFamily(cidr).AncestorsLongestPrefixFirst(uint(cidr.Bits()), cidrKey(cidr), func(prefix uint, k cidrKey, v T) bool { + return fn(netip.Prefix(k), v) }) } -func (c *CIDRTrie[T]) AncestorLongestPrefixFirstIterator(cidr netip.Prefix) Iterator[Key[netip.Prefix], T] { +func (c *CIDRTrie[T]) AncestorLongestPrefixFirstIterator(cidr netip.Prefix) ancestorLPFIterator[cidrKey, T] { return c.treeForFamily(cidr).AncestorLongestPrefixFirstIterator(uint(cidr.Bits()), cidrKey(cidr)) } // Descendants iterates over every CIDR that is contained by the CIDR argument. func (c *CIDRTrie[T]) Descendants(cidr netip.Prefix, fn func(k netip.Prefix, v T) bool) { - c.treeForFamily(cidr).Descendants(uint(cidr.Bits()), cidrKey(cidr), func(prefix uint, k Key[netip.Prefix], v T) bool { - return fn(k.Value(), v) + c.treeForFamily(cidr).Descendants(uint(cidr.Bits()), cidrKey(cidr), func(prefix uint, k cidrKey, v T) bool { + return fn(netip.Prefix(k), v) }) } -func (c *CIDRTrie[T]) DescendantIterator(cidr netip.Prefix) Iterator[Key[netip.Prefix], T] { +func (c *CIDRTrie[T]) DescendantIterator(cidr netip.Prefix) descendantIterator[cidrKey, T] { return c.treeForFamily(cidr).DescendantIterator(uint(cidr.Bits()), cidrKey(cidr)) } // DescendantsShortestPrefixFirst iterates over every CIDR that is contained by the CIDR argument. func (c *CIDRTrie[T]) DescendantsShortestPrefixFirst(cidr netip.Prefix, fn func(k netip.Prefix, v T) bool) { - c.treeForFamily(cidr).DescendantsShortestPrefixFirst(uint(cidr.Bits()), cidrKey(cidr), func(prefix uint, k Key[netip.Prefix], v T) bool { - return fn(k.Value(), v) + c.treeForFamily(cidr).DescendantsShortestPrefixFirst(uint(cidr.Bits()), cidrKey(cidr), func(prefix uint, k cidrKey, v T) bool { + return fn(netip.Prefix(k), v) }) } -func (c *CIDRTrie[T]) DescendantShortestPrefixFirstIterator(cidr netip.Prefix) Iterator[Key[netip.Prefix], T] { +func (c *CIDRTrie[T]) DescendantShortestPrefixFirstIterator(cidr netip.Prefix) descendantSPFIterator[cidrKey, T] { return c.treeForFamily(cidr).DescendantShortestPrefixFirstIterator(uint(cidr.Bits()), cidrKey(cidr)) } @@ -111,22 +111,22 @@ func (c *CIDRTrie[T]) Len() uint { // keys first. func (c *CIDRTrie[T]) ForEach(fn func(k netip.Prefix, v T) bool) { var v4Break bool - c.v4.ForEach(func(prefix uint, k Key[netip.Prefix], v T) bool { - if !fn(k.Value(), v) { + c.v4.ForEach(func(prefix uint, k cidrKey, v T) bool { + if !fn(netip.Prefix(k), v) { v4Break = true return false } return true }) if !v4Break { - c.v6.ForEach(func(prefix uint, k Key[netip.Prefix], v T) bool { - return fn(k.Value(), v) + c.v6.ForEach(func(prefix uint, k cidrKey, v T) bool { + return fn(netip.Prefix(k), v) }) } } -func (c *CIDRTrie[T]) treeForFamily(cidr netip.Prefix) Trie[Key[netip.Prefix], T] { +func (c *CIDRTrie[T]) treeForFamily(cidr netip.Prefix) Trie[cidrKey, T] { if cidr.Addr().Is6() { return c.v6 } @@ -135,10 +135,6 @@ func (c *CIDRTrie[T]) treeForFamily(cidr netip.Prefix) Trie[Key[netip.Prefix], T type cidrKey netip.Prefix -func (k cidrKey) Value() netip.Prefix { - return netip.Prefix(k) -} - func (k cidrKey) BitValueAt(idx uint) uint8 { addr := netip.Prefix(k).Addr() if addr.Is4() { @@ -154,9 +150,9 @@ func (k cidrKey) BitValueAt(idx uint) uint8 { } } -func (k cidrKey) CommonPrefix(k2 netip.Prefix) uint { +func (k cidrKey) CommonPrefix(k2 cidrKey) uint { addr1 := netip.Prefix(k).Addr() - addr2 := k2.Addr() + addr2 := netip.Prefix(k2).Addr() words1 := (*[2]uint64)(unsafe.Pointer(&addr1)) words2 := (*[2]uint64)(unsafe.Pointer(&addr2)) if addr1.Is4() { diff --git a/vendor/github.com/cilium/cilium/pkg/container/bitlpm/trie.go b/vendor/github.com/cilium/cilium/pkg/container/bitlpm/trie.go index d64c7f0e3b..eb46d8db44 100644 --- a/vendor/github.com/cilium/cilium/pkg/container/bitlpm/trie.go +++ b/vendor/github.com/cilium/cilium/pkg/container/bitlpm/trie.go @@ -16,6 +16,9 @@ import ( // minimum number of bits (from MSB to LSB) that another comparable key // must match. // +// 'K' must implement the Key[K] interface, and should be passed by value for optimum +// performance. If 'K' is a pointer type, its Key[K] methods must accept nil receivers. +// // Each method's comments describes the mechanism of how the method // works. // @@ -25,7 +28,7 @@ import ( // [most significant bit]: https://en.wikipedia.org/wiki/Bit_numbering#Most_significant_bit // [least significant bit]: https://en.wikipedia.org/wiki/Bit_numbering#Least_significant_bit // [longest prefix match algorithm]: https://en.wikipedia.org/wiki/Longest_prefix_match -type Trie[K, T any] interface { +type Trie[K Key[K], T any] interface { // ExactLookup returns a value only if the prefix and key // match an entry in the Trie exactly. // @@ -46,7 +49,7 @@ type Trie[K, T any] interface { Ancestors(prefix uint, key K, fn func(uint, K, T) bool) // AncestorIterator returns an iterator for ancestors that // can be used to produce the 'Next' key/value pair in sequence. - AncestorIterator(prefix uint, key K) Iterator[K, T] + AncestorIterator(prefix uint, key K) ancestorIterator[K, T] // AncestorsLongestPrefixFirst iterates over every prefix-key pair that // contains the prefix-key argument pair. If the function argument // returns false the iteration will stop. AncestorsLongestPrefixFirst @@ -56,7 +59,7 @@ type Trie[K, T any] interface { // AncestorLongestPrefixFirstIterator returns an iterator for ancestors // that can be used to produce the 'Next' key/value pair in sequence, // starting from the key with the longest common prefix with 'key'. - AncestorLongestPrefixFirstIterator(prefix uint, key K) Iterator[K, T] + AncestorLongestPrefixFirstIterator(prefix uint, key K) ancestorLPFIterator[K, T] // Descendants iterates over every prefix-key pair that is contained // by the prefix-key argument pair. If the function argument // returns false the iteration will stop. Descendants does **not** iterate @@ -67,7 +70,7 @@ type Trie[K, T any] interface { Descendants(prefix uint, key K, fn func(uint, K, T) bool) // DescendantIterator returns an iterator for descendants // that can be used to produce the 'Next' key/value pair in sequence. - DescendantIterator(prefix uint, key K) Iterator[K, T] + DescendantIterator(prefix uint, key K) descendantIterator[K, T] // DescendantsShortestPrefixFirst iterates over every prefix-key pair that is contained by // the prefix-key argument pair. If the function argument returns false the iteration will // stop. DescendantsShortestPrefixFirst iterates keys starting from shortest prefix, and @@ -77,7 +80,7 @@ type Trie[K, T any] interface { // DescendantShortestPrefixFirstIterator returns an iterator for descendants // that can be used to produce the 'Next' key/value pair in sequence, // starting from the key with the shortest common prefix with 'key'. - DescendantShortestPrefixFirstIterator(prefix uint, key K) Iterator[K, T] + DescendantShortestPrefixFirstIterator(prefix uint, key K) descendantSPFIterator[K, T] // Upsert updates or inserts the trie with a a prefix, key, // and value. The method returns true if the key is new, and // false if the key already existed. @@ -98,16 +101,6 @@ type Trie[K, T any] interface { ForEach(fn func(uint, K, T) bool) } -// Iterator is an interface that can be used to produce the next key/value pair in iteration -// sequence. 'ok' is 'false' when the sequence ends; 'key' and 'value' are returned with empty -// values in that case. -// Iteration state is held in the implementation explicitly, rather than in Go stack/closures. -// Policy mapstate generation benchmark BenchmarkRegenerateCIDRDenyPolicyRules reports 25% less allocations -// with Iterator, even in combination with Go 1.23 Iterators on the caller side. -type Iterator[K, T any] interface { - Next() (ok bool, key K, value T) -} - // Key is an interface that implements all the necessary // methods to index and retrieve keys. type Key[K any] interface { @@ -118,13 +111,11 @@ type Key[K any] interface { // BitValueAt returns the value of the bit at an argument // index. MSB is 0 and LSB is n-1. BitValueAt(uint) uint8 - // Value returns the underlying value of the Key. - Value() K } // trie is the generic implementation of a bit-trie that can -// accept arbitrary keys conforming to the Key[K] interface. -type trie[K, T any] struct { +// accept arbitrary keys conforming to the Key interface. +type trie[K Key[K], T any] struct { root *node[K, T] maxPrefix uint entries uint @@ -133,17 +124,17 @@ type trie[K, T any] struct { // NewTrie returns a Trie that accepts the Key[K any] interface // as its key argument. This enables the user of this Trie to // define their own bit-key. -func NewTrie[K, T any](maxPrefix uint) Trie[Key[K], T] { +func NewTrie[K Key[K], T any](maxPrefix uint) Trie[K, T] { return &trie[K, T]{ maxPrefix: maxPrefix, } } // node represents a specific key and prefix in the trie -type node[K, T any] struct { +type node[K Key[K], T any] struct { children [2]*node[K, T] prefixLen uint - key Key[K] + key K intermediate bool value T } @@ -153,7 +144,7 @@ type node[K, T any] struct { // // Note: If the prefix argument exceeds the Trie's maximum // prefix, it will be set to the Trie's maximum prefix. -func (t *trie[K, T]) ExactLookup(prefixLen uint, k Key[K]) (ret T, found bool) { +func (t *trie[K, T]) ExactLookup(prefixLen uint, k K) (ret T, found bool) { prefixLen = min(prefixLen, t.maxPrefix) t.traverse(prefixLen, k, func(currentNode *node[K, T]) bool { // Only copy node value if exact prefix length is found @@ -169,7 +160,7 @@ func (t *trie[K, T]) ExactLookup(prefixLen uint, k Key[K]) (ret T, found bool) { // LongestPrefixMatch returns the value for the key with the // longest prefix match of the argument key. -func (t *trie[K, T]) LongestPrefixMatch(k Key[K]) (key Key[K], value T, ok bool) { +func (t *trie[K, T]) LongestPrefixMatch(k K) (key K, value T, ok bool) { var lpmNode *node[K, T] t.traverse(t.maxPrefix, k, func(currentNode *node[K, T]) bool { lpmNode = currentNode @@ -188,7 +179,7 @@ func (t *trie[K, T]) LongestPrefixMatch(k Key[K]) (key Key[K], value T, ok bool) // Note: Ancestors sets any prefixLen argument that exceeds the maximum // prefix allowed by the trie to the maximum prefix allowed by the // trie. -func (t *trie[K, T]) Ancestors(prefixLen uint, k Key[K], fn func(prefix uint, key Key[K], value T) bool) { +func (t *trie[K, T]) Ancestors(prefixLen uint, k K, fn func(prefix uint, key K, value T) bool) { prefixLen = min(prefixLen, t.maxPrefix) t.traverse(prefixLen, k, func(currentNode *node[K, T]) bool { return fn(currentNode.prefixLen, currentNode.key, currentNode.value) @@ -196,29 +187,26 @@ func (t *trie[K, T]) Ancestors(prefixLen uint, k Key[K], fn func(prefix uint, ke } // ancestorIterator implements Iteraror for ancestor iteration -type ancestorIterator[K, T any] struct { - key Key[K] +type ancestorIterator[K Key[K], T any] struct { + key K prefixLen uint maxPrefix uint currentNode *node[K, T] } // AncestorIterator returns an iterator for ancestors. -func (t *trie[K, T]) AncestorIterator(prefixLen uint, k Key[K]) Iterator[Key[K], T] { - if k != nil { - return &ancestorIterator[K, T]{ - prefixLen: min(prefixLen, t.maxPrefix), - key: k, - maxPrefix: t.maxPrefix, - currentNode: t.root, - } +func (t *trie[K, T]) AncestorIterator(prefixLen uint, k K) ancestorIterator[K, T] { + return ancestorIterator[K, T]{ + prefixLen: min(prefixLen, t.maxPrefix), + key: k, + maxPrefix: t.maxPrefix, + currentNode: t.root, } - return &ancestorIterator[K, T]{} } // Next produces the 'Next' key/value pair in the iteration sequence maintained by 'iter'. 'ok' is // 'false' when the sequence ends; 'key' and 'value' are returned with empty values in that case. -func (i *ancestorIterator[K, T]) Next() (ok bool, key Key[K], value T) { +func (i *ancestorIterator[K, T]) Next() (ok bool, key K, value T) { for i.currentNode != nil { k := i.key prefixLen := i.prefixLen @@ -246,30 +234,28 @@ func (i *ancestorIterator[K, T]) Next() (ok bool, key Key[K], value T) { // ancestorLPFIterator implements Iteraror for ancestor iteration for longest-prefix-first iteration // order. -type ancestorLPFIterator[K, T any] struct { +type ancestorLPFIterator[K Key[K], T any] struct { stack nodes[K, T] } // AncestorLongestPrefixFirstIterator returns an iterator for ancestors // that can be used to produce the 'Next' key/value pair in sequence, // starting from the key with the longest common prefix with 'key'. -func (t *trie[K, T]) AncestorLongestPrefixFirstIterator(prefixLen uint, k Key[K]) Iterator[Key[K], T] { - iter := &ancestorLPFIterator[K, T]{} - if k != nil { - for currentNode := t.root; currentNode != nil; currentNode = currentNode.children[k.BitValueAt(currentNode.prefixLen)] { - matchLen := currentNode.prefixMatch(prefixLen, k) - // The current-node does not match. - if matchLen < currentNode.prefixLen { - break - } - // Skip over intermediate nodes - if currentNode.intermediate { - continue - } - iter.stack.push(currentNode) - if matchLen == t.maxPrefix { - break - } +func (t *trie[K, T]) AncestorLongestPrefixFirstIterator(prefixLen uint, k K) ancestorLPFIterator[K, T] { + iter := ancestorLPFIterator[K, T]{} + for currentNode := t.root; currentNode != nil; currentNode = currentNode.children[k.BitValueAt(currentNode.prefixLen)] { + matchLen := currentNode.prefixMatch(prefixLen, k) + // The current-node does not match. + if matchLen < currentNode.prefixLen { + break + } + // Skip over intermediate nodes + if currentNode.intermediate { + continue + } + iter.stack.push(currentNode) + if matchLen == t.maxPrefix { + break } } return iter @@ -277,7 +263,7 @@ func (t *trie[K, T]) AncestorLongestPrefixFirstIterator(prefixLen uint, k Key[K] // Next produces the 'Next' key/value pair in the iteration sequence maintained by 'iter'. 'ok' is // 'false' when the sequence ends; 'key' and 'value' are returned with empty values in that case. -func (i *ancestorLPFIterator[K, T]) Next() (ok bool, key Key[K], value T) { +func (i *ancestorLPFIterator[K, T]) Next() (ok bool, key K, value T) { if len(i.stack) > 0 { n := i.stack.pop() return true, n.key, n.value @@ -286,38 +272,36 @@ func (i *ancestorLPFIterator[K, T]) Next() (ok bool, key Key[K], value T) { } // descendantIterator implements Iteraror for descendants iteration -type descendantIterator[K, T any] struct { +type descendantIterator[K Key[K], T any] struct { nodes nodes[K, T] } // DescendantIterator returns an iterator for descendants // that can be used to produce the 'Next' key/value pair in sequence. -func (t *trie[K, T]) DescendantIterator(prefixLen uint, k Key[K]) Iterator[Key[K], T] { - iter := &descendantIterator[K, T]{} - if k != nil { - prefixLen = min(prefixLen, t.maxPrefix) - currentNode := t.root - for currentNode != nil { - matchLen := currentNode.prefixMatch(prefixLen, k) - // CurrentNode matches the prefix-key argument - if matchLen >= prefixLen { - iter.nodes.push(currentNode) - break - } - // currentNode is a leaf and has no children. Calling k.BitValueAt may - // overrun the key storage. - if currentNode.prefixLen >= t.maxPrefix { - break - } - currentNode = currentNode.children[k.BitValueAt(currentNode.prefixLen)] +func (t *trie[K, T]) DescendantIterator(prefixLen uint, k K) descendantIterator[K, T] { + iter := descendantIterator[K, T]{} + prefixLen = min(prefixLen, t.maxPrefix) + currentNode := t.root + for currentNode != nil { + matchLen := currentNode.prefixMatch(prefixLen, k) + // CurrentNode matches the prefix-key argument + if matchLen >= prefixLen { + iter.nodes.push(currentNode) + break + } + // currentNode is a leaf and has no children. Calling k.BitValueAt may + // overrun the key storage. + if currentNode.prefixLen >= t.maxPrefix { + break } + currentNode = currentNode.children[k.BitValueAt(currentNode.prefixLen)] } return iter } // Next produces the 'Next' key/value pair in the iteration sequence maintained by 'iter'. 'ok' is // 'false' when the sequence ends; 'key' and 'value' are returned with empty values in that case. -func (i *descendantIterator[K, T]) Next() (ok bool, key Key[K], value T) { +func (i *descendantIterator[K, T]) Next() (ok bool, key K, value T) { for len(i.nodes) > 0 { // pop the latest node n := i.nodes.pop() @@ -339,7 +323,7 @@ func (i *descendantIterator[K, T]) Next() (ok bool, key Key[K], value T) { // descendantSPFIterator implements Iteraror for descendants iteration for shortest-prefix-first // iteration order. -type descendantSPFIterator[K, T any] struct { +type descendantSPFIterator[K Key[K], T any] struct { heap nodes[K, T] } @@ -348,32 +332,30 @@ type descendantSPFIterator[K, T any] struct { // stop. DescendantsShortestPrefixFirst iterates keys starting from shortest prefix, and // progressing towards keys with longer prefixes. Keys with equal prefix lengths are not // iterated in any particular order. -func (t *trie[K, T]) DescendantShortestPrefixFirstIterator(prefixLen uint, k Key[K]) Iterator[Key[K], T] { - iter := &descendantSPFIterator[K, T]{} - if k != nil { - prefixLen = min(prefixLen, t.maxPrefix) - currentNode := t.root - for currentNode != nil { - matchLen := currentNode.prefixMatch(prefixLen, k) - // CurrentNode matches the prefix-key argument - if matchLen >= prefixLen { - iter.heap.push(currentNode) - break - } - // currentNode is a leaf and has no children. Calling k.BitValueAt may - // overrun the key storage. - if currentNode.prefixLen >= t.maxPrefix { - break - } - currentNode = currentNode.children[k.BitValueAt(currentNode.prefixLen)] +func (t *trie[K, T]) DescendantShortestPrefixFirstIterator(prefixLen uint, k K) descendantSPFIterator[K, T] { + iter := descendantSPFIterator[K, T]{} + prefixLen = min(prefixLen, t.maxPrefix) + currentNode := t.root + for currentNode != nil { + matchLen := currentNode.prefixMatch(prefixLen, k) + // CurrentNode matches the prefix-key argument + if matchLen >= prefixLen { + iter.heap.push(currentNode) + break } + // currentNode is a leaf and has no children. Calling k.BitValueAt may + // overrun the key storage. + if currentNode.prefixLen >= t.maxPrefix { + break + } + currentNode = currentNode.children[k.BitValueAt(currentNode.prefixLen)] } return iter } // Next produces the 'Next' key/value pair in the iteration sequence maintained by 'iter'. 'ok' is // 'false' when the sequence ends; 'key' and 'value' are returned with empty values in that case. -func (i *descendantSPFIterator[K, T]) Next() (ok bool, key Key[K], value T) { +func (i *descendantSPFIterator[K, T]) Next() (ok bool, key K, value T) { for i.heap.Len() > 0 { // pop the node with the lowest prefix length from the heap n := i.heap.popHeap() @@ -393,7 +375,7 @@ func (i *descendantSPFIterator[K, T]) Next() (ok bool, key Key[K], value T) { return false, key, value } -func (t *trie[K, T]) AncestorsLongestPrefixFirst(prefixLen uint, k Key[K], fn func(prefix uint, key Key[K], value T) bool) { +func (t *trie[K, T]) AncestorsLongestPrefixFirst(prefixLen uint, k K, fn func(prefix uint, key K, value T) bool) { prefixLen = min(prefixLen, t.maxPrefix) t.treverse(prefixLen, k, func(currentNode *node[K, T]) bool { return fn(currentNode.prefixLen, currentNode.key, currentNode.value) @@ -408,10 +390,7 @@ func (t *trie[K, T]) AncestorsLongestPrefixFirst(prefixLen uint, k Key[K], fn fu // Note: Descendants sets any prefixLen argument that exceeds the maximum // prefix allowed by the trie to the maximum prefix allowed by the // trie. -func (t *trie[K, T]) Descendants(prefixLen uint, k Key[K], fn func(prefix uint, key Key[K], value T) bool) { - if k == nil { - return - } +func (t *trie[K, T]) Descendants(prefixLen uint, k K, fn func(prefix uint, key K, value T) bool) { prefixLen = min(prefixLen, t.maxPrefix) currentNode := t.root for currentNode != nil { @@ -439,10 +418,7 @@ func (t *trie[K, T]) Descendants(prefixLen uint, k Key[K], fn func(prefix uint, // Note: Descendants sets any prefixLen argument that exceeds the maximum // prefix allowed by the trie to the maximum prefix allowed by the // trie. -func (t *trie[K, T]) DescendantsShortestPrefixFirst(prefixLen uint, k Key[K], fn func(prefix uint, key Key[K], value T) bool) { - if k == nil { - return - } +func (t *trie[K, T]) DescendantsShortestPrefixFirst(prefixLen uint, k K, fn func(prefix uint, key K, value T) bool) { prefixLen = min(prefixLen, t.maxPrefix) currentNode := t.root for currentNode != nil { @@ -483,10 +459,7 @@ func (t *trie[K, T]) DescendantsShortestPrefixFirst(prefixLen uint, k Key[K], fn // determine which children of the current node to traverse (to // check if there is a more specific match). If there is no child then // traversal ends. Otherwise traversal continues. -func (t *trie[K, T]) traverse(prefixLen uint, k Key[K], fn func(currentNode *node[K, T]) bool) { - if k == nil { - return - } +func (t *trie[K, T]) traverse(prefixLen uint, k K, fn func(currentNode *node[K, T]) bool) { for currentNode := t.root; currentNode != nil; currentNode = currentNode.children[k.BitValueAt(currentNode.prefixLen)] { matchLen := currentNode.prefixMatch(prefixLen, k) // The current-node does not match. @@ -509,11 +482,7 @@ func (t *trie[K, T]) traverse(prefixLen uint, k Key[K], fn func(currentNode *nod const nPointersOnCacheline = 8 // treverse is like traverse, but it calls 'fn' in reverse order, starting from the most specific match -func (t *trie[K, T]) treverse(prefixLen uint, k Key[K], fn func(currentNode *node[K, T]) bool) { - if k == nil { - return - } - +func (t *trie[K, T]) treverse(prefixLen uint, k K, fn func(currentNode *node[K, T]) bool) { // stack is used to reverse the order in which nodes are visited. // Preallocate space for some pointers to reduce allocations and copies. stack := make([]*node[K, T], 0, nPointersOnCacheline) @@ -602,10 +571,7 @@ func (t *trie[K, T]) treverse(prefixLen uint, k Key[K], fn func(currentNode *nod // Note: Upsert sets any "prefixLen" argument that exceeds the maximum // prefix allowed by the trie to the maximum prefix allowed by the // trie. -func (t *trie[K, T]) Upsert(prefixLen uint, k Key[K], value T) bool { - if k == nil { - return false - } +func (t *trie[K, T]) Upsert(prefixLen uint, k K, value T) bool { prefixLen = min(prefixLen, t.maxPrefix) upsertNode := &node[K, T]{ prefixLen: prefixLen, @@ -738,10 +704,7 @@ func (t *trie[K, T]) Upsert(prefixLen uint, k Key[K], value T) bool { // Note: Delete sets any prefixLen argument that exceeds the maximum // prefix allowed by the trie to the maximum prefix allowed by the // trie. -func (t *trie[K, T]) Delete(prefixLen uint, k Key[K]) bool { - if k == nil { - return false - } +func (t *trie[K, T]) Delete(prefixLen uint, k K) bool { prefixLen = min(prefixLen, t.maxPrefix) var ( @@ -836,7 +799,7 @@ func (t *trie[K, T]) Len() uint { return t.entries } -func (t *trie[K, T]) ForEach(fn func(prefix uint, key Key[K], value T) bool) { +func (t *trie[K, T]) ForEach(fn func(prefix uint, key K, value T) bool) { if t.root != nil { t.root.forEach(fn) } @@ -845,9 +808,9 @@ func (t *trie[K, T]) ForEach(fn func(prefix uint, key Key[K], value T) bool) { // prefixMatch returns the length that the node key and // the argument key match, with the limit of the match being // the lesser of the node-key prefix or the argument-key prefix. -func (n *node[K, T]) prefixMatch(prefix uint, k Key[K]) uint { +func (n *node[K, T]) prefixMatch(prefix uint, k K) uint { limit := min(n.prefixLen, prefix) - prefixLen := n.key.CommonPrefix(k.Value()) + prefixLen := n.key.CommonPrefix(k) if prefixLen >= limit { return limit } @@ -856,7 +819,7 @@ func (n *node[K, T]) prefixMatch(prefix uint, k Key[K]) uint { // forEach calls the argument function for each key and value in // the subtree rooted at the current node, iterating recursively in depth-first manner. -func (n *node[K, T]) forEach(fn func(prefix uint, key Key[K], value T) bool) { +func (n *node[K, T]) forEach(fn func(prefix uint, key K, value T) bool) { if !n.intermediate { if !fn(n.prefixLen, n.key, n.value) { return @@ -871,7 +834,7 @@ func (n *node[K, T]) forEach(fn func(prefix uint, key Key[K], value T) bool) { } // nodes implements container/heap for trie nodes -type nodes[K, T any] []*node[K, T] +type nodes[K Key[K], T any] []*node[K, T] // container/heap interface functions func (nodes nodes[K, T]) Len() int { return len(nodes) } @@ -924,7 +887,7 @@ func (nodes *nodes[K, T]) popHeap() *node[K, T] { // the node with the shortest prefix of the subtree it represents. To iterate in the order // of increasing prefix lengths, on each round we pop the node with the shortest prefix from the // heap, visit it, and push its children into the heap. -func (n *node[K, T]) forEachShortestPrefixFirst(fn func(prefix uint, key Key[K], value T) bool) { +func (n *node[K, T]) forEachShortestPrefixFirst(fn func(prefix uint, key K, value T) bool) { // nodes is a heap used to track the heads of each unvisited subtree. Each node in the heap // has the shortest prefix length of any node in the subtree it represents. // Preallocate space for some pointers to reduce allocations and copies. diff --git a/vendor/github.com/cilium/cilium/pkg/container/bitlpm/unsigned.go b/vendor/github.com/cilium/cilium/pkg/container/bitlpm/unsigned.go index 37795cc8e0..2d771b09e8 100644 --- a/vendor/github.com/cilium/cilium/pkg/container/bitlpm/unsigned.go +++ b/vendor/github.com/cilium/cilium/pkg/container/bitlpm/unsigned.go @@ -4,7 +4,6 @@ package bitlpm import ( - "fmt" "math/bits" "unsafe" ) @@ -18,7 +17,7 @@ type Unsigned interface { // UintTrie uses all unsigned integer types // except for uintptr and uint. type UintTrie[K Unsigned, V any] struct { - trie Trie[Key[K], V] + trie Trie[unsignedKey[K], V] keySize uint } @@ -28,55 +27,41 @@ func NewUintTrie[K Unsigned, T any]() *UintTrie[K, T] { var k K size := uint(unsafe.Sizeof(k)) return &UintTrie[K, T]{ - trie: NewTrie[K, T](size * 8), + trie: NewTrie[unsignedKey[K], T](size * 8), keySize: size, } } -func (tu *UintTrie[K, T]) getKey(k K) Key[K] { - switch tu.keySize { - case 1: - return unsignedKey8[K](k) - case 2: - return unsignedKey16[K](k) - case 4: - return unsignedKey32[K](k) - case 8: - return unsignedKey64[K](k) - } - panic(fmt.Sprintf("unexpected key size of %d", unsafe.Sizeof(k))) -} - func (ut *UintTrie[K, T]) Upsert(prefix uint, k K, value T) bool { - return ut.trie.Upsert(prefix, ut.getKey(k), value) + return ut.trie.Upsert(prefix, unsignedKey[K]{value: k}, value) } func (ut *UintTrie[K, T]) Delete(prefix uint, k K) bool { - return ut.trie.Delete(prefix, ut.getKey(k)) + return ut.trie.Delete(prefix, unsignedKey[K]{value: k}) } func (ut *UintTrie[K, T]) ExactLookup(prefix uint, k K) (T, bool) { - return ut.trie.ExactLookup(prefix, ut.getKey(k)) + return ut.trie.ExactLookup(prefix, unsignedKey[K]{value: k}) } func (ut *UintTrie[K, T]) LongestPrefixMatch(k K) (K, T, bool) { - k2, v, ok := ut.trie.LongestPrefixMatch(ut.getKey(k)) + k2, v, ok := ut.trie.LongestPrefixMatch(unsignedKey[K]{value: k}) if ok { - return k2.Value(), v, ok + return k2.value, v, ok } var empty K return empty, v, ok } func (ut *UintTrie[K, T]) Ancestors(prefix uint, k K, fn func(prefix uint, key K, value T) bool) { - ut.trie.Ancestors(prefix, ut.getKey(k), func(prefix uint, k Key[K], v T) bool { - return fn(prefix, k.Value(), v) + ut.trie.Ancestors(prefix, unsignedKey[K]{value: k}, func(prefix uint, k unsignedKey[K], v T) bool { + return fn(prefix, k.value, v) }) } func (ut *UintTrie[K, T]) Descendants(prefix uint, k K, fn func(prefix uint, key K, value T) bool) { - ut.trie.Descendants(prefix, ut.getKey(k), func(prefix uint, k Key[K], v T) bool { - return fn(prefix, k.Value(), v) + ut.trie.Descendants(prefix, unsignedKey[K]{value: k}, func(prefix uint, k unsignedKey[K], v T) bool { + return fn(prefix, k.value, v) }) } @@ -85,75 +70,47 @@ func (ut *UintTrie[K, T]) Len() uint { } func (ut *UintTrie[K, T]) ForEach(fn func(prefix uint, key K, value T) bool) { - ut.trie.ForEach(func(prefix uint, k Key[K], v T) bool { - return fn(prefix, k.Value(), v) + ut.trie.ForEach(func(prefix uint, k unsignedKey[K], v T) bool { + return fn(prefix, k.value, v) }) } -type unsignedKey8[U Unsigned] uint8 - -func (u unsignedKey8[U]) CommonPrefix(v U) uint { - return uint(bits.LeadingZeros8(uint8(U(u) ^ v))) -} - -func (u unsignedKey8[U]) BitValueAt(i uint) uint8 { - if u&(1<<(7-i)) == 0 { - return 0 - } - return 1 -} - -func (u unsignedKey8[U]) Value() U { - return U(u) -} - -type unsignedKey16[U Unsigned] uint16 - -func (u unsignedKey16[U]) CommonPrefix(v U) uint { - return uint(bits.LeadingZeros16(uint16(u) ^ uint16(v))) -} - -func (u unsignedKey16[U]) BitValueAt(i uint) uint8 { - if u&(1<<(15-i)) == 0 { - return 0 - } - return 1 -} - -func (u unsignedKey16[U]) Value() U { - return U(u) -} - -type unsignedKey32[U Unsigned] uint32 - -func (u unsignedKey32[U]) CommonPrefix(v U) uint { - return uint(bits.LeadingZeros32(uint32(u) ^ uint32(v))) +type unsignedKey[U Unsigned] struct { + value U } -func (u unsignedKey32[U]) BitValueAt(i uint) uint8 { - if u&(1<<(31-i)) == 0 { - return 0 +func (u unsignedKey[U]) CommonPrefix(v unsignedKey[U]) uint { + switch any(u.value).(type) { + case uint8: + return uint(bits.LeadingZeros8(uint8(u.value ^ v.value))) + case uint16: + return uint(bits.LeadingZeros16(uint16(u.value ^ v.value))) + case uint32: + return uint(bits.LeadingZeros32(uint32(u.value ^ v.value))) + case uint64: + return uint(bits.LeadingZeros64(uint64(u.value ^ v.value))) } - return 1 -} - -func (u unsignedKey32[U]) Value() U { - return U(u) -} - -type unsignedKey64[U Unsigned] uint64 - -func (u unsignedKey64[U]) CommonPrefix(v U) uint { - return uint(bits.LeadingZeros64(uint64(u) ^ uint64(v))) -} - -func (u unsignedKey64[U]) BitValueAt(i uint) uint8 { - if u&(1<<(63-i)) == 0 { - return 0 + return 0 +} + +func (u unsignedKey[U]) BitValueAt(i uint) uint8 { + switch any(u.value).(type) { + case uint8: + if u.value&(1<<(7-i)) == 0 { + return 0 + } + case uint16: + if u.value&(1<<(15-i)) == 0 { + return 0 + } + case uint32: + if u.value&(1<<(31-i)) == 0 { + return 0 + } + case uint64: + if u.value&(1<<(63-i)) == 0 { + return 0 + } } return 1 } - -func (u unsignedKey64[U]) Value() U { - return U(u) -} diff --git a/vendor/github.com/cilium/cilium/pkg/container/versioned/value.go b/vendor/github.com/cilium/cilium/pkg/container/versioned/value.go index 29c4bfe9e9..79aa63e3f3 100644 --- a/vendor/github.com/cilium/cilium/pkg/container/versioned/value.go +++ b/vendor/github.com/cilium/cilium/pkg/container/versioned/value.go @@ -18,6 +18,7 @@ import ( "github.com/cilium/cilium/pkg/lock" "github.com/cilium/cilium/pkg/logging/logfields" + "github.com/cilium/cilium/pkg/option" ) type version uint64 @@ -53,6 +54,8 @@ type VersionHandle struct { // Coordinator of this versionHandle, if any. Used for closing if non-nil. // Atomic due to nilling and for copy prevention. coordinator atomic.Pointer[Coordinator] + // Optional stack trace of the caller for debugging purposes + stacktrace hclog.CapturedStacktrace } func (h *VersionHandle) IsValid() bool { @@ -98,7 +101,11 @@ func (h *VersionHandle) Close() error { func versionHandleFinalizer(h *VersionHandle) { coordinator := h.coordinator.Load() if coordinator != nil && coordinator.Logger != nil { - coordinator.Logger.WithField(logfields.Version, h.version).Error("Handle for version not closed.") + logger := coordinator.Logger + if h.stacktrace != "" { + logger = logger.WithField(logfields.Stacktrace, h.stacktrace) + } + logger.WithField(logfields.Version, h.version).Error("Handle for version not closed.") } h.Close() } @@ -114,6 +121,11 @@ func newVersionHandle(version version, coordinator *Coordinator) *VersionHandle // Set a finalizer to catch unclosed handles. The finalizer function complains // loudly, so that we do not rely the finalizer for closing. runtime.SetFinalizer(h, versionHandleFinalizer) + + if option.Config.Debug { + // capture a stacktrace for debugging + h.stacktrace = hclog.Stacktrace() + } } return h } diff --git a/vendor/github.com/cilium/cilium/pkg/crypto/certificatemanager/certificate_manager.go b/vendor/github.com/cilium/cilium/pkg/crypto/certificatemanager/certificate_manager.go index 3750dc9f11..779b1e2312 100644 --- a/vendor/github.com/cilium/cilium/pkg/crypto/certificatemanager/certificate_manager.go +++ b/vendor/github.com/cilium/cilium/pkg/crypto/certificatemanager/certificate_manager.go @@ -33,6 +33,7 @@ type CertificateManager interface { type SecretManager interface { GetSecretString(ctx context.Context, secret *api.Secret, ns string) (string, error) PolicySecretSyncEnabled() bool + SecretsOnlyFromSecretsNamespace() bool GetSecretSyncNamespace() string } @@ -47,34 +48,39 @@ type managerConfig struct { EnablePolicySecretsSync bool PolicySecretsNamespace string + + PolicySecretsOnlyFromSecretsNamespace bool } func (mc managerConfig) Flags(flags *pflag.FlagSet) { flags.String("certificates-directory", mc.CertificatesDirectory, "Root directory to find certificates specified in L7 TLS policy enforcement") flags.Bool("enable-policy-secrets-sync", mc.EnablePolicySecretsSync, "Enables Envoy secret sync for Secrets used in CiliumNetworkPolicy and CiliumClusterwideNetworkPolicy") + flags.Bool("policy-secrets-only-from-secrets-namespace", mc.PolicySecretsOnlyFromSecretsNamespace, "Configures the agent to only read policy Secrets from the policy-secrets-namespace") flags.String("policy-secrets-namespace", mc.PolicySecretsNamespace, "PolicySecretsNamesapce is the namespace having secrets used in CNP and CCNP") } // Manager will manage the way certificates are retrieved based in the given // k8sClient and rootPath. type manager struct { - rootPath string - k8sClient k8sClient.Clientset - secretSyncNamespace string - secretSyncEnabled bool - Logger logrus.FieldLogger + rootPath string + k8sClient k8sClient.Clientset + secretSyncNamespace string + secretSyncEnabled bool + secretsFromSecretSyncNamespace bool + Logger logrus.FieldLogger } // NewManager returns a new manager. func NewManager(cfg managerConfig, clientset k8sClient.Clientset, logger logrus.FieldLogger) (CertificateManager, SecretManager) { m := &manager{ - rootPath: cfg.CertificatesDirectory, - k8sClient: clientset, - Logger: logger, - secretSyncEnabled: cfg.EnablePolicySecretsSync, + rootPath: cfg.CertificatesDirectory, + k8sClient: clientset, + Logger: logger, + secretSyncEnabled: cfg.EnablePolicySecretsSync, + secretsFromSecretSyncNamespace: cfg.PolicySecretsOnlyFromSecretsNamespace, } - if cfg.EnablePolicySecretsSync { + if cfg.PolicySecretsOnlyFromSecretsNamespace { m.secretSyncNamespace = cfg.PolicySecretsNamespace } @@ -95,6 +101,10 @@ func (m *manager) PolicySecretSyncEnabled() bool { return m.secretSyncEnabled } +func (m *manager) SecretsOnlyFromSecretsNamespace() bool { + return m.secretsFromSecretSyncNamespace +} + // getSecrets returns either local or k8s secrets, giving precedence for local secrets if configured. // It also returns a boolean indicating if the values were read from disk or not. // The 'ns' parameter is used as the secret namespace if 'secret.Namespace' is an empty string, and is @@ -137,23 +147,25 @@ func (m *manager) getSecrets(ctx context.Context, secret *api.Secret, ns string) return nsName, secrets, true, nil } - // If there's no secret synchronization namespace configured, then we need to read values + if m.secretSyncEnabled && m.secretSyncNamespace != "" { + // If we get here, then the secret is _not_ being read from the filesystem, + // and secret sync is enabled, so we are sending via SDS, + // and then we don't want to inspect the Secret at all, because + // that will require the agent to have more access than it needs. So we return an empty `secrets` map. + // TODO(youngnick): Deprecate and remove reading from file for secrets. + emptySecrets := make(map[string][]byte) + return nsName, emptySecrets, false, nil + } + + // If secret synchronization is disabled, then we need to read values // directly from Kubernetes. Not a good idea, for security or performance reasons, but included // for backwards compatibility. // TODO(youngnick): Once we are comfortable with SDS stability, remove this and pass the // reference to the original secret instead. (This will require changes to the secretsync // package so that it can register specific secrets from anywhere.) - if m.secretSyncNamespace == "" { - secrets, err := m.k8sClient.GetSecrets(ctx, ns, secret.Name) - return nsName, secrets, true, err - } - // If the secret is _not_ being read from the filesystem, then we don't want to inspect it at all, because - // that will require the agent to have more access than it needs. So we return an empty `secrets` map. - // The plan here is to deprecate reading from file entirely, at which all this code will be removed. - // TODO(youngnick): Deprecate and remove reading from file for secrets. - emptySecrets := make(map[string][]byte) - return nsName, emptySecrets, false, nil + secrets, err := m.k8sClient.GetSecrets(ctx, ns, secret.Name) + return nsName, secrets, true, err } const ( diff --git a/vendor/github.com/cilium/cilium/pkg/defaults/defaults.go b/vendor/github.com/cilium/cilium/pkg/defaults/defaults.go index 06b0fab602..37b52e9c16 100644 --- a/vendor/github.com/cilium/cilium/pkg/defaults/defaults.go +++ b/vendor/github.com/cilium/cilium/pkg/defaults/defaults.go @@ -17,6 +17,9 @@ const ( // ClusterMeshHealthPort is the default value for option.ClusterMeshHealthPort ClusterMeshHealthPort = 80 + // EnableGops is the default value for option.EnableGops + EnableGops = true + // GopsPortAgent is the default value for option.GopsPort in the agent GopsPortAgent = 9890 @@ -109,7 +112,7 @@ const ( // for each FQDN selector in endpoint's restored DNS rules. DNSMaxIPsPerRestoredRule = 1000 - // FFQDNRegexCompileLRUSize defines the maximum size for the FQDN regex + // FQDNRegexCompileLRUSize defines the maximum size for the FQDN regex // compilation LRU used by the DNS proxy and policy validation. FQDNRegexCompileLRUSize = 1024 @@ -453,15 +456,11 @@ const ( // RestoreV6Addr is used as match for cilium_host v6 (router) address RestoreV6Addr = "cilium.v6.internal.raw " - // EnableWellKnownIdentities is enabled by default as this is the - // original behavior. New default Helm templates will disable this. - EnableWellKnownIdentities = true - // CertsDirectory is the default directory used to find certificates // specified in the L7 policies. CertsDirectory = RuntimePath + "/certs" - // IPAMExpiration is the timeout after which an IP subject to expiratio + // IPAMExpiration is the timeout after which an IP subject to expiration // is being released again if no endpoint is being created in time. IPAMExpiration = 10 * time.Minute @@ -481,11 +480,6 @@ const ( // for local traffic EnableIdentityMark = true - // EnableHighScaleIPcache enables the special ipcache mode for high scale - // clusters. The ipcache content will be reduced to the strict minimum and - // traffic will be encapsulated to carry security identities. - EnableHighScaleIPcache = false - // K8sEnableLeasesFallbackDiscovery enables k8s to fallback to API probing to check // for the support of Leases in Kubernetes when there is an error in discovering // API groups using Discovery API. @@ -584,6 +578,9 @@ const ( // BGPRouterIDAllocationMode is default BGP router-id allocation mode BGPRouterIDAllocationMode = "default" + + // WireguardTrackAllIPsFallback forces the WireGuard agent to track all IPs. + WireguardTrackAllIPsFallback = false ) var ( diff --git a/vendor/github.com/cilium/cilium/pkg/fqdn/matchpattern/matchpattern.go b/vendor/github.com/cilium/cilium/pkg/fqdn/matchpattern/matchpattern.go index 68e083175d..04a7b0998d 100644 --- a/vendor/github.com/cilium/cilium/pkg/fqdn/matchpattern/matchpattern.go +++ b/vendor/github.com/cilium/cilium/pkg/fqdn/matchpattern/matchpattern.go @@ -23,7 +23,7 @@ const MatchAllAnchoredPattern = "(?:)" // it can be or-ed (joined with "|") with other rules, and still match all rules. const MatchAllUnAnchoredPattern = ".*" -// Validate ensures that pattern is a parseable matchPattern. It returns the +// Validate ensures that pattern is a parsable matchPattern. It returns the // regexp generated when validating. func Validate(pattern string) (matcher *regexp.Regexp, err error) { if err := prevalidate(pattern); err != nil { diff --git a/vendor/github.com/cilium/cilium/pkg/hive/hive.go b/vendor/github.com/cilium/cilium/pkg/hive/hive.go index 82397c860d..7afee7d1ea 100644 --- a/vendor/github.com/cilium/cilium/pkg/hive/hive.go +++ b/vendor/github.com/cilium/cilium/pkg/hive/hive.go @@ -16,11 +16,9 @@ import ( "github.com/cilium/statedb" "github.com/sirupsen/logrus" - flowpb "github.com/cilium/cilium/api/v1/flow" "github.com/cilium/cilium/pkg/cidr" "github.com/cilium/cilium/pkg/hive/health" "github.com/cilium/cilium/pkg/hive/health/types" - "github.com/cilium/cilium/pkg/hubble" "github.com/cilium/cilium/pkg/logging" "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/metrics" @@ -114,20 +112,6 @@ var decodeHooks = cell.DecodeHooks{ } return cidr.ParseCIDR(s) }, - // Decode JSON encoded *flowpb.FlowFilter fields - func(from reflect.Type, to reflect.Type, data interface{}) (interface{}, error) { - if from.Kind() != reflect.Slice { - return data, nil - } - xs, ok := data.([]string) - if !ok { - return data, nil - } - if to != reflect.TypeOf(([]*flowpb.FlowFilter)(nil)) { - return data, nil - } - return hubble.ParseFlowFilters(xs...) - }, } func AddConfigOverride[Cfg cell.Flagger](h *Hive, override func(*Cfg)) { diff --git a/vendor/github.com/cilium/cilium/pkg/hubble/helpers.go b/vendor/github.com/cilium/cilium/pkg/hubble/helpers.go deleted file mode 100644 index 69f7fa4279..0000000000 --- a/vendor/github.com/cilium/cilium/pkg/hubble/helpers.go +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Authors of Cilium - -package hubble - -import ( - "encoding/json" - "fmt" - "strings" - - flowpb "github.com/cilium/cilium/api/v1/flow" -) - -func ParseFlowFilters(args ...string) ([]*flowpb.FlowFilter, error) { - filters := make([]*flowpb.FlowFilter, 0, len(args)) - for _, enc := range args { - dec := json.NewDecoder(strings.NewReader(enc)) - var filter flowpb.FlowFilter - if err := dec.Decode(&filter); err != nil { - return nil, fmt.Errorf("failed to decode flow filter '%v': %w", enc, err) - } - filters = append(filters, &filter) - } - return filters, nil -} diff --git a/vendor/github.com/cilium/cilium/pkg/identity/identity.go b/vendor/github.com/cilium/cilium/pkg/identity/identity.go index d55de2cac2..39e0375fd9 100644 --- a/vendor/github.com/cilium/cilium/pkg/identity/identity.go +++ b/vendor/github.com/cilium/cilium/pkg/identity/identity.go @@ -326,5 +326,5 @@ func IdentityAllocationIsLocal(lbls labels.Labels) bool { // UpdateIdentities is an interface to be called when identities change type UpdateIdentities interface { - UpdateIdentities(added, deleted IdentityMap, wg *sync.WaitGroup) + UpdateIdentities(added, deleted IdentityMap, wg *sync.WaitGroup) (mutated bool) } diff --git a/vendor/github.com/cilium/cilium/pkg/ipcache/types/types.go b/vendor/github.com/cilium/cilium/pkg/ipcache/types/types.go index ee19ffb904..988dcf662a 100644 --- a/vendor/github.com/cilium/cilium/pkg/ipcache/types/types.go +++ b/vendor/github.com/cilium/cilium/pkg/ipcache/types/types.go @@ -17,7 +17,13 @@ import ( // PolicyHandler is responsible for handling identity updates into the core // policy engine. See SelectorCache.UpdateIdentities() for more details. type PolicyHandler interface { - UpdateIdentities(added, deleted identity.IdentityMap, wg *sync.WaitGroup) + UpdateIdentities(added, deleted identity.IdentityMap, wg *sync.WaitGroup) (mutated bool) +} + +// PolicyUpdater is responsible for triggering regeneration of all endpoints. +// See pkg/policy/trigger.go for more details. +type PolicyUpdater interface { + TriggerPolicyUpdates(reason string) } // DatapathHandler is responsible for ensuring that policy updates in the diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/ccnp_types.go b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/ccnp_types.go index 36f8e62820..dd563f079f 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/ccnp_types.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/ccnp_types.go @@ -5,7 +5,6 @@ package v2 import ( "fmt" - "reflect" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -62,16 +61,6 @@ func (r *CiliumClusterwideNetworkPolicy) SetDerivedPolicyStatus(derivativePolicy r.Status.DerivativePolicies[derivativePolicyName] = status } -// AnnotationsEquals returns true if ObjectMeta.Annotations of each -// CiliumClusterwideNetworkPolicy are equivalent (i.e., they contain equivalent key-value -// pairs). -func (r *CiliumClusterwideNetworkPolicy) AnnotationsEquals(o *CiliumClusterwideNetworkPolicy) bool { - if o == nil { - return r == nil - } - return reflect.DeepEqual(r.ObjectMeta.Annotations, o.ObjectMeta.Annotations) -} - // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // +k8s:openapi-gen=false // +deepequal-gen=false diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/cnp_types.go b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/cnp_types.go index a3210aff37..27c2667f36 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/cnp_types.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/cnp_types.go @@ -5,7 +5,6 @@ package v2 import ( "fmt" - "reflect" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -158,16 +157,6 @@ func (r *CiliumNetworkPolicy) SetDerivedPolicyStatus(derivativePolicyName string r.Status.DerivativePolicies[derivativePolicyName] = status } -// AnnotationsEquals returns true if ObjectMeta.Annotations of each -// CiliumNetworkPolicy are equivalent (i.e., they contain equivalent key-value -// pairs). -func (r *CiliumNetworkPolicy) AnnotationsEquals(o *CiliumNetworkPolicy) bool { - if o == nil { - return r == nil - } - return reflect.DeepEqual(r.ObjectMeta.Annotations, o.ObjectMeta.Annotations) -} - // Parse parses a CiliumNetworkPolicy and returns a list of cilium policy // rules. func (r *CiliumNetworkPolicy) Parse() (api.Rules, error) { diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/service.go b/vendor/github.com/cilium/cilium/pkg/k8s/service.go index 1b3f876668..735ba166f4 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/service.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/service.go @@ -79,14 +79,18 @@ func getAnnotationServiceForwardingMode(svc *slim_corev1.Service) (loadbalancer. } func getAnnotationServiceLoadBalancingAlgorithm(svc *slim_corev1.Service) (loadbalancer.SVCLoadBalancingAlgorithm, error) { - if value, ok := annotation.Get(svc, annotation.ServiceLoadBalancingAlgorithm); ok { + return GetAnnotationServiceLoadBalancingAlgorithm(svc.Annotations, loadbalancer.ToSVCLoadBalancingAlgorithm(option.Config.NodePortAlg)) +} + +func GetAnnotationServiceLoadBalancingAlgorithm(ann map[string]string, defaultAlg loadbalancer.SVCLoadBalancingAlgorithm) (loadbalancer.SVCLoadBalancingAlgorithm, error) { + if value, ok := ann[annotation.ServiceLoadBalancingAlgorithm]; ok { val := loadbalancer.ToSVCLoadBalancingAlgorithm(strings.ToLower(value)) if val != loadbalancer.SVCLoadBalancingAlgorithmUndef { return val, nil } - return loadbalancer.ToSVCLoadBalancingAlgorithm(option.Config.NodePortAlg), fmt.Errorf("Value %q is not supported for %q", val, annotation.ServiceLoadBalancingAlgorithm) + return defaultAlg, fmt.Errorf("Value %q is not supported for %q", val, annotation.ServiceLoadBalancingAlgorithm) } - return loadbalancer.ToSVCLoadBalancingAlgorithm(option.Config.NodePortAlg), nil + return defaultAlg, nil } func getTopologyAware(svc *slim_corev1.Service) bool { diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/service_cache.go b/vendor/github.com/cilium/cilium/pkg/k8s/service_cache.go index 3c19338a8c..b8236fb69a 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/service_cache.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/service_cache.go @@ -413,11 +413,11 @@ func (s *ServiceCache) DeleteService(k8sSvc *slim_corev1.Service, swg *lock.Stop if serviceOK { s.metrics.DelService(oldService) s.emitEvent(ServiceEvent{ - Action: DeleteService, - ID: svcID, - OldService: oldService, - OldEndpoints: endpoints, - SWGDone: swg.Add(), + Action: DeleteService, + ID: svcID, + Service: oldService, + Endpoints: endpoints, + SWGDone: swg.Add(), }) } } @@ -808,7 +808,6 @@ func (s *ServiceCache) mergeExternalServiceDeleteLocked(service *serviceStore.Cl Action: UpdateService, ID: id, Service: svc, - OldService: svc, Endpoints: endpoints, OldEndpoints: oldEPs, SWGDone: swg.Add(), @@ -817,8 +816,6 @@ func (s *ServiceCache) mergeExternalServiceDeleteLocked(service *serviceStore.Cl if !serviceReady { delete(s.services, id) event.Action = DeleteService - event.Service = nil - event.Endpoints = nil } s.emitEvent(event) @@ -874,11 +871,11 @@ func (s *ServiceCache) MergeClusterServiceDelete(service *serviceStore.ClusterSe if ok { s.emitEvent(ServiceEvent{ - Action: DeleteService, - ID: id, - OldService: svc, - OldEndpoints: endpoints, - SWGDone: swg.Add(), + Action: DeleteService, + ID: id, + Service: svc, + Endpoints: endpoints, + SWGDone: swg.Add(), }) } } diff --git a/vendor/github.com/cilium/cilium/pkg/labels/array.go b/vendor/github.com/cilium/cilium/pkg/labels/array.go index e13b055d73..dfffb11f15 100644 --- a/vendor/github.com/cilium/cilium/pkg/labels/array.go +++ b/vendor/github.com/cilium/cilium/pkg/labels/array.go @@ -4,6 +4,7 @@ package labels import ( + "bytes" "sort" "strings" ) @@ -197,19 +198,50 @@ func (ls LabelArray) GetModel() []string { return res } -func (ls LabelArray) String() string { - var sb strings.Builder +func LabelArrayFromString(str string) LabelArray { + // each LabelArray starts with '[' and ends with ']' + if len(str) > 2 && str[0] == '[' && str[len(str)-1] == ']' { + str = str[1 : len(str)-1] // remove brackets + labels := strings.Split(str, " ") + la := make(LabelArray, 0, len(labels)) + for j := range labels { + la = append(la, ParseLabel(labels[j])) + } + if len(la) > 0 { + return la + } + } + return nil +} + +func (ls LabelArray) BuildString(sb *strings.Builder) { sb.WriteString("[") for l := range ls { if l > 0 { sb.WriteString(" ") } - sb.WriteString(ls[l].String()) + ls[l].BuildString(sb) } sb.WriteString("]") +} + +func (ls LabelArray) String() string { + var sb strings.Builder + ls.BuildString(&sb) return sb.String() } +func (ls LabelArray) BuildBytes(buf *bytes.Buffer) { + buf.WriteString("[") + for l := range ls { + if l > 0 { + buf.WriteString(" ") + } + ls[l].BuildBytes(buf) + } + buf.WriteString("]") +} + // StringMap converts LabelArray into map[string]string // Note: The source is included in the keys with a ':' separator. // Note: LabelArray does not deduplicate entries, as it is an array. It is diff --git a/vendor/github.com/cilium/cilium/pkg/labels/arraylist.go b/vendor/github.com/cilium/cilium/pkg/labels/arraylist.go index 80d1b2ae3b..8bed5ee57a 100644 --- a/vendor/github.com/cilium/cilium/pkg/labels/arraylist.go +++ b/vendor/github.com/cilium/cilium/pkg/labels/arraylist.go @@ -4,8 +4,10 @@ package labels import ( - "fmt" + "bytes" + "iter" "sort" + "strings" ) // LabelArrayList is an array of LabelArrays. It is primarily intended as a @@ -38,13 +40,10 @@ func (ls LabelArrayList) GetModel() [][]string { // Equals returns true if the label arrays lists have the same label arrays in the same order. func (ls LabelArrayList) Equals(b LabelArrayList) bool { if len(ls) != len(b) { - fmt.Printf("LEN DIFFERS: obtained %v, expected %v\n", ls, b) return false } for l := range ls { if !ls[l].Equals(b[l]) { - fmt.Printf("LABEL ARRAY %d DIFFERS: obtained %v, expected %v\n", - l, ls[l], b[l]) return false } } @@ -92,14 +91,61 @@ func (ls LabelArrayList) Diff(expected LabelArrayList) (res string) { // GetModel returns the LabelArrayList as a [][]string. Each member LabelArray // becomes a []string. func (ls LabelArrayList) String() string { - res := "" - for _, v := range ls { - if res != "" { - res += ", " + var sb strings.Builder + for i := range ls { + if i > 0 { + sb.WriteString(", ") } - res += v.String() + ls[i].BuildString(&sb) + } + return sb.String() +} + +func LabelArrayListFromString(str string) (ls LabelArrayList) { + // each LabelArray starts with '[' and ends with ']' + if len(str) > 2 && str[0] == '[' && str[len(str)-1] == ']' { + str = str[1 : len(str)-1] // remove first and last bracket + arrays := strings.Split(str, "], [") + for i := range arrays { + labels := strings.Split(arrays[i], " ") + var la LabelArray + for j := range labels { + la = append(la, ParseLabel(labels[j])) + } + ls = append(ls, la) + } + } + return ls +} + +func ModelsFromLabelArrayListString(str string) iter.Seq[[]string] { + return func(yield func(labelArray []string) bool) { + // each LabelArray starts with '[' and ends with ']' + if len(str) > 2 && str[0] == '[' && str[len(str)-1] == ']' { + str = str[1 : len(str)-1] // remove first and last bracket + for { + i := strings.Index(str, "], [") + if i < 0 { + break + } + if !yield(strings.Split(str[:i], " ")) { + return + } + str = str[i+4:] + } + // last label array + yield(strings.Split(str, " ")) + } + } +} + +func (ls LabelArrayList) BuildBytes(buf *bytes.Buffer) { + for l, v := range ls { + if l > 0 { + buf.WriteString(", ") + } + v.BuildBytes(buf) } - return res } // Sort sorts the LabelArrayList in-place, but also returns the sorted list @@ -146,3 +192,86 @@ func (lsp *LabelArrayList) MergeSorted(include LabelArrayList) LabelArrayList { *lsp = merged return *lsp } + +func nextArray(str string, end int) (int, int) { + start := strings.IndexByte(str[end:], '[') + if start >= 0 { + start += end + end = strings.IndexByte(str[start:], ']') + if end >= 0 { + end += start + 1 + } + } + return start, end +} + +func writeRemainder(str string, start, end int, sb *strings.Builder) { + if start >= 0 && start < end { + if sb.Len() > 0 { + sb.WriteString(", ") + } + sb.WriteString(str[start:]) + } +} + +// merge 'b' to 'a' assuming both are sorted +func MergeSortedLabelArrayListStrings(a, b string) string { + var sb strings.Builder + var aStart, aEnd, bStart, bEnd int +Loop: + for { + // get the next label array on 'a' + aStart, aEnd = nextArray(a, aEnd) + if aStart < 0 || aEnd < 0 || aStart >= aEnd { + // no more label arrays in a, concat the rest of 'b' + // next item from 'b' has not been parsed yet + bStart, bEnd = nextArray(b, bEnd) + writeRemainder(b, bStart, bEnd, &sb) + break + } + + // get the next label array on 'b' + bStart, bEnd = nextArray(b, bEnd) + if bStart < 0 || bEnd < 0 || bStart >= bEnd { + // no more label arrays in b, concat the rest of 'a' + writeRemainder(a, aStart, aEnd, &sb) + break + } + + // Add lesser label arrays from 'a' + for a[aStart:aEnd] < b[bStart:bEnd] { + if sb.Len() > 0 { + sb.WriteString(", ") + } + sb.WriteString(a[aStart:aEnd]) + // get the next label array on 'a' + aStart, aEnd = nextArray(a, aEnd) + if aStart < 0 || aEnd < 0 || aStart >= aEnd { + // no more label arrays in 'a', concat the rest of 'b' + writeRemainder(b, bStart, bEnd, &sb) + break Loop + } + } + // Add lesser values from 'b' + for a[aStart:aEnd] > b[bStart:bEnd] { + if sb.Len() > 0 { + sb.WriteString(", ") + } + sb.WriteString(b[bStart:bEnd]) + // get the next label array on 'b' + bStart, bEnd = nextArray(b, bEnd) + if bStart < 0 || bEnd < 0 || bStart >= bEnd { + // no more label arrays in 'b', concat the rest of 'a' + writeRemainder(a, aStart, aEnd, &sb) + break Loop + } + } + if a[aStart:aEnd] == b[bStart:bEnd] { + if sb.Len() > 0 { + sb.WriteString(", ") + } + sb.WriteString(b[bStart:bEnd]) + } + } + return sb.String() +} diff --git a/vendor/github.com/cilium/cilium/pkg/labels/labels.go b/vendor/github.com/cilium/cilium/pkg/labels/labels.go index 40c714ee0f..6c2acb3d45 100644 --- a/vendor/github.com/cilium/cilium/pkg/labels/labels.go +++ b/vendor/github.com/cilium/cilium/pkg/labels/labels.go @@ -411,6 +411,26 @@ func (l *Label) String() string { return l.Source + ":" + l.Key } +func (l *Label) BuildString(sb *strings.Builder) { + sb.WriteString(l.Source) + sb.WriteString(":") + sb.WriteString(l.Key) + if len(l.Value) != 0 { + sb.WriteString("=") + sb.WriteString(l.Value) + } +} + +func (l *Label) BuildBytes(buf *bytes.Buffer) { + buf.WriteString(l.Source) + buf.WriteString(":") + buf.WriteString(l.Key) + if len(l.Value) != 0 { + buf.WriteString("=") + buf.WriteString(l.Value) + } +} + // IsValid returns true if Key != "". func (l *Label) IsValid() bool { return l.Key != "" diff --git a/vendor/github.com/cilium/cilium/pkg/loadbalancer/loadbalancer.go b/vendor/github.com/cilium/cilium/pkg/loadbalancer/loadbalancer.go index d6f2588624..7adc2f73d3 100644 --- a/vendor/github.com/cilium/cilium/pkg/loadbalancer/loadbalancer.go +++ b/vendor/github.com/cilium/cilium/pkg/loadbalancer/loadbalancer.go @@ -74,11 +74,22 @@ func ToSVCForwardingMode(s string) SVCForwardingMode { type SVCLoadBalancingAlgorithm uint8 const ( - SVCLoadBalancingAlgorithmUndef = 0 - SVCLoadBalancingAlgorithmRandom = 1 - SVCLoadBalancingAlgorithmMaglev = 2 + SVCLoadBalancingAlgorithmUndef SVCLoadBalancingAlgorithm = 0 + SVCLoadBalancingAlgorithmRandom SVCLoadBalancingAlgorithm = 1 + SVCLoadBalancingAlgorithmMaglev SVCLoadBalancingAlgorithm = 2 ) +func (d SVCLoadBalancingAlgorithm) String() string { + switch d { + case SVCLoadBalancingAlgorithmRandom: + return "random" + case SVCLoadBalancingAlgorithmMaglev: + return "maglev" + default: + return "undef" + } +} + func ToSVCLoadBalancingAlgorithm(s string) SVCLoadBalancingAlgorithm { if s == option.NodePortAlgMaglev { return SVCLoadBalancingAlgorithmMaglev @@ -480,6 +491,14 @@ func (n ServiceName) String() string { return n.Namespace + "/" + n.Name } +func (n ServiceName) AppendSuffix(suffix string) ServiceName { + return ServiceName{ + Namespace: n.Namespace, + Name: n.Name + suffix, + Cluster: n.Cluster, + } +} + // BackendID is the backend's ID. type BackendID uint32 diff --git a/vendor/github.com/cilium/cilium/pkg/metrics/cmd.go b/vendor/github.com/cilium/cilium/pkg/metrics/cmd.go index fe4b81612e..d9b9ffca15 100644 --- a/vendor/github.com/cilium/cilium/pkg/metrics/cmd.go +++ b/vendor/github.com/cilium/cilium/pkg/metrics/cmd.go @@ -7,8 +7,6 @@ import ( "cmp" _ "embed" "encoding/json" - "errors" - "flag" "fmt" "html/template" "io" @@ -25,6 +23,7 @@ import ( "github.com/cilium/hive/script" "github.com/prometheus/client_golang/prometheus" dto "github.com/prometheus/client_model/go" + "github.com/spf13/pflag" "gopkg.in/yaml.v3" "github.com/cilium/cilium/api/v1/models" @@ -44,7 +43,12 @@ func metricsCommand(r *Registry, dc *sampler) script.Cmd { return script.Command( script.CmdUsage{ Summary: "List registered metrics", - Args: "[-o=file] [-format={table,yaml,json}] [-s] [-e] [match regex]", + Args: "[match regex]", + Flags: func(fs *pflag.FlagSet) { + fs.StringP("out", "o", "", "Output file") + fs.BoolP("sampled", "s", false, "Show sampled metrics") + fs.StringP("format", "f", "table", "Output format, one of: table, json or yaml") + }, RegexpArgs: func(rawArgs ...string) []int { for i, arg := range rawArgs { if !strings.HasPrefix(arg, "-") { @@ -57,10 +61,9 @@ func metricsCommand(r *Registry, dc *sampler) script.Cmd { return nil }, Detail: []string{ - "To write the metrics to a file: 'metrics -o=/path/to/file'", + "To write the metrics to a file: 'metrics --out=/path/to/file'", "To show metrics matching a regex: 'metrics foo.*'", - "To show only the enabled metrics: 'metrics -e'", - "To show samples from last 60 minutes: 'metrics -s'", + "To show samples from last 60 minutes: 'metrics --sampled'", "", "The metric samples can be plotted with 'metrics/plot' command.", "", @@ -76,19 +79,18 @@ func metricsCommand(r *Registry, dc *sampler) script.Cmd { }, }, func(s *script.State, args ...string) (script.WaitFunc, error) { - flags := flag.NewFlagSet("metrics", flag.ContinueOnError) - flags.SetOutput(s.LogWriter()) - file := flags.String("o", "", "Output file") - samples := flags.Bool("s", false, "Show sampled metrics") - format := flags.String("format", "table", "Output format, one of: table, json or yaml") - if err := flags.Parse(args); err != nil { - if errors.Is(err, flag.ErrHelp) { - return nil, nil - } + file, err := s.Flags.GetString("out") + if err != nil { + return nil, err + } + sampled, err := s.Flags.GetBool("sampled") + if err != nil { + return nil, err + } + format, err := s.Flags.GetString("format") + if err != nil { return nil, err } - args = flags.Args() - var re *regexp.Regexp if len(args) > 0 { var err error @@ -99,8 +101,8 @@ func metricsCommand(r *Registry, dc *sampler) script.Cmd { } var w io.Writer - if *file != "" { - f, err := os.OpenFile(s.Path(*file), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644) + if file != "" { + f, err := os.OpenFile(s.Path(file), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644) if err != nil { return nil, err } @@ -110,11 +112,11 @@ func metricsCommand(r *Registry, dc *sampler) script.Cmd { w = s.LogWriter() } - if *samples { - return nil, writeMetricsFromSamples(w, *format, re, dc) + if sampled { + return nil, writeMetricsFromSamples(w, format, re, dc) } - return nil, writeMetricsFromRegistry(w, *format, re, r.inner) + return nil, writeMetricsFromRegistry(w, format, re, r.inner) }, ) } @@ -125,7 +127,11 @@ func plotCommand(dc *sampler) script.Cmd { return script.Command( script.CmdUsage{ Summary: "Plot sampled metrics as a line graph", - Args: "[-o=file] [-rate] [match regex]", + Args: "[match regex]", + Flags: func(fs *pflag.FlagSet) { + fs.StringP("out", "o", "", "Output file") + fs.Bool("rate", false, "Plot the rate of change") + }, RegexpArgs: func(rawArgs ...string) []int { for i, arg := range rawArgs { if !strings.HasPrefix(arg, "-") { @@ -157,18 +163,16 @@ func plotCommand(dc *sampler) script.Cmd { }, }, func(s *script.State, args ...string) (script.WaitFunc, error) { - flags := flag.NewFlagSet("metrics/plot", flag.ContinueOnError) - flags.SetOutput(s.LogWriter()) - file := flags.String("o", "", "Output file") - rate := flags.Bool("rate", false, "Plot the rate of change") - if err := flags.Parse(args); err != nil { - if errors.Is(err, flag.ErrHelp) { - return nil, nil - } + s.Logf("args: %v\n", args) + + file, err := s.Flags.GetString("out") + if err != nil { + return nil, err + } + rate, err := s.Flags.GetBool("rate") + if err != nil { return nil, err } - args = flags.Args() - var re *regexp.Regexp if len(args) > 0 { var err error @@ -179,8 +183,8 @@ func plotCommand(dc *sampler) script.Cmd { } var w io.Writer - if *file != "" { - f, err := os.OpenFile(s.Path(*file), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644) + if file != "" { + f, err := os.OpenFile(s.Path(file), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644) if err != nil { return nil, err } @@ -221,13 +225,13 @@ func plotCommand(dc *sampler) script.Cmd { switch ds := ds.(type) { case *gaugeOrCounterSamples: - PlotSamples(w, *rate, ds.getName(), ds.getLabels(), samplingTimeSpan, ds.samples.grab(), ds.bits) + PlotSamples(w, rate, ds.getName(), ds.getLabels(), samplingTimeSpan, ds.samples.grab(), ds.bits) case *histogramSamples: - PlotSamples(w, *rate, ds.getName()+" (p50)", ds.getLabels(), samplingTimeSpan, ds.p50.grab(), ds.bits) + PlotSamples(w, rate, ds.getName()+" (p50)", ds.getLabels(), samplingTimeSpan, ds.p50.grab(), ds.bits) fmt.Fprintln(w) - PlotSamples(w, *rate, ds.getName()+" (p90)", ds.getLabels(), samplingTimeSpan, ds.p90.grab(), ds.bits) + PlotSamples(w, rate, ds.getName()+" (p90)", ds.getLabels(), samplingTimeSpan, ds.p90.grab(), ds.bits) fmt.Fprintln(w) - PlotSamples(w, *rate, ds.getName()+" (p99)", ds.getLabels(), samplingTimeSpan, ds.p99.grab(), ds.bits) + PlotSamples(w, rate, ds.getName()+" (p99)", ds.getLabels(), samplingTimeSpan, ds.p99.grab(), ds.bits) } return nil, nil @@ -242,23 +246,20 @@ func htmlCommand(dc *sampler) script.Cmd { return script.Command( script.CmdUsage{ Summary: "Produce a HTML file from the sampled metrics", - Args: "[-o=file]", - Detail: []string{}, + Args: "", + Flags: func(fs *pflag.FlagSet) { + fs.StringP("out", "o", "", "Output file") + }, + Detail: []string{}, }, func(s *script.State, args ...string) (script.WaitFunc, error) { - flags := flag.NewFlagSet("metrics/html", flag.ContinueOnError) - flags.SetOutput(s.LogWriter()) - file := flags.String("o", "", "Output file") - if err := flags.Parse(args); err != nil { - if errors.Is(err, flag.ErrHelp) { - return nil, nil - } + file, err := s.Flags.GetString("out") + if err != nil { return nil, err } - var w io.Writer - if *file != "" { - f, err := os.OpenFile(s.Path(*file), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644) + if file != "" { + f, err := os.OpenFile(s.Path(file), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644) if err != nil { return nil, err } diff --git a/vendor/github.com/cilium/cilium/pkg/node/local_node_store.go b/vendor/github.com/cilium/cilium/pkg/node/local_node_store.go index e8c6ecdd2e..fda7d561dc 100644 --- a/vendor/github.com/cilium/cilium/pkg/node/local_node_store.go +++ b/vendor/github.com/cilium/cilium/pkg/node/local_node_store.go @@ -16,6 +16,7 @@ import ( "github.com/cilium/cilium/pkg/cidr" "github.com/cilium/cilium/pkg/lock" "github.com/cilium/cilium/pkg/node/types" + "github.com/cilium/cilium/pkg/source" ) // +deepequal-gen=true @@ -115,6 +116,7 @@ func NewLocalNodeStore(params LocalNodeStoreParams) (*LocalNodeStore, error) { // we don't need to always check for nil values. Labels: make(map[string]string), Annotations: make(map[string]string), + Source: source.Unspec, }}, hasValue: hasValue, } diff --git a/vendor/github.com/cilium/cilium/pkg/option/config.go b/vendor/github.com/cilium/cilium/pkg/option/config.go index 9215cd7566..b939fd6429 100644 --- a/vendor/github.com/cilium/cilium/pkg/option/config.go +++ b/vendor/github.com/cilium/cilium/pkg/option/config.go @@ -83,7 +83,7 @@ const ( AllowLocalhostPolicy = "policy" // AnnotateK8sNode enables annotating a kubernetes node while bootstrapping - // the daemon, which can also be disbled using this option. + // the daemon, which can also be disabled using this option. AnnotateK8sNode = "annotate-k8s-node" // ARPPingRefreshPeriod is the ARP entries refresher period @@ -159,6 +159,9 @@ const ( // GopsPort is the TCP port for the gops server. GopsPort = "gops-port" + // EnableGops run the gops server + EnableGops = "enable-gops" + // FixedIdentityMapping is the key-value for the fixed identity mapping // which allows to use reserved label for fixed identities FixedIdentityMapping = "fixed-identity-mapping" @@ -206,13 +209,6 @@ const ( // K8sServiceCacheSize is service cache size for cilium k8s package. K8sServiceCacheSize = "k8s-service-cache-size" - // K8sServiceDebounceBufferSize is the maximum number of service events to buffer. - K8sServiceDebounceBufferSize = "k8s-service-debounce-buffer-size" - - // K8sServiceDebounceBufferWaitTime is the amount of time to wait before emitting - // the service event buffer. - K8sServiceDebounceWaitTime = "k8s-service-debounce-wait-time" - // K8sSyncTimeout is the timeout since last event was received to synchronize all resources with k8s. K8sSyncTimeoutName = "k8s-sync-timeout" @@ -284,6 +280,9 @@ const ( // level annotation for configuring bpf loadbalancing algorithm. LoadBalancerAlgorithmAnnotation = "bpf-lb-algorithm-annotation" + // LoadBalancerOnly is legacy knob for --datapath-mode=lb-only. + LoadBalancerOnly = "bpf-lb-only" + // Alias to NodePortAcceleration LoadBalancerAcceleration = "bpf-lb-acceleration" @@ -317,11 +316,6 @@ const ( // conflicting marks. EnableIdentityMark = "enable-identity-mark" - // EnableHighScaleIPcache enables the special ipcache mode for high scale - // clusters. The ipcache content will be reduced to the strict minimum and - // traffic will be encapsulated to carry security identities. - EnableHighScaleIPcache = "enable-high-scale-ipcache" - // AddressScopeMax controls the maximum address scope for addresses to be // considered local ones with HOST_ID in the ipcache AddressScopeMax = "local-max-addr-scope" @@ -784,6 +778,9 @@ const ( // EnableWireguard is the name of the option to enable WireGuard EnableWireguard = "enable-wireguard" + // WireguardTrackAllIPsFallback forces the WireGuard agent to track all IPs. + WireguardTrackAllIPsFallback = "wireguard-track-all-ips-fallback" + // EnableL2Announcements is the name of the option to enable l2 announcements EnableL2Announcements = "enable-l2-announcements" @@ -972,11 +969,6 @@ const ( // the allocation prefix of the local node. EnableLocalNodeRoute = "enable-local-node-route" - // EnableWellKnownIdentities enables the use of well-known identities. - // This is requires if identiy resolution is required to bring up the - // control plane, e.g. when using the managed etcd feature - EnableWellKnownIdentities = "enable-well-known-identities" - // PolicyAuditModeArg argument enables policy audit mode. PolicyAuditModeArg = "policy-audit-mode" @@ -1205,6 +1197,9 @@ const ( // EnableCiliumEndpointSlice enables the cilium endpoint slicing feature. EnableCiliumEndpointSlice = "enable-cilium-endpoint-slice" + // IdentityManagementMode controls whether CiliumIdentities are managed by cilium-agent, cilium-operator, or both. + IdentityManagementMode = "identity-management-mode" + // EnableExternalWorkloads enables the support for external workloads. EnableExternalWorkloads = "enable-external-workloads" @@ -1271,6 +1266,16 @@ const ( // PprofPortAgent is the default value for pprof in the agent PprofPortAgent = 6060 + + // IdentityManagementModeAgent means cilium-agent is solely responsible for managing CiliumIdentity. + IdentityManagementModeAgent = "agent" + + // IdentityManagementModeOperator means cilium-operator is solely responsible for managing CiliumIdentity. + IdentityManagementModeOperator = "operator" + + // IdentityManagementModeBoth means cilium-agent and cilium-operator both manage identities + // (used only during migration between "agent" and "operator"). + IdentityManagementModeBoth = "both" ) // getEnvName returns the environment variable to be used for the given option name. @@ -1413,13 +1418,6 @@ type DaemonConfig struct { // K8sServiceCacheSize is the service cache size for cilium k8s package. K8sServiceCacheSize uint - // Number of distinct services to buffer at most. - K8sServiceDebounceBufferSize int - - // The amount of time to wait to debounce service events before - // emitting the buffer. - K8sServiceDebounceWaitTime time.Duration - // MTU is the maximum transmission unit of the underlying network MTU int @@ -1590,6 +1588,9 @@ type DaemonConfig struct { // EnableEncryptionStrictMode enables strict mode for encryption EnableEncryptionStrictMode bool + // WireguardTrackAllIPsFallback forces the WireGuard agent to track all IPs. + WireguardTrackAllIPsFallback bool + // EncryptionStrictModeCIDR is the CIDR to use for strict mode EncryptionStrictModeCIDR netip.Prefix @@ -1909,6 +1910,9 @@ type DaemonConfig struct { // LoadBalancerProtocolDifferentiation enables support for service protocol differentiation (TCP, UDP, SCTP) LoadBalancerProtocolDifferentiation bool + // LoadBalancerOnly is legacy knob for --datapath-mode=lb-only. + LoadBalancerOnly bool + // EnablePMTUDiscovery indicates whether to send ICMP fragmentation-needed // replies to the client (when needed). EnablePMTUDiscovery bool @@ -1971,11 +1975,6 @@ type DaemonConfig struct { // conflicting marks. EnableIdentityMark bool - // EnableHighScaleIPcache enables the special ipcache mode for high scale - // clusters. The ipcache content will be reduced to the strict minimum and - // traffic will be encapsulated to carry security identities. - EnableHighScaleIPcache bool - // KernelHz is the HZ rate the kernel is operating in KernelHz int @@ -2026,11 +2025,6 @@ type DaemonConfig struct { // the network policy for cilium-agent. AllowICMPFragNeeded bool - // EnableWellKnownIdentities enables the use of well-known identities. - // This is requires if identiy resolution is required to bring up the - // control plane, e.g. when using the managed etcd feature - EnableWellKnownIdentities bool - // Azure options // PolicyAuditMode enables non-drop mode for installed policies. In @@ -2303,7 +2297,6 @@ var ( AutoCreateCiliumNodeResource: defaults.AutoCreateCiliumNodeResource, IdentityAllocationMode: IdentityAllocationModeKVstore, AllowICMPFragNeeded: defaults.AllowICMPFragNeeded, - EnableWellKnownIdentities: defaults.EnableWellKnownIdentities, AllocatorListTimeout: defaults.AllocatorListTimeout, EnableICMPRules: defaults.EnableICMPRules, UseCiliumInternalIPForIPsec: defaults.UseCiliumInternalIPForIPsec, @@ -2389,18 +2382,36 @@ func (c *DaemonConfig) TunnelingEnabled() bool { // devices to implement some features. func (c *DaemonConfig) AreDevicesRequired() bool { return c.EnableNodePort || c.EnableHostFirewall || c.EnableWireguard || - c.EnableHighScaleIPcache || c.EnableL2Announcements || c.ForceDeviceRequired || - c.EnableIPSecEncryptedOverlay + c.EnableL2Announcements || c.ForceDeviceRequired || c.EnableIPSecEncryptedOverlay } -// When WG & encrypt-node are on, a NodePort BPF to-be forwarded request -// to a remote node running a selected service endpoint must be encrypted. -// To make the NodePort's rev-{S,D}NAT translations to happen for a reply -// from the remote node, we need to attach bpf_host to the Cilium's WG -// netdev (otherwise, the WG netdev after decrypting the reply will pass -// it to the stack which drops the packet). +// NeedBPFHostOnWireGuardDevice returns true if the agent needs to attach +// a BPF program on the Ingress of Cilium's WireGuard device func (c *DaemonConfig) NeedBPFHostOnWireGuardDevice() bool { - return c.EnableNodePort && c.EnableWireguard && c.EncryptNode + if !c.EnableWireguard { + return false + } + + // In native routing mode we want to deliver packets to local endpoints + // straight from BPF, without passing through the stack. + // This matches overlay mode (where bpf_overlay would handle the delivery) + // and native routing mode without encryption (where bpf_host at the native + // device would handle the delivery). + if !c.TunnelingEnabled() { + return true + } + + // When WG & encrypt-node are on, a NodePort BPF to-be forwarded request + // to a remote node running a selected service endpoint must be encrypted. + // To make the NodePort's rev-{S,D}NAT translations to happen for a reply + // from the remote node, we need to attach bpf_host to the Cilium's WG + // netdev (otherwise, the WG netdev after decrypting the reply will pass + // it to the stack which drops the packet). + if c.EnableNodePort && c.EncryptNode { + return true + } + + return false } // MasqueradingEnabled returns true if either IPv4 or IPv6 masquerading is enabled. @@ -2838,12 +2849,12 @@ func (c *DaemonConfig) Populate(vp *viper.Viper) { c.IPv6MCastDevice = vp.GetString(IPv6MCastDevice) c.EnableIPSec = vp.GetBool(EnableIPSecName) c.EnableWireguard = vp.GetBool(EnableWireguard) + c.WireguardTrackAllIPsFallback = vp.GetBool(WireguardTrackAllIPsFallback) c.EnableL2Announcements = vp.GetBool(EnableL2Announcements) c.L2AnnouncerLeaseDuration = vp.GetDuration(L2AnnouncerLeaseDuration) c.L2AnnouncerRenewDeadline = vp.GetDuration(L2AnnouncerRenewDeadline) c.L2AnnouncerRetryPeriod = vp.GetDuration(L2AnnouncerRetryPeriod) c.WireguardPersistentKeepalive = vp.GetDuration(WireguardPersistentKeepalive) - c.EnableWellKnownIdentities = vp.GetBool(EnableWellKnownIdentities) c.EnableXDPPrefilter = vp.GetBool(EnableXDPPrefilter) c.EnableTCX = vp.GetBool(EnableTCX) c.DisableCiliumEndpointCRD = vp.GetBool(DisableCiliumEndpointCRDName) @@ -2898,8 +2909,6 @@ func (c *DaemonConfig) Populate(vp *viper.Viper) { c.K8sRequireIPv4PodCIDR = vp.GetBool(K8sRequireIPv4PodCIDRName) c.K8sRequireIPv6PodCIDR = vp.GetBool(K8sRequireIPv6PodCIDRName) c.K8sServiceCacheSize = uint(vp.GetInt(K8sServiceCacheSize)) - c.K8sServiceDebounceBufferSize = vp.GetInt(K8sServiceDebounceBufferSize) - c.K8sServiceDebounceWaitTime = vp.GetDuration(K8sServiceDebounceWaitTime) c.K8sSyncTimeout = vp.GetDuration(K8sSyncTimeoutName) c.AllocatorListTimeout = vp.GetDuration(AllocatorListTimeoutName) c.K8sWatcherEndpointSelector = vp.GetString(K8sWatcherEndpointSelector) @@ -2961,7 +2970,6 @@ func (c *DaemonConfig) Populate(vp *viper.Viper) { c.BGPSecretsNamespace = vp.GetString(BGPSecretsNamespace) c.ExternalClusterIP = vp.GetBool(ExternalClusterIPName) c.EnableNat46X64Gateway = vp.GetBool(EnableNat46X64Gateway) - c.EnableHighScaleIPcache = vp.GetBool(EnableHighScaleIPcache) c.EnableIPv4Masquerade = vp.GetBool(EnableIPv4Masquerade) && c.EnableIPv4 c.EnableIPv6Masquerade = vp.GetBool(EnableIPv6Masquerade) && c.EnableIPv6 c.EnableBPFMasquerade = vp.GetBool(EnableBPFMasquerade) @@ -3322,9 +3330,8 @@ func (c *DaemonConfig) Populate(vp *viper.Viper) { } c.LoadBalancerProtocolDifferentiation = vp.GetBool(LoadBalancerProtocolDifferentiation) - + c.LoadBalancerOnly = vp.GetBool(LoadBalancerOnly) c.EnableInternalTrafficPolicy = vp.GetBool(EnableInternalTrafficPolicy) - c.EnableSourceIPVerification = vp.GetBool(EnableSourceIPVerification) } @@ -3798,6 +3805,7 @@ func (c *DaemonConfig) checksum() [32]byte { sumConfig := *c // Ignore variable parts sumConfig.Opts = nil + sumConfig.EncryptInterface = nil cBytes, err := json.Marshal(&sumConfig) if err != nil { return [32]byte{} @@ -3853,7 +3861,8 @@ func (c *DaemonConfig) diffFromFile() error { diff = cmp.Diff(&config, c, opts, cmpopts.IgnoreTypes(&IntOptions{}), - cmpopts.IgnoreTypes(&OptionLibrary{})) + cmpopts.IgnoreTypes(&OptionLibrary{}), + cmpopts.IgnoreFields(DaemonConfig{}, "EncryptInterface")) } return fmt.Errorf("Config differs:\n%s", diff) } diff --git a/vendor/github.com/cilium/cilium/pkg/policy/api/egress.go b/vendor/github.com/cilium/cilium/pkg/policy/api/egress.go index 95b3ca309c..ca7f82a56d 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/api/egress.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/api/egress.go @@ -80,12 +80,7 @@ type EgressCommonRule struct { // ToServices is a list of services to which the endpoint subject // to the rule is allowed to initiate connections. - // Currently Cilium only supports toServices for K8s services without - // selectors. - // - // Example: - // Any endpoint with the label "app=backend-app" is allowed to - // initiate connections to all cidrs backing the "external-service" service + // Currently Cilium only supports toServices for K8s services. // // +kubebuilder:validation:Optional ToServices []Service `json:"toServices,omitempty"` diff --git a/vendor/github.com/cilium/cilium/pkg/policy/api/fqdn.go b/vendor/github.com/cilium/cilium/pkg/policy/api/fqdn.go index 765ca48cf1..af75adc67a 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/api/fqdn.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/api/fqdn.go @@ -18,7 +18,7 @@ var ( allowedMatchNameChars = regexp.MustCompile("^[-a-zA-Z0-9_.]+$") // allowedPatternChars tests that the MatchPattern field contains only the - // characters we want in our wilcard scheme. + // characters we want in our wildcard scheme. allowedPatternChars = regexp.MustCompile("^[-a-zA-Z0-9_.*]+$") // the * inside the [] is a literal * // FQDNMatchNameRegexString is a regex string which matches what's expected @@ -51,7 +51,7 @@ type FQDNSelector struct { // A trailing "." is automatically added when missing. // // Examples: - // `*.cilium.io` matches subomains of cilium at that level + // `*.cilium.io` matches subdomains of cilium at that level // www.cilium.io and blog.cilium.io match, cilium.io and google.com do not // `*cilium.io` matches cilium.io and all subdomains ends with "cilium.io" // except those containing "." separator, subcilium.io and sub-cilium.io match, diff --git a/vendor/github.com/cilium/cilium/pkg/policy/api/rule.go b/vendor/github.com/cilium/cilium/pkg/policy/api/rule.go index 000354854d..c77b131f15 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/api/rule.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/api/rule.go @@ -76,7 +76,7 @@ type Rule struct { // Ingress is a list of IngressRule which are enforced at ingress. // If omitted or empty, this rule does not apply at ingress. // - // +kubebuilder:validation:Optional + // +kubebuilder:validation:AnyOf Ingress []IngressRule `json:"ingress,omitempty"` // IngressDeny is a list of IngressDenyRule which are enforced at ingress. @@ -84,13 +84,13 @@ type Rule struct { // rules in the 'ingress' field. // If omitted or empty, this rule does not apply at ingress. // - // +kubebuilder:validation:Optional + // +kubebuilder:validation:AnyOf IngressDeny []IngressDenyRule `json:"ingressDeny,omitempty"` // Egress is a list of EgressRule which are enforced at egress. // If omitted or empty, this rule does not apply at egress. // - // +kubebuilder:validation:Optional + // +kubebuilder:validation:AnyOf Egress []EgressRule `json:"egress,omitempty"` // EgressDeny is a list of EgressDenyRule which are enforced at egress. @@ -98,7 +98,7 @@ type Rule struct { // rules in the 'egress' field. // If omitted or empty, this rule does not apply at egress. // - // +kubebuilder:validation:Optional + // +kubebuilder:validation:AnyOf EgressDeny []EgressDenyRule `json:"egressDeny,omitempty"` // Labels is a list of optional strings which can be used to @@ -232,6 +232,12 @@ func (r *Rule) WithEgressDenyRules(rules []EgressDenyRule) *Rule { return r } +// WithEnableDefaultDeny configures the Rule to enable default deny. +func (r *Rule) WithEnableDefaultDeny(ingress, egress bool) *Rule { + r.EnableDefaultDeny = DefaultDenyConfig{&ingress, &egress} + return r +} + // WithLabels configures the Rule with the specified labels metadata. func (r *Rule) WithLabels(labels labels.LabelArray) *Rule { r.Labels = labels diff --git a/vendor/github.com/cilium/cilium/pkg/policy/api/rule_validation.go b/vendor/github.com/cilium/cilium/pkg/policy/api/rule_validation.go index 126fd1c98d..57f61f279b 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/api/rule_validation.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/api/rule_validation.go @@ -36,6 +36,10 @@ var ( // Note: this function is called from both the operator and the agent; // make sure any configuration flags are bound in **both** binaries. func (r *Rule) Sanitize() error { + if len(r.Ingress) == 0 && len(r.IngressDeny) == 0 && len(r.Egress) == 0 && len(r.EgressDeny) == 0 { + return fmt.Errorf("rule must have at least one of Ingress, IngressDeny, Egress, EgressDeny") + } + if option.Config.EnableNonDefaultDenyPolicies { // Fill in the default traffic posture of this Rule. // Default posture is per-direction (ingress or egress), @@ -53,7 +57,6 @@ func (r *Rule) Sanitize() error { // Since Non Default Deny Policies is disabled by flag, set EnableDefaultDeny to true r.EnableDefaultDeny.Egress = &enableDefaultDenyDefault r.EnableDefaultDeny.Ingress = &enableDefaultDenyDefault - } if r.EndpointSelector.LabelSelector == nil && r.NodeSelector.LabelSelector == nil { diff --git a/vendor/github.com/cilium/cilium/pkg/policy/api/service.go b/vendor/github.com/cilium/cilium/pkg/policy/api/service.go index 57868a367a..4c8debda91 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/api/service.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/api/service.go @@ -6,7 +6,10 @@ package api // ServiceSelector is a label selector for k8s services type ServiceSelector EndpointSelector -// Service wraps around selectors for services +// Service selects policy targets that are bundled as part of a +// logical load-balanced service. +// +// Currently only Kubernetes-based Services are supported. type Service struct { // K8sServiceSelector selects services by k8s labels and namespace K8sServiceSelector *K8sServiceSelectorNamespace `json:"k8sServiceSelector,omitempty"` @@ -14,13 +17,13 @@ type Service struct { K8sService *K8sServiceNamespace `json:"k8sService,omitempty"` } -// K8sServiceNamespace is an abstraction for the k8s service + namespace types. +// K8sServiceNamespace selects services by name and, optionally, namespace. type K8sServiceNamespace struct { ServiceName string `json:"serviceName,omitempty"` Namespace string `json:"namespace,omitempty"` } -// K8sServiceSelectorNamespace wraps service selector with namespace +// K8sServiceSelectorNamespace selects services by labels. type K8sServiceSelectorNamespace struct { // +kubebuilder:validation:Required Selector ServiceSelector `json:"selector"` diff --git a/vendor/github.com/cilium/cilium/pkg/policy/l4.go b/vendor/github.com/cilium/cilium/pkg/policy/l4.go index 5e72934c05..bce55e57f9 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/l4.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/l4.go @@ -12,6 +12,7 @@ import ( "strconv" "strings" "sync/atomic" + "unique" cilium "github.com/cilium/proxy/go/cilium/api" "github.com/sirupsen/logrus" @@ -321,15 +322,6 @@ func (l7 L7DataMap) MarshalJSON() ([]byte, error) { return buffer.Bytes(), err } -// ShallowCopy returns a shallow copy of the L7DataMap. -func (l7 L7DataMap) ShallowCopy() L7DataMap { - m := make(L7DataMap, len(l7)) - for k, v := range l7 { - m[k] = v - } - return m -} - // L7ParserType is the type used to indicate what L7 parser to use. // Consts are defined for all well known L7 parsers. // Unknown string values are created for key-value pair policies, which @@ -403,6 +395,64 @@ func (a L7ParserType) Merge(b L7ParserType) (L7ParserType, error) { return ParserTypeNone, fmt.Errorf("cannot merge conflicting L7 parsers (%s/%s)", a, b) } +// ruleOrigin is an interned labels.LabelArrayList.String(), a list of rule labels tracking which +// policy rules are the origin for this policy. This information is used when distilling a policy to +// an EndpointPolicy, to track which policy rules were involved for a specific verdict. +type ruleOrigin unique.Handle[string] + +func (ro ruleOrigin) Value() string { + return unique.Handle[string](ro).Value() +} + +func makeRuleOrigin(lbls labels.LabelArrayList) ruleOrigin { + return ruleOrigin(unique.Make(lbls.String())) +} + +func (ro *ruleOrigin) Merge(other ruleOrigin) bool { + if ro.Value() == "" { + *ro = other + return true + } + if other.Value() != "" { + *ro = ruleOrigin(unique.Make(labels.MergeSortedLabelArrayListStrings(ro.Value(), other.Value()))) + return true + } + return false +} + +func singleRuleOrigin(ruleLabels stringLabels) ruleOrigin { + return ruleOrigin(ruleLabels) +} + +var NilRuleOrigin = singleRuleOrigin(EmptyStringLabels) + +type testOrigin map[CachedSelector]labels.LabelArrayList + +func OriginForTest(m testOrigin) map[CachedSelector]ruleOrigin { + res := make(map[CachedSelector]ruleOrigin, len(m)) + for cs, lbls := range m { + res[cs] = makeRuleOrigin(lbls) + } + return res +} + +func (o ruleOrigin) GetLabelArrayList() labels.LabelArrayList { + return labels.LabelArrayListFromString(o.Value()) +} + +// stringLabels is an interned labels.LabelArray.String() +type stringLabels unique.Handle[string] + +var EmptyStringLabels = makeStringLabels(nil) + +func (sl stringLabels) Value() string { + return unique.Handle[string](sl).Value() +} + +func makeStringLabels(lbls labels.LabelArray) stringLabels { + return stringLabels(unique.Make(lbls.Sort().String())) +} + // L4Filter represents the policy (allowed remote sources / destinations of // traffic) that applies at a specific L4 port/protocol combination (including // all ports and protocols), at either ingress or egress. The policy here is @@ -435,11 +485,9 @@ type L4Filter struct { L7Parser L7ParserType `json:"-"` // Ingress is true if filter applies at ingress; false if it applies at egress. Ingress bool `json:"-"` - // RuleOrigin tracks which policy rules (identified by labels) are the origin for this L3/L4 - // (i.e. selector and port) filter. This information is used when distilling a policy to an - // EndpointPolicy, to track which policy rules were involved for a specific verdict. - // Each LabelArrayList is in sorted order. - RuleOrigin map[CachedSelector]labels.LabelArrayList `json:"-"` + // RuleOrigin is a set of rule labels tracking which policy rules are the origin for this + // L3/L4 filter. + RuleOrigin map[CachedSelector]ruleOrigin `json:"-"` // This reference is circular, but it is cleaned up at Detach() policy atomic.Pointer[L4Policy] @@ -459,8 +507,8 @@ func (l4 *L4Filter) SelectsAllEndpoints() bool { // CopyL7RulesPerEndpoint returns a shallow copy of the PerSelectorPolicies of the // L4Filter. -func (l4 *L4Filter) CopyL7RulesPerEndpoint() L7DataMap { - return l4.PerSelectorPolicies.ShallowCopy() +func (l4 *L4Filter) GetPerSelectorPolicies() L7DataMap { + return l4.PerSelectorPolicies } // GetL7Parser returns the L7ParserType of the L4Filter. @@ -624,7 +672,7 @@ func (l4 *L4Filter) toMapState(p *EndpointPolicy, features policyFeatures, chang continue } } - entry := newMapStateEntry(cs, l4.RuleOrigin[cs], proxyPort, priority, isDenyRule, authReq) + entry := newMapStateEntry(l4.RuleOrigin[cs], proxyPort, priority, isDenyRule, authReq) if cs.IsWildcard() { for _, keyToAdd := range keysToAdd { @@ -730,7 +778,7 @@ func (l4 *L4Filter) IsPeerSelector() bool { return true } -func (l4 *L4Filter) cacheIdentitySelector(sel api.EndpointSelector, lbls labels.LabelArray, selectorCache *SelectorCache) CachedSelector { +func (l4 *L4Filter) cacheIdentitySelector(sel api.EndpointSelector, lbls stringLabels, selectorCache *SelectorCache) CachedSelector { cs, added := selectorCache.AddIdentitySelector(l4, lbls, sel) if added { l4.PerSelectorPolicies[cs] = nil // no per-selector policy (yet) @@ -738,19 +786,19 @@ func (l4 *L4Filter) cacheIdentitySelector(sel api.EndpointSelector, lbls labels. return cs } -func (l4 *L4Filter) cacheIdentitySelectors(selectors api.EndpointSelectorSlice, lbls labels.LabelArray, selectorCache *SelectorCache) { +func (l4 *L4Filter) cacheIdentitySelectors(selectors api.EndpointSelectorSlice, lbls stringLabels, selectorCache *SelectorCache) { for _, sel := range selectors { l4.cacheIdentitySelector(sel, lbls, selectorCache) } } -func (l4 *L4Filter) cacheFQDNSelectors(selectors api.FQDNSelectorSlice, lbls labels.LabelArray, selectorCache *SelectorCache) { +func (l4 *L4Filter) cacheFQDNSelectors(selectors api.FQDNSelectorSlice, lbls stringLabels, selectorCache *SelectorCache) { for _, fqdnSel := range selectors { l4.cacheFQDNSelector(fqdnSel, lbls, selectorCache) } } -func (l4 *L4Filter) cacheFQDNSelector(sel api.FQDNSelector, lbls labels.LabelArray, selectorCache *SelectorCache) types.CachedSelector { +func (l4 *L4Filter) cacheFQDNSelector(sel api.FQDNSelector, lbls stringLabels, selectorCache *SelectorCache) types.CachedSelector { cs, added := selectorCache.AddFQDNSelector(l4, lbls, sel) if added { l4.PerSelectorPolicies[cs] = nil // no per-selector policy (yet) @@ -832,7 +880,7 @@ func (l4 *L4Filter) getCerts(policyCtx PolicyContext, tls *api.TLSContext, direc // rules via the `rule` parameter. // Not called with an empty peerEndpoints. func createL4Filter(policyCtx PolicyContext, peerEndpoints api.EndpointSelectorSlice, auth *api.Authentication, rule api.Ports, port api.PortProtocol, - protocol api.L4Proto, ruleLabels labels.LabelArray, ingress bool, fqdns api.FQDNSelectorSlice, + protocol api.L4Proto, ruleLabels stringLabels, ingress bool, fqdns api.FQDNSelectorSlice, ) (*L4Filter, error) { selectorCache := policyCtx.GetSelectorCache() @@ -856,7 +904,7 @@ func createL4Filter(policyCtx PolicyContext, peerEndpoints api.EndpointSelectorS Protocol: protocol, U8Proto: u8p, PerSelectorPolicies: make(L7DataMap), - RuleOrigin: make(map[CachedSelector]labels.LabelArrayList), // Filled in below. + RuleOrigin: make(map[CachedSelector]ruleOrigin), // Filled in below. Ingress: ingress, } @@ -944,8 +992,9 @@ func createL4Filter(policyCtx PolicyContext, peerEndpoints api.EndpointSelectorS l4.PerSelectorPolicies.addPolicyForSelector(rules, terminatingTLS, originatingTLS, auth, policyCtx.IsDeny(), sni, listener, priority) } + origin := singleRuleOrigin(ruleLabels) for cs := range l4.PerSelectorPolicies { - l4.RuleOrigin[cs] = labels.LabelArrayList{ruleLabels} + l4.RuleOrigin[cs] = origin } return l4, nil @@ -971,12 +1020,6 @@ func (l4 *L4Filter) detach(selectorCache *SelectorCache) { // from SelectorCache. L4Filter (and L4Policy) is read-only after this is called, // multiple goroutines will be reading the fields from that point on. func (l4 *L4Filter) attach(ctx PolicyContext, l4Policy *L4Policy) policyFeatures { - // All rules have been added to the L4Filter at this point. - // Sort the rules label array list for more efficient equality comparison. - for _, labels := range l4.RuleOrigin { - labels.Sort() - } - var features policyFeatures for cs, cp := range l4.PerSelectorPolicies { if cp != nil { @@ -1024,7 +1067,7 @@ func (l4 *L4Filter) attach(ctx PolicyContext, l4Policy *L4Policy) policyFeatures // hostWildcardL7 determines if L7 traffic from Host should be // wildcarded (in the relevant daemon mode). func createL4IngressFilter(policyCtx PolicyContext, fromEndpoints api.EndpointSelectorSlice, auth *api.Authentication, hostWildcardL7 []string, rule api.Ports, port api.PortProtocol, - protocol api.L4Proto, ruleLabels labels.LabelArray, + protocol api.L4Proto, ruleLabels stringLabels, ) (*L4Filter, error) { filter, err := createL4Filter(policyCtx, fromEndpoints, auth, rule, port, protocol, ruleLabels, true, nil) if err != nil { @@ -1052,7 +1095,7 @@ func createL4IngressFilter(policyCtx PolicyContext, fromEndpoints api.EndpointSe // to the original rules that the filter is derived from. This filter may be // associated with a series of L7 rules via the `rule` parameter. func createL4EgressFilter(policyCtx PolicyContext, toEndpoints api.EndpointSelectorSlice, auth *api.Authentication, rule api.Ports, port api.PortProtocol, - protocol api.L4Proto, ruleLabels labels.LabelArray, fqdns api.FQDNSelectorSlice, + protocol api.L4Proto, ruleLabels stringLabels, fqdns api.FQDNSelectorSlice, ) (*L4Filter, error) { return createL4Filter(policyCtx, toEndpoints, auth, rule, port, protocol, ruleLabels, false, fqdns) } @@ -1144,7 +1187,9 @@ func addL4Filter(policyCtx PolicyContext, // we know about. New CachedSelectors are added. for cs, newLabels := range filterToMerge.RuleOrigin { if existingLabels, ok := existingFilter.RuleOrigin[cs]; ok { - existingFilter.RuleOrigin[cs] = existingLabels.MergeSorted(newLabels) + if changed := existingLabels.Merge(newLabels); changed { + existingFilter.RuleOrigin[cs] = existingLabels + } } else { existingFilter.RuleOrigin[cs] = newLabels } @@ -1655,7 +1700,7 @@ func (l4Policy *L4Policy) AccumulateMapChanges(l4 *L4Filter, cs CachedSelector, keysToAdd = append(keysToAdd, KeyForDirection(direction).WithPortProtoPrefix(proto, mp.port, uint8(bits.LeadingZeros16(^mp.mask)))) } - value := newMapStateEntry(cs, derivedFrom, proxyPort, priority, isDeny, authReq) + value := newMapStateEntry(derivedFrom, proxyPort, priority, isDeny, authReq) if option.Config.Debug { authString := "default" @@ -1752,8 +1797,9 @@ func (l4 *L4Policy) GetModel() *models.L4Policy { rulesBySelector := map[string][][]string{} derivedFrom := labels.LabelArrayList{} for sel, rules := range v.RuleOrigin { - derivedFrom.MergeSorted(rules) - rulesBySelector[sel.String()] = rules.GetModel() + lal := rules.GetLabelArrayList() + derivedFrom.MergeSorted(lal) + rulesBySelector[sel.String()] = lal.GetModel() } ingress = append(ingress, &models.PolicyRule{ Rule: v.Marshal(), @@ -1765,9 +1811,11 @@ func (l4 *L4Policy) GetModel() *models.L4Policy { egress := []*models.PolicyRule{} l4.Egress.PortRules.ForEach(func(v *L4Filter) bool { + // TODO: Add RulesBySelector field like for ingress above? derivedFrom := labels.LabelArrayList{} for _, rules := range v.RuleOrigin { - derivedFrom.MergeSorted(rules) + lal := rules.GetLabelArrayList() + derivedFrom.MergeSorted(lal) } egress = append(egress, &models.PolicyRule{ Rule: v.Marshal(), @@ -1785,7 +1833,7 @@ func (l4 *L4Policy) GetModel() *models.L4Policy { // ProxyPolicy is any type which encodes state needed to redirect to an L7 // proxy. type ProxyPolicy interface { - CopyL7RulesPerEndpoint() L7DataMap + GetPerSelectorPolicies() L7DataMap GetL7Parser() L7ParserType GetIngress() bool GetPort() uint16 diff --git a/vendor/github.com/cilium/cilium/pkg/policy/lookup.go b/vendor/github.com/cilium/cilium/pkg/policy/lookup.go new file mode 100644 index 0000000000..b972e42c55 --- /dev/null +++ b/vendor/github.com/cilium/cilium/pkg/policy/lookup.go @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package policy + +// This includes some utilities for simulating policy verdicts. +// +// It is only used for tests, but is used by multiple packages. + +import ( + "fmt" + "log/slog" + + "github.com/sirupsen/logrus" + + "github.com/cilium/cilium/pkg/identity" + "github.com/cilium/cilium/pkg/policy/api" + "github.com/cilium/cilium/pkg/spanstat" + "github.com/cilium/cilium/pkg/u8proto" +) + +type Flow struct { + From, To *identity.Identity + Proto u8proto.U8proto + Dport uint16 +} + +type EndpointInfo struct { + ID uint64 + + TCPNamedPorts map[string]uint16 + UDPNamedPorts map[string]uint16 + + Logger *slog.Logger + + // Used when determining peer named ports + remoteEndpoint *EndpointInfo +} + +// LookupFlow determines the policy verdict for a given flow. +// +// The flow's identities must have been loaded in to the repository's SelectorCache, +// or policy will not be correctly computed. +// +// This function is only used for testing, but in multiple packages. +// +// TODO: add support for redirects +func LookupFlow(repo PolicyRepository, flow Flow, srcEP, dstEP *EndpointInfo) (api.Decision, error) { + if flow.From.ID == 0 || flow.To.ID == 0 { + return api.Undecided, fmt.Errorf("cannot lookup flow: numeric IDs missing") + } + if _, exists := repo.GetSelectorCache().idCache[flow.From.ID]; !exists { + return api.Undecided, fmt.Errorf("From.ID not in SelectorCache!") + } + if _, exists := repo.GetSelectorCache().idCache[flow.To.ID]; !exists { + return api.Undecided, fmt.Errorf("To.ID not in SelectorCache!") + } + if flow.Dport == 0 { + return api.Undecided, fmt.Errorf("cannot lookup flow: port number missing") + } + if flow.Proto == 0 { + return api.Undecided, fmt.Errorf("cannot lookup flow: protocol missing") + } + + if srcEP == nil { + srcEP = &EndpointInfo{ + ID: uint64(flow.From.ID), + } + } + + if dstEP == nil { + dstEP = &EndpointInfo{ + ID: uint64(flow.To.ID), + } + } + + srcEP.remoteEndpoint = dstEP + dstEP.remoteEndpoint = srcEP + + // Resolve and look up the flow as egress from the source + selPolSrc, _, err := repo.GetSelectorPolicy(flow.From, 0, &dummyPolicyStats{}) + if err != nil { + return api.Undecided, fmt.Errorf("GetSelectorPolicy(from) failed: %w", err) + } + + epp := selPolSrc.DistillPolicy(srcEP, nil) + epp.Ready() + epp.Detach() + key := EgressKey().WithIdentity(flow.To.ID).WithPortProto(flow.Proto, flow.Dport) + entry, _, _ := epp.Lookup(key) + if entry.IsDeny() { + return api.Denied, nil + } + + // Resolve ingress policy for destination + selPolDst, _, err := repo.GetSelectorPolicy(flow.To, 0, &dummyPolicyStats{}) + if err != nil { + return api.Undecided, fmt.Errorf("GetSelectorPolicy(to) failed: %w", err) + } + epp = selPolDst.DistillPolicy(dstEP, nil) + epp.Ready() + epp.Detach() + key = IngressKey().WithIdentity(flow.From.ID).WithPortProto(flow.Proto, flow.Dport) + entry, _, _ = epp.Lookup(key) + if entry.IsDeny() { + return api.Denied, nil + } + + return api.Allowed, nil +} + +var _ PolicyOwner = &EndpointInfo{} + +func (ei *EndpointInfo) GetID() uint64 { + return ei.ID +} + +// GetNamedPort determines the named port of the *destination*. So, if ingress +// is false, then this looks up the peer. +func (ei *EndpointInfo) GetNamedPort(ingress bool, name string, proto u8proto.U8proto) uint16 { + if !ingress && ei.remoteEndpoint != nil { + return ei.remoteEndpoint.GetNamedPort(true, name, proto) + } + switch { + case proto == u8proto.TCP && ei.TCPNamedPorts != nil: + return ei.TCPNamedPorts[name] + case proto == u8proto.UDP && ei.UDPNamedPorts != nil: + return ei.UDPNamedPorts[name] + } + + return 0 +} + +func (ei *EndpointInfo) PolicyDebug(fields logrus.Fields, msg string) { + if ei.Logger != nil { + args := make([]any, 0, len(fields)*2) + for k, v := range fields { + args = append(args, k, v) + } + ei.Logger.Debug(msg, args...) + } +} + +func (ei *EndpointInfo) IsHost() bool { + return false +} + +// MapStateSize returns the size of the current desired policy map, used for preallocation of the +// new map. Return 0 here as this is only used for testing. +func (ei *EndpointInfo) MapStateSize() int { + return 0 +} + +type dummyPolicyStats struct { + waitingForPolicyRepository spanstat.SpanStat + policyCalculation spanstat.SpanStat +} + +func (s *dummyPolicyStats) WaitingForPolicyRepository() *spanstat.SpanStat { + return &s.waitingForPolicyRepository +} + +func (s *dummyPolicyStats) SelectorPolicyCalculation() *spanstat.SpanStat { + return &s.policyCalculation +} diff --git a/vendor/github.com/cilium/cilium/pkg/policy/mapstate.go b/vendor/github.com/cilium/cilium/pkg/policy/mapstate.go index a2283a4b1e..5d2b8633d5 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/mapstate.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/mapstate.go @@ -4,15 +4,12 @@ package policy import ( - "fmt" "iter" - "slices" "github.com/hashicorp/go-hclog" "github.com/sirupsen/logrus" "github.com/cilium/cilium/pkg/container/bitlpm" - "github.com/cilium/cilium/pkg/container/set" "github.com/cilium/cilium/pkg/container/versioned" "github.com/cilium/cilium/pkg/identity" "github.com/cilium/cilium/pkg/labels" @@ -32,11 +29,10 @@ import ( type Key = types.Key type Keys = types.Keys type MapStateEntry = types.MapStateEntry -type MapStateOwner = types.CachedSelector const NoAuthRequirement = types.NoAuthRequirement -// Map type for external use. Internally we have more detail in private 'mapSteteEntry' type, +// Map type for external use. Internally we have more detail in private 'mapStateEntry' type, // as well as more extensive indexing via tries. type MapStateMap map[Key]MapStateEntry @@ -102,7 +98,7 @@ type mapState struct { entries mapStateMap // trie is a Trie that indexes policy Keys without their identity // and stores the identities in an associated builtin map. - trie bitlpm.Trie[bitlpm.Key[types.LPMKey], IDSet] + trie bitlpm.Trie[types.LPMKey, IDSet] } type IDSet map[identity.NumericIdentity]struct{} @@ -125,14 +121,11 @@ func (ms *mapState) upsert(k Key, e mapStateEntry) { // Update indices if 'k' is a new key if !exists { // Update trie - idSet, ok := ms.trie.ExactLookup(k.PrefixLength(), k) + idSet, ok := ms.trie.ExactLookup(k.PrefixLength(), k.LPMKey) if !ok { idSet = make(IDSet) - kCpy := k - kCpy.Identity = 0 - ms.trie.Upsert(kCpy.PrefixLength(), kCpy, idSet) + ms.trie.Upsert(k.PrefixLength(), k.LPMKey, idSet) } - idSet[k.Identity] = struct{}{} } } @@ -142,12 +135,11 @@ func (ms *mapState) delete(k Key) { if exists { delete(ms.entries, k) - id := k.Identity - idSet, ok := ms.trie.ExactLookup(k.PrefixLength(), k) + idSet, ok := ms.trie.ExactLookup(k.PrefixLength(), k.LPMKey) if ok { - delete(idSet, id) + delete(idSet, k.Identity) if len(idSet) == 0 { - ms.trie.Delete(k.PrefixLength(), k) + ms.trie.Delete(k.PrefixLength(), k.LPMKey) } } } @@ -208,9 +200,9 @@ func (ms *mapState) forID(k Key, idSet IDSet, f func(Key, mapStateEntry) bool) b // or wildcard ID) in the trie. func (ms *mapState) BroaderOrEqualKeys(key Key) iter.Seq2[Key, mapStateEntry] { return func(yield func(Key, mapStateEntry) bool) { - iter := ms.trie.AncestorIterator(key.PrefixLength(), key) + iter := ms.trie.AncestorIterator(key.PrefixLength(), key.LPMKey) for ok, lpmKey, idSet := iter.Next(); ok; ok, lpmKey, idSet = iter.Next() { - k := Key{LPMKey: lpmKey.Value()} + k := Key{LPMKey: lpmKey} // ANY identity is broader or equal to all identities, visit it first if it exists if !ms.forID(k.WithIdentity(0), idSet, yield) { @@ -231,9 +223,9 @@ func (ms *mapState) BroaderOrEqualKeys(key Key) iter.Seq2[Key, mapStateEntry] { // state that allows iteration to be continued even if the current trie node is removed. func (ms *mapState) NarrowerOrEqualKeys(key Key) iter.Seq2[Key, mapStateEntry] { return func(yield func(Key, mapStateEntry) bool) { - iter := ms.trie.DescendantIterator(key.PrefixLength(), key) + iter := ms.trie.DescendantIterator(key.PrefixLength(), key.LPMKey) for ok, lpmKey, idSet := iter.Next(); ok; ok, lpmKey, idSet = iter.Next() { - k := Key{LPMKey: lpmKey.Value()} + k := Key{LPMKey: lpmKey} // All identities are narrower or equal to ANY identity. if key.Identity == 0 { @@ -254,9 +246,9 @@ func (ms *mapState) NarrowerOrEqualKeys(key Key) iter.Seq2[Key, mapStateEntry] { // with most specific match with the same ID as in 'key' being returned first. func (ms *mapState) CoveringKeysWithSameID(key Key) iter.Seq2[Key, mapStateEntry] { return func(yield func(Key, mapStateEntry) bool) { - iter := ms.trie.AncestorLongestPrefixFirstIterator(key.PrefixLength(), key) + iter := ms.trie.AncestorLongestPrefixFirstIterator(key.PrefixLength(), key.LPMKey) for ok, lpmKey, idSet := iter.Next(); ok; ok, lpmKey, idSet = iter.Next() { - k := Key{LPMKey: lpmKey.Value()} + k := Key{LPMKey: lpmKey} // Visit key with the same identity, if port/proto is different. if !k.PortProtoIsEqual(key) && !ms.forID(k.WithIdentity(key.Identity), idSet, yield) { @@ -270,9 +262,9 @@ func (ms *mapState) CoveringKeysWithSameID(key Key) iter.Seq2[Key, mapStateEntry // order (least specific match first). func (ms *mapState) SubsetKeysWithSameID(key Key) iter.Seq2[Key, mapStateEntry] { return func(yield func(Key, mapStateEntry) bool) { - iter := ms.trie.DescendantShortestPrefixFirstIterator(key.PrefixLength(), key) + iter := ms.trie.DescendantShortestPrefixFirstIterator(key.PrefixLength(), key.LPMKey) for ok, lpmKey, idSet := iter.Next(); ok; ok, lpmKey, idSet = iter.Next() { - k := Key{LPMKey: lpmKey.Value()} + k := Key{LPMKey: lpmKey} // Visit key with the same identity, if port/proto is different. if !k.PortProtoIsEqual(key) && !ms.forID(k.WithIdentity(key.Identity), idSet, yield) { @@ -286,16 +278,16 @@ func (ms *mapState) SubsetKeysWithSameID(key Key) iter.Seq2[Key, mapStateEntry] // with most specific match with the same ID as in 'key' being returned first. func (ms *mapState) LPMAncestors(key Key) iter.Seq2[Key, mapStateEntry] { return func(yield func(Key, mapStateEntry) bool) { - iter := ms.trie.AncestorLongestPrefixFirstIterator(key.PrefixLength(), key) + iter := ms.trie.AncestorLongestPrefixFirstIterator(key.PrefixLength(), key.LPMKey) for ok, lpmKey, idSet := iter.Next(); ok; ok, lpmKey, idSet = iter.Next() { - k := Key{LPMKey: lpmKey.Value()} + k := Key{LPMKey: lpmKey} - // Visit key with the same identity, if port/proto is different. + // Visit key with the same identity, if one exists. if !ms.forID(k.WithIdentity(key.Identity), idSet, yield) { return } // Then visit key with zero identity if not already done above and one - // exists + // exists. if key.Identity != 0 && !ms.forID(k.WithIdentity(0), idSet, yield) { return } @@ -391,58 +383,51 @@ func (ms *mapState) lookup(key Key) (mapStateEntry, bool) { } // Deny by default if no matches are found - return mapStateEntry{MapStateEntry: types.DenyEntry()}, false + return mapStateEntry{MapStateEntry: types.DenyEntry(), derivedFromRules: NilRuleOrigin}, false } func (ms *mapState) Len() int { return len(ms.entries) } -// mapSteteEntry is the entry type with additional internal bookkeping of the relation between +// mapStateEntry is the entry type with additional internal bookkeping of the relation between // explicitly and implicitly added entries. type mapStateEntry struct { MapStateEntry // derivedFromRules tracks the policy rules this entry derives from. - // In sorted order. - derivedFromRules labels.LabelArrayList - - // owners collects the keys in the map and selectors in the policy that require this key to be present. - // TODO: keep track which selector needed the entry to be deny, redirect, or just allow. - owners set.Set[MapStateOwner] + // Must be initialized explicitly, zero-intialization does not work with unique.Handle[]. + derivedFromRules ruleOrigin } -// newMapStateEntry creates a map state entry. If redirect is true, the -// caller is expected to replace the ProxyPort field before it is added to -// the actual BPF map. -// 'cs' is used to keep track of which policy selectors need this entry. If it is 'nil' this entry -// will become sticky and cannot be completely removed via incremental updates. Even in this case -// the entry may be overridden or removed by a deny entry. -func newMapStateEntry(cs MapStateOwner, derivedFrom labels.LabelArrayList, proxyPort uint16, priority uint8, deny bool, authReq AuthRequirement) mapStateEntry { - return NewMapStateEntry(types.NewMapStateEntry(deny, proxyPort, priority, authReq), derivedFrom, cs) +// newMapStateEntry creates a map state entry. +func newMapStateEntry(derivedFrom ruleOrigin, proxyPort uint16, priority uint8, deny bool, authReq AuthRequirement) mapStateEntry { + return mapStateEntry{ + MapStateEntry: types.NewMapStateEntry(deny, proxyPort, priority, authReq), + derivedFromRules: derivedFrom, + } } -// newAllowEntryWithLabels creates an allow entry with the specified labels and a 'nil' owner. +// newAllowEntryWithLabels creates an allow entry with the specified labels. // Used for adding allow-all entries when policy enforcement is not wanted. func newAllowEntryWithLabels(lbls labels.LabelArray) mapStateEntry { - return newMapStateEntry(nil, labels.LabelArrayList{lbls}, 0, 0, false, NoAuthRequirement) + return newMapStateEntry(singleRuleOrigin(makeStringLabels(lbls)), 0, 0, false, NoAuthRequirement) } -func NewMapStateEntry(e MapStateEntry, derivedFrom labels.LabelArrayList, owners ...MapStateOwner) mapStateEntry { +func NewMapStateEntry(e MapStateEntry) mapStateEntry { return mapStateEntry{ MapStateEntry: e, - derivedFromRules: derivedFrom, - owners: set.NewSet(owners...), + derivedFromRules: NilRuleOrigin, } } -func (e *mapStateEntry) GetRuleLabels() labels.LabelArrayList { - return e.derivedFromRules +func emptyMapState() mapState { + return newMapState(0) } -func newMapState() mapState { +func newMapState(size int) mapState { return mapState{ - entries: make(mapStateMap), + entries: make(mapStateMap, size), trie: bitlpm.NewTrie[types.LPMKey, IDSet](types.MapStatePrefixLen), } } @@ -486,19 +471,6 @@ func (ms *mapState) updateExisting(k Key, v mapStateEntry) { ms.entries[k] = v } -// equalsWithLabels determines if this mapState is equal to the -// argument MapState. Only compares the exported MapStateEntry and derivedFromLabels. -// Only used for testing. -func (msA *mapState) equalsWithLabels(msB *mapState) bool { - if msA.Len() != msB.Len() { - return false - } - return msA.forEach(func(kA Key, vA mapStateEntry) bool { - vB, ok := msB.get(kA) - return ok && (&vB).DatapathAndDerivedFromEqual(&vA) - }) -} - // Equals determines if this MapState is equal to the // argument (exported) MapStateMap // Only used for testing from other packages. @@ -520,10 +492,33 @@ func (msA *mapState) Equal(msB *mapState) bool { } return msA.forEach(func(kA Key, vA mapStateEntry) bool { vB, ok := msB.get(kA) - return ok && (&vB).deepEqual(&vA) + return ok && (&vB).Equal(&vA) }) } +// Diff returns the string of differences between 'obtained' and 'expected' prefixed with +// '+ ' or '- ' for obtaining something unexpected, or not obtaining the expected, respectively. +// For use in debugging from other packages. +func (obtained MapStateMap) Diff(expected MapStateMap) (res string) { + res += "Missing (-), Unexpected (+):\n" + for kE, vE := range expected { + if vO, ok := obtained[kE]; ok { + if vO != vE { + res += "- " + kE.String() + ": " + vE.String() + "\n" + res += "+ " + kE.String() + ": " + vO.String() + "\n" + } + } else { + res += "- " + kE.String() + ": " + vE.String() + "\n" + } + } + for kO, vO := range obtained { + if _, ok := expected[kO]; !ok { + res += "+ " + kO.String() + ": " + vO.String() + "\n" + } + } + return res +} + // Diff returns the string of differences between 'obtained' and 'expected' prefixed with // '+ ' or '- ' for obtaining something unexpected, or not obtaining the expected, respectively. // For use in debugging from other packages. @@ -555,7 +550,7 @@ func (obtained *mapState) diff(expected *mapState) (res string) { res += "Missing (-), Unexpected (+):\n" expected.forEach(func(kE Key, vE mapStateEntry) bool { if vO, ok := obtained.get(kE); ok { - if !(&vO).deepEqual(&vE) { + if !(&vO).Equal(&vE) { res += "- " + kE.String() + ": " + vE.String() + "\n" res += "+ " + kE.String() + ": " + vO.String() + "\n" } @@ -581,49 +576,29 @@ func (ms mapState) String() (res string) { return res } -// DatapathAndDerivedFromEqual returns true of two entries are equal in the datapath's PoV, -// i.e., IsDeny, ProxyPort and AuthType are the same for both entries, and the DerivedFromRules -// fields are also equal. +// Equal returns true of two entries are equal. // This is used for testing only via mapState.Equal and mapState.Diff. -func (e *mapStateEntry) DatapathAndDerivedFromEqual(o *mapStateEntry) bool { +func (e *mapStateEntry) Equal(o *mapStateEntry) bool { if e == nil || o == nil { return e == o } - return e.MapStateEntry == o.MapStateEntry && e.derivedFromRules.DeepEqual(&o.derivedFromRules) -} - -// DeepEqual is a manually generated deepequal function, deeply comparing the -// receiver with other. in must be non-nil. -// Defined manually due to deepequal-gen not supporting interface types. -func (e *mapStateEntry) deepEqual(o *mapStateEntry) bool { - if !e.DatapathAndDerivedFromEqual(o) { - return false - } - - if !e.owners.Equal(o.owners) { - return false - } - - return true + return e.MapStateEntry == o.MapStateEntry && e.derivedFromRules == o.derivedFromRules } // String returns a string representation of the MapStateEntry func (e mapStateEntry) String() string { - return e.MapStateEntry.String() + - ",derivedFromRules=" + fmt.Sprintf("%v", e.derivedFromRules) + - ",owners=" + e.owners.String() + return e.MapStateEntry.String() + ",derivedFromRules=" + e.derivedFromRules.Value() } // addKeyWithChanges adds a 'key' with value 'entry' to 'keys' keeping track of incremental changes in 'adds' and 'deletes', and any changed or removed old values in 'old', if not nil. func (ms *mapState) addKeyWithChanges(key Key, entry mapStateEntry, changes ChangeState) bool { - // Keep all owners that need this entry so that it is deleted only if all the owners delete their contribution var datapathEqual bool oldEntry, exists := ms.get(key) // Only merge if both old and new are allows or denies if exists && oldEntry.IsDeny() == entry.IsDeny() { // Do nothing if entries are equal - if entry.deepEqual(&oldEntry) { + if entry.Equal(&oldEntry) { return false // nothing to do } @@ -635,9 +610,8 @@ func (ms *mapState) addKeyWithChanges(key Key, entry mapStateEntry, changes Chan datapathEqual = oldEntry.MapStateEntry == entry.MapStateEntry oldEntry.MapStateEntry.Merge(entry.MapStateEntry) - oldEntry.owners.Merge(entry.owners) - if len(entry.derivedFromRules) > 0 { - oldEntry.derivedFromRules.MergeSorted(entry.derivedFromRules) + if entry.derivedFromRules.Value() != "" { + oldEntry.derivedFromRules.Merge(entry.derivedFromRules) } ms.updateExisting(key, oldEntry) @@ -669,34 +643,11 @@ func (ms *mapState) addKeyWithChanges(key Key, entry mapStateEntry, changes Chan return true } -// deleteKeyWithChanges deletes a 'key' from 'keys' keeping track of incremental changes in 'adds' -// and 'deletes'. -// The key is unconditionally deleted if 'owner' is nil, otherwise only the contribution of this -// 'owner' is removed. -func (ms *mapState) deleteKeyWithChanges(owner MapStateOwner, key Key, changes ChangeState) { +// deleteKeyWithChanges deletes a 'key' from 'ms' keeping track of incremental changes in 'changes' +func (ms *mapState) deleteKeyWithChanges(key Key, changes ChangeState) { if entry, exists := ms.get(key); exists { // Save old value before any changes, if desired - oldAdded := changes.insertOldIfNotExists(key, entry) - if owner != nil { - if entry.owners.Has(owner) { - // remove this owner from entry's owners - changed := entry.owners.Remove(owner) - // key is not deleted if other owners still need it - if entry.owners.Len() > 0 { - if changed { - // re-insert entry due to owner change - ms.updateExisting(key, entry) - } - return - } - } else { - // 'owner' was not found, do not change anything - if oldAdded { - delete(changes.old, key) - } - return - } - } + changes.insertOldIfNotExists(key, entry) if changes.Deletes != nil { changes.Deletes[key] = struct{}{} @@ -770,7 +721,7 @@ func (ms *mapState) insertWithChanges(newKey Key, newEntry mapStateEntry, featur // Delete covered allows and denies with a different key for k, v := range ms.NarrowerOrEqualKeys(newKey) { if !v.IsDeny() || k != newKey { - ms.deleteKeyWithChanges(nil, k, changes) + ms.deleteKeyWithChanges(k, changes) } } } else { @@ -791,7 +742,7 @@ func (ms *mapState) insertWithChanges(newKey Key, newEntry mapStateEntry, featur if features.contains(redirectRules) { for k, v := range ms.NarrowerOrEqualKeys(newKey) { if !v.IsDeny() && v.ProxyPortPriority < newEntry.ProxyPortPriority { - ms.deleteKeyWithChanges(nil, k, changes) + ms.deleteKeyWithChanges(k, changes) } } } @@ -871,10 +822,6 @@ func (changes *ChangeState) insertOldIfNotExists(key Key, entry mapStateEntry) b // Only insert the old entry if the entry was not first added on this round of // changes. if _, added := changes.Adds[key]; !added { - // Clone to keep this entry separate from the one that may remain in 'keys' - entry.derivedFromRules = slices.Clone(entry.derivedFromRules) - entry.owners = entry.owners.Clone() - changes.old[key] = entry return true } @@ -1011,8 +958,7 @@ func (mc *MapChanges) consumeMapChanges(p *EndpointPolicy, features policyFeatur } else { // Delete the contribution of this cs to the key and collect incremental // changes - cs, _ := entry.owners.Get() // get the sole selector - p.policyMapState.deleteKeyWithChanges(cs, key, changes) + p.policyMapState.deleteKeyWithChanges(key, changes) } } diff --git a/vendor/github.com/cilium/cilium/pkg/policy/repository.go b/vendor/github.com/cilium/cilium/pkg/policy/repository.go index eca9a31c25..b7433b6afe 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/repository.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/repository.go @@ -4,12 +4,10 @@ package policy import ( - "cmp" "context" "encoding/json" "fmt" "maps" - "slices" "sync/atomic" cilium "github.com/cilium/proxy/go/cilium/api" @@ -119,7 +117,7 @@ type PolicyRepository interface { // This is used to skip policy calculation when a certain revision delta is // known to not affect the given identity. Pass a skipRevision of 0 to force // calculation. - GetSelectorPolicy(id *identity.Identity, skipRevision uint64, stats GetPolicyStatistics) (SelectorPolicy, uint64) + GetSelectorPolicy(id *identity.Identity, skipRevision uint64, stats GetPolicyStatistics) (SelectorPolicy, uint64, error) GetRevision() uint64 GetRulesList() *models.Policy @@ -171,26 +169,6 @@ type Repository struct { metricsManager api.PolicyMetrics } -// Lock acquiers the lock of the whole policy tree. -func (p *Repository) Lock() { - p.mutex.Lock() -} - -// Unlock releases the lock of the whole policy tree. -func (p *Repository) Unlock() { - p.mutex.Unlock() -} - -// RLock acquiers the read lock of the whole policy tree. -func (p *Repository) RLock() { - p.mutex.RLock() -} - -// RUnlock releases the read lock of the whole policy tree. -func (p *Repository) RUnlock() { - p.mutex.RUnlock() -} - // GetSelectorCache() returns the selector cache used by the Repository func (p *Repository) GetSelectorCache() *SelectorCache { return p.selectorCache @@ -273,135 +251,6 @@ func (state *traceState) trace(rules int, ctx *SearchContext) { } } -// ResolveL4IngressPolicy resolves the L4 ingress policy for a set of endpoints -// by searching the policy repository for `PortRule` rules that are attached to -// a `Rule` where the EndpointSelector matches `ctx.To`. `ctx.From` takes no effect and -// is ignored in the search. If multiple `PortRule` rules are found, all rules -// are merged together. If rules contains overlapping port definitions, the first -// rule found in the repository takes precedence. -// -// TODO: Coalesce l7 rules? -// -// Caller must release resources by calling Detach() on the returned map! -// -// NOTE: This is only called from unit tests, but from multiple packages. -func (p *Repository) ResolveL4IngressPolicy(ctx *SearchContext) (L4PolicyMap, error) { - policyCtx := policyContext{ - repo: p, - ns: ctx.To.Get(labels.LabelSourceK8sKeyPrefix + k8sConst.PodNamespaceLabel), - } - rules := make(ruleSlice, 0, len(p.rules)) - for _, rule := range p.rules { - rules = append(rules, rule) - } - // Sort for unit tests - slices.SortFunc[ruleSlice](rules, func(a, b *rule) int { - return cmp.Compare(a.key.idx, b.key.idx) - }) - result, err := rules.resolveL4IngressPolicy(&policyCtx, ctx) - if err != nil { - return nil, err - } - - return result, nil -} - -// ResolveL4EgressPolicy resolves the L4 egress policy for a set of endpoints -// by searching the policy repository for `PortRule` rules that are attached to -// a `Rule` where the EndpointSelector matches `ctx.From`. `ctx.To` takes no effect and -// is ignored in the search. If multiple `PortRule` rules are found, all rules -// are merged together. If rules contains overlapping port definitions, the first -// rule found in the repository takes precedence. -// -// Caller must release resources by calling Detach() on the returned map! -// -// NOTE: This is only called from unit tests, but from multiple packages. -func (p *Repository) ResolveL4EgressPolicy(ctx *SearchContext) (L4PolicyMap, error) { - policyCtx := policyContext{ - repo: p, - ns: ctx.From.Get(labels.LabelSourceK8sKeyPrefix + k8sConst.PodNamespaceLabel), - } - rules := make(ruleSlice, 0, len(p.rules)) - for _, rule := range p.rules { - rules = append(rules, rule) - } - slices.SortFunc[ruleSlice](rules, func(a, b *rule) int { - return cmp.Compare(a.key.idx, b.key.idx) - }) - result, err := rules.resolveL4EgressPolicy(&policyCtx, ctx) - if err != nil { - return nil, err - } - - return result, nil -} - -// AllowsIngressRLocked evaluates the policy repository for the provided search -// context and returns the verdict for ingress. If no matching policy allows for -// the connection, the request will be denied. The policy repository mutex must -// be held. -// -// NOTE: This is only called from unit tests, but from multiple packages. -func (p *Repository) AllowsIngressRLocked(ctx *SearchContext) api.Decision { - // Lack of DPorts in the SearchContext means L3-only search - if len(ctx.DPorts) == 0 { - newCtx := *ctx - newCtx.DPorts = []*models.Port{{ - Port: 0, - Protocol: models.PortProtocolANY, - }} - ctx = &newCtx - } - - ctx.PolicyTrace("Tracing %s", ctx.String()) - ingressPolicy, err := p.ResolveL4IngressPolicy(ctx) - if err != nil { - log.WithError(err).Warn("Evaluation error while resolving L4 ingress policy") - } - - verdict := api.Denied - if err == nil && ingressPolicy.Len() > 0 { - verdict = ingressPolicy.IngressCoversContext(ctx) - } - - ctx.PolicyTrace("Ingress verdict: %s", verdict.String()) - ingressPolicy.Detach(p.GetSelectorCache()) - - return verdict -} - -// AllowsEgressRLocked evaluates the policy repository for the provided search -// context and returns the verdict. If no matching policy allows for the -// connection, the request will be denied. The policy repository mutex must be -// held. -// -// NOTE: This is only called from unit tests, but from multiple packages. -func (p *Repository) AllowsEgressRLocked(ctx *SearchContext) api.Decision { - // Lack of DPorts in the SearchContext means L3-only search - if len(ctx.DPorts) == 0 { - newCtx := *ctx - newCtx.DPorts = []*models.Port{{ - Port: 0, - Protocol: models.PortProtocolANY, - }} - ctx = &newCtx - } - - ctx.PolicyTrace("Tracing %s\n", ctx.String()) - egressPolicy, err := p.ResolveL4EgressPolicy(ctx) - if err != nil { - log.WithError(err).Warn("Evaluation error while resolving L4 egress policy") - } - verdict := api.Denied - if err == nil && egressPolicy.Len() > 0 { - verdict = egressPolicy.EgressCoversContext(ctx) - } - - ctx.PolicyTrace("Egress verdict: %s", verdict.String()) - egressPolicy.Detach(p.GetSelectorCache()) - return verdict -} - func (p *Repository) Search(lbls labels.LabelArray) (api.Rules, uint64) { p.mutex.RLock() defer p.mutex.RUnlock() @@ -484,7 +333,7 @@ func (p *Repository) newRule(apiRule api.Rule, key ruleKey) *rule { Rule: apiRule, key: key, } - r.subjectSelector, _ = p.selectorCache.AddIdentitySelector(r, r.Labels, *r.getSelector()) + r.subjectSelector, _ = p.selectorCache.AddIdentitySelector(r, makeStringLabels(r.Labels), *r.getSelector()) return r } @@ -519,36 +368,6 @@ func (p *Repository) Iterate(f func(rule *api.Rule)) { } } -// deleteByLabelsLocked deletes all rules in the policy repository which -// contain the specified labels. Returns the revision of the policy repository -// after deleting the rules, as well as now many rules were deleted. -func (p *Repository) deleteByLabelsLocked(lbls labels.LabelArray) (ruleSlice, uint64, int) { - deletedRules := ruleSlice{} - - for key, r := range p.rules { - if r.Labels.Contains(lbls) { - deletedRules = append(deletedRules, r) - p.del(key) - } - } - l := len(deletedRules) - - if l > 0 { - p.BumpRevision() - } - - return deletedRules, p.GetRevision(), l -} - -// deleteByLabels deletes all rules in the policy repository which contain the -// specified labels -func (p *Repository) deleteByLabels(lbls labels.LabelArray) (uint64, int) { - p.mutex.Lock() - defer p.mutex.Unlock() - _, rev, numDeleted := p.deleteByLabelsLocked(lbls) - return rev, numDeleted -} - // JSONMarshalRules returns a slice of policy rules as string in JSON // representation func JSONMarshalRules(rules api.Rules) string { @@ -559,37 +378,6 @@ func JSONMarshalRules(rules api.Rules) string { return string(b) } -// GetRulesMatching returns whether any of the rules in a repository contain a -// rule with labels matching the labels in the provided LabelArray. -// -// Must be called with p.mutex held -func (p *Repository) GetRulesMatching(lbls labels.LabelArray) (ingressMatch bool, egressMatch bool) { - ingressMatch = false - egressMatch = false - for _, r := range p.rules { - rulesMatch := r.getSelector().Matches(lbls) - if rulesMatch { - if len(r.Ingress) > 0 { - ingressMatch = true - } - if len(r.IngressDeny) > 0 { - ingressMatch = true - } - if len(r.Egress) > 0 { - egressMatch = true - } - if len(r.EgressDeny) > 0 { - egressMatch = true - } - } - - if ingressMatch && egressMatch { - return - } - } - return -} - // GetRevision returns the revision of the policy repository func (p *Repository) GetRevision() uint64 { return p.revision.Load() @@ -826,10 +614,10 @@ func wildcardRule(lbls labels.LabelArray, ingress bool) *rule { // This is used to skip policy calculation when a certain revision delta is // known to not affect the given identity. Pass a skipRevision of 0 to force // calculation. -func (r *Repository) GetSelectorPolicy(id *identity.Identity, skipRevision uint64, stats GetPolicyStatistics) (SelectorPolicy, uint64) { +func (r *Repository) GetSelectorPolicy(id *identity.Identity, skipRevision uint64, stats GetPolicyStatistics) (SelectorPolicy, uint64, error) { stats.WaitingForPolicyRepository().Start() - r.RLock() - defer r.RUnlock() + r.mutex.RLock() + defer r.mutex.RUnlock() stats.WaitingForPolicyRepository().End(true) rev := r.GetRevision() @@ -837,7 +625,7 @@ func (r *Repository) GetSelectorPolicy(id *identity.Identity, skipRevision uint6 // Do we already have a given revision? // If so, skip calculation. if skipRevision >= rev { - return nil, rev + return nil, rev, nil } stats.SelectorPolicyCalculation().Start() @@ -851,7 +639,7 @@ func (r *Repository) GetSelectorPolicy(id *identity.Identity, skipRevision uint6 stats.SelectorPolicyCalculation().Reset() } - return sp, rev + return sp, rev, err } // ReplaceByResource replaces all rules by resource, returning the complete set of affected endpoints. @@ -863,8 +651,8 @@ func (p *Repository) ReplaceByResource(rules api.Rules, resource ipcachetypes.Re return } - p.Lock() - defer p.Unlock() + p.mutex.Lock() + defer p.mutex.Unlock() affectedIDs = &set.Set[identity.NumericIdentity]{} oldRules := maps.Clone(p.rulesByResource[resource]) // need to clone as `p.del()` mutates this @@ -901,8 +689,8 @@ func (p *Repository) ReplaceByResource(rules api.Rules, resource ipcachetypes.Re // where the "key" is a list of labels, possibly multiple, that should be removed before // installing the new rules. func (p *Repository) ReplaceByLabels(rules api.Rules, searchLabelsList []labels.LabelArray) (affectedIDs *set.Set[identity.NumericIdentity], rev uint64, oldRuleCnt int) { - p.Lock() - defer p.Unlock() + p.mutex.Lock() + defer p.mutex.Unlock() var oldRules []*rule affectedIDs = &set.Set[identity.NumericIdentity]{} diff --git a/vendor/github.com/cilium/cilium/pkg/policy/resolve.go b/vendor/github.com/cilium/cilium/pkg/policy/resolve.go index f6ad13059c..2c137ab80a 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/resolve.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/resolve.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "iter" + "runtime" "github.com/sirupsen/logrus" @@ -112,7 +113,8 @@ func (p *EndpointPolicy) LookupRedirectPort(ingress bool, protocol string, port // 'key' must not have a wildcard identity or port. func (p *EndpointPolicy) Lookup(key Key) (MapStateEntry, labels.LabelArrayList, bool) { entry, found := p.policyMapState.lookup(key) - return entry.MapStateEntry, entry.derivedFromRules, found + lbls := labels.LabelArrayListFromString(entry.derivedFromRules.Value()) + return entry.MapStateEntry, lbls, found } // PolicyOwner is anything which consumes a EndpointPolicy. @@ -121,6 +123,7 @@ type PolicyOwner interface { GetNamedPort(ingress bool, name string, proto u8proto.U8proto) uint16 PolicyDebug(fields logrus.Fields, msg string) IsHost() bool + MapStateSize() int } // newSelectorPolicy returns an empty selectorPolicy stub. @@ -177,7 +180,7 @@ func (p *selectorPolicy) DistillPolicy(policyOwner PolicyOwner, redirects map[st calculatedPolicy = &EndpointPolicy{ selectorPolicy: p, VersionHandle: version, - policyMapState: newMapState(), + policyMapState: newMapState(policyOwner.MapStateSize()), policyMapChanges: MapChanges{ firstVersion: version.Version(), }, @@ -222,7 +225,8 @@ func (p *EndpointPolicy) Detach() { // in case the call was missed previouly if p.Ready() == nil { // succeeded, so it was missed previously - log.Warningf("Detach: EndpointPolicy was not marked as Ready") + _, file, line, _ := runtime.Caller(1) + log.Warningf("Detach: EndpointPolicy was not marked as Ready (%s:%d)", file, line) } // Also release the version handle held for incremental updates, if any. // This must be done after the removeUser() call above, so that we do not get a new version @@ -242,13 +246,13 @@ var errMissingKey = errors.New("Key not found") // GetRuleLabels returns the list of labels of the rules that contributed // to the entry at this key. -// The returned LabelArrayList is shallow-copied and therefore must not be mutated. -func (p *EndpointPolicy) GetRuleLabels(k Key) (labels.LabelArrayList, error) { +// The returned string is the string representation of a LabelArrayList. +func (p *EndpointPolicy) GetRuleLabels(k Key) (string, error) { entry, ok := p.policyMapState.get(k) if !ok { - return nil, errMissingKey + return "", errMissingKey } - return entry.GetRuleLabels(), nil + return entry.derivedFromRules.Value(), nil } func (p *EndpointPolicy) Entries() iter.Seq2[Key, MapStateEntry] { @@ -389,12 +393,7 @@ func (l4policy L4DirectionPolicy) forEachRedirectFilter(yield func(*L4Filter, *P return ok } -// ConsumeMapChanges transfers the changes from MapChanges to the caller. -// SelectorCache used as Identities interface which only has GetPrefix() that needs no lock. -// Endpoints explicitly wait for a WaitGroup signaling completion of AccumulatePolicyMapChanges -// calls before calling ConsumeMapChanges so that if we see any partial changes here, there will be -// another call after to cover for the rest. -// PolicyOwner (aka Endpoint) is locked during this call. +// ConsumeMapChanges applies accumulated MapChanges to EndpointPolicy 'p' and returns a symmary of changes. // Caller is responsible for calling the returned 'closer' to release resources held for the new version! // 'closer' may not be called while selector cache is locked! func (p *EndpointPolicy) ConsumeMapChanges() (closer func(), changes ChangeState) { @@ -431,6 +430,6 @@ func (p *EndpointPolicy) ConsumeMapChanges() (closer func(), changes ChangeState func NewEndpointPolicy(repo PolicyRepository) *EndpointPolicy { return &EndpointPolicy{ selectorPolicy: newSelectorPolicy(repo.GetSelectorCache()), - policyMapState: newMapState(), + policyMapState: emptyMapState(), } } diff --git a/vendor/github.com/cilium/cilium/pkg/policy/rule.go b/vendor/github.com/cilium/cilium/pkg/policy/rule.go index 29715ea578..e239bb61a3 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/rule.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/rule.go @@ -333,7 +333,7 @@ func mergePortProto(ctx *SearchContext, existingFilter, filterToMerge *L4Filter, // forwarded to the proxy for endpoints matching those labels, but the proxy // will allow all such traffic. func mergeIngressPortProto(policyCtx PolicyContext, ctx *SearchContext, endpoints api.EndpointSelectorSlice, auth *api.Authentication, hostWildcardL7 []string, - r api.Ports, p api.PortProtocol, proto api.L4Proto, ruleLabels labels.LabelArray, resMap L4PolicyMap) (int, error) { + r api.Ports, p api.PortProtocol, proto api.L4Proto, ruleLabels stringLabels, resMap L4PolicyMap) (int, error) { // Create a new L4Filter filterToMerge, err := createL4IngressFilter(policyCtx, endpoints, auth, hostWildcardL7, r, p, proto, ruleLabels) if err != nil { @@ -400,7 +400,7 @@ func rulePortsCoverSearchContext(ports []api.PortProtocol, ctx *SearchContext) b return false } -func mergeIngress(policyCtx PolicyContext, ctx *SearchContext, fromEndpoints api.EndpointSelectorSlice, auth *api.Authentication, toPorts, icmp api.PortsIterator, ruleLabels labels.LabelArray, resMap L4PolicyMap) (int, error) { +func mergeIngress(policyCtx PolicyContext, ctx *SearchContext, fromEndpoints api.EndpointSelectorSlice, auth *api.Authentication, toPorts, icmp api.PortsIterator, ruleLabels stringLabels, resMap L4PolicyMap) (int, error) { found := 0 // short-circuit if no endpoint is selected @@ -578,7 +578,7 @@ func (r *rule) resolveIngressPolicy( } for _, ingressRule := range r.Ingress { fromEndpoints := ingressRule.GetSourceEndpointSelectorsWithRequirements(requirements) - cnt, err := mergeIngress(policyCtx, ctx, fromEndpoints, ingressRule.Authentication, ingressRule.ToPorts, ingressRule.ICMPs, r.Rule.Labels.DeepCopy(), result) + cnt, err := mergeIngress(policyCtx, ctx, fromEndpoints, ingressRule.Authentication, ingressRule.ToPorts, ingressRule.ICMPs, makeStringLabels(r.Rule.Labels), result) if err != nil { return nil, err } @@ -593,7 +593,7 @@ func (r *rule) resolveIngressPolicy( }() for _, ingressRule := range r.IngressDeny { fromEndpoints := ingressRule.GetSourceEndpointSelectorsWithRequirements(requirementsDeny) - cnt, err := mergeIngress(policyCtx, ctx, fromEndpoints, nil, ingressRule.ToPorts, ingressRule.ICMPs, r.Rule.Labels.DeepCopy(), result) + cnt, err := mergeIngress(policyCtx, ctx, fromEndpoints, nil, ingressRule.ToPorts, ingressRule.ICMPs, makeStringLabels(r.Rule.Labels), result) if err != nil { return nil, err } @@ -643,7 +643,7 @@ func (r *rule) getSubjects() []identity.NumericIdentity { // ****************** EGRESS POLICY ****************** -func mergeEgress(policyCtx PolicyContext, ctx *SearchContext, toEndpoints api.EndpointSelectorSlice, auth *api.Authentication, toPorts, icmp api.PortsIterator, ruleLabels labels.LabelArray, resMap L4PolicyMap, fqdns api.FQDNSelectorSlice) (int, error) { +func mergeEgress(policyCtx PolicyContext, ctx *SearchContext, toEndpoints api.EndpointSelectorSlice, auth *api.Authentication, toPorts, icmp api.PortsIterator, ruleLabels stringLabels, resMap L4PolicyMap, fqdns api.FQDNSelectorSlice) (int, error) { found := 0 // short-circuit if no endpoint is selected @@ -768,7 +768,7 @@ func mergeEgress(policyCtx PolicyContext, ctx *SearchContext, toEndpoints api.En // being merged has conflicting L7 rules with those already in the provided // L4PolicyMap for the specified port-protocol tuple, it returns an error. func mergeEgressPortProto(policyCtx PolicyContext, ctx *SearchContext, endpoints api.EndpointSelectorSlice, auth *api.Authentication, r api.Ports, p api.PortProtocol, - proto api.L4Proto, ruleLabels labels.LabelArray, resMap L4PolicyMap, fqdns api.FQDNSelectorSlice) (int, error) { + proto api.L4Proto, ruleLabels stringLabels, resMap L4PolicyMap, fqdns api.FQDNSelectorSlice) (int, error) { // Create a new L4Filter filterToMerge, err := createL4EgressFilter(policyCtx, endpoints, auth, r, p, proto, ruleLabels, fqdns) if err != nil { @@ -806,7 +806,7 @@ func (r *rule) resolveEgressPolicy( } for _, egressRule := range r.Egress { toEndpoints := egressRule.GetDestinationEndpointSelectorsWithRequirements(requirements) - cnt, err := mergeEgress(policyCtx, ctx, toEndpoints, egressRule.Authentication, egressRule.ToPorts, egressRule.ICMPs, r.Rule.Labels.DeepCopy(), result, egressRule.ToFQDNs) + cnt, err := mergeEgress(policyCtx, ctx, toEndpoints, egressRule.Authentication, egressRule.ToPorts, egressRule.ICMPs, makeStringLabels(r.Rule.Labels), result, egressRule.ToFQDNs) if err != nil { return nil, err } @@ -821,7 +821,7 @@ func (r *rule) resolveEgressPolicy( }() for _, egressRule := range r.EgressDeny { toEndpoints := egressRule.GetDestinationEndpointSelectorsWithRequirements(requirementsDeny) - cnt, err := mergeEgress(policyCtx, ctx, toEndpoints, nil, egressRule.ToPorts, egressRule.ICMPs, r.Rule.Labels.DeepCopy(), result, nil) + cnt, err := mergeEgress(policyCtx, ctx, toEndpoints, nil, egressRule.ToPorts, egressRule.ICMPs, makeStringLabels(r.Rule.Labels), result, nil) if err != nil { return nil, err } diff --git a/vendor/github.com/cilium/cilium/pkg/policy/selectorcache.go b/vendor/github.com/cilium/cilium/pkg/policy/selectorcache.go index 5e792c2f43..71e58a1f88 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/selectorcache.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/selectorcache.go @@ -322,7 +322,7 @@ type identityNotifier interface { // AddFQDNSelector adds the given api.FQDNSelector in to the selector cache. If // an identical EndpointSelector has already been cached, the corresponding // types.CachedSelector is returned, otherwise one is created and added to the cache. -func (sc *SelectorCache) AddFQDNSelector(user CachedSelectionUser, lbls labels.LabelArray, fqdnSelec api.FQDNSelector) (cachedSelector types.CachedSelector, added bool) { +func (sc *SelectorCache) AddFQDNSelector(user CachedSelectionUser, lbls stringLabels, fqdnSelec api.FQDNSelector) (cachedSelector types.CachedSelector, added bool) { key := fqdnSelec.String() sc.mutex.Lock() @@ -345,7 +345,7 @@ func (sc *SelectorCache) AddFQDNSelector(user CachedSelectionUser, lbls labels.L } // must hold lock for writing -func (sc *SelectorCache) addSelectorLocked(user CachedSelectionUser, lbls labels.LabelArray, key string, source selectorSource) (types.CachedSelector, bool) { +func (sc *SelectorCache) addSelectorLocked(user CachedSelectionUser, lbls stringLabels, key string, source selectorSource) (types.CachedSelector, bool) { idSel := &identitySelector{ key: key, users: make(map[CachedSelectionUser]struct{}), @@ -393,7 +393,7 @@ func (sc *SelectorCache) FindCachedIdentitySelector(selector api.EndpointSelecto // selector cache. If an identical EndpointSelector has already been // cached, the corresponding types.CachedSelector is returned, otherwise one // is created and added to the cache. -func (sc *SelectorCache) AddIdentitySelector(user types.CachedSelectionUser, lbls labels.LabelArray, selector api.EndpointSelector) (cachedSelector types.CachedSelector, added bool) { +func (sc *SelectorCache) AddIdentitySelector(user types.CachedSelectionUser, lbls stringLabels, selector api.EndpointSelector) (cachedSelector types.CachedSelector, added bool) { // The key returned here may be different for equivalent // labelselectors, if the selector's requirements are stored // in different orders. When this happens we'll be tracking @@ -498,7 +498,14 @@ func (sc *SelectorCache) CanSkipUpdate(added, deleted identity.IdentityMap) bool // Caller should Wait() on the returned sync.WaitGroup before triggering any // policy updates. Policy updates may need Endpoint locks, so this Wait() can // deadlock if the caller is holding any endpoint locks. -func (sc *SelectorCache) UpdateIdentities(added, deleted identity.IdentityMap, wg *sync.WaitGroup) { +// +// Incremental deletes of mutated identities are not sent to the users, as that could +// lead to deletion of policy map entries while other selectors may still select the mutated +// identity. +// In this case the return value is 'true' and the caller should trigger policy updates on all +// endpoints to remove the affected identity only from selectors that no longer select the mutated +// identity. +func (sc *SelectorCache) UpdateIdentities(added, deleted identity.IdentityMap, wg *sync.WaitGroup) (mutated bool) { sc.mutex.Lock() defer sc.mutex.Unlock() @@ -581,8 +588,13 @@ func (sc *SelectorCache) UpdateIdentities(added, deleted identity.IdentityMap, w adds = append(adds, numericID) idSel.cachedSelections[numericID] = struct{}{} } else if !matches && exists { - // identity was mutated and no longer matches - dels = append(dels, numericID) + // Identity was mutated and no longer matches, the identity + // is deleted from the cached selections, but is not sent to + // users as a deletion. Instead, we return 'mutated = true' + // telling the caller to trigger forced policy updates on + // all endpoints to recompute the policy as if the mutated + // identity was never selected by the affected selector. + mutated = true delete(idSel.cachedSelections, numericID) } } @@ -609,4 +621,5 @@ func (sc *SelectorCache) UpdateIdentities(added, deleted identity.IdentityMap, w txn.Commit() } + return mutated } diff --git a/vendor/github.com/cilium/cilium/pkg/policy/selectorcache_selector.go b/vendor/github.com/cilium/cilium/pkg/policy/selectorcache_selector.go index cbe5dbc3da..332396e1e6 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/selectorcache_selector.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/selectorcache_selector.go @@ -63,7 +63,7 @@ type identitySelector struct { selections versioned.Value[identity.NumericIdentitySlice] users map[CachedSelectionUser]struct{} cachedSelections map[identity.NumericIdentity]struct{} - metadataLbls labels.LabelArray + metadataLbls stringLabels } func (i *identitySelector) MaySelectPeers() bool { @@ -198,7 +198,7 @@ func (i *identitySelector) GetSelections(version *versioned.VersionHandle) ident } func (i *identitySelector) GetMetadataLabels() labels.LabelArray { - return i.metadataLbls + return labels.LabelArrayFromString(string(i.metadataLbls.Value())) } // Selects return 'true' if the CachedSelector selects the given diff --git a/vendor/github.com/cilium/cilium/pkg/policy/types/types.go b/vendor/github.com/cilium/cilium/pkg/policy/types/types.go index 426c4799d6..9847694025 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/types/types.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/types/types.go @@ -246,10 +246,4 @@ func (k LPMKey) BitValueAt(i uint) uint8 { } } -// Value implements the Value method for the -// bitlpm.Key interface. -func (k LPMKey) Value() LPMKey { - return k -} - type Keys map[Key]struct{} diff --git a/vendor/github.com/cilium/cilium/pkg/source/source.go b/vendor/github.com/cilium/cilium/pkg/source/source.go index 0406349f65..e24601bc56 100644 --- a/vendor/github.com/cilium/cilium/pkg/source/source.go +++ b/vendor/github.com/cilium/cilium/pkg/source/source.go @@ -4,6 +4,8 @@ package source import ( + "slices" + "github.com/cilium/hive/cell" ) @@ -63,6 +65,9 @@ const ( // Sources is a priority-sorted slice of sources. type Sources []Source +// The ordering in defaultSources is critical and it should only be changed +// with care because as it determines the behavior of AllowOverwrite(). +// It is from highest precedence to lowest precedence. var defaultSources Sources = []Source{ KubeAPIServer, Local, @@ -70,6 +75,7 @@ var defaultSources Sources = []Source{ CustomResource, Kubernetes, ClusterMesh, + Directory, LocalAPI, Generated, Restored, @@ -79,57 +85,18 @@ var defaultSources Sources = []Source{ // AllowOverwrite returns true if new state from a particular source is allowed // to overwrite existing state from another source func AllowOverwrite(existing, new Source) bool { - switch existing { - - // KubeAPIServer state can only be overwritten by other kube-apiserver - // state. - case KubeAPIServer: - return new == KubeAPIServer - - // Local state can only be overwritten by other local state or - // kube-apiserver state. - case Local: - return new == Local || new == KubeAPIServer - - // KVStore can be overwritten by other kvstore, local state, or - // kube-apiserver state. - case KVStore: - return new == KVStore || new == Local || new == KubeAPIServer - - // Custom-resource state can be overwritten by other CRD, kvstore, - // local or kube-apiserver state. - case CustomResource: - return new == CustomResource || new == KVStore || new == Local || new == KubeAPIServer - - // Kubernetes state can be overwritten by everything except clustermesh, - // local API, generated, restored and unspecified state. - case Kubernetes: - return new != ClusterMesh && new != LocalAPI && new != Generated && new != Restored && new != Unspec - - // ClusterMesh state can be overwritten by everything except local API, - // generated, restored and unspecified state. - case ClusterMesh: - return new != LocalAPI && new != Generated && new != Restored && new != Unspec - - // Local API state can be overwritten by everything except restored, - // generated and unspecified state - case LocalAPI: - return new != Generated && new != Restored && new != Unspec - - // Generated can be overwritten by everything except by Restored and - // Unspecified - case Generated: - return new != Restored && new != Unspec - - // Restored can be overwritten by everything except by Unspecified - case Restored: - return new != Unspec - - // Unspecified state can be overwritten by everything - case Unspec: - return true + overflowNegative := overflowNegativeTo(len(defaultSources)) + return overflowNegative(slices.Index(defaultSources, new)) <= overflowNegative(slices.Index(defaultSources, existing)) +} + +func overflowNegativeTo(infinity int) func(int) int { + return func(n int) int { + if n < 0 { + return infinity + } else { + return n + } } - return true } var Cell = cell.Module( diff --git a/vendor/github.com/cilium/hive/script/engine.go b/vendor/github.com/cilium/hive/script/engine.go index 84208aab19..ed4fa6fdf3 100644 --- a/vendor/github.com/cilium/hive/script/engine.go +++ b/vendor/github.com/cilium/hive/script/engine.go @@ -320,7 +320,8 @@ func (e *Engine) Execute(s *State, file string, script *bufio.Reader, log io.Wri regexpArgs = usage.RegexpArgs(rawArgs...) } } - cmd.args = expandArgs(s, cmd.rawArgs, regexpArgs) + cmd.origArgs = expandArgs(s, cmd.rawArgs, regexpArgs) + cmd.args = cmd.origArgs // Run the command. err = e.runCommand(s, cmd, impl) @@ -411,6 +412,7 @@ func (e *Engine) ExecuteLine(s *State, line string, log io.Writer) (err error) { } } cmd.args = expandArgs(s, cmd.rawArgs, regexpArgs) + cmd.origArgs = cmd.args // Run the command. err = e.runCommand(s, cmd, impl) @@ -436,6 +438,7 @@ type command struct { conds []condition // all must be satisfied name string // the name of the command; must be non-empty rawArgs [][]argFragment + origArgs []string // original arguments before pflag parsing args []string // shell-expanded arguments following name background bool // command should run in background (ends with a trailing &) } @@ -695,7 +698,7 @@ func (e *Engine) runCommand(s *State, cmd *command, impl Cmd) error { if usage.Flags != nil { usage.Flags(fs) } - if err := fs.Parse(cmd.args); err != nil { + if err := fs.Parse(cmd.origArgs); err != nil { if errors.Is(err, pflag.ErrHelp) { out := new(strings.Builder) err = e.ListCmds(out, true, "^"+cmd.name+"$") diff --git a/vendor/github.com/containerd/containerd/content/local/store.go b/vendor/github.com/containerd/containerd/content/local/store.go index e1baee4c27..efe886014c 100644 --- a/vendor/github.com/containerd/containerd/content/local/store.go +++ b/vendor/github.com/containerd/containerd/content/local/store.go @@ -67,6 +67,8 @@ type LabelStore interface { type store struct { root string ls LabelStore + + ensureIngestRootOnce func() error } // NewStore returns a local content store @@ -80,14 +82,13 @@ func NewStore(root string) (content.Store, error) { // require labels and should use `NewStore`. `NewLabeledStore` is primarily // useful for tests or standalone implementations. func NewLabeledStore(root string, ls LabelStore) (content.Store, error) { - if err := os.MkdirAll(filepath.Join(root, "ingest"), 0777); err != nil { - return nil, err - } - - return &store{ + s := &store{ root: root, ls: ls, - }, nil + } + + s.ensureIngestRootOnce = sync.OnceValue(s.ensureIngestRoot) + return s, nil } func (s *store) Info(ctx context.Context, dgst digest.Digest) (content.Info, error) { @@ -294,6 +295,9 @@ func (s *store) Status(ctx context.Context, ref string) (content.Status, error) func (s *store) ListStatuses(ctx context.Context, fs ...string) ([]content.Status, error) { fp, err := os.Open(filepath.Join(s.root, "ingest")) if err != nil { + if os.IsNotExist(err) { + return nil, nil + } return nil, err } @@ -344,6 +348,9 @@ func (s *store) ListStatuses(ctx context.Context, fs ...string) ([]content.Statu func (s *store) WalkStatusRefs(ctx context.Context, fn func(string) error) error { fp, err := os.Open(filepath.Join(s.root, "ingest")) if err != nil { + if os.IsNotExist(err) { + return nil + } return err } @@ -545,6 +552,11 @@ func (s *store) writer(ctx context.Context, ref string, total int64, expected di ) foundValidIngest := false + + if err := s.ensureIngestRootOnce(); err != nil { + return nil, err + } + // ensure that the ingest path has been created. if err := os.Mkdir(path, 0755); err != nil { if !os.IsExist(err) { @@ -655,6 +667,10 @@ func (s *store) ingestPaths(ref string) (string, string, string) { return fp, rp, dp } +func (s *store) ensureIngestRoot() error { + return os.MkdirAll(filepath.Join(s.root, "ingest"), 0777) +} + func readFileString(path string) (string, error) { p, err := os.ReadFile(path) return string(p), err diff --git a/vendor/github.com/containerd/containerd/remotes/docker/resolver.go b/vendor/github.com/containerd/containerd/remotes/docker/resolver.go index 4ca2b921eb..8ce4cccc01 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/resolver.go +++ b/vendor/github.com/containerd/containerd/remotes/docker/resolver.go @@ -25,8 +25,10 @@ import ( "net" "net/http" "net/url" + "os" "path" "strings" + "sync" "github.com/containerd/log" "github.com/opencontainers/go-digest" @@ -717,13 +719,18 @@ func NewHTTPFallback(transport http.RoundTripper) http.RoundTripper { type httpFallback struct { super http.RoundTripper host string + mu sync.Mutex } func (f *httpFallback) RoundTrip(r *http.Request) (*http.Response, error) { + f.mu.Lock() + fallback := f.host == r.URL.Host + f.mu.Unlock() + // only fall back if the same host had previously fell back - if f.host != r.URL.Host { + if !fallback { resp, err := f.super.RoundTrip(r) - if !isTLSError(err) { + if !isTLSError(err) && !isPortError(err, r.URL.Host) { return resp, err } } @@ -734,8 +741,12 @@ func (f *httpFallback) RoundTrip(r *http.Request) (*http.Response, error) { plainHTTPRequest := *r plainHTTPRequest.URL = &plainHTTPUrl - if f.host != r.URL.Host { - f.host = r.URL.Host + if !fallback { + f.mu.Lock() + if f.host != r.URL.Host { + f.host = r.URL.Host + } + f.mu.Unlock() // update body on the second attempt if r.Body != nil && r.GetBody != nil { @@ -765,6 +776,18 @@ func isTLSError(err error) bool { return false } +func isPortError(err error, host string) bool { + if isConnError(err) || os.IsTimeout(err) { + if _, port, _ := net.SplitHostPort(host); port != "" { + // Port is specified, will not retry on different port with scheme change + return false + } + return true + } + + return false +} + // HTTPFallback is an http.RoundTripper which allows fallback from https to http // for registry endpoints with configurations for both http and TLS, such as // defaulted localhost endpoints. diff --git a/vendor/github.com/containerd/containerd/remotes/docker/resolver_unix.go b/vendor/github.com/containerd/containerd/remotes/docker/resolver_unix.go new file mode 100644 index 0000000000..4ef0e0062a --- /dev/null +++ b/vendor/github.com/containerd/containerd/remotes/docker/resolver_unix.go @@ -0,0 +1,28 @@ +//go:build !windows + +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package docker + +import ( + "errors" + "syscall" +) + +func isConnError(err error) bool { + return errors.Is(err, syscall.ECONNREFUSED) +} diff --git a/vendor/github.com/containerd/containerd/remotes/docker/resolver_windows.go b/vendor/github.com/containerd/containerd/remotes/docker/resolver_windows.go new file mode 100644 index 0000000000..9c98df04bb --- /dev/null +++ b/vendor/github.com/containerd/containerd/remotes/docker/resolver_windows.go @@ -0,0 +1,30 @@ +//go:build windows + +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package docker + +import ( + "errors" + "syscall" + + "golang.org/x/sys/windows" +) + +func isConnError(err error) bool { + return errors.Is(err, syscall.ECONNREFUSED) || errors.Is(err, windows.WSAECONNREFUSED) +} diff --git a/vendor/github.com/containerd/containerd/version/version.go b/vendor/github.com/containerd/containerd/version/version.go index c61791188d..b83e759641 100644 --- a/vendor/github.com/containerd/containerd/version/version.go +++ b/vendor/github.com/containerd/containerd/version/version.go @@ -23,7 +23,7 @@ var ( Package = "github.com/containerd/containerd" // Version holds the complete version number. Filled in at linking time. - Version = "1.7.23+unknown" + Version = "1.7.24+unknown" // Revision is filled with the VCS (e.g. git) revision being used to build // the program at linking time. diff --git a/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md b/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md index 04b5685ab4..cb1252b53e 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md +++ b/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md @@ -6,6 +6,35 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] ## +## [0.3.6] - 2024-12-17 ## + +### Compatibility ### +- The minimum Go version requirement for `filepath-securejoin` is now Go 1.18 + (we use generics internally). + + For reference, `filepath-securejoin@v0.3.0` somewhat-arbitrarily bumped the + Go version requirement to 1.21. + + While we did make some use of Go 1.21 stdlib features (and in principle Go + versions <= 1.21 are no longer even supported by upstream anymore), some + downstreams have complained that the version bump has meant that they have to + do workarounds when backporting fixes that use the new `filepath-securejoin` + API onto old branches. This is not an ideal situation, but since using this + library is probably better for most downstreams than a hand-rolled + workaround, we now have compatibility shims that allow us to build on older + Go versions. +- Lower minimum version requirement for `golang.org/x/sys` to `v0.18.0` (we + need the wrappers for `fsconfig(2)`), which should also make backporting + patches to older branches easier. + +## [0.3.5] - 2024-12-06 ## + +### Fixed ### +- `MkdirAll` will now no longer return an `EEXIST` error if two racing + processes are creating the same directory. We will still verify that the path + is a directory, but this will avoid spurious errors when multiple threads or + programs are trying to `MkdirAll` the same path. opencontainers/runc#4543 + ## [0.3.4] - 2024-10-09 ## ### Fixed ### @@ -164,8 +193,10 @@ This is our first release of `github.com/cyphar/filepath-securejoin`, containing a full implementation with a coverage of 93.5% (the only missing cases are the error cases, which are hard to mocktest at the moment). -[Unreleased]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.4...HEAD -[0.3.3]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.3...v0.3.4 +[Unreleased]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.6...HEAD +[0.3.6]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.5...v0.3.6 +[0.3.5]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.4...v0.3.5 +[0.3.4]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.3...v0.3.4 [0.3.3]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.2...v0.3.3 [0.3.2]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.1...v0.3.2 [0.3.1]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.0...v0.3.1 diff --git a/vendor/github.com/cyphar/filepath-securejoin/VERSION b/vendor/github.com/cyphar/filepath-securejoin/VERSION index 42045acae2..449d7e73a9 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/VERSION +++ b/vendor/github.com/cyphar/filepath-securejoin/VERSION @@ -1 +1 @@ -0.3.4 +0.3.6 diff --git a/vendor/github.com/cyphar/filepath-securejoin/gocompat_errors_go120.go b/vendor/github.com/cyphar/filepath-securejoin/gocompat_errors_go120.go new file mode 100644 index 0000000000..42452bbf9b --- /dev/null +++ b/vendor/github.com/cyphar/filepath-securejoin/gocompat_errors_go120.go @@ -0,0 +1,18 @@ +//go:build linux && go1.20 + +// Copyright (C) 2024 SUSE LLC. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package securejoin + +import ( + "fmt" +) + +// wrapBaseError is a helper that is equivalent to fmt.Errorf("%w: %w"), except +// that on pre-1.20 Go versions only errors.Is() works properly (errors.Unwrap) +// is only guaranteed to give you baseErr. +func wrapBaseError(baseErr, extraErr error) error { + return fmt.Errorf("%w: %w", extraErr, baseErr) +} diff --git a/vendor/github.com/cyphar/filepath-securejoin/gocompat_errors_unsupported.go b/vendor/github.com/cyphar/filepath-securejoin/gocompat_errors_unsupported.go new file mode 100644 index 0000000000..e7adca3fd1 --- /dev/null +++ b/vendor/github.com/cyphar/filepath-securejoin/gocompat_errors_unsupported.go @@ -0,0 +1,38 @@ +//go:build linux && !go1.20 + +// Copyright (C) 2024 SUSE LLC. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package securejoin + +import ( + "fmt" +) + +type wrappedError struct { + inner error + isError error +} + +func (err wrappedError) Is(target error) bool { + return err.isError == target +} + +func (err wrappedError) Unwrap() error { + return err.inner +} + +func (err wrappedError) Error() string { + return fmt.Sprintf("%v: %v", err.isError, err.inner) +} + +// wrapBaseError is a helper that is equivalent to fmt.Errorf("%w: %w"), except +// that on pre-1.20 Go versions only errors.Is() works properly (errors.Unwrap) +// is only guaranteed to give you baseErr. +func wrapBaseError(baseErr, extraErr error) error { + return wrappedError{ + inner: baseErr, + isError: extraErr, + } +} diff --git a/vendor/github.com/cyphar/filepath-securejoin/gocompat_generics_go121.go b/vendor/github.com/cyphar/filepath-securejoin/gocompat_generics_go121.go new file mode 100644 index 0000000000..ddd6fa9a41 --- /dev/null +++ b/vendor/github.com/cyphar/filepath-securejoin/gocompat_generics_go121.go @@ -0,0 +1,32 @@ +//go:build linux && go1.21 + +// Copyright (C) 2024 SUSE LLC. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package securejoin + +import ( + "slices" + "sync" +) + +func slices_DeleteFunc[S ~[]E, E any](slice S, delFn func(E) bool) S { + return slices.DeleteFunc(slice, delFn) +} + +func slices_Contains[S ~[]E, E comparable](slice S, val E) bool { + return slices.Contains(slice, val) +} + +func slices_Clone[S ~[]E, E any](slice S) S { + return slices.Clone(slice) +} + +func sync_OnceValue[T any](f func() T) func() T { + return sync.OnceValue(f) +} + +func sync_OnceValues[T1, T2 any](f func() (T1, T2)) func() (T1, T2) { + return sync.OnceValues(f) +} diff --git a/vendor/github.com/cyphar/filepath-securejoin/gocompat_generics_unsupported.go b/vendor/github.com/cyphar/filepath-securejoin/gocompat_generics_unsupported.go new file mode 100644 index 0000000000..f1e6fe7e71 --- /dev/null +++ b/vendor/github.com/cyphar/filepath-securejoin/gocompat_generics_unsupported.go @@ -0,0 +1,124 @@ +//go:build linux && !go1.21 + +// Copyright (C) 2024 SUSE LLC. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package securejoin + +import ( + "sync" +) + +// These are very minimal implementations of functions that appear in Go 1.21's +// stdlib, included so that we can build on older Go versions. Most are +// borrowed directly from the stdlib, and a few are modified to be "obviously +// correct" without needing to copy too many other helpers. + +// clearSlice is equivalent to the builtin clear from Go 1.21. +// Copied from the Go 1.24 stdlib implementation. +func clearSlice[S ~[]E, E any](slice S) { + var zero E + for i := range slice { + slice[i] = zero + } +} + +// Copied from the Go 1.24 stdlib implementation. +func slices_IndexFunc[S ~[]E, E any](s S, f func(E) bool) int { + for i := range s { + if f(s[i]) { + return i + } + } + return -1 +} + +// Copied from the Go 1.24 stdlib implementation. +func slices_DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S { + i := slices_IndexFunc(s, del) + if i == -1 { + return s + } + // Don't start copying elements until we find one to delete. + for j := i + 1; j < len(s); j++ { + if v := s[j]; !del(v) { + s[i] = v + i++ + } + } + clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC + return s[:i] +} + +// Similar to the stdlib slices.Contains, except that we don't have +// slices.Index so we need to use slices.IndexFunc for this non-Func helper. +func slices_Contains[S ~[]E, E comparable](s S, v E) bool { + return slices_IndexFunc(s, func(e E) bool { return e == v }) >= 0 +} + +// Copied from the Go 1.24 stdlib implementation. +func slices_Clone[S ~[]E, E any](s S) S { + // Preserve nil in case it matters. + if s == nil { + return nil + } + return append(S([]E{}), s...) +} + +// Copied from the Go 1.24 stdlib implementation. +func sync_OnceValue[T any](f func() T) func() T { + var ( + once sync.Once + valid bool + p any + result T + ) + g := func() { + defer func() { + p = recover() + if !valid { + panic(p) + } + }() + result = f() + f = nil + valid = true + } + return func() T { + once.Do(g) + if !valid { + panic(p) + } + return result + } +} + +// Copied from the Go 1.24 stdlib implementation. +func sync_OnceValues[T1, T2 any](f func() (T1, T2)) func() (T1, T2) { + var ( + once sync.Once + valid bool + p any + r1 T1 + r2 T2 + ) + g := func() { + defer func() { + p = recover() + if !valid { + panic(p) + } + }() + r1, r2 = f() + f = nil + valid = true + } + return func() (T1, T2) { + once.Do(g) + if !valid { + panic(p) + } + return r1, r2 + } +} diff --git a/vendor/github.com/cyphar/filepath-securejoin/lookup_linux.go b/vendor/github.com/cyphar/filepath-securejoin/lookup_linux.go index 290befa154..be81e498d7 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/lookup_linux.go +++ b/vendor/github.com/cyphar/filepath-securejoin/lookup_linux.go @@ -12,7 +12,6 @@ import ( "os" "path" "path/filepath" - "slices" "strings" "golang.org/x/sys/unix" @@ -113,7 +112,7 @@ func (s *symlinkStack) push(dir *os.File, remainingPath, linkTarget string) erro return nil } // Split the link target and clean up any "" parts. - linkTargetParts := slices.DeleteFunc( + linkTargetParts := slices_DeleteFunc( strings.Split(linkTarget, "/"), func(part string) bool { return part == "" || part == "." }) diff --git a/vendor/github.com/cyphar/filepath-securejoin/mkdir_linux.go b/vendor/github.com/cyphar/filepath-securejoin/mkdir_linux.go index b5f674524c..5e559bb7a8 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/mkdir_linux.go +++ b/vendor/github.com/cyphar/filepath-securejoin/mkdir_linux.go @@ -11,7 +11,6 @@ import ( "fmt" "os" "path/filepath" - "slices" "strings" "golang.org/x/sys/unix" @@ -93,7 +92,7 @@ func MkdirAllHandle(root *os.File, unsafePath string, mode int) (_ *os.File, Err } remainingParts := strings.Split(remainingPath, string(filepath.Separator)) - if slices.Contains(remainingParts, "..") { + if slices_Contains(remainingParts, "..") { // The path contained ".." components after the end of the "real" // components. We could try to safely resolve ".." here but that would // add a bunch of extra logic for something that it's not clear even @@ -119,11 +118,20 @@ func MkdirAllHandle(root *os.File, unsafePath string, mode int) (_ *os.File, Err // NOTE: mkdir(2) will not follow trailing symlinks, so we can safely // create the final component without worrying about symlink-exchange // attacks. - if err := unix.Mkdirat(int(currentDir.Fd()), part, uint32(mode)); err != nil { + // + // If we get -EEXIST, it's possible that another program created the + // directory at the same time as us. In that case, just continue on as + // if we created it (if the created inode is not a directory, the + // following open call will fail). + if err := unix.Mkdirat(int(currentDir.Fd()), part, uint32(mode)); err != nil && !errors.Is(err, unix.EEXIST) { err = &os.PathError{Op: "mkdirat", Path: currentDir.Name() + "/" + part, Err: err} // Make the error a bit nicer if the directory is dead. - if err2 := isDeadInode(currentDir); err2 != nil { - err = fmt.Errorf("%w (%w)", err, err2) + if deadErr := isDeadInode(currentDir); deadErr != nil { + // TODO: Once we bump the minimum Go version to 1.20, we can use + // multiple %w verbs for this wrapping. For now we need to use a + // compatibility shim for older Go versions. + //err = fmt.Errorf("%w (%w)", err, deadErr) + err = wrapBaseError(err, deadErr) } return nil, err } diff --git a/vendor/github.com/cyphar/filepath-securejoin/openat2_linux.go b/vendor/github.com/cyphar/filepath-securejoin/openat2_linux.go index ae3b381efe..f7a13e69ce 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/openat2_linux.go +++ b/vendor/github.com/cyphar/filepath-securejoin/openat2_linux.go @@ -12,12 +12,11 @@ import ( "os" "path/filepath" "strings" - "sync" "golang.org/x/sys/unix" ) -var hasOpenat2 = sync.OnceValue(func() bool { +var hasOpenat2 = sync_OnceValue(func() bool { fd, err := unix.Openat2(unix.AT_FDCWD, ".", &unix.OpenHow{ Flags: unix.O_PATH | unix.O_CLOEXEC, Resolve: unix.RESOLVE_NO_SYMLINKS | unix.RESOLVE_IN_ROOT, diff --git a/vendor/github.com/cyphar/filepath-securejoin/procfs_linux.go b/vendor/github.com/cyphar/filepath-securejoin/procfs_linux.go index 8cc827d704..809a579cbd 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/procfs_linux.go +++ b/vendor/github.com/cyphar/filepath-securejoin/procfs_linux.go @@ -12,7 +12,6 @@ import ( "os" "runtime" "strconv" - "sync" "golang.org/x/sys/unix" ) @@ -54,7 +53,7 @@ func verifyProcRoot(procRoot *os.File) error { return nil } -var hasNewMountApi = sync.OnceValue(func() bool { +var hasNewMountApi = sync_OnceValue(func() bool { // All of the pieces of the new mount API we use (fsopen, fsconfig, // fsmount, open_tree) were added together in Linux 5.1[1,2], so we can // just check for one of the syscalls and the others should also be @@ -192,11 +191,11 @@ func doGetProcRoot() (*os.File, error) { return procRoot, err } -var getProcRoot = sync.OnceValues(func() (*os.File, error) { +var getProcRoot = sync_OnceValues(func() (*os.File, error) { return doGetProcRoot() }) -var hasProcThreadSelf = sync.OnceValue(func() bool { +var hasProcThreadSelf = sync_OnceValue(func() bool { return unix.Access("/proc/thread-self/", unix.F_OK) == nil }) @@ -265,12 +264,20 @@ func procThreadSelf(procRoot *os.File, subpath string) (_ *os.File, _ procThread Resolve: unix.RESOLVE_BENEATH | unix.RESOLVE_NO_XDEV | unix.RESOLVE_NO_MAGICLINKS, }) if err != nil { - return nil, nil, fmt.Errorf("%w: %w", errUnsafeProcfs, err) + // TODO: Once we bump the minimum Go version to 1.20, we can use + // multiple %w verbs for this wrapping. For now we need to use a + // compatibility shim for older Go versions. + //err = fmt.Errorf("%w: %w", errUnsafeProcfs, err) + return nil, nil, wrapBaseError(err, errUnsafeProcfs) } } else { handle, err = openatFile(procRoot, threadSelf+subpath, unix.O_PATH|unix.O_NOFOLLOW|unix.O_CLOEXEC, 0) if err != nil { - return nil, nil, fmt.Errorf("%w: %w", errUnsafeProcfs, err) + // TODO: Once we bump the minimum Go version to 1.20, we can use + // multiple %w verbs for this wrapping. For now we need to use a + // compatibility shim for older Go versions. + //err = fmt.Errorf("%w: %w", errUnsafeProcfs, err) + return nil, nil, wrapBaseError(err, errUnsafeProcfs) } defer func() { if Err != nil { @@ -289,12 +296,17 @@ func procThreadSelf(procRoot *os.File, subpath string) (_ *os.File, _ procThread return handle, runtime.UnlockOSThread, nil } -var hasStatxMountId = sync.OnceValue(func() bool { +// STATX_MNT_ID_UNIQUE is provided in golang.org/x/sys@v0.20.0, but in order to +// avoid bumping the requirement for a single constant we can just define it +// ourselves. +const STATX_MNT_ID_UNIQUE = 0x4000 + +var hasStatxMountId = sync_OnceValue(func() bool { var ( stx unix.Statx_t // We don't care which mount ID we get. The kernel will give us the // unique one if it is supported. - wantStxMask uint32 = unix.STATX_MNT_ID_UNIQUE | unix.STATX_MNT_ID + wantStxMask uint32 = STATX_MNT_ID_UNIQUE | unix.STATX_MNT_ID ) err := unix.Statx(-int(unix.EBADF), "/", 0, int(wantStxMask), &stx) return err == nil && stx.Mask&wantStxMask != 0 @@ -310,7 +322,7 @@ func getMountId(dir *os.File, path string) (uint64, error) { stx unix.Statx_t // We don't care which mount ID we get. The kernel will give us the // unique one if it is supported. - wantStxMask uint32 = unix.STATX_MNT_ID_UNIQUE | unix.STATX_MNT_ID + wantStxMask uint32 = STATX_MNT_ID_UNIQUE | unix.STATX_MNT_ID ) err := unix.Statx(int(dir.Fd()), path, unix.AT_EMPTY_PATH|unix.AT_SYMLINK_NOFOLLOW, int(wantStxMask), &stx) diff --git a/vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go b/vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go index c1cfa62fd2..85450bf6b3 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go @@ -18,6 +18,8 @@ const blockThreshold = 1e6 var ( // ErrClosed is returned when Write is called on a closed BytesPipe. + // + // Deprecated: this type is only used internally, and will be removed in the next release. ErrClosed = errors.New("write to closed BytesPipe") bufPools = make(map[int]*sync.Pool) @@ -28,6 +30,8 @@ var ( // All written data may be read at most once. Also, BytesPipe allocates // and releases new byte slices to adjust to current needs, so the buffer // won't be overgrown after peak loads. +// +// Deprecated: this type is only used internally, and will be removed in the next release. type BytesPipe struct { mu sync.Mutex wait *sync.Cond @@ -40,6 +44,8 @@ type BytesPipe struct { // NewBytesPipe creates new BytesPipe, initialized by specified slice. // If buf is nil, then it will be initialized with slice which cap is 64. // buf will be adjusted in a way that len(buf) == 0, cap(buf) == cap(buf). +// +// Deprecated: this function is only used internally, and will be removed in the next release. func NewBytesPipe() *BytesPipe { bp := &BytesPipe{} bp.buf = append(bp.buf, getBuffer(minCap)) diff --git a/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go b/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go index 91b8d18266..d8a8893ff1 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go @@ -80,13 +80,19 @@ func (wf *WriteFlusher) Close() error { return nil } +// nopFlusher represents a type which flush operation is nop. +type nopFlusher struct{} + +// Flush is a nop operation. +func (f *nopFlusher) Flush() {} + // NewWriteFlusher returns a new WriteFlusher. func NewWriteFlusher(w io.Writer) *WriteFlusher { var fl flusher if f, ok := w.(flusher); ok { fl = f } else { - fl = &NopFlusher{} + fl = &nopFlusher{} } return &WriteFlusher{w: w, flusher: fl, closed: make(chan struct{}), flushed: make(chan struct{})} } diff --git a/vendor/github.com/docker/docker/pkg/ioutils/writers.go b/vendor/github.com/docker/docker/pkg/ioutils/writers.go index 1f50602f28..aec8b4c03e 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/writers.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/writers.go @@ -6,6 +6,8 @@ import ( ) // NopWriter represents a type which write operation is nop. +// +// Deprecated: use [io.Discard] instead. This type will be removed in the next release. type NopWriter struct{} func (*NopWriter) Write(buf []byte) (int, error) { @@ -19,15 +21,16 @@ type nopWriteCloser struct { func (w *nopWriteCloser) Close() error { return nil } // NopWriteCloser returns a nopWriteCloser. +// +// Deprecated: This function is no longer used and will be removed in the next release. func NopWriteCloser(w io.Writer) io.WriteCloser { return &nopWriteCloser{w} } // NopFlusher represents a type which flush operation is nop. -type NopFlusher struct{} - -// Flush is a nop operation. -func (f *NopFlusher) Flush() {} +// +// Deprecated: NopFlusher is only used internally and will be removed in the next release. +type NopFlusher = nopFlusher type writeCloserWrapper struct { io.Writer @@ -55,12 +58,16 @@ func NewWriteCloserWrapper(r io.Writer, closer func() error) io.WriteCloser { // of bytes written to the writer during a "session". // This can be convenient when write return is masked // (e.g., json.Encoder.Encode()) +// +// Deprecated: this type is no longer used and will be removed in the next release. type WriteCounter struct { Count int64 Writer io.Writer } // NewWriteCounter returns a new WriteCounter. +// +// Deprecated: this function is no longer used and will be removed in the next release. func NewWriteCounter(w io.Writer) *WriteCounter { return &WriteCounter{ Writer: w, diff --git a/vendor/github.com/google/btree/btree.go b/vendor/github.com/google/btree/btree.go index 969b910d70..6f5184fef7 100644 --- a/vendor/github.com/google/btree/btree.go +++ b/vendor/github.com/google/btree/btree.go @@ -479,7 +479,7 @@ func (n *node) growChildAndRemove(i int, item Item, minItems int, typ toRemove) child := n.mutableChild(i) // merge with right child mergeItem := n.items.removeAt(i) - mergeChild := n.children.removeAt(i + 1) + mergeChild := n.children.removeAt(i + 1).mutableFor(n.cow) child.items = append(child.items, mergeItem) child.items = append(child.items, mergeChild.items...) child.children = append(child.children, mergeChild.children...) diff --git a/vendor/github.com/google/go-github/v68/AUTHORS b/vendor/github.com/google/go-github/v68/AUTHORS new file mode 100644 index 0000000000..a6104ffa9a --- /dev/null +++ b/vendor/github.com/google/go-github/v68/AUTHORS @@ -0,0 +1,548 @@ +# This is the official list of go-github authors for copyright purposes. +# +# This does not necessarily list everyone who has contributed code, since in +# some cases, their employer may be the copyright holder. To see the full list +# of contributors, see the revision history in source control or +# https://github.com/google/go-github/graphs/contributors. +# +# Authors who wish to be recognized in this file should add themselves (or +# their employer, as appropriate). + +178inaba +2BFL +413x +6543 <6543@obermui.de> +Abed Kibbe +Abhijit Hota +Abhinav Gupta +abhishek +Abhishek Sharma +Abhishek Veeramalla +aboy +Adam Kohring +Aditya Mahendrakar +adrienzieba +afdesk +Ahmad Nurus S +Ahmed Hagy +Aidan +Aidan Steele +Ainsley Chong +ajz01 +Akeda Bagus +Akhil Mohan +Alec Thomas +Aleks Clark +Alex Bramley +Alex Ellis +Alex Orr +Alex Su +Alex Unger +Alexander Harkness +Alexey Alekhin +Alexis Couvreur +Alexis Gauthiez +Ali Farooq +Alin Balutoiu +Allan Guwatudde +Allen Sun +Amey Sakhadeo +Anders Janmyr +Andreas Deininger +Andreas Garnæs +Andrew Gillis +Andrew Ryabchun +Andrew Svoboda +Andriyun +Andy Grunwald +Andy Hume +Andy Lindeman +angie pinilla +Anish Rajan +anjanashenoy +Anshuman Bhartiya +Antoine +Antoine Pelisse +Anton Nguyen +Anubha Kushwaha +appilon +aprp +apurwaj2 +Aravind +Arda Kuyumcu +Ary +Arıl Bozoluk +Asier Marruedo +Austin Burdine +Austin Dizzy +Azuka Okuleye +Ben Batha +Benjamen Keroack +Benjamin Nater +Berkay Tacyildiz +Beshr Kayali +Beyang Liu +billnapier +Billy Keyes +Billy Lynch +Bingtan Lu +Bjorn Neergaard +Björn Häuser +Bo Huang +boljen +Bracken +Brad Harris +Brad Moylan +Bradley Falzon +Bradley McAllister +Brandon Butler +Brandon Cook +Brandon Stubbs +Brett Kuhlman +Brett Logan +Brian Egizi +Bryan Boreham +Bryan Peterson +Cami Diez +Carl Johnson +Carlos Alexandro Becker +Carlos Tadeu Panato Junior +Casey +ChandanChainani +chandresh-pancholi +Charles Fenwick Elliott +Charlie Yan +Chmouel Boudjnah +Chris Allen Lane +Chris King +Chris Mc +Chris Raborg +Chris Roche +Chris Schaefer +chrisforrette +Christian Bargmann +Christian Muehlhaeuser +Christoph Jerolimov +Christoph Sassenberg +CI Monk +Clemens W +Colin Misare +Craig Gumbley +Craig Peterson +Cristian Maglie +Cyb3r Jak3 +Daehyeok Mun +Dalton Hubble +Daniel Lanner +Daniel Leavitt +Daniel Nilsson +Daoq +Dave Du Cros +Dave Henderson +Dave Perrett +Dave Protasowski +David Deng +David Gamba +David J. M. Karlsen +David Jannotta +David Ji +David Lopez Reyes +Davide Zipeto +Dennis Webb +Derek Jobst +DeviousLab +Dhi Aurrahman +Diego Lapiduz +Diogo Vilela +Dion Gionet Mallet +Dmitri Shuralyov +dmnlk +Don Petersen +Doug Turner +Drew Fradette +Dustin Deus +Dustin Lish +Eivind +Eli Uriegas +Elliott Beach +Emerson Wood +Emil V +Emma Sax +Eng Zer Jun +Enrico Candino +eperm +Erick Fejta +Erik Elkins +Erik Nobel +Erwan Finot +erwinvaneyk +Evan Anderson +Evan Elias +Fabian Holler +Fabrice +Fatema-Moaiyadi +Federico Di Pierro +Felix Geisendörfer +Filippo Valsorda +Florian Forster +Florian Maier +Florian Wagner +Francesc Gil +Francis +Francisco Guimarães +François de Metz +Fredrik Jönsson +Gabriel +Gal Ofri +Garrett Squire +George Kontridze +Georgy Buranov +Glen Mailer +Gnahz +Google Inc. +Grachev Mikhail +Gregory Oschwald +griffin_stewie +guangwu +Guillaume Jacquet +Guz Alexander +Guðmundur Bjarni Ólafsson +Hanno Hecker +Hari haran +Harikesh00 +haya14busa +haya14busa +Henrik Lundström +Hiroki Ito +Hubot Jr +Huy Tr +huydx +i2bskn +Iain Steers +Ikko Ashimine +Ilia Choly +Ioannis Georgoulas +Isao Jonas +ishan upadhyay +isqua +Ivan Martos +Jacob Valdemar +Jake Krammer +Jake Scaltreto +Jake White +Jameel Haffejee +James Bowes +James Cockbain +James Loh +James Maguire +James Turley +Jamie West +Jan Guth +Jan Kosecki +Jan Å vábík +Jason Field +Javier Campanini +Jef LeCompte +Jeff Wenzbauer +Jens Rantil +Jeremy Morris +Jesse Haka +Jesse Newland +Jihoon Chung +Jille Timmermans +Jimmi Dyson +Joan Saum +JoannaaKL +Joe Tsai +John Barton +John Engelman +John Jones +John Liu +Jordan Brockopp +Jordan Burandt +Jordan Sussman +Jorge Ferrero +Jorge Gómez Reus +Joshua Bezaleel Abednego +João Cerqueira +JP Phillips +jpbelanger-mtl +Juan +Juan Basso +Julien Garcia Gonzalez +Julien Midedji +Julien Rostand +Junya Kono +Justin Abrahms +Justin Toh +Jusung Lee +jzhoucliqr +k0ral +k1rnt +kadern0 +Karthik Sundari +Katrina Owen +Kautilya Tripathi +Keita Urashima +Kevin Burke +Kevin Wang +Kevin Zhao +kgalli +Khanh Ngo +Kirill +Konrad Malawski +Kookheon Kwon +Krishna Indani +Krzysztof Kowalczyk +Kshitij Saraogi +Kumar Saurabh +Kyle Kurz +kyokomi +Lachlan Cooper +Lars Lehtonen +Laurent Verdoïa +leopoldwang +Liam Galvin +Liam Stanley +Lluis Campos +Lovro Mažgon +Loïs Postula +Luca Campese +Lucas Alcantara +Lucas Martin-King +Luis Davim +Luke Evers +Luke Hinds +Luke Kysow +Luke Roberts +Luke Young +lynn [they] +Léo Salé +M. Ryan Rigdon +Magnus Kulke +Maksim Zhylinski +Marc Binder +Marcelo Carlos +Mark Tareshawty +Martin Holman +Martin-Louis Bright +Martins Sipenko +Marwan Sulaiman +Masayuki Izumi +Mat Geist +Matheus Santos Araújo +Matija Horvat +Matin Rahmanian +Matt +Matt Brender +Matt Dainty +Matt Gaunt +Matt Landis +Matt Mencel +Matt Moore +Matt Simons +Matthew Reidy +Maxime Bury +Michael Meng +Michael Spiegel +Michael Tiller +MichaÅ‚ Glapa +Michelangelo Morrillo +Miguel Elias dos Santos +Mike Chen +Miles Crabill +Mishin Nikolai +mohammad ali <2018cs92@student.uet.edu.pk> +Mohammed AlDujaili +Mohammed Nafees +Mudit +Mukundan Senthil +Munia Balayil +Mustafa Abban +Nadav Kaner +Naoki Kanatani +Nathan VanBenschoten +Navaneeth Suresh +Nayeem Hasan +Neal Caffery +Neil O'Toole +Nicholas Herring +Nick Miyake +Nick Platt +Nick Spragg +Nicolas Chapurlat +Nikhita Raghunath +Nikita Pivkin +Nilesh Singh +Noah Hanjun Lee +Noah Zoschke +Noble Varghese +ns-cweber +nxya +Ole Orhagen +Oleg Kovalov +Oleksandr Redko +OndÅ™ej Kupka +Ori Talmor +Osama Faqhruldin +oslowalk +Pablo Pérez Schröder +Palash Nigam +Panagiotis Moustafellos +Parham Alvani +pari-27 +Parker Moore +parkhyukjun89 +Pat Alwell +Patrick DeVivo +Patrick Marabeas +Patrik Nordlén +Pavel Dvoinos +Pavel Shtanko +Pete Wagner +Petr Shevtsov +Pierce McEntagart +Pierre Carrier +Piotr Zurek +Piyush Chugh +Pj Meyer +Pratik Mallya +Qais Patankar +Quang Le Hong +Quentin Leffray +Quinn Slack +Rackspace US, Inc. +Radek Simko +RadliÅ„ski Ignacy +Rafael Aramizu Gomes +Rajat Jindal +Rajendra arora +Rajkumar +Ramesh Gaikwad +Ranbir Singh +Ravi Shekhar Jethani +RaviTeja Pothana +rc1140 +Red Hat, Inc. +Reetuparna Mukherjee +reeves122 +Reinier Timmer +Renjith R +Rez Moss +Riaje +Ricco Førgaard +Richard de Vries +Rob Figueiredo +Rohit Upadhyay +Rojan Dinc +Roming22 +Ronak Jain +Ronan Pelliard +Ross Gustafson +Ruben Vereecken +Rufina Talalaeva +Russell Boley +Ryan Leung +Ryan Lower +Ryan Skidmore +Ryo Nakao +Saaarah +Safwan Olaimat +Sahil Dua +Sai Ravi Teja Chintakrindi +saisi +Sam Minnée +Sandeep Sukhani +Sander Knape +Sander van Harmelen +Sanket Payghan +Sarah Funkhouser +Sarasa Kisaragi +Sasha Melentyev +Sean Wang +Sebastian Mandrean +Sebastian Mæland Pedersen +Sergei Popinevskii +Sergey Romanov +Sergio Garcia +Seth Vargo +Sevki +Shagun Khemka +shakeelrao +Shawn Catanzarite +Shawn Smith +Shibasis Patel +Sho Okada +Shrikrishna Singh +Simon Davis +sona-tar +soniachikh +SoundCloud, Ltd. +Sridhar Mocherla +SriVignessh Pss +Stefan Sedich +Steve Hipwell +Steve Teuber +Stian Eikeland +Suhaib Mujahid +sushmita wable +Sven Palberg +Szymon Kodrebski +Søren Hansen +T.J. Corrigan +Takashi Yoneuchi +Takayuki Watanabe +Taketoshi Fujiwara +Taketoshi Fujiwara +Takuma Kajikawa +Tasya Aditya Rukmana +Theo Henson +Theofilos Petsios +Thomas Aidan Curran +Thomas Bruyelle +Tim Rogers +Timothy O'Brien +Timothée Peignier +Tingluo Huang +tkhandel +Tobias Gesellchen +Tom Payne +Tomasz Adam Skrzypczak +tomfeigin +Travis Tomsu +Trey Tacon +tsbkw +ttacon +Vaibhav Singh +Varadarajan Aravamudhan +Victor Castell +Victor Vrantchan +Victory Osikwemhe +vikkyomkar +Vivek +Vlad Ungureanu +Wasim Thabraze +Weslei Juan Moser Pereira +Wheeler Law +Will Maier +Will Norris +Willem D'Haeseleer +William Bailey +William Cooke +Xabi +xibz +Yann Malet +Yannick Utard +Yarden Shoham +Yicheng Qin +Yosuke Akatsuka +Yumikiyo Osanai +Yurii Soldak +Yusef Mohamadi +Yusuke Kuoka +Zach Latta +Ze Peng +zhouhaibing089 +六开箱 +缘生 +蒋航 diff --git a/vendor/github.com/google/go-github/v68/LICENSE b/vendor/github.com/google/go-github/v68/LICENSE new file mode 100644 index 0000000000..28b6486f0b --- /dev/null +++ b/vendor/github.com/google/go-github/v68/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013 The go-github AUTHORS. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/google/go-github/v68/github/actions.go b/vendor/github.com/google/go-github/v68/github/actions.go new file mode 100644 index 0000000000..4b88a1e114 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions.go @@ -0,0 +1,12 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +// ActionsService handles communication with the actions related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/actions/ +type ActionsService service diff --git a/vendor/github.com/google/go-github/v68/github/actions_artifacts.go b/vendor/github.com/google/go-github/v68/github/actions_artifacts.go new file mode 100644 index 0000000000..e05a9a8402 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_artifacts.go @@ -0,0 +1,177 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" + "net/url" +) + +// ArtifactWorkflowRun represents a GitHub artifact's workflow run. +// +// GitHub API docs: https://docs.github.com/rest/actions/artifacts +type ArtifactWorkflowRun struct { + ID *int64 `json:"id,omitempty"` + RepositoryID *int64 `json:"repository_id,omitempty"` + HeadRepositoryID *int64 `json:"head_repository_id,omitempty"` + HeadBranch *string `json:"head_branch,omitempty"` + HeadSHA *string `json:"head_sha,omitempty"` +} + +// Artifact represents a GitHub artifact. Artifacts allow sharing +// data between jobs in a workflow and provide storage for data +// once a workflow is complete. +// +// GitHub API docs: https://docs.github.com/rest/actions/artifacts +type Artifact struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Name *string `json:"name,omitempty"` + SizeInBytes *int64 `json:"size_in_bytes,omitempty"` + URL *string `json:"url,omitempty"` + ArchiveDownloadURL *string `json:"archive_download_url,omitempty"` + Expired *bool `json:"expired,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + ExpiresAt *Timestamp `json:"expires_at,omitempty"` + WorkflowRun *ArtifactWorkflowRun `json:"workflow_run,omitempty"` +} + +// ArtifactList represents a list of GitHub artifacts. +// +// GitHub API docs: https://docs.github.com/rest/actions/artifacts#artifacts +type ArtifactList struct { + TotalCount *int64 `json:"total_count,omitempty"` + Artifacts []*Artifact `json:"artifacts,omitempty"` +} + +// ListArtifactsOptions specifies the optional parameters to the +// ActionsService.ListArtifacts method. +type ListArtifactsOptions struct { + // Name represents the name field of an artifact. + // When specified, only artifacts with this name will be returned. + Name *string `url:"name,omitempty"` + + ListOptions +} + +// ListArtifacts lists all artifacts that belong to a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/artifacts#list-artifacts-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/artifacts +func (s *ActionsService) ListArtifacts(ctx context.Context, owner, repo string, opts *ListArtifactsOptions) (*ArtifactList, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/artifacts", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + artifactList := new(ArtifactList) + resp, err := s.client.Do(ctx, req, artifactList) + if err != nil { + return nil, resp, err + } + + return artifactList, resp, nil +} + +// ListWorkflowRunArtifacts lists all artifacts that belong to a workflow run. +// +// GitHub API docs: https://docs.github.com/rest/actions/artifacts#list-workflow-run-artifacts +// +//meta:operation GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts +func (s *ActionsService) ListWorkflowRunArtifacts(ctx context.Context, owner, repo string, runID int64, opts *ListOptions) (*ArtifactList, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/artifacts", owner, repo, runID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + artifactList := new(ArtifactList) + resp, err := s.client.Do(ctx, req, artifactList) + if err != nil { + return nil, resp, err + } + + return artifactList, resp, nil +} + +// GetArtifact gets a specific artifact for a workflow run. +// +// GitHub API docs: https://docs.github.com/rest/actions/artifacts#get-an-artifact +// +//meta:operation GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id} +func (s *ActionsService) GetArtifact(ctx context.Context, owner, repo string, artifactID int64) (*Artifact, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/artifacts/%v", owner, repo, artifactID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + artifact := new(Artifact) + resp, err := s.client.Do(ctx, req, artifact) + if err != nil { + return nil, resp, err + } + + return artifact, resp, nil +} + +// DownloadArtifact gets a redirect URL to download an archive for a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/artifacts#download-an-artifact +// +//meta:operation GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id}/{archive_format} +func (s *ActionsService) DownloadArtifact(ctx context.Context, owner, repo string, artifactID int64, maxRedirects int) (*url.URL, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/artifacts/%v/zip", owner, repo, artifactID) + + resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, maxRedirects) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusFound { + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + } + + parsedURL, err := url.Parse(resp.Header.Get("Location")) + if err != nil { + return nil, newResponse(resp), err + } + + return parsedURL, newResponse(resp), nil +} + +// DeleteArtifact deletes a workflow run artifact. +// +// GitHub API docs: https://docs.github.com/rest/actions/artifacts#delete-an-artifact +// +//meta:operation DELETE /repos/{owner}/{repo}/actions/artifacts/{artifact_id} +func (s *ActionsService) DeleteArtifact(ctx context.Context, owner, repo string, artifactID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/artifacts/%v", owner, repo, artifactID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_cache.go b/vendor/github.com/google/go-github/v68/github/actions_cache.go new file mode 100644 index 0000000000..852e9860f1 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_cache.go @@ -0,0 +1,249 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ActionsCache represents a GitHub action cache. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#about-the-cache-api +type ActionsCache struct { + ID *int64 `json:"id,omitempty" url:"-"` + Ref *string `json:"ref,omitempty" url:"ref"` + Key *string `json:"key,omitempty" url:"key"` + Version *string `json:"version,omitempty" url:"-"` + LastAccessedAt *Timestamp `json:"last_accessed_at,omitempty" url:"-"` + CreatedAt *Timestamp `json:"created_at,omitempty" url:"-"` + SizeInBytes *int64 `json:"size_in_bytes,omitempty" url:"-"` +} + +// ActionsCacheList represents a list of GitHub actions Cache. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#list-github-actions-caches-for-a-repository +type ActionsCacheList struct { + TotalCount int `json:"total_count"` + ActionsCaches []*ActionsCache `json:"actions_caches,omitempty"` +} + +// ActionsCacheUsage represents a GitHub Actions Cache Usage object. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#get-github-actions-cache-usage-for-a-repository +type ActionsCacheUsage struct { + FullName string `json:"full_name"` + ActiveCachesSizeInBytes int64 `json:"active_caches_size_in_bytes"` + ActiveCachesCount int `json:"active_caches_count"` +} + +// ActionsCacheUsageList represents a list of repositories with GitHub Actions cache usage for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#get-github-actions-cache-usage-for-a-repository +type ActionsCacheUsageList struct { + TotalCount int `json:"total_count"` + RepoCacheUsage []*ActionsCacheUsage `json:"repository_cache_usages,omitempty"` +} + +// TotalCacheUsage represents total GitHub actions cache usage of an organization or enterprise. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#get-github-actions-cache-usage-for-an-enterprise +type TotalCacheUsage struct { + TotalActiveCachesUsageSizeInBytes int64 `json:"total_active_caches_size_in_bytes"` + TotalActiveCachesCount int `json:"total_active_caches_count"` +} + +// ActionsCacheListOptions represents a list of all possible optional Query parameters for ListCaches method. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#list-github-actions-caches-for-a-repository +type ActionsCacheListOptions struct { + ListOptions + // The Git reference for the results you want to list. + // The ref for a branch can be formatted either as refs/heads/ + // or simply . To reference a pull request use refs/pull//merge + Ref *string `url:"ref,omitempty"` + Key *string `url:"key,omitempty"` + // Can be one of: "created_at", "last_accessed_at", "size_in_bytes". Default: "last_accessed_at" + Sort *string `url:"sort,omitempty"` + // Can be one of: "asc", "desc" Default: desc + Direction *string `url:"direction,omitempty"` +} + +// ListCaches lists the GitHub Actions caches for a repository. +// You must authenticate using an access token with the repo scope to use this endpoint. +// +// Permissions: must have the actions:read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#list-github-actions-caches-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/caches +func (s *ActionsService) ListCaches(ctx context.Context, owner, repo string, opts *ActionsCacheListOptions) (*ActionsCacheList, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/caches", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + actionCacheList := new(ActionsCacheList) + resp, err := s.client.Do(ctx, req, actionCacheList) + if err != nil { + return nil, resp, err + } + + return actionCacheList, resp, nil +} + +// DeleteCachesByKey deletes one or more GitHub Actions caches for a repository, using a complete cache key. +// By default, all caches that match the provided key are deleted, but you can optionally provide +// a Git ref to restrict deletions to caches that match both the provided key and the Git ref. +// The ref for a branch can be formatted either as "refs/heads/" or simply "". +// To reference a pull request use "refs/pull//merge". If you don't want to use ref just pass nil in parameter. +// +// Permissions: You must authenticate using an access token with the repo scope to use this endpoint. GitHub Apps must have the actions:write permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#delete-github-actions-caches-for-a-repository-using-a-cache-key +// +//meta:operation DELETE /repos/{owner}/{repo}/actions/caches +func (s *ActionsService) DeleteCachesByKey(ctx context.Context, owner, repo, key string, ref *string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/caches", owner, repo) + u, err := addOptions(u, ActionsCache{Key: &key, Ref: ref}) + if err != nil { + return nil, err + } + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteCachesByID deletes a GitHub Actions cache for a repository, using a cache ID. +// +// Permissions: You must authenticate using an access token with the repo scope to use this endpoint. GitHub Apps must have the actions:write permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#delete-a-github-actions-cache-for-a-repository-using-a-cache-id +// +//meta:operation DELETE /repos/{owner}/{repo}/actions/caches/{cache_id} +func (s *ActionsService) DeleteCachesByID(ctx context.Context, owner, repo string, cacheID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/caches/%v", owner, repo, cacheID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// GetCacheUsageForRepo gets GitHub Actions cache usage for a repository. The data fetched using this API is refreshed approximately every 5 minutes, +// so values returned from this endpoint may take at least 5 minutes to get updated. +// +// Permissions: Anyone with read access to the repository can use this endpoint. If the repository is private, you must use an +// access token with the repo scope. GitHub Apps must have the actions:read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#get-github-actions-cache-usage-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/cache/usage +func (s *ActionsService) GetCacheUsageForRepo(ctx context.Context, owner, repo string) (*ActionsCacheUsage, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/cache/usage", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + cacheUsage := new(ActionsCacheUsage) + res, err := s.client.Do(ctx, req, cacheUsage) + if err != nil { + return nil, res, err + } + + return cacheUsage, res, err +} + +// ListCacheUsageByRepoForOrg lists repositories and their GitHub Actions cache usage for an organization. The data fetched using this API is +// refreshed approximately every 5 minutes, so values returned from this endpoint may take at least 5 minutes to get updated. +// +// Permissions: You must authenticate using an access token with the read:org scope to use this endpoint. +// GitHub Apps must have the organization_administration:read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#list-repositories-with-github-actions-cache-usage-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/cache/usage-by-repository +func (s *ActionsService) ListCacheUsageByRepoForOrg(ctx context.Context, org string, opts *ListOptions) (*ActionsCacheUsageList, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/cache/usage-by-repository", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + cacheUsage := new(ActionsCacheUsageList) + res, err := s.client.Do(ctx, req, cacheUsage) + if err != nil { + return nil, res, err + } + + return cacheUsage, res, err +} + +// GetTotalCacheUsageForOrg gets the total GitHub Actions cache usage for an organization. The data fetched using this API is refreshed approximately every +// 5 minutes, so values returned from this endpoint may take at least 5 minutes to get updated. +// +// Permissions: You must authenticate using an access token with the read:org scope to use this endpoint. +// GitHub Apps must have the organization_administration:read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#get-github-actions-cache-usage-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/cache/usage +func (s *ActionsService) GetTotalCacheUsageForOrg(ctx context.Context, org string) (*TotalCacheUsage, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/cache/usage", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + cacheUsage := new(TotalCacheUsage) + res, err := s.client.Do(ctx, req, cacheUsage) + if err != nil { + return nil, res, err + } + + return cacheUsage, res, err +} + +// GetTotalCacheUsageForEnterprise gets the total GitHub Actions cache usage for an enterprise. The data fetched using this API is refreshed approximately every 5 minutes, +// so values returned from this endpoint may take at least 5 minutes to get updated. +// +// Permissions: You must authenticate using an access token with the "admin:enterprise" scope to use this endpoint. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/cache#get-github-actions-cache-usage-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/cache/usage +func (s *ActionsService) GetTotalCacheUsageForEnterprise(ctx context.Context, enterprise string) (*TotalCacheUsage, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/cache/usage", enterprise) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + cacheUsage := new(TotalCacheUsage) + res, err := s.client.Do(ctx, req, cacheUsage) + if err != nil { + return nil, res, err + } + + return cacheUsage, res, err +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_oidc.go b/vendor/github.com/google/go-github/v68/github/actions_oidc.go new file mode 100644 index 0000000000..596aa9d981 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_oidc.go @@ -0,0 +1,81 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// OIDCSubjectClaimCustomTemplate represents an OIDC subject claim customization template. +type OIDCSubjectClaimCustomTemplate struct { + UseDefault *bool `json:"use_default,omitempty"` + IncludeClaimKeys []string `json:"include_claim_keys,omitempty"` +} + +// GetOrgOIDCSubjectClaimCustomTemplate gets the subject claim customization template for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/oidc#get-the-customization-template-for-an-oidc-subject-claim-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/oidc/customization/sub +func (s *ActionsService) GetOrgOIDCSubjectClaimCustomTemplate(ctx context.Context, org string) (*OIDCSubjectClaimCustomTemplate, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/oidc/customization/sub", org) + return s.getOIDCSubjectClaimCustomTemplate(ctx, u) +} + +// GetRepoOIDCSubjectClaimCustomTemplate gets the subject claim customization template for a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/oidc#get-the-customization-template-for-an-oidc-subject-claim-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/oidc/customization/sub +func (s *ActionsService) GetRepoOIDCSubjectClaimCustomTemplate(ctx context.Context, owner, repo string) (*OIDCSubjectClaimCustomTemplate, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/oidc/customization/sub", owner, repo) + return s.getOIDCSubjectClaimCustomTemplate(ctx, u) +} + +func (s *ActionsService) getOIDCSubjectClaimCustomTemplate(ctx context.Context, url string) (*OIDCSubjectClaimCustomTemplate, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + tmpl := new(OIDCSubjectClaimCustomTemplate) + resp, err := s.client.Do(ctx, req, tmpl) + if err != nil { + return nil, resp, err + } + + return tmpl, resp, nil +} + +// SetOrgOIDCSubjectClaimCustomTemplate sets the subject claim customization for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/oidc#set-the-customization-template-for-an-oidc-subject-claim-for-an-organization +// +//meta:operation PUT /orgs/{org}/actions/oidc/customization/sub +func (s *ActionsService) SetOrgOIDCSubjectClaimCustomTemplate(ctx context.Context, org string, template *OIDCSubjectClaimCustomTemplate) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/oidc/customization/sub", org) + return s.setOIDCSubjectClaimCustomTemplate(ctx, u, template) +} + +// SetRepoOIDCSubjectClaimCustomTemplate sets the subject claim customization for a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/oidc#set-the-customization-template-for-an-oidc-subject-claim-for-a-repository +// +//meta:operation PUT /repos/{owner}/{repo}/actions/oidc/customization/sub +func (s *ActionsService) SetRepoOIDCSubjectClaimCustomTemplate(ctx context.Context, owner, repo string, template *OIDCSubjectClaimCustomTemplate) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/oidc/customization/sub", owner, repo) + return s.setOIDCSubjectClaimCustomTemplate(ctx, u, template) +} + +func (s *ActionsService) setOIDCSubjectClaimCustomTemplate(ctx context.Context, url string, template *OIDCSubjectClaimCustomTemplate) (*Response, error) { + req, err := s.client.NewRequest("PUT", url, template) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_permissions_enterprise.go b/vendor/github.com/google/go-github/v68/github/actions_permissions_enterprise.go new file mode 100644 index 0000000000..a6a85aa32a --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_permissions_enterprise.go @@ -0,0 +1,258 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ActionsEnabledOnEnterpriseRepos represents all the repositories in an enterprise for which Actions is enabled. +type ActionsEnabledOnEnterpriseRepos struct { + TotalCount int `json:"total_count"` + Organizations []*Organization `json:"organizations"` +} + +// ActionsPermissionsEnterprise represents a policy for allowed actions in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions +type ActionsPermissionsEnterprise struct { + EnabledOrganizations *string `json:"enabled_organizations,omitempty"` + AllowedActions *string `json:"allowed_actions,omitempty"` + SelectedActionsURL *string `json:"selected_actions_url,omitempty"` +} + +func (a ActionsPermissionsEnterprise) String() string { + return Stringify(a) +} + +// DefaultWorkflowPermissionEnterprise represents the default permissions for GitHub Actions workflows for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions +type DefaultWorkflowPermissionEnterprise struct { + DefaultWorkflowPermissions *string `json:"default_workflow_permissions,omitempty"` + CanApprovePullRequestReviews *bool `json:"can_approve_pull_request_reviews,omitempty"` +} + +// GetActionsPermissionsInEnterprise gets the GitHub Actions permissions policy for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions#get-github-actions-permissions-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/permissions +func (s *ActionsService) GetActionsPermissionsInEnterprise(ctx context.Context, enterprise string) (*ActionsPermissionsEnterprise, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/permissions", enterprise) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + permissions := new(ActionsPermissionsEnterprise) + resp, err := s.client.Do(ctx, req, permissions) + if err != nil { + return nil, resp, err + } + + return permissions, resp, nil +} + +// EditActionsPermissionsInEnterprise sets the permissions policy in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions#set-github-actions-permissions-for-an-enterprise +// +//meta:operation PUT /enterprises/{enterprise}/actions/permissions +func (s *ActionsService) EditActionsPermissionsInEnterprise(ctx context.Context, enterprise string, actionsPermissionsEnterprise ActionsPermissionsEnterprise) (*ActionsPermissionsEnterprise, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/permissions", enterprise) + req, err := s.client.NewRequest("PUT", u, actionsPermissionsEnterprise) + if err != nil { + return nil, nil, err + } + + p := new(ActionsPermissionsEnterprise) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// ListEnabledOrgsInEnterprise lists the selected organizations that are enabled for GitHub Actions in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions#list-selected-organizations-enabled-for-github-actions-in-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/permissions/organizations +func (s *ActionsService) ListEnabledOrgsInEnterprise(ctx context.Context, owner string, opts *ListOptions) (*ActionsEnabledOnEnterpriseRepos, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/permissions/organizations", owner) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + orgs := &ActionsEnabledOnEnterpriseRepos{} + resp, err := s.client.Do(ctx, req, orgs) + if err != nil { + return nil, resp, err + } + + return orgs, resp, nil +} + +// SetEnabledOrgsInEnterprise replaces the list of selected organizations that are enabled for GitHub Actions in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions#set-selected-organizations-enabled-for-github-actions-in-an-enterprise +// +//meta:operation PUT /enterprises/{enterprise}/actions/permissions/organizations +func (s *ActionsService) SetEnabledOrgsInEnterprise(ctx context.Context, owner string, organizationIDs []int64) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/permissions/organizations", owner) + + req, err := s.client.NewRequest("PUT", u, struct { + IDs []int64 `json:"selected_organization_ids"` + }{IDs: organizationIDs}) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// AddEnabledOrgInEnterprise adds an organization to the list of selected organizations that are enabled for GitHub Actions in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions#enable-a-selected-organization-for-github-actions-in-an-enterprise +// +//meta:operation PUT /enterprises/{enterprise}/actions/permissions/organizations/{org_id} +func (s *ActionsService) AddEnabledOrgInEnterprise(ctx context.Context, owner string, organizationID int64) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/permissions/organizations/%v", owner, organizationID) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// RemoveEnabledOrgInEnterprise removes an organization from the list of selected organizations that are enabled for GitHub Actions in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions#disable-a-selected-organization-for-github-actions-in-an-enterprise +// +//meta:operation DELETE /enterprises/{enterprise}/actions/permissions/organizations/{org_id} +func (s *ActionsService) RemoveEnabledOrgInEnterprise(ctx context.Context, owner string, organizationID int64) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/permissions/organizations/%v", owner, organizationID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// GetActionsAllowedInEnterprise gets the actions that are allowed in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions#get-allowed-actions-and-reusable-workflows-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/permissions/selected-actions +func (s *ActionsService) GetActionsAllowedInEnterprise(ctx context.Context, enterprise string) (*ActionsAllowed, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/permissions/selected-actions", enterprise) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + actionsAllowed := new(ActionsAllowed) + resp, err := s.client.Do(ctx, req, actionsAllowed) + if err != nil { + return nil, resp, err + } + + return actionsAllowed, resp, nil +} + +// EditActionsAllowedInEnterprise sets the actions that are allowed in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions#set-allowed-actions-and-reusable-workflows-for-an-enterprise +// +//meta:operation PUT /enterprises/{enterprise}/actions/permissions/selected-actions +func (s *ActionsService) EditActionsAllowedInEnterprise(ctx context.Context, enterprise string, actionsAllowed ActionsAllowed) (*ActionsAllowed, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/permissions/selected-actions", enterprise) + req, err := s.client.NewRequest("PUT", u, actionsAllowed) + if err != nil { + return nil, nil, err + } + + p := new(ActionsAllowed) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// GetDefaultWorkflowPermissionsInEnterprise gets the GitHub Actions default workflow permissions for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions#get-default-workflow-permissions-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/permissions/workflow +func (s *ActionsService) GetDefaultWorkflowPermissionsInEnterprise(ctx context.Context, enterprise string) (*DefaultWorkflowPermissionEnterprise, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/permissions/workflow", enterprise) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + permissions := new(DefaultWorkflowPermissionEnterprise) + resp, err := s.client.Do(ctx, req, permissions) + if err != nil { + return nil, resp, err + } + + return permissions, resp, nil +} + +// EditDefaultWorkflowPermissionsInEnterprise sets the GitHub Actions default workflow permissions for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions#set-default-workflow-permissions-for-an-enterprise +// +//meta:operation PUT /enterprises/{enterprise}/actions/permissions/workflow +func (s *ActionsService) EditDefaultWorkflowPermissionsInEnterprise(ctx context.Context, enterprise string, permissions DefaultWorkflowPermissionEnterprise) (*DefaultWorkflowPermissionEnterprise, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/permissions/workflow", enterprise) + req, err := s.client.NewRequest("PUT", u, permissions) + if err != nil { + return nil, nil, err + } + + p := new(DefaultWorkflowPermissionEnterprise) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_permissions_orgs.go b/vendor/github.com/google/go-github/v68/github/actions_permissions_orgs.go new file mode 100644 index 0000000000..2f555f2493 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_permissions_orgs.go @@ -0,0 +1,271 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ActionsPermissions represents a policy for repositories and allowed actions in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions +type ActionsPermissions struct { + EnabledRepositories *string `json:"enabled_repositories,omitempty"` + AllowedActions *string `json:"allowed_actions,omitempty"` + SelectedActionsURL *string `json:"selected_actions_url,omitempty"` +} + +func (a ActionsPermissions) String() string { + return Stringify(a) +} + +// ActionsEnabledOnOrgRepos represents all the repositories in an organization for which Actions is enabled. +type ActionsEnabledOnOrgRepos struct { + TotalCount int `json:"total_count"` + Repositories []*Repository `json:"repositories"` +} + +// ActionsAllowed represents selected actions that are allowed. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions +type ActionsAllowed struct { + GithubOwnedAllowed *bool `json:"github_owned_allowed,omitempty"` + VerifiedAllowed *bool `json:"verified_allowed,omitempty"` + PatternsAllowed []string `json:"patterns_allowed,omitempty"` +} + +func (a ActionsAllowed) String() string { + return Stringify(a) +} + +// DefaultWorkflowPermissionOrganization represents the default permissions for GitHub Actions workflows for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions +type DefaultWorkflowPermissionOrganization struct { + DefaultWorkflowPermissions *string `json:"default_workflow_permissions,omitempty"` + CanApprovePullRequestReviews *bool `json:"can_approve_pull_request_reviews,omitempty"` +} + +// GetActionsPermissions gets the GitHub Actions permissions policy for repositories and allowed actions in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#get-github-actions-permissions-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/permissions +func (s *ActionsService) GetActionsPermissions(ctx context.Context, org string) (*ActionsPermissions, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + permissions := new(ActionsPermissions) + resp, err := s.client.Do(ctx, req, permissions) + if err != nil { + return nil, resp, err + } + + return permissions, resp, nil +} + +// EditActionsPermissions sets the permissions policy for repositories and allowed actions in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#set-github-actions-permissions-for-an-organization +// +//meta:operation PUT /orgs/{org}/actions/permissions +func (s *ActionsService) EditActionsPermissions(ctx context.Context, org string, actionsPermissions ActionsPermissions) (*ActionsPermissions, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions", org) + req, err := s.client.NewRequest("PUT", u, actionsPermissions) + if err != nil { + return nil, nil, err + } + + p := new(ActionsPermissions) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// ListEnabledReposInOrg lists the selected repositories that are enabled for GitHub Actions in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#list-selected-repositories-enabled-for-github-actions-in-an-organization +// +//meta:operation GET /orgs/{org}/actions/permissions/repositories +func (s *ActionsService) ListEnabledReposInOrg(ctx context.Context, owner string, opts *ListOptions) (*ActionsEnabledOnOrgRepos, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions/repositories", owner) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + repos := &ActionsEnabledOnOrgRepos{} + resp, err := s.client.Do(ctx, req, repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// SetEnabledReposInOrg replaces the list of selected repositories that are enabled for GitHub Actions in an organization.. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#set-selected-repositories-enabled-for-github-actions-in-an-organization +// +//meta:operation PUT /orgs/{org}/actions/permissions/repositories +func (s *ActionsService) SetEnabledReposInOrg(ctx context.Context, owner string, repositoryIDs []int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions/repositories", owner) + + req, err := s.client.NewRequest("PUT", u, struct { + IDs []int64 `json:"selected_repository_ids"` + }{IDs: repositoryIDs}) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// AddEnabledReposInOrg adds a repository to the list of selected repositories that are enabled for GitHub Actions in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#enable-a-selected-repository-for-github-actions-in-an-organization +// +//meta:operation PUT /orgs/{org}/actions/permissions/repositories/{repository_id} +func (s *ActionsService) AddEnabledReposInOrg(ctx context.Context, owner string, repositoryID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions/repositories/%v", owner, repositoryID) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// RemoveEnabledReposInOrg removes a single repository from the list of enabled repos for GitHub Actions in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#disable-a-selected-repository-for-github-actions-in-an-organization +// +//meta:operation DELETE /orgs/{org}/actions/permissions/repositories/{repository_id} +func (s *ActionsService) RemoveEnabledReposInOrg(ctx context.Context, owner string, repositoryID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions/repositories/%v", owner, repositoryID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// GetActionsAllowed gets the actions that are allowed in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#get-allowed-actions-and-reusable-workflows-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/permissions/selected-actions +func (s *ActionsService) GetActionsAllowed(ctx context.Context, org string) (*ActionsAllowed, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions/selected-actions", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + actionsAllowed := new(ActionsAllowed) + resp, err := s.client.Do(ctx, req, actionsAllowed) + if err != nil { + return nil, resp, err + } + + return actionsAllowed, resp, nil +} + +// EditActionsAllowed sets the actions that are allowed in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#set-allowed-actions-and-reusable-workflows-for-an-organization +// +//meta:operation PUT /orgs/{org}/actions/permissions/selected-actions +func (s *ActionsService) EditActionsAllowed(ctx context.Context, org string, actionsAllowed ActionsAllowed) (*ActionsAllowed, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions/selected-actions", org) + req, err := s.client.NewRequest("PUT", u, actionsAllowed) + if err != nil { + return nil, nil, err + } + + p := new(ActionsAllowed) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// GetDefaultWorkflowPermissionsInOrganization gets the GitHub Actions default workflow permissions for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#get-default-workflow-permissions-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/permissions/workflow +func (s *ActionsService) GetDefaultWorkflowPermissionsInOrganization(ctx context.Context, org string) (*DefaultWorkflowPermissionOrganization, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions/workflow", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + permissions := new(DefaultWorkflowPermissionOrganization) + resp, err := s.client.Do(ctx, req, permissions) + if err != nil { + return nil, resp, err + } + + return permissions, resp, nil +} + +// EditDefaultWorkflowPermissionsInOrganization sets the GitHub Actions default workflow permissions for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#set-default-workflow-permissions-for-an-organization +// +//meta:operation PUT /orgs/{org}/actions/permissions/workflow +func (s *ActionsService) EditDefaultWorkflowPermissionsInOrganization(ctx context.Context, org string, permissions DefaultWorkflowPermissionOrganization) (*DefaultWorkflowPermissionOrganization, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions/workflow", org) + req, err := s.client.NewRequest("PUT", u, permissions) + if err != nil { + return nil, nil, err + } + + p := new(DefaultWorkflowPermissionOrganization) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_required_workflows.go b/vendor/github.com/google/go-github/v68/github/actions_required_workflows.go new file mode 100644 index 0000000000..b89741a82a --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_required_workflows.go @@ -0,0 +1,267 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// OrgRequiredWorkflow represents a required workflow object at the org level. +type OrgRequiredWorkflow struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` + Scope *string `json:"scope,omitempty"` + Ref *string `json:"ref,omitempty"` + State *string `json:"state,omitempty"` + SelectedRepositoriesURL *string `json:"selected_repositories_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Repository *Repository `json:"repository,omitempty"` +} + +// OrgRequiredWorkflows represents the required workflows for the org. +type OrgRequiredWorkflows struct { + TotalCount *int `json:"total_count,omitempty"` + RequiredWorkflows []*OrgRequiredWorkflow `json:"required_workflows,omitempty"` +} + +// CreateUpdateRequiredWorkflowOptions represents the input object used to create or update required workflows. +type CreateUpdateRequiredWorkflowOptions struct { + WorkflowFilePath *string `json:"workflow_file_path,omitempty"` + RepositoryID *int64 `json:"repository_id,omitempty"` + Scope *string `json:"scope,omitempty"` + SelectedRepositoryIDs *SelectedRepoIDs `json:"selected_repository_ids,omitempty"` +} + +// RequiredWorkflowSelectedRepos represents the repos that a required workflow is applied to. +type RequiredWorkflowSelectedRepos struct { + TotalCount *int `json:"total_count,omitempty"` + Repositories []*Repository `json:"repositories,omitempty"` +} + +// RepoRequiredWorkflow represents a required workflow object at the repo level. +type RepoRequiredWorkflow struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Name *string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` + State *string `json:"state,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + BadgeURL *string `json:"badge_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + SourceRepository *Repository `json:"source_repository,omitempty"` +} + +// RepoRequiredWorkflows represents the required workflows for a repo. +type RepoRequiredWorkflows struct { + TotalCount *int `json:"total_count,omitempty"` + RequiredWorkflows []*RepoRequiredWorkflow `json:"required_workflows,omitempty"` +} + +// ListOrgRequiredWorkflows lists the RequiredWorkflows for an org. +// +// GitHub API docs: https://docs.github.com/actions/using-workflows/required-workflows +// +//meta:operation GET /orgs/{org}/actions/required_workflows +func (s *ActionsService) ListOrgRequiredWorkflows(ctx context.Context, org string, opts *ListOptions) (*OrgRequiredWorkflows, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/required_workflows", org) + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + requiredWorkflows := new(OrgRequiredWorkflows) + resp, err := s.client.Do(ctx, req, &requiredWorkflows) + if err != nil { + return nil, resp, err + } + + return requiredWorkflows, resp, nil +} + +// CreateRequiredWorkflow creates the required workflow in an org. +// +// GitHub API docs: https://docs.github.com/actions/using-workflows/required-workflows +// +//meta:operation POST /orgs/{org}/actions/required_workflows +func (s *ActionsService) CreateRequiredWorkflow(ctx context.Context, org string, createRequiredWorkflowOptions *CreateUpdateRequiredWorkflowOptions) (*OrgRequiredWorkflow, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/required_workflows", org) + req, err := s.client.NewRequest("POST", url, createRequiredWorkflowOptions) + if err != nil { + return nil, nil, err + } + + orgRequiredWorkflow := new(OrgRequiredWorkflow) + resp, err := s.client.Do(ctx, req, orgRequiredWorkflow) + if err != nil { + return nil, resp, err + } + + return orgRequiredWorkflow, resp, nil +} + +// GetRequiredWorkflowByID get the RequiredWorkflows for an org by its ID. +// +// GitHub API docs: https://docs.github.com/actions/using-workflows/required-workflows +// +//meta:operation GET /orgs/{org}/actions/required_workflows/{workflow_id} +func (s *ActionsService) GetRequiredWorkflowByID(ctx context.Context, owner string, requiredWorkflowID int64) (*OrgRequiredWorkflow, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/required_workflows/%v", owner, requiredWorkflowID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + requiredWorkflow := new(OrgRequiredWorkflow) + resp, err := s.client.Do(ctx, req, &requiredWorkflow) + if err != nil { + return nil, resp, err + } + + return requiredWorkflow, resp, nil +} + +// UpdateRequiredWorkflow updates a required workflow in an org. +// +// GitHub API docs: https://docs.github.com/actions/using-workflows/required-workflows +// +//meta:operation PATCH /orgs/{org}/actions/required_workflows/{workflow_id} +func (s *ActionsService) UpdateRequiredWorkflow(ctx context.Context, org string, requiredWorkflowID int64, updateRequiredWorkflowOptions *CreateUpdateRequiredWorkflowOptions) (*OrgRequiredWorkflow, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/required_workflows/%v", org, requiredWorkflowID) + req, err := s.client.NewRequest("PATCH", url, updateRequiredWorkflowOptions) + if err != nil { + return nil, nil, err + } + + orgRequiredWorkflow := new(OrgRequiredWorkflow) + resp, err := s.client.Do(ctx, req, orgRequiredWorkflow) + if err != nil { + return nil, resp, err + } + + return orgRequiredWorkflow, resp, nil +} + +// DeleteRequiredWorkflow deletes a required workflow in an org. +// +// GitHub API docs: https://docs.github.com/actions/using-workflows/required-workflows +// +//meta:operation DELETE /orgs/{org}/actions/required_workflows/{workflow_id} +func (s *ActionsService) DeleteRequiredWorkflow(ctx context.Context, org string, requiredWorkflowID int64) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/required_workflows/%v", org, requiredWorkflowID) + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// ListRequiredWorkflowSelectedRepos lists the Repositories selected for a workflow. +// +// GitHub API docs: https://docs.github.com/actions/using-workflows/required-workflows +// +//meta:operation GET /orgs/{org}/actions/required_workflows/{workflow_id}/repositories +func (s *ActionsService) ListRequiredWorkflowSelectedRepos(ctx context.Context, org string, requiredWorkflowID int64, opts *ListOptions) (*RequiredWorkflowSelectedRepos, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/required_workflows/%v/repositories", org, requiredWorkflowID) + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + requiredWorkflowRepos := new(RequiredWorkflowSelectedRepos) + resp, err := s.client.Do(ctx, req, &requiredWorkflowRepos) + if err != nil { + return nil, resp, err + } + + return requiredWorkflowRepos, resp, nil +} + +// SetRequiredWorkflowSelectedRepos sets the Repositories selected for a workflow. +// +// GitHub API docs: https://docs.github.com/actions/using-workflows/required-workflows +// +//meta:operation PUT /orgs/{org}/actions/required_workflows/{workflow_id}/repositories +func (s *ActionsService) SetRequiredWorkflowSelectedRepos(ctx context.Context, org string, requiredWorkflowID int64, ids SelectedRepoIDs) (*Response, error) { + type repoIDs struct { + SelectedIDs SelectedRepoIDs `json:"selected_repository_ids"` + } + url := fmt.Sprintf("orgs/%v/actions/required_workflows/%v/repositories", org, requiredWorkflowID) + req, err := s.client.NewRequest("PUT", url, repoIDs{SelectedIDs: ids}) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddRepoToRequiredWorkflow adds the Repository to a required workflow. +// +// GitHub API docs: https://docs.github.com/actions/using-workflows/required-workflows +// +//meta:operation PUT /orgs/{org}/actions/required_workflows/{workflow_id}/repositories/{repository_id} +func (s *ActionsService) AddRepoToRequiredWorkflow(ctx context.Context, org string, requiredWorkflowID, repoID int64) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/required_workflows/%v/repositories/%v", org, requiredWorkflowID, repoID) + req, err := s.client.NewRequest("PUT", url, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// RemoveRepoFromRequiredWorkflow removes the Repository from a required workflow. +// +// GitHub API docs: https://docs.github.com/actions/using-workflows/required-workflows +// +//meta:operation DELETE /orgs/{org}/actions/required_workflows/{workflow_id}/repositories/{repository_id} +func (s *ActionsService) RemoveRepoFromRequiredWorkflow(ctx context.Context, org string, requiredWorkflowID, repoID int64) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/required_workflows/%v/repositories/%v", org, requiredWorkflowID, repoID) + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// ListRepoRequiredWorkflows lists the RequiredWorkflows for a repo. +// +// GitHub API docs: https://docs.github.com/actions/using-workflows/required-workflows +// +//meta:operation GET /repos/{owner}/{repo}/actions/required_workflows +func (s *ActionsService) ListRepoRequiredWorkflows(ctx context.Context, owner, repo string, opts *ListOptions) (*RepoRequiredWorkflows, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/required_workflows", owner, repo) + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + requiredWorkflows := new(RepoRequiredWorkflows) + resp, err := s.client.Do(ctx, req, &requiredWorkflows) + if err != nil { + return nil, resp, err + } + + return requiredWorkflows, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_runner_groups.go b/vendor/github.com/google/go-github/v68/github/actions_runner_groups.go new file mode 100644 index 0000000000..b2ee32f614 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_runner_groups.go @@ -0,0 +1,337 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// RunnerGroup represents a self-hosted runner group configured in an organization. +type RunnerGroup struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Visibility *string `json:"visibility,omitempty"` + Default *bool `json:"default,omitempty"` + SelectedRepositoriesURL *string `json:"selected_repositories_url,omitempty"` + RunnersURL *string `json:"runners_url,omitempty"` + Inherited *bool `json:"inherited,omitempty"` + AllowsPublicRepositories *bool `json:"allows_public_repositories,omitempty"` + RestrictedToWorkflows *bool `json:"restricted_to_workflows,omitempty"` + SelectedWorkflows []string `json:"selected_workflows,omitempty"` + WorkflowRestrictionsReadOnly *bool `json:"workflow_restrictions_read_only,omitempty"` +} + +// RunnerGroups represents a collection of self-hosted runner groups configured for an organization. +type RunnerGroups struct { + TotalCount int `json:"total_count"` + RunnerGroups []*RunnerGroup `json:"runner_groups"` +} + +// CreateRunnerGroupRequest represents a request to create a Runner group for an organization. +type CreateRunnerGroupRequest struct { + Name *string `json:"name,omitempty"` + Visibility *string `json:"visibility,omitempty"` + // List of repository IDs that can access the runner group. + SelectedRepositoryIDs []int64 `json:"selected_repository_ids,omitempty"` + // Runners represent a list of runner IDs to add to the runner group. + Runners []int64 `json:"runners,omitempty"` + // If set to True, public repos can use this runner group + AllowsPublicRepositories *bool `json:"allows_public_repositories,omitempty"` + // If true, the runner group will be restricted to running only the workflows specified in the SelectedWorkflows slice. + RestrictedToWorkflows *bool `json:"restricted_to_workflows,omitempty"` + // List of workflows the runner group should be allowed to run. This setting will be ignored unless RestrictedToWorkflows is set to true. + SelectedWorkflows []string `json:"selected_workflows,omitempty"` +} + +// UpdateRunnerGroupRequest represents a request to update a Runner group for an organization. +type UpdateRunnerGroupRequest struct { + Name *string `json:"name,omitempty"` + Visibility *string `json:"visibility,omitempty"` + AllowsPublicRepositories *bool `json:"allows_public_repositories,omitempty"` + RestrictedToWorkflows *bool `json:"restricted_to_workflows,omitempty"` + SelectedWorkflows []string `json:"selected_workflows,omitempty"` +} + +// SetRepoAccessRunnerGroupRequest represents a request to replace the list of repositories +// that can access a self-hosted runner group configured in an organization. +type SetRepoAccessRunnerGroupRequest struct { + // Updated list of repository IDs that should be given access to the runner group. + SelectedRepositoryIDs []int64 `json:"selected_repository_ids"` +} + +// SetRunnerGroupRunnersRequest represents a request to replace the list of +// self-hosted runners that are part of an organization runner group. +type SetRunnerGroupRunnersRequest struct { + // Updated list of runner IDs that should be given access to the runner group. + Runners []int64 `json:"runners"` +} + +// ListOrgRunnerGroupOptions extend ListOptions to have the optional parameters VisibleToRepository. +type ListOrgRunnerGroupOptions struct { + ListOptions + + // Only return runner groups that are allowed to be used by this repository. + VisibleToRepository string `url:"visible_to_repository,omitempty"` +} + +// ListOrganizationRunnerGroups lists all self-hosted runner groups configured in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#list-self-hosted-runner-groups-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/runner-groups +func (s *ActionsService) ListOrganizationRunnerGroups(ctx context.Context, org string, opts *ListOrgRunnerGroupOptions) (*RunnerGroups, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + groups := &RunnerGroups{} + resp, err := s.client.Do(ctx, req, &groups) + if err != nil { + return nil, resp, err + } + + return groups, resp, nil +} + +// GetOrganizationRunnerGroup gets a specific self-hosted runner group for an organization using its RunnerGroup ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#get-a-self-hosted-runner-group-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/runner-groups/{runner_group_id} +func (s *ActionsService) GetOrganizationRunnerGroup(ctx context.Context, org string, groupID int64) (*RunnerGroup, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v", org, groupID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runnerGroup := new(RunnerGroup) + resp, err := s.client.Do(ctx, req, runnerGroup) + if err != nil { + return nil, resp, err + } + + return runnerGroup, resp, nil +} + +// DeleteOrganizationRunnerGroup deletes a self-hosted runner group from an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#delete-a-self-hosted-runner-group-from-an-organization +// +//meta:operation DELETE /orgs/{org}/actions/runner-groups/{runner_group_id} +func (s *ActionsService) DeleteOrganizationRunnerGroup(ctx context.Context, org string, groupID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v", org, groupID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// CreateOrganizationRunnerGroup creates a new self-hosted runner group for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#create-a-self-hosted-runner-group-for-an-organization +// +//meta:operation POST /orgs/{org}/actions/runner-groups +func (s *ActionsService) CreateOrganizationRunnerGroup(ctx context.Context, org string, createReq CreateRunnerGroupRequest) (*RunnerGroup, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups", org) + req, err := s.client.NewRequest("POST", u, createReq) + if err != nil { + return nil, nil, err + } + + runnerGroup := new(RunnerGroup) + resp, err := s.client.Do(ctx, req, runnerGroup) + if err != nil { + return nil, resp, err + } + + return runnerGroup, resp, nil +} + +// UpdateOrganizationRunnerGroup updates a self-hosted runner group for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#update-a-self-hosted-runner-group-for-an-organization +// +//meta:operation PATCH /orgs/{org}/actions/runner-groups/{runner_group_id} +func (s *ActionsService) UpdateOrganizationRunnerGroup(ctx context.Context, org string, groupID int64, updateReq UpdateRunnerGroupRequest) (*RunnerGroup, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v", org, groupID) + req, err := s.client.NewRequest("PATCH", u, updateReq) + if err != nil { + return nil, nil, err + } + + runnerGroup := new(RunnerGroup) + resp, err := s.client.Do(ctx, req, runnerGroup) + if err != nil { + return nil, resp, err + } + + return runnerGroup, resp, nil +} + +// ListRepositoryAccessRunnerGroup lists the repositories with access to a self-hosted runner group configured in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#list-repository-access-to-a-self-hosted-runner-group-in-an-organization +// +//meta:operation GET /orgs/{org}/actions/runner-groups/{runner_group_id}/repositories +func (s *ActionsService) ListRepositoryAccessRunnerGroup(ctx context.Context, org string, groupID int64, opts *ListOptions) (*ListRepositories, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/repositories", org, groupID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + repos := &ListRepositories{} + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// SetRepositoryAccessRunnerGroup replaces the list of repositories that have access to a self-hosted runner group configured in an organization +// with a new List of repositories. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#set-repository-access-for-a-self-hosted-runner-group-in-an-organization +// +//meta:operation PUT /orgs/{org}/actions/runner-groups/{runner_group_id}/repositories +func (s *ActionsService) SetRepositoryAccessRunnerGroup(ctx context.Context, org string, groupID int64, ids SetRepoAccessRunnerGroupRequest) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/repositories", org, groupID) + + req, err := s.client.NewRequest("PUT", u, ids) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddRepositoryAccessRunnerGroup adds a repository to the list of selected repositories that can access a self-hosted runner group. +// The runner group must have visibility set to 'selected'. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#add-repository-access-to-a-self-hosted-runner-group-in-an-organization +// +//meta:operation PUT /orgs/{org}/actions/runner-groups/{runner_group_id}/repositories/{repository_id} +func (s *ActionsService) AddRepositoryAccessRunnerGroup(ctx context.Context, org string, groupID, repoID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/repositories/%v", org, groupID, repoID) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveRepositoryAccessRunnerGroup removes a repository from the list of selected repositories that can access a self-hosted runner group. +// The runner group must have visibility set to 'selected'. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#remove-repository-access-to-a-self-hosted-runner-group-in-an-organization +// +//meta:operation DELETE /orgs/{org}/actions/runner-groups/{runner_group_id}/repositories/{repository_id} +func (s *ActionsService) RemoveRepositoryAccessRunnerGroup(ctx context.Context, org string, groupID, repoID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/repositories/%v", org, groupID, repoID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListRunnerGroupRunners lists self-hosted runners that are in a specific organization group. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#list-self-hosted-runners-in-a-group-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/runner-groups/{runner_group_id}/runners +func (s *ActionsService) ListRunnerGroupRunners(ctx context.Context, org string, groupID int64, opts *ListOptions) (*Runners, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/runners", org, groupID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runners := &Runners{} + resp, err := s.client.Do(ctx, req, &runners) + if err != nil { + return nil, resp, err + } + + return runners, resp, nil +} + +// SetRunnerGroupRunners replaces the list of self-hosted runners that are part of an organization runner group +// with a new list of runners. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#set-self-hosted-runners-in-a-group-for-an-organization +// +//meta:operation PUT /orgs/{org}/actions/runner-groups/{runner_group_id}/runners +func (s *ActionsService) SetRunnerGroupRunners(ctx context.Context, org string, groupID int64, ids SetRunnerGroupRunnersRequest) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/runners", org, groupID) + + req, err := s.client.NewRequest("PUT", u, ids) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddRunnerGroupRunners adds a self-hosted runner to a runner group configured in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#add-a-self-hosted-runner-to-a-group-for-an-organization +// +//meta:operation PUT /orgs/{org}/actions/runner-groups/{runner_group_id}/runners/{runner_id} +func (s *ActionsService) AddRunnerGroupRunners(ctx context.Context, org string, groupID, runnerID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/runners/%v", org, groupID, runnerID) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveRunnerGroupRunners removes a self-hosted runner from a group configured in an organization. +// The runner is then returned to the default group. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#remove-a-self-hosted-runner-from-a-group-for-an-organization +// +//meta:operation DELETE /orgs/{org}/actions/runner-groups/{runner_group_id}/runners/{runner_id} +func (s *ActionsService) RemoveRunnerGroupRunners(ctx context.Context, org string, groupID, runnerID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/runners/%v", org, groupID, runnerID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_runners.go b/vendor/github.com/google/go-github/v68/github/actions_runners.go new file mode 100644 index 0000000000..c4ae48232e --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_runners.go @@ -0,0 +1,377 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// RunnerApplicationDownload represents a binary for the self-hosted runner application that can be downloaded. +type RunnerApplicationDownload struct { + OS *string `json:"os,omitempty"` + Architecture *string `json:"architecture,omitempty"` + DownloadURL *string `json:"download_url,omitempty"` + Filename *string `json:"filename,omitempty"` + TempDownloadToken *string `json:"temp_download_token,omitempty"` + SHA256Checksum *string `json:"sha256_checksum,omitempty"` +} + +// ListRunnerApplicationDownloads lists self-hosted runner application binaries that can be downloaded and run. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#list-runner-applications-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/runners/downloads +func (s *ActionsService) ListRunnerApplicationDownloads(ctx context.Context, owner, repo string) ([]*RunnerApplicationDownload, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runners/downloads", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var rads []*RunnerApplicationDownload + resp, err := s.client.Do(ctx, req, &rads) + if err != nil { + return nil, resp, err + } + + return rads, resp, nil +} + +// GenerateJITConfigRequest specifies body parameters to GenerateRepoJITConfig. +type GenerateJITConfigRequest struct { + Name string `json:"name"` + RunnerGroupID int64 `json:"runner_group_id"` + WorkFolder *string `json:"work_folder,omitempty"` + + // Labels represents the names of the custom labels to add to the runner. + // Minimum items: 1. Maximum items: 100. + Labels []string `json:"labels"` +} + +// JITRunnerConfig represents encoded JIT configuration that can be used to bootstrap a self-hosted runner. +type JITRunnerConfig struct { + Runner *Runner `json:"runner,omitempty"` + EncodedJITConfig *string `json:"encoded_jit_config,omitempty"` +} + +// GenerateOrgJITConfig generate a just-in-time configuration for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#create-configuration-for-a-just-in-time-runner-for-an-organization +// +//meta:operation POST /orgs/{org}/actions/runners/generate-jitconfig +func (s *ActionsService) GenerateOrgJITConfig(ctx context.Context, org string, request *GenerateJITConfigRequest) (*JITRunnerConfig, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runners/generate-jitconfig", org) + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + jitConfig := new(JITRunnerConfig) + resp, err := s.client.Do(ctx, req, jitConfig) + if err != nil { + return nil, resp, err + } + + return jitConfig, resp, nil +} + +// GenerateRepoJITConfig generates a just-in-time configuration for a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#create-configuration-for-a-just-in-time-runner-for-a-repository +// +//meta:operation POST /repos/{owner}/{repo}/actions/runners/generate-jitconfig +func (s *ActionsService) GenerateRepoJITConfig(ctx context.Context, owner, repo string, request *GenerateJITConfigRequest) (*JITRunnerConfig, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runners/generate-jitconfig", owner, repo) + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + jitConfig := new(JITRunnerConfig) + resp, err := s.client.Do(ctx, req, jitConfig) + if err != nil { + return nil, resp, err + } + + return jitConfig, resp, nil +} + +// RegistrationToken represents a token that can be used to add a self-hosted runner to a repository. +type RegistrationToken struct { + Token *string `json:"token,omitempty"` + ExpiresAt *Timestamp `json:"expires_at,omitempty"` +} + +// CreateRegistrationToken creates a token that can be used to add a self-hosted runner. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#create-a-registration-token-for-a-repository +// +//meta:operation POST /repos/{owner}/{repo}/actions/runners/registration-token +func (s *ActionsService) CreateRegistrationToken(ctx context.Context, owner, repo string) (*RegistrationToken, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runners/registration-token", owner, repo) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + registrationToken := new(RegistrationToken) + resp, err := s.client.Do(ctx, req, registrationToken) + if err != nil { + return nil, resp, err + } + + return registrationToken, resp, nil +} + +// Runner represents a self-hosted runner registered with a repository. +type Runner struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + OS *string `json:"os,omitempty"` + Status *string `json:"status,omitempty"` + Busy *bool `json:"busy,omitempty"` + Labels []*RunnerLabels `json:"labels,omitempty"` +} + +// RunnerLabels represents a collection of labels attached to each runner. +type RunnerLabels struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Type *string `json:"type,omitempty"` +} + +// Runners represents a collection of self-hosted runners for a repository. +type Runners struct { + TotalCount int `json:"total_count"` + Runners []*Runner `json:"runners"` +} + +// ListRunnersOptions specifies the optional parameters to the ListRunners and ListOrganizationRunners methods. +type ListRunnersOptions struct { + Name *string `url:"name,omitempty"` + ListOptions +} + +// ListRunners lists all the self-hosted runners for a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#list-self-hosted-runners-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/runners +func (s *ActionsService) ListRunners(ctx context.Context, owner, repo string, opts *ListRunnersOptions) (*Runners, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runners", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runners := &Runners{} + resp, err := s.client.Do(ctx, req, &runners) + if err != nil { + return nil, resp, err + } + + return runners, resp, nil +} + +// GetRunner gets a specific self-hosted runner for a repository using its runner ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#get-a-self-hosted-runner-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/runners/{runner_id} +func (s *ActionsService) GetRunner(ctx context.Context, owner, repo string, runnerID int64) (*Runner, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runners/%v", owner, repo, runnerID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runner := new(Runner) + resp, err := s.client.Do(ctx, req, runner) + if err != nil { + return nil, resp, err + } + + return runner, resp, nil +} + +// RemoveToken represents a token that can be used to remove a self-hosted runner from a repository. +type RemoveToken struct { + Token *string `json:"token,omitempty"` + ExpiresAt *Timestamp `json:"expires_at,omitempty"` +} + +// CreateRemoveToken creates a token that can be used to remove a self-hosted runner from a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#create-a-remove-token-for-a-repository +// +//meta:operation POST /repos/{owner}/{repo}/actions/runners/remove-token +func (s *ActionsService) CreateRemoveToken(ctx context.Context, owner, repo string) (*RemoveToken, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runners/remove-token", owner, repo) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + removeToken := new(RemoveToken) + resp, err := s.client.Do(ctx, req, removeToken) + if err != nil { + return nil, resp, err + } + + return removeToken, resp, nil +} + +// RemoveRunner forces the removal of a self-hosted runner in a repository using the runner id. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#delete-a-self-hosted-runner-from-a-repository +// +//meta:operation DELETE /repos/{owner}/{repo}/actions/runners/{runner_id} +func (s *ActionsService) RemoveRunner(ctx context.Context, owner, repo string, runnerID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runners/%v", owner, repo, runnerID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListOrganizationRunnerApplicationDownloads lists self-hosted runner application binaries that can be downloaded and run. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#list-runner-applications-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/runners/downloads +func (s *ActionsService) ListOrganizationRunnerApplicationDownloads(ctx context.Context, org string) ([]*RunnerApplicationDownload, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runners/downloads", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var rads []*RunnerApplicationDownload + resp, err := s.client.Do(ctx, req, &rads) + if err != nil { + return nil, resp, err + } + + return rads, resp, nil +} + +// CreateOrganizationRegistrationToken creates a token that can be used to add a self-hosted runner to an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#create-a-registration-token-for-an-organization +// +//meta:operation POST /orgs/{org}/actions/runners/registration-token +func (s *ActionsService) CreateOrganizationRegistrationToken(ctx context.Context, org string) (*RegistrationToken, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runners/registration-token", org) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + registrationToken := new(RegistrationToken) + resp, err := s.client.Do(ctx, req, registrationToken) + if err != nil { + return nil, resp, err + } + + return registrationToken, resp, nil +} + +// ListOrganizationRunners lists all the self-hosted runners for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#list-self-hosted-runners-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/runners +func (s *ActionsService) ListOrganizationRunners(ctx context.Context, org string, opts *ListRunnersOptions) (*Runners, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runners", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runners := &Runners{} + resp, err := s.client.Do(ctx, req, &runners) + if err != nil { + return nil, resp, err + } + + return runners, resp, nil +} + +// GetOrganizationRunner gets a specific self-hosted runner for an organization using its runner ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#get-a-self-hosted-runner-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/runners/{runner_id} +func (s *ActionsService) GetOrganizationRunner(ctx context.Context, org string, runnerID int64) (*Runner, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runners/%v", org, runnerID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runner := new(Runner) + resp, err := s.client.Do(ctx, req, runner) + if err != nil { + return nil, resp, err + } + + return runner, resp, nil +} + +// CreateOrganizationRemoveToken creates a token that can be used to remove a self-hosted runner from an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#create-a-remove-token-for-an-organization +// +//meta:operation POST /orgs/{org}/actions/runners/remove-token +func (s *ActionsService) CreateOrganizationRemoveToken(ctx context.Context, org string) (*RemoveToken, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runners/remove-token", org) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + removeToken := new(RemoveToken) + resp, err := s.client.Do(ctx, req, removeToken) + if err != nil { + return nil, resp, err + } + + return removeToken, resp, nil +} + +// RemoveOrganizationRunner forces the removal of a self-hosted runner from an organization using the runner id. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#delete-a-self-hosted-runner-from-an-organization +// +//meta:operation DELETE /orgs/{org}/actions/runners/{runner_id} +func (s *ActionsService) RemoveOrganizationRunner(ctx context.Context, org string, runnerID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runners/%v", org, runnerID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_secrets.go b/vendor/github.com/google/go-github/v68/github/actions_secrets.go new file mode 100644 index 0000000000..cba85c1004 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_secrets.go @@ -0,0 +1,407 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" + "strconv" +) + +// PublicKey represents the public key that should be used to encrypt secrets. +type PublicKey struct { + KeyID *string `json:"key_id"` + Key *string `json:"key"` +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +// This ensures GitHub Enterprise versions which return a numeric key id +// do not error out when unmarshaling. +func (p *PublicKey) UnmarshalJSON(data []byte) error { + var pk struct { + KeyID interface{} `json:"key_id"` + Key *string `json:"key"` + } + + if err := json.Unmarshal(data, &pk); err != nil { + return err + } + + p.Key = pk.Key + + switch v := pk.KeyID.(type) { + case nil: + return nil + case string: + p.KeyID = &v + case float64: + p.KeyID = Ptr(strconv.FormatFloat(v, 'f', -1, 64)) + default: + return fmt.Errorf("unable to unmarshal %T as a string", v) + } + + return nil +} + +func (s *ActionsService) getPublicKey(ctx context.Context, url string) (*PublicKey, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + pubKey := new(PublicKey) + resp, err := s.client.Do(ctx, req, pubKey) + if err != nil { + return nil, resp, err + } + + return pubKey, resp, nil +} + +// GetRepoPublicKey gets a public key that should be used for secret encryption. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#get-a-repository-public-key +// +//meta:operation GET /repos/{owner}/{repo}/actions/secrets/public-key +func (s *ActionsService) GetRepoPublicKey(ctx context.Context, owner, repo string) (*PublicKey, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/secrets/public-key", owner, repo) + return s.getPublicKey(ctx, url) +} + +// GetOrgPublicKey gets a public key that should be used for secret encryption. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#get-an-organization-public-key +// +//meta:operation GET /orgs/{org}/actions/secrets/public-key +func (s *ActionsService) GetOrgPublicKey(ctx context.Context, org string) (*PublicKey, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/public-key", org) + return s.getPublicKey(ctx, url) +} + +// GetEnvPublicKey gets a public key that should be used for secret encryption. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.7/rest/actions/secrets#get-an-environment-public-key +// +//meta:operation GET /repositories/{repository_id}/environments/{environment_name}/secrets/public-key +func (s *ActionsService) GetEnvPublicKey(ctx context.Context, repoID int, env string) (*PublicKey, *Response, error) { + url := fmt.Sprintf("repositories/%v/environments/%v/secrets/public-key", repoID, env) + return s.getPublicKey(ctx, url) +} + +// Secret represents a repository action secret. +type Secret struct { + Name string `json:"name"` + CreatedAt Timestamp `json:"created_at"` + UpdatedAt Timestamp `json:"updated_at"` + Visibility string `json:"visibility,omitempty"` + SelectedRepositoriesURL string `json:"selected_repositories_url,omitempty"` +} + +// Secrets represents one item from the ListSecrets response. +type Secrets struct { + TotalCount int `json:"total_count"` + Secrets []*Secret `json:"secrets"` +} + +func (s *ActionsService) listSecrets(ctx context.Context, url string, opts *ListOptions) (*Secrets, *Response, error) { + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + secrets := new(Secrets) + resp, err := s.client.Do(ctx, req, &secrets) + if err != nil { + return nil, resp, err + } + + return secrets, resp, nil +} + +// ListRepoSecrets lists all secrets available in a repository +// without revealing their encrypted values. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#list-repository-secrets +// +//meta:operation GET /repos/{owner}/{repo}/actions/secrets +func (s *ActionsService) ListRepoSecrets(ctx context.Context, owner, repo string, opts *ListOptions) (*Secrets, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/secrets", owner, repo) + return s.listSecrets(ctx, url, opts) +} + +// ListRepoOrgSecrets lists all organization secrets available in a repository +// without revealing their encrypted values. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#list-repository-organization-secrets +// +//meta:operation GET /repos/{owner}/{repo}/actions/organization-secrets +func (s *ActionsService) ListRepoOrgSecrets(ctx context.Context, owner, repo string, opts *ListOptions) (*Secrets, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/organization-secrets", owner, repo) + return s.listSecrets(ctx, url, opts) +} + +// ListOrgSecrets lists all secrets available in an organization +// without revealing their encrypted values. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#list-organization-secrets +// +//meta:operation GET /orgs/{org}/actions/secrets +func (s *ActionsService) ListOrgSecrets(ctx context.Context, org string, opts *ListOptions) (*Secrets, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets", org) + return s.listSecrets(ctx, url, opts) +} + +// ListEnvSecrets lists all secrets available in an environment. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.7/rest/actions/secrets#list-environment-secrets +// +//meta:operation GET /repositories/{repository_id}/environments/{environment_name}/secrets +func (s *ActionsService) ListEnvSecrets(ctx context.Context, repoID int, env string, opts *ListOptions) (*Secrets, *Response, error) { + url := fmt.Sprintf("repositories/%v/environments/%v/secrets", repoID, env) + return s.listSecrets(ctx, url, opts) +} + +func (s *ActionsService) getSecret(ctx context.Context, url string) (*Secret, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + secret := new(Secret) + resp, err := s.client.Do(ctx, req, secret) + if err != nil { + return nil, resp, err + } + + return secret, resp, nil +} + +// GetRepoSecret gets a single repository secret without revealing its encrypted value. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#get-a-repository-secret +// +//meta:operation GET /repos/{owner}/{repo}/actions/secrets/{secret_name} +func (s *ActionsService) GetRepoSecret(ctx context.Context, owner, repo, name string) (*Secret, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, name) + return s.getSecret(ctx, url) +} + +// GetOrgSecret gets a single organization secret without revealing its encrypted value. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#get-an-organization-secret +// +//meta:operation GET /orgs/{org}/actions/secrets/{secret_name} +func (s *ActionsService) GetOrgSecret(ctx context.Context, org, name string) (*Secret, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/%v", org, name) + return s.getSecret(ctx, url) +} + +// GetEnvSecret gets a single environment secret without revealing its encrypted value. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.7/rest/actions/secrets#get-an-environment-secret +// +//meta:operation GET /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name} +func (s *ActionsService) GetEnvSecret(ctx context.Context, repoID int, env, secretName string) (*Secret, *Response, error) { + url := fmt.Sprintf("repositories/%v/environments/%v/secrets/%v", repoID, env, secretName) + return s.getSecret(ctx, url) +} + +// SelectedRepoIDs are the repository IDs that have access to the actions secrets. +type SelectedRepoIDs []int64 + +// EncryptedSecret represents a secret that is encrypted using a public key. +// +// The value of EncryptedValue must be your secret, encrypted with +// LibSodium (see documentation here: https://libsodium.gitbook.io/doc/bindings_for_other_languages) +// using the public key retrieved using the GetPublicKey method. +type EncryptedSecret struct { + Name string `json:"-"` + KeyID string `json:"key_id"` + EncryptedValue string `json:"encrypted_value"` + Visibility string `json:"visibility,omitempty"` + SelectedRepositoryIDs SelectedRepoIDs `json:"selected_repository_ids,omitempty"` +} + +func (s *ActionsService) putSecret(ctx context.Context, url string, eSecret *EncryptedSecret) (*Response, error) { + req, err := s.client.NewRequest("PUT", url, eSecret) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// CreateOrUpdateRepoSecret creates or updates a repository secret with an encrypted value. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#create-or-update-a-repository-secret +// +//meta:operation PUT /repos/{owner}/{repo}/actions/secrets/{secret_name} +func (s *ActionsService) CreateOrUpdateRepoSecret(ctx context.Context, owner, repo string, eSecret *EncryptedSecret) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, eSecret.Name) + return s.putSecret(ctx, url, eSecret) +} + +// CreateOrUpdateOrgSecret creates or updates an organization secret with an encrypted value. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#create-or-update-an-organization-secret +// +//meta:operation PUT /orgs/{org}/actions/secrets/{secret_name} +func (s *ActionsService) CreateOrUpdateOrgSecret(ctx context.Context, org string, eSecret *EncryptedSecret) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/%v", org, eSecret.Name) + return s.putSecret(ctx, url, eSecret) +} + +// CreateOrUpdateEnvSecret creates or updates a single environment secret with an encrypted value. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.7/rest/actions/secrets#create-or-update-an-environment-secret +// +//meta:operation PUT /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name} +func (s *ActionsService) CreateOrUpdateEnvSecret(ctx context.Context, repoID int, env string, eSecret *EncryptedSecret) (*Response, error) { + url := fmt.Sprintf("repositories/%v/environments/%v/secrets/%v", repoID, env, eSecret.Name) + return s.putSecret(ctx, url, eSecret) +} + +func (s *ActionsService) deleteSecret(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteRepoSecret deletes a secret in a repository using the secret name. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#delete-a-repository-secret +// +//meta:operation DELETE /repos/{owner}/{repo}/actions/secrets/{secret_name} +func (s *ActionsService) DeleteRepoSecret(ctx context.Context, owner, repo, name string) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, name) + return s.deleteSecret(ctx, url) +} + +// DeleteOrgSecret deletes a secret in an organization using the secret name. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#delete-an-organization-secret +// +//meta:operation DELETE /orgs/{org}/actions/secrets/{secret_name} +func (s *ActionsService) DeleteOrgSecret(ctx context.Context, org, name string) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/%v", org, name) + return s.deleteSecret(ctx, url) +} + +// DeleteEnvSecret deletes a secret in an environment using the secret name. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.7/rest/actions/secrets#delete-an-environment-secret +// +//meta:operation DELETE /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name} +func (s *ActionsService) DeleteEnvSecret(ctx context.Context, repoID int, env, secretName string) (*Response, error) { + url := fmt.Sprintf("repositories/%v/environments/%v/secrets/%v", repoID, env, secretName) + return s.deleteSecret(ctx, url) +} + +// SelectedReposList represents the list of repositories selected for an organization secret. +type SelectedReposList struct { + TotalCount *int `json:"total_count,omitempty"` + Repositories []*Repository `json:"repositories,omitempty"` +} + +func (s *ActionsService) listSelectedReposForSecret(ctx context.Context, url string, opts *ListOptions) (*SelectedReposList, *Response, error) { + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + result := new(SelectedReposList) + resp, err := s.client.Do(ctx, req, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// ListSelectedReposForOrgSecret lists all repositories that have access to a secret. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#list-selected-repositories-for-an-organization-secret +// +//meta:operation GET /orgs/{org}/actions/secrets/{secret_name}/repositories +func (s *ActionsService) ListSelectedReposForOrgSecret(ctx context.Context, org, name string, opts *ListOptions) (*SelectedReposList, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories", org, name) + return s.listSelectedReposForSecret(ctx, url, opts) +} + +func (s *ActionsService) setSelectedReposForSecret(ctx context.Context, url string, ids SelectedRepoIDs) (*Response, error) { + type repoIDs struct { + SelectedIDs SelectedRepoIDs `json:"selected_repository_ids"` + } + + req, err := s.client.NewRequest("PUT", url, repoIDs{SelectedIDs: ids}) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// SetSelectedReposForOrgSecret sets the repositories that have access to a secret. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#set-selected-repositories-for-an-organization-secret +// +//meta:operation PUT /orgs/{org}/actions/secrets/{secret_name}/repositories +func (s *ActionsService) SetSelectedReposForOrgSecret(ctx context.Context, org, name string, ids SelectedRepoIDs) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories", org, name) + return s.setSelectedReposForSecret(ctx, url, ids) +} + +func (s *ActionsService) addSelectedRepoToSecret(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("PUT", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddSelectedRepoToOrgSecret adds a repository to an organization secret. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#add-selected-repository-to-an-organization-secret +// +//meta:operation PUT /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id} +func (s *ActionsService) AddSelectedRepoToOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories/%v", org, name, *repo.ID) + return s.addSelectedRepoToSecret(ctx, url) +} + +func (s *ActionsService) removeSelectedRepoFromSecret(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveSelectedRepoFromOrgSecret removes a repository from an organization secret. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#remove-selected-repository-from-an-organization-secret +// +//meta:operation DELETE /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id} +func (s *ActionsService) RemoveSelectedRepoFromOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories/%v", org, name, *repo.ID) + return s.removeSelectedRepoFromSecret(ctx, url) +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_variables.go b/vendor/github.com/google/go-github/v68/github/actions_variables.go new file mode 100644 index 0000000000..bca46b6df6 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_variables.go @@ -0,0 +1,341 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ActionsVariable represents a repository action variable. +type ActionsVariable struct { + Name string `json:"name"` + Value string `json:"value"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Visibility *string `json:"visibility,omitempty"` + // Used by ListOrgVariables and GetOrgVariables + SelectedRepositoriesURL *string `json:"selected_repositories_url,omitempty"` + // Used by UpdateOrgVariable and CreateOrgVariable + SelectedRepositoryIDs *SelectedRepoIDs `json:"selected_repository_ids,omitempty"` +} + +// ActionsVariables represents one item from the ListVariables response. +type ActionsVariables struct { + TotalCount int `json:"total_count"` + Variables []*ActionsVariable `json:"variables"` +} + +func (s *ActionsService) listVariables(ctx context.Context, url string, opts *ListOptions) (*ActionsVariables, *Response, error) { + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + variables := new(ActionsVariables) + resp, err := s.client.Do(ctx, req, &variables) + if err != nil { + return nil, resp, err + } + + return variables, resp, nil +} + +// ListRepoVariables lists all variables available in a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#list-repository-variables +// +//meta:operation GET /repos/{owner}/{repo}/actions/variables +func (s *ActionsService) ListRepoVariables(ctx context.Context, owner, repo string, opts *ListOptions) (*ActionsVariables, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/variables", owner, repo) + return s.listVariables(ctx, url, opts) +} + +// ListRepoOrgVariables lists all organization variables available in a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#list-repository-organization-variables +// +//meta:operation GET /repos/{owner}/{repo}/actions/organization-variables +func (s *ActionsService) ListRepoOrgVariables(ctx context.Context, owner, repo string, opts *ListOptions) (*ActionsVariables, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/organization-variables", owner, repo) + return s.listVariables(ctx, url, opts) +} + +// ListOrgVariables lists all variables available in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#list-organization-variables +// +//meta:operation GET /orgs/{org}/actions/variables +func (s *ActionsService) ListOrgVariables(ctx context.Context, org string, opts *ListOptions) (*ActionsVariables, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/variables", org) + return s.listVariables(ctx, url, opts) +} + +// ListEnvVariables lists all variables available in an environment. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#list-environment-variables +// +//meta:operation GET /repos/{owner}/{repo}/environments/{environment_name}/variables +func (s *ActionsService) ListEnvVariables(ctx context.Context, owner, repo, env string, opts *ListOptions) (*ActionsVariables, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/environments/%v/variables", owner, repo, env) + return s.listVariables(ctx, url, opts) +} + +func (s *ActionsService) getVariable(ctx context.Context, url string) (*ActionsVariable, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + variable := new(ActionsVariable) + resp, err := s.client.Do(ctx, req, variable) + if err != nil { + return nil, resp, err + } + + return variable, resp, nil +} + +// GetRepoVariable gets a single repository variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#get-a-repository-variable +// +//meta:operation GET /repos/{owner}/{repo}/actions/variables/{name} +func (s *ActionsService) GetRepoVariable(ctx context.Context, owner, repo, name string) (*ActionsVariable, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/variables/%v", owner, repo, name) + return s.getVariable(ctx, url) +} + +// GetOrgVariable gets a single organization variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#get-an-organization-variable +// +//meta:operation GET /orgs/{org}/actions/variables/{name} +func (s *ActionsService) GetOrgVariable(ctx context.Context, org, name string) (*ActionsVariable, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/variables/%v", org, name) + return s.getVariable(ctx, url) +} + +// GetEnvVariable gets a single environment variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#get-an-environment-variable +// +//meta:operation GET /repos/{owner}/{repo}/environments/{environment_name}/variables/{name} +func (s *ActionsService) GetEnvVariable(ctx context.Context, owner, repo, env, variableName string) (*ActionsVariable, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/environments/%v/variables/%v", owner, repo, env, variableName) + return s.getVariable(ctx, url) +} + +func (s *ActionsService) postVariable(ctx context.Context, url string, variable *ActionsVariable) (*Response, error) { + req, err := s.client.NewRequest("POST", url, variable) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// CreateRepoVariable creates a repository variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#create-a-repository-variable +// +//meta:operation POST /repos/{owner}/{repo}/actions/variables +func (s *ActionsService) CreateRepoVariable(ctx context.Context, owner, repo string, variable *ActionsVariable) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/variables", owner, repo) + return s.postVariable(ctx, url, variable) +} + +// CreateOrgVariable creates an organization variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#create-an-organization-variable +// +//meta:operation POST /orgs/{org}/actions/variables +func (s *ActionsService) CreateOrgVariable(ctx context.Context, org string, variable *ActionsVariable) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/variables", org) + return s.postVariable(ctx, url, variable) +} + +// CreateEnvVariable creates an environment variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#create-an-environment-variable +// +//meta:operation POST /repos/{owner}/{repo}/environments/{environment_name}/variables +func (s *ActionsService) CreateEnvVariable(ctx context.Context, owner, repo, env string, variable *ActionsVariable) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/environments/%v/variables", owner, repo, env) + return s.postVariable(ctx, url, variable) +} + +func (s *ActionsService) patchVariable(ctx context.Context, url string, variable *ActionsVariable) (*Response, error) { + req, err := s.client.NewRequest("PATCH", url, variable) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// UpdateRepoVariable updates a repository variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#update-a-repository-variable +// +//meta:operation PATCH /repos/{owner}/{repo}/actions/variables/{name} +func (s *ActionsService) UpdateRepoVariable(ctx context.Context, owner, repo string, variable *ActionsVariable) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/variables/%v", owner, repo, variable.Name) + return s.patchVariable(ctx, url, variable) +} + +// UpdateOrgVariable updates an organization variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#update-an-organization-variable +// +//meta:operation PATCH /orgs/{org}/actions/variables/{name} +func (s *ActionsService) UpdateOrgVariable(ctx context.Context, org string, variable *ActionsVariable) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/variables/%v", org, variable.Name) + return s.patchVariable(ctx, url, variable) +} + +// UpdateEnvVariable updates an environment variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#update-an-environment-variable +// +//meta:operation PATCH /repos/{owner}/{repo}/environments/{environment_name}/variables/{name} +func (s *ActionsService) UpdateEnvVariable(ctx context.Context, owner, repo, env string, variable *ActionsVariable) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/environments/%v/variables/%v", owner, repo, env, variable.Name) + return s.patchVariable(ctx, url, variable) +} + +func (s *ActionsService) deleteVariable(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteRepoVariable deletes a variable in a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#delete-a-repository-variable +// +//meta:operation DELETE /repos/{owner}/{repo}/actions/variables/{name} +func (s *ActionsService) DeleteRepoVariable(ctx context.Context, owner, repo, name string) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/variables/%v", owner, repo, name) + return s.deleteVariable(ctx, url) +} + +// DeleteOrgVariable deletes a variable in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#delete-an-organization-variable +// +//meta:operation DELETE /orgs/{org}/actions/variables/{name} +func (s *ActionsService) DeleteOrgVariable(ctx context.Context, org, name string) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/variables/%v", org, name) + return s.deleteVariable(ctx, url) +} + +// DeleteEnvVariable deletes a variable in an environment. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#delete-an-environment-variable +// +//meta:operation DELETE /repos/{owner}/{repo}/environments/{environment_name}/variables/{name} +func (s *ActionsService) DeleteEnvVariable(ctx context.Context, owner, repo, env, variableName string) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/environments/%v/variables/%v", owner, repo, env, variableName) + return s.deleteVariable(ctx, url) +} + +func (s *ActionsService) listSelectedReposForVariable(ctx context.Context, url string, opts *ListOptions) (*SelectedReposList, *Response, error) { + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + result := new(SelectedReposList) + resp, err := s.client.Do(ctx, req, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// ListSelectedReposForOrgVariable lists all repositories that have access to a variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#list-selected-repositories-for-an-organization-variable +// +//meta:operation GET /orgs/{org}/actions/variables/{name}/repositories +func (s *ActionsService) ListSelectedReposForOrgVariable(ctx context.Context, org, name string, opts *ListOptions) (*SelectedReposList, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/variables/%v/repositories", org, name) + return s.listSelectedReposForVariable(ctx, url, opts) +} + +func (s *ActionsService) setSelectedReposForVariable(ctx context.Context, url string, ids SelectedRepoIDs) (*Response, error) { + type repoIDs struct { + SelectedIDs SelectedRepoIDs `json:"selected_repository_ids"` + } + + req, err := s.client.NewRequest("PUT", url, repoIDs{SelectedIDs: ids}) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// SetSelectedReposForOrgVariable sets the repositories that have access to a variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#set-selected-repositories-for-an-organization-variable +// +//meta:operation PUT /orgs/{org}/actions/variables/{name}/repositories +func (s *ActionsService) SetSelectedReposForOrgVariable(ctx context.Context, org, name string, ids SelectedRepoIDs) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/variables/%v/repositories", org, name) + return s.setSelectedReposForVariable(ctx, url, ids) +} + +func (s *ActionsService) addSelectedRepoToVariable(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("PUT", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddSelectedRepoToOrgVariable adds a repository to an organization variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#add-selected-repository-to-an-organization-variable +// +//meta:operation PUT /orgs/{org}/actions/variables/{name}/repositories/{repository_id} +func (s *ActionsService) AddSelectedRepoToOrgVariable(ctx context.Context, org, name string, repo *Repository) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/variables/%v/repositories/%v", org, name, *repo.ID) + return s.addSelectedRepoToVariable(ctx, url) +} + +func (s *ActionsService) removeSelectedRepoFromVariable(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveSelectedRepoFromOrgVariable removes a repository from an organization variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#remove-selected-repository-from-an-organization-variable +// +//meta:operation DELETE /orgs/{org}/actions/variables/{name}/repositories/{repository_id} +func (s *ActionsService) RemoveSelectedRepoFromOrgVariable(ctx context.Context, org, name string, repo *Repository) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/variables/%v/repositories/%v", org, name, *repo.ID) + return s.removeSelectedRepoFromVariable(ctx, url) +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_workflow_jobs.go b/vendor/github.com/google/go-github/v68/github/actions_workflow_jobs.go new file mode 100644 index 0000000000..84bbe5aa46 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_workflow_jobs.go @@ -0,0 +1,165 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" + "net/url" +) + +// TaskStep represents a single task step from a sequence of tasks of a job. +type TaskStep struct { + Name *string `json:"name,omitempty"` + Status *string `json:"status,omitempty"` + Conclusion *string `json:"conclusion,omitempty"` + Number *int64 `json:"number,omitempty"` + StartedAt *Timestamp `json:"started_at,omitempty"` + CompletedAt *Timestamp `json:"completed_at,omitempty"` +} + +// WorkflowJob represents a repository action workflow job. +type WorkflowJob struct { + ID *int64 `json:"id,omitempty"` + RunID *int64 `json:"run_id,omitempty"` + RunURL *string `json:"run_url,omitempty"` + NodeID *string `json:"node_id,omitempty"` + HeadBranch *string `json:"head_branch,omitempty"` + HeadSHA *string `json:"head_sha,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + Status *string `json:"status,omitempty"` + Conclusion *string `json:"conclusion,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + StartedAt *Timestamp `json:"started_at,omitempty"` + CompletedAt *Timestamp `json:"completed_at,omitempty"` + Name *string `json:"name,omitempty"` + Steps []*TaskStep `json:"steps,omitempty"` + CheckRunURL *string `json:"check_run_url,omitempty"` + // Labels represents runner labels from the `runs-on:` key from a GitHub Actions workflow. + Labels []string `json:"labels,omitempty"` + RunnerID *int64 `json:"runner_id,omitempty"` + RunnerName *string `json:"runner_name,omitempty"` + RunnerGroupID *int64 `json:"runner_group_id,omitempty"` + RunnerGroupName *string `json:"runner_group_name,omitempty"` + RunAttempt *int64 `json:"run_attempt,omitempty"` + WorkflowName *string `json:"workflow_name,omitempty"` +} + +// Jobs represents a slice of repository action workflow job. +type Jobs struct { + TotalCount *int `json:"total_count,omitempty"` + Jobs []*WorkflowJob `json:"jobs,omitempty"` +} + +// ListWorkflowJobsOptions specifies optional parameters to ListWorkflowJobs. +type ListWorkflowJobsOptions struct { + // Filter specifies how jobs should be filtered by their completed_at timestamp. + // Possible values are: + // latest - Returns jobs from the most recent execution of the workflow run + // all - Returns all jobs for a workflow run, including from old executions of the workflow run + // + // Default value is "latest". + Filter string `url:"filter,omitempty"` + ListOptions +} + +// ListWorkflowJobs lists all jobs for a workflow run. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-jobs#list-jobs-for-a-workflow-run +// +//meta:operation GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs +func (s *ActionsService) ListWorkflowJobs(ctx context.Context, owner, repo string, runID int64, opts *ListWorkflowJobsOptions) (*Jobs, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/actions/runs/%v/jobs", owner, repo, runID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + jobs := new(Jobs) + resp, err := s.client.Do(ctx, req, &jobs) + if err != nil { + return nil, resp, err + } + + return jobs, resp, nil +} + +// ListWorkflowJobsAttempt lists jobs for a workflow run Attempt. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-jobs#list-jobs-for-a-workflow-run-attempt +// +//meta:operation GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs +func (s *ActionsService) ListWorkflowJobsAttempt(ctx context.Context, owner, repo string, runID, attemptNumber int64, opts *ListOptions) (*Jobs, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/actions/runs/%v/attempts/%v/jobs", owner, repo, runID, attemptNumber) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + jobs := new(Jobs) + resp, err := s.client.Do(ctx, req, &jobs) + if err != nil { + return nil, resp, err + } + + return jobs, resp, nil +} + +// GetWorkflowJobByID gets a specific job in a workflow run by ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-jobs#get-a-job-for-a-workflow-run +// +//meta:operation GET /repos/{owner}/{repo}/actions/jobs/{job_id} +func (s *ActionsService) GetWorkflowJobByID(ctx context.Context, owner, repo string, jobID int64) (*WorkflowJob, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/jobs/%v", owner, repo, jobID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + job := new(WorkflowJob) + resp, err := s.client.Do(ctx, req, job) + if err != nil { + return nil, resp, err + } + + return job, resp, nil +} + +// GetWorkflowJobLogs gets a redirect URL to download a plain text file of logs for a workflow job. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-jobs#download-job-logs-for-a-workflow-run +// +//meta:operation GET /repos/{owner}/{repo}/actions/jobs/{job_id}/logs +func (s *ActionsService) GetWorkflowJobLogs(ctx context.Context, owner, repo string, jobID int64, maxRedirects int) (*url.URL, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/jobs/%v/logs", owner, repo, jobID) + + resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, maxRedirects) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusFound { + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + } + + parsedURL, err := url.Parse(resp.Header.Get("Location")) + return parsedURL, newResponse(resp), err +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_workflow_runs.go b/vendor/github.com/google/go-github/v68/github/actions_workflow_runs.go new file mode 100644 index 0000000000..122ea1d0e2 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_workflow_runs.go @@ -0,0 +1,475 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" + "net/url" +) + +// WorkflowRun represents a repository action workflow run. +type WorkflowRun struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + NodeID *string `json:"node_id,omitempty"` + HeadBranch *string `json:"head_branch,omitempty"` + HeadSHA *string `json:"head_sha,omitempty"` + Path *string `json:"path,omitempty"` + RunNumber *int `json:"run_number,omitempty"` + RunAttempt *int `json:"run_attempt,omitempty"` + Event *string `json:"event,omitempty"` + DisplayTitle *string `json:"display_title,omitempty"` + Status *string `json:"status,omitempty"` + Conclusion *string `json:"conclusion,omitempty"` + WorkflowID *int64 `json:"workflow_id,omitempty"` + CheckSuiteID *int64 `json:"check_suite_id,omitempty"` + CheckSuiteNodeID *string `json:"check_suite_node_id,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + PullRequests []*PullRequest `json:"pull_requests,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + RunStartedAt *Timestamp `json:"run_started_at,omitempty"` + JobsURL *string `json:"jobs_url,omitempty"` + LogsURL *string `json:"logs_url,omitempty"` + CheckSuiteURL *string `json:"check_suite_url,omitempty"` + ArtifactsURL *string `json:"artifacts_url,omitempty"` + CancelURL *string `json:"cancel_url,omitempty"` + RerunURL *string `json:"rerun_url,omitempty"` + PreviousAttemptURL *string `json:"previous_attempt_url,omitempty"` + HeadCommit *HeadCommit `json:"head_commit,omitempty"` + WorkflowURL *string `json:"workflow_url,omitempty"` + Repository *Repository `json:"repository,omitempty"` + HeadRepository *Repository `json:"head_repository,omitempty"` + Actor *User `json:"actor,omitempty"` + TriggeringActor *User `json:"triggering_actor,omitempty"` + ReferencedWorkflows []*ReferencedWorkflow `json:"referenced_workflows,omitempty"` +} + +// WorkflowRuns represents a slice of repository action workflow run. +type WorkflowRuns struct { + TotalCount *int `json:"total_count,omitempty"` + WorkflowRuns []*WorkflowRun `json:"workflow_runs,omitempty"` +} + +// ListWorkflowRunsOptions specifies optional parameters to ListWorkflowRuns. +type ListWorkflowRunsOptions struct { + Actor string `url:"actor,omitempty"` + Branch string `url:"branch,omitempty"` + Event string `url:"event,omitempty"` + Status string `url:"status,omitempty"` + Created string `url:"created,omitempty"` + HeadSHA string `url:"head_sha,omitempty"` + ExcludePullRequests bool `url:"exclude_pull_requests,omitempty"` + CheckSuiteID int64 `url:"check_suite_id,omitempty"` + ListOptions +} + +// WorkflowRunUsage represents a usage of a specific workflow run. +type WorkflowRunUsage struct { + Billable *WorkflowRunBillMap `json:"billable,omitempty"` + RunDurationMS *int64 `json:"run_duration_ms,omitempty"` +} + +// WorkflowRunBillMap represents different runner environments available for a workflow run. +// Its key is the name of its environment, e.g. "UBUNTU", "MACOS", "WINDOWS", etc. +type WorkflowRunBillMap map[string]*WorkflowRunBill + +// WorkflowRunBill specifies billable time for a specific environment in a workflow run. +type WorkflowRunBill struct { + TotalMS *int64 `json:"total_ms,omitempty"` + Jobs *int `json:"jobs,omitempty"` + JobRuns []*WorkflowRunJobRun `json:"job_runs,omitempty"` +} + +// WorkflowRunJobRun represents a usage of individual jobs of a specific workflow run. +type WorkflowRunJobRun struct { + JobID *int `json:"job_id,omitempty"` + DurationMS *int64 `json:"duration_ms,omitempty"` +} + +// WorkflowRunAttemptOptions specifies optional parameters to GetWorkflowRunAttempt. +type WorkflowRunAttemptOptions struct { + ExcludePullRequests *bool `url:"exclude_pull_requests,omitempty"` +} + +// PendingDeploymentsRequest specifies body parameters to PendingDeployments. +type PendingDeploymentsRequest struct { + EnvironmentIDs []int64 `json:"environment_ids"` + // State can be one of: "approved", "rejected". + State string `json:"state"` + Comment string `json:"comment"` +} + +type ReferencedWorkflow struct { + Path *string `json:"path,omitempty"` + SHA *string `json:"sha,omitempty"` + Ref *string `json:"ref,omitempty"` +} + +// PendingDeployment represents the pending_deployments response. +type PendingDeployment struct { + Environment *PendingDeploymentEnvironment `json:"environment,omitempty"` + WaitTimer *int64 `json:"wait_timer,omitempty"` + WaitTimerStartedAt *Timestamp `json:"wait_timer_started_at,omitempty"` + CurrentUserCanApprove *bool `json:"current_user_can_approve,omitempty"` + Reviewers []*RequiredReviewer `json:"reviewers,omitempty"` +} + +// PendingDeploymentEnvironment represents pending deployment environment properties. +type PendingDeploymentEnvironment struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Name *string `json:"name,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` +} + +// ReviewCustomDeploymentProtectionRuleRequest specifies the parameters to ReviewCustomDeploymentProtectionRule. +type ReviewCustomDeploymentProtectionRuleRequest struct { + EnvironmentName string `json:"environment_name"` + State string `json:"state"` + Comment string `json:"comment"` +} + +func (s *ActionsService) listWorkflowRuns(ctx context.Context, endpoint string, opts *ListWorkflowRunsOptions) (*WorkflowRuns, *Response, error) { + u, err := addOptions(endpoint, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runs := new(WorkflowRuns) + resp, err := s.client.Do(ctx, req, &runs) + if err != nil { + return nil, resp, err + } + + return runs, resp, nil +} + +// ListWorkflowRunsByID lists all workflow runs by workflow ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#list-workflow-runs-for-a-workflow +// +//meta:operation GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs +func (s *ActionsService) ListWorkflowRunsByID(ctx context.Context, owner, repo string, workflowID int64, opts *ListWorkflowRunsOptions) (*WorkflowRuns, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/actions/workflows/%v/runs", owner, repo, workflowID) + return s.listWorkflowRuns(ctx, u, opts) +} + +// ListWorkflowRunsByFileName lists all workflow runs by workflow file name. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#list-workflow-runs-for-a-workflow +// +//meta:operation GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs +func (s *ActionsService) ListWorkflowRunsByFileName(ctx context.Context, owner, repo, workflowFileName string, opts *ListWorkflowRunsOptions) (*WorkflowRuns, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/actions/workflows/%v/runs", owner, repo, workflowFileName) + return s.listWorkflowRuns(ctx, u, opts) +} + +// ListRepositoryWorkflowRuns lists all workflow runs for a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#list-workflow-runs-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/runs +func (s *ActionsService) ListRepositoryWorkflowRuns(ctx context.Context, owner, repo string, opts *ListWorkflowRunsOptions) (*WorkflowRuns, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/actions/runs", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runs := new(WorkflowRuns) + resp, err := s.client.Do(ctx, req, &runs) + if err != nil { + return nil, resp, err + } + + return runs, resp, nil +} + +// GetWorkflowRunByID gets a specific workflow run by ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#get-a-workflow-run +// +//meta:operation GET /repos/{owner}/{repo}/actions/runs/{run_id} +func (s *ActionsService) GetWorkflowRunByID(ctx context.Context, owner, repo string, runID int64) (*WorkflowRun, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v", owner, repo, runID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + run := new(WorkflowRun) + resp, err := s.client.Do(ctx, req, run) + if err != nil { + return nil, resp, err + } + + return run, resp, nil +} + +// GetWorkflowRunAttempt gets a specific workflow run attempt. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#get-a-workflow-run-attempt +// +//meta:operation GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number} +func (s *ActionsService) GetWorkflowRunAttempt(ctx context.Context, owner, repo string, runID int64, attemptNumber int, opts *WorkflowRunAttemptOptions) (*WorkflowRun, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/attempts/%v", owner, repo, runID, attemptNumber) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + run := new(WorkflowRun) + resp, err := s.client.Do(ctx, req, run) + if err != nil { + return nil, resp, err + } + + return run, resp, nil +} + +// GetWorkflowRunAttemptLogs gets a redirect URL to download a plain text file of logs for a workflow run for attempt number. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#download-workflow-run-attempt-logs +// +//meta:operation GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/logs +func (s *ActionsService) GetWorkflowRunAttemptLogs(ctx context.Context, owner, repo string, runID int64, attemptNumber int, maxRedirects int) (*url.URL, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/attempts/%v/logs", owner, repo, runID, attemptNumber) + + resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, maxRedirects) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusFound { + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + } + + parsedURL, err := url.Parse(resp.Header.Get("Location")) + return parsedURL, newResponse(resp), err +} + +// RerunWorkflowByID re-runs a workflow by ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#re-run-a-workflow +// +//meta:operation POST /repos/{owner}/{repo}/actions/runs/{run_id}/rerun +func (s *ActionsService) RerunWorkflowByID(ctx context.Context, owner, repo string, runID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/rerun", owner, repo, runID) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RerunFailedJobsByID re-runs all of the failed jobs and their dependent jobs in a workflow run by ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#re-run-failed-jobs-from-a-workflow-run +// +//meta:operation POST /repos/{owner}/{repo}/actions/runs/{run_id}/rerun-failed-jobs +func (s *ActionsService) RerunFailedJobsByID(ctx context.Context, owner, repo string, runID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/rerun-failed-jobs", owner, repo, runID) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RerunJobByID re-runs a job and its dependent jobs in a workflow run by ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#re-run-a-job-from-a-workflow-run +// +//meta:operation POST /repos/{owner}/{repo}/actions/jobs/{job_id}/rerun +func (s *ActionsService) RerunJobByID(ctx context.Context, owner, repo string, jobID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/jobs/%v/rerun", owner, repo, jobID) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// CancelWorkflowRunByID cancels a workflow run by ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#cancel-a-workflow-run +// +//meta:operation POST /repos/{owner}/{repo}/actions/runs/{run_id}/cancel +func (s *ActionsService) CancelWorkflowRunByID(ctx context.Context, owner, repo string, runID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/cancel", owner, repo, runID) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// GetWorkflowRunLogs gets a redirect URL to download a plain text file of logs for a workflow run. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#download-workflow-run-logs +// +//meta:operation GET /repos/{owner}/{repo}/actions/runs/{run_id}/logs +func (s *ActionsService) GetWorkflowRunLogs(ctx context.Context, owner, repo string, runID int64, maxRedirects int) (*url.URL, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/logs", owner, repo, runID) + + resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, maxRedirects) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusFound { + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + } + + parsedURL, err := url.Parse(resp.Header.Get("Location")) + return parsedURL, newResponse(resp), err +} + +// DeleteWorkflowRun deletes a workflow run by ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#delete-a-workflow-run +// +//meta:operation DELETE /repos/{owner}/{repo}/actions/runs/{run_id} +func (s *ActionsService) DeleteWorkflowRun(ctx context.Context, owner, repo string, runID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v", owner, repo, runID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteWorkflowRunLogs deletes all logs for a workflow run. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#delete-workflow-run-logs +// +//meta:operation DELETE /repos/{owner}/{repo}/actions/runs/{run_id}/logs +func (s *ActionsService) DeleteWorkflowRunLogs(ctx context.Context, owner, repo string, runID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/logs", owner, repo, runID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// GetWorkflowRunUsageByID gets a specific workflow usage run by run ID in the unit of billable milliseconds. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#get-workflow-run-usage +// +//meta:operation GET /repos/{owner}/{repo}/actions/runs/{run_id}/timing +func (s *ActionsService) GetWorkflowRunUsageByID(ctx context.Context, owner, repo string, runID int64) (*WorkflowRunUsage, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/timing", owner, repo, runID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + workflowRunUsage := new(WorkflowRunUsage) + resp, err := s.client.Do(ctx, req, workflowRunUsage) + if err != nil { + return nil, resp, err + } + + return workflowRunUsage, resp, nil +} + +// GetPendingDeployments get all deployment environments for a workflow run that are waiting for protection rules to pass. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#get-pending-deployments-for-a-workflow-run +// +//meta:operation GET /repos/{owner}/{repo}/actions/runs/{run_id}/pending_deployments +func (s *ActionsService) GetPendingDeployments(ctx context.Context, owner, repo string, runID int64) ([]*PendingDeployment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/pending_deployments", owner, repo, runID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var deployments []*PendingDeployment + resp, err := s.client.Do(ctx, req, &deployments) + if err != nil { + return nil, resp, err + } + + return deployments, resp, nil +} + +// PendingDeployments approve or reject pending deployments that are waiting on approval by a required reviewer. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#review-pending-deployments-for-a-workflow-run +// +//meta:operation POST /repos/{owner}/{repo}/actions/runs/{run_id}/pending_deployments +func (s *ActionsService) PendingDeployments(ctx context.Context, owner, repo string, runID int64, request *PendingDeploymentsRequest) ([]*Deployment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/pending_deployments", owner, repo, runID) + + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + var deployments []*Deployment + resp, err := s.client.Do(ctx, req, &deployments) + if err != nil { + return nil, resp, err + } + + return deployments, resp, nil +} + +// ReviewCustomDeploymentProtectionRule approves or rejects custom deployment protection rules provided by a GitHub App for a workflow run. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#review-custom-deployment-protection-rules-for-a-workflow-run +// +//meta:operation POST /repos/{owner}/{repo}/actions/runs/{run_id}/deployment_protection_rule +func (s *ActionsService) ReviewCustomDeploymentProtectionRule(ctx context.Context, owner, repo string, runID int64, request *ReviewCustomDeploymentProtectionRuleRequest) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/deployment_protection_rule", owner, repo, runID) + + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + return resp, err +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_workflows.go b/vendor/github.com/google/go-github/v68/github/actions_workflows.go new file mode 100644 index 0000000000..0214e6abff --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_workflows.go @@ -0,0 +1,237 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Workflow represents a repository action workflow. +type Workflow struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Name *string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` + State *string `json:"state,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + BadgeURL *string `json:"badge_url,omitempty"` +} + +// Workflows represents a slice of repository action workflows. +type Workflows struct { + TotalCount *int `json:"total_count,omitempty"` + Workflows []*Workflow `json:"workflows,omitempty"` +} + +// WorkflowUsage represents a usage of a specific workflow. +type WorkflowUsage struct { + Billable *WorkflowBillMap `json:"billable,omitempty"` +} + +// WorkflowBillMap represents different runner environments available for a workflow. +// Its key is the name of its environment, e.g. "UBUNTU", "MACOS", "WINDOWS", etc. +type WorkflowBillMap map[string]*WorkflowBill + +// WorkflowBill specifies billable time for a specific environment in a workflow. +type WorkflowBill struct { + TotalMS *int64 `json:"total_ms,omitempty"` +} + +// CreateWorkflowDispatchEventRequest represents a request to create a workflow dispatch event. +type CreateWorkflowDispatchEventRequest struct { + // Ref represents the reference of the workflow run. + // The reference can be a branch or a tag. + // Ref is required when creating a workflow dispatch event. + Ref string `json:"ref"` + // Inputs represents input keys and values configured in the workflow file. + // The maximum number of properties is 10. + // Default: Any default properties configured in the workflow file will be used when `inputs` are omitted. + Inputs map[string]interface{} `json:"inputs,omitempty"` +} + +// ListWorkflows lists all workflows in a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflows#list-repository-workflows +// +//meta:operation GET /repos/{owner}/{repo}/actions/workflows +func (s *ActionsService) ListWorkflows(ctx context.Context, owner, repo string, opts *ListOptions) (*Workflows, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/actions/workflows", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + workflows := new(Workflows) + resp, err := s.client.Do(ctx, req, &workflows) + if err != nil { + return nil, resp, err + } + + return workflows, resp, nil +} + +// GetWorkflowByID gets a specific workflow by ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflows#get-a-workflow +// +//meta:operation GET /repos/{owner}/{repo}/actions/workflows/{workflow_id} +func (s *ActionsService) GetWorkflowByID(ctx context.Context, owner, repo string, workflowID int64) (*Workflow, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v", owner, repo, workflowID) + + return s.getWorkflow(ctx, u) +} + +// GetWorkflowByFileName gets a specific workflow by file name. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflows#get-a-workflow +// +//meta:operation GET /repos/{owner}/{repo}/actions/workflows/{workflow_id} +func (s *ActionsService) GetWorkflowByFileName(ctx context.Context, owner, repo, workflowFileName string) (*Workflow, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v", owner, repo, workflowFileName) + + return s.getWorkflow(ctx, u) +} + +func (s *ActionsService) getWorkflow(ctx context.Context, url string) (*Workflow, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + workflow := new(Workflow) + resp, err := s.client.Do(ctx, req, workflow) + if err != nil { + return nil, resp, err + } + + return workflow, resp, nil +} + +// GetWorkflowUsageByID gets a specific workflow usage by ID in the unit of billable milliseconds. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflows#get-workflow-usage +// +//meta:operation GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/timing +func (s *ActionsService) GetWorkflowUsageByID(ctx context.Context, owner, repo string, workflowID int64) (*WorkflowUsage, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/timing", owner, repo, workflowID) + + return s.getWorkflowUsage(ctx, u) +} + +// GetWorkflowUsageByFileName gets a specific workflow usage by file name in the unit of billable milliseconds. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflows#get-workflow-usage +// +//meta:operation GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/timing +func (s *ActionsService) GetWorkflowUsageByFileName(ctx context.Context, owner, repo, workflowFileName string) (*WorkflowUsage, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/timing", owner, repo, workflowFileName) + + return s.getWorkflowUsage(ctx, u) +} + +func (s *ActionsService) getWorkflowUsage(ctx context.Context, url string) (*WorkflowUsage, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + workflowUsage := new(WorkflowUsage) + resp, err := s.client.Do(ctx, req, workflowUsage) + if err != nil { + return nil, resp, err + } + + return workflowUsage, resp, nil +} + +// CreateWorkflowDispatchEventByID manually triggers a GitHub Actions workflow run. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflows#create-a-workflow-dispatch-event +// +//meta:operation POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches +func (s *ActionsService) CreateWorkflowDispatchEventByID(ctx context.Context, owner, repo string, workflowID int64, event CreateWorkflowDispatchEventRequest) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/dispatches", owner, repo, workflowID) + + return s.createWorkflowDispatchEvent(ctx, u, &event) +} + +// CreateWorkflowDispatchEventByFileName manually triggers a GitHub Actions workflow run. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflows#create-a-workflow-dispatch-event +// +//meta:operation POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches +func (s *ActionsService) CreateWorkflowDispatchEventByFileName(ctx context.Context, owner, repo, workflowFileName string, event CreateWorkflowDispatchEventRequest) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/dispatches", owner, repo, workflowFileName) + + return s.createWorkflowDispatchEvent(ctx, u, &event) +} + +func (s *ActionsService) createWorkflowDispatchEvent(ctx context.Context, url string, event *CreateWorkflowDispatchEventRequest) (*Response, error) { + req, err := s.client.NewRequest("POST", url, event) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// EnableWorkflowByID enables a workflow and sets the state of the workflow to "active". +// +// GitHub API docs: https://docs.github.com/rest/actions/workflows#enable-a-workflow +// +//meta:operation PUT /repos/{owner}/{repo}/actions/workflows/{workflow_id}/enable +func (s *ActionsService) EnableWorkflowByID(ctx context.Context, owner, repo string, workflowID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/enable", owner, repo, workflowID) + return s.doNewPutRequest(ctx, u) +} + +// EnableWorkflowByFileName enables a workflow and sets the state of the workflow to "active". +// +// GitHub API docs: https://docs.github.com/rest/actions/workflows#enable-a-workflow +// +//meta:operation PUT /repos/{owner}/{repo}/actions/workflows/{workflow_id}/enable +func (s *ActionsService) EnableWorkflowByFileName(ctx context.Context, owner, repo, workflowFileName string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/enable", owner, repo, workflowFileName) + return s.doNewPutRequest(ctx, u) +} + +// DisableWorkflowByID disables a workflow and sets the state of the workflow to "disabled_manually". +// +// GitHub API docs: https://docs.github.com/rest/actions/workflows#disable-a-workflow +// +//meta:operation PUT /repos/{owner}/{repo}/actions/workflows/{workflow_id}/disable +func (s *ActionsService) DisableWorkflowByID(ctx context.Context, owner, repo string, workflowID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/disable", owner, repo, workflowID) + return s.doNewPutRequest(ctx, u) +} + +// DisableWorkflowByFileName disables a workflow and sets the state of the workflow to "disabled_manually". +// +// GitHub API docs: https://docs.github.com/rest/actions/workflows#disable-a-workflow +// +//meta:operation PUT /repos/{owner}/{repo}/actions/workflows/{workflow_id}/disable +func (s *ActionsService) DisableWorkflowByFileName(ctx context.Context, owner, repo, workflowFileName string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/disable", owner, repo, workflowFileName) + return s.doNewPutRequest(ctx, u) +} + +func (s *ActionsService) doNewPutRequest(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("PUT", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/activity.go b/vendor/github.com/google/go-github/v68/github/activity.go new file mode 100644 index 0000000000..edf8cc4397 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/activity.go @@ -0,0 +1,77 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import "context" + +// ActivityService handles communication with the activity related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/activity/ +type ActivityService service + +// FeedLink represents a link to a related resource. +type FeedLink struct { + HRef *string `json:"href,omitempty"` + Type *string `json:"type,omitempty"` +} + +// Feeds represents timeline resources in Atom format. +type Feeds struct { + TimelineURL *string `json:"timeline_url,omitempty"` + UserURL *string `json:"user_url,omitempty"` + CurrentUserPublicURL *string `json:"current_user_public_url,omitempty"` + CurrentUserURL *string `json:"current_user_url,omitempty"` + CurrentUserActorURL *string `json:"current_user_actor_url,omitempty"` + CurrentUserOrganizationURL *string `json:"current_user_organization_url,omitempty"` + CurrentUserOrganizationURLs []string `json:"current_user_organization_urls,omitempty"` + Links *FeedLinks `json:"_links,omitempty"` +} + +// FeedLinks represents the links in a Feed. +type FeedLinks struct { + Timeline *FeedLink `json:"timeline,omitempty"` + User *FeedLink `json:"user,omitempty"` + CurrentUserPublic *FeedLink `json:"current_user_public,omitempty"` + CurrentUser *FeedLink `json:"current_user,omitempty"` + CurrentUserActor *FeedLink `json:"current_user_actor,omitempty"` + CurrentUserOrganization *FeedLink `json:"current_user_organization,omitempty"` + CurrentUserOrganizations []*FeedLink `json:"current_user_organizations,omitempty"` +} + +// ListFeeds lists all the feeds available to the authenticated user. +// +// GitHub provides several timeline resources in Atom format: +// +// Timeline: The GitHub global public timeline +// User: The public timeline for any user, using URI template +// Current user public: The public timeline for the authenticated user +// Current user: The private timeline for the authenticated user +// Current user actor: The private timeline for activity created by the +// authenticated user +// Current user organizations: The private timeline for the organizations +// the authenticated user is a member of. +// +// Note: Private feeds are only returned when authenticating via Basic Auth +// since current feed URIs use the older, non revocable auth tokens. +// +// GitHub API docs: https://docs.github.com/rest/activity/feeds#get-feeds +// +//meta:operation GET /feeds +func (s *ActivityService) ListFeeds(ctx context.Context) (*Feeds, *Response, error) { + req, err := s.client.NewRequest("GET", "feeds", nil) + if err != nil { + return nil, nil, err + } + + f := &Feeds{} + resp, err := s.client.Do(ctx, req, f) + if err != nil { + return nil, resp, err + } + + return f, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/activity_events.go b/vendor/github.com/google/go-github/v68/github/activity_events.go new file mode 100644 index 0000000000..b12baa99e6 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/activity_events.go @@ -0,0 +1,235 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListEvents drinks from the firehose of all public events across GitHub. +// +// GitHub API docs: https://docs.github.com/rest/activity/events#list-public-events +// +//meta:operation GET /events +func (s *ActivityService) ListEvents(ctx context.Context, opts *ListOptions) ([]*Event, *Response, error) { + u, err := addOptions("events", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListRepositoryEvents lists events for a repository. +// +// GitHub API docs: https://docs.github.com/rest/activity/events#list-repository-events +// +//meta:operation GET /repos/{owner}/{repo}/events +func (s *ActivityService) ListRepositoryEvents(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Event, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/events", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListIssueEventsForRepository lists issue events for a repository. +// +// GitHub API docs: https://docs.github.com/rest/issues/events#list-issue-events-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/issues/events +func (s *ActivityService) ListIssueEventsForRepository(ctx context.Context, owner, repo string, opts *ListOptions) ([]*IssueEvent, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/events", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*IssueEvent + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListEventsForRepoNetwork lists public events for a network of repositories. +// +// GitHub API docs: https://docs.github.com/rest/activity/events#list-public-events-for-a-network-of-repositories +// +//meta:operation GET /networks/{owner}/{repo}/events +func (s *ActivityService) ListEventsForRepoNetwork(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Event, *Response, error) { + u := fmt.Sprintf("networks/%v/%v/events", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListEventsForOrganization lists public events for an organization. +// +// GitHub API docs: https://docs.github.com/rest/activity/events#list-public-organization-events +// +//meta:operation GET /orgs/{org}/events +func (s *ActivityService) ListEventsForOrganization(ctx context.Context, org string, opts *ListOptions) ([]*Event, *Response, error) { + u := fmt.Sprintf("orgs/%v/events", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListEventsPerformedByUser lists the events performed by a user. If publicOnly is +// true, only public events will be returned. +// +// GitHub API docs: https://docs.github.com/rest/activity/events#list-events-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/rest/activity/events#list-public-events-for-a-user +// +//meta:operation GET /users/{username}/events +//meta:operation GET /users/{username}/events/public +func (s *ActivityService) ListEventsPerformedByUser(ctx context.Context, user string, publicOnly bool, opts *ListOptions) ([]*Event, *Response, error) { + var u string + if publicOnly { + u = fmt.Sprintf("users/%v/events/public", user) + } else { + u = fmt.Sprintf("users/%v/events", user) + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListEventsReceivedByUser lists the events received by a user. If publicOnly is +// true, only public events will be returned. +// +// GitHub API docs: https://docs.github.com/rest/activity/events#list-events-received-by-the-authenticated-user +// GitHub API docs: https://docs.github.com/rest/activity/events#list-public-events-received-by-a-user +// +//meta:operation GET /users/{username}/received_events +//meta:operation GET /users/{username}/received_events/public +func (s *ActivityService) ListEventsReceivedByUser(ctx context.Context, user string, publicOnly bool, opts *ListOptions) ([]*Event, *Response, error) { + var u string + if publicOnly { + u = fmt.Sprintf("users/%v/received_events/public", user) + } else { + u = fmt.Sprintf("users/%v/received_events", user) + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListUserEventsForOrganization provides the user’s organization dashboard. You +// must be authenticated as the user to view this. +// +// GitHub API docs: https://docs.github.com/rest/activity/events#list-organization-events-for-the-authenticated-user +// +//meta:operation GET /users/{username}/events/orgs/{org} +func (s *ActivityService) ListUserEventsForOrganization(ctx context.Context, org, user string, opts *ListOptions) ([]*Event, *Response, error) { + u := fmt.Sprintf("users/%v/events/orgs/%v", user, org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/activity_notifications.go b/vendor/github.com/google/go-github/v68/github/activity_notifications.go new file mode 100644 index 0000000000..e712323ed4 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/activity_notifications.go @@ -0,0 +1,258 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// Notification identifies a GitHub notification for a user. +type Notification struct { + ID *string `json:"id,omitempty"` + Repository *Repository `json:"repository,omitempty"` + Subject *NotificationSubject `json:"subject,omitempty"` + + // Reason identifies the event that triggered the notification. + // + // GitHub API docs: https://docs.github.com/rest/activity#notification-reasons + Reason *string `json:"reason,omitempty"` + + Unread *bool `json:"unread,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + LastReadAt *Timestamp `json:"last_read_at,omitempty"` + URL *string `json:"url,omitempty"` +} + +// NotificationSubject identifies the subject of a notification. +type NotificationSubject struct { + Title *string `json:"title,omitempty"` + URL *string `json:"url,omitempty"` + LatestCommentURL *string `json:"latest_comment_url,omitempty"` + Type *string `json:"type,omitempty"` +} + +// NotificationListOptions specifies the optional parameters to the +// ActivityService.ListNotifications method. +type NotificationListOptions struct { + All bool `url:"all,omitempty"` + Participating bool `url:"participating,omitempty"` + Since time.Time `url:"since,omitempty"` + Before time.Time `url:"before,omitempty"` + + ListOptions +} + +// ListNotifications lists all notifications for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/activity/notifications#list-notifications-for-the-authenticated-user +// +//meta:operation GET /notifications +func (s *ActivityService) ListNotifications(ctx context.Context, opts *NotificationListOptions) ([]*Notification, *Response, error) { + u := "notifications" + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var notifications []*Notification + resp, err := s.client.Do(ctx, req, ¬ifications) + if err != nil { + return nil, resp, err + } + + return notifications, resp, nil +} + +// ListRepositoryNotifications lists all notifications in a given repository +// for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/activity/notifications#list-repository-notifications-for-the-authenticated-user +// +//meta:operation GET /repos/{owner}/{repo}/notifications +func (s *ActivityService) ListRepositoryNotifications(ctx context.Context, owner, repo string, opts *NotificationListOptions) ([]*Notification, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/notifications", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var notifications []*Notification + resp, err := s.client.Do(ctx, req, ¬ifications) + if err != nil { + return nil, resp, err + } + + return notifications, resp, nil +} + +type markReadOptions struct { + LastReadAt Timestamp `json:"last_read_at,omitempty"` +} + +// MarkNotificationsRead marks all notifications up to lastRead as read. +// +// GitHub API docs: https://docs.github.com/rest/activity/notifications#mark-notifications-as-read +// +//meta:operation PUT /notifications +func (s *ActivityService) MarkNotificationsRead(ctx context.Context, lastRead Timestamp) (*Response, error) { + opts := &markReadOptions{ + LastReadAt: lastRead, + } + req, err := s.client.NewRequest("PUT", "notifications", opts) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// MarkRepositoryNotificationsRead marks all notifications up to lastRead in +// the specified repository as read. +// +// GitHub API docs: https://docs.github.com/rest/activity/notifications#mark-repository-notifications-as-read +// +//meta:operation PUT /repos/{owner}/{repo}/notifications +func (s *ActivityService) MarkRepositoryNotificationsRead(ctx context.Context, owner, repo string, lastRead Timestamp) (*Response, error) { + opts := &markReadOptions{ + LastReadAt: lastRead, + } + u := fmt.Sprintf("repos/%v/%v/notifications", owner, repo) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// GetThread gets the specified notification thread. +// +// GitHub API docs: https://docs.github.com/rest/activity/notifications#get-a-thread +// +//meta:operation GET /notifications/threads/{thread_id} +func (s *ActivityService) GetThread(ctx context.Context, id string) (*Notification, *Response, error) { + u := fmt.Sprintf("notifications/threads/%v", id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + notification := new(Notification) + resp, err := s.client.Do(ctx, req, notification) + if err != nil { + return nil, resp, err + } + + return notification, resp, nil +} + +// MarkThreadRead marks the specified thread as read. +// +// GitHub API docs: https://docs.github.com/rest/activity/notifications#mark-a-thread-as-read +// +//meta:operation PATCH /notifications/threads/{thread_id} +func (s *ActivityService) MarkThreadRead(ctx context.Context, id string) (*Response, error) { + u := fmt.Sprintf("notifications/threads/%v", id) + + req, err := s.client.NewRequest("PATCH", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// MarkThreadDone marks the specified thread as done. +// Marking a thread as "done" is equivalent to marking a notification in your notification inbox on GitHub as done. +// +// GitHub API docs: https://docs.github.com/rest/activity/notifications#mark-a-thread-as-done +// +//meta:operation DELETE /notifications/threads/{thread_id} +func (s *ActivityService) MarkThreadDone(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("notifications/threads/%v", id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// GetThreadSubscription checks to see if the authenticated user is subscribed +// to a thread. +// +// GitHub API docs: https://docs.github.com/rest/activity/notifications#get-a-thread-subscription-for-the-authenticated-user +// +//meta:operation GET /notifications/threads/{thread_id}/subscription +func (s *ActivityService) GetThreadSubscription(ctx context.Context, id string) (*Subscription, *Response, error) { + u := fmt.Sprintf("notifications/threads/%v/subscription", id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + sub := new(Subscription) + resp, err := s.client.Do(ctx, req, sub) + if err != nil { + return nil, resp, err + } + + return sub, resp, nil +} + +// SetThreadSubscription sets the subscription for the specified thread for the +// authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/activity/notifications#set-a-thread-subscription +// +//meta:operation PUT /notifications/threads/{thread_id}/subscription +func (s *ActivityService) SetThreadSubscription(ctx context.Context, id string, subscription *Subscription) (*Subscription, *Response, error) { + u := fmt.Sprintf("notifications/threads/%v/subscription", id) + + req, err := s.client.NewRequest("PUT", u, subscription) + if err != nil { + return nil, nil, err + } + + sub := new(Subscription) + resp, err := s.client.Do(ctx, req, sub) + if err != nil { + return nil, resp, err + } + + return sub, resp, nil +} + +// DeleteThreadSubscription deletes the subscription for the specified thread +// for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/activity/notifications#delete-a-thread-subscription +// +//meta:operation DELETE /notifications/threads/{thread_id}/subscription +func (s *ActivityService) DeleteThreadSubscription(ctx context.Context, id string) (*Response, error) { + u := fmt.Sprintf("notifications/threads/%v/subscription", id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/activity_star.go b/vendor/github.com/google/go-github/v68/github/activity_star.go new file mode 100644 index 0000000000..cebdacf76a --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/activity_star.go @@ -0,0 +1,152 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "strings" +) + +// StarredRepository is returned by ListStarred. +type StarredRepository struct { + StarredAt *Timestamp `json:"starred_at,omitempty"` + Repository *Repository `json:"repo,omitempty"` +} + +// Stargazer represents a user that has starred a repository. +type Stargazer struct { + StarredAt *Timestamp `json:"starred_at,omitempty"` + User *User `json:"user,omitempty"` +} + +// ListStargazers lists people who have starred the specified repo. +// +// GitHub API docs: https://docs.github.com/rest/activity/starring#list-stargazers +// +//meta:operation GET /repos/{owner}/{repo}/stargazers +func (s *ActivityService) ListStargazers(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Stargazer, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/stargazers", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeStarringPreview) + + var stargazers []*Stargazer + resp, err := s.client.Do(ctx, req, &stargazers) + if err != nil { + return nil, resp, err + } + + return stargazers, resp, nil +} + +// ActivityListStarredOptions specifies the optional parameters to the +// ActivityService.ListStarred method. +type ActivityListStarredOptions struct { + // How to sort the repository list. Possible values are: created, updated, + // pushed, full_name. Default is "full_name". + Sort string `url:"sort,omitempty"` + + // Direction in which to sort repositories. Possible values are: asc, desc. + // Default is "asc" when sort is "full_name", otherwise default is "desc". + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// ListStarred lists all the repos starred by a user. Passing the empty string +// will list the starred repositories for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/activity/starring#list-repositories-starred-by-a-user +// GitHub API docs: https://docs.github.com/rest/activity/starring#list-repositories-starred-by-the-authenticated-user +// +//meta:operation GET /user/starred +//meta:operation GET /users/{username}/starred +func (s *ActivityService) ListStarred(ctx context.Context, user string, opts *ActivityListStarredOptions) ([]*StarredRepository, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/starred", user) + } else { + u = "user/starred" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when APIs fully launch + acceptHeaders := []string{mediaTypeStarringPreview, mediaTypeTopicsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var repos []*StarredRepository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// IsStarred checks if a repository is starred by authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/activity/starring#check-if-a-repository-is-starred-by-the-authenticated-user +// +//meta:operation GET /user/starred/{owner}/{repo} +func (s *ActivityService) IsStarred(ctx context.Context, owner, repo string) (bool, *Response, error) { + u := fmt.Sprintf("user/starred/%v/%v", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + starred, err := parseBoolResponse(err) + return starred, resp, err +} + +// Star a repository as the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/activity/starring#star-a-repository-for-the-authenticated-user +// +//meta:operation PUT /user/starred/{owner}/{repo} +func (s *ActivityService) Star(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("user/starred/%v/%v", owner, repo) + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Unstar a repository as the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/activity/starring#unstar-a-repository-for-the-authenticated-user +// +//meta:operation DELETE /user/starred/{owner}/{repo} +func (s *ActivityService) Unstar(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("user/starred/%v/%v", owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/activity_watching.go b/vendor/github.com/google/go-github/v68/github/activity_watching.go new file mode 100644 index 0000000000..348590057b --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/activity_watching.go @@ -0,0 +1,158 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Subscription identifies a repository or thread subscription. +type Subscription struct { + Subscribed *bool `json:"subscribed,omitempty"` + Ignored *bool `json:"ignored,omitempty"` + Reason *string `json:"reason,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + URL *string `json:"url,omitempty"` + + // only populated for repository subscriptions + RepositoryURL *string `json:"repository_url,omitempty"` + + // only populated for thread subscriptions + ThreadURL *string `json:"thread_url,omitempty"` +} + +// ListWatchers lists watchers of a particular repo. +// +// GitHub API docs: https://docs.github.com/rest/activity/watching#list-watchers +// +//meta:operation GET /repos/{owner}/{repo}/subscribers +func (s *ActivityService) ListWatchers(ctx context.Context, owner, repo string, opts *ListOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/subscribers", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var watchers []*User + resp, err := s.client.Do(ctx, req, &watchers) + if err != nil { + return nil, resp, err + } + + return watchers, resp, nil +} + +// ListWatched lists the repositories the specified user is watching. Passing +// the empty string will fetch watched repos for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/activity/watching#list-repositories-watched-by-a-user +// GitHub API docs: https://docs.github.com/rest/activity/watching#list-repositories-watched-by-the-authenticated-user +// +//meta:operation GET /user/subscriptions +//meta:operation GET /users/{username}/subscriptions +func (s *ActivityService) ListWatched(ctx context.Context, user string, opts *ListOptions) ([]*Repository, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/subscriptions", user) + } else { + u = "user/subscriptions" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var watched []*Repository + resp, err := s.client.Do(ctx, req, &watched) + if err != nil { + return nil, resp, err + } + + return watched, resp, nil +} + +// GetRepositorySubscription returns the subscription for the specified +// repository for the authenticated user. If the authenticated user is not +// watching the repository, a nil Subscription is returned. +// +// GitHub API docs: https://docs.github.com/rest/activity/watching#get-a-repository-subscription +// +//meta:operation GET /repos/{owner}/{repo}/subscription +func (s *ActivityService) GetRepositorySubscription(ctx context.Context, owner, repo string) (*Subscription, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + sub := new(Subscription) + resp, err := s.client.Do(ctx, req, sub) + if err != nil { + // if it's just a 404, don't return that as an error + _, err = parseBoolResponse(err) + return nil, resp, err + } + + return sub, resp, nil +} + +// SetRepositorySubscription sets the subscription for the specified repository +// for the authenticated user. +// +// To watch a repository, set subscription.Subscribed to true. +// To ignore notifications made within a repository, set subscription.Ignored to true. +// To stop watching a repository, use DeleteRepositorySubscription. +// +// GitHub API docs: https://docs.github.com/rest/activity/watching#set-a-repository-subscription +// +//meta:operation PUT /repos/{owner}/{repo}/subscription +func (s *ActivityService) SetRepositorySubscription(ctx context.Context, owner, repo string, subscription *Subscription) (*Subscription, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo) + + req, err := s.client.NewRequest("PUT", u, subscription) + if err != nil { + return nil, nil, err + } + + sub := new(Subscription) + resp, err := s.client.Do(ctx, req, sub) + if err != nil { + return nil, resp, err + } + + return sub, resp, nil +} + +// DeleteRepositorySubscription deletes the subscription for the specified +// repository for the authenticated user. +// +// This is used to stop watching a repository. To control whether or not to +// receive notifications from a repository, use SetRepositorySubscription. +// +// GitHub API docs: https://docs.github.com/rest/activity/watching#delete-a-repository-subscription +// +//meta:operation DELETE /repos/{owner}/{repo}/subscription +func (s *ActivityService) DeleteRepositorySubscription(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/admin.go b/vendor/github.com/google/go-github/v68/github/admin.go new file mode 100644 index 0000000000..adf55d6414 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/admin.go @@ -0,0 +1,123 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// AdminService handles communication with the admin related methods of the +// GitHub API. These API routes are normally only accessible for GitHub +// Enterprise installations. +// +// GitHub API docs: https://docs.github.com/rest/enterprise-admin +type AdminService service + +// TeamLDAPMapping represents the mapping between a GitHub team and an LDAP group. +type TeamLDAPMapping struct { + ID *int64 `json:"id,omitempty"` + LDAPDN *string `json:"ldap_dn,omitempty"` + URL *string `json:"url,omitempty"` + Name *string `json:"name,omitempty"` + Slug *string `json:"slug,omitempty"` + Description *string `json:"description,omitempty"` + Privacy *string `json:"privacy,omitempty"` + Permission *string `json:"permission,omitempty"` + + MembersURL *string `json:"members_url,omitempty"` + RepositoriesURL *string `json:"repositories_url,omitempty"` +} + +func (m TeamLDAPMapping) String() string { + return Stringify(m) +} + +// UserLDAPMapping represents the mapping between a GitHub user and an LDAP user. +type UserLDAPMapping struct { + ID *int64 `json:"id,omitempty"` + LDAPDN *string `json:"ldap_dn,omitempty"` + Login *string `json:"login,omitempty"` + AvatarURL *string `json:"avatar_url,omitempty"` + GravatarID *string `json:"gravatar_id,omitempty"` + Type *string `json:"type,omitempty"` + SiteAdmin *bool `json:"site_admin,omitempty"` + + URL *string `json:"url,omitempty"` + EventsURL *string `json:"events_url,omitempty"` + FollowingURL *string `json:"following_url,omitempty"` + FollowersURL *string `json:"followers_url,omitempty"` + GistsURL *string `json:"gists_url,omitempty"` + OrganizationsURL *string `json:"organizations_url,omitempty"` + ReceivedEventsURL *string `json:"received_events_url,omitempty"` + ReposURL *string `json:"repos_url,omitempty"` + StarredURL *string `json:"starred_url,omitempty"` + SubscriptionsURL *string `json:"subscriptions_url,omitempty"` +} + +func (m UserLDAPMapping) String() string { + return Stringify(m) +} + +// Enterprise represents the GitHub enterprise profile. +type Enterprise struct { + ID *int `json:"id,omitempty"` + Slug *string `json:"slug,omitempty"` + Name *string `json:"name,omitempty"` + NodeID *string `json:"node_id,omitempty"` + AvatarURL *string `json:"avatar_url,omitempty"` + Description *string `json:"description,omitempty"` + WebsiteURL *string `json:"website_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +func (m Enterprise) String() string { + return Stringify(m) +} + +// UpdateUserLDAPMapping updates the mapping between a GitHub user and an LDAP user. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/ldap#update-ldap-mapping-for-a-user +// +//meta:operation PATCH /admin/ldap/users/{username}/mapping +func (s *AdminService) UpdateUserLDAPMapping(ctx context.Context, user string, mapping *UserLDAPMapping) (*UserLDAPMapping, *Response, error) { + u := fmt.Sprintf("admin/ldap/users/%v/mapping", user) + req, err := s.client.NewRequest("PATCH", u, mapping) + if err != nil { + return nil, nil, err + } + + m := new(UserLDAPMapping) + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// UpdateTeamLDAPMapping updates the mapping between a GitHub team and an LDAP group. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/ldap#update-ldap-mapping-for-a-team +// +//meta:operation PATCH /admin/ldap/teams/{team_id}/mapping +func (s *AdminService) UpdateTeamLDAPMapping(ctx context.Context, team int64, mapping *TeamLDAPMapping) (*TeamLDAPMapping, *Response, error) { + u := fmt.Sprintf("admin/ldap/teams/%v/mapping", team) + req, err := s.client.NewRequest("PATCH", u, mapping) + if err != nil { + return nil, nil, err + } + + m := new(TeamLDAPMapping) + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/admin_orgs.go b/vendor/github.com/google/go-github/v68/github/admin_orgs.go new file mode 100644 index 0000000000..8b50756b0d --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/admin_orgs.go @@ -0,0 +1,95 @@ +// Copyright 2019 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// createOrgRequest is a subset of Organization and is used internally +// by CreateOrg to pass only the known fields for the endpoint. +type createOrgRequest struct { + Login *string `json:"login,omitempty"` + Admin *string `json:"admin,omitempty"` +} + +// CreateOrg creates a new organization in GitHub Enterprise. +// +// Note that only a subset of the org fields are used and org must +// not be nil. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/orgs#create-an-organization +// +//meta:operation POST /admin/organizations +func (s *AdminService) CreateOrg(ctx context.Context, org *Organization, admin string) (*Organization, *Response, error) { + u := "admin/organizations" + + orgReq := &createOrgRequest{ + Login: org.Login, + Admin: &admin, + } + + req, err := s.client.NewRequest("POST", u, orgReq) + if err != nil { + return nil, nil, err + } + + o := new(Organization) + resp, err := s.client.Do(ctx, req, o) + if err != nil { + return nil, resp, err + } + + return o, resp, nil +} + +// renameOrgRequest is a subset of Organization and is used internally +// by RenameOrg and RenameOrgByName to pass only the known fields for the endpoint. +type renameOrgRequest struct { + Login *string `json:"login,omitempty"` +} + +// RenameOrgResponse is the response given when renaming an Organization. +type RenameOrgResponse struct { + Message *string `json:"message,omitempty"` + URL *string `json:"url,omitempty"` +} + +// RenameOrg renames an organization in GitHub Enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/orgs#update-an-organization-name +// +//meta:operation PATCH /admin/organizations/{org} +func (s *AdminService) RenameOrg(ctx context.Context, org *Organization, newName string) (*RenameOrgResponse, *Response, error) { + return s.RenameOrgByName(ctx, *org.Login, newName) +} + +// RenameOrgByName renames an organization in GitHub Enterprise using its current name. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/orgs#update-an-organization-name +// +//meta:operation PATCH /admin/organizations/{org} +func (s *AdminService) RenameOrgByName(ctx context.Context, org, newName string) (*RenameOrgResponse, *Response, error) { + u := fmt.Sprintf("admin/organizations/%v", org) + + orgReq := &renameOrgRequest{ + Login: &newName, + } + + req, err := s.client.NewRequest("PATCH", u, orgReq) + if err != nil { + return nil, nil, err + } + + o := new(RenameOrgResponse) + resp, err := s.client.Do(ctx, req, o) + if err != nil { + return nil, resp, err + } + + return o, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/admin_stats.go b/vendor/github.com/google/go-github/v68/github/admin_stats.go new file mode 100644 index 0000000000..f012d7984c --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/admin_stats.go @@ -0,0 +1,172 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" +) + +// AdminStats represents a variety of stats of a GitHub Enterprise +// installation. +type AdminStats struct { + Issues *IssueStats `json:"issues,omitempty"` + Hooks *HookStats `json:"hooks,omitempty"` + Milestones *MilestoneStats `json:"milestones,omitempty"` + Orgs *OrgStats `json:"orgs,omitempty"` + Comments *CommentStats `json:"comments,omitempty"` + Pages *PageStats `json:"pages,omitempty"` + Users *UserStats `json:"users,omitempty"` + Gists *GistStats `json:"gists,omitempty"` + Pulls *PullStats `json:"pulls,omitempty"` + Repos *RepoStats `json:"repos,omitempty"` +} + +func (s AdminStats) String() string { + return Stringify(s) +} + +// IssueStats represents the number of total, open and closed issues. +type IssueStats struct { + TotalIssues *int `json:"total_issues,omitempty"` + OpenIssues *int `json:"open_issues,omitempty"` + ClosedIssues *int `json:"closed_issues,omitempty"` +} + +func (s IssueStats) String() string { + return Stringify(s) +} + +// HookStats represents the number of total, active and inactive hooks. +type HookStats struct { + TotalHooks *int `json:"total_hooks,omitempty"` + ActiveHooks *int `json:"active_hooks,omitempty"` + InactiveHooks *int `json:"inactive_hooks,omitempty"` +} + +func (s HookStats) String() string { + return Stringify(s) +} + +// MilestoneStats represents the number of total, open and close milestones. +type MilestoneStats struct { + TotalMilestones *int `json:"total_milestones,omitempty"` + OpenMilestones *int `json:"open_milestones,omitempty"` + ClosedMilestones *int `json:"closed_milestones,omitempty"` +} + +func (s MilestoneStats) String() string { + return Stringify(s) +} + +// OrgStats represents the number of total, disabled organizations and the team +// and team member count. +type OrgStats struct { + TotalOrgs *int `json:"total_orgs,omitempty"` + DisabledOrgs *int `json:"disabled_orgs,omitempty"` + TotalTeams *int `json:"total_teams,omitempty"` + TotalTeamMembers *int `json:"total_team_members,omitempty"` +} + +func (s OrgStats) String() string { + return Stringify(s) +} + +// CommentStats represents the number of total comments on commits, gists, issues +// and pull requests. +type CommentStats struct { + TotalCommitComments *int `json:"total_commit_comments,omitempty"` + TotalGistComments *int `json:"total_gist_comments,omitempty"` + TotalIssueComments *int `json:"total_issue_comments,omitempty"` + TotalPullRequestComments *int `json:"total_pull_request_comments,omitempty"` +} + +func (s CommentStats) String() string { + return Stringify(s) +} + +// PageStats represents the total number of github pages. +type PageStats struct { + TotalPages *int `json:"total_pages,omitempty"` +} + +func (s PageStats) String() string { + return Stringify(s) +} + +// UserStats represents the number of total, admin and suspended users. +type UserStats struct { + TotalUsers *int `json:"total_users,omitempty"` + AdminUsers *int `json:"admin_users,omitempty"` + SuspendedUsers *int `json:"suspended_users,omitempty"` +} + +func (s UserStats) String() string { + return Stringify(s) +} + +// GistStats represents the number of total, private and public gists. +type GistStats struct { + TotalGists *int `json:"total_gists,omitempty"` + PrivateGists *int `json:"private_gists,omitempty"` + PublicGists *int `json:"public_gists,omitempty"` +} + +func (s GistStats) String() string { + return Stringify(s) +} + +// PullStats represents the number of total, merged, mergable and unmergeable +// pull-requests. +type PullStats struct { + TotalPulls *int `json:"total_pulls,omitempty"` + MergedPulls *int `json:"merged_pulls,omitempty"` + MergablePulls *int `json:"mergeable_pulls,omitempty"` + UnmergablePulls *int `json:"unmergeable_pulls,omitempty"` +} + +func (s PullStats) String() string { + return Stringify(s) +} + +// RepoStats represents the number of total, root, fork, organization repositories +// together with the total number of pushes and wikis. +type RepoStats struct { + TotalRepos *int `json:"total_repos,omitempty"` + RootRepos *int `json:"root_repos,omitempty"` + ForkRepos *int `json:"fork_repos,omitempty"` + OrgRepos *int `json:"org_repos,omitempty"` + TotalPushes *int `json:"total_pushes,omitempty"` + TotalWikis *int `json:"total_wikis,omitempty"` +} + +func (s RepoStats) String() string { + return Stringify(s) +} + +// GetAdminStats returns a variety of metrics about a GitHub Enterprise +// installation. +// +// Please note that this is only available to site administrators, +// otherwise it will error with a 404 not found (instead of 401 or 403). +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/admin-stats#get-all-statistics +// +//meta:operation GET /enterprise/stats/all +func (s *AdminService) GetAdminStats(ctx context.Context) (*AdminStats, *Response, error) { + u := "enterprise/stats/all" + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + m := new(AdminStats) + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/admin_users.go b/vendor/github.com/google/go-github/v68/github/admin_users.go new file mode 100644 index 0000000000..6877cef460 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/admin_users.go @@ -0,0 +1,137 @@ +// Copyright 2019 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// CreateUserRequest represents the fields sent to the `CreateUser` endpoint. +// Note that `Login` is a required field. +type CreateUserRequest struct { + Login string `json:"login"` + Email *string `json:"email,omitempty"` + Suspended *bool `json:"suspended,omitempty"` +} + +// CreateUser creates a new user in GitHub Enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/users#create-a-user +// +//meta:operation POST /admin/users +func (s *AdminService) CreateUser(ctx context.Context, userReq CreateUserRequest) (*User, *Response, error) { + u := "admin/users" + + req, err := s.client.NewRequest("POST", u, userReq) + if err != nil { + return nil, nil, err + } + + var user User + resp, err := s.client.Do(ctx, req, &user) + if err != nil { + return nil, resp, err + } + + return &user, resp, nil +} + +// DeleteUser deletes a user in GitHub Enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/users#delete-a-user +// +//meta:operation DELETE /admin/users/{username} +func (s *AdminService) DeleteUser(ctx context.Context, username string) (*Response, error) { + u := "admin/users/" + username + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// ImpersonateUserOptions represents the scoping for the OAuth token. +type ImpersonateUserOptions struct { + Scopes []string `json:"scopes,omitempty"` +} + +// OAuthAPP represents the GitHub Site Administrator OAuth app. +type OAuthAPP struct { + URL *string `json:"url,omitempty"` + Name *string `json:"name,omitempty"` + ClientID *string `json:"client_id,omitempty"` +} + +func (s OAuthAPP) String() string { + return Stringify(s) +} + +// UserAuthorization represents the impersonation response. +type UserAuthorization struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + Scopes []string `json:"scopes,omitempty"` + Token *string `json:"token,omitempty"` + TokenLastEight *string `json:"token_last_eight,omitempty"` + HashedToken *string `json:"hashed_token,omitempty"` + App *OAuthAPP `json:"app,omitempty"` + Note *string `json:"note,omitempty"` + NoteURL *string `json:"note_url,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + Fingerprint *string `json:"fingerprint,omitempty"` +} + +// CreateUserImpersonation creates an impersonation OAuth token. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/users#create-an-impersonation-oauth-token +// +//meta:operation POST /admin/users/{username}/authorizations +func (s *AdminService) CreateUserImpersonation(ctx context.Context, username string, opts *ImpersonateUserOptions) (*UserAuthorization, *Response, error) { + u := fmt.Sprintf("admin/users/%s/authorizations", username) + + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + a := new(UserAuthorization) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + + return a, resp, nil +} + +// DeleteUserImpersonation deletes an impersonation OAuth token. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/users#delete-an-impersonation-oauth-token +// +//meta:operation DELETE /admin/users/{username}/authorizations +func (s *AdminService) DeleteUserImpersonation(ctx context.Context, username string) (*Response, error) { + u := fmt.Sprintf("admin/users/%s/authorizations", username) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/apps.go b/vendor/github.com/google/go-github/v68/github/apps.go new file mode 100644 index 0000000000..3dd392d083 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/apps.go @@ -0,0 +1,495 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// AppsService provides access to the installation related functions +// in the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/apps/ +type AppsService service + +// App represents a GitHub App. +type App struct { + ID *int64 `json:"id,omitempty"` + Slug *string `json:"slug,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Owner *User `json:"owner,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + ExternalURL *string `json:"external_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Permissions *InstallationPermissions `json:"permissions,omitempty"` + Events []string `json:"events,omitempty"` + InstallationsCount *int `json:"installations_count,omitempty"` +} + +// InstallationToken represents an installation token. +type InstallationToken struct { + Token *string `json:"token,omitempty"` + ExpiresAt *Timestamp `json:"expires_at,omitempty"` + Permissions *InstallationPermissions `json:"permissions,omitempty"` + Repositories []*Repository `json:"repositories,omitempty"` +} + +// InstallationTokenOptions allow restricting a token's access to specific repositories. +type InstallationTokenOptions struct { + // The IDs of the repositories that the installation token can access. + // Providing repository IDs restricts the access of an installation token to specific repositories. + RepositoryIDs []int64 `json:"repository_ids,omitempty"` + + // The names of the repositories that the installation token can access. + // Providing repository names restricts the access of an installation token to specific repositories. + Repositories []string `json:"repositories,omitempty"` + + // The permissions granted to the access token. + // The permissions object includes the permission names and their access type. + Permissions *InstallationPermissions `json:"permissions,omitempty"` +} + +type InstallationTokenListRepoOptions struct { + // The IDs of the repositories that the installation token can access. + // Providing repository IDs restricts the access of an installation token to specific repositories. + RepositoryIDs []int64 `json:"repository_ids"` + + // The names of the repositories that the installation token can access. + // Providing repository names restricts the access of an installation token to specific repositories. + Repositories []string `json:"repositories,omitempty"` + + // The permissions granted to the access token. + // The permissions object includes the permission names and their access type. + Permissions *InstallationPermissions `json:"permissions,omitempty"` +} + +// InstallationPermissions lists the repository and organization permissions for an installation. +// +// Permission names taken from: +// +// https://docs.github.com/enterprise-server@3.0/rest/apps#create-an-installation-access-token-for-an-app +// https://docs.github.com/rest/apps#create-an-installation-access-token-for-an-app +type InstallationPermissions struct { + Actions *string `json:"actions,omitempty"` + ActionsVariables *string `json:"actions_variables,omitempty"` + Administration *string `json:"administration,omitempty"` + Attestations *string `json:"attestations,omitempty"` + Blocking *string `json:"blocking,omitempty"` + Checks *string `json:"checks,omitempty"` + Codespaces *string `json:"codespaces,omitempty"` + CodespacesLifecycleAdmin *string `json:"codespaces_lifecycle_admin,omitempty"` + CodespacesMetadata *string `json:"codespaces_metadata,omitempty"` + CodespacesSecrets *string `json:"codespaces_secrets,omitempty"` + CodespacesUserSecrets *string `json:"codespaces_user_secrets,omitempty"` + Contents *string `json:"contents,omitempty"` + ContentReferences *string `json:"content_references,omitempty"` + CopilotMessages *string `json:"copilot_messages,omitempty"` + DependabotSecrets *string `json:"dependabot_secrets,omitempty"` + Deployments *string `json:"deployments,omitempty"` + Discussions *string `json:"discussions,omitempty"` + Emails *string `json:"emails,omitempty"` + Environments *string `json:"environments,omitempty"` + Followers *string `json:"followers,omitempty"` + Gists *string `json:"gists,omitempty"` + GitSigningSSHPublicKeys *string `json:"git_signing_ssh_public_keys,omitempty"` + GPGKeys *string `json:"gpg_keys,omitempty"` + InteractionLimits *string `json:"interaction_limits,omitempty"` + Issues *string `json:"issues,omitempty"` + Keys *string `json:"keys,omitempty"` + Metadata *string `json:"metadata,omitempty"` + Members *string `json:"members,omitempty"` + MergeQueues *string `json:"merge_queues,omitempty"` + OrganizationActionsVariables *string `json:"organization_actions_variables,omitempty"` + OrganizationAdministration *string `json:"organization_administration,omitempty"` + OrganizationAnnouncementBanners *string `json:"organization_announcement_banners,omitempty"` + OrganizationAPIInsights *string `json:"organization_api_insights,omitempty"` + OrganizationCodespaces *string `json:"organization_codespaces,omitempty"` + OrganizationCodespacesSecrets *string `json:"organization_codespaces_secrets,omitempty"` + OrganizationCodespacesSettings *string `json:"organization_codespaces_settings,omitempty"` + OrganizationCopilotSeatManagement *string `json:"organization_copilot_seat_management,omitempty"` + OrganizationCustomProperties *string `json:"organization_custom_properties,omitempty"` + OrganizationCustomRoles *string `json:"organization_custom_roles,omitempty"` + OrganizationCustomOrgRoles *string `json:"organization_custom_org_roles,omitempty"` + OrganizationDependabotSecrets *string `json:"organization_dependabot_secrets,omitempty"` + OrganizationEvents *string `json:"organization_events,omitempty"` + OrganizationHooks *string `json:"organization_hooks,omitempty"` + OrganizationKnowledgeBases *string `json:"organization_knowledge_bases,omitempty"` + OrganizationPackages *string `json:"organization_packages,omitempty"` + OrganizationPersonalAccessTokens *string `json:"organization_personal_access_tokens,omitempty"` + OrganizationPersonalAccessTokenRequests *string `json:"organization_personal_access_token_requests,omitempty"` + OrganizationPlan *string `json:"organization_plan,omitempty"` + OrganizationPreReceiveHooks *string `json:"organization_pre_receive_hooks,omitempty"` + OrganizationProjects *string `json:"organization_projects,omitempty"` + OrganizationSecrets *string `json:"organization_secrets,omitempty"` + OrganizationSelfHostedRunners *string `json:"organization_self_hosted_runners,omitempty"` + OrganizationUserBlocking *string `json:"organization_user_blocking,omitempty"` + Packages *string `json:"packages,omitempty"` + Pages *string `json:"pages,omitempty"` + Plan *string `json:"plan,omitempty"` + Profile *string `json:"profile,omitempty"` + PullRequests *string `json:"pull_requests,omitempty"` + RepositoryAdvisories *string `json:"repository_advisories,omitempty"` + RepositoryCustomProperties *string `json:"repository_custom_properties,omitempty"` + RepositoryHooks *string `json:"repository_hooks,omitempty"` + RepositoryProjects *string `json:"repository_projects,omitempty"` + RepositoryPreReceiveHooks *string `json:"repository_pre_receive_hooks,omitempty"` + Secrets *string `json:"secrets,omitempty"` + SecretScanningAlerts *string `json:"secret_scanning_alerts,omitempty"` + SecurityEvents *string `json:"security_events,omitempty"` + SingleFile *string `json:"single_file,omitempty"` + Starring *string `json:"starring,omitempty"` + Statuses *string `json:"statuses,omitempty"` + TeamDiscussions *string `json:"team_discussions,omitempty"` + UserEvents *string `json:"user_events,omitempty"` + VulnerabilityAlerts *string `json:"vulnerability_alerts,omitempty"` + Watching *string `json:"watching,omitempty"` + Workflows *string `json:"workflows,omitempty"` +} + +// InstallationRequest represents a pending GitHub App installation request. +type InstallationRequest struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Account *User `json:"account,omitempty"` + Requester *User `json:"requester,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` +} + +// Installation represents a GitHub Apps installation. +type Installation struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + AppID *int64 `json:"app_id,omitempty"` + AppSlug *string `json:"app_slug,omitempty"` + TargetID *int64 `json:"target_id,omitempty"` + Account *User `json:"account,omitempty"` + AccessTokensURL *string `json:"access_tokens_url,omitempty"` + RepositoriesURL *string `json:"repositories_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + TargetType *string `json:"target_type,omitempty"` + SingleFileName *string `json:"single_file_name,omitempty"` + RepositorySelection *string `json:"repository_selection,omitempty"` + Events []string `json:"events,omitempty"` + SingleFilePaths []string `json:"single_file_paths,omitempty"` + Permissions *InstallationPermissions `json:"permissions,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + HasMultipleSingleFiles *bool `json:"has_multiple_single_files,omitempty"` + SuspendedBy *User `json:"suspended_by,omitempty"` + SuspendedAt *Timestamp `json:"suspended_at,omitempty"` +} + +// Attachment represents a GitHub Apps attachment. +type Attachment struct { + ID *int64 `json:"id,omitempty"` + Title *string `json:"title,omitempty"` + Body *string `json:"body,omitempty"` +} + +// ContentReference represents a reference to a URL in an issue or pull request. +type ContentReference struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Reference *string `json:"reference,omitempty"` +} + +func (i Installation) String() string { + return Stringify(i) +} + +// Get a single GitHub App. Passing the empty string will get +// the authenticated GitHub App. +// +// Note: appSlug is just the URL-friendly name of your GitHub App. +// You can find this on the settings page for your GitHub App +// (e.g., https://github.com/settings/apps/:app_slug). +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#get-an-app +// GitHub API docs: https://docs.github.com/rest/apps/apps#get-the-authenticated-app +// +//meta:operation GET /app +//meta:operation GET /apps/{app_slug} +func (s *AppsService) Get(ctx context.Context, appSlug string) (*App, *Response, error) { + var u string + if appSlug != "" { + u = fmt.Sprintf("apps/%v", appSlug) + } else { + u = "app" + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + app := new(App) + resp, err := s.client.Do(ctx, req, app) + if err != nil { + return nil, resp, err + } + + return app, resp, nil +} + +// ListInstallationRequests lists the pending installation requests that the current GitHub App has. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#list-installation-requests-for-the-authenticated-app +// +//meta:operation GET /app/installation-requests +func (s *AppsService) ListInstallationRequests(ctx context.Context, opts *ListOptions) ([]*InstallationRequest, *Response, error) { + u, err := addOptions("app/installation-requests", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var i []*InstallationRequest + resp, err := s.client.Do(ctx, req, &i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} + +// ListInstallations lists the installations that the current GitHub App has. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#list-installations-for-the-authenticated-app +// +//meta:operation GET /app/installations +func (s *AppsService) ListInstallations(ctx context.Context, opts *ListOptions) ([]*Installation, *Response, error) { + u, err := addOptions("app/installations", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var i []*Installation + resp, err := s.client.Do(ctx, req, &i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} + +// GetInstallation returns the specified installation. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#get-an-installation-for-the-authenticated-app +// +//meta:operation GET /app/installations/{installation_id} +func (s *AppsService) GetInstallation(ctx context.Context, id int64) (*Installation, *Response, error) { + return s.getInstallation(ctx, fmt.Sprintf("app/installations/%v", id)) +} + +// ListUserInstallations lists installations that are accessible to the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/apps/installations#list-app-installations-accessible-to-the-user-access-token +// +//meta:operation GET /user/installations +func (s *AppsService) ListUserInstallations(ctx context.Context, opts *ListOptions) ([]*Installation, *Response, error) { + u, err := addOptions("user/installations", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var i struct { + Installations []*Installation `json:"installations"` + } + resp, err := s.client.Do(ctx, req, &i) + if err != nil { + return nil, resp, err + } + + return i.Installations, resp, nil +} + +// SuspendInstallation suspends the specified installation. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#suspend-an-app-installation +// +//meta:operation PUT /app/installations/{installation_id}/suspended +func (s *AppsService) SuspendInstallation(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("app/installations/%v/suspended", id) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// UnsuspendInstallation unsuspends the specified installation. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#unsuspend-an-app-installation +// +//meta:operation DELETE /app/installations/{installation_id}/suspended +func (s *AppsService) UnsuspendInstallation(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("app/installations/%v/suspended", id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteInstallation deletes the specified installation. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#delete-an-installation-for-the-authenticated-app +// +//meta:operation DELETE /app/installations/{installation_id} +func (s *AppsService) DeleteInstallation(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("app/installations/%v", id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// CreateInstallationToken creates a new installation token. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#create-an-installation-access-token-for-an-app +// +//meta:operation POST /app/installations/{installation_id}/access_tokens +func (s *AppsService) CreateInstallationToken(ctx context.Context, id int64, opts *InstallationTokenOptions) (*InstallationToken, *Response, error) { + u := fmt.Sprintf("app/installations/%v/access_tokens", id) + + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + t := new(InstallationToken) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// CreateInstallationTokenListRepos creates a new installation token with a list of all repositories in an installation which is not possible with CreateInstallationToken. +// +// It differs from CreateInstallationToken by taking InstallationTokenListRepoOptions as a parameter which does not omit RepositoryIDs if that field is nil or an empty array. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#create-an-installation-access-token-for-an-app +// +//meta:operation POST /app/installations/{installation_id}/access_tokens +func (s *AppsService) CreateInstallationTokenListRepos(ctx context.Context, id int64, opts *InstallationTokenListRepoOptions) (*InstallationToken, *Response, error) { + u := fmt.Sprintf("app/installations/%v/access_tokens", id) + + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + t := new(InstallationToken) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// CreateAttachment creates a new attachment on user comment containing a url. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.3/rest/reference/apps#create-a-content-attachment +// +//meta:operation POST /repos/{owner}/{repo}/content_references/{content_reference_id}/attachments +func (s *AppsService) CreateAttachment(ctx context.Context, contentReferenceID int64, title, body string) (*Attachment, *Response, error) { + u := fmt.Sprintf("content_references/%v/attachments", contentReferenceID) + payload := &Attachment{Title: Ptr(title), Body: Ptr(body)} + req, err := s.client.NewRequest("POST", u, payload) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeContentAttachmentsPreview) + + m := &Attachment{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// FindOrganizationInstallation finds the organization's installation information. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#get-an-organization-installation-for-the-authenticated-app +// +//meta:operation GET /orgs/{org}/installation +func (s *AppsService) FindOrganizationInstallation(ctx context.Context, org string) (*Installation, *Response, error) { + return s.getInstallation(ctx, fmt.Sprintf("orgs/%v/installation", org)) +} + +// FindRepositoryInstallation finds the repository's installation information. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#get-a-repository-installation-for-the-authenticated-app +// +//meta:operation GET /repos/{owner}/{repo}/installation +func (s *AppsService) FindRepositoryInstallation(ctx context.Context, owner, repo string) (*Installation, *Response, error) { + return s.getInstallation(ctx, fmt.Sprintf("repos/%v/%v/installation", owner, repo)) +} + +// FindRepositoryInstallationByID finds the repository's installation information. +// +// Note: FindRepositoryInstallationByID uses the undocumented GitHub API endpoint "GET /repositories/{repository_id}/installation". +// +//meta:operation GET /repositories/{repository_id}/installation +func (s *AppsService) FindRepositoryInstallationByID(ctx context.Context, id int64) (*Installation, *Response, error) { + return s.getInstallation(ctx, fmt.Sprintf("repositories/%d/installation", id)) +} + +// FindUserInstallation finds the user's installation information. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#get-a-user-installation-for-the-authenticated-app +// +//meta:operation GET /users/{username}/installation +func (s *AppsService) FindUserInstallation(ctx context.Context, user string) (*Installation, *Response, error) { + return s.getInstallation(ctx, fmt.Sprintf("users/%v/installation", user)) +} + +func (s *AppsService) getInstallation(ctx context.Context, url string) (*Installation, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + i := new(Installation) + resp, err := s.client.Do(ctx, req, i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/apps_hooks.go b/vendor/github.com/google/go-github/v68/github/apps_hooks.go new file mode 100644 index 0000000000..6046827ef0 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/apps_hooks.go @@ -0,0 +1,52 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" +) + +// GetHookConfig returns the webhook configuration for a GitHub App. +// The underlying transport must be authenticated as an app. +// +// GitHub API docs: https://docs.github.com/rest/apps/webhooks#get-a-webhook-configuration-for-an-app +// +//meta:operation GET /app/hook/config +func (s *AppsService) GetHookConfig(ctx context.Context) (*HookConfig, *Response, error) { + req, err := s.client.NewRequest("GET", "app/hook/config", nil) + if err != nil { + return nil, nil, err + } + + config := new(HookConfig) + resp, err := s.client.Do(ctx, req, &config) + if err != nil { + return nil, resp, err + } + + return config, resp, nil +} + +// UpdateHookConfig updates the webhook configuration for a GitHub App. +// The underlying transport must be authenticated as an app. +// +// GitHub API docs: https://docs.github.com/rest/apps/webhooks#update-a-webhook-configuration-for-an-app +// +//meta:operation PATCH /app/hook/config +func (s *AppsService) UpdateHookConfig(ctx context.Context, config *HookConfig) (*HookConfig, *Response, error) { + req, err := s.client.NewRequest("PATCH", "app/hook/config", config) + if err != nil { + return nil, nil, err + } + + c := new(HookConfig) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/apps_hooks_deliveries.go b/vendor/github.com/google/go-github/v68/github/apps_hooks_deliveries.go new file mode 100644 index 0000000000..59800a0ae4 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/apps_hooks_deliveries.go @@ -0,0 +1,78 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListHookDeliveries lists deliveries of an App webhook. +// +// GitHub API docs: https://docs.github.com/rest/apps/webhooks#list-deliveries-for-an-app-webhook +// +//meta:operation GET /app/hook/deliveries +func (s *AppsService) ListHookDeliveries(ctx context.Context, opts *ListCursorOptions) ([]*HookDelivery, *Response, error) { + u, err := addOptions("app/hook/deliveries", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + deliveries := []*HookDelivery{} + resp, err := s.client.Do(ctx, req, &deliveries) + if err != nil { + return nil, resp, err + } + + return deliveries, resp, nil +} + +// GetHookDelivery returns the App webhook delivery with the specified ID. +// +// GitHub API docs: https://docs.github.com/rest/apps/webhooks#get-a-delivery-for-an-app-webhook +// +//meta:operation GET /app/hook/deliveries/{delivery_id} +func (s *AppsService) GetHookDelivery(ctx context.Context, deliveryID int64) (*HookDelivery, *Response, error) { + u := fmt.Sprintf("app/hook/deliveries/%v", deliveryID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + h := new(HookDelivery) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// RedeliverHookDelivery redelivers a delivery for an App webhook. +// +// GitHub API docs: https://docs.github.com/rest/apps/webhooks#redeliver-a-delivery-for-an-app-webhook +// +//meta:operation POST /app/hook/deliveries/{delivery_id}/attempts +func (s *AppsService) RedeliverHookDelivery(ctx context.Context, deliveryID int64) (*HookDelivery, *Response, error) { + u := fmt.Sprintf("app/hook/deliveries/%v/attempts", deliveryID) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + h := new(HookDelivery) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/apps_installation.go b/vendor/github.com/google/go-github/v68/github/apps_installation.go new file mode 100644 index 0000000000..d430511d07 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/apps_installation.go @@ -0,0 +1,138 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "strings" +) + +// ListRepositories represents the response from the list repos endpoints. +type ListRepositories struct { + TotalCount *int `json:"total_count,omitempty"` + Repositories []*Repository `json:"repositories"` +} + +// ListRepos lists the repositories that are accessible to the authenticated installation. +// +// GitHub API docs: https://docs.github.com/rest/apps/installations#list-repositories-accessible-to-the-app-installation +// +//meta:operation GET /installation/repositories +func (s *AppsService) ListRepos(ctx context.Context, opts *ListOptions) (*ListRepositories, *Response, error) { + u, err := addOptions("installation/repositories", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{ + mediaTypeTopicsPreview, + mediaTypeRepositoryVisibilityPreview, + mediaTypeRepositoryTemplatePreview, + } + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var r *ListRepositories + + resp, err := s.client.Do(ctx, req, &r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// ListUserRepos lists repositories that are accessible +// to the authenticated user for an installation. +// +// GitHub API docs: https://docs.github.com/rest/apps/installations#list-repositories-accessible-to-the-user-access-token +// +//meta:operation GET /user/installations/{installation_id}/repositories +func (s *AppsService) ListUserRepos(ctx context.Context, id int64, opts *ListOptions) (*ListRepositories, *Response, error) { + u := fmt.Sprintf("user/installations/%v/repositories", id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{ + mediaTypeTopicsPreview, + mediaTypeRepositoryVisibilityPreview, + mediaTypeRepositoryTemplatePreview, + } + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var r *ListRepositories + resp, err := s.client.Do(ctx, req, &r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// AddRepository adds a single repository to an installation. +// +// GitHub API docs: https://docs.github.com/rest/apps/installations#add-a-repository-to-an-app-installation +// +//meta:operation PUT /user/installations/{installation_id}/repositories/{repository_id} +func (s *AppsService) AddRepository(ctx context.Context, instID, repoID int64) (*Repository, *Response, error) { + u := fmt.Sprintf("user/installations/%v/repositories/%v", instID, repoID) + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, nil, err + } + + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// RemoveRepository removes a single repository from an installation. +// +// GitHub API docs: https://docs.github.com/rest/apps/installations#remove-a-repository-from-an-app-installation +// +//meta:operation DELETE /user/installations/{installation_id}/repositories/{repository_id} +func (s *AppsService) RemoveRepository(ctx context.Context, instID, repoID int64) (*Response, error) { + u := fmt.Sprintf("user/installations/%v/repositories/%v", instID, repoID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RevokeInstallationToken revokes an installation token. +// +// GitHub API docs: https://docs.github.com/rest/apps/installations#revoke-an-installation-access-token +// +//meta:operation DELETE /installation/token +func (s *AppsService) RevokeInstallationToken(ctx context.Context) (*Response, error) { + u := "installation/token" + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/apps_manifest.go b/vendor/github.com/google/go-github/v68/github/apps_manifest.go new file mode 100644 index 0000000000..5b6ff9af41 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/apps_manifest.go @@ -0,0 +1,51 @@ +// Copyright 2019 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// AppConfig describes the configuration of a GitHub App. +type AppConfig struct { + ID *int64 `json:"id,omitempty"` + Slug *string `json:"slug,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Owner *User `json:"owner,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + ExternalURL *string `json:"external_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + ClientID *string `json:"client_id,omitempty"` + ClientSecret *string `json:"client_secret,omitempty"` + WebhookSecret *string `json:"webhook_secret,omitempty"` + PEM *string `json:"pem,omitempty"` +} + +// CompleteAppManifest completes the App manifest handshake flow for the given +// code. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#create-a-github-app-from-a-manifest +// +//meta:operation POST /app-manifests/{code}/conversions +func (s *AppsService) CompleteAppManifest(ctx context.Context, code string) (*AppConfig, *Response, error) { + u := fmt.Sprintf("app-manifests/%s/conversions", code) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + cfg := new(AppConfig) + resp, err := s.client.Do(ctx, req, cfg) + if err != nil { + return nil, resp, err + } + + return cfg, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/apps_marketplace.go b/vendor/github.com/google/go-github/v68/github/apps_marketplace.go new file mode 100644 index 0000000000..976775a79a --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/apps_marketplace.go @@ -0,0 +1,207 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// MarketplaceService handles communication with the marketplace related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/apps#marketplace +type MarketplaceService struct { + client *Client + // Stubbed controls whether endpoints that return stubbed data are used + // instead of production endpoints. Stubbed data is fake data that's useful + // for testing your GitHub Apps. Stubbed data is hard-coded and will not + // change based on actual subscriptions. + // + // GitHub API docs: https://docs.github.com/rest/apps#testing-with-stubbed-endpoints + Stubbed bool +} + +// MarketplacePlan represents a GitHub Apps Marketplace Listing Plan. +type MarketplacePlan struct { + URL *string `json:"url,omitempty"` + AccountsURL *string `json:"accounts_url,omitempty"` + ID *int64 `json:"id,omitempty"` + Number *int `json:"number,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + MonthlyPriceInCents *int `json:"monthly_price_in_cents,omitempty"` + YearlyPriceInCents *int `json:"yearly_price_in_cents,omitempty"` + // The pricing model for this listing. Can be one of "flat-rate", "per-unit", or "free". + PriceModel *string `json:"price_model,omitempty"` + UnitName *string `json:"unit_name,omitempty"` + Bullets *[]string `json:"bullets,omitempty"` + // State can be one of the values "draft" or "published". + State *string `json:"state,omitempty"` + HasFreeTrial *bool `json:"has_free_trial,omitempty"` +} + +// MarketplacePurchase represents a GitHub Apps Marketplace Purchase. +type MarketplacePurchase struct { + Account *MarketplacePurchaseAccount `json:"account,omitempty"` + // BillingCycle can be one of the values "yearly", "monthly" or nil. + BillingCycle *string `json:"billing_cycle,omitempty"` + NextBillingDate *Timestamp `json:"next_billing_date,omitempty"` + UnitCount *int `json:"unit_count,omitempty"` + Plan *MarketplacePlan `json:"plan,omitempty"` + OnFreeTrial *bool `json:"on_free_trial,omitempty"` + FreeTrialEndsOn *Timestamp `json:"free_trial_ends_on,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +// MarketplacePendingChange represents a pending change to a GitHub Apps Marketplace Plan. +type MarketplacePendingChange struct { + EffectiveDate *Timestamp `json:"effective_date,omitempty"` + UnitCount *int `json:"unit_count,omitempty"` + ID *int64 `json:"id,omitempty"` + Plan *MarketplacePlan `json:"plan,omitempty"` +} + +// MarketplacePlanAccount represents a GitHub Account (user or organization) on a specific plan. +type MarketplacePlanAccount struct { + URL *string `json:"url,omitempty"` + Type *string `json:"type,omitempty"` + ID *int64 `json:"id,omitempty"` + Login *string `json:"login,omitempty"` + OrganizationBillingEmail *string `json:"organization_billing_email,omitempty"` + MarketplacePurchase *MarketplacePurchase `json:"marketplace_purchase,omitempty"` + MarketplacePendingChange *MarketplacePendingChange `json:"marketplace_pending_change,omitempty"` +} + +// MarketplacePurchaseAccount represents a GitHub Account (user or organization) for a Purchase. +type MarketplacePurchaseAccount struct { + URL *string `json:"url,omitempty"` + Type *string `json:"type,omitempty"` + ID *int64 `json:"id,omitempty"` + Login *string `json:"login,omitempty"` + OrganizationBillingEmail *string `json:"organization_billing_email,omitempty"` + Email *string `json:"email,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +// ListPlans lists all plans for your Marketplace listing. +// +// GitHub API docs: https://docs.github.com/rest/apps/marketplace#list-plans +// GitHub API docs: https://docs.github.com/rest/apps/marketplace#list-plans-stubbed +// +//meta:operation GET /marketplace_listing/plans +//meta:operation GET /marketplace_listing/stubbed/plans +func (s *MarketplaceService) ListPlans(ctx context.Context, opts *ListOptions) ([]*MarketplacePlan, *Response, error) { + uri := s.marketplaceURI("plans") + u, err := addOptions(uri, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var plans []*MarketplacePlan + resp, err := s.client.Do(ctx, req, &plans) + if err != nil { + return nil, resp, err + } + + return plans, resp, nil +} + +// ListPlanAccountsForPlan lists all GitHub accounts (user or organization) on a specific plan. +// +// GitHub API docs: https://docs.github.com/rest/apps/marketplace#list-accounts-for-a-plan +// GitHub API docs: https://docs.github.com/rest/apps/marketplace#list-accounts-for-a-plan-stubbed +// +//meta:operation GET /marketplace_listing/plans/{plan_id}/accounts +//meta:operation GET /marketplace_listing/stubbed/plans/{plan_id}/accounts +func (s *MarketplaceService) ListPlanAccountsForPlan(ctx context.Context, planID int64, opts *ListOptions) ([]*MarketplacePlanAccount, *Response, error) { + uri := s.marketplaceURI(fmt.Sprintf("plans/%v/accounts", planID)) + u, err := addOptions(uri, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var accounts []*MarketplacePlanAccount + resp, err := s.client.Do(ctx, req, &accounts) + if err != nil { + return nil, resp, err + } + + return accounts, resp, nil +} + +// GetPlanAccountForAccount get GitHub account (user or organization) associated with an account. +// +// GitHub API docs: https://docs.github.com/rest/apps/marketplace#get-a-subscription-plan-for-an-account +// GitHub API docs: https://docs.github.com/rest/apps/marketplace#get-a-subscription-plan-for-an-account-stubbed +// +//meta:operation GET /marketplace_listing/accounts/{account_id} +//meta:operation GET /marketplace_listing/stubbed/accounts/{account_id} +func (s *MarketplaceService) GetPlanAccountForAccount(ctx context.Context, accountID int64) (*MarketplacePlanAccount, *Response, error) { + uri := s.marketplaceURI(fmt.Sprintf("accounts/%v", accountID)) + + req, err := s.client.NewRequest("GET", uri, nil) + if err != nil { + return nil, nil, err + } + + var account *MarketplacePlanAccount + resp, err := s.client.Do(ctx, req, &account) + if err != nil { + return nil, resp, err + } + + return account, resp, nil +} + +// ListMarketplacePurchasesForUser lists all GitHub marketplace purchases made by a user. +// +// GitHub API docs: https://docs.github.com/rest/apps/marketplace#list-subscriptions-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/rest/apps/marketplace#list-subscriptions-for-the-authenticated-user-stubbed +// +//meta:operation GET /user/marketplace_purchases +//meta:operation GET /user/marketplace_purchases/stubbed +func (s *MarketplaceService) ListMarketplacePurchasesForUser(ctx context.Context, opts *ListOptions) ([]*MarketplacePurchase, *Response, error) { + uri := "user/marketplace_purchases" + if s.Stubbed { + uri = "user/marketplace_purchases/stubbed" + } + + u, err := addOptions(uri, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var purchases []*MarketplacePurchase + resp, err := s.client.Do(ctx, req, &purchases) + if err != nil { + return nil, resp, err + } + return purchases, resp, nil +} + +func (s *MarketplaceService) marketplaceURI(endpoint string) string { + url := "marketplace_listing" + if s.Stubbed { + url = "marketplace_listing/stubbed" + } + return url + "/" + endpoint +} diff --git a/vendor/github.com/google/go-github/v68/github/attestations.go b/vendor/github.com/google/go-github/v68/github/attestations.go new file mode 100644 index 0000000000..618d5d73f6 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/attestations.go @@ -0,0 +1,27 @@ +// Copyright 2024 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "encoding/json" +) + +// Attestation represents an artifact attestation associated with a repository. +// The provided bundle can be used to verify the provenance of artifacts. +// +// https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds +type Attestation struct { + // The attestation's Sigstore Bundle. + // Refer to the sigstore bundle specification for more info: + // https://github.com/sigstore/protobuf-specs/blob/main/protos/sigstore_bundle.proto + Bundle json.RawMessage `json:"bundle"` + RepositoryID int64 `json:"repository_id"` +} + +// AttestationsResponse represents a collection of artifact attestations. +type AttestationsResponse struct { + Attestations []*Attestation `json:"attestations"` +} diff --git a/vendor/github.com/google/go-github/v68/github/authorizations.go b/vendor/github.com/google/go-github/v68/github/authorizations.go new file mode 100644 index 0000000000..8b8a67d552 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/authorizations.go @@ -0,0 +1,293 @@ +// Copyright 2015 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Scope models a GitHub authorization scope. +// +// GitHub API docs: https://docs.github.com/rest/oauth/#scopes +type Scope string + +// This is the set of scopes for GitHub API V3. +const ( + ScopeNone Scope = "(no scope)" // REVISIT: is this actually returned, or just a documentation artifact? + ScopeUser Scope = "user" + ScopeUserEmail Scope = "user:email" + ScopeUserFollow Scope = "user:follow" + ScopePublicRepo Scope = "public_repo" + ScopeRepo Scope = "repo" + ScopeRepoDeployment Scope = "repo_deployment" + ScopeRepoStatus Scope = "repo:status" + ScopeDeleteRepo Scope = "delete_repo" + ScopeNotifications Scope = "notifications" + ScopeGist Scope = "gist" + ScopeReadRepoHook Scope = "read:repo_hook" + ScopeWriteRepoHook Scope = "write:repo_hook" + ScopeAdminRepoHook Scope = "admin:repo_hook" + ScopeAdminOrgHook Scope = "admin:org_hook" + ScopeReadOrg Scope = "read:org" + ScopeWriteOrg Scope = "write:org" + ScopeAdminOrg Scope = "admin:org" + ScopeReadPublicKey Scope = "read:public_key" + ScopeWritePublicKey Scope = "write:public_key" + ScopeAdminPublicKey Scope = "admin:public_key" + ScopeReadGPGKey Scope = "read:gpg_key" + ScopeWriteGPGKey Scope = "write:gpg_key" + ScopeAdminGPGKey Scope = "admin:gpg_key" + ScopeSecurityEvents Scope = "security_events" +) + +// AuthorizationsService handles communication with the authorization related +// methods of the GitHub API. +// +// This service requires HTTP Basic Authentication; it cannot be accessed using +// an OAuth token. +// +// GitHub API docs: https://docs.github.com/rest/oauth-authorizations +type AuthorizationsService service + +// Authorization represents an individual GitHub authorization. +type Authorization struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + Scopes []Scope `json:"scopes,omitempty"` + Token *string `json:"token,omitempty"` + TokenLastEight *string `json:"token_last_eight,omitempty"` + HashedToken *string `json:"hashed_token,omitempty"` + App *AuthorizationApp `json:"app,omitempty"` + Note *string `json:"note,omitempty"` + NoteURL *string `json:"note_url,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + Fingerprint *string `json:"fingerprint,omitempty"` + + // User is only populated by the Check and Reset methods. + User *User `json:"user,omitempty"` +} + +func (a Authorization) String() string { + return Stringify(a) +} + +// AuthorizationApp represents an individual GitHub app (in the context of authorization). +type AuthorizationApp struct { + URL *string `json:"url,omitempty"` + Name *string `json:"name,omitempty"` + ClientID *string `json:"client_id,omitempty"` +} + +func (a AuthorizationApp) String() string { + return Stringify(a) +} + +// Grant represents an OAuth application that has been granted access to an account. +type Grant struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + App *AuthorizationApp `json:"app,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Scopes []string `json:"scopes,omitempty"` +} + +func (g Grant) String() string { + return Stringify(g) +} + +// AuthorizationRequest represents a request to create an authorization. +type AuthorizationRequest struct { + Scopes []Scope `json:"scopes,omitempty"` + Note *string `json:"note,omitempty"` + NoteURL *string `json:"note_url,omitempty"` + ClientID *string `json:"client_id,omitempty"` + ClientSecret *string `json:"client_secret,omitempty"` + Fingerprint *string `json:"fingerprint,omitempty"` +} + +func (a AuthorizationRequest) String() string { + return Stringify(a) +} + +// AuthorizationUpdateRequest represents a request to update an authorization. +// +// Note that for any one update, you must only provide one of the "scopes" +// fields. That is, you may provide only one of "Scopes", or "AddScopes", or +// "RemoveScopes". +// +// GitHub API docs: https://docs.github.com/rest/oauth-authorizations#update-an-existing-authorization +type AuthorizationUpdateRequest struct { + Scopes []string `json:"scopes,omitempty"` + AddScopes []string `json:"add_scopes,omitempty"` + RemoveScopes []string `json:"remove_scopes,omitempty"` + Note *string `json:"note,omitempty"` + NoteURL *string `json:"note_url,omitempty"` + Fingerprint *string `json:"fingerprint,omitempty"` +} + +func (a AuthorizationUpdateRequest) String() string { + return Stringify(a) +} + +// Check if an OAuth token is valid for a specific app. +// +// Note that this operation requires the use of BasicAuth, but where the +// username is the OAuth application clientID, and the password is its +// clientSecret. Invalid tokens will return a 404 Not Found. +// +// The returned Authorization.User field will be populated. +// +// GitHub API docs: https://docs.github.com/rest/apps/oauth-applications#check-a-token +// +//meta:operation POST /applications/{client_id}/token +func (s *AuthorizationsService) Check(ctx context.Context, clientID, accessToken string) (*Authorization, *Response, error) { + u := fmt.Sprintf("applications/%v/token", clientID) + + reqBody := &struct { + AccessToken string `json:"access_token"` + }{AccessToken: accessToken} + + req, err := s.client.NewRequest("POST", u, reqBody) + if err != nil { + return nil, nil, err + } + req.Header.Set("Accept", mediaTypeOAuthAppPreview) + + a := new(Authorization) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + + return a, resp, nil +} + +// Reset is used to reset a valid OAuth token without end user involvement. +// Applications must save the "token" property in the response, because changes +// take effect immediately. +// +// Note that this operation requires the use of BasicAuth, but where the +// username is the OAuth application clientID, and the password is its +// clientSecret. Invalid tokens will return a 404 Not Found. +// +// The returned Authorization.User field will be populated. +// +// GitHub API docs: https://docs.github.com/rest/apps/oauth-applications#reset-a-token +// +//meta:operation PATCH /applications/{client_id}/token +func (s *AuthorizationsService) Reset(ctx context.Context, clientID, accessToken string) (*Authorization, *Response, error) { + u := fmt.Sprintf("applications/%v/token", clientID) + + reqBody := &struct { + AccessToken string `json:"access_token"` + }{AccessToken: accessToken} + + req, err := s.client.NewRequest("PATCH", u, reqBody) + if err != nil { + return nil, nil, err + } + req.Header.Set("Accept", mediaTypeOAuthAppPreview) + + a := new(Authorization) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + + return a, resp, nil +} + +// Revoke an authorization for an application. +// +// Note that this operation requires the use of BasicAuth, but where the +// username is the OAuth application clientID, and the password is its +// clientSecret. Invalid tokens will return a 404 Not Found. +// +// GitHub API docs: https://docs.github.com/rest/apps/oauth-applications#delete-an-app-token +// +//meta:operation DELETE /applications/{client_id}/token +func (s *AuthorizationsService) Revoke(ctx context.Context, clientID, accessToken string) (*Response, error) { + u := fmt.Sprintf("applications/%v/token", clientID) + + reqBody := &struct { + AccessToken string `json:"access_token"` + }{AccessToken: accessToken} + + req, err := s.client.NewRequest("DELETE", u, reqBody) + if err != nil { + return nil, err + } + req.Header.Set("Accept", mediaTypeOAuthAppPreview) + + return s.client.Do(ctx, req, nil) +} + +// DeleteGrant deletes an OAuth application grant. Deleting an application's +// grant will also delete all OAuth tokens associated with the application for +// the user. +// +// GitHub API docs: https://docs.github.com/rest/apps/oauth-applications#delete-an-app-authorization +// +//meta:operation DELETE /applications/{client_id}/grant +func (s *AuthorizationsService) DeleteGrant(ctx context.Context, clientID, accessToken string) (*Response, error) { + u := fmt.Sprintf("applications/%v/grant", clientID) + + reqBody := &struct { + AccessToken string `json:"access_token"` + }{AccessToken: accessToken} + + req, err := s.client.NewRequest("DELETE", u, reqBody) + if err != nil { + return nil, err + } + req.Header.Set("Accept", mediaTypeOAuthAppPreview) + + return s.client.Do(ctx, req, nil) +} + +// CreateImpersonation creates an impersonation OAuth token. +// +// This requires admin permissions. With the returned Authorization.Token +// you can e.g. create or delete a user's public SSH key. NOTE: creating a +// new token automatically revokes an existing one. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/users#create-an-impersonation-oauth-token +// +//meta:operation POST /admin/users/{username}/authorizations +func (s *AuthorizationsService) CreateImpersonation(ctx context.Context, username string, authReq *AuthorizationRequest) (*Authorization, *Response, error) { + u := fmt.Sprintf("admin/users/%v/authorizations", username) + req, err := s.client.NewRequest("POST", u, authReq) + if err != nil { + return nil, nil, err + } + + a := new(Authorization) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + return a, resp, nil +} + +// DeleteImpersonation deletes an impersonation OAuth token. +// +// NOTE: there can be only one at a time. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/users#delete-an-impersonation-oauth-token +// +//meta:operation DELETE /admin/users/{username}/authorizations +func (s *AuthorizationsService) DeleteImpersonation(ctx context.Context, username string) (*Response, error) { + u := fmt.Sprintf("admin/users/%v/authorizations", username) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/billing.go b/vendor/github.com/google/go-github/v68/github/billing.go new file mode 100644 index 0000000000..09b1a5d017 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/billing.go @@ -0,0 +1,218 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// BillingService provides access to the billing related functions +// in the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/billing +type BillingService service + +// ActionBilling represents a GitHub Action billing. +type ActionBilling struct { + TotalMinutesUsed float64 `json:"total_minutes_used"` + TotalPaidMinutesUsed float64 `json:"total_paid_minutes_used"` + IncludedMinutes float64 `json:"included_minutes"` + MinutesUsedBreakdown MinutesUsedBreakdown `json:"minutes_used_breakdown"` +} + +// MinutesUsedBreakdown counts the actions minutes used by machine type (e.g. UBUNTU, WINDOWS, MACOS). +type MinutesUsedBreakdown = map[string]int + +// PackageBilling represents a GitHub Package billing. +type PackageBilling struct { + TotalGigabytesBandwidthUsed int `json:"total_gigabytes_bandwidth_used"` + TotalPaidGigabytesBandwidthUsed int `json:"total_paid_gigabytes_bandwidth_used"` + IncludedGigabytesBandwidth float64 `json:"included_gigabytes_bandwidth"` +} + +// StorageBilling represents a GitHub Storage billing. +type StorageBilling struct { + DaysLeftInBillingCycle int `json:"days_left_in_billing_cycle"` + EstimatedPaidStorageForMonth float64 `json:"estimated_paid_storage_for_month"` + EstimatedStorageForMonth float64 `json:"estimated_storage_for_month"` +} + +// ActiveCommitters represents the total active committers across all repositories in an Organization. +type ActiveCommitters struct { + TotalAdvancedSecurityCommitters int `json:"total_advanced_security_committers"` + TotalCount int `json:"total_count"` + MaximumAdvancedSecurityCommitters int `json:"maximum_advanced_security_committers"` + PurchasedAdvancedSecurityCommitters int `json:"purchased_advanced_security_committers"` + Repositories []*RepositoryActiveCommitters `json:"repositories,omitempty"` +} + +// RepositoryActiveCommitters represents active committers on each repository. +type RepositoryActiveCommitters struct { + Name *string `json:"name,omitempty"` + AdvancedSecurityCommitters *int `json:"advanced_security_committers,omitempty"` + AdvancedSecurityCommittersBreakdown []*AdvancedSecurityCommittersBreakdown `json:"advanced_security_committers_breakdown,omitempty"` +} + +// AdvancedSecurityCommittersBreakdown represents the user activity breakdown for ActiveCommitters. +type AdvancedSecurityCommittersBreakdown struct { + UserLogin *string `json:"user_login,omitempty"` + LastPushedDate *string `json:"last_pushed_date,omitempty"` +} + +// GetActionsBillingOrg returns the summary of the free and paid GitHub Actions minutes used for an Org. +// +// GitHub API docs: https://docs.github.com/rest/billing/billing#get-github-actions-billing-for-an-organization +// +//meta:operation GET /orgs/{org}/settings/billing/actions +func (s *BillingService) GetActionsBillingOrg(ctx context.Context, org string) (*ActionBilling, *Response, error) { + u := fmt.Sprintf("orgs/%v/settings/billing/actions", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + actionsOrgBilling := new(ActionBilling) + resp, err := s.client.Do(ctx, req, actionsOrgBilling) + if err != nil { + return nil, resp, err + } + + return actionsOrgBilling, resp, nil +} + +// GetPackagesBillingOrg returns the free and paid storage used for GitHub Packages in gigabytes for an Org. +// +// GitHub API docs: https://docs.github.com/rest/billing/billing#get-github-packages-billing-for-an-organization +// +//meta:operation GET /orgs/{org}/settings/billing/packages +func (s *BillingService) GetPackagesBillingOrg(ctx context.Context, org string) (*PackageBilling, *Response, error) { + u := fmt.Sprintf("orgs/%v/settings/billing/packages", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + packagesOrgBilling := new(PackageBilling) + resp, err := s.client.Do(ctx, req, packagesOrgBilling) + if err != nil { + return nil, resp, err + } + + return packagesOrgBilling, resp, nil +} + +// GetStorageBillingOrg returns the estimated paid and estimated total storage used for GitHub Actions +// and GitHub Packages in gigabytes for an Org. +// +// GitHub API docs: https://docs.github.com/rest/billing/billing#get-shared-storage-billing-for-an-organization +// +//meta:operation GET /orgs/{org}/settings/billing/shared-storage +func (s *BillingService) GetStorageBillingOrg(ctx context.Context, org string) (*StorageBilling, *Response, error) { + u := fmt.Sprintf("orgs/%v/settings/billing/shared-storage", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + storageOrgBilling := new(StorageBilling) + resp, err := s.client.Do(ctx, req, storageOrgBilling) + if err != nil { + return nil, resp, err + } + + return storageOrgBilling, resp, nil +} + +// GetAdvancedSecurityActiveCommittersOrg returns the GitHub Advanced Security active committers for an organization per repository. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/billing/billing#get-github-advanced-security-active-committers-for-an-organization +// +//meta:operation GET /orgs/{org}/settings/billing/advanced-security +func (s *BillingService) GetAdvancedSecurityActiveCommittersOrg(ctx context.Context, org string, opts *ListOptions) (*ActiveCommitters, *Response, error) { + u := fmt.Sprintf("orgs/%v/settings/billing/advanced-security", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + activeOrgCommitters := new(ActiveCommitters) + resp, err := s.client.Do(ctx, req, activeOrgCommitters) + if err != nil { + return nil, resp, err + } + + return activeOrgCommitters, resp, nil +} + +// GetActionsBillingUser returns the summary of the free and paid GitHub Actions minutes used for a user. +// +// GitHub API docs: https://docs.github.com/rest/billing/billing#get-github-actions-billing-for-a-user +// +//meta:operation GET /users/{username}/settings/billing/actions +func (s *BillingService) GetActionsBillingUser(ctx context.Context, user string) (*ActionBilling, *Response, error) { + u := fmt.Sprintf("users/%v/settings/billing/actions", user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + actionsUserBilling := new(ActionBilling) + resp, err := s.client.Do(ctx, req, actionsUserBilling) + if err != nil { + return nil, resp, err + } + + return actionsUserBilling, resp, nil +} + +// GetPackagesBillingUser returns the free and paid storage used for GitHub Packages in gigabytes for a user. +// +// GitHub API docs: https://docs.github.com/rest/billing/billing#get-github-packages-billing-for-a-user +// +//meta:operation GET /users/{username}/settings/billing/packages +func (s *BillingService) GetPackagesBillingUser(ctx context.Context, user string) (*PackageBilling, *Response, error) { + u := fmt.Sprintf("users/%v/settings/billing/packages", user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + packagesUserBilling := new(PackageBilling) + resp, err := s.client.Do(ctx, req, packagesUserBilling) + if err != nil { + return nil, resp, err + } + + return packagesUserBilling, resp, nil +} + +// GetStorageBillingUser returns the estimated paid and estimated total storage used for GitHub Actions +// and GitHub Packages in gigabytes for a user. +// +// GitHub API docs: https://docs.github.com/rest/billing/billing#get-shared-storage-billing-for-a-user +// +//meta:operation GET /users/{username}/settings/billing/shared-storage +func (s *BillingService) GetStorageBillingUser(ctx context.Context, user string) (*StorageBilling, *Response, error) { + u := fmt.Sprintf("users/%v/settings/billing/shared-storage", user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + storageUserBilling := new(StorageBilling) + resp, err := s.client.Do(ctx, req, storageUserBilling) + if err != nil { + return nil, resp, err + } + + return storageUserBilling, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/checks.go b/vendor/github.com/google/go-github/v68/github/checks.go new file mode 100644 index 0000000000..711be207c2 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/checks.go @@ -0,0 +1,478 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ChecksService provides access to the Checks API in the +// GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/checks/ +type ChecksService service + +// CheckRun represents a GitHub check run on a repository associated with a GitHub app. +type CheckRun struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + HeadSHA *string `json:"head_sha,omitempty"` + ExternalID *string `json:"external_id,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + DetailsURL *string `json:"details_url,omitempty"` + Status *string `json:"status,omitempty"` + Conclusion *string `json:"conclusion,omitempty"` + StartedAt *Timestamp `json:"started_at,omitempty"` + CompletedAt *Timestamp `json:"completed_at,omitempty"` + Output *CheckRunOutput `json:"output,omitempty"` + Name *string `json:"name,omitempty"` + CheckSuite *CheckSuite `json:"check_suite,omitempty"` + App *App `json:"app,omitempty"` + PullRequests []*PullRequest `json:"pull_requests,omitempty"` +} + +// CheckRunOutput represents the output of a CheckRun. +type CheckRunOutput struct { + Title *string `json:"title,omitempty"` + Summary *string `json:"summary,omitempty"` + Text *string `json:"text,omitempty"` + AnnotationsCount *int `json:"annotations_count,omitempty"` + AnnotationsURL *string `json:"annotations_url,omitempty"` + Annotations []*CheckRunAnnotation `json:"annotations,omitempty"` + Images []*CheckRunImage `json:"images,omitempty"` +} + +// CheckRunAnnotation represents an annotation object for a CheckRun output. +type CheckRunAnnotation struct { + Path *string `json:"path,omitempty"` + StartLine *int `json:"start_line,omitempty"` + EndLine *int `json:"end_line,omitempty"` + StartColumn *int `json:"start_column,omitempty"` + EndColumn *int `json:"end_column,omitempty"` + AnnotationLevel *string `json:"annotation_level,omitempty"` + Message *string `json:"message,omitempty"` + Title *string `json:"title,omitempty"` + RawDetails *string `json:"raw_details,omitempty"` +} + +// CheckRunImage represents an image object for a CheckRun output. +type CheckRunImage struct { + Alt *string `json:"alt,omitempty"` + ImageURL *string `json:"image_url,omitempty"` + Caption *string `json:"caption,omitempty"` +} + +// CheckSuite represents a suite of check runs. +type CheckSuite struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + HeadBranch *string `json:"head_branch,omitempty"` + HeadSHA *string `json:"head_sha,omitempty"` + URL *string `json:"url,omitempty"` + BeforeSHA *string `json:"before,omitempty"` + AfterSHA *string `json:"after,omitempty"` + Status *string `json:"status,omitempty"` + Conclusion *string `json:"conclusion,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + App *App `json:"app,omitempty"` + Repository *Repository `json:"repository,omitempty"` + PullRequests []*PullRequest `json:"pull_requests,omitempty"` + + // The following fields are only populated by Webhook events. + HeadCommit *Commit `json:"head_commit,omitempty"` + LatestCheckRunsCount *int64 `json:"latest_check_runs_count,omitempty"` + Rerequstable *bool `json:"rerequestable,omitempty"` + RunsRerequstable *bool `json:"runs_rerequestable,omitempty"` +} + +func (c CheckRun) String() string { + return Stringify(c) +} + +func (c CheckSuite) String() string { + return Stringify(c) +} + +// GetCheckRun gets a check-run for a repository. +// +// GitHub API docs: https://docs.github.com/rest/checks/runs#get-a-check-run +// +//meta:operation GET /repos/{owner}/{repo}/check-runs/{check_run_id} +func (s *ChecksService) GetCheckRun(ctx context.Context, owner, repo string, checkRunID int64) (*CheckRun, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/check-runs/%v", owner, repo, checkRunID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + checkRun := new(CheckRun) + resp, err := s.client.Do(ctx, req, checkRun) + if err != nil { + return nil, resp, err + } + + return checkRun, resp, nil +} + +// GetCheckSuite gets a single check suite. +// +// GitHub API docs: https://docs.github.com/rest/checks/suites#get-a-check-suite +// +//meta:operation GET /repos/{owner}/{repo}/check-suites/{check_suite_id} +func (s *ChecksService) GetCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64) (*CheckSuite, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/check-suites/%v", owner, repo, checkSuiteID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + checkSuite := new(CheckSuite) + resp, err := s.client.Do(ctx, req, checkSuite) + if err != nil { + return nil, resp, err + } + + return checkSuite, resp, nil +} + +// CreateCheckRunOptions sets up parameters needed to create a CheckRun. +type CreateCheckRunOptions struct { + Name string `json:"name"` // The name of the check (e.g., "code-coverage"). (Required.) + HeadSHA string `json:"head_sha"` // The SHA of the commit. (Required.) + DetailsURL *string `json:"details_url,omitempty"` // The URL of the integrator's site that has the full details of the check. (Optional.) + ExternalID *string `json:"external_id,omitempty"` // A reference for the run on the integrator's system. (Optional.) + Status *string `json:"status,omitempty"` // The current status. Can be one of "queued", "in_progress", or "completed". Default: "queued". (Optional.) + Conclusion *string `json:"conclusion,omitempty"` // Can be one of "success", "failure", "neutral", "cancelled", "skipped", "timed_out", or "action_required". (Optional. Required if you provide a status of "completed".) + StartedAt *Timestamp `json:"started_at,omitempty"` // The time that the check run began. (Optional.) + CompletedAt *Timestamp `json:"completed_at,omitempty"` // The time the check completed. (Optional. Required if you provide conclusion.) + Output *CheckRunOutput `json:"output,omitempty"` // Provide descriptive details about the run. (Optional) + Actions []*CheckRunAction `json:"actions,omitempty"` // Possible further actions the integrator can perform, which a user may trigger. (Optional.) +} + +// CheckRunAction exposes further actions the integrator can perform, which a user may trigger. +type CheckRunAction struct { + Label string `json:"label"` // The text to be displayed on a button in the web UI. The maximum size is 20 characters. (Required.) + Description string `json:"description"` // A short explanation of what this action would do. The maximum size is 40 characters. (Required.) + Identifier string `json:"identifier"` // A reference for the action on the integrator's system. The maximum size is 20 characters. (Required.) +} + +// CreateCheckRun creates a check run for repository. +// +// GitHub API docs: https://docs.github.com/rest/checks/runs#create-a-check-run +// +//meta:operation POST /repos/{owner}/{repo}/check-runs +func (s *ChecksService) CreateCheckRun(ctx context.Context, owner, repo string, opts CreateCheckRunOptions) (*CheckRun, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/check-runs", owner, repo) + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + checkRun := new(CheckRun) + resp, err := s.client.Do(ctx, req, checkRun) + if err != nil { + return nil, resp, err + } + + return checkRun, resp, nil +} + +// UpdateCheckRunOptions sets up parameters needed to update a CheckRun. +type UpdateCheckRunOptions struct { + Name string `json:"name"` // The name of the check (e.g., "code-coverage"). (Required.) + DetailsURL *string `json:"details_url,omitempty"` // The URL of the integrator's site that has the full details of the check. (Optional.) + ExternalID *string `json:"external_id,omitempty"` // A reference for the run on the integrator's system. (Optional.) + Status *string `json:"status,omitempty"` // The current status. Can be one of "queued", "in_progress", or "completed". Default: "queued". (Optional.) + Conclusion *string `json:"conclusion,omitempty"` // Can be one of "success", "failure", "neutral", "cancelled", "skipped", "timed_out", or "action_required". (Optional. Required if you provide a status of "completed".) + CompletedAt *Timestamp `json:"completed_at,omitempty"` // The time the check completed. (Optional. Required if you provide conclusion.) + Output *CheckRunOutput `json:"output,omitempty"` // Provide descriptive details about the run. (Optional) + Actions []*CheckRunAction `json:"actions,omitempty"` // Possible further actions the integrator can perform, which a user may trigger. (Optional.) +} + +// UpdateCheckRun updates a check run for a specific commit in a repository. +// +// GitHub API docs: https://docs.github.com/rest/checks/runs#update-a-check-run +// +//meta:operation PATCH /repos/{owner}/{repo}/check-runs/{check_run_id} +func (s *ChecksService) UpdateCheckRun(ctx context.Context, owner, repo string, checkRunID int64, opts UpdateCheckRunOptions) (*CheckRun, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/check-runs/%v", owner, repo, checkRunID) + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + checkRun := new(CheckRun) + resp, err := s.client.Do(ctx, req, checkRun) + if err != nil { + return nil, resp, err + } + + return checkRun, resp, nil +} + +// ListCheckRunAnnotations lists the annotations for a check run. +// +// GitHub API docs: https://docs.github.com/rest/checks/runs#list-check-run-annotations +// +//meta:operation GET /repos/{owner}/{repo}/check-runs/{check_run_id}/annotations +func (s *ChecksService) ListCheckRunAnnotations(ctx context.Context, owner, repo string, checkRunID int64, opts *ListOptions) ([]*CheckRunAnnotation, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/check-runs/%v/annotations", owner, repo, checkRunID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + var checkRunAnnotations []*CheckRunAnnotation + resp, err := s.client.Do(ctx, req, &checkRunAnnotations) + if err != nil { + return nil, resp, err + } + + return checkRunAnnotations, resp, nil +} + +// ListCheckRunsOptions represents parameters to list check runs. +type ListCheckRunsOptions struct { + CheckName *string `url:"check_name,omitempty"` // Returns check runs with the specified name. + Status *string `url:"status,omitempty"` // Returns check runs with the specified status. Can be one of "queued", "in_progress", or "completed". + Filter *string `url:"filter,omitempty"` // Filters check runs by their completed_at timestamp. Can be one of "latest" (returning the most recent check runs) or "all". Default: "latest" + AppID *int64 `url:"app_id,omitempty"` // Filters check runs by GitHub App ID. + + ListOptions +} + +// ListCheckRunsResults represents the result of a check run list. +type ListCheckRunsResults struct { + Total *int `json:"total_count,omitempty"` + CheckRuns []*CheckRun `json:"check_runs,omitempty"` +} + +// ListCheckRunsForRef lists check runs for a specific ref. +// +// GitHub API docs: https://docs.github.com/rest/checks/runs#list-check-runs-for-a-git-reference +// +//meta:operation GET /repos/{owner}/{repo}/commits/{ref}/check-runs +func (s *ChecksService) ListCheckRunsForRef(ctx context.Context, owner, repo, ref string, opts *ListCheckRunsOptions) (*ListCheckRunsResults, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/check-runs", owner, repo, refURLEscape(ref)) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + var checkRunResults *ListCheckRunsResults + resp, err := s.client.Do(ctx, req, &checkRunResults) + if err != nil { + return nil, resp, err + } + + return checkRunResults, resp, nil +} + +// ListCheckRunsCheckSuite lists check runs for a check suite. +// +// GitHub API docs: https://docs.github.com/rest/checks/runs#list-check-runs-in-a-check-suite +// +//meta:operation GET /repos/{owner}/{repo}/check-suites/{check_suite_id}/check-runs +func (s *ChecksService) ListCheckRunsCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64, opts *ListCheckRunsOptions) (*ListCheckRunsResults, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/check-suites/%v/check-runs", owner, repo, checkSuiteID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + var checkRunResults *ListCheckRunsResults + resp, err := s.client.Do(ctx, req, &checkRunResults) + if err != nil { + return nil, resp, err + } + + return checkRunResults, resp, nil +} + +// ReRequestCheckRun triggers GitHub to rerequest an existing check run. +// +// GitHub API docs: https://docs.github.com/rest/checks/runs#rerequest-a-check-run +// +//meta:operation POST /repos/{owner}/{repo}/check-runs/{check_run_id}/rerequest +func (s *ChecksService) ReRequestCheckRun(ctx context.Context, owner, repo string, checkRunID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/check-runs/%v/rerequest", owner, repo, checkRunID) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + return s.client.Do(ctx, req, nil) +} + +// ListCheckSuiteOptions represents parameters to list check suites. +type ListCheckSuiteOptions struct { + CheckName *string `url:"check_name,omitempty"` // Filters checks suites by the name of the check run. + AppID *int `url:"app_id,omitempty"` // Filters check suites by GitHub App id. + + ListOptions +} + +// ListCheckSuiteResults represents the result of a check run list. +type ListCheckSuiteResults struct { + Total *int `json:"total_count,omitempty"` + CheckSuites []*CheckSuite `json:"check_suites,omitempty"` +} + +// ListCheckSuitesForRef lists check suite for a specific ref. +// +// GitHub API docs: https://docs.github.com/rest/checks/suites#list-check-suites-for-a-git-reference +// +//meta:operation GET /repos/{owner}/{repo}/commits/{ref}/check-suites +func (s *ChecksService) ListCheckSuitesForRef(ctx context.Context, owner, repo, ref string, opts *ListCheckSuiteOptions) (*ListCheckSuiteResults, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/check-suites", owner, repo, refURLEscape(ref)) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + var checkSuiteResults *ListCheckSuiteResults + resp, err := s.client.Do(ctx, req, &checkSuiteResults) + if err != nil { + return nil, resp, err + } + + return checkSuiteResults, resp, nil +} + +// AutoTriggerCheck enables or disables automatic creation of CheckSuite events upon pushes to the repository. +type AutoTriggerCheck struct { + AppID *int64 `json:"app_id,omitempty"` // The id of the GitHub App. (Required.) + Setting *bool `json:"setting,omitempty"` // Set to "true" to enable automatic creation of CheckSuite events upon pushes to the repository, or "false" to disable them. Default: "true" (Required.) +} + +// CheckSuitePreferenceOptions set options for check suite preferences for a repository. +type CheckSuitePreferenceOptions struct { + AutoTriggerChecks []*AutoTriggerCheck `json:"auto_trigger_checks,omitempty"` // A slice of auto trigger checks that can be set for a check suite in a repository. +} + +// CheckSuitePreferenceResults represents the results of the preference set operation. +type CheckSuitePreferenceResults struct { + Preferences *PreferenceList `json:"preferences,omitempty"` + Repository *Repository `json:"repository,omitempty"` +} + +// PreferenceList represents a list of auto trigger checks for repository. +type PreferenceList struct { + AutoTriggerChecks []*AutoTriggerCheck `json:"auto_trigger_checks,omitempty"` // A slice of auto trigger checks that can be set for a check suite in a repository. +} + +// SetCheckSuitePreferences changes the default automatic flow when creating check suites. +// +// GitHub API docs: https://docs.github.com/rest/checks/suites#update-repository-preferences-for-check-suites +// +//meta:operation PATCH /repos/{owner}/{repo}/check-suites/preferences +func (s *ChecksService) SetCheckSuitePreferences(ctx context.Context, owner, repo string, opts CheckSuitePreferenceOptions) (*CheckSuitePreferenceResults, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/check-suites/preferences", owner, repo) + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + var checkSuitePrefResults *CheckSuitePreferenceResults + resp, err := s.client.Do(ctx, req, &checkSuitePrefResults) + if err != nil { + return nil, resp, err + } + + return checkSuitePrefResults, resp, nil +} + +// CreateCheckSuiteOptions sets up parameters to manually create a check suites. +type CreateCheckSuiteOptions struct { + HeadSHA string `json:"head_sha"` // The sha of the head commit. (Required.) + HeadBranch *string `json:"head_branch,omitempty"` // The name of the head branch where the code changes are implemented. +} + +// CreateCheckSuite manually creates a check suite for a repository. +// +// GitHub API docs: https://docs.github.com/rest/checks/suites#create-a-check-suite +// +//meta:operation POST /repos/{owner}/{repo}/check-suites +func (s *ChecksService) CreateCheckSuite(ctx context.Context, owner, repo string, opts CreateCheckSuiteOptions) (*CheckSuite, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/check-suites", owner, repo) + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + checkSuite := new(CheckSuite) + resp, err := s.client.Do(ctx, req, checkSuite) + if err != nil { + return nil, resp, err + } + + return checkSuite, resp, nil +} + +// ReRequestCheckSuite triggers GitHub to rerequest an existing check suite, without pushing new code to a repository. +// +// GitHub API docs: https://docs.github.com/rest/checks/suites#rerequest-a-check-suite +// +//meta:operation POST /repos/{owner}/{repo}/check-suites/{check_suite_id}/rerequest +func (s *ChecksService) ReRequestCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/check-suites/%v/rerequest", owner, repo, checkSuiteID) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + resp, err := s.client.Do(ctx, req, nil) + return resp, err +} diff --git a/vendor/github.com/google/go-github/v68/github/code_scanning.go b/vendor/github.com/google/go-github/v68/github/code_scanning.go new file mode 100644 index 0000000000..a8fca98a92 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/code_scanning.go @@ -0,0 +1,664 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "strconv" + "strings" +) + +// CodeScanningService handles communication with the code scanning related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning +type CodeScanningService service + +// Rule represents the complete details of GitHub Code Scanning alert type. +type Rule struct { + ID *string `json:"id,omitempty"` + Severity *string `json:"severity,omitempty"` + Description *string `json:"description,omitempty"` + Name *string `json:"name,omitempty"` + SecuritySeverityLevel *string `json:"security_severity_level,omitempty"` + FullDescription *string `json:"full_description,omitempty"` + Tags []string `json:"tags,omitempty"` + Help *string `json:"help,omitempty"` +} + +// Location represents the exact location of the GitHub Code Scanning Alert in the scanned project. +type Location struct { + Path *string `json:"path,omitempty"` + StartLine *int `json:"start_line,omitempty"` + EndLine *int `json:"end_line,omitempty"` + StartColumn *int `json:"start_column,omitempty"` + EndColumn *int `json:"end_column,omitempty"` +} + +// Message is a part of MostRecentInstance struct which provides the appropriate message when any action is performed on the analysis object. +type Message struct { + Text *string `json:"text,omitempty"` +} + +// MostRecentInstance provides details of the most recent instance of this alert for the default branch or for the specified Git reference. +type MostRecentInstance struct { + Ref *string `json:"ref,omitempty"` + AnalysisKey *string `json:"analysis_key,omitempty"` + Category *string `json:"category,omitempty"` + Environment *string `json:"environment,omitempty"` + State *string `json:"state,omitempty"` + CommitSHA *string `json:"commit_sha,omitempty"` + Message *Message `json:"message,omitempty"` + Location *Location `json:"location,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + Classifications []string `json:"classifications,omitempty"` +} + +// Tool represents the tool used to generate a GitHub Code Scanning Alert. +type Tool struct { + Name *string `json:"name,omitempty"` + GUID *string `json:"guid,omitempty"` + Version *string `json:"version,omitempty"` +} + +// Alert represents an individual GitHub Code Scanning Alert on a single repository. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning +type Alert struct { + Number *int `json:"number,omitempty"` + Repository *Repository `json:"repository,omitempty"` + RuleID *string `json:"rule_id,omitempty"` + RuleSeverity *string `json:"rule_severity,omitempty"` + RuleDescription *string `json:"rule_description,omitempty"` + Rule *Rule `json:"rule,omitempty"` + Tool *Tool `json:"tool,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + FixedAt *Timestamp `json:"fixed_at,omitempty"` + State *string `json:"state,omitempty"` + ClosedBy *User `json:"closed_by,omitempty"` + ClosedAt *Timestamp `json:"closed_at,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + MostRecentInstance *MostRecentInstance `json:"most_recent_instance,omitempty"` + Instances []*MostRecentInstance `json:"instances,omitempty"` + DismissedBy *User `json:"dismissed_by,omitempty"` + DismissedAt *Timestamp `json:"dismissed_at,omitempty"` + DismissedReason *string `json:"dismissed_reason,omitempty"` + DismissedComment *string `json:"dismissed_comment,omitempty"` + InstancesURL *string `json:"instances_url,omitempty"` +} + +// ID returns the ID associated with an alert. It is the number at the end of the security alert's URL. +func (a *Alert) ID() int64 { + if a == nil { + return 0 + } + + s := a.GetHTMLURL() + + // Check for an ID to parse at the end of the url + if i := strings.LastIndex(s, "/"); i >= 0 { + s = s[i+1:] + } + + // Return the alert ID as a 64-bit integer. Unable to convert or out of range returns 0. + id, err := strconv.ParseInt(s, 10, 64) + if err != nil { + return 0 + } + + return id +} + +// AlertInstancesListOptions specifies optional parameters to the CodeScanningService.ListAlertInstances method. +type AlertInstancesListOptions struct { + // Return code scanning alert instances for a specific branch reference. + // The ref can be formatted as refs/heads/ or simply . To reference a pull request use refs/pull//merge + Ref string `url:"ref,omitempty"` + + ListOptions +} + +// AlertListOptions specifies optional parameters to the CodeScanningService.ListAlerts method. +type AlertListOptions struct { + // State of the code scanning alerts to list. Set to closed to list only closed code scanning alerts. Default: open + State string `url:"state,omitempty"` + + // Return code scanning alerts for a specific branch reference. + // The ref can be formatted as refs/heads/ or simply . To reference a pull request use refs/pull//merge + Ref string `url:"ref,omitempty"` + + // If specified, only code scanning alerts with this severity will be returned. Possible values are: critical, high, medium, low, warning, note, error. + Severity string `url:"severity,omitempty"` + + // The name of a code scanning tool. Only results by this tool will be listed. + ToolName string `url:"tool_name,omitempty"` + + ListCursorOptions + + // Add ListOptions so offset pagination with integer type "page" query parameter is accepted + // since ListCursorOptions accepts "page" as string only. + ListOptions +} + +// AnalysesListOptions specifies optional parameters to the CodeScanningService.ListAnalysesForRepo method. +type AnalysesListOptions struct { + // Return code scanning analyses belonging to the same SARIF upload. + SarifID *string `url:"sarif_id,omitempty"` + + // Return code scanning analyses for a specific branch reference. + // The ref can be formatted as refs/heads/ or simply . To reference a pull request use refs/pull//merge + Ref *string `url:"ref,omitempty"` + + ListOptions +} + +// CodeQLDatabase represents a metadata about the CodeQL database. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning +type CodeQLDatabase struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Language *string `json:"language,omitempty"` + Uploader *User `json:"uploader,omitempty"` + ContentType *string `json:"content_type,omitempty"` + Size *int64 `json:"size,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + URL *string `json:"url,omitempty"` +} + +// ScanningAnalysis represents an individual GitHub Code Scanning ScanningAnalysis on a single repository. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning +type ScanningAnalysis struct { + ID *int64 `json:"id,omitempty"` + Ref *string `json:"ref,omitempty"` + CommitSHA *string `json:"commit_sha,omitempty"` + AnalysisKey *string `json:"analysis_key,omitempty"` + Environment *string `json:"environment,omitempty"` + Error *string `json:"error,omitempty"` + Category *string `json:"category,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + ResultsCount *int `json:"results_count,omitempty"` + RulesCount *int `json:"rules_count,omitempty"` + URL *string `json:"url,omitempty"` + SarifID *string `json:"sarif_id,omitempty"` + Tool *Tool `json:"tool,omitempty"` + Deletable *bool `json:"deletable,omitempty"` + Warning *string `json:"warning,omitempty"` +} + +// SarifAnalysis specifies the results of a code scanning job. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning +type SarifAnalysis struct { + CommitSHA *string `json:"commit_sha,omitempty"` + Ref *string `json:"ref,omitempty"` + Sarif *string `json:"sarif,omitempty"` + CheckoutURI *string `json:"checkout_uri,omitempty"` + StartedAt *Timestamp `json:"started_at,omitempty"` + ToolName *string `json:"tool_name,omitempty"` +} + +// CodeScanningAlertState specifies the state of a code scanning alert. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning +type CodeScanningAlertState struct { + // State sets the state of the code scanning alert and is a required field. + // You must also provide DismissedReason when you set the state to "dismissed". + // State can be one of: "open", "dismissed". + State string `json:"state"` + // DismissedReason represents the reason for dismissing or closing the alert. + // It is required when the state is "dismissed". + // It can be one of: "false positive", "won't fix", "used in tests". + DismissedReason *string `json:"dismissed_reason,omitempty"` + // DismissedComment is associated with the dismissal of the alert. + DismissedComment *string `json:"dismissed_comment,omitempty"` +} + +// SarifID identifies a sarif analysis upload. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning +type SarifID struct { + ID *string `json:"id,omitempty"` + URL *string `json:"url,omitempty"` +} + +// ListAlertsForOrg lists code scanning alerts for an org. +// +// You must use an access token with the security_events scope to use this endpoint. GitHub Apps must have the security_events +// read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#list-code-scanning-alerts-for-an-organization +// +//meta:operation GET /orgs/{org}/code-scanning/alerts +func (s *CodeScanningService) ListAlertsForOrg(ctx context.Context, org string, opts *AlertListOptions) ([]*Alert, *Response, error) { + u := fmt.Sprintf("orgs/%v/code-scanning/alerts", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var alerts []*Alert + resp, err := s.client.Do(ctx, req, &alerts) + if err != nil { + return nil, resp, err + } + + return alerts, resp, nil +} + +// ListAlertsForRepo lists code scanning alerts for a repository. +// +// Lists all open code scanning alerts for the default branch (usually master) and protected branches in a repository. +// You must use an access token with the security_events scope to use this endpoint. GitHub Apps must have the security_events +// read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#list-code-scanning-alerts-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/code-scanning/alerts +func (s *CodeScanningService) ListAlertsForRepo(ctx context.Context, owner, repo string, opts *AlertListOptions) ([]*Alert, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/alerts", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var alerts []*Alert + resp, err := s.client.Do(ctx, req, &alerts) + if err != nil { + return nil, resp, err + } + + return alerts, resp, nil +} + +// GetAlert gets a single code scanning alert for a repository. +// +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the security_events read permission to use this endpoint. +// +// The security alert_id is the number at the end of the security alert's URL. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#get-a-code-scanning-alert +// +//meta:operation GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number} +func (s *CodeScanningService) GetAlert(ctx context.Context, owner, repo string, id int64) (*Alert, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/alerts/%v", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + a := new(Alert) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + + return a, resp, nil +} + +// UpdateAlert updates the state of a single code scanning alert for a repository. +// +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the security_events read permission to use this endpoint. +// +// The security alert_id is the number at the end of the security alert's URL. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#update-a-code-scanning-alert +// +//meta:operation PATCH /repos/{owner}/{repo}/code-scanning/alerts/{alert_number} +func (s *CodeScanningService) UpdateAlert(ctx context.Context, owner, repo string, id int64, stateInfo *CodeScanningAlertState) (*Alert, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/alerts/%v", owner, repo, id) + + req, err := s.client.NewRequest("PATCH", u, stateInfo) + if err != nil { + return nil, nil, err + } + + a := new(Alert) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + + return a, resp, nil +} + +// ListAlertInstances lists instances of a code scanning alert. +// +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the security_events read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#list-instances-of-a-code-scanning-alert +// +//meta:operation GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances +func (s *CodeScanningService) ListAlertInstances(ctx context.Context, owner, repo string, id int64, opts *AlertInstancesListOptions) ([]*MostRecentInstance, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/alerts/%v/instances", owner, repo, id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var alertInstances []*MostRecentInstance + resp, err := s.client.Do(ctx, req, &alertInstances) + if err != nil { + return nil, resp, err + } + + return alertInstances, resp, nil +} + +// UploadSarif uploads the result of code scanning job to GitHub. +// +// For the parameter sarif, you must first compress your SARIF file using gzip and then translate the contents of the file into a Base64 encoding string. +// You must use an access token with the security_events scope to use this endpoint. GitHub Apps must have the security_events +// write permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#upload-an-analysis-as-sarif-data +// +//meta:operation POST /repos/{owner}/{repo}/code-scanning/sarifs +func (s *CodeScanningService) UploadSarif(ctx context.Context, owner, repo string, sarif *SarifAnalysis) (*SarifID, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/sarifs", owner, repo) + + req, err := s.client.NewRequest("POST", u, sarif) + if err != nil { + return nil, nil, err + } + + // This will always return an error without unmarshalling the data + resp, err := s.client.Do(ctx, req, nil) + // Even though there was an error, we still return the response + // in case the caller wants to inspect it further. + // However, if the error is AcceptedError, decode it below before + // returning from this function and closing the response body. + var acceptedError *AcceptedError + if !errors.As(err, &acceptedError) { + return nil, resp, err + } + sarifID := new(SarifID) + decErr := json.Unmarshal(acceptedError.Raw, sarifID) + if decErr != nil { + return nil, resp, decErr + } + + return sarifID, resp, nil +} + +// SARIFUpload represents information about a SARIF upload. +type SARIFUpload struct { + // `pending` files have not yet been processed, while `complete` means results from the SARIF have been stored. + // `failed` files have either not been processed at all, or could only be partially processed. + ProcessingStatus *string `json:"processing_status,omitempty"` + // The REST API URL for getting the analyses associated with the upload. + AnalysesURL *string `json:"analyses_url,omitempty"` +} + +// GetSARIF gets information about a SARIF upload. +// +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the security_events read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#get-information-about-a-sarif-upload +// +//meta:operation GET /repos/{owner}/{repo}/code-scanning/sarifs/{sarif_id} +func (s *CodeScanningService) GetSARIF(ctx context.Context, owner, repo, sarifID string) (*SARIFUpload, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/sarifs/%v", owner, repo, sarifID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + sarifUpload := new(SARIFUpload) + resp, err := s.client.Do(ctx, req, sarifUpload) + if err != nil { + return nil, resp, err + } + + return sarifUpload, resp, nil +} + +// ListAnalysesForRepo lists code scanning analyses for a repository. +// +// Lists the details of all code scanning analyses for a repository, starting with the most recent. +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the security_events read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#list-code-scanning-analyses-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/code-scanning/analyses +func (s *CodeScanningService) ListAnalysesForRepo(ctx context.Context, owner, repo string, opts *AnalysesListOptions) ([]*ScanningAnalysis, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/analyses", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var analyses []*ScanningAnalysis + resp, err := s.client.Do(ctx, req, &analyses) + if err != nil { + return nil, resp, err + } + + return analyses, resp, nil +} + +// GetAnalysis gets a single code scanning analysis for a repository. +// +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the security_events read permission to use this endpoint. +// +// The security analysis_id is the ID of the analysis, as returned from the ListAnalysesForRepo operation. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#get-a-code-scanning-analysis-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/code-scanning/analyses/{analysis_id} +func (s *CodeScanningService) GetAnalysis(ctx context.Context, owner, repo string, id int64) (*ScanningAnalysis, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/analyses/%v", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + analysis := new(ScanningAnalysis) + resp, err := s.client.Do(ctx, req, analysis) + if err != nil { + return nil, resp, err + } + + return analysis, resp, nil +} + +// DeleteAnalysis represents a successful deletion of a code scanning analysis. +type DeleteAnalysis struct { + // Next deletable analysis in chain, without last analysis deletion confirmation + NextAnalysisURL *string `json:"next_analysis_url,omitempty"` + // Next deletable analysis in chain, with last analysis deletion confirmation + ConfirmDeleteURL *string `json:"confirm_delete_url,omitempty"` +} + +// DeleteAnalysis deletes a single code scanning analysis from a repository. +// +// You must use an access token with the repo scope to use this endpoint. +// GitHub Apps must have the security_events read permission to use this endpoint. +// +// The security analysis_id is the ID of the analysis, as returned from the ListAnalysesForRepo operation. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#delete-a-code-scanning-analysis-from-a-repository +// +//meta:operation DELETE /repos/{owner}/{repo}/code-scanning/analyses/{analysis_id} +func (s *CodeScanningService) DeleteAnalysis(ctx context.Context, owner, repo string, id int64) (*DeleteAnalysis, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/analyses/%v", owner, repo, id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, nil, err + } + + deleteAnalysis := new(DeleteAnalysis) + resp, err := s.client.Do(ctx, req, deleteAnalysis) + if err != nil { + return nil, resp, err + } + + return deleteAnalysis, resp, nil +} + +// ListCodeQLDatabases lists the CodeQL databases that are available in a repository. +// +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the contents read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#list-codeql-databases-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/code-scanning/codeql/databases +func (s *CodeScanningService) ListCodeQLDatabases(ctx context.Context, owner, repo string) ([]*CodeQLDatabase, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/codeql/databases", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var codeqlDatabases []*CodeQLDatabase + resp, err := s.client.Do(ctx, req, &codeqlDatabases) + if err != nil { + return nil, resp, err + } + + return codeqlDatabases, resp, nil +} + +// GetCodeQLDatabase gets a CodeQL database for a language in a repository. +// +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the contents read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#get-a-codeql-database-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/code-scanning/codeql/databases/{language} +func (s *CodeScanningService) GetCodeQLDatabase(ctx context.Context, owner, repo, language string) (*CodeQLDatabase, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/codeql/databases/%v", owner, repo, language) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + codeqlDatabase := new(CodeQLDatabase) + resp, err := s.client.Do(ctx, req, codeqlDatabase) + if err != nil { + return nil, resp, err + } + + return codeqlDatabase, resp, nil +} + +// DefaultSetupConfiguration represents a code scanning default setup configuration. +type DefaultSetupConfiguration struct { + State *string `json:"state,omitempty"` + Languages []string `json:"languages,omitempty"` + QuerySuite *string `json:"query_suite,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +// GetDefaultSetupConfiguration gets a code scanning default setup configuration. +// +// You must use an access token with the repo scope to use this +// endpoint with private repos or the public_repo scope for public repos. GitHub Apps must have the repo write +// permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#get-a-code-scanning-default-setup-configuration +// +//meta:operation GET /repos/{owner}/{repo}/code-scanning/default-setup +func (s *CodeScanningService) GetDefaultSetupConfiguration(ctx context.Context, owner, repo string) (*DefaultSetupConfiguration, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/code-scanning/default-setup", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + cfg := new(DefaultSetupConfiguration) + resp, err := s.client.Do(ctx, req, cfg) + if err != nil { + return nil, resp, err + } + + return cfg, resp, nil +} + +// UpdateDefaultSetupConfigurationOptions specifies parameters to the CodeScanningService.UpdateDefaultSetupConfiguration +// method. +type UpdateDefaultSetupConfigurationOptions struct { + State string `json:"state"` + QuerySuite *string `json:"query_suite,omitempty"` + Languages []string `json:"languages,omitempty"` +} + +// UpdateDefaultSetupConfigurationResponse represents a response from updating a code scanning default setup configuration. +type UpdateDefaultSetupConfigurationResponse struct { + RunID *int64 `json:"run_id,omitempty"` + RunURL *string `json:"run_url,omitempty"` +} + +// UpdateDefaultSetupConfiguration updates a code scanning default setup configuration. +// +// You must use an access token with the repo scope to use this +// endpoint with private repos or the public_repo scope for public repos. GitHub Apps must have the repo write +// permission to use this endpoint. +// +// This method might return an AcceptedError and a status code of 202. This is because this is the status that GitHub +// returns to signify that it has now scheduled the update of the pull request branch in a background task. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#update-a-code-scanning-default-setup-configuration +// +//meta:operation PATCH /repos/{owner}/{repo}/code-scanning/default-setup +func (s *CodeScanningService) UpdateDefaultSetupConfiguration(ctx context.Context, owner, repo string, options *UpdateDefaultSetupConfigurationOptions) (*UpdateDefaultSetupConfigurationResponse, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/code-scanning/default-setup", owner, repo) + + req, err := s.client.NewRequest("PATCH", u, options) + if err != nil { + return nil, nil, err + } + + a := new(UpdateDefaultSetupConfigurationResponse) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + + return a, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/codesofconduct.go b/vendor/github.com/google/go-github/v68/github/codesofconduct.go new file mode 100644 index 0000000000..aba0574171 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/codesofconduct.go @@ -0,0 +1,87 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// CodesOfConductService provides access to code-of-conduct-related functions in the GitHub API. +type CodesOfConductService service + +// CodeOfConduct represents a code of conduct. +type CodeOfConduct struct { + Name *string `json:"name,omitempty"` + Key *string `json:"key,omitempty"` + URL *string `json:"url,omitempty"` + Body *string `json:"body,omitempty"` +} + +func (c *CodeOfConduct) String() string { + return Stringify(c) +} + +// List returns all codes of conduct. +// +// GitHub API docs: https://docs.github.com/rest/codes-of-conduct/codes-of-conduct#get-all-codes-of-conduct +// +//meta:operation GET /codes_of_conduct +func (s *CodesOfConductService) List(ctx context.Context) ([]*CodeOfConduct, *Response, error) { + req, err := s.client.NewRequest("GET", "codes_of_conduct", nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeCodesOfConductPreview) + + var cs []*CodeOfConduct + resp, err := s.client.Do(ctx, req, &cs) + if err != nil { + return nil, resp, err + } + + return cs, resp, nil +} + +// ListCodesOfConduct returns all codes of conduct. +// +// Deprecated: Use CodesOfConductService.List instead. +func (c *Client) ListCodesOfConduct(ctx context.Context) ([]*CodeOfConduct, *Response, error) { + return c.CodesOfConduct.List(ctx) +} + +// Get returns an individual code of conduct. +// +// GitHub API docs: https://docs.github.com/rest/codes-of-conduct/codes-of-conduct#get-a-code-of-conduct +// +//meta:operation GET /codes_of_conduct/{key} +func (s *CodesOfConductService) Get(ctx context.Context, key string) (*CodeOfConduct, *Response, error) { + u := fmt.Sprintf("codes_of_conduct/%s", key) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeCodesOfConductPreview) + + coc := new(CodeOfConduct) + resp, err := s.client.Do(ctx, req, coc) + if err != nil { + return nil, resp, err + } + + return coc, resp, nil +} + +// GetCodeOfConduct returns an individual code of conduct. +// +// Deprecated: Use CodesOfConductService.Get instead. +func (c *Client) GetCodeOfConduct(ctx context.Context, key string) (*CodeOfConduct, *Response, error) { + return c.CodesOfConduct.Get(ctx, key) +} diff --git a/vendor/github.com/google/go-github/v68/github/codespaces.go b/vendor/github.com/google/go-github/v68/github/codespaces.go new file mode 100644 index 0000000000..608370503f --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/codespaces.go @@ -0,0 +1,266 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// CodespacesService handles communication with the Codespaces related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/ +type CodespacesService service + +// Codespace represents a codespace. +// +// GitHub API docs: https://docs.github.com/rest/codespaces +type Codespace struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + DisplayName *string `json:"display_name,omitempty"` + EnvironmentID *string `json:"environment_id,omitempty"` + Owner *User `json:"owner,omitempty"` + BillableOwner *User `json:"billable_owner,omitempty"` + Repository *Repository `json:"repository,omitempty"` + Machine *CodespacesMachine `json:"machine,omitempty"` + DevcontainerPath *string `json:"devcontainer_path,omitempty"` + Prebuild *bool `json:"prebuild,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + LastUsedAt *Timestamp `json:"last_used_at,omitempty"` + State *string `json:"state,omitempty"` + URL *string `json:"url,omitempty"` + GitStatus *CodespacesGitStatus `json:"git_status,omitempty"` + Location *string `json:"location,omitempty"` + IdleTimeoutMinutes *int `json:"idle_timeout_minutes,omitempty"` + WebURL *string `json:"web_url,omitempty"` + MachinesURL *string `json:"machines_url,omitempty"` + StartURL *string `json:"start_url,omitempty"` + StopURL *string `json:"stop_url,omitempty"` + PullsURL *string `json:"pulls_url,omitempty"` + RecentFolders []string `json:"recent_folders,omitempty"` + RuntimeConstraints *CodespacesRuntimeConstraints `json:"runtime_constraints,omitempty"` + PendingOperation *bool `json:"pending_operation,omitempty"` + PendingOperationDisabledReason *string `json:"pending_operation_disabled_reason,omitempty"` + IdleTimeoutNotice *string `json:"idle_timeout_notice,omitempty"` + RetentionPeriodMinutes *int `json:"retention_period_minutes,omitempty"` + RetentionExpiresAt *Timestamp `json:"retention_expires_at,omitempty"` + LastKnownStopNotice *string `json:"last_known_stop_notice,omitempty"` +} + +// CodespacesGitStatus represents the git status of a codespace. +type CodespacesGitStatus struct { + Ahead *int `json:"ahead,omitempty"` + Behind *int `json:"behind,omitempty"` + HasUnpushedChanges *bool `json:"has_unpushed_changes,omitempty"` + HasUncommittedChanges *bool `json:"has_uncommitted_changes,omitempty"` + Ref *string `json:"ref,omitempty"` +} + +// CodespacesMachine represents the machine type of a codespace. +type CodespacesMachine struct { + Name *string `json:"name,omitempty"` + DisplayName *string `json:"display_name,omitempty"` + OperatingSystem *string `json:"operating_system,omitempty"` + StorageInBytes *int64 `json:"storage_in_bytes,omitempty"` + MemoryInBytes *int64 `json:"memory_in_bytes,omitempty"` + CPUs *int `json:"cpus,omitempty"` + PrebuildAvailability *string `json:"prebuild_availability,omitempty"` +} + +// CodespacesRuntimeConstraints represents the runtime constraints of a codespace. +type CodespacesRuntimeConstraints struct { + AllowedPortPrivacySettings []string `json:"allowed_port_privacy_settings,omitempty"` +} + +// ListCodespaces represents the response from the list codespaces endpoints. +type ListCodespaces struct { + TotalCount *int `json:"total_count,omitempty"` + Codespaces []*Codespace `json:"codespaces"` +} + +// ListInRepo lists codespaces for a user in a repository. +// +// Lists the codespaces associated with a specified repository and the authenticated user. +// You must authenticate using an access token with the codespace scope to use this endpoint. +// GitHub Apps must have read access to the codespaces repository permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/codespaces#list-codespaces-in-a-repository-for-the-authenticated-user +// +//meta:operation GET /repos/{owner}/{repo}/codespaces +func (s *CodespacesService) ListInRepo(ctx context.Context, owner, repo string, opts *ListOptions) (*ListCodespaces, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/codespaces", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var codespaces *ListCodespaces + resp, err := s.client.Do(ctx, req, &codespaces) + if err != nil { + return nil, resp, err + } + + return codespaces, resp, nil +} + +// ListCodespacesOptions represents the options for listing codespaces for a user. +type ListCodespacesOptions struct { + ListOptions + RepositoryID int64 `url:"repository_id,omitempty"` +} + +// List lists codespaces for an authenticated user. +// +// Lists the authenticated user's codespaces. +// You must authenticate using an access token with the codespace scope to use this endpoint. +// GitHub Apps must have read access to the codespaces repository permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/codespaces#list-codespaces-for-the-authenticated-user +// +//meta:operation GET /user/codespaces +func (s *CodespacesService) List(ctx context.Context, opts *ListCodespacesOptions) (*ListCodespaces, *Response, error) { + u := "user/codespaces" + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var codespaces *ListCodespaces + resp, err := s.client.Do(ctx, req, &codespaces) + if err != nil { + return nil, resp, err + } + + return codespaces, resp, nil +} + +// CreateCodespaceOptions represents options for the creation of a codespace in a repository. +type CreateCodespaceOptions struct { + Ref *string `json:"ref,omitempty"` + // Geo represents the geographic area for this codespace. + // If not specified, the value is assigned by IP. + // This property replaces location, which is being deprecated. + // Geo can be one of: `EuropeWest`, `SoutheastAsia`, `UsEast`, `UsWest`. + Geo *string `json:"geo,omitempty"` + ClientIP *string `json:"client_ip,omitempty"` + Machine *string `json:"machine,omitempty"` + DevcontainerPath *string `json:"devcontainer_path,omitempty"` + MultiRepoPermissionsOptOut *bool `json:"multi_repo_permissions_opt_out,omitempty"` + WorkingDirectory *string `json:"working_directory,omitempty"` + IdleTimeoutMinutes *int `json:"idle_timeout_minutes,omitempty"` + DisplayName *string `json:"display_name,omitempty"` + // RetentionPeriodMinutes represents the duration in minutes after codespace has gone idle in which it will be deleted. + // Must be integer minutes between 0 and 43200 (30 days). + RetentionPeriodMinutes *int `json:"retention_period_minutes,omitempty"` +} + +// CreateInRepo creates a codespace in a repository. +// +// Creates a codespace owned by the authenticated user in the specified repository. +// You must authenticate using an access token with the codespace scope to use this endpoint. +// GitHub Apps must have write access to the codespaces repository permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/codespaces#create-a-codespace-in-a-repository +// +//meta:operation POST /repos/{owner}/{repo}/codespaces +func (s *CodespacesService) CreateInRepo(ctx context.Context, owner, repo string, request *CreateCodespaceOptions) (*Codespace, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/codespaces", owner, repo) + + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + var codespace *Codespace + resp, err := s.client.Do(ctx, req, &codespace) + if err != nil { + return nil, resp, err + } + + return codespace, resp, nil +} + +// Start starts a codespace. +// +// You must authenticate using an access token with the codespace scope to use this endpoint. +// GitHub Apps must have write access to the codespaces_lifecycle_admin repository permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/codespaces#start-a-codespace-for-the-authenticated-user +// +//meta:operation POST /user/codespaces/{codespace_name}/start +func (s *CodespacesService) Start(ctx context.Context, codespaceName string) (*Codespace, *Response, error) { + u := fmt.Sprintf("user/codespaces/%v/start", codespaceName) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + var codespace *Codespace + resp, err := s.client.Do(ctx, req, &codespace) + if err != nil { + return nil, resp, err + } + + return codespace, resp, nil +} + +// Stop stops a codespace. +// +// You must authenticate using an access token with the codespace scope to use this endpoint. +// GitHub Apps must have write access to the codespaces_lifecycle_admin repository permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/codespaces#stop-a-codespace-for-the-authenticated-user +// +//meta:operation POST /user/codespaces/{codespace_name}/stop +func (s *CodespacesService) Stop(ctx context.Context, codespaceName string) (*Codespace, *Response, error) { + u := fmt.Sprintf("user/codespaces/%v/stop", codespaceName) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + var codespace *Codespace + resp, err := s.client.Do(ctx, req, &codespace) + if err != nil { + return nil, resp, err + } + + return codespace, resp, nil +} + +// Delete deletes a codespace. +// +// You must authenticate using an access token with the codespace scope to use this endpoint. +// GitHub Apps must have write access to the codespaces repository permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/codespaces#delete-a-codespace-for-the-authenticated-user +// +//meta:operation DELETE /user/codespaces/{codespace_name} +func (s *CodespacesService) Delete(ctx context.Context, codespaceName string) (*Response, error) { + u := fmt.Sprintf("user/codespaces/%v", codespaceName) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/codespaces_secrets.go b/vendor/github.com/google/go-github/v68/github/codespaces_secrets.go new file mode 100644 index 0000000000..438c27f8ff --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/codespaces_secrets.go @@ -0,0 +1,451 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListUserSecrets list all secrets available for a users codespace +// +// Lists all secrets available for a user's Codespaces without revealing their encrypted values +// You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint +// GitHub Apps must have read access to the codespaces_user_secrets user permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/secrets#list-secrets-for-the-authenticated-user +// +//meta:operation GET /user/codespaces/secrets +func (s *CodespacesService) ListUserSecrets(ctx context.Context, opts *ListOptions) (*Secrets, *Response, error) { + u, err := addOptions("user/codespaces/secrets", opts) + if err != nil { + return nil, nil, err + } + return s.listSecrets(ctx, u) +} + +// ListOrgSecrets list all secrets available to an org +// +// Lists all Codespaces secrets available at the organization-level without revealing their encrypted values. You must authenticate using an access token with the admin:org scope to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/organization-secrets#list-organization-secrets +// +//meta:operation GET /orgs/{org}/codespaces/secrets +func (s *CodespacesService) ListOrgSecrets(ctx context.Context, org string, opts *ListOptions) (*Secrets, *Response, error) { + u := fmt.Sprintf("orgs/%v/codespaces/secrets", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + return s.listSecrets(ctx, u) +} + +// ListRepoSecrets list all secrets available to a repo +// +// Lists all secrets available in a repository without revealing their encrypted values. You must authenticate using an access token with the repo scope to use this endpoint. GitHub Apps must have write access to the codespaces_secrets repository permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/repository-secrets#list-repository-secrets +// +//meta:operation GET /repos/{owner}/{repo}/codespaces/secrets +func (s *CodespacesService) ListRepoSecrets(ctx context.Context, owner, repo string, opts *ListOptions) (*Secrets, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/codespaces/secrets", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + return s.listSecrets(ctx, u) +} + +func (s *CodespacesService) listSecrets(ctx context.Context, url string) (*Secrets, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + var secrets *Secrets + resp, err := s.client.Do(ctx, req, &secrets) + if err != nil { + return nil, resp, err + } + + return secrets, resp, nil +} + +// GetUserPublicKey gets the users public key for encrypting codespace secrets +// +// Gets your public key, which you need to encrypt secrets. You need to encrypt a secret before you can create or update secrets. +// You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint. +// GitHub Apps must have read access to the codespaces_user_secrets user permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/secrets#get-public-key-for-the-authenticated-user +// +//meta:operation GET /user/codespaces/secrets/public-key +func (s *CodespacesService) GetUserPublicKey(ctx context.Context) (*PublicKey, *Response, error) { + return s.getPublicKey(ctx, "user/codespaces/secrets/public-key") +} + +// GetOrgPublicKey gets the org public key for encrypting codespace secrets +// +// Gets a public key for an organization, which is required in order to encrypt secrets. You need to encrypt the value of a secret before you can create or update secrets. You must authenticate using an access token with the admin:org scope to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/organization-secrets#get-an-organization-public-key +// +//meta:operation GET /orgs/{org}/codespaces/secrets/public-key +func (s *CodespacesService) GetOrgPublicKey(ctx context.Context, org string) (*PublicKey, *Response, error) { + return s.getPublicKey(ctx, fmt.Sprintf("orgs/%v/codespaces/secrets/public-key", org)) +} + +// GetRepoPublicKey gets the repo public key for encrypting codespace secrets +// +// Gets your public key, which you need to encrypt secrets. You need to encrypt a secret before you can create or update secrets. Anyone with read access to the repository can use this endpoint. If the repository is private you must use an access token with the repo scope. GitHub Apps must have write access to the codespaces_secrets repository permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/repository-secrets#get-a-repository-public-key +// +//meta:operation GET /repos/{owner}/{repo}/codespaces/secrets/public-key +func (s *CodespacesService) GetRepoPublicKey(ctx context.Context, owner, repo string) (*PublicKey, *Response, error) { + return s.getPublicKey(ctx, fmt.Sprintf("repos/%v/%v/codespaces/secrets/public-key", owner, repo)) +} + +func (s *CodespacesService) getPublicKey(ctx context.Context, url string) (*PublicKey, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + var publicKey *PublicKey + resp, err := s.client.Do(ctx, req, &publicKey) + if err != nil { + return nil, resp, err + } + + return publicKey, resp, nil +} + +// GetUserSecret gets a users codespace secret +// +// Gets a secret available to a user's codespaces without revealing its encrypted value. +// You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint. +// GitHub Apps must have read access to the codespaces_user_secrets user permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/secrets#get-a-secret-for-the-authenticated-user +// +//meta:operation GET /user/codespaces/secrets/{secret_name} +func (s *CodespacesService) GetUserSecret(ctx context.Context, name string) (*Secret, *Response, error) { + u := fmt.Sprintf("user/codespaces/secrets/%v", name) + return s.getSecret(ctx, u) +} + +// GetOrgSecret gets an org codespace secret +// +// Gets an organization secret without revealing its encrypted value. You must authenticate using an access token with the admin:org scope to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/organization-secrets#get-an-organization-secret +// +//meta:operation GET /orgs/{org}/codespaces/secrets/{secret_name} +func (s *CodespacesService) GetOrgSecret(ctx context.Context, org, name string) (*Secret, *Response, error) { + u := fmt.Sprintf("orgs/%v/codespaces/secrets/%v", org, name) + return s.getSecret(ctx, u) +} + +// GetRepoSecret gets a repo codespace secret +// +// Gets a single repository secret without revealing its encrypted value. You must authenticate using an access token with the repo scope to use this endpoint. GitHub Apps must have write access to the codespaces_secrets repository permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/repository-secrets#get-a-repository-secret +// +//meta:operation GET /repos/{owner}/{repo}/codespaces/secrets/{secret_name} +func (s *CodespacesService) GetRepoSecret(ctx context.Context, owner, repo, name string) (*Secret, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/codespaces/secrets/%v", owner, repo, name) + return s.getSecret(ctx, u) +} + +func (s *CodespacesService) getSecret(ctx context.Context, url string) (*Secret, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + var secret *Secret + resp, err := s.client.Do(ctx, req, &secret) + if err != nil { + return nil, resp, err + } + + return secret, resp, nil +} + +// CreateOrUpdateUserSecret creates or updates a users codespace secret +// +// Creates or updates a secret for a user's codespace with an encrypted value. Encrypt your secret using LibSodium. +// You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must also have Codespaces access to use this endpoint. +// GitHub Apps must have write access to the codespaces_user_secrets user permission and codespaces_secrets repository permission on all referenced repositories to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/secrets#create-or-update-a-secret-for-the-authenticated-user +// +//meta:operation PUT /user/codespaces/secrets/{secret_name} +func (s *CodespacesService) CreateOrUpdateUserSecret(ctx context.Context, eSecret *EncryptedSecret) (*Response, error) { + u := fmt.Sprintf("user/codespaces/secrets/%v", eSecret.Name) + return s.createOrUpdateSecret(ctx, u, eSecret) +} + +// CreateOrUpdateOrgSecret creates or updates an orgs codespace secret +// +// Creates or updates an organization secret with an encrypted value. Encrypt your secret using LibSodium. You must authenticate using an access token with the admin:org scope to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/organization-secrets#create-or-update-an-organization-secret +// +//meta:operation PUT /orgs/{org}/codespaces/secrets/{secret_name} +func (s *CodespacesService) CreateOrUpdateOrgSecret(ctx context.Context, org string, eSecret *EncryptedSecret) (*Response, error) { + u := fmt.Sprintf("orgs/%v/codespaces/secrets/%v", org, eSecret.Name) + return s.createOrUpdateSecret(ctx, u, eSecret) +} + +// CreateOrUpdateRepoSecret creates or updates a repos codespace secret +// +// Creates or updates a repository secret with an encrypted value. Encrypt your secret using LibSodium. You must authenticate using an access token with the repo scope to use this endpoint. GitHub Apps must have write access to the codespaces_secrets repository permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/repository-secrets#create-or-update-a-repository-secret +// +//meta:operation PUT /repos/{owner}/{repo}/codespaces/secrets/{secret_name} +func (s *CodespacesService) CreateOrUpdateRepoSecret(ctx context.Context, owner, repo string, eSecret *EncryptedSecret) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/codespaces/secrets/%v", owner, repo, eSecret.Name) + return s.createOrUpdateSecret(ctx, u, eSecret) +} + +func (s *CodespacesService) createOrUpdateSecret(ctx context.Context, url string, eSecret *EncryptedSecret) (*Response, error) { + req, err := s.client.NewRequest("PUT", url, eSecret) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// DeleteUserSecret deletes a users codespace secret +// +// Deletes a secret from a user's codespaces using the secret name. Deleting the secret will remove access from all codespaces that were allowed to access the secret. +// You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint. +// GitHub Apps must have write access to the codespaces_user_secrets user permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/secrets#delete-a-secret-for-the-authenticated-user +// +//meta:operation DELETE /user/codespaces/secrets/{secret_name} +func (s *CodespacesService) DeleteUserSecret(ctx context.Context, name string) (*Response, error) { + u := fmt.Sprintf("user/codespaces/secrets/%v", name) + return s.deleteSecret(ctx, u) +} + +// DeleteOrgSecret deletes an orgs codespace secret +// +// Deletes an organization secret using the secret name. You must authenticate using an access token with the admin:org scope to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/organization-secrets#delete-an-organization-secret +// +//meta:operation DELETE /orgs/{org}/codespaces/secrets/{secret_name} +func (s *CodespacesService) DeleteOrgSecret(ctx context.Context, org, name string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/codespaces/secrets/%v", org, name) + return s.deleteSecret(ctx, u) +} + +// DeleteRepoSecret deletes a repos codespace secret +// +// Deletes a secret in a repository using the secret name. You must authenticate using an access token with the repo scope to use this endpoint. GitHub Apps must have write access to the codespaces_secrets repository permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/repository-secrets#delete-a-repository-secret +// +//meta:operation DELETE /repos/{owner}/{repo}/codespaces/secrets/{secret_name} +func (s *CodespacesService) DeleteRepoSecret(ctx context.Context, owner, repo, name string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/codespaces/secrets/%v", owner, repo, name) + return s.deleteSecret(ctx, u) +} + +func (s *CodespacesService) deleteSecret(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// ListSelectedReposForUserSecret lists the repositories that have been granted the ability to use a user's codespace secret. +// +// You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint. +// GitHub Apps must have read access to the codespaces_user_secrets user permission and write access to the codespaces_secrets repository permission on all referenced repositories to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/secrets#list-selected-repositories-for-a-user-secret +// +//meta:operation GET /user/codespaces/secrets/{secret_name}/repositories +func (s *CodespacesService) ListSelectedReposForUserSecret(ctx context.Context, name string, opts *ListOptions) (*SelectedReposList, *Response, error) { + u := fmt.Sprintf("user/codespaces/secrets/%v/repositories", name) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + return s.listSelectedReposForSecret(ctx, u) +} + +// ListSelectedReposForOrgSecret lists the repositories that have been granted the ability to use an organization's codespace secret. +// +// Lists all repositories that have been selected when the visibility for repository access to a secret is set to selected. You must authenticate using an access token with the admin:org scope to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/organization-secrets#list-selected-repositories-for-an-organization-secret +// +//meta:operation GET /orgs/{org}/codespaces/secrets/{secret_name}/repositories +func (s *CodespacesService) ListSelectedReposForOrgSecret(ctx context.Context, org, name string, opts *ListOptions) (*SelectedReposList, *Response, error) { + u := fmt.Sprintf("orgs/%v/codespaces/secrets/%v/repositories", org, name) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + return s.listSelectedReposForSecret(ctx, u) +} + +func (s *CodespacesService) listSelectedReposForSecret(ctx context.Context, url string) (*SelectedReposList, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + var repositories *SelectedReposList + resp, err := s.client.Do(ctx, req, &repositories) + if err != nil { + return nil, resp, err + } + + return repositories, resp, nil +} + +// SetSelectedReposForUserSecret sets the repositories that have been granted the ability to use a user's codespace secret. +// +// You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint. +// GitHub Apps must have write access to the codespaces_user_secrets user permission and write access to the codespaces_secrets repository permission on all referenced repositories to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/secrets#set-selected-repositories-for-a-user-secret +// +//meta:operation PUT /user/codespaces/secrets/{secret_name}/repositories +func (s *CodespacesService) SetSelectedReposForUserSecret(ctx context.Context, name string, ids SelectedRepoIDs) (*Response, error) { + u := fmt.Sprintf("user/codespaces/secrets/%v/repositories", name) + return s.setSelectedRepoForSecret(ctx, u, ids) +} + +// SetSelectedReposForOrgSecret sets the repositories that have been granted the ability to use a user's codespace secret. +// +// Replaces all repositories for an organization secret when the visibility for repository access is set to selected. The visibility is set when you Create or update an organization secret. You must authenticate using an access token with the admin:org scope to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/organization-secrets#set-selected-repositories-for-an-organization-secret +// +//meta:operation PUT /orgs/{org}/codespaces/secrets/{secret_name}/repositories +func (s *CodespacesService) SetSelectedReposForOrgSecret(ctx context.Context, org, name string, ids SelectedRepoIDs) (*Response, error) { + u := fmt.Sprintf("orgs/%v/codespaces/secrets/%v/repositories", org, name) + return s.setSelectedRepoForSecret(ctx, u, ids) +} + +func (s *CodespacesService) setSelectedRepoForSecret(ctx context.Context, url string, ids SelectedRepoIDs) (*Response, error) { + type repoIDs struct { + SelectedIDs SelectedRepoIDs `json:"selected_repository_ids"` + } + + req, err := s.client.NewRequest("PUT", url, repoIDs{SelectedIDs: ids}) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// AddSelectedRepoToUserSecret adds a repository to the list of repositories that have been granted the ability to use a user's codespace secret. +// +// Adds a repository to the selected repositories for a user's codespace secret. You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint. GitHub Apps must have write access to the codespaces_user_secrets user permission and write access to the codespaces_secrets repository permission on the referenced repository to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/secrets#add-a-selected-repository-to-a-user-secret +// +//meta:operation PUT /user/codespaces/secrets/{secret_name}/repositories/{repository_id} +func (s *CodespacesService) AddSelectedRepoToUserSecret(ctx context.Context, name string, repo *Repository) (*Response, error) { + u := fmt.Sprintf("user/codespaces/secrets/%v/repositories/%v", name, *repo.ID) + return s.addSelectedRepoToSecret(ctx, u) +} + +// AddSelectedRepoToOrgSecret adds a repository to the list of repositories that have been granted the ability to use an organization's codespace secret. +// +// Adds a repository to an organization secret when the visibility for repository access is set to selected. The visibility is set when you Create or update an organization secret. You must authenticate using an access token with the admin:org scope to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/organization-secrets#add-selected-repository-to-an-organization-secret +// +//meta:operation PUT /orgs/{org}/codespaces/secrets/{secret_name}/repositories/{repository_id} +func (s *CodespacesService) AddSelectedRepoToOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) { + u := fmt.Sprintf("orgs/%v/codespaces/secrets/%v/repositories/%v", org, name, *repo.ID) + return s.addSelectedRepoToSecret(ctx, u) +} + +func (s *CodespacesService) addSelectedRepoToSecret(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("PUT", url, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// RemoveSelectedRepoFromUserSecret removes a repository from the list of repositories that have been granted the ability to use a user's codespace secret. +// +// Removes a repository from the selected repositories for a user's codespace secret. You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint. GitHub Apps must have write access to the codespaces_user_secrets user permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/secrets#remove-a-selected-repository-from-a-user-secret +// +//meta:operation DELETE /user/codespaces/secrets/{secret_name}/repositories/{repository_id} +func (s *CodespacesService) RemoveSelectedRepoFromUserSecret(ctx context.Context, name string, repo *Repository) (*Response, error) { + u := fmt.Sprintf("user/codespaces/secrets/%v/repositories/%v", name, *repo.ID) + return s.removeSelectedRepoFromSecret(ctx, u) +} + +// RemoveSelectedRepoFromOrgSecret removes a repository from the list of repositories that have been granted the ability to use an organization's codespace secret. +// +// Removes a repository from an organization secret when the visibility for repository access is set to selected. The visibility is set when you Create or update an organization secret. You must authenticate using an access token with the admin:org scope to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/organization-secrets#remove-selected-repository-from-an-organization-secret +// +//meta:operation DELETE /orgs/{org}/codespaces/secrets/{secret_name}/repositories/{repository_id} +func (s *CodespacesService) RemoveSelectedRepoFromOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) { + u := fmt.Sprintf("orgs/%v/codespaces/secrets/%v/repositories/%v", org, name, *repo.ID) + return s.removeSelectedRepoFromSecret(ctx, u) +} + +func (s *CodespacesService) removeSelectedRepoFromSecret(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/copilot.go b/vendor/github.com/google/go-github/v68/github/copilot.go new file mode 100644 index 0000000000..a2b2aa0995 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/copilot.go @@ -0,0 +1,570 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "time" +) + +// CopilotService provides access to the Copilot-related functions +// in the GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/copilot/ +type CopilotService service + +// CopilotOrganizationDetails represents the details of an organization's Copilot for Business subscription. +type CopilotOrganizationDetails struct { + SeatBreakdown *CopilotSeatBreakdown `json:"seat_breakdown"` + PublicCodeSuggestions string `json:"public_code_suggestions"` + CopilotChat string `json:"copilot_chat"` + SeatManagementSetting string `json:"seat_management_setting"` +} + +// CopilotSeatBreakdown represents the breakdown of Copilot for Business seats for the organization. +type CopilotSeatBreakdown struct { + Total int `json:"total"` + AddedThisCycle int `json:"added_this_cycle"` + PendingCancellation int `json:"pending_cancellation"` + PendingInvitation int `json:"pending_invitation"` + ActiveThisCycle int `json:"active_this_cycle"` + InactiveThisCycle int `json:"inactive_this_cycle"` +} + +// ListCopilotSeatsResponse represents the Copilot for Business seat assignments for an organization. +type ListCopilotSeatsResponse struct { + TotalSeats int64 `json:"total_seats"` + Seats []*CopilotSeatDetails `json:"seats"` +} + +// CopilotSeatDetails represents the details of a Copilot for Business seat. +type CopilotSeatDetails struct { + // Assignee can either be a User, Team, or Organization. + Assignee interface{} `json:"assignee"` + AssigningTeam *Team `json:"assigning_team,omitempty"` + PendingCancellationDate *string `json:"pending_cancellation_date,omitempty"` + LastActivityAt *Timestamp `json:"last_activity_at,omitempty"` + LastActivityEditor *string `json:"last_activity_editor,omitempty"` + CreatedAt *Timestamp `json:"created_at"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + PlanType *string `json:"plan_type,omitempty"` +} + +// SeatAssignments represents the number of seats assigned. +type SeatAssignments struct { + SeatsCreated int `json:"seats_created"` +} + +// SeatCancellations represents the number of seats cancelled. +type SeatCancellations struct { + SeatsCancelled int `json:"seats_cancelled"` +} + +// CopilotMetricsListOptions represents the optional parameters to the CopilotService get metrics methods. +type CopilotMetricsListOptions struct { + Since *time.Time `url:"since,omitempty"` + Until *time.Time `url:"until,omitempty"` + + ListOptions +} + +// CopilotIDECodeCompletionsLanguage represents Copilot usage metrics for completions in the IDE for a language. +type CopilotIDECodeCompletionsLanguage struct { + Name string `json:"name"` + TotalEngagedUsers int `json:"total_engaged_users"` +} + +// CopilotIDECodeCompletionsModelLanguage represents Copilot usage metrics for completions in the IDE for a model and language. +type CopilotIDECodeCompletionsModelLanguage struct { + Name string `json:"name"` + TotalEngagedUsers int `json:"total_engaged_users"` + TotalCodeSuggestions int `json:"total_code_suggestions"` + TotalCodeAcceptances int `json:"total_code_acceptances"` + TotalCodeLinesSuggested int `json:"total_code_lines_suggested"` + TotalCodeLinesAccepted int `json:"total_code_lines_accepted"` +} + +// CopilotIDECodeCompletionsModel represents Copilot usage metrics for completions in the IDE for a model. +type CopilotIDECodeCompletionsModel struct { + Name string `json:"name"` + IsCustomModel bool `json:"is_custom_model"` + CustomModelTrainingDate *string `json:"custom_model_training_date,omitempty"` + TotalEngagedUsers int `json:"total_engaged_users"` + Languages []*CopilotIDECodeCompletionsModelLanguage `json:"languages"` +} + +// CopilotIDECodeCompletionsEditor represents Copilot usage metrics for completions in the IDE for an editor. +type CopilotIDECodeCompletionsEditor struct { + Name string `json:"name"` + TotalEngagedUsers int `json:"total_engaged_users"` + Models []*CopilotIDECodeCompletionsModel `json:"models"` +} + +// CopilotIDECodeCompletions represents Copilot usage metrics for Copilot code completions in the IDE, categorized by editor, model and language. +type CopilotIDECodeCompletions struct { + TotalEngagedUsers int `json:"total_engaged_users"` + Languages []*CopilotIDECodeCompletionsLanguage `json:"languages"` + Editors []*CopilotIDECodeCompletionsEditor `json:"editors"` +} + +// CopilotIDEChatModel represents Copilot usage metrics for chatting with a model in the IDE. +type CopilotIDEChatModel struct { + Name string `json:"name"` + IsCustomModel bool `json:"is_custom_model"` + CustomModelTrainingDate *string `json:"custom_model_training_date,omitempty"` + TotalEngagedUsers int `json:"total_engaged_users"` + TotalChats int `json:"total_chats"` + TotalChatInsertionEvents int `json:"total_chat_insertion_events"` + TotalChatCopyEvents int `json:"total_chat_copy_events"` +} + +// CopilotIDEChatEditor represents Copilot usage metrics for chatting with a model in the IDE, categorized by editor and model. +type CopilotIDEChatEditor struct { + Name string `json:"name"` + TotalEngagedUsers int `json:"total_engaged_users"` + Models []*CopilotIDEChatModel `json:"models"` +} + +// CopilotIDEChat represents Copilot usage metrics for Copilot Chat in the IDE, categorized by editor and model. +type CopilotIDEChat struct { + TotalEngagedUsers int `json:"total_engaged_users"` + Editors []*CopilotIDEChatEditor `json:"editors"` +} + +// CopilotDotcomChatModel represents Copilot usage metrics for chatting with a model in the webbrowser. +type CopilotDotcomChatModel struct { + Name string `json:"name"` + IsCustomModel bool `json:"is_custom_model"` + CustomModelTrainingDate *string `json:"custom_model_training_date,omitempty"` + TotalEngagedUsers int `json:"total_engaged_users"` + TotalChats int `json:"total_chats"` +} + +// CopilotDotcomChat represents Copilot usage metrics for Copilot Chat in the webbrowser, categorized by model. +type CopilotDotcomChat struct { + TotalEngagedUsers int `json:"total_engaged_users"` + Models []*CopilotDotcomChatModel `json:"models"` +} + +// CopilotDotcomPullRequestsModel represents Copilot usage metrics for pull requests in the webbrowser, categorized by model. +type CopilotDotcomPullRequestsModel struct { + Name string `json:"name"` + IsCustomModel bool `json:"is_custom_model"` + CustomModelTrainingDate *string `json:"custom_model_training_date,omitempty"` + TotalPRSummariesCreated int `json:"total_pr_summaries_created"` + TotalEngagedUsers int `json:"total_engaged_users"` +} + +// CopilotDotcomPullRequestsRepository represents Copilot usage metrics for pull requests in the webbrowser, categorized by repository. +type CopilotDotcomPullRequestsRepository struct { + Name string `json:"name"` + TotalEngagedUsers int `json:"total_engaged_users"` + Models []*CopilotDotcomPullRequestsModel `json:"models"` +} + +// CopilotDotcomPullRequests represents Copilot usage metrics for pull requests in the webbrowser, categorized by repository and model. +type CopilotDotcomPullRequests struct { + TotalEngagedUsers int `json:"total_engaged_users"` + Repositories []*CopilotDotcomPullRequestsRepository `json:"repositories"` +} + +// CopilotMetrics represents Copilot usage metrics for a given day. +type CopilotMetrics struct { + Date string `json:"date"` + TotalActiveUsers *int `json:"total_active_users,omitempty"` + TotalEngagedUsers *int `json:"total_engaged_users,omitempty"` + CopilotIDECodeCompletions *CopilotIDECodeCompletions `json:"copilot_ide_code_completions,omitempty"` + CopilotIDEChat *CopilotIDEChat `json:"copilot_ide_chat,omitempty"` + CopilotDotcomChat *CopilotDotcomChat `json:"copilot_dotcom_chat,omitempty"` + CopilotDotcomPullRequests *CopilotDotcomPullRequests `json:"copilot_dotcom_pull_requests,omitempty"` +} + +func (cp *CopilotSeatDetails) UnmarshalJSON(data []byte) error { + // Using an alias to avoid infinite recursion when calling json.Unmarshal + type alias CopilotSeatDetails + var seatDetail alias + + if err := json.Unmarshal(data, &seatDetail); err != nil { + return err + } + + cp.AssigningTeam = seatDetail.AssigningTeam + cp.PendingCancellationDate = seatDetail.PendingCancellationDate + cp.LastActivityAt = seatDetail.LastActivityAt + cp.LastActivityEditor = seatDetail.LastActivityEditor + cp.CreatedAt = seatDetail.CreatedAt + cp.UpdatedAt = seatDetail.UpdatedAt + cp.PlanType = seatDetail.PlanType + + switch v := seatDetail.Assignee.(type) { + case map[string]interface{}: + jsonData, err := json.Marshal(seatDetail.Assignee) + if err != nil { + return err + } + + if v["type"] == nil { + return errors.New("assignee type field is not set") + } + + if t, ok := v["type"].(string); ok && t == "User" { + user := &User{} + if err := json.Unmarshal(jsonData, user); err != nil { + return err + } + cp.Assignee = user + } else if t, ok := v["type"].(string); ok && t == "Team" { + team := &Team{} + if err := json.Unmarshal(jsonData, team); err != nil { + return err + } + cp.Assignee = team + } else if t, ok := v["type"].(string); ok && t == "Organization" { + organization := &Organization{} + if err := json.Unmarshal(jsonData, organization); err != nil { + return err + } + cp.Assignee = organization + } else { + return fmt.Errorf("unsupported assignee type %v", v["type"]) + } + default: + return fmt.Errorf("unsupported assignee type %T", v) + } + + return nil +} + +// GetUser gets the User from the CopilotSeatDetails if the assignee is a user. +func (cp *CopilotSeatDetails) GetUser() (*User, bool) { u, ok := cp.Assignee.(*User); return u, ok } + +// GetTeam gets the Team from the CopilotSeatDetails if the assignee is a team. +func (cp *CopilotSeatDetails) GetTeam() (*Team, bool) { t, ok := cp.Assignee.(*Team); return t, ok } + +// GetOrganization gets the Organization from the CopilotSeatDetails if the assignee is an organization. +func (cp *CopilotSeatDetails) GetOrganization() (*Organization, bool) { + o, ok := cp.Assignee.(*Organization) + return o, ok +} + +// GetCopilotBilling gets Copilot for Business billing information and settings for an organization. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#get-copilot-seat-information-and-settings-for-an-organization +// +//meta:operation GET /orgs/{org}/copilot/billing +func (s *CopilotService) GetCopilotBilling(ctx context.Context, org string) (*CopilotOrganizationDetails, *Response, error) { + u := fmt.Sprintf("orgs/%v/copilot/billing", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var copilotDetails *CopilotOrganizationDetails + resp, err := s.client.Do(ctx, req, &copilotDetails) + if err != nil { + return nil, resp, err + } + + return copilotDetails, resp, nil +} + +// ListCopilotSeats lists Copilot for Business seat assignments for an organization. +// +// To paginate through all seats, populate 'Page' with the number of the last page. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#list-all-copilot-seat-assignments-for-an-organization +// +//meta:operation GET /orgs/{org}/copilot/billing/seats +func (s *CopilotService) ListCopilotSeats(ctx context.Context, org string, opts *ListOptions) (*ListCopilotSeatsResponse, *Response, error) { + u := fmt.Sprintf("orgs/%v/copilot/billing/seats", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var copilotSeats *ListCopilotSeatsResponse + resp, err := s.client.Do(ctx, req, &copilotSeats) + if err != nil { + return nil, resp, err + } + + return copilotSeats, resp, nil +} + +// ListCopilotEnterpriseSeats lists Copilot for Business seat assignments for an enterprise. +// +// To paginate through all seats, populate 'Page' with the number of the last page. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#list-all-copilot-seat-assignments-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/copilot/billing/seats +func (s *CopilotService) ListCopilotEnterpriseSeats(ctx context.Context, enterprise string, opts *ListOptions) (*ListCopilotSeatsResponse, *Response, error) { + u := fmt.Sprintf("enterprises/%v/copilot/billing/seats", enterprise) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var copilotSeats *ListCopilotSeatsResponse + resp, err := s.client.Do(ctx, req, &copilotSeats) + if err != nil { + return nil, resp, err + } + + return copilotSeats, resp, nil +} + +// AddCopilotTeams adds teams to the Copilot for Business subscription for an organization. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#add-teams-to-the-copilot-subscription-for-an-organization +// +//meta:operation POST /orgs/{org}/copilot/billing/selected_teams +func (s *CopilotService) AddCopilotTeams(ctx context.Context, org string, teamNames []string) (*SeatAssignments, *Response, error) { + u := fmt.Sprintf("orgs/%v/copilot/billing/selected_teams", org) + + body := struct { + SelectedTeams []string `json:"selected_teams"` + }{ + SelectedTeams: teamNames, + } + + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + var seatAssignments *SeatAssignments + resp, err := s.client.Do(ctx, req, &seatAssignments) + if err != nil { + return nil, resp, err + } + + return seatAssignments, resp, nil +} + +// RemoveCopilotTeams removes teams from the Copilot for Business subscription for an organization. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#remove-teams-from-the-copilot-subscription-for-an-organization +// +//meta:operation DELETE /orgs/{org}/copilot/billing/selected_teams +func (s *CopilotService) RemoveCopilotTeams(ctx context.Context, org string, teamNames []string) (*SeatCancellations, *Response, error) { + u := fmt.Sprintf("orgs/%v/copilot/billing/selected_teams", org) + + body := struct { + SelectedTeams []string `json:"selected_teams"` + }{ + SelectedTeams: teamNames, + } + + req, err := s.client.NewRequest("DELETE", u, body) + if err != nil { + return nil, nil, err + } + + var seatCancellations *SeatCancellations + resp, err := s.client.Do(ctx, req, &seatCancellations) + if err != nil { + return nil, resp, err + } + + return seatCancellations, resp, nil +} + +// AddCopilotUsers adds users to the Copilot for Business subscription for an organization +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#add-users-to-the-copilot-subscription-for-an-organization +// +//meta:operation POST /orgs/{org}/copilot/billing/selected_users +func (s *CopilotService) AddCopilotUsers(ctx context.Context, org string, users []string) (*SeatAssignments, *Response, error) { + u := fmt.Sprintf("orgs/%v/copilot/billing/selected_users", org) + + body := struct { + SelectedUsernames []string `json:"selected_usernames"` + }{ + SelectedUsernames: users, + } + + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + var seatAssignments *SeatAssignments + resp, err := s.client.Do(ctx, req, &seatAssignments) + if err != nil { + return nil, resp, err + } + + return seatAssignments, resp, nil +} + +// RemoveCopilotUsers removes users from the Copilot for Business subscription for an organization. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#remove-users-from-the-copilot-subscription-for-an-organization +// +//meta:operation DELETE /orgs/{org}/copilot/billing/selected_users +func (s *CopilotService) RemoveCopilotUsers(ctx context.Context, org string, users []string) (*SeatCancellations, *Response, error) { + u := fmt.Sprintf("orgs/%v/copilot/billing/selected_users", org) + + body := struct { + SelectedUsernames []string `json:"selected_usernames"` + }{ + SelectedUsernames: users, + } + + req, err := s.client.NewRequest("DELETE", u, body) + if err != nil { + return nil, nil, err + } + + var seatCancellations *SeatCancellations + resp, err := s.client.Do(ctx, req, &seatCancellations) + if err != nil { + return nil, resp, err + } + + return seatCancellations, resp, nil +} + +// GetSeatDetails gets Copilot for Business seat assignment details for a user. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#get-copilot-seat-assignment-details-for-a-user +// +//meta:operation GET /orgs/{org}/members/{username}/copilot +func (s *CopilotService) GetSeatDetails(ctx context.Context, org, user string) (*CopilotSeatDetails, *Response, error) { + u := fmt.Sprintf("orgs/%v/members/%v/copilot", org, user) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var seatDetails *CopilotSeatDetails + resp, err := s.client.Do(ctx, req, &seatDetails) + if err != nil { + return nil, resp, err + } + + return seatDetails, resp, nil +} + +// GetEnterpriseMetrics gets Copilot usage metrics for an enterprise. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-metrics#get-copilot-metrics-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/copilot/metrics +func (s *CopilotService) GetEnterpriseMetrics(ctx context.Context, enterprise string, opts *CopilotMetricsListOptions) ([]*CopilotMetrics, *Response, error) { + u := fmt.Sprintf("enterprises/%v/copilot/metrics", enterprise) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var metrics []*CopilotMetrics + resp, err := s.client.Do(ctx, req, &metrics) + if err != nil { + return nil, resp, err + } + + return metrics, resp, nil +} + +// GetEnterpriseTeamMetrics gets Copilot usage metrics for an enterprise team. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-metrics#get-copilot-metrics-for-an-enterprise-team +// +//meta:operation GET /enterprises/{enterprise}/team/{team_slug}/copilot/metrics +func (s *CopilotService) GetEnterpriseTeamMetrics(ctx context.Context, enterprise, team string, opts *CopilotMetricsListOptions) ([]*CopilotMetrics, *Response, error) { + u := fmt.Sprintf("enterprises/%v/team/%v/copilot/metrics", enterprise, team) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var metrics []*CopilotMetrics + resp, err := s.client.Do(ctx, req, &metrics) + if err != nil { + return nil, resp, err + } + + return metrics, resp, nil +} + +// GetOrganizationMetrics gets Copilot usage metrics for an organization. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-metrics#get-copilot-metrics-for-an-organization +// +//meta:operation GET /orgs/{org}/copilot/metrics +func (s *CopilotService) GetOrganizationMetrics(ctx context.Context, org string, opts *CopilotMetricsListOptions) ([]*CopilotMetrics, *Response, error) { + u := fmt.Sprintf("orgs/%v/copilot/metrics", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var metrics []*CopilotMetrics + resp, err := s.client.Do(ctx, req, &metrics) + if err != nil { + return nil, resp, err + } + + return metrics, resp, nil +} + +// GetOrganizationTeamMetrics gets Copilot usage metrics for an organization team. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-metrics#get-copilot-metrics-for-a-team +// +//meta:operation GET /orgs/{org}/team/{team_slug}/copilot/metrics +func (s *CopilotService) GetOrganizationTeamMetrics(ctx context.Context, org, team string, opts *CopilotMetricsListOptions) ([]*CopilotMetrics, *Response, error) { + u := fmt.Sprintf("orgs/%v/team/%v/copilot/metrics", org, team) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var metrics []*CopilotMetrics + resp, err := s.client.Do(ctx, req, &metrics) + if err != nil { + return nil, resp, err + } + + return metrics, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/dependabot.go b/vendor/github.com/google/go-github/v68/github/dependabot.go new file mode 100644 index 0000000000..2a11a9c956 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/dependabot.go @@ -0,0 +1,12 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +// DependabotService handles communication with the Dependabot related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/ +type DependabotService service diff --git a/vendor/github.com/google/go-github/v68/github/dependabot_alerts.go b/vendor/github.com/google/go-github/v68/github/dependabot_alerts.go new file mode 100644 index 0000000000..c274f07bec --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/dependabot_alerts.go @@ -0,0 +1,176 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Dependency represents the vulnerable dependency. +type Dependency struct { + Package *VulnerabilityPackage `json:"package,omitempty"` + ManifestPath *string `json:"manifest_path,omitempty"` + Scope *string `json:"scope,omitempty"` +} + +// AdvisoryCVSS represents the advisory pertaining to the Common Vulnerability Scoring System. +type AdvisoryCVSS struct { + Score *float64 `json:"score,omitempty"` + VectorString *string `json:"vector_string,omitempty"` +} + +// AdvisoryCWEs represent the advisory pertaining to Common Weakness Enumeration. +type AdvisoryCWEs struct { + CWEID *string `json:"cwe_id,omitempty"` + Name *string `json:"name,omitempty"` +} + +// DependabotSecurityAdvisory represents the GitHub Security Advisory. +type DependabotSecurityAdvisory struct { + GHSAID *string `json:"ghsa_id,omitempty"` + CVEID *string `json:"cve_id,omitempty"` + Summary *string `json:"summary,omitempty"` + Description *string `json:"description,omitempty"` + Vulnerabilities []*AdvisoryVulnerability `json:"vulnerabilities,omitempty"` + Severity *string `json:"severity,omitempty"` + CVSS *AdvisoryCVSS `json:"cvss,omitempty"` + CWEs []*AdvisoryCWEs `json:"cwes,omitempty"` + Identifiers []*AdvisoryIdentifier `json:"identifiers,omitempty"` + References []*AdvisoryReference `json:"references,omitempty"` + PublishedAt *Timestamp `json:"published_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + WithdrawnAt *Timestamp `json:"withdrawn_at,omitempty"` +} + +// DependabotAlert represents a Dependabot alert. +type DependabotAlert struct { + Number *int `json:"number,omitempty"` + State *string `json:"state,omitempty"` + Dependency *Dependency `json:"dependency,omitempty"` + SecurityAdvisory *DependabotSecurityAdvisory `json:"security_advisory,omitempty"` + SecurityVulnerability *AdvisoryVulnerability `json:"security_vulnerability,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + DismissedAt *Timestamp `json:"dismissed_at,omitempty"` + DismissedBy *User `json:"dismissed_by,omitempty"` + DismissedReason *string `json:"dismissed_reason,omitempty"` + DismissedComment *string `json:"dismissed_comment,omitempty"` + FixedAt *Timestamp `json:"fixed_at,omitempty"` + AutoDismissedAt *Timestamp `json:"auto_dismissed_at,omitempty"` + // The repository is always empty for events + Repository *Repository `json:"repository,omitempty"` +} + +// DependabotAlertState represents the state of a Dependabot alert to update. +type DependabotAlertState struct { + // The state of the Dependabot alert. A dismissed_reason must be provided when setting the state to dismissed. + State string `json:"state"` + // Required when state is dismissed. A reason for dismissing the alert. + // Can be one of: fix_started, inaccurate, no_bandwidth, not_used, tolerable_risk + DismissedReason *string `json:"dismissed_reason,omitempty"` + // An optional comment associated with dismissing the alert. + DismissedComment *string `json:"dismissed_comment,omitempty"` +} + +// ListAlertsOptions specifies the optional parameters to the DependabotService.ListRepoAlerts +// and DependabotService.ListOrgAlerts methods. +type ListAlertsOptions struct { + State *string `url:"state,omitempty"` + Severity *string `url:"severity,omitempty"` + Ecosystem *string `url:"ecosystem,omitempty"` + Package *string `url:"package,omitempty"` + Scope *string `url:"scope,omitempty"` + Sort *string `url:"sort,omitempty"` + Direction *string `url:"direction,omitempty"` + + ListOptions + ListCursorOptions +} + +func (s *DependabotService) listAlerts(ctx context.Context, url string, opts *ListAlertsOptions) ([]*DependabotAlert, *Response, error) { + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var alerts []*DependabotAlert + resp, err := s.client.Do(ctx, req, &alerts) + if err != nil { + return nil, resp, err + } + + return alerts, resp, nil +} + +// ListRepoAlerts lists all Dependabot alerts of a repository. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/alerts#list-dependabot-alerts-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/dependabot/alerts +func (s *DependabotService) ListRepoAlerts(ctx context.Context, owner, repo string, opts *ListAlertsOptions) ([]*DependabotAlert, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependabot/alerts", owner, repo) + return s.listAlerts(ctx, url, opts) +} + +// ListOrgAlerts lists all Dependabot alerts of an organization. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/alerts#list-dependabot-alerts-for-an-organization +// +//meta:operation GET /orgs/{org}/dependabot/alerts +func (s *DependabotService) ListOrgAlerts(ctx context.Context, org string, opts *ListAlertsOptions) ([]*DependabotAlert, *Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/alerts", org) + return s.listAlerts(ctx, url, opts) +} + +// GetRepoAlert gets a single repository Dependabot alert. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/alerts#get-a-dependabot-alert +// +//meta:operation GET /repos/{owner}/{repo}/dependabot/alerts/{alert_number} +func (s *DependabotService) GetRepoAlert(ctx context.Context, owner, repo string, number int) (*DependabotAlert, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependabot/alerts/%v", owner, repo, number) + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + alert := new(DependabotAlert) + resp, err := s.client.Do(ctx, req, alert) + if err != nil { + return nil, resp, err + } + + return alert, resp, nil +} + +// UpdateAlert updates a Dependabot alert. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/alerts#update-a-dependabot-alert +// +//meta:operation PATCH /repos/{owner}/{repo}/dependabot/alerts/{alert_number} +func (s *DependabotService) UpdateAlert(ctx context.Context, owner, repo string, number int, stateInfo *DependabotAlertState) (*DependabotAlert, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependabot/alerts/%v", owner, repo, number) + req, err := s.client.NewRequest("PATCH", url, stateInfo) + if err != nil { + return nil, nil, err + } + + alert := new(DependabotAlert) + resp, err := s.client.Do(ctx, req, alert) + if err != nil { + return nil, resp, err + } + + return alert, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/dependabot_secrets.go b/vendor/github.com/google/go-github/v68/github/dependabot_secrets.go new file mode 100644 index 0000000000..e85c805a63 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/dependabot_secrets.go @@ -0,0 +1,289 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +func (s *DependabotService) getPublicKey(ctx context.Context, url string) (*PublicKey, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + pubKey := new(PublicKey) + resp, err := s.client.Do(ctx, req, pubKey) + if err != nil { + return nil, resp, err + } + + return pubKey, resp, nil +} + +// GetRepoPublicKey gets a public key that should be used for Dependabot secret encryption. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#get-a-repository-public-key +// +//meta:operation GET /repos/{owner}/{repo}/dependabot/secrets/public-key +func (s *DependabotService) GetRepoPublicKey(ctx context.Context, owner, repo string) (*PublicKey, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependabot/secrets/public-key", owner, repo) + return s.getPublicKey(ctx, url) +} + +// GetOrgPublicKey gets a public key that should be used for Dependabot secret encryption. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#get-an-organization-public-key +// +//meta:operation GET /orgs/{org}/dependabot/secrets/public-key +func (s *DependabotService) GetOrgPublicKey(ctx context.Context, org string) (*PublicKey, *Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets/public-key", org) + return s.getPublicKey(ctx, url) +} + +func (s *DependabotService) listSecrets(ctx context.Context, url string, opts *ListOptions) (*Secrets, *Response, error) { + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + secrets := new(Secrets) + resp, err := s.client.Do(ctx, req, &secrets) + if err != nil { + return nil, resp, err + } + + return secrets, resp, nil +} + +// ListRepoSecrets lists all Dependabot secrets available in a repository +// without revealing their encrypted values. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#list-repository-secrets +// +//meta:operation GET /repos/{owner}/{repo}/dependabot/secrets +func (s *DependabotService) ListRepoSecrets(ctx context.Context, owner, repo string, opts *ListOptions) (*Secrets, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependabot/secrets", owner, repo) + return s.listSecrets(ctx, url, opts) +} + +// ListOrgSecrets lists all Dependabot secrets available in an organization +// without revealing their encrypted values. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#list-organization-secrets +// +//meta:operation GET /orgs/{org}/dependabot/secrets +func (s *DependabotService) ListOrgSecrets(ctx context.Context, org string, opts *ListOptions) (*Secrets, *Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets", org) + return s.listSecrets(ctx, url, opts) +} + +func (s *DependabotService) getSecret(ctx context.Context, url string) (*Secret, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + secret := new(Secret) + resp, err := s.client.Do(ctx, req, secret) + if err != nil { + return nil, resp, err + } + + return secret, resp, nil +} + +// GetRepoSecret gets a single repository Dependabot secret without revealing its encrypted value. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#get-a-repository-secret +// +//meta:operation GET /repos/{owner}/{repo}/dependabot/secrets/{secret_name} +func (s *DependabotService) GetRepoSecret(ctx context.Context, owner, repo, name string) (*Secret, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependabot/secrets/%v", owner, repo, name) + return s.getSecret(ctx, url) +} + +// GetOrgSecret gets a single organization Dependabot secret without revealing its encrypted value. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#get-an-organization-secret +// +//meta:operation GET /orgs/{org}/dependabot/secrets/{secret_name} +func (s *DependabotService) GetOrgSecret(ctx context.Context, org, name string) (*Secret, *Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets/%v", org, name) + return s.getSecret(ctx, url) +} + +// DependabotEncryptedSecret represents a secret that is encrypted using a public key for Dependabot. +// +// The value of EncryptedValue must be your secret, encrypted with +// LibSodium (see documentation here: https://libsodium.gitbook.io/doc/bindings_for_other_languages) +// using the public key retrieved using the GetPublicKey method. +type DependabotEncryptedSecret struct { + Name string `json:"-"` + KeyID string `json:"key_id"` + EncryptedValue string `json:"encrypted_value"` + Visibility string `json:"visibility,omitempty"` + SelectedRepositoryIDs DependabotSecretsSelectedRepoIDs `json:"selected_repository_ids,omitempty"` +} + +func (s *DependabotService) putSecret(ctx context.Context, url string, eSecret *DependabotEncryptedSecret) (*Response, error) { + req, err := s.client.NewRequest("PUT", url, eSecret) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// CreateOrUpdateRepoSecret creates or updates a repository Dependabot secret with an encrypted value. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#create-or-update-a-repository-secret +// +//meta:operation PUT /repos/{owner}/{repo}/dependabot/secrets/{secret_name} +func (s *DependabotService) CreateOrUpdateRepoSecret(ctx context.Context, owner, repo string, eSecret *DependabotEncryptedSecret) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependabot/secrets/%v", owner, repo, eSecret.Name) + return s.putSecret(ctx, url, eSecret) +} + +// CreateOrUpdateOrgSecret creates or updates an organization Dependabot secret with an encrypted value. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#create-or-update-an-organization-secret +// +//meta:operation PUT /orgs/{org}/dependabot/secrets/{secret_name} +func (s *DependabotService) CreateOrUpdateOrgSecret(ctx context.Context, org string, eSecret *DependabotEncryptedSecret) (*Response, error) { + repoIDs := make([]string, len(eSecret.SelectedRepositoryIDs)) + for i, secret := range eSecret.SelectedRepositoryIDs { + repoIDs[i] = fmt.Sprintf("%v", secret) + } + params := struct { + *DependabotEncryptedSecret + SelectedRepositoryIDs []string `json:"selected_repository_ids,omitempty"` + }{ + DependabotEncryptedSecret: eSecret, + SelectedRepositoryIDs: repoIDs, + } + + url := fmt.Sprintf("orgs/%v/dependabot/secrets/%v", org, eSecret.Name) + req, err := s.client.NewRequest("PUT", url, params) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +func (s *DependabotService) deleteSecret(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteRepoSecret deletes a Dependabot secret in a repository using the secret name. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#delete-a-repository-secret +// +//meta:operation DELETE /repos/{owner}/{repo}/dependabot/secrets/{secret_name} +func (s *DependabotService) DeleteRepoSecret(ctx context.Context, owner, repo, name string) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependabot/secrets/%v", owner, repo, name) + return s.deleteSecret(ctx, url) +} + +// DeleteOrgSecret deletes a Dependabot secret in an organization using the secret name. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#delete-an-organization-secret +// +//meta:operation DELETE /orgs/{org}/dependabot/secrets/{secret_name} +func (s *DependabotService) DeleteOrgSecret(ctx context.Context, org, name string) (*Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets/%v", org, name) + return s.deleteSecret(ctx, url) +} + +// ListSelectedReposForOrgSecret lists all repositories that have access to a Dependabot secret. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#list-selected-repositories-for-an-organization-secret +// +//meta:operation GET /orgs/{org}/dependabot/secrets/{secret_name}/repositories +func (s *DependabotService) ListSelectedReposForOrgSecret(ctx context.Context, org, name string, opts *ListOptions) (*SelectedReposList, *Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets/%v/repositories", org, name) + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + result := new(SelectedReposList) + resp, err := s.client.Do(ctx, req, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// DependabotSecretsSelectedRepoIDs are the repository IDs that have access to the dependabot secrets. +type DependabotSecretsSelectedRepoIDs []int64 + +// SetSelectedReposForOrgSecret sets the repositories that have access to a Dependabot secret. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#set-selected-repositories-for-an-organization-secret +// +//meta:operation PUT /orgs/{org}/dependabot/secrets/{secret_name}/repositories +func (s *DependabotService) SetSelectedReposForOrgSecret(ctx context.Context, org, name string, ids DependabotSecretsSelectedRepoIDs) (*Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets/%v/repositories", org, name) + type repoIDs struct { + SelectedIDs DependabotSecretsSelectedRepoIDs `json:"selected_repository_ids"` + } + + req, err := s.client.NewRequest("PUT", url, repoIDs{SelectedIDs: ids}) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddSelectedRepoToOrgSecret adds a repository to an organization Dependabot secret. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#add-selected-repository-to-an-organization-secret +// +//meta:operation PUT /orgs/{org}/dependabot/secrets/{secret_name}/repositories/{repository_id} +func (s *DependabotService) AddSelectedRepoToOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets/%v/repositories/%v", org, name, *repo.ID) + req, err := s.client.NewRequest("PUT", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveSelectedRepoFromOrgSecret removes a repository from an organization Dependabot secret. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#remove-selected-repository-from-an-organization-secret +// +//meta:operation DELETE /orgs/{org}/dependabot/secrets/{secret_name}/repositories/{repository_id} +func (s *DependabotService) RemoveSelectedRepoFromOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets/%v/repositories/%v", org, name, *repo.ID) + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/dependency_graph.go b/vendor/github.com/google/go-github/v68/github/dependency_graph.go new file mode 100644 index 0000000000..86a1fe48b9 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/dependency_graph.go @@ -0,0 +1,82 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +type DependencyGraphService service + +// SBOM represents a software bill of materials, which describes the +// packages/libraries that a repository depends on. +type SBOM struct { + SBOM *SBOMInfo `json:"sbom,omitempty"` +} + +// CreationInfo represents when the SBOM was created and who created it. +type CreationInfo struct { + Created *Timestamp `json:"created,omitempty"` + Creators []string `json:"creators,omitempty"` +} + +// RepoDependencies represents the dependencies of a repo. +type RepoDependencies struct { + SPDXID *string `json:"SPDXID,omitempty"` + // Package name + Name *string `json:"name,omitempty"` + VersionInfo *string `json:"versionInfo,omitempty"` + DownloadLocation *string `json:"downloadLocation,omitempty"` + FilesAnalyzed *bool `json:"filesAnalyzed,omitempty"` + LicenseConcluded *string `json:"licenseConcluded,omitempty"` + LicenseDeclared *string `json:"licenseDeclared,omitempty"` +} + +// SBOMInfo represents a software bill of materials (SBOM) using SPDX. +// SPDX is an open standard for SBOMs that +// identifies and catalogs components, licenses, copyrights, security +// references, and other metadata relating to software. +type SBOMInfo struct { + SPDXID *string `json:"SPDXID,omitempty"` + SPDXVersion *string `json:"spdxVersion,omitempty"` + CreationInfo *CreationInfo `json:"creationInfo,omitempty"` + + // Repo name + Name *string `json:"name,omitempty"` + DataLicense *string `json:"dataLicense,omitempty"` + DocumentDescribes []string `json:"documentDescribes,omitempty"` + DocumentNamespace *string `json:"documentNamespace,omitempty"` + + // List of packages dependencies + Packages []*RepoDependencies `json:"packages,omitempty"` +} + +func (s SBOM) String() string { + return Stringify(s) +} + +// GetSBOM fetches the software bill of materials for a repository. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/sboms#export-a-software-bill-of-materials-sbom-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/dependency-graph/sbom +func (s *DependencyGraphService) GetSBOM(ctx context.Context, owner, repo string) (*SBOM, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/dependency-graph/sbom", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var sbom *SBOM + resp, err := s.client.Do(ctx, req, &sbom) + if err != nil { + return nil, resp, err + } + + return sbom, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/dependency_graph_snapshots.go b/vendor/github.com/google/go-github/v68/github/dependency_graph_snapshots.go new file mode 100644 index 0000000000..0606b98151 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/dependency_graph_snapshots.go @@ -0,0 +1,113 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// DependencyGraphSnapshotResolvedDependency represents a resolved dependency in a dependency graph snapshot. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +type DependencyGraphSnapshotResolvedDependency struct { + PackageURL *string `json:"package_url,omitempty"` + // Represents whether the dependency is requested directly by the manifest or is a dependency of another dependency. + // Can have the following values: + // - "direct": indicates that the dependency is requested directly by the manifest. + // - "indirect": indicates that the dependency is a dependency of another dependency. + Relationship *string `json:"relationship,omitempty"` + // Represents whether the dependency is required for the primary build artifact or is only used for development. + // Can have the following values: + // - "runtime": indicates that the dependency is required for the primary build artifact. + // - "development": indicates that the dependency is only used for development. + Scope *string `json:"scope,omitempty"` + Dependencies []string `json:"dependencies,omitempty"` +} + +// DependencyGraphSnapshotJob represents the job that created the snapshot. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +type DependencyGraphSnapshotJob struct { + Correlator *string `json:"correlator,omitempty"` + ID *string `json:"id,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` +} + +// DependencyGraphSnapshotDetector represents a description of the detector used. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +type DependencyGraphSnapshotDetector struct { + Name *string `json:"name,omitempty"` + Version *string `json:"version,omitempty"` + URL *string `json:"url,omitempty"` +} + +// DependencyGraphSnapshotManifestFile represents the file declaring the repository's dependencies. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +type DependencyGraphSnapshotManifestFile struct { + SourceLocation *string `json:"source_location,omitempty"` +} + +// DependencyGraphSnapshotManifest represents a collection of related dependencies declared in a file or representing a logical group of dependencies. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +type DependencyGraphSnapshotManifest struct { + Name *string `json:"name,omitempty"` + File *DependencyGraphSnapshotManifestFile `json:"file,omitempty"` + Resolved map[string]*DependencyGraphSnapshotResolvedDependency `json:"resolved,omitempty"` +} + +// DependencyGraphSnapshot represent a snapshot of a repository's dependencies. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +type DependencyGraphSnapshot struct { + Version int `json:"version"` + Sha *string `json:"sha,omitempty"` + Ref *string `json:"ref,omitempty"` + Job *DependencyGraphSnapshotJob `json:"job,omitempty"` + Detector *DependencyGraphSnapshotDetector `json:"detector,omitempty"` + Scanned *Timestamp `json:"scanned,omitempty"` + Manifests map[string]*DependencyGraphSnapshotManifest `json:"manifests,omitempty"` +} + +// DependencyGraphSnapshotCreationData represents the dependency snapshot's creation result. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +type DependencyGraphSnapshotCreationData struct { + ID int64 `json:"id"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + Message *string `json:"message,omitempty"` + // Represents the snapshot creation result. + // Can have the following values: + // - "SUCCESS": indicates that the snapshot was successfully created and the repository's dependencies were updated. + // - "ACCEPTED": indicates that the snapshot was successfully created, but the repository's dependencies were not updated. + // - "INVALID": indicates that the snapshot was malformed. + Result *string `json:"result,omitempty"` +} + +// CreateSnapshot creates a new snapshot of a repository's dependencies. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +// +//meta:operation POST /repos/{owner}/{repo}/dependency-graph/snapshots +func (s *DependencyGraphService) CreateSnapshot(ctx context.Context, owner, repo string, dependencyGraphSnapshot *DependencyGraphSnapshot) (*DependencyGraphSnapshotCreationData, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependency-graph/snapshots", owner, repo) + + req, err := s.client.NewRequest("POST", url, dependencyGraphSnapshot) + if err != nil { + return nil, nil, err + } + + var snapshotCreationData *DependencyGraphSnapshotCreationData + resp, err := s.client.Do(ctx, req, &snapshotCreationData) + if err != nil { + return nil, resp, err + } + + return snapshotCreationData, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/doc.go b/vendor/github.com/google/go-github/v68/github/doc.go new file mode 100644 index 0000000000..4a0f163a0b --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/doc.go @@ -0,0 +1,194 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package github provides a client for using the GitHub API. + +Usage: + + import "github.com/google/go-github/v68/github" // with go modules enabled (GO111MODULE=on or outside GOPATH) + import "github.com/google/go-github/github" // with go modules disabled + +Construct a new GitHub client, then use the various services on the client to +access different parts of the GitHub API. For example: + + client := github.NewClient(nil) + + // list all organizations for user "willnorris" + orgs, _, err := client.Organizations.List(ctx, "willnorris", nil) + +Some API methods have optional parameters that can be passed. For example: + + client := github.NewClient(nil) + + // list public repositories for org "github" + opt := &github.RepositoryListByOrgOptions{Type: "public"} + repos, _, err := client.Repositories.ListByOrg(ctx, "github", opt) + +The services of a client divide the API into logical chunks and correspond to +the structure of the GitHub API documentation at +https://docs.github.com/rest . + +NOTE: Using the https://pkg.go.dev/context package, one can easily +pass cancelation signals and deadlines to various services of the client for +handling a request. In case there is no context available, then context.Background() +can be used as a starting point. + +For more sample code snippets, head over to the https://github.com/google/go-github/tree/master/example directory. + +# Authentication + +Use Client.WithAuthToken to configure your client to authenticate using an Oauth token +(for example, a personal access token). This is what is needed for a majority of use cases +aside from GitHub Apps. + + client := github.NewClient(nil).WithAuthToken("... your access token ...") + +Note that when using an authenticated Client, all calls made by the client will +include the specified OAuth token. Therefore, authenticated clients should +almost never be shared between different users. + +For API methods that require HTTP Basic Authentication, use the +BasicAuthTransport. + +GitHub Apps authentication can be provided by the +https://github.com/bradleyfalzon/ghinstallation package. +It supports both authentication as an installation, using an installation access token, +and as an app, using a JWT. + +To authenticate as an installation: + + import "github.com/bradleyfalzon/ghinstallation" + + func main() { + // Wrap the shared transport for use with the integration ID 1 authenticating with installation ID 99. + itr, err := ghinstallation.NewKeyFromFile(http.DefaultTransport, 1, 99, "2016-10-19.private-key.pem") + if err != nil { + // Handle error. + } + + // Use installation transport with client + client := github.NewClient(&http.Client{Transport: itr}) + + // Use client... + } + +To authenticate as an app, using a JWT: + + import "github.com/bradleyfalzon/ghinstallation" + + func main() { + // Wrap the shared transport for use with the application ID 1. + atr, err := ghinstallation.NewAppsTransportKeyFromFile(http.DefaultTransport, 1, "2016-10-19.private-key.pem") + if err != nil { + // Handle error. + } + + // Use app transport with client + client := github.NewClient(&http.Client{Transport: atr}) + + // Use client... + } + +# Rate Limiting + +GitHub imposes a rate limit on all API clients. Unauthenticated clients are +limited to 60 requests per hour, while authenticated clients can make up to +5,000 requests per hour. The Search API has a custom rate limit. Unauthenticated +clients are limited to 10 requests per minute, while authenticated clients +can make up to 30 requests per minute. To receive the higher rate limit when +making calls that are not issued on behalf of a user, +use UnauthenticatedRateLimitedTransport. + +The returned Response.Rate value contains the rate limit information +from the most recent API call. If a recent enough response isn't +available, you can use RateLimits to fetch the most up-to-date rate +limit data for the client. + +To detect an API rate limit error, you can check if its type is *github.RateLimitError. +For secondary rate limits, you can check if its type is *github.AbuseRateLimitError: + + repos, _, err := client.Repositories.List(ctx, "", nil) + if _, ok := err.(*github.RateLimitError); ok { + log.Println("hit rate limit") + } + if _, ok := err.(*github.AbuseRateLimitError); ok { + log.Println("hit secondary rate limit") + } + +Learn more about GitHub rate limiting at +https://docs.github.com/rest/rate-limit . + +# Accepted Status + +Some endpoints may return a 202 Accepted status code, meaning that the +information required is not yet ready and was scheduled to be gathered on +the GitHub side. Methods known to behave like this are documented specifying +this behavior. + +To detect this condition of error, you can check if its type is +*github.AcceptedError: + + stats, _, err := client.Repositories.ListContributorsStats(ctx, org, repo) + if _, ok := err.(*github.AcceptedError); ok { + log.Println("scheduled on GitHub side") + } + +# Conditional Requests + +The GitHub API has good support for conditional requests which will help +prevent you from burning through your rate limit, as well as help speed up your +application. go-github does not handle conditional requests directly, but is +instead designed to work with a caching http.Transport. We recommend using +https://github.com/gregjones/httpcache for that. + +Learn more about GitHub conditional requests at +https://docs.github.com/rest/overview/resources-in-the-rest-api#conditional-requests. + +# Creating and Updating Resources + +All structs for GitHub resources use pointer values for all non-repeated fields. +This allows distinguishing between unset fields and those set to a zero-value. +Helper functions have been provided to easily create these pointers for string, +bool, and int values. For example: + + // create a new private repository named "foo" + repo := &github.Repository{ + Name: github.Ptr("foo"), + Private: github.Ptr(true), + } + client.Repositories.Create(ctx, "", repo) + +Users who have worked with protocol buffers should find this pattern familiar. + +# Pagination + +All requests for resource collections (repos, pull requests, issues, etc.) +support pagination. Pagination options are described in the +github.ListOptions struct and passed to the list methods directly or as an +embedded type of a more specific list options struct (for example +github.PullRequestListOptions). Pages information is available via the +github.Response struct. + + client := github.NewClient(nil) + + opt := &github.RepositoryListByOrgOptions{ + ListOptions: github.ListOptions{PerPage: 10}, + } + // get all pages of results + var allRepos []*github.Repository + for { + repos, resp, err := client.Repositories.ListByOrg(ctx, "github", opt) + if err != nil { + return err + } + allRepos = append(allRepos, repos...) + if resp.NextPage == 0 { + break + } + opt.Page = resp.NextPage + } +*/ +package github diff --git a/vendor/github.com/google/go-github/v68/github/emojis.go b/vendor/github.com/google/go-github/v68/github/emojis.go new file mode 100644 index 0000000000..b7a03dd98c --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/emojis.go @@ -0,0 +1,40 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" +) + +// EmojisService provides access to emoji-related functions in the GitHub API. +type EmojisService service + +// List returns the emojis available to use on GitHub. +// +// GitHub API docs: https://docs.github.com/rest/emojis/emojis#get-emojis +// +//meta:operation GET /emojis +func (s *EmojisService) List(ctx context.Context) (map[string]string, *Response, error) { + req, err := s.client.NewRequest("GET", "emojis", nil) + if err != nil { + return nil, nil, err + } + + var emoji map[string]string + resp, err := s.client.Do(ctx, req, &emoji) + if err != nil { + return nil, resp, err + } + + return emoji, resp, nil +} + +// ListEmojis returns the emojis available to use on GitHub. +// +// Deprecated: Use EmojisService.List instead. +func (c *Client) ListEmojis(ctx context.Context) (map[string]string, *Response, error) { + return c.Emojis.List(ctx) +} diff --git a/vendor/github.com/google/go-github/v68/github/enterprise.go b/vendor/github.com/google/go-github/v68/github/enterprise.go new file mode 100644 index 0000000000..2036f8bc75 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/enterprise.go @@ -0,0 +1,12 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +// EnterpriseService provides access to the enterprise related functions +// in the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/enterprise-admin/ +type EnterpriseService service diff --git a/vendor/github.com/google/go-github/v68/github/enterprise_actions_runner_groups.go b/vendor/github.com/google/go-github/v68/github/enterprise_actions_runner_groups.go new file mode 100644 index 0000000000..f171df7573 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/enterprise_actions_runner_groups.go @@ -0,0 +1,336 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListOrganizations represents the response from the list orgs endpoints. +type ListOrganizations struct { + TotalCount *int `json:"total_count,omitempty"` + Organizations []*Organization `json:"organizations"` +} + +// EnterpriseRunnerGroup represents a self-hosted runner group configured in an enterprise. +type EnterpriseRunnerGroup struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Visibility *string `json:"visibility,omitempty"` + Default *bool `json:"default,omitempty"` + SelectedOrganizationsURL *string `json:"selected_organizations_url,omitempty"` + RunnersURL *string `json:"runners_url,omitempty"` + Inherited *bool `json:"inherited,omitempty"` + AllowsPublicRepositories *bool `json:"allows_public_repositories,omitempty"` + RestrictedToWorkflows *bool `json:"restricted_to_workflows,omitempty"` + SelectedWorkflows []string `json:"selected_workflows,omitempty"` + WorkflowRestrictionsReadOnly *bool `json:"workflow_restrictions_read_only,omitempty"` +} + +// EnterpriseRunnerGroups represents a collection of self-hosted runner groups configured for an enterprise. +type EnterpriseRunnerGroups struct { + TotalCount *int `json:"total_count,omitempty"` + RunnerGroups []*EnterpriseRunnerGroup `json:"runner_groups"` +} + +// CreateEnterpriseRunnerGroupRequest represents a request to create a Runner group for an enterprise. +type CreateEnterpriseRunnerGroupRequest struct { + Name *string `json:"name,omitempty"` + Visibility *string `json:"visibility,omitempty"` + // List of organization IDs that can access the runner group. + SelectedOrganizationIDs []int64 `json:"selected_organization_ids,omitempty"` + // Runners represent a list of runner IDs to add to the runner group. + Runners []int64 `json:"runners,omitempty"` + // If set to True, public repos can use this runner group + AllowsPublicRepositories *bool `json:"allows_public_repositories,omitempty"` + // If true, the runner group will be restricted to running only the workflows specified in the SelectedWorkflows slice. + RestrictedToWorkflows *bool `json:"restricted_to_workflows,omitempty"` + // List of workflows the runner group should be allowed to run. This setting will be ignored unless RestrictedToWorkflows is set to true. + SelectedWorkflows []string `json:"selected_workflows,omitempty"` +} + +// UpdateEnterpriseRunnerGroupRequest represents a request to update a Runner group for an enterprise. +type UpdateEnterpriseRunnerGroupRequest struct { + Name *string `json:"name,omitempty"` + Visibility *string `json:"visibility,omitempty"` + AllowsPublicRepositories *bool `json:"allows_public_repositories,omitempty"` + RestrictedToWorkflows *bool `json:"restricted_to_workflows,omitempty"` + SelectedWorkflows []string `json:"selected_workflows,omitempty"` +} + +// SetOrgAccessRunnerGroupRequest represents a request to replace the list of organizations +// that can access a self-hosted runner group configured in an enterprise. +type SetOrgAccessRunnerGroupRequest struct { + // Updated list of organization IDs that should be given access to the runner group. + SelectedOrganizationIDs []int64 `json:"selected_organization_ids"` +} + +// ListEnterpriseRunnerGroupOptions extend ListOptions to have the optional parameters VisibleToOrganization. +type ListEnterpriseRunnerGroupOptions struct { + ListOptions + + // Only return runner groups that are allowed to be used by this organization. + VisibleToOrganization string `url:"visible_to_organization,omitempty"` +} + +// ListRunnerGroups lists all self-hosted runner groups configured in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#list-self-hosted-runner-groups-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/runner-groups +func (s *EnterpriseService) ListRunnerGroups(ctx context.Context, enterprise string, opts *ListEnterpriseRunnerGroupOptions) (*EnterpriseRunnerGroups, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups", enterprise) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + groups := &EnterpriseRunnerGroups{} + resp, err := s.client.Do(ctx, req, &groups) + if err != nil { + return nil, resp, err + } + + return groups, resp, nil +} + +// GetEnterpriseRunnerGroup gets a specific self-hosted runner group for an enterprise using its RunnerGroup ID. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#get-a-self-hosted-runner-group-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/runner-groups/{runner_group_id} +func (s *EnterpriseService) GetEnterpriseRunnerGroup(ctx context.Context, enterprise string, groupID int64) (*EnterpriseRunnerGroup, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups/%v", enterprise, groupID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runnerGroup := new(EnterpriseRunnerGroup) + resp, err := s.client.Do(ctx, req, runnerGroup) + if err != nil { + return nil, resp, err + } + + return runnerGroup, resp, nil +} + +// DeleteEnterpriseRunnerGroup deletes a self-hosted runner group from an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#delete-a-self-hosted-runner-group-from-an-enterprise +// +//meta:operation DELETE /enterprises/{enterprise}/actions/runner-groups/{runner_group_id} +func (s *EnterpriseService) DeleteEnterpriseRunnerGroup(ctx context.Context, enterprise string, groupID int64) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups/%v", enterprise, groupID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// CreateEnterpriseRunnerGroup creates a new self-hosted runner group for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#create-a-self-hosted-runner-group-for-an-enterprise +// +//meta:operation POST /enterprises/{enterprise}/actions/runner-groups +func (s *EnterpriseService) CreateEnterpriseRunnerGroup(ctx context.Context, enterprise string, createReq CreateEnterpriseRunnerGroupRequest) (*EnterpriseRunnerGroup, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups", enterprise) + req, err := s.client.NewRequest("POST", u, createReq) + if err != nil { + return nil, nil, err + } + + runnerGroup := new(EnterpriseRunnerGroup) + resp, err := s.client.Do(ctx, req, runnerGroup) + if err != nil { + return nil, resp, err + } + + return runnerGroup, resp, nil +} + +// UpdateEnterpriseRunnerGroup updates a self-hosted runner group for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#update-a-self-hosted-runner-group-for-an-enterprise +// +//meta:operation PATCH /enterprises/{enterprise}/actions/runner-groups/{runner_group_id} +func (s *EnterpriseService) UpdateEnterpriseRunnerGroup(ctx context.Context, enterprise string, groupID int64, updateReq UpdateEnterpriseRunnerGroupRequest) (*EnterpriseRunnerGroup, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups/%v", enterprise, groupID) + req, err := s.client.NewRequest("PATCH", u, updateReq) + if err != nil { + return nil, nil, err + } + + runnerGroup := new(EnterpriseRunnerGroup) + resp, err := s.client.Do(ctx, req, runnerGroup) + if err != nil { + return nil, resp, err + } + + return runnerGroup, resp, nil +} + +// ListOrganizationAccessRunnerGroup lists the organizations with access to a self-hosted runner group configured in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#list-organization-access-to-a-self-hosted-runner-group-in-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/organizations +func (s *EnterpriseService) ListOrganizationAccessRunnerGroup(ctx context.Context, enterprise string, groupID int64, opts *ListOptions) (*ListOrganizations, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups/%v/organizations", enterprise, groupID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + orgs := &ListOrganizations{} + resp, err := s.client.Do(ctx, req, &orgs) + if err != nil { + return nil, resp, err + } + + return orgs, resp, nil +} + +// SetOrganizationAccessRunnerGroup replaces the list of organizations that have access to a self-hosted runner group configured in an enterprise +// with a new List of organizations. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#set-organization-access-for-a-self-hosted-runner-group-in-an-enterprise +// +//meta:operation PUT /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/organizations +func (s *EnterpriseService) SetOrganizationAccessRunnerGroup(ctx context.Context, enterprise string, groupID int64, ids SetOrgAccessRunnerGroupRequest) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups/%v/organizations", enterprise, groupID) + + req, err := s.client.NewRequest("PUT", u, ids) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddOrganizationAccessRunnerGroup adds an organization to the list of selected organizations that can access a self-hosted runner group. +// The runner group must have visibility set to 'selected'. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#add-organization-access-to-a-self-hosted-runner-group-in-an-enterprise +// +//meta:operation PUT /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/organizations/{org_id} +func (s *EnterpriseService) AddOrganizationAccessRunnerGroup(ctx context.Context, enterprise string, groupID, orgID int64) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups/%v/organizations/%v", enterprise, groupID, orgID) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveOrganizationAccessRunnerGroup removes an organization from the list of selected organizations that can access a self-hosted runner group. +// The runner group must have visibility set to 'selected'. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#remove-organization-access-to-a-self-hosted-runner-group-in-an-enterprise +// +//meta:operation DELETE /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/organizations/{org_id} +func (s *EnterpriseService) RemoveOrganizationAccessRunnerGroup(ctx context.Context, enterprise string, groupID, orgID int64) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups/%v/organizations/%v", enterprise, groupID, orgID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListRunnerGroupRunners lists self-hosted runners that are in a specific enterprise group. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#list-self-hosted-runners-in-a-group-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/runners +func (s *EnterpriseService) ListRunnerGroupRunners(ctx context.Context, enterprise string, groupID int64, opts *ListOptions) (*Runners, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups/%v/runners", enterprise, groupID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runners := &Runners{} + resp, err := s.client.Do(ctx, req, &runners) + if err != nil { + return nil, resp, err + } + + return runners, resp, nil +} + +// SetRunnerGroupRunners replaces the list of self-hosted runners that are part of an enterprise runner group +// with a new list of runners. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#set-self-hosted-runners-in-a-group-for-an-enterprise +// +//meta:operation PUT /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/runners +func (s *EnterpriseService) SetRunnerGroupRunners(ctx context.Context, enterprise string, groupID int64, ids SetRunnerGroupRunnersRequest) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups/%v/runners", enterprise, groupID) + + req, err := s.client.NewRequest("PUT", u, ids) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddRunnerGroupRunners adds a self-hosted runner to a runner group configured in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#add-a-self-hosted-runner-to-a-group-for-an-enterprise +// +//meta:operation PUT /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/runners/{runner_id} +func (s *EnterpriseService) AddRunnerGroupRunners(ctx context.Context, enterprise string, groupID, runnerID int64) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups/%v/runners/%v", enterprise, groupID, runnerID) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveRunnerGroupRunners removes a self-hosted runner from a group configured in an enterprise. +// The runner is then returned to the default group. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#remove-a-self-hosted-runner-from-a-group-for-an-enterprise +// +//meta:operation DELETE /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/runners/{runner_id} +func (s *EnterpriseService) RemoveRunnerGroupRunners(ctx context.Context, enterprise string, groupID, runnerID int64) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups/%v/runners/%v", enterprise, groupID, runnerID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/enterprise_actions_runners.go b/vendor/github.com/google/go-github/v68/github/enterprise_actions_runners.go new file mode 100644 index 0000000000..fa345aea8a --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/enterprise_actions_runners.go @@ -0,0 +1,139 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListRunnerApplicationDownloads lists self-hosted runner application binaries that can be downloaded and run. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runners#list-runner-applications-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/runners/downloads +func (s *EnterpriseService) ListRunnerApplicationDownloads(ctx context.Context, enterprise string) ([]*RunnerApplicationDownload, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runners/downloads", enterprise) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var rads []*RunnerApplicationDownload + resp, err := s.client.Do(ctx, req, &rads) + if err != nil { + return nil, resp, err + } + + return rads, resp, nil +} + +// GenerateEnterpriseJITConfig generates a just-in-time configuration for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runners#create-configuration-for-a-just-in-time-runner-for-an-enterprise +// +//meta:operation POST /enterprises/{enterprise}/actions/runners/generate-jitconfig +func (s *EnterpriseService) GenerateEnterpriseJITConfig(ctx context.Context, enterprise string, request *GenerateJITConfigRequest) (*JITRunnerConfig, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runners/generate-jitconfig", enterprise) + + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + jitConfig := new(JITRunnerConfig) + resp, err := s.client.Do(ctx, req, jitConfig) + if err != nil { + return nil, resp, err + } + + return jitConfig, resp, nil +} + +// CreateRegistrationToken creates a token that can be used to add a self-hosted runner. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runners#create-a-registration-token-for-an-enterprise +// +//meta:operation POST /enterprises/{enterprise}/actions/runners/registration-token +func (s *EnterpriseService) CreateRegistrationToken(ctx context.Context, enterprise string) (*RegistrationToken, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runners/registration-token", enterprise) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + registrationToken := new(RegistrationToken) + resp, err := s.client.Do(ctx, req, registrationToken) + if err != nil { + return nil, resp, err + } + + return registrationToken, resp, nil +} + +// ListRunners lists all the self-hosted runners for a enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runners#list-self-hosted-runners-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/runners +func (s *EnterpriseService) ListRunners(ctx context.Context, enterprise string, opts *ListRunnersOptions) (*Runners, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runners", enterprise) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runners := &Runners{} + resp, err := s.client.Do(ctx, req, &runners) + if err != nil { + return nil, resp, err + } + + return runners, resp, nil +} + +// GetRunner gets a specific self-hosted runner configured in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runners#get-a-self-hosted-runner-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/runners/{runner_id} +func (s *EnterpriseService) GetRunner(ctx context.Context, enterprise string, runnerID int64) (*Runner, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runners/%v", enterprise, runnerID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runner := new(Runner) + resp, err := s.client.Do(ctx, req, runner) + if err != nil { + return nil, resp, err + } + + return runner, resp, nil +} + +// RemoveRunner forces the removal of a self-hosted runner from an enterprise using the runner id. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runners#delete-a-self-hosted-runner-from-an-enterprise +// +//meta:operation DELETE /enterprises/{enterprise}/actions/runners/{runner_id} +func (s *EnterpriseService) RemoveRunner(ctx context.Context, enterprise string, runnerID int64) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runners/%v", enterprise, runnerID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/enterprise_audit_log.go b/vendor/github.com/google/go-github/v68/github/enterprise_audit_log.go new file mode 100644 index 0000000000..058a7d1778 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/enterprise_audit_log.go @@ -0,0 +1,37 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetAuditLog gets the audit-log entries for an organization. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/audit-log#get-the-audit-log-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/audit-log +func (s *EnterpriseService) GetAuditLog(ctx context.Context, enterprise string, opts *GetAuditLogOptions) ([]*AuditEntry, *Response, error) { + u := fmt.Sprintf("enterprises/%v/audit-log", enterprise) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var auditEntries []*AuditEntry + resp, err := s.client.Do(ctx, req, &auditEntries) + if err != nil { + return nil, resp, err + } + + return auditEntries, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/enterprise_code_security_and_analysis.go b/vendor/github.com/google/go-github/v68/github/enterprise_code_security_and_analysis.go new file mode 100644 index 0000000000..159aeae4dc --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/enterprise_code_security_and_analysis.go @@ -0,0 +1,85 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// EnterpriseSecurityAnalysisSettings represents security analysis settings for an enterprise. +type EnterpriseSecurityAnalysisSettings struct { + AdvancedSecurityEnabledForNewRepositories *bool `json:"advanced_security_enabled_for_new_repositories,omitempty"` + SecretScanningEnabledForNewRepositories *bool `json:"secret_scanning_enabled_for_new_repositories,omitempty"` + SecretScanningPushProtectionEnabledForNewRepositories *bool `json:"secret_scanning_push_protection_enabled_for_new_repositories,omitempty"` + SecretScanningPushProtectionCustomLink *string `json:"secret_scanning_push_protection_custom_link,omitempty"` + SecretScanningValidityChecksEnabled *bool `json:"secret_scanning_validity_checks_enabled,omitempty"` +} + +// GetCodeSecurityAndAnalysis gets code security and analysis features for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/code-security-and-analysis#get-code-security-and-analysis-features-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/code_security_and_analysis +func (s *EnterpriseService) GetCodeSecurityAndAnalysis(ctx context.Context, enterprise string) (*EnterpriseSecurityAnalysisSettings, *Response, error) { + u := fmt.Sprintf("enterprises/%v/code_security_and_analysis", enterprise) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + settings := new(EnterpriseSecurityAnalysisSettings) + resp, err := s.client.Do(ctx, req, settings) + if err != nil { + return nil, resp, err + } + + return settings, resp, nil +} + +// UpdateCodeSecurityAndAnalysis updates code security and analysis features for new repositories in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/code-security-and-analysis#update-code-security-and-analysis-features-for-an-enterprise +// +//meta:operation PATCH /enterprises/{enterprise}/code_security_and_analysis +func (s *EnterpriseService) UpdateCodeSecurityAndAnalysis(ctx context.Context, enterprise string, settings *EnterpriseSecurityAnalysisSettings) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/code_security_and_analysis", enterprise) + req, err := s.client.NewRequest("PATCH", u, settings) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// EnableDisableSecurityFeature enables or disables a security feature for all repositories in an enterprise. +// +// Valid values for securityProduct: "advanced_security", "secret_scanning", "secret_scanning_push_protection". +// Valid values for enablement: "enable_all", "disable_all". +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/code-security-and-analysis#enable-or-disable-a-security-feature +// +//meta:operation POST /enterprises/{enterprise}/{security_product}/{enablement} +func (s *EnterpriseService) EnableDisableSecurityFeature(ctx context.Context, enterprise, securityProduct, enablement string) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/%v/%v", enterprise, securityProduct, enablement) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/enterprise_properties.go b/vendor/github.com/google/go-github/v68/github/enterprise_properties.go new file mode 100644 index 0000000000..bc5ab55a3a --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/enterprise_properties.go @@ -0,0 +1,121 @@ +// Copyright 2024 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetAllCustomProperties gets all custom properties that are defined for the specified enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/custom-properties#get-custom-properties-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/properties/schema +func (s *EnterpriseService) GetAllCustomProperties(ctx context.Context, enterprise string) ([]*CustomProperty, *Response, error) { + u := fmt.Sprintf("enterprises/%v/properties/schema", enterprise) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var customProperties []*CustomProperty + resp, err := s.client.Do(ctx, req, &customProperties) + if err != nil { + return nil, resp, err + } + + return customProperties, resp, nil +} + +// CreateOrUpdateCustomProperties creates new or updates existing custom properties that are defined for the specified enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/custom-properties#create-or-update-custom-properties-for-an-enterprise +// +//meta:operation PATCH /enterprises/{enterprise}/properties/schema +func (s *EnterpriseService) CreateOrUpdateCustomProperties(ctx context.Context, enterprise string, properties []*CustomProperty) ([]*CustomProperty, *Response, error) { + u := fmt.Sprintf("enterprises/%v/properties/schema", enterprise) + + params := struct { + Properties []*CustomProperty `json:"properties"` + }{ + Properties: properties, + } + + req, err := s.client.NewRequest("PATCH", u, params) + if err != nil { + return nil, nil, err + } + + var customProperties []*CustomProperty + resp, err := s.client.Do(ctx, req, &customProperties) + if err != nil { + return nil, resp, err + } + + return customProperties, resp, nil +} + +// GetCustomProperty gets a custom property that is defined for the specified enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/custom-properties#get-a-custom-property-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/properties/schema/{custom_property_name} +func (s *EnterpriseService) GetCustomProperty(ctx context.Context, enterprise, customPropertyName string) (*CustomProperty, *Response, error) { + u := fmt.Sprintf("enterprises/%v/properties/schema/%v", enterprise, customPropertyName) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var customProperty *CustomProperty + resp, err := s.client.Do(ctx, req, &customProperty) + if err != nil { + return nil, resp, err + } + + return customProperty, resp, nil +} + +// CreateOrUpdateCustomProperty creates a new or updates an existing custom property that is defined for the specified enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/custom-properties#create-or-update-a-custom-property-for-an-enterprise +// +//meta:operation PUT /enterprises/{enterprise}/properties/schema/{custom_property_name} +func (s *EnterpriseService) CreateOrUpdateCustomProperty(ctx context.Context, enterprise, customPropertyName string, property *CustomProperty) (*CustomProperty, *Response, error) { + u := fmt.Sprintf("enterprises/%v/properties/schema/%v", enterprise, customPropertyName) + + req, err := s.client.NewRequest("PUT", u, property) + if err != nil { + return nil, nil, err + } + + var customProperty *CustomProperty + resp, err := s.client.Do(ctx, req, &customProperty) + if err != nil { + return nil, resp, err + } + + return customProperty, resp, nil +} + +// RemoveCustomProperty removes a custom property that is defined for the specified enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/custom-properties#remove-a-custom-property-for-an-enterprise +// +//meta:operation DELETE /enterprises/{enterprise}/properties/schema/{custom_property_name} +func (s *EnterpriseService) RemoveCustomProperty(ctx context.Context, enterprise, customPropertyName string) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/properties/schema/%v", enterprise, customPropertyName) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/event.go b/vendor/github.com/google/go-github/v68/github/event.go new file mode 100644 index 0000000000..e98606bce5 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/event.go @@ -0,0 +1,54 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "encoding/json" +) + +// Event represents a GitHub event. +type Event struct { + Type *string `json:"type,omitempty"` + Public *bool `json:"public,omitempty"` + RawPayload *json.RawMessage `json:"payload,omitempty"` + Repo *Repository `json:"repo,omitempty"` + Actor *User `json:"actor,omitempty"` + Org *Organization `json:"org,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + ID *string `json:"id,omitempty"` +} + +func (e Event) String() string { + return Stringify(e) +} + +// ParsePayload parses the event payload. For recognized event types, +// a value of the corresponding struct type will be returned. +func (e *Event) ParsePayload() (interface{}, error) { + // It would be nice if e.Type were the snake_case name of the event, + // but the existing interface uses the struct name instead. + payload := EventForType(typeToMessageMapping[e.GetType()]) + + if err := json.Unmarshal(e.GetRawPayload(), &payload); err != nil { + return nil, err + } + + return payload, nil +} + +// Payload returns the parsed event payload. For recognized event types, +// a value of the corresponding struct type will be returned. +// +// Deprecated: Use ParsePayload instead, which returns an error +// rather than panics if JSON unmarshaling raw payload fails. +func (e *Event) Payload() (payload interface{}) { + var err error + payload, err = e.ParsePayload() + if err != nil { + panic(err) + } + return payload +} diff --git a/vendor/github.com/google/go-github/v68/github/event_types.go b/vendor/github.com/google/go-github/v68/github/event_types.go new file mode 100644 index 0000000000..37e62c2fab --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/event_types.go @@ -0,0 +1,1928 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// These event types are shared between the Events API and used as Webhook payloads. + +package github + +import "encoding/json" + +// RequestedAction is included in a CheckRunEvent when a user has invoked an action, +// i.e. when the CheckRunEvent's Action field is "requested_action". +type RequestedAction struct { + Identifier string `json:"identifier"` // The integrator reference of the action requested by the user. +} + +// BranchProtectionRuleEvent triggered when a check suite is "created", "edited", or "deleted". +// The Webhook event name is "branch_protection_rule". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#branch_protection_rule +type BranchProtectionRuleEvent struct { + Action *string `json:"action,omitempty"` + Rule *BranchProtectionRule `json:"rule,omitempty"` + Changes *ProtectionChanges `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// BranchProtectionConfigurationEvent is triggered when there is a change to branch protection configurations for a repository. +// The Webhook event name is "branch_protection_configuration". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#branch_protection_configuration +type BranchProtectionConfigurationEvent struct { + Action *string `json:"action,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Enterprise *Enterprise `json:"enterprise,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// CheckRunEvent is triggered when a check run is "created", "completed", or "rerequested". +// The Webhook event name is "check_run". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#check_run +type CheckRunEvent struct { + CheckRun *CheckRun `json:"check_run,omitempty"` + // The action performed. Possible values are: "created", "completed", "rerequested" or "requested_action". + Action *string `json:"action,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The action requested by the user. Populated when the Action is "requested_action". + RequestedAction *RequestedAction `json:"requested_action,omitempty"` // +} + +// CheckSuiteEvent is triggered when a check suite is "completed", "requested", or "rerequested". +// The Webhook event name is "check_suite". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#check_suite +type CheckSuiteEvent struct { + CheckSuite *CheckSuite `json:"check_suite,omitempty"` + // The action performed. Possible values are: "completed", "requested" or "rerequested". + Action *string `json:"action,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// CommitCommentEvent is triggered when a commit comment is created. +// The Webhook event name is "commit_comment". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#commit_comment +type CommitCommentEvent struct { + Comment *RepositoryComment `json:"comment,omitempty"` + + // The following fields are only populated by Webhook events. + Action *string `json:"action,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// ContentReferenceEvent is triggered when the body or comment of an issue or +// pull request includes a URL that matches a configured content reference +// domain. +// The Webhook event name is "content_reference". +// +// GitHub API docs: https://developer.github.com/webhooks/event-payloads/#content_reference +type ContentReferenceEvent struct { + Action *string `json:"action,omitempty"` + ContentReference *ContentReference `json:"content_reference,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// CreateEvent represents a created repository, branch, or tag. +// The Webhook event name is "create". +// +// Note: webhooks will not receive this event for created repositories. +// Additionally, webhooks will not receive this event for tags if more +// than three tags are pushed at once. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/github-event-types#createevent +type CreateEvent struct { + Ref *string `json:"ref,omitempty"` + // RefType is the object that was created. Possible values are: "repository", "branch", "tag". + RefType *string `json:"ref_type,omitempty"` + MasterBranch *string `json:"master_branch,omitempty"` + Description *string `json:"description,omitempty"` + PusherType *string `json:"pusher_type,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// CustomPropertyEvent represents a created, deleted or updated custom property. +// The Webhook event name is "custom_property". +// +// Note: this is related to custom property configuration at the enterprise or organization level. +// See CustomPropertyValuesEvent for activity related to custom property values for a repository. +// +// GitHub API docs: https://docs.github.com/en/webhooks/webhook-events-and-payloads#custom_property +type CustomPropertyEvent struct { + // Action possible values are: "created", "deleted", "updated". + Action *string `json:"action,omitempty"` + Definition *CustomProperty `json:"definition,omitempty"` + + // The following fields are only populated by Webhook events. + Enterprise *Enterprise `json:"enterprise,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` +} + +// CustomPropertyValuesEvent represents an update to a custom property. +// The Webhook event name is "custom_property_values". +// +// GitHub API docs: https://docs.github.com/en/webhooks/webhook-events-and-payloads#custom_property_values +type CustomPropertyValuesEvent struct { + // Action possible values are: "updated". + Action *string `json:"action,omitempty"` + NewPropertyValues []*CustomPropertyValue `json:"new_property_values,omitempty"` + OldPropertyValues []*CustomPropertyValue `json:"old_property_values,omitempty"` + + // The following fields are only populated by Webhook events. + Enterprise *Enterprise `json:"enterprise,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` +} + +// DeleteEvent represents a deleted branch or tag. +// The Webhook event name is "delete". +// +// Note: webhooks will not receive this event for tags if more than three tags +// are deleted at once. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/github-event-types#deleteevent +type DeleteEvent struct { + Ref *string `json:"ref,omitempty"` + // RefType is the object that was deleted. Possible values are: "branch", "tag". + RefType *string `json:"ref_type,omitempty"` + + // The following fields are only populated by Webhook events. + PusherType *string `json:"pusher_type,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// DependabotAlertEvent is triggered when there is activity relating to Dependabot alerts. +// The Webhook event name is "dependabot_alert". +// +// GitHub API docs: https://docs.github.com/webhooks-and-events/webhooks/webhook-events-and-payloads#dependabot_alert +type DependabotAlertEvent struct { + Action *string `json:"action,omitempty"` + Alert *DependabotAlert `json:"alert,omitempty"` + + // The following fields are only populated by Webhook events. + Installation *Installation `json:"installation,omitempty"` + Enterprise *Enterprise `json:"enterprise,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Organization *Organization `json:"organization,omitempty"` +} + +// DeployKeyEvent is triggered when a deploy key is added or removed from a repository. +// The Webhook event name is "deploy_key". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#deploy_key +type DeployKeyEvent struct { + // Action is the action that was performed. Possible values are: + // "created" or "deleted". + Action *string `json:"action,omitempty"` + + // The deploy key resource. + Key *Key `json:"key,omitempty"` + + // The Repository where the event occurred + Repo *Repository `json:"repository,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Organization *Organization `json:"organization,omitempty"` + + // The following fields are only populated by Webhook events. + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// DeploymentEvent represents a deployment. +// The Webhook event name is "deployment". +// +// Events of this type are not visible in timelines, they are only used to trigger hooks. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#deployment +type DeploymentEvent struct { + Deployment *Deployment `json:"deployment,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Workflow *Workflow `json:"workflow,omitempty"` + WorkflowRun *WorkflowRun `json:"workflow_run,omitempty"` + + // The following fields are only populated by Webhook events. + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// DeploymentProtectionRuleEvent represents a deployment protection rule event. +// The Webhook event name is "deployment_protection_rule". +// +// GitHub API docs: https://docs.github.com/webhooks-and-events/webhooks/webhook-events-and-payloads#deployment_protection_rule +type DeploymentProtectionRuleEvent struct { + Action *string `json:"action,omitempty"` + Environment *string `json:"environment,omitempty"` + Event *string `json:"event,omitempty"` + + // The URL Github provides for a third-party to use in order to pass/fail a deployment gate + DeploymentCallbackURL *string `json:"deployment_callback_url,omitempty"` + Deployment *Deployment `json:"deployment,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Organization *Organization `json:"organization,omitempty"` + PullRequests []*PullRequest `json:"pull_requests,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// DeploymentReviewEvent represents a deployment review event. +// The Webhook event name is "deployment_review". +// +// GitHub API docs: https://docs.github.com/webhooks-and-events/webhooks/webhook-events-and-payloads?#deployment_review +type DeploymentReviewEvent struct { + // The action performed. Possible values are: "requested", "approved", or "rejected". + Action *string `json:"action,omitempty"` + + // The following will be populated only if requested. + Requester *User `json:"requester,omitempty"` + Environment *string `json:"environment,omitempty"` + + // The following will be populated only if approved or rejected. + Approver *User `json:"approver,omitempty"` + Comment *string `json:"comment,omitempty"` + WorkflowJobRuns []*WorkflowJobRun `json:"workflow_job_runs,omitempty"` + + Enterprise *Enterprise `json:"enterprise,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Reviewers []*RequiredReviewer `json:"reviewers,omitempty"` + Sender *User `json:"sender,omitempty"` + Since *string `json:"since,omitempty"` + WorkflowJobRun *WorkflowJobRun `json:"workflow_job_run,omitempty"` + WorkflowRun *WorkflowRun `json:"workflow_run,omitempty"` +} + +// WorkflowJobRun represents a workflow_job_run in a GitHub DeploymentReviewEvent. +type WorkflowJobRun struct { + Conclusion *string `json:"conclusion,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + Environment *string `json:"environment,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Status *string `json:"status,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +// DeploymentStatusEvent represents a deployment status. +// The Webhook event name is "deployment_status". +// +// Events of this type are not visible in timelines, they are only used to trigger hooks. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#deployment_status +type DeploymentStatusEvent struct { + Action *string `json:"action,omitempty"` + Deployment *Deployment `json:"deployment,omitempty"` + DeploymentStatus *DeploymentStatus `json:"deployment_status,omitempty"` + Repo *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// DiscussionCommentEvent represents a webhook event for a comment on discussion. +// The Webhook event name is "discussion_comment". +// +// GitHub API docs: https://docs.github.com/webhooks-and-events/webhooks/webhook-events-and-payloads#discussion_comment +type DiscussionCommentEvent struct { + // Action is the action that was performed on the comment. + // Possible values are: "created", "edited", "deleted". ** check what all can be added + Action *string `json:"action,omitempty"` + Discussion *Discussion `json:"discussion,omitempty"` + Comment *CommentDiscussion `json:"comment,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// CommentDiscussion represents a comment in a GitHub DiscussionCommentEvent. +type CommentDiscussion struct { + AuthorAssociation *string `json:"author_association,omitempty"` + Body *string `json:"body,omitempty"` + ChildCommentCount *int `json:"child_comment_count,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + DiscussionID *int64 `json:"discussion_id,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + ParentID *int64 `json:"parent_id,omitempty"` + Reactions *Reactions `json:"reactions,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + User *User `json:"user,omitempty"` +} + +// DiscussionEvent represents a webhook event for a discussion. +// The Webhook event name is "discussion". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#discussion +type DiscussionEvent struct { + // Action is the action that was performed. Possible values are: + // created, edited, deleted, pinned, unpinned, locked, unlocked, + // transferred, category_changed, answered, or unanswered. + Action *string `json:"action,omitempty"` + Discussion *Discussion `json:"discussion,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// Discussion represents a discussion in a GitHub DiscussionEvent. +type Discussion struct { + RepositoryURL *string `json:"repository_url,omitempty"` + DiscussionCategory *DiscussionCategory `json:"category,omitempty"` + AnswerHTMLURL *string `json:"answer_html_url,omitempty"` + AnswerChosenAt *Timestamp `json:"answer_chosen_at,omitempty"` + AnswerChosenBy *string `json:"answer_chosen_by,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Number *int `json:"number,omitempty"` + Title *string `json:"title,omitempty"` + User *User `json:"user,omitempty"` + State *string `json:"state,omitempty"` + Locked *bool `json:"locked,omitempty"` + Comments *int `json:"comments,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + AuthorAssociation *string `json:"author_association,omitempty"` + ActiveLockReason *string `json:"active_lock_reason,omitempty"` + Body *string `json:"body,omitempty"` +} + +// DiscussionCategory represents a discussion category in a GitHub DiscussionEvent. +type DiscussionCategory struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + RepositoryID *int64 `json:"repository_id,omitempty"` + Emoji *string `json:"emoji,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Slug *string `json:"slug,omitempty"` + IsAnswerable *bool `json:"is_answerable,omitempty"` +} + +// ForkEvent is triggered when a user forks a repository. +// The Webhook event name is "fork". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#fork +type ForkEvent struct { + // Forkee is the created repository. + Forkee *Repository `json:"forkee,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// GitHubAppAuthorizationEvent is triggered when a user's authorization for a +// GitHub Application is revoked. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#github_app_authorization +type GitHubAppAuthorizationEvent struct { + // The action performed. Possible value is: "revoked". + Action *string `json:"action,omitempty"` + + // The following fields are only populated by Webhook events. + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// Page represents a single Wiki page. +type Page struct { + PageName *string `json:"page_name,omitempty"` + Title *string `json:"title,omitempty"` + Summary *string `json:"summary,omitempty"` + Action *string `json:"action,omitempty"` + SHA *string `json:"sha,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` +} + +// GollumEvent is triggered when a Wiki page is created or updated. +// The Webhook event name is "gollum". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#gollum +type GollumEvent struct { + Pages []*Page `json:"pages,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// EditChange represents the changes when an issue, pull request, comment, +// or repository has been edited. +type EditChange struct { + Title *EditTitle `json:"title,omitempty"` + Body *EditBody `json:"body,omitempty"` + Base *EditBase `json:"base,omitempty"` + Repo *EditRepo `json:"repository,omitempty"` + Owner *EditOwner `json:"owner,omitempty"` + DefaultBranch *EditDefaultBranch `json:"default_branch,omitempty"` + Topics *EditTopics `json:"topics,omitempty"` +} + +// EditTitle represents a pull-request title change. +type EditTitle struct { + From *string `json:"from,omitempty"` +} + +// EditBody represents a change of pull-request body. +type EditBody struct { + From *string `json:"from,omitempty"` +} + +// EditBase represents the change of a pull-request base branch. +type EditBase struct { + Ref *EditRef `json:"ref,omitempty"` + SHA *EditSHA `json:"sha,omitempty"` +} + +// EditRef represents a ref change of a pull-request. +type EditRef struct { + From *string `json:"from,omitempty"` +} + +// EditRepo represents a change of repository name. +type EditRepo struct { + Name *RepoName `json:"name,omitempty"` +} + +// EditOwner represents a change of repository ownership. +type EditOwner struct { + OwnerInfo *OwnerInfo `json:"from,omitempty"` +} + +// OwnerInfo represents the account info of the owner of the repo (could be User or Organization but both are User structs). +type OwnerInfo struct { + User *User `json:"user,omitempty"` + Org *User `json:"organization,omitempty"` +} + +// RepoName represents a change of repository name. +type RepoName struct { + From *string `json:"from,omitempty"` +} + +// EditTopics represents a change of repository topics. +type EditTopics struct { + From []string `json:"from,omitempty"` +} + +// EditSHA represents a sha change of a pull-request. +type EditSHA struct { + From *string `json:"from,omitempty"` +} + +// EditDefaultBranch represents a change of repository's default branch name. +type EditDefaultBranch struct { + From *string `json:"from,omitempty"` +} + +// ProjectChange represents the changes when a project has been edited. +type ProjectChange struct { + Name *ProjectName `json:"name,omitempty"` + Body *ProjectBody `json:"body,omitempty"` +} + +// ProjectName represents a project name change. +type ProjectName struct { + From *string `json:"from,omitempty"` +} + +// ProjectBody represents a project body change. +type ProjectBody struct { + From *string `json:"from,omitempty"` +} + +// ProjectCardChange represents the changes when a project card has been edited. +type ProjectCardChange struct { + Note *ProjectCardNote `json:"note,omitempty"` +} + +// ProjectCardNote represents a change of a note of a project card. +type ProjectCardNote struct { + From *string `json:"from,omitempty"` +} + +// ProjectColumnChange represents the changes when a project column has been edited. +type ProjectColumnChange struct { + Name *ProjectColumnName `json:"name,omitempty"` +} + +// ProjectColumnName represents a project column name change. +type ProjectColumnName struct { + From *string `json:"from,omitempty"` +} + +// TeamChange represents the changes when a team has been edited. +type TeamChange struct { + Description *TeamDescription `json:"description,omitempty"` + Name *TeamName `json:"name,omitempty"` + Privacy *TeamPrivacy `json:"privacy,omitempty"` + Repository *TeamRepository `json:"repository,omitempty"` +} + +// TeamDescription represents a team description change. +type TeamDescription struct { + From *string `json:"from,omitempty"` +} + +// TeamName represents a team name change. +type TeamName struct { + From *string `json:"from,omitempty"` +} + +// TeamPrivacy represents a team privacy change. +type TeamPrivacy struct { + From *string `json:"from,omitempty"` +} + +// TeamRepository represents a team repository permission change. +type TeamRepository struct { + Permissions *TeamPermissions `json:"permissions,omitempty"` +} + +// TeamPermissions represents a team permission change. +type TeamPermissions struct { + From *TeamPermissionsFrom `json:"from,omitempty"` +} + +// TeamPermissionsFrom represents a team permission change. +type TeamPermissionsFrom struct { + Admin *bool `json:"admin,omitempty"` + Pull *bool `json:"pull,omitempty"` + Push *bool `json:"push,omitempty"` +} + +// InstallationEvent is triggered when a GitHub App has been installed, uninstalled, suspend, unsuspended +// or new permissions have been accepted. +// The Webhook event name is "installation". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#installation +type InstallationEvent struct { + // The action that was performed. Can be either "created", "deleted", "suspend", "unsuspend" or "new_permissions_accepted". + Action *string `json:"action,omitempty"` + Repositories []*Repository `json:"repositories,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Requester *User `json:"requester,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// InstallationRepositoriesEvent is triggered when a repository is added or +// removed from an installation. The Webhook event name is "installation_repositories". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#installation_repositories +type InstallationRepositoriesEvent struct { + // The action that was performed. Can be either "added" or "removed". + Action *string `json:"action,omitempty"` + RepositoriesAdded []*Repository `json:"repositories_added,omitempty"` + RepositoriesRemoved []*Repository `json:"repositories_removed,omitempty"` + RepositorySelection *string `json:"repository_selection,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// InstallationLoginChange represents a change in login on an installation. +type InstallationLoginChange struct { + From *string `json:"from,omitempty"` +} + +// InstallationSlugChange represents a change in slug on an installation. +type InstallationSlugChange struct { + From *string `json:"from,omitempty"` +} + +// InstallationChanges represents a change in slug or login on an installation. +type InstallationChanges struct { + Login *InstallationLoginChange `json:"login,omitempty"` + Slug *InstallationSlugChange `json:"slug,omitempty"` +} + +// InstallationTargetEvent is triggered when there is activity on an installation from a user or organization account. +// The Webhook event name is "installation_target". +// +// GitHub API docs: https://docs.github.com/webhooks-and-events/webhooks/webhook-events-and-payloads#installation_target +type InstallationTargetEvent struct { + Account *User `json:"account,omitempty"` + Action *string `json:"action,omitempty"` + Changes *InstallationChanges `json:"changes,omitempty"` + Enterprise *Enterprise `json:"enterprise,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Repository *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + TargetType *string `json:"target_type,omitempty"` +} + +// IssueCommentEvent is triggered when an issue comment is created on an issue +// or pull request. +// The Webhook event name is "issue_comment". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#issue_comment +type IssueCommentEvent struct { + // Action is the action that was performed on the comment. + // Possible values are: "created", "edited", "deleted". + Action *string `json:"action,omitempty"` + Issue *Issue `json:"issue,omitempty"` + Comment *IssueComment `json:"comment,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Organization *Organization `json:"organization,omitempty"` +} + +// IssuesEvent is triggered when an issue is opened, edited, deleted, transferred, +// pinned, unpinned, closed, reopened, assigned, unassigned, labeled, unlabeled, +// locked, unlocked, milestoned, or demilestoned. +// The Webhook event name is "issues". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#issues +type IssuesEvent struct { + // Action is the action that was performed. Possible values are: "opened", + // "edited", "deleted", "transferred", "pinned", "unpinned", "closed", "reopened", + // "assigned", "unassigned", "labeled", "unlabeled", "locked", "unlocked", + // "milestoned", or "demilestoned". + Action *string `json:"action,omitempty"` + Issue *Issue `json:"issue,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Label *Label `json:"label,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Milestone *Milestone `json:"milestone,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// LabelEvent is triggered when a repository's label is created, edited, or deleted. +// The Webhook event name is "label" +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#label +type LabelEvent struct { + // Action is the action that was performed. Possible values are: + // "created", "edited", "deleted" + Action *string `json:"action,omitempty"` + Label *Label `json:"label,omitempty"` + Changes *EditChange `json:"changes,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// MarketplacePurchaseEvent is triggered when a user purchases, cancels, or changes +// their GitHub Marketplace plan. +// Webhook event name "marketplace_purchase". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#marketplace_purchase +type MarketplacePurchaseEvent struct { + // Action is the action that was performed. Possible values are: + // "purchased", "cancelled", "pending_change", "pending_change_cancelled", "changed". + Action *string `json:"action,omitempty"` + + // The following fields are only populated by Webhook events. + EffectiveDate *Timestamp `json:"effective_date,omitempty"` + MarketplacePurchase *MarketplacePurchase `json:"marketplace_purchase,omitempty"` + PreviousMarketplacePurchase *MarketplacePurchase `json:"previous_marketplace_purchase,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// MemberChangesPermission represents changes to a repository collaborator's permissions. +type MemberChangesPermission struct { + From *string `json:"from,omitempty"` + To *string `json:"to,omitempty"` +} + +// MemberChangesRoleName represents changes to a repository collaborator's role. +type MemberChangesRoleName struct { + From *string `json:"from,omitempty"` + To *string `json:"to,omitempty"` +} + +// MemberChanges represents changes to a repository collaborator's role or permission. +type MemberChanges struct { + Permission *MemberChangesPermission `json:"permission,omitempty"` + RoleName *MemberChangesRoleName `json:"role_name,omitempty"` +} + +// MemberEvent is triggered when a user's membership as a collaborator to a repository changes. +// The Webhook event name is "member". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#member +type MemberEvent struct { + // Action is the action that was performed. Possible values are: "added", "edited", "removed". + Action *string `json:"action,omitempty"` + Member *User `json:"member,omitempty"` + Changes *MemberChanges `json:"changes,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// MembershipEvent is triggered when a user is added or removed from a team. +// The Webhook event name is "membership". +// +// Events of this type are not visible in timelines, they are only used to +// trigger organization webhooks. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#membership +type MembershipEvent struct { + // Action is the action that was performed. Possible values are: "added", "removed". + Action *string `json:"action,omitempty"` + // Scope is the scope of the membership. Possible value is: "team". + Scope *string `json:"scope,omitempty"` + Member *User `json:"member,omitempty"` + Team *Team `json:"team,omitempty"` + + // The following fields are only populated by Webhook events. + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// MergeGroup represents the merge group in a merge queue. +type MergeGroup struct { + // The SHA of the merge group. + HeadSHA *string `json:"head_sha,omitempty"` + // The full ref of the merge group. + HeadRef *string `json:"head_ref,omitempty"` + // The SHA of the merge group's parent commit. + BaseSHA *string `json:"base_sha,omitempty"` + // The full ref of the branch the merge group will be merged into. + BaseRef *string `json:"base_ref,omitempty"` + // An expanded representation of the head_sha commit. + HeadCommit *Commit `json:"head_commit,omitempty"` +} + +// MergeGroupEvent represents activity related to merge groups in a merge queue. The type of activity is specified +// in the action property of the payload object. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#merge_group +type MergeGroupEvent struct { + // The action that was performed. Currently, can only be checks_requested. + Action *string `json:"action,omitempty"` + // The merge group. + MergeGroup *MergeGroup `json:"merge_group,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Sender *User `json:"sender,omitempty"` +} + +// MetaEvent is triggered when the webhook that this event is configured on is deleted. +// This event will only listen for changes to the particular hook the event is installed on. +// Therefore, it must be selected for each hook that you'd like to receive meta events for. +// The Webhook event name is "meta". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#meta +type MetaEvent struct { + // Action is the action that was performed. Possible value is: "deleted". + Action *string `json:"action,omitempty"` + // The ID of the modified webhook. + HookID *int64 `json:"hook_id,omitempty"` + // The modified webhook. + // This will contain different keys based on the type of webhook it is: repository, + // organization, business, app, or GitHub Marketplace. + Hook *Hook `json:"hook,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// MilestoneEvent is triggered when a milestone is created, closed, opened, edited, or deleted. +// The Webhook event name is "milestone". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#milestone +type MilestoneEvent struct { + // Action is the action that was performed. Possible values are: + // "created", "closed", "opened", "edited", "deleted" + Action *string `json:"action,omitempty"` + Milestone *Milestone `json:"milestone,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Org *Organization `json:"organization,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// OrganizationEvent is triggered when an organization is deleted and renamed, and when a user is added, +// removed, or invited to an organization. +// Events of this type are not visible in timelines. These events are only used to trigger organization hooks. +// Webhook event name is "organization". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#organization +type OrganizationEvent struct { + // Action is the action that was performed. + // Possible values are: "deleted", "renamed", "member_added", "member_removed", or "member_invited". + Action *string `json:"action,omitempty"` + + // Invitation is the invitation for the user or email if the action is "member_invited". + Invitation *Invitation `json:"invitation,omitempty"` + + // Membership is the membership between the user and the organization. + // Not present when the action is "member_invited". + Membership *Membership `json:"membership,omitempty"` + + Organization *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// OrgBlockEvent is triggered when an organization blocks or unblocks a user. +// The Webhook event name is "org_block". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#org_block +type OrgBlockEvent struct { + // Action is the action that was performed. + // Can be "blocked" or "unblocked". + Action *string `json:"action,omitempty"` + BlockedUser *User `json:"blocked_user,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + + // The following fields are only populated by Webhook events. + Installation *Installation `json:"installation,omitempty"` +} + +// PackageEvent represents activity related to GitHub Packages. +// The Webhook event name is "package". +// +// This event is triggered when a GitHub Package is published or updated. +// +// GitHub API docs: https://developer.github.com/webhooks/event-payloads/#package +type PackageEvent struct { + // Action is the action that was performed. + // Can be "published" or "updated". + Action *string `json:"action,omitempty"` + Package *Package `json:"package,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + + // The following fields are only populated by Webhook events. + Installation *Installation `json:"installation,omitempty"` +} + +// PageBuildEvent represents an attempted build of a GitHub Pages site, whether +// successful or not. +// The Webhook event name is "page_build". +// +// This event is triggered on push to a GitHub Pages enabled branch (gh-pages +// for project pages, master for user and organization pages). +// +// Events of this type are not visible in timelines, they are only used to trigger hooks. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#page_build +type PageBuildEvent struct { + Build *PagesBuild `json:"build,omitempty"` + + // The following fields are only populated by Webhook events. + ID *int64 `json:"id,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// PersonalAccessTokenRequestEvent occurs when there is activity relating to a +// request for a fine-grained personal access token to access resources that +// belong to a resource owner that requires approval for token access. +// The webhook event name is "personal_access_token_request". +// +// GitHub API docs: https://docs.github.com/webhooks-and-events/webhooks/webhook-events-and-payloads#personal_access_token_request +type PersonalAccessTokenRequestEvent struct { + // Action is the action that was performed. Possible values are: + // "approved", "cancelled", "created" or "denied" + Action *string `json:"action,omitempty"` + PersonalAccessTokenRequest *PersonalAccessTokenRequest `json:"personal_access_token_request,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// PersonalAccessTokenRequest contains the details of a PersonalAccessTokenRequestEvent. +type PersonalAccessTokenRequest struct { + // Unique identifier of the request for access via fine-grained personal + // access token. Used as the pat_request_id parameter in the list and review + // API calls. + ID *int64 `json:"id,omitempty"` + Owner *User `json:"owner,omitempty"` + + // New requested permissions, categorized by type of permission. + PermissionsAdded *PersonalAccessTokenPermissions `json:"permissions_added,omitempty"` + + // Requested permissions that elevate access for a previously approved + // request for access, categorized by type of permission. + PermissionsUpgraded *PersonalAccessTokenPermissions `json:"permissions_upgraded,omitempty"` + + // Permissions requested, categorized by type of permission. + // This field incorporates permissions_added and permissions_upgraded. + PermissionsResult *PersonalAccessTokenPermissions `json:"permissions_result,omitempty"` + + // Type of repository selection requested. Possible values are: + // "none", "all" or "subset" + RepositorySelection *string `json:"repository_selection,omitempty"` + + // The number of repositories the token is requesting access to. + // This field is only populated when repository_selection is subset. + RepositoryCount *int64 `json:"repository_count,omitempty"` + + // An array of repository objects the token is requesting access to. + // This field is only populated when repository_selection is subset. + Repositories []*Repository `json:"repositories,omitempty"` + + // Date and time when the request for access was created. + CreatedAt *Timestamp `json:"created_at,omitempty"` + + // Whether the associated fine-grained personal access token has expired. + TokenExpired *bool `json:"token_expired,omitempty"` + + // Date and time when the associated fine-grained personal access token expires. + TokenExpiresAt *Timestamp `json:"token_expires_at,omitempty"` + + // Date and time when the associated fine-grained personal access token was last used for authentication. + TokenLastUsedAt *Timestamp `json:"token_last_used_at,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// PersonalAccessTokenPermissions represents the original or newly requested +// scope of permissions for a fine-grained personal access token within a PersonalAccessTokenRequest. +type PersonalAccessTokenPermissions struct { + Org map[string]string `json:"organization,omitempty"` + Repo map[string]string `json:"repository,omitempty"` + Other map[string]string `json:"other,omitempty"` +} + +// PingEvent is triggered when a Webhook is added to GitHub. +// +// GitHub API docs: https://developer.github.com/webhooks/#ping-event +type PingEvent struct { + // Random string of GitHub zen. + Zen *string `json:"zen,omitempty"` + // The ID of the webhook that triggered the ping. + HookID *int64 `json:"hook_id,omitempty"` + // The webhook configuration. + Hook *Hook `json:"hook,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// ProjectV2Event is triggered when there is activity relating to an organization-level project. +// The Webhook event name is "projects_v2". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#projects_v2 +type ProjectV2Event struct { + Action *string `json:"action,omitempty"` + ProjectsV2 *ProjectV2 `json:"projects_v2,omitempty"` + + // The following fields are only populated by Webhook events. + Installation *Installation `json:"installation,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` +} + +// ProjectV2 represents a v2 project. +type ProjectV2 struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Owner *User `json:"owner,omitempty"` + Creator *User `json:"creator,omitempty"` + Title *string `json:"title,omitempty"` + Description *string `json:"description,omitempty"` + Public *bool `json:"public,omitempty"` + ClosedAt *Timestamp `json:"closed_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + DeletedAt *Timestamp `json:"deleted_at,omitempty"` + Number *int `json:"number,omitempty"` + ShortDescription *string `json:"short_description,omitempty"` + DeletedBy *User `json:"deleted_by,omitempty"` + + // Fields migrated from the Project (classic) struct: + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + ColumnsURL *string `json:"columns_url,omitempty"` + OwnerURL *string `json:"owner_url,omitempty"` + Name *string `json:"name,omitempty"` + Body *string `json:"body,omitempty"` + State *string `json:"state,omitempty"` + OrganizationPermission *string `json:"organization_permission,omitempty"` + Private *bool `json:"private,omitempty"` +} + +// ProjectV2ItemEvent is triggered when there is activity relating to an item on an organization-level project. +// The Webhook event name is "projects_v2_item". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#projects_v2_item +type ProjectV2ItemEvent struct { + Action *string `json:"action,omitempty"` + Changes *ProjectV2ItemChange `json:"changes,omitempty"` + ProjectV2Item *ProjectV2Item `json:"projects_v2_item,omitempty"` + + // The following fields are only populated by Webhook events. + Installation *Installation `json:"installation,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` +} + +// ProjectV2ItemChange represents a project v2 item change. +type ProjectV2ItemChange struct { + ArchivedAt *ArchivedAt `json:"archived_at,omitempty"` +} + +// ArchivedAt represents an archiving date change. +type ArchivedAt struct { + From *Timestamp `json:"from,omitempty"` + To *Timestamp `json:"to,omitempty"` +} + +// ProjectV2Item represents an item belonging to a project. +type ProjectV2Item struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + ProjectNodeID *string `json:"project_node_id,omitempty"` + ContentNodeID *string `json:"content_node_id,omitempty"` + ContentType *string `json:"content_type,omitempty"` + Creator *User `json:"creator,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + ArchivedAt *Timestamp `json:"archived_at,omitempty"` +} + +// PublicEvent is triggered when a private repository is open sourced. +// According to GitHub: "Without a doubt: the best GitHub event." +// The Webhook event name is "public". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#public +type PublicEvent struct { + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// PullRequestEvent is triggered when a pull request is assigned, unassigned, labeled, +// unlabeled, opened, edited, closed, reopened, synchronize, ready_for_review, +// locked, unlocked, a pull request review is requested, or a review request is removed. +// The Webhook event name is "pull_request". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/github-event-types#pullrequestevent +type PullRequestEvent struct { + // Action is the action that was performed. Possible values are: + // "assigned", "unassigned", "review_requested", "review_request_removed", "labeled", "unlabeled", + // "opened", "edited", "closed", "ready_for_review", "locked", "unlocked", or "reopened". + // If the action is "closed" and the "merged" key is "false", the pull request was closed with unmerged commits. + // If the action is "closed" and the "merged" key is "true", the pull request was merged. + // While webhooks are also triggered when a pull request is synchronized, Events API timelines + // don't include pull request events with the "synchronize" action. + Action *string `json:"action,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Number *int `json:"number,omitempty"` + PullRequest *PullRequest `json:"pull_request,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + // RequestedReviewer is populated in "review_requested", "review_request_removed" event deliveries. + // A request affecting multiple reviewers at once is split into multiple + // such event deliveries, each with a single, different RequestedReviewer. + RequestedReviewer *User `json:"requested_reviewer,omitempty"` + // In the event that a team is requested instead of a user, "requested_team" gets sent in place of + // "requested_user" with the same delivery behavior. + RequestedTeam *Team `json:"requested_team,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Label *Label `json:"label,omitempty"` // Populated in "labeled" event deliveries. + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Organization *Organization `json:"organization,omitempty"` + + // The following fields are only populated when the Action is "synchronize". + Before *string `json:"before,omitempty"` + After *string `json:"after,omitempty"` + + // The following will be populated if the event was performed by an App + PerformedViaGithubApp *App `json:"performed_via_github_app,omitempty"` +} + +// PullRequestReviewEvent is triggered when a review is submitted on a pull +// request. +// The Webhook event name is "pull_request_review". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#pull_request_review +type PullRequestReviewEvent struct { + // Action is always "submitted". + Action *string `json:"action,omitempty"` + Review *PullRequestReview `json:"review,omitempty"` + PullRequest *PullRequest `json:"pull_request,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Organization *Organization `json:"organization,omitempty"` +} + +// PullRequestReviewCommentEvent is triggered when a comment is created on a +// portion of the unified diff of a pull request. +// The Webhook event name is "pull_request_review_comment". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#pull_request_review_comment +type PullRequestReviewCommentEvent struct { + // Action is the action that was performed on the comment. + // Possible values are: "created", "edited", "deleted". + Action *string `json:"action,omitempty"` + PullRequest *PullRequest `json:"pull_request,omitempty"` + Comment *PullRequestComment `json:"comment,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// PullRequestReviewThreadEvent is triggered when a comment made as part of a +// review of a pull request is marked resolved or unresolved. +// The Webhook event name is "pull_request_review_thread". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#pull_request_review_thread +type PullRequestReviewThreadEvent struct { + // Action is the action that was performed on the comment. + // Possible values are: "resolved", "unresolved". + Action *string `json:"action,omitempty"` + Thread *PullRequestThread `json:"thread,omitempty"` + PullRequest *PullRequest `json:"pull_request,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// PullRequestTargetEvent is triggered when a pull request is assigned, unassigned, labeled, +// unlabeled, opened, edited, closed, reopened, synchronize, ready_for_review, +// locked, unlocked, a pull request review is requested, or a review request is removed. +// The Webhook event name is "pull_request_target". +// +// GitHub API docs: https://docs.github.com/actions/events-that-trigger-workflows#pull_request_target +type PullRequestTargetEvent struct { + // Action is the action that was performed. Possible values are: + // "assigned", "unassigned", "labeled", "unlabeled", "opened", "edited", "closed", "reopened", + // "ready_for_review", "locked", "unlocked", "review_requested" or "review_request_removed". + // If the action is "closed" and the "merged" key is "false", the pull request was closed with unmerged commits. + // If the action is "closed" and the "merged" key is "true", the pull request was merged. + // While webhooks are also triggered when a pull request is synchronized, Events API timelines + // don't include pull request events with the "synchronize" action. + Action *string `json:"action,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Number *int `json:"number,omitempty"` + PullRequest *PullRequest `json:"pull_request,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + // RequestedReviewer is populated in "review_requested", "review_request_removed" event deliveries. + // A request affecting multiple reviewers at once is split into multiple + // such event deliveries, each with a single, different RequestedReviewer. + RequestedReviewer *User `json:"requested_reviewer,omitempty"` + // In the event that a team is requested instead of a user, "requested_team" gets sent in place of + // "requested_user" with the same delivery behavior. + RequestedTeam *Team `json:"requested_team,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Label *Label `json:"label,omitempty"` // Populated in "labeled" event deliveries. + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Organization *Organization `json:"organization,omitempty"` + + // The following fields are only populated when the Action is "synchronize". + Before *string `json:"before,omitempty"` + After *string `json:"after,omitempty"` + + // The following will be populated if the event was performed by an App + PerformedViaGithubApp *App `json:"performed_via_github_app,omitempty"` +} + +// PushEvent represents a git push to a GitHub repository. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#push +type PushEvent struct { + PushID *int64 `json:"push_id,omitempty"` + Head *string `json:"head,omitempty"` + Ref *string `json:"ref,omitempty"` + Size *int `json:"size,omitempty"` + Commits []*HeadCommit `json:"commits,omitempty"` + Before *string `json:"before,omitempty"` + DistinctSize *int `json:"distinct_size,omitempty"` + + // The following fields are only populated by Webhook events. + Action *string `json:"action,omitempty"` + After *string `json:"after,omitempty"` + Created *bool `json:"created,omitempty"` + Deleted *bool `json:"deleted,omitempty"` + Forced *bool `json:"forced,omitempty"` + BaseRef *string `json:"base_ref,omitempty"` + Compare *string `json:"compare,omitempty"` + Repo *PushEventRepository `json:"repository,omitempty"` + HeadCommit *HeadCommit `json:"head_commit,omitempty"` + Pusher *CommitAuthor `json:"pusher,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Organization *Organization `json:"organization,omitempty"` +} + +func (p PushEvent) String() string { + return Stringify(p) +} + +// HeadCommit represents a git commit in a GitHub PushEvent. +type HeadCommit struct { + Message *string `json:"message,omitempty"` + Author *CommitAuthor `json:"author,omitempty"` + URL *string `json:"url,omitempty"` + Distinct *bool `json:"distinct,omitempty"` + + // The following fields are only populated by Events API. + SHA *string `json:"sha,omitempty"` + + // The following fields are only populated by Webhook events. + ID *string `json:"id,omitempty"` + TreeID *string `json:"tree_id,omitempty"` + Timestamp *Timestamp `json:"timestamp,omitempty"` + Committer *CommitAuthor `json:"committer,omitempty"` + Added []string `json:"added,omitempty"` + Removed []string `json:"removed,omitempty"` + Modified []string `json:"modified,omitempty"` +} + +func (h HeadCommit) String() string { + return Stringify(h) +} + +// PushEventRepository represents the repo object in a PushEvent payload. +type PushEventRepository struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Name *string `json:"name,omitempty"` + FullName *string `json:"full_name,omitempty"` + Owner *User `json:"owner,omitempty"` + Private *bool `json:"private,omitempty"` + Description *string `json:"description,omitempty"` + Fork *bool `json:"fork,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + PushedAt *Timestamp `json:"pushed_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Homepage *string `json:"homepage,omitempty"` + PullsURL *string `json:"pulls_url,omitempty"` + Size *int `json:"size,omitempty"` + StargazersCount *int `json:"stargazers_count,omitempty"` + WatchersCount *int `json:"watchers_count,omitempty"` + Language *string `json:"language,omitempty"` + HasIssues *bool `json:"has_issues,omitempty"` + HasDownloads *bool `json:"has_downloads,omitempty"` + HasWiki *bool `json:"has_wiki,omitempty"` + HasPages *bool `json:"has_pages,omitempty"` + ForksCount *int `json:"forks_count,omitempty"` + Archived *bool `json:"archived,omitempty"` + Disabled *bool `json:"disabled,omitempty"` + OpenIssuesCount *int `json:"open_issues_count,omitempty"` + DefaultBranch *string `json:"default_branch,omitempty"` + MasterBranch *string `json:"master_branch,omitempty"` + Organization *string `json:"organization,omitempty"` + URL *string `json:"url,omitempty"` + ArchiveURL *string `json:"archive_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + StatusesURL *string `json:"statuses_url,omitempty"` + GitURL *string `json:"git_url,omitempty"` + SSHURL *string `json:"ssh_url,omitempty"` + CloneURL *string `json:"clone_url,omitempty"` + SVNURL *string `json:"svn_url,omitempty"` + Topics []string `json:"topics,omitempty"` + CustomProperties map[string]interface{} `json:"custom_properties,omitempty"` +} + +// PushEventRepoOwner is a basic representation of user/org in a PushEvent payload. +type PushEventRepoOwner struct { + Name *string `json:"name,omitempty"` + Email *string `json:"email,omitempty"` +} + +// ReleaseEvent is triggered when a release is published, unpublished, created, +// edited, deleted, or prereleased. +// The Webhook event name is "release". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#release +type ReleaseEvent struct { + // Action is the action that was performed. Possible values are: "published", "unpublished", + // "created", "edited", "deleted", or "prereleased". + Action *string `json:"action,omitempty"` + Release *RepositoryRelease `json:"release,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// RepositoryEvent is triggered when a repository is created, archived, unarchived, +// renamed, edited, transferred, made public, or made private. Organization hooks are +// also triggered when a repository is deleted. +// The Webhook event name is "repository". +// +// Events of this type are not visible in timelines, they are only used to +// trigger organization webhooks. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#repository +type RepositoryEvent struct { + // Action is the action that was performed. Possible values are: "created", + // "deleted" (organization hooks only), "archived", "unarchived", "edited", "renamed", + // "transferred", "publicized", or "privatized". + Action *string `json:"action,omitempty"` + Repo *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// RepositoryDispatchEvent is triggered when a client sends a POST request to the repository dispatch event endpoint. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#repository_dispatch +type RepositoryDispatchEvent struct { + // Action is the event_type that submitted with the repository dispatch payload. Value can be any string. + Action *string `json:"action,omitempty"` + Branch *string `json:"branch,omitempty"` + ClientPayload json.RawMessage `json:"client_payload,omitempty"` + Repo *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// RepositoryImportEvent represents the activity related to a repository being imported to GitHub. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#repository_import +type RepositoryImportEvent struct { + // Status represents the final state of the import. This can be one of "success", "cancelled", or "failure". + Status *string `json:"status,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` +} + +// RepositoryRulesetEvent triggers whenever there is a change to the repository's ruleset configuration. +// +// This can include updates to protection rules, required status checks, code owners, or other related configurations. +// +// GitHub API docs: https://docs.github.com/en/webhooks/webhook-events-and-payloads#repository_ruleset +type RepositoryRulesetEvent struct { + Action *string `json:"action,omitempty"` + Enterprise *Enterprise `json:"enterprise,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Repository *Repository `json:"repository,omitempty"` + RepositoryRuleset *RepositoryRuleset `json:"repository_ruleset"` + Changes *RepositoryRulesetEditedChanges `json:"changes,omitempty"` + Sender *User `json:"sender"` +} + +// RepositoryVulnerabilityAlertEvent is triggered when a security alert is created, dismissed, or resolved. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#repository_vulnerability_alert +type RepositoryVulnerabilityAlertEvent struct { + // Action is the action that was performed. Possible values are: "create", "dismiss", "resolve". + Action *string `json:"action,omitempty"` + + // The security alert of the vulnerable dependency. + Alert *RepositoryVulnerabilityAlert `json:"alert,omitempty"` + + // The repository of the vulnerable dependency. + Repository *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Installation *Installation `json:"installation,omitempty"` + + // The user that triggered the event. + Sender *User `json:"sender,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// RepositoryVulnerabilityAlert represents a repository security alert. +type RepositoryVulnerabilityAlert struct { + ID *int64 `json:"id,omitempty"` + AffectedRange *string `json:"affected_range,omitempty"` + AffectedPackageName *string `json:"affected_package_name,omitempty"` + ExternalReference *string `json:"external_reference,omitempty"` + ExternalIdentifier *string `json:"external_identifier,omitempty"` + GitHubSecurityAdvisoryID *string `json:"ghsa_id,omitempty"` + Severity *string `json:"severity,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + FixedIn *string `json:"fixed_in,omitempty"` + Dismisser *User `json:"dismisser,omitempty"` + DismissReason *string `json:"dismiss_reason,omitempty"` + DismissedAt *Timestamp `json:"dismissed_at,omitempty"` +} + +// SecretScanningAlertEvent is triggered when a secret scanning alert occurs in a repository. +// The Webhook name is secret_scanning_alert. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#secret_scanning_alert +type SecretScanningAlertEvent struct { + // Action is the action that was performed. Possible values are: "created", "resolved", or "reopened". + Action *string `json:"action,omitempty"` + + // Alert is the secret scanning alert involved in the event. + Alert *SecretScanningAlert `json:"alert,omitempty"` + + // Only populated by the "resolved" and "reopen" actions + Sender *User `json:"sender,omitempty"` + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Enterprise *Enterprise `json:"enterprise,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// SecretScanningAlertLocationEvent is triggered when there is activity relating to the locations of a secret in a secret scanning alert. +// The Webhook event name is "secret_scanning_alert_location". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#secret_scanning_alert_location +type SecretScanningAlertLocationEvent struct { + Action *string `json:"action,omitempty"` + Alert *SecretScanningAlert `json:"alert,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Location *SecretScanningAlertLocation `json:"location,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` +} + +// SecurityAndAnalysisEvent is triggered when code security and analysis features +// are enabled or disabled for a repository. +// +// GitHub API docs: https://docs.github.com/webhooks-and-events/webhooks/webhook-events-and-payloads#security_and_analysis +type SecurityAndAnalysisEvent struct { + Changes *SecurityAndAnalysisChange `json:"changes,omitempty"` + Enterprise *Enterprise `json:"enterprise,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Repository *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` +} + +// SecurityAndAnalysisChange represents the changes when security and analysis +// features are enabled or disabled for a repository. +type SecurityAndAnalysisChange struct { + From *SecurityAndAnalysisChangeFrom `json:"from,omitempty"` +} + +// SecurityAndAnalysisChangeFrom represents which change was made when security +// and analysis features are enabled or disabled for a repository. +type SecurityAndAnalysisChangeFrom struct { + SecurityAndAnalysis *SecurityAndAnalysis `json:"security_and_analysis,omitempty"` +} + +// StarEvent is triggered when a star is added or removed from a repository. +// The Webhook event name is "star". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#star +type StarEvent struct { + // Action is the action that was performed. Possible values are: "created" or "deleted". + Action *string `json:"action,omitempty"` + + // StarredAt is the time the star was created. It will be null for the "deleted" action. + StarredAt *Timestamp `json:"starred_at,omitempty"` + + // The following fields are only populated by Webhook events. + Org *Organization `json:"organization,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// StatusEvent is triggered when the status of a Git commit changes. +// The Webhook event name is "status". +// +// Events of this type are not visible in timelines, they are only used to +// trigger hooks. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#status +type StatusEvent struct { + SHA *string `json:"sha,omitempty"` + // State is the new state. Possible values are: "pending", "success", "failure", "error". + State *string `json:"state,omitempty"` + Description *string `json:"description,omitempty"` + TargetURL *string `json:"target_url,omitempty"` + Branches []*Branch `json:"branches,omitempty"` + + // The following fields are only populated by Webhook events. + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Context *string `json:"context,omitempty"` + Commit *RepositoryCommit `json:"commit,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// TeamEvent is triggered when an organization's team is created, modified or deleted. +// The Webhook event name is "team". +// +// Events of this type are not visible in timelines. These events are only used +// to trigger hooks. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#team +type TeamEvent struct { + Action *string `json:"action,omitempty"` + Team *Team `json:"team,omitempty"` + Changes *TeamChange `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// TeamAddEvent is triggered when a repository is added to a team. +// The Webhook event name is "team_add". +// +// Events of this type are not visible in timelines. These events are only used +// to trigger hooks. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#team_add +type TeamAddEvent struct { + Team *Team `json:"team,omitempty"` + Repo *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// UserEvent is triggered when a user is created or deleted. +// The Webhook event name is "user". +// +// Only global webhooks can subscribe to this event type. +// +// GitHub API docs: https://developer.github.com/enterprise/v3/activity/events/types/#userevent-enterprise +type UserEvent struct { + User *User `json:"user,omitempty"` + // The action performed. Possible values are: "created" or "deleted". + Action *string `json:"action,omitempty"` + Enterprise *Enterprise `json:"enterprise,omitempty"` + Sender *User `json:"sender,omitempty"` + + // The following fields are only populated by Webhook events. + Installation *Installation `json:"installation,omitempty"` +} + +// WatchEvent is related to starring a repository, not watching. See this API +// blog post for an explanation: https://developer.github.com/changes/2012-09-05-watcher-api/ +// +// The event’s actor is the user who starred a repository, and the event’s +// repository is the repository that was starred. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#watch +type WatchEvent struct { + // Action is the action that was performed. Possible value is: "started". + Action *string `json:"action,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// WorkflowDispatchEvent is triggered when someone triggers a workflow run on GitHub or +// sends a POST request to the create a workflow dispatch event endpoint. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#workflow_dispatch +type WorkflowDispatchEvent struct { + Inputs json.RawMessage `json:"inputs,omitempty"` + Ref *string `json:"ref,omitempty"` + Workflow *string `json:"workflow,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// WorkflowJobEvent is triggered when a job is queued, started or completed. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#workflow_job +type WorkflowJobEvent struct { + WorkflowJob *WorkflowJob `json:"workflow_job,omitempty"` + + Action *string `json:"action,omitempty"` + + // The following fields are only populated by Webhook events. + + // Org is not nil when the webhook is configured for an organization or the event + // occurs from activity in a repository owned by an organization. + Org *Organization `json:"organization,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Deployment *Deployment `json:"deployment,omitempty"` +} + +// WorkflowRunEvent is triggered when a GitHub Actions workflow run is requested or completed. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#workflow_run +type WorkflowRunEvent struct { + Action *string `json:"action,omitempty"` + Workflow *Workflow `json:"workflow,omitempty"` + WorkflowRun *WorkflowRun `json:"workflow_run,omitempty"` + + // The following fields are only populated by Webhook events. + Org *Organization `json:"organization,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// SecurityAdvisory represents the advisory object in SecurityAdvisoryEvent payload. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#security_advisory +type SecurityAdvisory struct { + CVSS *AdvisoryCVSS `json:"cvss,omitempty"` + CWEs []*AdvisoryCWEs `json:"cwes,omitempty"` + GHSAID *string `json:"ghsa_id,omitempty"` + Summary *string `json:"summary,omitempty"` + Description *string `json:"description,omitempty"` + Severity *string `json:"severity,omitempty"` + Identifiers []*AdvisoryIdentifier `json:"identifiers,omitempty"` + References []*AdvisoryReference `json:"references,omitempty"` + PublishedAt *Timestamp `json:"published_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + WithdrawnAt *Timestamp `json:"withdrawn_at,omitempty"` + Vulnerabilities []*AdvisoryVulnerability `json:"vulnerabilities,omitempty"` + CVEID *string `json:"cve_id,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + Author *User `json:"author,omitempty"` + Publisher *User `json:"publisher,omitempty"` + State *string `json:"state,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + ClosedAt *Timestamp `json:"closed_at,omitempty"` + Submission *SecurityAdvisorySubmission `json:"submission,omitempty"` + CWEIDs []string `json:"cwe_ids,omitempty"` + Credits []*RepoAdvisoryCredit `json:"credits,omitempty"` + CreditsDetailed []*RepoAdvisoryCreditDetailed `json:"credits_detailed,omitempty"` + CollaboratingUsers []*User `json:"collaborating_users,omitempty"` + CollaboratingTeams []*Team `json:"collaborating_teams,omitempty"` + PrivateFork *Repository `json:"private_fork,omitempty"` +} + +// AdvisoryIdentifier represents the identifier for a Security Advisory. +type AdvisoryIdentifier struct { + Value *string `json:"value,omitempty"` + Type *string `json:"type,omitempty"` +} + +// AdvisoryReference represents the reference url for the security advisory. +type AdvisoryReference struct { + URL *string `json:"url,omitempty"` +} + +// AdvisoryVulnerability represents the vulnerability object for a Security Advisory. +type AdvisoryVulnerability struct { + Package *VulnerabilityPackage `json:"package,omitempty"` + Severity *string `json:"severity,omitempty"` + VulnerableVersionRange *string `json:"vulnerable_version_range,omitempty"` + FirstPatchedVersion *FirstPatchedVersion `json:"first_patched_version,omitempty"` + + // PatchedVersions and VulnerableFunctions are used in the following APIs: + // - https://docs.github.com/rest/security-advisories/repository-advisories#list-repository-security-advisories-for-an-organization + // - https://docs.github.com/rest/security-advisories/repository-advisories#list-repository-security-advisories + PatchedVersions *string `json:"patched_versions,omitempty"` + VulnerableFunctions []string `json:"vulnerable_functions,omitempty"` +} + +// VulnerabilityPackage represents the package object for an Advisory Vulnerability. +type VulnerabilityPackage struct { + Ecosystem *string `json:"ecosystem,omitempty"` + Name *string `json:"name,omitempty"` +} + +// FirstPatchedVersion represents the identifier for the first patched version of that vulnerability. +type FirstPatchedVersion struct { + Identifier *string `json:"identifier,omitempty"` +} + +// SecurityAdvisoryEvent is triggered when a security-related vulnerability is found in software on GitHub. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#security_advisory +type SecurityAdvisoryEvent struct { + Action *string `json:"action,omitempty"` + SecurityAdvisory *SecurityAdvisory `json:"security_advisory,omitempty"` + + // The following fields are only populated by Webhook events. + Enterprise *Enterprise `json:"enterprise,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Repository *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` +} + +// CodeScanningAlertEvent is triggered when a code scanning finds a potential vulnerability or error in your code. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#code_scanning_alert +type CodeScanningAlertEvent struct { + Action *string `json:"action,omitempty"` + Alert *Alert `json:"alert,omitempty"` + Ref *string `json:"ref,omitempty"` + // CommitOID is the commit SHA of the code scanning alert + CommitOID *string `json:"commit_oid,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + + Installation *Installation `json:"installation,omitempty"` +} + +// SponsorshipEvent represents a sponsorship event in GitHub. +// +// GitHub API docs: https://docs.github.com/en/rest/overview/github-event-types?apiVersion=2022-11-28#sponsorshipevent +type SponsorshipEvent struct { + Action *string `json:"action,omitempty"` + EffectiveDate *string `json:"effective_date,omitempty"` + Changes *SponsorshipChanges `json:"changes,omitempty"` + Repository *Repository `json:"repository,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// SponsorshipChanges represents changes made to the sponsorship. +type SponsorshipChanges struct { + Tier *SponsorshipTier `json:"tier,omitempty"` + PrivacyLevel *string `json:"privacy_level,omitempty"` +} + +// SponsorshipTier represents the tier information of a sponsorship. +type SponsorshipTier struct { + From *string `json:"from,omitempty"` +} diff --git a/vendor/github.com/google/go-github/v68/github/gists.go b/vendor/github.com/google/go-github/v68/github/gists.go new file mode 100644 index 0000000000..08180c6d30 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/gists.go @@ -0,0 +1,397 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// GistsService handles communication with the Gist related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/gists +type GistsService service + +// Gist represents a GitHub's gist. +type Gist struct { + ID *string `json:"id,omitempty"` + Description *string `json:"description,omitempty"` + Public *bool `json:"public,omitempty"` + Owner *User `json:"owner,omitempty"` + Files map[GistFilename]GistFile `json:"files,omitempty"` + Comments *int `json:"comments,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + GitPullURL *string `json:"git_pull_url,omitempty"` + GitPushURL *string `json:"git_push_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +func (g Gist) String() string { + return Stringify(g) +} + +// GistFilename represents filename on a gist. +type GistFilename string + +// GistFile represents a file on a gist. +type GistFile struct { + Size *int `json:"size,omitempty"` + Filename *string `json:"filename,omitempty"` + Language *string `json:"language,omitempty"` + Type *string `json:"type,omitempty"` + RawURL *string `json:"raw_url,omitempty"` + Content *string `json:"content,omitempty"` +} + +func (g GistFile) String() string { + return Stringify(g) +} + +// GistCommit represents a commit on a gist. +type GistCommit struct { + URL *string `json:"url,omitempty"` + Version *string `json:"version,omitempty"` + User *User `json:"user,omitempty"` + ChangeStatus *CommitStats `json:"change_status,omitempty"` + CommittedAt *Timestamp `json:"committed_at,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +func (gc GistCommit) String() string { + return Stringify(gc) +} + +// GistFork represents a fork of a gist. +type GistFork struct { + URL *string `json:"url,omitempty"` + User *User `json:"user,omitempty"` + ID *string `json:"id,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +func (gf GistFork) String() string { + return Stringify(gf) +} + +// GistListOptions specifies the optional parameters to the +// GistsService.List, GistsService.ListAll, and GistsService.ListStarred methods. +type GistListOptions struct { + // Since filters Gists by time. + Since time.Time `url:"since,omitempty"` + + ListOptions +} + +// List gists for a user. Passing the empty string will list +// all public gists if called anonymously. However, if the call +// is authenticated, it will returns all gists for the authenticated +// user. +// +// GitHub API docs: https://docs.github.com/rest/gists/gists#list-gists-for-a-user +// GitHub API docs: https://docs.github.com/rest/gists/gists#list-gists-for-the-authenticated-user +// +//meta:operation GET /gists +//meta:operation GET /users/{username}/gists +func (s *GistsService) List(ctx context.Context, user string, opts *GistListOptions) ([]*Gist, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/gists", user) + } else { + u = "gists" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var gists []*Gist + resp, err := s.client.Do(ctx, req, &gists) + if err != nil { + return nil, resp, err + } + + return gists, resp, nil +} + +// ListAll lists all public gists. +// +// GitHub API docs: https://docs.github.com/rest/gists/gists#list-public-gists +// +//meta:operation GET /gists/public +func (s *GistsService) ListAll(ctx context.Context, opts *GistListOptions) ([]*Gist, *Response, error) { + u, err := addOptions("gists/public", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var gists []*Gist + resp, err := s.client.Do(ctx, req, &gists) + if err != nil { + return nil, resp, err + } + + return gists, resp, nil +} + +// ListStarred lists starred gists of authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/gists/gists#list-starred-gists +// +//meta:operation GET /gists/starred +func (s *GistsService) ListStarred(ctx context.Context, opts *GistListOptions) ([]*Gist, *Response, error) { + u, err := addOptions("gists/starred", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var gists []*Gist + resp, err := s.client.Do(ctx, req, &gists) + if err != nil { + return nil, resp, err + } + + return gists, resp, nil +} + +// Get a single gist. +// +// GitHub API docs: https://docs.github.com/rest/gists/gists#get-a-gist +// +//meta:operation GET /gists/{gist_id} +func (s *GistsService) Get(ctx context.Context, id string) (*Gist, *Response, error) { + u := fmt.Sprintf("gists/%v", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + gist := new(Gist) + resp, err := s.client.Do(ctx, req, gist) + if err != nil { + return nil, resp, err + } + + return gist, resp, nil +} + +// GetRevision gets a specific revision of a gist. +// +// GitHub API docs: https://docs.github.com/rest/gists/gists#get-a-gist-revision +// +//meta:operation GET /gists/{gist_id}/{sha} +func (s *GistsService) GetRevision(ctx context.Context, id, sha string) (*Gist, *Response, error) { + u := fmt.Sprintf("gists/%v/%v", id, sha) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + gist := new(Gist) + resp, err := s.client.Do(ctx, req, gist) + if err != nil { + return nil, resp, err + } + + return gist, resp, nil +} + +// Create a gist for authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/gists/gists#create-a-gist +// +//meta:operation POST /gists +func (s *GistsService) Create(ctx context.Context, gist *Gist) (*Gist, *Response, error) { + u := "gists" + req, err := s.client.NewRequest("POST", u, gist) + if err != nil { + return nil, nil, err + } + + g := new(Gist) + resp, err := s.client.Do(ctx, req, g) + if err != nil { + return nil, resp, err + } + + return g, resp, nil +} + +// Edit a gist. +// +// GitHub API docs: https://docs.github.com/rest/gists/gists#update-a-gist +// +//meta:operation PATCH /gists/{gist_id} +func (s *GistsService) Edit(ctx context.Context, id string, gist *Gist) (*Gist, *Response, error) { + u := fmt.Sprintf("gists/%v", id) + req, err := s.client.NewRequest("PATCH", u, gist) + if err != nil { + return nil, nil, err + } + + g := new(Gist) + resp, err := s.client.Do(ctx, req, g) + if err != nil { + return nil, resp, err + } + + return g, resp, nil +} + +// ListCommits lists commits of a gist. +// +// GitHub API docs: https://docs.github.com/rest/gists/gists#list-gist-commits +// +//meta:operation GET /gists/{gist_id}/commits +func (s *GistsService) ListCommits(ctx context.Context, id string, opts *ListOptions) ([]*GistCommit, *Response, error) { + u := fmt.Sprintf("gists/%v/commits", id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var gistCommits []*GistCommit + resp, err := s.client.Do(ctx, req, &gistCommits) + if err != nil { + return nil, resp, err + } + + return gistCommits, resp, nil +} + +// Delete a gist. +// +// GitHub API docs: https://docs.github.com/rest/gists/gists#delete-a-gist +// +//meta:operation DELETE /gists/{gist_id} +func (s *GistsService) Delete(ctx context.Context, id string) (*Response, error) { + u := fmt.Sprintf("gists/%v", id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Star a gist on behalf of authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/gists/gists#star-a-gist +// +//meta:operation PUT /gists/{gist_id}/star +func (s *GistsService) Star(ctx context.Context, id string) (*Response, error) { + u := fmt.Sprintf("gists/%v/star", id) + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Unstar a gist on a behalf of authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/gists/gists#unstar-a-gist +// +//meta:operation DELETE /gists/{gist_id}/star +func (s *GistsService) Unstar(ctx context.Context, id string) (*Response, error) { + u := fmt.Sprintf("gists/%v/star", id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// IsStarred checks if a gist is starred by authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/gists/gists#check-if-a-gist-is-starred +// +//meta:operation GET /gists/{gist_id}/star +func (s *GistsService) IsStarred(ctx context.Context, id string) (bool, *Response, error) { + u := fmt.Sprintf("gists/%v/star", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + starred, err := parseBoolResponse(err) + return starred, resp, err +} + +// Fork a gist. +// +// GitHub API docs: https://docs.github.com/rest/gists/gists#fork-a-gist +// +//meta:operation POST /gists/{gist_id}/forks +func (s *GistsService) Fork(ctx context.Context, id string) (*Gist, *Response, error) { + u := fmt.Sprintf("gists/%v/forks", id) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + g := new(Gist) + resp, err := s.client.Do(ctx, req, g) + if err != nil { + return nil, resp, err + } + + return g, resp, nil +} + +// ListForks lists forks of a gist. +// +// GitHub API docs: https://docs.github.com/rest/gists/gists#list-gist-forks +// +//meta:operation GET /gists/{gist_id}/forks +func (s *GistsService) ListForks(ctx context.Context, id string, opts *ListOptions) ([]*GistFork, *Response, error) { + u := fmt.Sprintf("gists/%v/forks", id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var gistForks []*GistFork + resp, err := s.client.Do(ctx, req, &gistForks) + if err != nil { + return nil, resp, err + } + + return gistForks, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/gists_comments.go b/vendor/github.com/google/go-github/v68/github/gists_comments.go new file mode 100644 index 0000000000..5e0614231b --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/gists_comments.go @@ -0,0 +1,128 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GistComment represents a Gist comment. +type GistComment struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + Body *string `json:"body,omitempty"` + User *User `json:"user,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` +} + +func (g GistComment) String() string { + return Stringify(g) +} + +// ListComments lists all comments for a gist. +// +// GitHub API docs: https://docs.github.com/rest/gists/comments#list-gist-comments +// +//meta:operation GET /gists/{gist_id}/comments +func (s *GistsService) ListComments(ctx context.Context, gistID string, opts *ListOptions) ([]*GistComment, *Response, error) { + u := fmt.Sprintf("gists/%v/comments", gistID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var comments []*GistComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// GetComment retrieves a single comment from a gist. +// +// GitHub API docs: https://docs.github.com/rest/gists/comments#get-a-gist-comment +// +//meta:operation GET /gists/{gist_id}/comments/{comment_id} +func (s *GistsService) GetComment(ctx context.Context, gistID string, commentID int64) (*GistComment, *Response, error) { + u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + c := new(GistComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// CreateComment creates a comment for a gist. +// +// GitHub API docs: https://docs.github.com/rest/gists/comments#create-a-gist-comment +// +//meta:operation POST /gists/{gist_id}/comments +func (s *GistsService) CreateComment(ctx context.Context, gistID string, comment *GistComment) (*GistComment, *Response, error) { + u := fmt.Sprintf("gists/%v/comments", gistID) + req, err := s.client.NewRequest("POST", u, comment) + if err != nil { + return nil, nil, err + } + + c := new(GistComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// EditComment edits an existing gist comment. +// +// GitHub API docs: https://docs.github.com/rest/gists/comments#update-a-gist-comment +// +//meta:operation PATCH /gists/{gist_id}/comments/{comment_id} +func (s *GistsService) EditComment(ctx context.Context, gistID string, commentID int64, comment *GistComment) (*GistComment, *Response, error) { + u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID) + req, err := s.client.NewRequest("PATCH", u, comment) + if err != nil { + return nil, nil, err + } + + c := new(GistComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// DeleteComment deletes a gist comment. +// +// GitHub API docs: https://docs.github.com/rest/gists/comments#delete-a-gist-comment +// +//meta:operation DELETE /gists/{gist_id}/comments/{comment_id} +func (s *GistsService) DeleteComment(ctx context.Context, gistID string, commentID int64) (*Response, error) { + u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/git.go b/vendor/github.com/google/go-github/v68/github/git.go new file mode 100644 index 0000000000..2ca835e1b5 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/git.go @@ -0,0 +1,12 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +// GitService handles communication with the git data related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/git/ +type GitService service diff --git a/vendor/github.com/google/go-github/v68/github/git_blobs.go b/vendor/github.com/google/go-github/v68/github/git_blobs.go new file mode 100644 index 0000000000..d890428889 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/git_blobs.go @@ -0,0 +1,88 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "context" + "fmt" +) + +// Blob represents a blob object. +type Blob struct { + Content *string `json:"content,omitempty"` + Encoding *string `json:"encoding,omitempty"` + SHA *string `json:"sha,omitempty"` + Size *int `json:"size,omitempty"` + URL *string `json:"url,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +// GetBlob fetches a blob from a repo given a SHA. +// +// GitHub API docs: https://docs.github.com/rest/git/blobs#get-a-blob +// +//meta:operation GET /repos/{owner}/{repo}/git/blobs/{file_sha} +func (s *GitService) GetBlob(ctx context.Context, owner string, repo string, sha string) (*Blob, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/blobs/%v", owner, repo, sha) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + blob := new(Blob) + resp, err := s.client.Do(ctx, req, blob) + if err != nil { + return nil, resp, err + } + + return blob, resp, nil +} + +// GetBlobRaw fetches a blob's contents from a repo. +// Unlike GetBlob, it returns the raw bytes rather than the base64-encoded data. +// +// GitHub API docs: https://docs.github.com/rest/git/blobs#get-a-blob +// +//meta:operation GET /repos/{owner}/{repo}/git/blobs/{file_sha} +func (s *GitService) GetBlobRaw(ctx context.Context, owner, repo, sha string) ([]byte, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/blobs/%v", owner, repo, sha) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", "application/vnd.github.v3.raw") + + var buf bytes.Buffer + resp, err := s.client.Do(ctx, req, &buf) + if err != nil { + return nil, resp, err + } + + return buf.Bytes(), resp, nil +} + +// CreateBlob creates a blob object. +// +// GitHub API docs: https://docs.github.com/rest/git/blobs#create-a-blob +// +//meta:operation POST /repos/{owner}/{repo}/git/blobs +func (s *GitService) CreateBlob(ctx context.Context, owner string, repo string, blob *Blob) (*Blob, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/blobs", owner, repo) + req, err := s.client.NewRequest("POST", u, blob) + if err != nil { + return nil, nil, err + } + + t := new(Blob) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/git_commits.go b/vendor/github.com/google/go-github/v68/github/git_commits.go new file mode 100644 index 0000000000..d7ed3ecbec --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/git_commits.go @@ -0,0 +1,224 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "context" + "errors" + "fmt" + "io" + "strings" +) + +// SignatureVerification represents GPG signature verification. +type SignatureVerification struct { + Verified *bool `json:"verified,omitempty"` + Reason *string `json:"reason,omitempty"` + Signature *string `json:"signature,omitempty"` + Payload *string `json:"payload,omitempty"` +} + +// MessageSigner is used by GitService.CreateCommit to sign a commit. +// +// To create a MessageSigner that signs a commit with a [golang.org/x/crypto/openpgp.Entity], +// or [github.com/ProtonMail/go-crypto/openpgp.Entity], use: +// +// commit.Signer = github.MessageSignerFunc(func(w io.Writer, r io.Reader) error { +// return openpgp.ArmoredDetachSign(w, openpgpEntity, r, nil) +// }) +type MessageSigner interface { + Sign(w io.Writer, r io.Reader) error +} + +// MessageSignerFunc is a single function implementation of MessageSigner. +type MessageSignerFunc func(w io.Writer, r io.Reader) error + +func (f MessageSignerFunc) Sign(w io.Writer, r io.Reader) error { + return f(w, r) +} + +// Commit represents a GitHub commit. +type Commit struct { + SHA *string `json:"sha,omitempty"` + Author *CommitAuthor `json:"author,omitempty"` + Committer *CommitAuthor `json:"committer,omitempty"` + Message *string `json:"message,omitempty"` + Tree *Tree `json:"tree,omitempty"` + Parents []*Commit `json:"parents,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + URL *string `json:"url,omitempty"` + Verification *SignatureVerification `json:"verification,omitempty"` + NodeID *string `json:"node_id,omitempty"` + + // CommentCount is the number of GitHub comments on the commit. This + // is only populated for requests that fetch GitHub data like + // Pulls.ListCommits, Repositories.ListCommits, etc. + CommentCount *int `json:"comment_count,omitempty"` +} + +func (c Commit) String() string { + return Stringify(c) +} + +// CommitAuthor represents the author or committer of a commit. The commit +// author may not correspond to a GitHub User. +type CommitAuthor struct { + Date *Timestamp `json:"date,omitempty"` + Name *string `json:"name,omitempty"` + Email *string `json:"email,omitempty"` + + // The following fields are only populated by Webhook events. + Login *string `json:"username,omitempty"` // Renamed for go-github consistency. +} + +func (c CommitAuthor) String() string { + return Stringify(c) +} + +// GetCommit fetches the Commit object for a given SHA. +// +// GitHub API docs: https://docs.github.com/rest/git/commits#get-a-commit-object +// +//meta:operation GET /repos/{owner}/{repo}/git/commits/{commit_sha} +func (s *GitService) GetCommit(ctx context.Context, owner string, repo string, sha string) (*Commit, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/commits/%v", owner, repo, sha) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + c := new(Commit) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// createCommit represents the body of a CreateCommit request. +type createCommit struct { + Author *CommitAuthor `json:"author,omitempty"` + Committer *CommitAuthor `json:"committer,omitempty"` + Message *string `json:"message,omitempty"` + Tree *string `json:"tree,omitempty"` + Parents []string `json:"parents,omitempty"` + Signature *string `json:"signature,omitempty"` +} + +type CreateCommitOptions struct { + // CreateCommit will sign the commit with this signer. See MessageSigner doc for more details. + // Ignored on commits where Verification.Signature is defined. + Signer MessageSigner +} + +// CreateCommit creates a new commit in a repository. +// commit must not be nil. +// +// The commit.Committer is optional and will be filled with the commit.Author +// data if omitted. If the commit.Author is omitted, it will be filled in with +// the authenticated user’s information and the current date. +// +// GitHub API docs: https://docs.github.com/rest/git/commits#create-a-commit +// +//meta:operation POST /repos/{owner}/{repo}/git/commits +func (s *GitService) CreateCommit(ctx context.Context, owner string, repo string, commit *Commit, opts *CreateCommitOptions) (*Commit, *Response, error) { + if commit == nil { + return nil, nil, errors.New("commit must be provided") + } + if opts == nil { + opts = &CreateCommitOptions{} + } + + u := fmt.Sprintf("repos/%v/%v/git/commits", owner, repo) + + parents := make([]string, len(commit.Parents)) + for i, parent := range commit.Parents { + parents[i] = *parent.SHA + } + + body := &createCommit{ + Author: commit.Author, + Committer: commit.Committer, + Message: commit.Message, + Parents: parents, + } + if commit.Tree != nil { + body.Tree = commit.Tree.SHA + } + switch { + case commit.Verification != nil: + body.Signature = commit.Verification.Signature + case opts.Signer != nil: + signature, err := createSignature(opts.Signer, body) + if err != nil { + return nil, nil, err + } + body.Signature = &signature + } + + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + c := new(Commit) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +func createSignature(signer MessageSigner, commit *createCommit) (string, error) { + if signer == nil { + return "", errors.New("createSignature: invalid parameters") + } + + message, err := createSignatureMessage(commit) + if err != nil { + return "", err + } + + var writer bytes.Buffer + err = signer.Sign(&writer, strings.NewReader(message)) + if err != nil { + return "", err + } + + return writer.String(), nil +} + +func createSignatureMessage(commit *createCommit) (string, error) { + if commit == nil || commit.Message == nil || *commit.Message == "" || commit.Author == nil { + return "", errors.New("createSignatureMessage: invalid parameters") + } + + var message []string + + if commit.Tree != nil { + message = append(message, fmt.Sprintf("tree %s", *commit.Tree)) + } + + for _, parent := range commit.Parents { + message = append(message, fmt.Sprintf("parent %s", parent)) + } + + message = append(message, fmt.Sprintf("author %s <%s> %d %s", commit.Author.GetName(), commit.Author.GetEmail(), commit.Author.GetDate().Unix(), commit.Author.GetDate().Format("-0700"))) + + committer := commit.Committer + if committer == nil { + committer = commit.Author + } + + // There needs to be a double newline after committer + message = append(message, fmt.Sprintf("committer %s <%s> %d %s\n", committer.GetName(), committer.GetEmail(), committer.GetDate().Unix(), committer.GetDate().Format("-0700"))) + message = append(message, *commit.Message) + + return strings.Join(message, "\n"), nil +} diff --git a/vendor/github.com/google/go-github/v68/github/git_refs.go b/vendor/github.com/google/go-github/v68/github/git_refs.go new file mode 100644 index 0000000000..91eb6dd43f --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/git_refs.go @@ -0,0 +1,185 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/url" + "strings" +) + +// Reference represents a GitHub reference. +type Reference struct { + Ref *string `json:"ref"` + URL *string `json:"url"` + Object *GitObject `json:"object"` + NodeID *string `json:"node_id,omitempty"` +} + +func (r Reference) String() string { + return Stringify(r) +} + +// GitObject represents a Git object. +type GitObject struct { + Type *string `json:"type"` + SHA *string `json:"sha"` + URL *string `json:"url"` +} + +func (o GitObject) String() string { + return Stringify(o) +} + +// createRefRequest represents the payload for creating a reference. +type createRefRequest struct { + Ref *string `json:"ref"` + SHA *string `json:"sha"` +} + +// updateRefRequest represents the payload for updating a reference. +type updateRefRequest struct { + SHA *string `json:"sha"` + Force *bool `json:"force"` +} + +// GetRef fetches a single reference in a repository. +// +// GitHub API docs: https://docs.github.com/rest/git/refs#get-a-reference +// +//meta:operation GET /repos/{owner}/{repo}/git/ref/{ref} +func (s *GitService) GetRef(ctx context.Context, owner string, repo string, ref string) (*Reference, *Response, error) { + ref = strings.TrimPrefix(ref, "refs/") + u := fmt.Sprintf("repos/%v/%v/git/ref/%v", owner, repo, refURLEscape(ref)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + r := new(Reference) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// refURLEscape escapes every path segment of the given ref. Those must +// not contain escaped "/" - as "%2F" - or github will not recognize it. +func refURLEscape(ref string) string { + parts := strings.Split(ref, "/") + for i, s := range parts { + parts[i] = url.PathEscape(s) + } + return strings.Join(parts, "/") +} + +// ReferenceListOptions specifies optional parameters to the +// GitService.ListMatchingRefs method. +type ReferenceListOptions struct { + Ref string `url:"-"` + + ListOptions +} + +// ListMatchingRefs lists references in a repository that match a supplied ref. +// Use an empty ref to list all references. +// +// GitHub API docs: https://docs.github.com/rest/git/refs#list-matching-references +// +//meta:operation GET /repos/{owner}/{repo}/git/matching-refs/{ref} +func (s *GitService) ListMatchingRefs(ctx context.Context, owner, repo string, opts *ReferenceListOptions) ([]*Reference, *Response, error) { + var ref string + if opts != nil { + ref = strings.TrimPrefix(opts.Ref, "refs/") + } + u := fmt.Sprintf("repos/%v/%v/git/matching-refs/%v", owner, repo, refURLEscape(ref)) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var rs []*Reference + resp, err := s.client.Do(ctx, req, &rs) + if err != nil { + return nil, resp, err + } + + return rs, resp, nil +} + +// CreateRef creates a new ref in a repository. +// +// GitHub API docs: https://docs.github.com/rest/git/refs#create-a-reference +// +//meta:operation POST /repos/{owner}/{repo}/git/refs +func (s *GitService) CreateRef(ctx context.Context, owner string, repo string, ref *Reference) (*Reference, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/refs", owner, repo) + req, err := s.client.NewRequest("POST", u, &createRefRequest{ + // back-compat with previous behavior that didn't require 'refs/' prefix + Ref: Ptr("refs/" + strings.TrimPrefix(*ref.Ref, "refs/")), + SHA: ref.Object.SHA, + }) + if err != nil { + return nil, nil, err + } + + r := new(Reference) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// UpdateRef updates an existing ref in a repository. +// +// GitHub API docs: https://docs.github.com/rest/git/refs#update-a-reference +// +//meta:operation PATCH /repos/{owner}/{repo}/git/refs/{ref} +func (s *GitService) UpdateRef(ctx context.Context, owner string, repo string, ref *Reference, force bool) (*Reference, *Response, error) { + refPath := strings.TrimPrefix(*ref.Ref, "refs/") + u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, refURLEscape(refPath)) + req, err := s.client.NewRequest("PATCH", u, &updateRefRequest{ + SHA: ref.Object.SHA, + Force: &force, + }) + if err != nil { + return nil, nil, err + } + + r := new(Reference) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// DeleteRef deletes a ref from a repository. +// +// GitHub API docs: https://docs.github.com/rest/git/refs#delete-a-reference +// +//meta:operation DELETE /repos/{owner}/{repo}/git/refs/{ref} +func (s *GitService) DeleteRef(ctx context.Context, owner string, repo string, ref string) (*Response, error) { + ref = strings.TrimPrefix(ref, "refs/") + u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, refURLEscape(ref)) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/git_tags.go b/vendor/github.com/google/go-github/v68/github/git_tags.go new file mode 100644 index 0000000000..67321566f7 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/git_tags.go @@ -0,0 +1,88 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Tag represents a tag object. +type Tag struct { + Tag *string `json:"tag,omitempty"` + SHA *string `json:"sha,omitempty"` + URL *string `json:"url,omitempty"` + Message *string `json:"message,omitempty"` + Tagger *CommitAuthor `json:"tagger,omitempty"` + Object *GitObject `json:"object,omitempty"` + Verification *SignatureVerification `json:"verification,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +// createTagRequest represents the body of a CreateTag request. This is mostly +// identical to Tag with the exception that the object SHA and Type are +// top-level fields, rather than being nested inside a JSON object. +type createTagRequest struct { + Tag *string `json:"tag,omitempty"` + Message *string `json:"message,omitempty"` + Object *string `json:"object,omitempty"` + Type *string `json:"type,omitempty"` + Tagger *CommitAuthor `json:"tagger,omitempty"` +} + +// GetTag fetches a tag from a repo given a SHA. +// +// GitHub API docs: https://docs.github.com/rest/git/tags#get-a-tag +// +//meta:operation GET /repos/{owner}/{repo}/git/tags/{tag_sha} +func (s *GitService) GetTag(ctx context.Context, owner string, repo string, sha string) (*Tag, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/tags/%v", owner, repo, sha) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + tag := new(Tag) + resp, err := s.client.Do(ctx, req, tag) + if err != nil { + return nil, resp, err + } + + return tag, resp, nil +} + +// CreateTag creates a tag object. +// +// GitHub API docs: https://docs.github.com/rest/git/tags#create-a-tag-object +// +//meta:operation POST /repos/{owner}/{repo}/git/tags +func (s *GitService) CreateTag(ctx context.Context, owner string, repo string, tag *Tag) (*Tag, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/tags", owner, repo) + + // convert Tag into a createTagRequest + tagRequest := &createTagRequest{ + Tag: tag.Tag, + Message: tag.Message, + Tagger: tag.Tagger, + } + if tag.Object != nil { + tagRequest.Object = tag.Object.SHA + tagRequest.Type = tag.Object.Type + } + + req, err := s.client.NewRequest("POST", u, tagRequest) + if err != nil { + return nil, nil, err + } + + t := new(Tag) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/git_trees.go b/vendor/github.com/google/go-github/v68/github/git_trees.go new file mode 100644 index 0000000000..b8eed58e13 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/git_trees.go @@ -0,0 +1,166 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" +) + +// Tree represents a GitHub tree. +type Tree struct { + SHA *string `json:"sha,omitempty"` + Entries []*TreeEntry `json:"tree,omitempty"` + + // Truncated is true if the number of items in the tree + // exceeded GitHub's maximum limit and the Entries were truncated + // in the response. Only populated for requests that fetch + // trees like Git.GetTree. + Truncated *bool `json:"truncated,omitempty"` +} + +func (t Tree) String() string { + return Stringify(t) +} + +// TreeEntry represents the contents of a tree structure. TreeEntry can +// represent either a blob, a commit (in the case of a submodule), or another +// tree. +type TreeEntry struct { + SHA *string `json:"sha,omitempty"` + Path *string `json:"path,omitempty"` + Mode *string `json:"mode,omitempty"` + Type *string `json:"type,omitempty"` + Size *int `json:"size,omitempty"` + Content *string `json:"content,omitempty"` + URL *string `json:"url,omitempty"` +} + +func (t TreeEntry) String() string { + return Stringify(t) +} + +// treeEntryWithFileDelete is used internally to delete a file whose +// Content and SHA fields are empty. It does this by removing the "omitempty" +// tag modifier on the SHA field which causes the GitHub API to receive +// {"sha":null} and thereby delete the file. +type treeEntryWithFileDelete struct { + SHA *string `json:"sha"` + Path *string `json:"path,omitempty"` + Mode *string `json:"mode,omitempty"` + Type *string `json:"type,omitempty"` + Size *int `json:"size,omitempty"` + Content *string `json:"content,omitempty"` + URL *string `json:"url,omitempty"` +} + +func (t *TreeEntry) MarshalJSON() ([]byte, error) { + if t.SHA == nil && t.Content == nil { + return json.Marshal(struct { + SHA *string `json:"sha"` + Path *string `json:"path,omitempty"` + Mode *string `json:"mode,omitempty"` + Type *string `json:"type,omitempty"` + }{ + nil, + t.Path, + t.Mode, + t.Type, + }) + } + return json.Marshal(struct { + SHA *string `json:"sha,omitempty"` + Path *string `json:"path,omitempty"` + Mode *string `json:"mode,omitempty"` + Type *string `json:"type,omitempty"` + Size *int `json:"size,omitempty"` + Content *string `json:"content,omitempty"` + URL *string `json:"url,omitempty"` + }{ + SHA: t.SHA, + Path: t.Path, + Mode: t.Mode, + Type: t.Type, + Size: t.Size, + Content: t.Content, + URL: t.URL, + }) +} + +// GetTree fetches the Tree object for a given sha hash from a repository. +// +// GitHub API docs: https://docs.github.com/rest/git/trees#get-a-tree +// +//meta:operation GET /repos/{owner}/{repo}/git/trees/{tree_sha} +func (s *GitService) GetTree(ctx context.Context, owner string, repo string, sha string, recursive bool) (*Tree, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/trees/%v", owner, repo, sha) + if recursive { + u += "?recursive=1" + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + t := new(Tree) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// createTree represents the body of a CreateTree request. +type createTree struct { + BaseTree string `json:"base_tree,omitempty"` + Entries []interface{} `json:"tree"` +} + +// CreateTree creates a new tree in a repository. If both a tree and a nested +// path modifying that tree are specified, it will overwrite the contents of +// that tree with the new path contents and write a new tree out. +// +// GitHub API docs: https://docs.github.com/rest/git/trees#create-a-tree +// +//meta:operation POST /repos/{owner}/{repo}/git/trees +func (s *GitService) CreateTree(ctx context.Context, owner string, repo string, baseTree string, entries []*TreeEntry) (*Tree, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/trees", owner, repo) + + newEntries := make([]interface{}, 0, len(entries)) + for _, entry := range entries { + if entry.Content == nil && entry.SHA == nil { + newEntries = append(newEntries, treeEntryWithFileDelete{ + Path: entry.Path, + Mode: entry.Mode, + Type: entry.Type, + Size: entry.Size, + URL: entry.URL, + }) + continue + } + newEntries = append(newEntries, entry) + } + + body := &createTree{ + BaseTree: baseTree, + Entries: newEntries, + } + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + t := new(Tree) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/github-accessors.go b/vendor/github.com/google/go-github/v68/github/github-accessors.go new file mode 100644 index 0000000000..0800c02c6c --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/github-accessors.go @@ -0,0 +1,26951 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by gen-accessors; DO NOT EDIT. +// Instead, please run "go generate ./..." as described here: +// https://github.com/google/go-github/blob/master/CONTRIBUTING.md#submitting-a-patch + +package github + +import ( + "encoding/json" + "time" +) + +// GetRetryAfter returns the RetryAfter field if it's non-nil, zero value otherwise. +func (a *AbuseRateLimitError) GetRetryAfter() time.Duration { + if a == nil || a.RetryAfter == nil { + return 0 + } + return *a.RetryAfter +} + +// GetGithubOwnedAllowed returns the GithubOwnedAllowed field if it's non-nil, zero value otherwise. +func (a *ActionsAllowed) GetGithubOwnedAllowed() bool { + if a == nil || a.GithubOwnedAllowed == nil { + return false + } + return *a.GithubOwnedAllowed +} + +// GetVerifiedAllowed returns the VerifiedAllowed field if it's non-nil, zero value otherwise. +func (a *ActionsAllowed) GetVerifiedAllowed() bool { + if a == nil || a.VerifiedAllowed == nil { + return false + } + return *a.VerifiedAllowed +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *ActionsCache) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *ActionsCache) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (a *ActionsCache) GetKey() string { + if a == nil || a.Key == nil { + return "" + } + return *a.Key +} + +// GetLastAccessedAt returns the LastAccessedAt field if it's non-nil, zero value otherwise. +func (a *ActionsCache) GetLastAccessedAt() Timestamp { + if a == nil || a.LastAccessedAt == nil { + return Timestamp{} + } + return *a.LastAccessedAt +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (a *ActionsCache) GetRef() string { + if a == nil || a.Ref == nil { + return "" + } + return *a.Ref +} + +// GetSizeInBytes returns the SizeInBytes field if it's non-nil, zero value otherwise. +func (a *ActionsCache) GetSizeInBytes() int64 { + if a == nil || a.SizeInBytes == nil { + return 0 + } + return *a.SizeInBytes +} + +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (a *ActionsCache) GetVersion() string { + if a == nil || a.Version == nil { + return "" + } + return *a.Version +} + +// GetDirection returns the Direction field if it's non-nil, zero value otherwise. +func (a *ActionsCacheListOptions) GetDirection() string { + if a == nil || a.Direction == nil { + return "" + } + return *a.Direction +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (a *ActionsCacheListOptions) GetKey() string { + if a == nil || a.Key == nil { + return "" + } + return *a.Key +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (a *ActionsCacheListOptions) GetRef() string { + if a == nil || a.Ref == nil { + return "" + } + return *a.Ref +} + +// GetSort returns the Sort field if it's non-nil, zero value otherwise. +func (a *ActionsCacheListOptions) GetSort() string { + if a == nil || a.Sort == nil { + return "" + } + return *a.Sort +} + +// GetAllowedActions returns the AllowedActions field if it's non-nil, zero value otherwise. +func (a *ActionsPermissions) GetAllowedActions() string { + if a == nil || a.AllowedActions == nil { + return "" + } + return *a.AllowedActions +} + +// GetEnabledRepositories returns the EnabledRepositories field if it's non-nil, zero value otherwise. +func (a *ActionsPermissions) GetEnabledRepositories() string { + if a == nil || a.EnabledRepositories == nil { + return "" + } + return *a.EnabledRepositories +} + +// GetSelectedActionsURL returns the SelectedActionsURL field if it's non-nil, zero value otherwise. +func (a *ActionsPermissions) GetSelectedActionsURL() string { + if a == nil || a.SelectedActionsURL == nil { + return "" + } + return *a.SelectedActionsURL +} + +// GetAllowedActions returns the AllowedActions field if it's non-nil, zero value otherwise. +func (a *ActionsPermissionsEnterprise) GetAllowedActions() string { + if a == nil || a.AllowedActions == nil { + return "" + } + return *a.AllowedActions +} + +// GetEnabledOrganizations returns the EnabledOrganizations field if it's non-nil, zero value otherwise. +func (a *ActionsPermissionsEnterprise) GetEnabledOrganizations() string { + if a == nil || a.EnabledOrganizations == nil { + return "" + } + return *a.EnabledOrganizations +} + +// GetSelectedActionsURL returns the SelectedActionsURL field if it's non-nil, zero value otherwise. +func (a *ActionsPermissionsEnterprise) GetSelectedActionsURL() string { + if a == nil || a.SelectedActionsURL == nil { + return "" + } + return *a.SelectedActionsURL +} + +// GetAllowedActions returns the AllowedActions field if it's non-nil, zero value otherwise. +func (a *ActionsPermissionsRepository) GetAllowedActions() string { + if a == nil || a.AllowedActions == nil { + return "" + } + return *a.AllowedActions +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (a *ActionsPermissionsRepository) GetEnabled() bool { + if a == nil || a.Enabled == nil { + return false + } + return *a.Enabled +} + +// GetSelectedActionsURL returns the SelectedActionsURL field if it's non-nil, zero value otherwise. +func (a *ActionsPermissionsRepository) GetSelectedActionsURL() string { + if a == nil || a.SelectedActionsURL == nil { + return "" + } + return *a.SelectedActionsURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *ActionsVariable) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetSelectedRepositoriesURL returns the SelectedRepositoriesURL field if it's non-nil, zero value otherwise. +func (a *ActionsVariable) GetSelectedRepositoriesURL() string { + if a == nil || a.SelectedRepositoriesURL == nil { + return "" + } + return *a.SelectedRepositoriesURL +} + +// GetSelectedRepositoryIDs returns the SelectedRepositoryIDs field. +func (a *ActionsVariable) GetSelectedRepositoryIDs() *SelectedRepoIDs { + if a == nil { + return nil + } + return a.SelectedRepositoryIDs +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (a *ActionsVariable) GetUpdatedAt() Timestamp { + if a == nil || a.UpdatedAt == nil { + return Timestamp{} + } + return *a.UpdatedAt +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (a *ActionsVariable) GetVisibility() string { + if a == nil || a.Visibility == nil { + return "" + } + return *a.Visibility +} + +// GetCountryCode returns the CountryCode field if it's non-nil, zero value otherwise. +func (a *ActorLocation) GetCountryCode() string { + if a == nil || a.CountryCode == nil { + return "" + } + return *a.CountryCode +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (a *AdminEnforcedChanges) GetFrom() bool { + if a == nil || a.From == nil { + return false + } + return *a.From +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (a *AdminEnforcement) GetURL() string { + if a == nil || a.URL == nil { + return "" + } + return *a.URL +} + +// GetComments returns the Comments field. +func (a *AdminStats) GetComments() *CommentStats { + if a == nil { + return nil + } + return a.Comments +} + +// GetGists returns the Gists field. +func (a *AdminStats) GetGists() *GistStats { + if a == nil { + return nil + } + return a.Gists +} + +// GetHooks returns the Hooks field. +func (a *AdminStats) GetHooks() *HookStats { + if a == nil { + return nil + } + return a.Hooks +} + +// GetIssues returns the Issues field. +func (a *AdminStats) GetIssues() *IssueStats { + if a == nil { + return nil + } + return a.Issues +} + +// GetMilestones returns the Milestones field. +func (a *AdminStats) GetMilestones() *MilestoneStats { + if a == nil { + return nil + } + return a.Milestones +} + +// GetOrgs returns the Orgs field. +func (a *AdminStats) GetOrgs() *OrgStats { + if a == nil { + return nil + } + return a.Orgs +} + +// GetPages returns the Pages field. +func (a *AdminStats) GetPages() *PageStats { + if a == nil { + return nil + } + return a.Pages +} + +// GetPulls returns the Pulls field. +func (a *AdminStats) GetPulls() *PullStats { + if a == nil { + return nil + } + return a.Pulls +} + +// GetRepos returns the Repos field. +func (a *AdminStats) GetRepos() *RepoStats { + if a == nil { + return nil + } + return a.Repos +} + +// GetUsers returns the Users field. +func (a *AdminStats) GetUsers() *UserStats { + if a == nil { + return nil + } + return a.Users +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (a *AdvancedSecurity) GetStatus() string { + if a == nil || a.Status == nil { + return "" + } + return *a.Status +} + +// GetLastPushedDate returns the LastPushedDate field if it's non-nil, zero value otherwise. +func (a *AdvancedSecurityCommittersBreakdown) GetLastPushedDate() string { + if a == nil || a.LastPushedDate == nil { + return "" + } + return *a.LastPushedDate +} + +// GetUserLogin returns the UserLogin field if it's non-nil, zero value otherwise. +func (a *AdvancedSecurityCommittersBreakdown) GetUserLogin() string { + if a == nil || a.UserLogin == nil { + return "" + } + return *a.UserLogin +} + +// GetScore returns the Score field. +func (a *AdvisoryCVSS) GetScore() *float64 { + if a == nil { + return nil + } + return a.Score +} + +// GetVectorString returns the VectorString field if it's non-nil, zero value otherwise. +func (a *AdvisoryCVSS) GetVectorString() string { + if a == nil || a.VectorString == nil { + return "" + } + return *a.VectorString +} + +// GetCWEID returns the CWEID field if it's non-nil, zero value otherwise. +func (a *AdvisoryCWEs) GetCWEID() string { + if a == nil || a.CWEID == nil { + return "" + } + return *a.CWEID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (a *AdvisoryCWEs) GetName() string { + if a == nil || a.Name == nil { + return "" + } + return *a.Name +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (a *AdvisoryIdentifier) GetType() string { + if a == nil || a.Type == nil { + return "" + } + return *a.Type +} + +// GetValue returns the Value field if it's non-nil, zero value otherwise. +func (a *AdvisoryIdentifier) GetValue() string { + if a == nil || a.Value == nil { + return "" + } + return *a.Value +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (a *AdvisoryReference) GetURL() string { + if a == nil || a.URL == nil { + return "" + } + return *a.URL +} + +// GetFirstPatchedVersion returns the FirstPatchedVersion field. +func (a *AdvisoryVulnerability) GetFirstPatchedVersion() *FirstPatchedVersion { + if a == nil { + return nil + } + return a.FirstPatchedVersion +} + +// GetPackage returns the Package field. +func (a *AdvisoryVulnerability) GetPackage() *VulnerabilityPackage { + if a == nil { + return nil + } + return a.Package +} + +// GetPatchedVersions returns the PatchedVersions field if it's non-nil, zero value otherwise. +func (a *AdvisoryVulnerability) GetPatchedVersions() string { + if a == nil || a.PatchedVersions == nil { + return "" + } + return *a.PatchedVersions +} + +// GetSeverity returns the Severity field if it's non-nil, zero value otherwise. +func (a *AdvisoryVulnerability) GetSeverity() string { + if a == nil || a.Severity == nil { + return "" + } + return *a.Severity +} + +// GetVulnerableVersionRange returns the VulnerableVersionRange field if it's non-nil, zero value otherwise. +func (a *AdvisoryVulnerability) GetVulnerableVersionRange() string { + if a == nil || a.VulnerableVersionRange == nil { + return "" + } + return *a.VulnerableVersionRange +} + +// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. +func (a *Alert) GetClosedAt() Timestamp { + if a == nil || a.ClosedAt == nil { + return Timestamp{} + } + return *a.ClosedAt +} + +// GetClosedBy returns the ClosedBy field. +func (a *Alert) GetClosedBy() *User { + if a == nil { + return nil + } + return a.ClosedBy +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *Alert) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetDismissedAt returns the DismissedAt field if it's non-nil, zero value otherwise. +func (a *Alert) GetDismissedAt() Timestamp { + if a == nil || a.DismissedAt == nil { + return Timestamp{} + } + return *a.DismissedAt +} + +// GetDismissedBy returns the DismissedBy field. +func (a *Alert) GetDismissedBy() *User { + if a == nil { + return nil + } + return a.DismissedBy +} + +// GetDismissedComment returns the DismissedComment field if it's non-nil, zero value otherwise. +func (a *Alert) GetDismissedComment() string { + if a == nil || a.DismissedComment == nil { + return "" + } + return *a.DismissedComment +} + +// GetDismissedReason returns the DismissedReason field if it's non-nil, zero value otherwise. +func (a *Alert) GetDismissedReason() string { + if a == nil || a.DismissedReason == nil { + return "" + } + return *a.DismissedReason +} + +// GetFixedAt returns the FixedAt field if it's non-nil, zero value otherwise. +func (a *Alert) GetFixedAt() Timestamp { + if a == nil || a.FixedAt == nil { + return Timestamp{} + } + return *a.FixedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (a *Alert) GetHTMLURL() string { + if a == nil || a.HTMLURL == nil { + return "" + } + return *a.HTMLURL +} + +// GetInstancesURL returns the InstancesURL field if it's non-nil, zero value otherwise. +func (a *Alert) GetInstancesURL() string { + if a == nil || a.InstancesURL == nil { + return "" + } + return *a.InstancesURL +} + +// GetMostRecentInstance returns the MostRecentInstance field. +func (a *Alert) GetMostRecentInstance() *MostRecentInstance { + if a == nil { + return nil + } + return a.MostRecentInstance +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (a *Alert) GetNumber() int { + if a == nil || a.Number == nil { + return 0 + } + return *a.Number +} + +// GetRepository returns the Repository field. +func (a *Alert) GetRepository() *Repository { + if a == nil { + return nil + } + return a.Repository +} + +// GetRule returns the Rule field. +func (a *Alert) GetRule() *Rule { + if a == nil { + return nil + } + return a.Rule +} + +// GetRuleDescription returns the RuleDescription field if it's non-nil, zero value otherwise. +func (a *Alert) GetRuleDescription() string { + if a == nil || a.RuleDescription == nil { + return "" + } + return *a.RuleDescription +} + +// GetRuleID returns the RuleID field if it's non-nil, zero value otherwise. +func (a *Alert) GetRuleID() string { + if a == nil || a.RuleID == nil { + return "" + } + return *a.RuleID +} + +// GetRuleSeverity returns the RuleSeverity field if it's non-nil, zero value otherwise. +func (a *Alert) GetRuleSeverity() string { + if a == nil || a.RuleSeverity == nil { + return "" + } + return *a.RuleSeverity +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (a *Alert) GetState() string { + if a == nil || a.State == nil { + return "" + } + return *a.State +} + +// GetTool returns the Tool field. +func (a *Alert) GetTool() *Tool { + if a == nil { + return nil + } + return a.Tool +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (a *Alert) GetUpdatedAt() Timestamp { + if a == nil || a.UpdatedAt == nil { + return Timestamp{} + } + return *a.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (a *Alert) GetURL() string { + if a == nil || a.URL == nil { + return "" + } + return *a.URL +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (a *AllowDeletionsEnforcementLevelChanges) GetFrom() string { + if a == nil || a.From == nil { + return "" + } + return *a.From +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (a *AllowForkSyncing) GetEnabled() bool { + if a == nil || a.Enabled == nil { + return false + } + return *a.Enabled +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (a *AnalysesListOptions) GetRef() string { + if a == nil || a.Ref == nil { + return "" + } + return *a.Ref +} + +// GetSarifID returns the SarifID field if it's non-nil, zero value otherwise. +func (a *AnalysesListOptions) GetSarifID() string { + if a == nil || a.SarifID == nil { + return "" + } + return *a.SarifID +} + +// GetDomains returns the Domains field. +func (a *APIMeta) GetDomains() *APIMetaDomains { + if a == nil { + return nil + } + return a.Domains +} + +// GetSSHKeyFingerprints returns the SSHKeyFingerprints map if it's non-nil, an empty map otherwise. +func (a *APIMeta) GetSSHKeyFingerprints() map[string]string { + if a == nil || a.SSHKeyFingerprints == nil { + return map[string]string{} + } + return a.SSHKeyFingerprints +} + +// GetVerifiablePasswordAuthentication returns the VerifiablePasswordAuthentication field if it's non-nil, zero value otherwise. +func (a *APIMeta) GetVerifiablePasswordAuthentication() bool { + if a == nil || a.VerifiablePasswordAuthentication == nil { + return false + } + return *a.VerifiablePasswordAuthentication +} + +// GetArtifactAttestations returns the ArtifactAttestations field. +func (a *APIMetaDomains) GetArtifactAttestations() *APIMetaArtifactAttestations { + if a == nil { + return nil + } + return a.ArtifactAttestations +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *App) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (a *App) GetDescription() string { + if a == nil || a.Description == nil { + return "" + } + return *a.Description +} + +// GetExternalURL returns the ExternalURL field if it's non-nil, zero value otherwise. +func (a *App) GetExternalURL() string { + if a == nil || a.ExternalURL == nil { + return "" + } + return *a.ExternalURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (a *App) GetHTMLURL() string { + if a == nil || a.HTMLURL == nil { + return "" + } + return *a.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *App) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetInstallationsCount returns the InstallationsCount field if it's non-nil, zero value otherwise. +func (a *App) GetInstallationsCount() int { + if a == nil || a.InstallationsCount == nil { + return 0 + } + return *a.InstallationsCount +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (a *App) GetName() string { + if a == nil || a.Name == nil { + return "" + } + return *a.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (a *App) GetNodeID() string { + if a == nil || a.NodeID == nil { + return "" + } + return *a.NodeID +} + +// GetOwner returns the Owner field. +func (a *App) GetOwner() *User { + if a == nil { + return nil + } + return a.Owner +} + +// GetPermissions returns the Permissions field. +func (a *App) GetPermissions() *InstallationPermissions { + if a == nil { + return nil + } + return a.Permissions +} + +// GetSlug returns the Slug field if it's non-nil, zero value otherwise. +func (a *App) GetSlug() string { + if a == nil || a.Slug == nil { + return "" + } + return *a.Slug +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (a *App) GetUpdatedAt() Timestamp { + if a == nil || a.UpdatedAt == nil { + return Timestamp{} + } + return *a.UpdatedAt +} + +// GetClientID returns the ClientID field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetClientID() string { + if a == nil || a.ClientID == nil { + return "" + } + return *a.ClientID +} + +// GetClientSecret returns the ClientSecret field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetClientSecret() string { + if a == nil || a.ClientSecret == nil { + return "" + } + return *a.ClientSecret +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetDescription() string { + if a == nil || a.Description == nil { + return "" + } + return *a.Description +} + +// GetExternalURL returns the ExternalURL field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetExternalURL() string { + if a == nil || a.ExternalURL == nil { + return "" + } + return *a.ExternalURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetHTMLURL() string { + if a == nil || a.HTMLURL == nil { + return "" + } + return *a.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetName() string { + if a == nil || a.Name == nil { + return "" + } + return *a.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetNodeID() string { + if a == nil || a.NodeID == nil { + return "" + } + return *a.NodeID +} + +// GetOwner returns the Owner field. +func (a *AppConfig) GetOwner() *User { + if a == nil { + return nil + } + return a.Owner +} + +// GetPEM returns the PEM field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetPEM() string { + if a == nil || a.PEM == nil { + return "" + } + return *a.PEM +} + +// GetSlug returns the Slug field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetSlug() string { + if a == nil || a.Slug == nil { + return "" + } + return *a.Slug +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetUpdatedAt() Timestamp { + if a == nil || a.UpdatedAt == nil { + return Timestamp{} + } + return *a.UpdatedAt +} + +// GetWebhookSecret returns the WebhookSecret field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetWebhookSecret() string { + if a == nil || a.WebhookSecret == nil { + return "" + } + return *a.WebhookSecret +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (a *ArchivedAt) GetFrom() Timestamp { + if a == nil || a.From == nil { + return Timestamp{} + } + return *a.From +} + +// GetTo returns the To field if it's non-nil, zero value otherwise. +func (a *ArchivedAt) GetTo() Timestamp { + if a == nil || a.To == nil { + return Timestamp{} + } + return *a.To +} + +// GetArchiveDownloadURL returns the ArchiveDownloadURL field if it's non-nil, zero value otherwise. +func (a *Artifact) GetArchiveDownloadURL() string { + if a == nil || a.ArchiveDownloadURL == nil { + return "" + } + return *a.ArchiveDownloadURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *Artifact) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetExpired returns the Expired field if it's non-nil, zero value otherwise. +func (a *Artifact) GetExpired() bool { + if a == nil || a.Expired == nil { + return false + } + return *a.Expired +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (a *Artifact) GetExpiresAt() Timestamp { + if a == nil || a.ExpiresAt == nil { + return Timestamp{} + } + return *a.ExpiresAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *Artifact) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (a *Artifact) GetName() string { + if a == nil || a.Name == nil { + return "" + } + return *a.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (a *Artifact) GetNodeID() string { + if a == nil || a.NodeID == nil { + return "" + } + return *a.NodeID +} + +// GetSizeInBytes returns the SizeInBytes field if it's non-nil, zero value otherwise. +func (a *Artifact) GetSizeInBytes() int64 { + if a == nil || a.SizeInBytes == nil { + return 0 + } + return *a.SizeInBytes +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (a *Artifact) GetUpdatedAt() Timestamp { + if a == nil || a.UpdatedAt == nil { + return Timestamp{} + } + return *a.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (a *Artifact) GetURL() string { + if a == nil || a.URL == nil { + return "" + } + return *a.URL +} + +// GetWorkflowRun returns the WorkflowRun field. +func (a *Artifact) GetWorkflowRun() *ArtifactWorkflowRun { + if a == nil { + return nil + } + return a.WorkflowRun +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (a *ArtifactList) GetTotalCount() int64 { + if a == nil || a.TotalCount == nil { + return 0 + } + return *a.TotalCount +} + +// GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise. +func (a *ArtifactWorkflowRun) GetHeadBranch() string { + if a == nil || a.HeadBranch == nil { + return "" + } + return *a.HeadBranch +} + +// GetHeadRepositoryID returns the HeadRepositoryID field if it's non-nil, zero value otherwise. +func (a *ArtifactWorkflowRun) GetHeadRepositoryID() int64 { + if a == nil || a.HeadRepositoryID == nil { + return 0 + } + return *a.HeadRepositoryID +} + +// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. +func (a *ArtifactWorkflowRun) GetHeadSHA() string { + if a == nil || a.HeadSHA == nil { + return "" + } + return *a.HeadSHA +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *ArtifactWorkflowRun) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetRepositoryID returns the RepositoryID field if it's non-nil, zero value otherwise. +func (a *ArtifactWorkflowRun) GetRepositoryID() int64 { + if a == nil || a.RepositoryID == nil { + return 0 + } + return *a.RepositoryID +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (a *Attachment) GetBody() string { + if a == nil || a.Body == nil { + return "" + } + return *a.Body +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *Attachment) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (a *Attachment) GetTitle() string { + if a == nil || a.Title == nil { + return "" + } + return *a.Title +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetAction() string { + if a == nil || a.Action == nil { + return "" + } + return *a.Action +} + +// GetActor returns the Actor field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetActor() string { + if a == nil || a.Actor == nil { + return "" + } + return *a.Actor +} + +// GetActorID returns the ActorID field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetActorID() int64 { + if a == nil || a.ActorID == nil { + return 0 + } + return *a.ActorID +} + +// GetActorLocation returns the ActorLocation field. +func (a *AuditEntry) GetActorLocation() *ActorLocation { + if a == nil { + return nil + } + return a.ActorLocation +} + +// GetBusiness returns the Business field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetBusiness() string { + if a == nil || a.Business == nil { + return "" + } + return *a.Business +} + +// GetBusinessID returns the BusinessID field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetBusinessID() int64 { + if a == nil || a.BusinessID == nil { + return 0 + } + return *a.BusinessID +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetDocumentID returns the DocumentID field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetDocumentID() string { + if a == nil || a.DocumentID == nil { + return "" + } + return *a.DocumentID +} + +// GetExternalIdentityNameID returns the ExternalIdentityNameID field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetExternalIdentityNameID() string { + if a == nil || a.ExternalIdentityNameID == nil { + return "" + } + return *a.ExternalIdentityNameID +} + +// GetExternalIdentityUsername returns the ExternalIdentityUsername field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetExternalIdentityUsername() string { + if a == nil || a.ExternalIdentityUsername == nil { + return "" + } + return *a.ExternalIdentityUsername +} + +// GetHashedToken returns the HashedToken field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetHashedToken() string { + if a == nil || a.HashedToken == nil { + return "" + } + return *a.HashedToken +} + +// GetOrg returns the Org field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetOrg() string { + if a == nil || a.Org == nil { + return "" + } + return *a.Org +} + +// GetOrgID returns the OrgID field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetOrgID() int64 { + if a == nil || a.OrgID == nil { + return 0 + } + return *a.OrgID +} + +// GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetTimestamp() Timestamp { + if a == nil || a.Timestamp == nil { + return Timestamp{} + } + return *a.Timestamp +} + +// GetTokenID returns the TokenID field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetTokenID() int64 { + if a == nil || a.TokenID == nil { + return 0 + } + return *a.TokenID +} + +// GetTokenScopes returns the TokenScopes field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetTokenScopes() string { + if a == nil || a.TokenScopes == nil { + return "" + } + return *a.TokenScopes +} + +// GetUser returns the User field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetUser() string { + if a == nil || a.User == nil { + return "" + } + return *a.User +} + +// GetUserID returns the UserID field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetUserID() int64 { + if a == nil || a.UserID == nil { + return 0 + } + return *a.UserID +} + +// GetApp returns the App field. +func (a *Authorization) GetApp() *AuthorizationApp { + if a == nil { + return nil + } + return a.App +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *Authorization) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. +func (a *Authorization) GetFingerprint() string { + if a == nil || a.Fingerprint == nil { + return "" + } + return *a.Fingerprint +} + +// GetHashedToken returns the HashedToken field if it's non-nil, zero value otherwise. +func (a *Authorization) GetHashedToken() string { + if a == nil || a.HashedToken == nil { + return "" + } + return *a.HashedToken +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *Authorization) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetNote returns the Note field if it's non-nil, zero value otherwise. +func (a *Authorization) GetNote() string { + if a == nil || a.Note == nil { + return "" + } + return *a.Note +} + +// GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise. +func (a *Authorization) GetNoteURL() string { + if a == nil || a.NoteURL == nil { + return "" + } + return *a.NoteURL +} + +// GetToken returns the Token field if it's non-nil, zero value otherwise. +func (a *Authorization) GetToken() string { + if a == nil || a.Token == nil { + return "" + } + return *a.Token +} + +// GetTokenLastEight returns the TokenLastEight field if it's non-nil, zero value otherwise. +func (a *Authorization) GetTokenLastEight() string { + if a == nil || a.TokenLastEight == nil { + return "" + } + return *a.TokenLastEight +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (a *Authorization) GetUpdatedAt() Timestamp { + if a == nil || a.UpdatedAt == nil { + return Timestamp{} + } + return *a.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (a *Authorization) GetURL() string { + if a == nil || a.URL == nil { + return "" + } + return *a.URL +} + +// GetUser returns the User field. +func (a *Authorization) GetUser() *User { + if a == nil { + return nil + } + return a.User +} + +// GetClientID returns the ClientID field if it's non-nil, zero value otherwise. +func (a *AuthorizationApp) GetClientID() string { + if a == nil || a.ClientID == nil { + return "" + } + return *a.ClientID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (a *AuthorizationApp) GetName() string { + if a == nil || a.Name == nil { + return "" + } + return *a.Name +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (a *AuthorizationApp) GetURL() string { + if a == nil || a.URL == nil { + return "" + } + return *a.URL +} + +// GetClientID returns the ClientID field if it's non-nil, zero value otherwise. +func (a *AuthorizationRequest) GetClientID() string { + if a == nil || a.ClientID == nil { + return "" + } + return *a.ClientID +} + +// GetClientSecret returns the ClientSecret field if it's non-nil, zero value otherwise. +func (a *AuthorizationRequest) GetClientSecret() string { + if a == nil || a.ClientSecret == nil { + return "" + } + return *a.ClientSecret +} + +// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. +func (a *AuthorizationRequest) GetFingerprint() string { + if a == nil || a.Fingerprint == nil { + return "" + } + return *a.Fingerprint +} + +// GetNote returns the Note field if it's non-nil, zero value otherwise. +func (a *AuthorizationRequest) GetNote() string { + if a == nil || a.Note == nil { + return "" + } + return *a.Note +} + +// GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise. +func (a *AuthorizationRequest) GetNoteURL() string { + if a == nil || a.NoteURL == nil { + return "" + } + return *a.NoteURL +} + +// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. +func (a *AuthorizationUpdateRequest) GetFingerprint() string { + if a == nil || a.Fingerprint == nil { + return "" + } + return *a.Fingerprint +} + +// GetNote returns the Note field if it's non-nil, zero value otherwise. +func (a *AuthorizationUpdateRequest) GetNote() string { + if a == nil || a.Note == nil { + return "" + } + return *a.Note +} + +// GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise. +func (a *AuthorizationUpdateRequest) GetNoteURL() string { + if a == nil || a.NoteURL == nil { + return "" + } + return *a.NoteURL +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (a *AuthorizedActorsOnly) GetFrom() bool { + if a == nil || a.From == nil { + return false + } + return *a.From +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (a *AuthorizedDismissalActorsOnlyChanges) GetFrom() bool { + if a == nil || a.From == nil { + return false + } + return *a.From +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *Autolink) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetIsAlphanumeric returns the IsAlphanumeric field if it's non-nil, zero value otherwise. +func (a *Autolink) GetIsAlphanumeric() bool { + if a == nil || a.IsAlphanumeric == nil { + return false + } + return *a.IsAlphanumeric +} + +// GetKeyPrefix returns the KeyPrefix field if it's non-nil, zero value otherwise. +func (a *Autolink) GetKeyPrefix() string { + if a == nil || a.KeyPrefix == nil { + return "" + } + return *a.KeyPrefix +} + +// GetURLTemplate returns the URLTemplate field if it's non-nil, zero value otherwise. +func (a *Autolink) GetURLTemplate() string { + if a == nil || a.URLTemplate == nil { + return "" + } + return *a.URLTemplate +} + +// GetIsAlphanumeric returns the IsAlphanumeric field if it's non-nil, zero value otherwise. +func (a *AutolinkOptions) GetIsAlphanumeric() bool { + if a == nil || a.IsAlphanumeric == nil { + return false + } + return *a.IsAlphanumeric +} + +// GetKeyPrefix returns the KeyPrefix field if it's non-nil, zero value otherwise. +func (a *AutolinkOptions) GetKeyPrefix() string { + if a == nil || a.KeyPrefix == nil { + return "" + } + return *a.KeyPrefix +} + +// GetURLTemplate returns the URLTemplate field if it's non-nil, zero value otherwise. +func (a *AutolinkOptions) GetURLTemplate() string { + if a == nil || a.URLTemplate == nil { + return "" + } + return *a.URLTemplate +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (a *AutomatedSecurityFixes) GetEnabled() bool { + if a == nil || a.Enabled == nil { + return false + } + return *a.Enabled +} + +// GetPaused returns the Paused field if it's non-nil, zero value otherwise. +func (a *AutomatedSecurityFixes) GetPaused() bool { + if a == nil || a.Paused == nil { + return false + } + return *a.Paused +} + +// GetAppID returns the AppID field if it's non-nil, zero value otherwise. +func (a *AutoTriggerCheck) GetAppID() int64 { + if a == nil || a.AppID == nil { + return 0 + } + return *a.AppID +} + +// GetSetting returns the Setting field if it's non-nil, zero value otherwise. +func (a *AutoTriggerCheck) GetSetting() bool { + if a == nil || a.Setting == nil { + return false + } + return *a.Setting +} + +// GetContent returns the Content field if it's non-nil, zero value otherwise. +func (b *Blob) GetContent() string { + if b == nil || b.Content == nil { + return "" + } + return *b.Content +} + +// GetEncoding returns the Encoding field if it's non-nil, zero value otherwise. +func (b *Blob) GetEncoding() string { + if b == nil || b.Encoding == nil { + return "" + } + return *b.Encoding +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (b *Blob) GetNodeID() string { + if b == nil || b.NodeID == nil { + return "" + } + return *b.NodeID +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (b *Blob) GetSHA() string { + if b == nil || b.SHA == nil { + return "" + } + return *b.SHA +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (b *Blob) GetSize() int { + if b == nil || b.Size == nil { + return 0 + } + return *b.Size +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (b *Blob) GetURL() string { + if b == nil || b.URL == nil { + return "" + } + return *b.URL +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (b *BlockCreations) GetEnabled() bool { + if b == nil || b.Enabled == nil { + return false + } + return *b.Enabled +} + +// GetCommit returns the Commit field. +func (b *Branch) GetCommit() *RepositoryCommit { + if b == nil { + return nil + } + return b.Commit +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (b *Branch) GetName() string { + if b == nil || b.Name == nil { + return "" + } + return *b.Name +} + +// GetProtected returns the Protected field if it's non-nil, zero value otherwise. +func (b *Branch) GetProtected() bool { + if b == nil || b.Protected == nil { + return false + } + return *b.Protected +} + +// GetProtection returns the Protection field. +func (b *Branch) GetProtection() *Protection { + if b == nil { + return nil + } + return b.Protection +} + +// GetCommit returns the Commit field. +func (b *BranchCommit) GetCommit() *Commit { + if b == nil { + return nil + } + return b.Commit +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (b *BranchCommit) GetName() string { + if b == nil || b.Name == nil { + return "" + } + return *b.Name +} + +// GetProtected returns the Protected field if it's non-nil, zero value otherwise. +func (b *BranchCommit) GetProtected() bool { + if b == nil || b.Protected == nil { + return false + } + return *b.Protected +} + +// GetProtected returns the Protected field if it's non-nil, zero value otherwise. +func (b *BranchListOptions) GetProtected() bool { + if b == nil || b.Protected == nil { + return false + } + return *b.Protected +} + +// GetCustomBranchPolicies returns the CustomBranchPolicies field if it's non-nil, zero value otherwise. +func (b *BranchPolicy) GetCustomBranchPolicies() bool { + if b == nil || b.CustomBranchPolicies == nil { + return false + } + return *b.CustomBranchPolicies +} + +// GetProtectedBranches returns the ProtectedBranches field if it's non-nil, zero value otherwise. +func (b *BranchPolicy) GetProtectedBranches() bool { + if b == nil || b.ProtectedBranches == nil { + return false + } + return *b.ProtectedBranches +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (b *BranchProtectionConfigurationEvent) GetAction() string { + if b == nil || b.Action == nil { + return "" + } + return *b.Action +} + +// GetEnterprise returns the Enterprise field. +func (b *BranchProtectionConfigurationEvent) GetEnterprise() *Enterprise { + if b == nil { + return nil + } + return b.Enterprise +} + +// GetInstallation returns the Installation field. +func (b *BranchProtectionConfigurationEvent) GetInstallation() *Installation { + if b == nil { + return nil + } + return b.Installation +} + +// GetOrg returns the Org field. +func (b *BranchProtectionConfigurationEvent) GetOrg() *Organization { + if b == nil { + return nil + } + return b.Org +} + +// GetRepo returns the Repo field. +func (b *BranchProtectionConfigurationEvent) GetRepo() *Repository { + if b == nil { + return nil + } + return b.Repo +} + +// GetSender returns the Sender field. +func (b *BranchProtectionConfigurationEvent) GetSender() *User { + if b == nil { + return nil + } + return b.Sender +} + +// GetAdminEnforced returns the AdminEnforced field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetAdminEnforced() bool { + if b == nil || b.AdminEnforced == nil { + return false + } + return *b.AdminEnforced +} + +// GetAllowDeletionsEnforcementLevel returns the AllowDeletionsEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetAllowDeletionsEnforcementLevel() string { + if b == nil || b.AllowDeletionsEnforcementLevel == nil { + return "" + } + return *b.AllowDeletionsEnforcementLevel +} + +// GetAllowForcePushesEnforcementLevel returns the AllowForcePushesEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetAllowForcePushesEnforcementLevel() string { + if b == nil || b.AllowForcePushesEnforcementLevel == nil { + return "" + } + return *b.AllowForcePushesEnforcementLevel +} + +// GetAuthorizedActorsOnly returns the AuthorizedActorsOnly field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetAuthorizedActorsOnly() bool { + if b == nil || b.AuthorizedActorsOnly == nil { + return false + } + return *b.AuthorizedActorsOnly +} + +// GetAuthorizedDismissalActorsOnly returns the AuthorizedDismissalActorsOnly field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetAuthorizedDismissalActorsOnly() bool { + if b == nil || b.AuthorizedDismissalActorsOnly == nil { + return false + } + return *b.AuthorizedDismissalActorsOnly +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetCreatedAt() Timestamp { + if b == nil || b.CreatedAt == nil { + return Timestamp{} + } + return *b.CreatedAt +} + +// GetDismissStaleReviewsOnPush returns the DismissStaleReviewsOnPush field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetDismissStaleReviewsOnPush() bool { + if b == nil || b.DismissStaleReviewsOnPush == nil { + return false + } + return *b.DismissStaleReviewsOnPush +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetID() int64 { + if b == nil || b.ID == nil { + return 0 + } + return *b.ID +} + +// GetIgnoreApprovalsFromContributors returns the IgnoreApprovalsFromContributors field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetIgnoreApprovalsFromContributors() bool { + if b == nil || b.IgnoreApprovalsFromContributors == nil { + return false + } + return *b.IgnoreApprovalsFromContributors +} + +// GetLinearHistoryRequirementEnforcementLevel returns the LinearHistoryRequirementEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetLinearHistoryRequirementEnforcementLevel() string { + if b == nil || b.LinearHistoryRequirementEnforcementLevel == nil { + return "" + } + return *b.LinearHistoryRequirementEnforcementLevel +} + +// GetMergeQueueEnforcementLevel returns the MergeQueueEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetMergeQueueEnforcementLevel() string { + if b == nil || b.MergeQueueEnforcementLevel == nil { + return "" + } + return *b.MergeQueueEnforcementLevel +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetName() string { + if b == nil || b.Name == nil { + return "" + } + return *b.Name +} + +// GetPullRequestReviewsEnforcementLevel returns the PullRequestReviewsEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetPullRequestReviewsEnforcementLevel() string { + if b == nil || b.PullRequestReviewsEnforcementLevel == nil { + return "" + } + return *b.PullRequestReviewsEnforcementLevel +} + +// GetRepositoryID returns the RepositoryID field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetRepositoryID() int64 { + if b == nil || b.RepositoryID == nil { + return 0 + } + return *b.RepositoryID +} + +// GetRequireCodeOwnerReview returns the RequireCodeOwnerReview field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetRequireCodeOwnerReview() bool { + if b == nil || b.RequireCodeOwnerReview == nil { + return false + } + return *b.RequireCodeOwnerReview +} + +// GetRequiredApprovingReviewCount returns the RequiredApprovingReviewCount field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetRequiredApprovingReviewCount() int { + if b == nil || b.RequiredApprovingReviewCount == nil { + return 0 + } + return *b.RequiredApprovingReviewCount +} + +// GetRequiredConversationResolutionLevel returns the RequiredConversationResolutionLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetRequiredConversationResolutionLevel() string { + if b == nil || b.RequiredConversationResolutionLevel == nil { + return "" + } + return *b.RequiredConversationResolutionLevel +} + +// GetRequiredDeploymentsEnforcementLevel returns the RequiredDeploymentsEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetRequiredDeploymentsEnforcementLevel() string { + if b == nil || b.RequiredDeploymentsEnforcementLevel == nil { + return "" + } + return *b.RequiredDeploymentsEnforcementLevel +} + +// GetRequiredStatusChecksEnforcementLevel returns the RequiredStatusChecksEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetRequiredStatusChecksEnforcementLevel() string { + if b == nil || b.RequiredStatusChecksEnforcementLevel == nil { + return "" + } + return *b.RequiredStatusChecksEnforcementLevel +} + +// GetSignatureRequirementEnforcementLevel returns the SignatureRequirementEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetSignatureRequirementEnforcementLevel() string { + if b == nil || b.SignatureRequirementEnforcementLevel == nil { + return "" + } + return *b.SignatureRequirementEnforcementLevel +} + +// GetStrictRequiredStatusChecksPolicy returns the StrictRequiredStatusChecksPolicy field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetStrictRequiredStatusChecksPolicy() bool { + if b == nil || b.StrictRequiredStatusChecksPolicy == nil { + return false + } + return *b.StrictRequiredStatusChecksPolicy +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetUpdatedAt() Timestamp { + if b == nil || b.UpdatedAt == nil { + return Timestamp{} + } + return *b.UpdatedAt +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRuleEvent) GetAction() string { + if b == nil || b.Action == nil { + return "" + } + return *b.Action +} + +// GetChanges returns the Changes field. +func (b *BranchProtectionRuleEvent) GetChanges() *ProtectionChanges { + if b == nil { + return nil + } + return b.Changes +} + +// GetInstallation returns the Installation field. +func (b *BranchProtectionRuleEvent) GetInstallation() *Installation { + if b == nil { + return nil + } + return b.Installation +} + +// GetOrg returns the Org field. +func (b *BranchProtectionRuleEvent) GetOrg() *Organization { + if b == nil { + return nil + } + return b.Org +} + +// GetRepo returns the Repo field. +func (b *BranchProtectionRuleEvent) GetRepo() *Repository { + if b == nil { + return nil + } + return b.Repo +} + +// GetRule returns the Rule field. +func (b *BranchProtectionRuleEvent) GetRule() *BranchProtectionRule { + if b == nil { + return nil + } + return b.Rule +} + +// GetSender returns the Sender field. +func (b *BranchProtectionRuleEvent) GetSender() *User { + if b == nil { + return nil + } + return b.Sender +} + +// GetActorID returns the ActorID field if it's non-nil, zero value otherwise. +func (b *BypassActor) GetActorID() int64 { + if b == nil || b.ActorID == nil { + return 0 + } + return *b.ActorID +} + +// GetActorType returns the ActorType field if it's non-nil, zero value otherwise. +func (b *BypassActor) GetActorType() string { + if b == nil || b.ActorType == nil { + return "" + } + return *b.ActorType +} + +// GetBypassMode returns the BypassMode field if it's non-nil, zero value otherwise. +func (b *BypassActor) GetBypassMode() string { + if b == nil || b.BypassMode == nil { + return "" + } + return *b.BypassMode +} + +// GetApp returns the App field. +func (c *CheckRun) GetApp() *App { + if c == nil { + return nil + } + return c.App +} + +// GetCheckSuite returns the CheckSuite field. +func (c *CheckRun) GetCheckSuite() *CheckSuite { + if c == nil { + return nil + } + return c.CheckSuite +} + +// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetCompletedAt() Timestamp { + if c == nil || c.CompletedAt == nil { + return Timestamp{} + } + return *c.CompletedAt +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetConclusion() string { + if c == nil || c.Conclusion == nil { + return "" + } + return *c.Conclusion +} + +// GetDetailsURL returns the DetailsURL field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetDetailsURL() string { + if c == nil || c.DetailsURL == nil { + return "" + } + return *c.DetailsURL +} + +// GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetExternalID() string { + if c == nil || c.ExternalID == nil { + return "" + } + return *c.ExternalID +} + +// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetHeadSHA() string { + if c == nil || c.HeadSHA == nil { + return "" + } + return *c.HeadSHA +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetOutput returns the Output field. +func (c *CheckRun) GetOutput() *CheckRunOutput { + if c == nil { + return nil + } + return c.Output +} + +// GetStartedAt returns the StartedAt field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetStartedAt() Timestamp { + if c == nil || c.StartedAt == nil { + return Timestamp{} + } + return *c.StartedAt +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetStatus() string { + if c == nil || c.Status == nil { + return "" + } + return *c.Status +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetAnnotationLevel returns the AnnotationLevel field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetAnnotationLevel() string { + if c == nil || c.AnnotationLevel == nil { + return "" + } + return *c.AnnotationLevel +} + +// GetEndColumn returns the EndColumn field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetEndColumn() int { + if c == nil || c.EndColumn == nil { + return 0 + } + return *c.EndColumn +} + +// GetEndLine returns the EndLine field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetEndLine() int { + if c == nil || c.EndLine == nil { + return 0 + } + return *c.EndLine +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetMessage() string { + if c == nil || c.Message == nil { + return "" + } + return *c.Message +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetPath() string { + if c == nil || c.Path == nil { + return "" + } + return *c.Path +} + +// GetRawDetails returns the RawDetails field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetRawDetails() string { + if c == nil || c.RawDetails == nil { + return "" + } + return *c.RawDetails +} + +// GetStartColumn returns the StartColumn field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetStartColumn() int { + if c == nil || c.StartColumn == nil { + return 0 + } + return *c.StartColumn +} + +// GetStartLine returns the StartLine field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetStartLine() int { + if c == nil || c.StartLine == nil { + return 0 + } + return *c.StartLine +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetTitle() string { + if c == nil || c.Title == nil { + return "" + } + return *c.Title +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (c *CheckRunEvent) GetAction() string { + if c == nil || c.Action == nil { + return "" + } + return *c.Action +} + +// GetCheckRun returns the CheckRun field. +func (c *CheckRunEvent) GetCheckRun() *CheckRun { + if c == nil { + return nil + } + return c.CheckRun +} + +// GetInstallation returns the Installation field. +func (c *CheckRunEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetOrg returns the Org field. +func (c *CheckRunEvent) GetOrg() *Organization { + if c == nil { + return nil + } + return c.Org +} + +// GetRepo returns the Repo field. +func (c *CheckRunEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetRequestedAction returns the RequestedAction field. +func (c *CheckRunEvent) GetRequestedAction() *RequestedAction { + if c == nil { + return nil + } + return c.RequestedAction +} + +// GetSender returns the Sender field. +func (c *CheckRunEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetAlt returns the Alt field if it's non-nil, zero value otherwise. +func (c *CheckRunImage) GetAlt() string { + if c == nil || c.Alt == nil { + return "" + } + return *c.Alt +} + +// GetCaption returns the Caption field if it's non-nil, zero value otherwise. +func (c *CheckRunImage) GetCaption() string { + if c == nil || c.Caption == nil { + return "" + } + return *c.Caption +} + +// GetImageURL returns the ImageURL field if it's non-nil, zero value otherwise. +func (c *CheckRunImage) GetImageURL() string { + if c == nil || c.ImageURL == nil { + return "" + } + return *c.ImageURL +} + +// GetAnnotationsCount returns the AnnotationsCount field if it's non-nil, zero value otherwise. +func (c *CheckRunOutput) GetAnnotationsCount() int { + if c == nil || c.AnnotationsCount == nil { + return 0 + } + return *c.AnnotationsCount +} + +// GetAnnotationsURL returns the AnnotationsURL field if it's non-nil, zero value otherwise. +func (c *CheckRunOutput) GetAnnotationsURL() string { + if c == nil || c.AnnotationsURL == nil { + return "" + } + return *c.AnnotationsURL +} + +// GetSummary returns the Summary field if it's non-nil, zero value otherwise. +func (c *CheckRunOutput) GetSummary() string { + if c == nil || c.Summary == nil { + return "" + } + return *c.Summary +} + +// GetText returns the Text field if it's non-nil, zero value otherwise. +func (c *CheckRunOutput) GetText() string { + if c == nil || c.Text == nil { + return "" + } + return *c.Text +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (c *CheckRunOutput) GetTitle() string { + if c == nil || c.Title == nil { + return "" + } + return *c.Title +} + +// GetAfterSHA returns the AfterSHA field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetAfterSHA() string { + if c == nil || c.AfterSHA == nil { + return "" + } + return *c.AfterSHA +} + +// GetApp returns the App field. +func (c *CheckSuite) GetApp() *App { + if c == nil { + return nil + } + return c.App +} + +// GetBeforeSHA returns the BeforeSHA field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetBeforeSHA() string { + if c == nil || c.BeforeSHA == nil { + return "" + } + return *c.BeforeSHA +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetConclusion() string { + if c == nil || c.Conclusion == nil { + return "" + } + return *c.Conclusion +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetHeadBranch() string { + if c == nil || c.HeadBranch == nil { + return "" + } + return *c.HeadBranch +} + +// GetHeadCommit returns the HeadCommit field. +func (c *CheckSuite) GetHeadCommit() *Commit { + if c == nil { + return nil + } + return c.HeadCommit +} + +// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetHeadSHA() string { + if c == nil || c.HeadSHA == nil { + return "" + } + return *c.HeadSHA +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetLatestCheckRunsCount returns the LatestCheckRunsCount field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetLatestCheckRunsCount() int64 { + if c == nil || c.LatestCheckRunsCount == nil { + return 0 + } + return *c.LatestCheckRunsCount +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetRepository returns the Repository field. +func (c *CheckSuite) GetRepository() *Repository { + if c == nil { + return nil + } + return c.Repository +} + +// GetRerequstable returns the Rerequstable field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetRerequstable() bool { + if c == nil || c.Rerequstable == nil { + return false + } + return *c.Rerequstable +} + +// GetRunsRerequstable returns the RunsRerequstable field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetRunsRerequstable() bool { + if c == nil || c.RunsRerequstable == nil { + return false + } + return *c.RunsRerequstable +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetStatus() string { + if c == nil || c.Status == nil { + return "" + } + return *c.Status +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetUpdatedAt() Timestamp { + if c == nil || c.UpdatedAt == nil { + return Timestamp{} + } + return *c.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (c *CheckSuiteEvent) GetAction() string { + if c == nil || c.Action == nil { + return "" + } + return *c.Action +} + +// GetCheckSuite returns the CheckSuite field. +func (c *CheckSuiteEvent) GetCheckSuite() *CheckSuite { + if c == nil { + return nil + } + return c.CheckSuite +} + +// GetInstallation returns the Installation field. +func (c *CheckSuiteEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetOrg returns the Org field. +func (c *CheckSuiteEvent) GetOrg() *Organization { + if c == nil { + return nil + } + return c.Org +} + +// GetRepo returns the Repo field. +func (c *CheckSuiteEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetSender returns the Sender field. +func (c *CheckSuiteEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetPreferences returns the Preferences field. +func (c *CheckSuitePreferenceResults) GetPreferences() *PreferenceList { + if c == nil { + return nil + } + return c.Preferences +} + +// GetRepository returns the Repository field. +func (c *CheckSuitePreferenceResults) GetRepository() *Repository { + if c == nil { + return nil + } + return c.Repository +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (c *CodeOfConduct) GetBody() string { + if c == nil || c.Body == nil { + return "" + } + return *c.Body +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (c *CodeOfConduct) GetKey() string { + if c == nil || c.Key == nil { + return "" + } + return *c.Key +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CodeOfConduct) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CodeOfConduct) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetSuggestion returns the Suggestion field if it's non-nil, zero value otherwise. +func (c *CodeownersError) GetSuggestion() string { + if c == nil || c.Suggestion == nil { + return "" + } + return *c.Suggestion +} + +// GetContentType returns the ContentType field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetContentType() string { + if c == nil || c.ContentType == nil { + return "" + } + return *c.ContentType +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetLanguage returns the Language field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetLanguage() string { + if c == nil || c.Language == nil { + return "" + } + return *c.Language +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetSize() int64 { + if c == nil || c.Size == nil { + return 0 + } + return *c.Size +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetUpdatedAt() Timestamp { + if c == nil || c.UpdatedAt == nil { + return Timestamp{} + } + return *c.UpdatedAt +} + +// GetUploader returns the Uploader field. +func (c *CodeQLDatabase) GetUploader() *User { + if c == nil { + return nil + } + return c.Uploader +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *CodeResult) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CodeResult) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (c *CodeResult) GetPath() string { + if c == nil || c.Path == nil { + return "" + } + return *c.Path +} + +// GetRepository returns the Repository field. +func (c *CodeResult) GetRepository() *Repository { + if c == nil { + return nil + } + return c.Repository +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (c *CodeResult) GetSHA() string { + if c == nil || c.SHA == nil { + return "" + } + return *c.SHA +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (c *CodeScanningAlertEvent) GetAction() string { + if c == nil || c.Action == nil { + return "" + } + return *c.Action +} + +// GetAlert returns the Alert field. +func (c *CodeScanningAlertEvent) GetAlert() *Alert { + if c == nil { + return nil + } + return c.Alert +} + +// GetCommitOID returns the CommitOID field if it's non-nil, zero value otherwise. +func (c *CodeScanningAlertEvent) GetCommitOID() string { + if c == nil || c.CommitOID == nil { + return "" + } + return *c.CommitOID +} + +// GetInstallation returns the Installation field. +func (c *CodeScanningAlertEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetOrg returns the Org field. +func (c *CodeScanningAlertEvent) GetOrg() *Organization { + if c == nil { + return nil + } + return c.Org +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (c *CodeScanningAlertEvent) GetRef() string { + if c == nil || c.Ref == nil { + return "" + } + return *c.Ref +} + +// GetRepo returns the Repo field. +func (c *CodeScanningAlertEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetSender returns the Sender field. +func (c *CodeScanningAlertEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetDismissedComment returns the DismissedComment field if it's non-nil, zero value otherwise. +func (c *CodeScanningAlertState) GetDismissedComment() string { + if c == nil || c.DismissedComment == nil { + return "" + } + return *c.DismissedComment +} + +// GetDismissedReason returns the DismissedReason field if it's non-nil, zero value otherwise. +func (c *CodeScanningAlertState) GetDismissedReason() string { + if c == nil || c.DismissedReason == nil { + return "" + } + return *c.DismissedReason +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (c *CodeSearchResult) GetIncompleteResults() bool { + if c == nil || c.IncompleteResults == nil { + return false + } + return *c.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (c *CodeSearchResult) GetTotal() int { + if c == nil || c.Total == nil { + return 0 + } + return *c.Total +} + +// GetAdvancedSecurity returns the AdvancedSecurity field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetAdvancedSecurity() string { + if c == nil || c.AdvancedSecurity == nil { + return "" + } + return *c.AdvancedSecurity +} + +// GetCodeScanningDefaultSetup returns the CodeScanningDefaultSetup field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetCodeScanningDefaultSetup() string { + if c == nil || c.CodeScanningDefaultSetup == nil { + return "" + } + return *c.CodeScanningDefaultSetup +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetDependabotAlerts returns the DependabotAlerts field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetDependabotAlerts() string { + if c == nil || c.DependabotAlerts == nil { + return "" + } + return *c.DependabotAlerts +} + +// GetDependabotSecurityUpdates returns the DependabotSecurityUpdates field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetDependabotSecurityUpdates() string { + if c == nil || c.DependabotSecurityUpdates == nil { + return "" + } + return *c.DependabotSecurityUpdates +} + +// GetDependencyGraph returns the DependencyGraph field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetDependencyGraph() string { + if c == nil || c.DependencyGraph == nil { + return "" + } + return *c.DependencyGraph +} + +// GetDependencyGraphAutosubmitAction returns the DependencyGraphAutosubmitAction field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetDependencyGraphAutosubmitAction() string { + if c == nil || c.DependencyGraphAutosubmitAction == nil { + return "" + } + return *c.DependencyGraphAutosubmitAction +} + +// GetDependencyGraphAutosubmitActionOptions returns the DependencyGraphAutosubmitActionOptions field. +func (c *CodeSecurityConfiguration) GetDependencyGraphAutosubmitActionOptions() *DependencyGraphAutosubmitActionOptions { + if c == nil { + return nil + } + return c.DependencyGraphAutosubmitActionOptions +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetDescription() string { + if c == nil || c.Description == nil { + return "" + } + return *c.Description +} + +// GetEnforcement returns the Enforcement field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetEnforcement() string { + if c == nil || c.Enforcement == nil { + return "" + } + return *c.Enforcement +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetPrivateVulnerabilityReporting returns the PrivateVulnerabilityReporting field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetPrivateVulnerabilityReporting() string { + if c == nil || c.PrivateVulnerabilityReporting == nil { + return "" + } + return *c.PrivateVulnerabilityReporting +} + +// GetSecretScanning returns the SecretScanning field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetSecretScanning() string { + if c == nil || c.SecretScanning == nil { + return "" + } + return *c.SecretScanning +} + +// GetSecretScanningNonProviderPatterns returns the SecretScanningNonProviderPatterns field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetSecretScanningNonProviderPatterns() string { + if c == nil || c.SecretScanningNonProviderPatterns == nil { + return "" + } + return *c.SecretScanningNonProviderPatterns +} + +// GetSecretScanningPushProtection returns the SecretScanningPushProtection field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetSecretScanningPushProtection() string { + if c == nil || c.SecretScanningPushProtection == nil { + return "" + } + return *c.SecretScanningPushProtection +} + +// GetSecretScanningValidityChecks returns the SecretScanningValidityChecks field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetSecretScanningValidityChecks() string { + if c == nil || c.SecretScanningValidityChecks == nil { + return "" + } + return *c.SecretScanningValidityChecks +} + +// GetTargetType returns the TargetType field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetTargetType() string { + if c == nil || c.TargetType == nil { + return "" + } + return *c.TargetType +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetUpdatedAt() Timestamp { + if c == nil || c.UpdatedAt == nil { + return Timestamp{} + } + return *c.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetConfiguration returns the Configuration field. +func (c *CodeSecurityConfigurationWithDefaultForNewRepos) GetConfiguration() *CodeSecurityConfiguration { + if c == nil { + return nil + } + return c.Configuration +} + +// GetDefaultForNewRepos returns the DefaultForNewRepos field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfigurationWithDefaultForNewRepos) GetDefaultForNewRepos() string { + if c == nil || c.DefaultForNewRepos == nil { + return "" + } + return *c.DefaultForNewRepos +} + +// GetBillableOwner returns the BillableOwner field. +func (c *Codespace) GetBillableOwner() *User { + if c == nil { + return nil + } + return c.BillableOwner +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *Codespace) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetDevcontainerPath returns the DevcontainerPath field if it's non-nil, zero value otherwise. +func (c *Codespace) GetDevcontainerPath() string { + if c == nil || c.DevcontainerPath == nil { + return "" + } + return *c.DevcontainerPath +} + +// GetDisplayName returns the DisplayName field if it's non-nil, zero value otherwise. +func (c *Codespace) GetDisplayName() string { + if c == nil || c.DisplayName == nil { + return "" + } + return *c.DisplayName +} + +// GetEnvironmentID returns the EnvironmentID field if it's non-nil, zero value otherwise. +func (c *Codespace) GetEnvironmentID() string { + if c == nil || c.EnvironmentID == nil { + return "" + } + return *c.EnvironmentID +} + +// GetGitStatus returns the GitStatus field. +func (c *Codespace) GetGitStatus() *CodespacesGitStatus { + if c == nil { + return nil + } + return c.GitStatus +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *Codespace) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetIdleTimeoutMinutes returns the IdleTimeoutMinutes field if it's non-nil, zero value otherwise. +func (c *Codespace) GetIdleTimeoutMinutes() int { + if c == nil || c.IdleTimeoutMinutes == nil { + return 0 + } + return *c.IdleTimeoutMinutes +} + +// GetIdleTimeoutNotice returns the IdleTimeoutNotice field if it's non-nil, zero value otherwise. +func (c *Codespace) GetIdleTimeoutNotice() string { + if c == nil || c.IdleTimeoutNotice == nil { + return "" + } + return *c.IdleTimeoutNotice +} + +// GetLastKnownStopNotice returns the LastKnownStopNotice field if it's non-nil, zero value otherwise. +func (c *Codespace) GetLastKnownStopNotice() string { + if c == nil || c.LastKnownStopNotice == nil { + return "" + } + return *c.LastKnownStopNotice +} + +// GetLastUsedAt returns the LastUsedAt field if it's non-nil, zero value otherwise. +func (c *Codespace) GetLastUsedAt() Timestamp { + if c == nil || c.LastUsedAt == nil { + return Timestamp{} + } + return *c.LastUsedAt +} + +// GetLocation returns the Location field if it's non-nil, zero value otherwise. +func (c *Codespace) GetLocation() string { + if c == nil || c.Location == nil { + return "" + } + return *c.Location +} + +// GetMachine returns the Machine field. +func (c *Codespace) GetMachine() *CodespacesMachine { + if c == nil { + return nil + } + return c.Machine +} + +// GetMachinesURL returns the MachinesURL field if it's non-nil, zero value otherwise. +func (c *Codespace) GetMachinesURL() string { + if c == nil || c.MachinesURL == nil { + return "" + } + return *c.MachinesURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *Codespace) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetOwner returns the Owner field. +func (c *Codespace) GetOwner() *User { + if c == nil { + return nil + } + return c.Owner +} + +// GetPendingOperation returns the PendingOperation field if it's non-nil, zero value otherwise. +func (c *Codespace) GetPendingOperation() bool { + if c == nil || c.PendingOperation == nil { + return false + } + return *c.PendingOperation +} + +// GetPendingOperationDisabledReason returns the PendingOperationDisabledReason field if it's non-nil, zero value otherwise. +func (c *Codespace) GetPendingOperationDisabledReason() string { + if c == nil || c.PendingOperationDisabledReason == nil { + return "" + } + return *c.PendingOperationDisabledReason +} + +// GetPrebuild returns the Prebuild field if it's non-nil, zero value otherwise. +func (c *Codespace) GetPrebuild() bool { + if c == nil || c.Prebuild == nil { + return false + } + return *c.Prebuild +} + +// GetPullsURL returns the PullsURL field if it's non-nil, zero value otherwise. +func (c *Codespace) GetPullsURL() string { + if c == nil || c.PullsURL == nil { + return "" + } + return *c.PullsURL +} + +// GetRepository returns the Repository field. +func (c *Codespace) GetRepository() *Repository { + if c == nil { + return nil + } + return c.Repository +} + +// GetRetentionExpiresAt returns the RetentionExpiresAt field if it's non-nil, zero value otherwise. +func (c *Codespace) GetRetentionExpiresAt() Timestamp { + if c == nil || c.RetentionExpiresAt == nil { + return Timestamp{} + } + return *c.RetentionExpiresAt +} + +// GetRetentionPeriodMinutes returns the RetentionPeriodMinutes field if it's non-nil, zero value otherwise. +func (c *Codespace) GetRetentionPeriodMinutes() int { + if c == nil || c.RetentionPeriodMinutes == nil { + return 0 + } + return *c.RetentionPeriodMinutes +} + +// GetRuntimeConstraints returns the RuntimeConstraints field. +func (c *Codespace) GetRuntimeConstraints() *CodespacesRuntimeConstraints { + if c == nil { + return nil + } + return c.RuntimeConstraints +} + +// GetStartURL returns the StartURL field if it's non-nil, zero value otherwise. +func (c *Codespace) GetStartURL() string { + if c == nil || c.StartURL == nil { + return "" + } + return *c.StartURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (c *Codespace) GetState() string { + if c == nil || c.State == nil { + return "" + } + return *c.State +} + +// GetStopURL returns the StopURL field if it's non-nil, zero value otherwise. +func (c *Codespace) GetStopURL() string { + if c == nil || c.StopURL == nil { + return "" + } + return *c.StopURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (c *Codespace) GetUpdatedAt() Timestamp { + if c == nil || c.UpdatedAt == nil { + return Timestamp{} + } + return *c.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *Codespace) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetWebURL returns the WebURL field if it's non-nil, zero value otherwise. +func (c *Codespace) GetWebURL() string { + if c == nil || c.WebURL == nil { + return "" + } + return *c.WebURL +} + +// GetAhead returns the Ahead field if it's non-nil, zero value otherwise. +func (c *CodespacesGitStatus) GetAhead() int { + if c == nil || c.Ahead == nil { + return 0 + } + return *c.Ahead +} + +// GetBehind returns the Behind field if it's non-nil, zero value otherwise. +func (c *CodespacesGitStatus) GetBehind() int { + if c == nil || c.Behind == nil { + return 0 + } + return *c.Behind +} + +// GetHasUncommittedChanges returns the HasUncommittedChanges field if it's non-nil, zero value otherwise. +func (c *CodespacesGitStatus) GetHasUncommittedChanges() bool { + if c == nil || c.HasUncommittedChanges == nil { + return false + } + return *c.HasUncommittedChanges +} + +// GetHasUnpushedChanges returns the HasUnpushedChanges field if it's non-nil, zero value otherwise. +func (c *CodespacesGitStatus) GetHasUnpushedChanges() bool { + if c == nil || c.HasUnpushedChanges == nil { + return false + } + return *c.HasUnpushedChanges +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (c *CodespacesGitStatus) GetRef() string { + if c == nil || c.Ref == nil { + return "" + } + return *c.Ref +} + +// GetCPUs returns the CPUs field if it's non-nil, zero value otherwise. +func (c *CodespacesMachine) GetCPUs() int { + if c == nil || c.CPUs == nil { + return 0 + } + return *c.CPUs +} + +// GetDisplayName returns the DisplayName field if it's non-nil, zero value otherwise. +func (c *CodespacesMachine) GetDisplayName() string { + if c == nil || c.DisplayName == nil { + return "" + } + return *c.DisplayName +} + +// GetMemoryInBytes returns the MemoryInBytes field if it's non-nil, zero value otherwise. +func (c *CodespacesMachine) GetMemoryInBytes() int64 { + if c == nil || c.MemoryInBytes == nil { + return 0 + } + return *c.MemoryInBytes +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CodespacesMachine) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetOperatingSystem returns the OperatingSystem field if it's non-nil, zero value otherwise. +func (c *CodespacesMachine) GetOperatingSystem() string { + if c == nil || c.OperatingSystem == nil { + return "" + } + return *c.OperatingSystem +} + +// GetPrebuildAvailability returns the PrebuildAvailability field if it's non-nil, zero value otherwise. +func (c *CodespacesMachine) GetPrebuildAvailability() string { + if c == nil || c.PrebuildAvailability == nil { + return "" + } + return *c.PrebuildAvailability +} + +// GetStorageInBytes returns the StorageInBytes field if it's non-nil, zero value otherwise. +func (c *CodespacesMachine) GetStorageInBytes() int64 { + if c == nil || c.StorageInBytes == nil { + return 0 + } + return *c.StorageInBytes +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *CollaboratorInvitation) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *CollaboratorInvitation) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CollaboratorInvitation) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetInvitee returns the Invitee field. +func (c *CollaboratorInvitation) GetInvitee() *User { + if c == nil { + return nil + } + return c.Invitee +} + +// GetInviter returns the Inviter field. +func (c *CollaboratorInvitation) GetInviter() *User { + if c == nil { + return nil + } + return c.Inviter +} + +// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise. +func (c *CollaboratorInvitation) GetPermissions() string { + if c == nil || c.Permissions == nil { + return "" + } + return *c.Permissions +} + +// GetRepo returns the Repo field. +func (c *CollaboratorInvitation) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CollaboratorInvitation) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetCommitURL returns the CommitURL field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetCommitURL() string { + if c == nil || c.CommitURL == nil { + return "" + } + return *c.CommitURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetRepositoryURL() string { + if c == nil || c.RepositoryURL == nil { + return "" + } + return *c.RepositoryURL +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetSHA() string { + if c == nil || c.SHA == nil { + return "" + } + return *c.SHA +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetState() string { + if c == nil || c.State == nil { + return "" + } + return *c.State +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetTotalCount() int { + if c == nil || c.TotalCount == nil { + return 0 + } + return *c.TotalCount +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *Comment) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (c *CommentDiscussion) GetAuthorAssociation() string { + if c == nil || c.AuthorAssociation == nil { + return "" + } + return *c.AuthorAssociation +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (c *CommentDiscussion) GetBody() string { + if c == nil || c.Body == nil { + return "" + } + return *c.Body +} + +// GetChildCommentCount returns the ChildCommentCount field if it's non-nil, zero value otherwise. +func (c *CommentDiscussion) GetChildCommentCount() int { + if c == nil || c.ChildCommentCount == nil { + return 0 + } + return *c.ChildCommentCount +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *CommentDiscussion) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetDiscussionID returns the DiscussionID field if it's non-nil, zero value otherwise. +func (c *CommentDiscussion) GetDiscussionID() int64 { + if c == nil || c.DiscussionID == nil { + return 0 + } + return *c.DiscussionID +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *CommentDiscussion) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CommentDiscussion) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *CommentDiscussion) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetParentID returns the ParentID field if it's non-nil, zero value otherwise. +func (c *CommentDiscussion) GetParentID() int64 { + if c == nil || c.ParentID == nil { + return 0 + } + return *c.ParentID +} + +// GetReactions returns the Reactions field. +func (c *CommentDiscussion) GetReactions() *Reactions { + if c == nil { + return nil + } + return c.Reactions +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (c *CommentDiscussion) GetRepositoryURL() string { + if c == nil || c.RepositoryURL == nil { + return "" + } + return *c.RepositoryURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (c *CommentDiscussion) GetUpdatedAt() Timestamp { + if c == nil || c.UpdatedAt == nil { + return Timestamp{} + } + return *c.UpdatedAt +} + +// GetUser returns the User field. +func (c *CommentDiscussion) GetUser() *User { + if c == nil { + return nil + } + return c.User +} + +// GetTotalCommitComments returns the TotalCommitComments field if it's non-nil, zero value otherwise. +func (c *CommentStats) GetTotalCommitComments() int { + if c == nil || c.TotalCommitComments == nil { + return 0 + } + return *c.TotalCommitComments +} + +// GetTotalGistComments returns the TotalGistComments field if it's non-nil, zero value otherwise. +func (c *CommentStats) GetTotalGistComments() int { + if c == nil || c.TotalGistComments == nil { + return 0 + } + return *c.TotalGistComments +} + +// GetTotalIssueComments returns the TotalIssueComments field if it's non-nil, zero value otherwise. +func (c *CommentStats) GetTotalIssueComments() int { + if c == nil || c.TotalIssueComments == nil { + return 0 + } + return *c.TotalIssueComments +} + +// GetTotalPullRequestComments returns the TotalPullRequestComments field if it's non-nil, zero value otherwise. +func (c *CommentStats) GetTotalPullRequestComments() int { + if c == nil || c.TotalPullRequestComments == nil { + return 0 + } + return *c.TotalPullRequestComments +} + +// GetAuthor returns the Author field. +func (c *Commit) GetAuthor() *CommitAuthor { + if c == nil { + return nil + } + return c.Author +} + +// GetCommentCount returns the CommentCount field if it's non-nil, zero value otherwise. +func (c *Commit) GetCommentCount() int { + if c == nil || c.CommentCount == nil { + return 0 + } + return *c.CommentCount +} + +// GetCommitter returns the Committer field. +func (c *Commit) GetCommitter() *CommitAuthor { + if c == nil { + return nil + } + return c.Committer +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *Commit) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (c *Commit) GetMessage() string { + if c == nil || c.Message == nil { + return "" + } + return *c.Message +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *Commit) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (c *Commit) GetSHA() string { + if c == nil || c.SHA == nil { + return "" + } + return *c.SHA +} + +// GetTree returns the Tree field. +func (c *Commit) GetTree() *Tree { + if c == nil { + return nil + } + return c.Tree +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *Commit) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetVerification returns the Verification field. +func (c *Commit) GetVerification() *SignatureVerification { + if c == nil { + return nil + } + return c.Verification +} + +// GetDate returns the Date field if it's non-nil, zero value otherwise. +func (c *CommitAuthor) GetDate() Timestamp { + if c == nil || c.Date == nil { + return Timestamp{} + } + return *c.Date +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (c *CommitAuthor) GetEmail() string { + if c == nil || c.Email == nil { + return "" + } + return *c.Email +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (c *CommitAuthor) GetLogin() string { + if c == nil || c.Login == nil { + return "" + } + return *c.Login +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CommitAuthor) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (c *CommitCommentEvent) GetAction() string { + if c == nil || c.Action == nil { + return "" + } + return *c.Action +} + +// GetComment returns the Comment field. +func (c *CommitCommentEvent) GetComment() *RepositoryComment { + if c == nil { + return nil + } + return c.Comment +} + +// GetInstallation returns the Installation field. +func (c *CommitCommentEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetOrg returns the Org field. +func (c *CommitCommentEvent) GetOrg() *Organization { + if c == nil { + return nil + } + return c.Org +} + +// GetRepo returns the Repo field. +func (c *CommitCommentEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetSender returns the Sender field. +func (c *CommitCommentEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetAdditions returns the Additions field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetAdditions() int { + if c == nil || c.Additions == nil { + return 0 + } + return *c.Additions +} + +// GetBlobURL returns the BlobURL field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetBlobURL() string { + if c == nil || c.BlobURL == nil { + return "" + } + return *c.BlobURL +} + +// GetChanges returns the Changes field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetChanges() int { + if c == nil || c.Changes == nil { + return 0 + } + return *c.Changes +} + +// GetContentsURL returns the ContentsURL field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetContentsURL() string { + if c == nil || c.ContentsURL == nil { + return "" + } + return *c.ContentsURL +} + +// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetDeletions() int { + if c == nil || c.Deletions == nil { + return 0 + } + return *c.Deletions +} + +// GetFilename returns the Filename field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetFilename() string { + if c == nil || c.Filename == nil { + return "" + } + return *c.Filename +} + +// GetPatch returns the Patch field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetPatch() string { + if c == nil || c.Patch == nil { + return "" + } + return *c.Patch +} + +// GetPreviousFilename returns the PreviousFilename field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetPreviousFilename() string { + if c == nil || c.PreviousFilename == nil { + return "" + } + return *c.PreviousFilename +} + +// GetRawURL returns the RawURL field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetRawURL() string { + if c == nil || c.RawURL == nil { + return "" + } + return *c.RawURL +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetSHA() string { + if c == nil || c.SHA == nil { + return "" + } + return *c.SHA +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetStatus() string { + if c == nil || c.Status == nil { + return "" + } + return *c.Status +} + +// GetAuthor returns the Author field. +func (c *CommitResult) GetAuthor() *User { + if c == nil { + return nil + } + return c.Author +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (c *CommitResult) GetCommentsURL() string { + if c == nil || c.CommentsURL == nil { + return "" + } + return *c.CommentsURL +} + +// GetCommit returns the Commit field. +func (c *CommitResult) GetCommit() *Commit { + if c == nil { + return nil + } + return c.Commit +} + +// GetCommitter returns the Committer field. +func (c *CommitResult) GetCommitter() *User { + if c == nil { + return nil + } + return c.Committer +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *CommitResult) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetRepository returns the Repository field. +func (c *CommitResult) GetRepository() *Repository { + if c == nil { + return nil + } + return c.Repository +} + +// GetScore returns the Score field. +func (c *CommitResult) GetScore() *float64 { + if c == nil { + return nil + } + return c.Score +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (c *CommitResult) GetSHA() string { + if c == nil || c.SHA == nil { + return "" + } + return *c.SHA +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CommitResult) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetAheadBy returns the AheadBy field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetAheadBy() int { + if c == nil || c.AheadBy == nil { + return 0 + } + return *c.AheadBy +} + +// GetBaseCommit returns the BaseCommit field. +func (c *CommitsComparison) GetBaseCommit() *RepositoryCommit { + if c == nil { + return nil + } + return c.BaseCommit +} + +// GetBehindBy returns the BehindBy field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetBehindBy() int { + if c == nil || c.BehindBy == nil { + return 0 + } + return *c.BehindBy +} + +// GetDiffURL returns the DiffURL field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetDiffURL() string { + if c == nil || c.DiffURL == nil { + return "" + } + return *c.DiffURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetMergeBaseCommit returns the MergeBaseCommit field. +func (c *CommitsComparison) GetMergeBaseCommit() *RepositoryCommit { + if c == nil { + return nil + } + return c.MergeBaseCommit +} + +// GetPatchURL returns the PatchURL field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetPatchURL() string { + if c == nil || c.PatchURL == nil { + return "" + } + return *c.PatchURL +} + +// GetPermalinkURL returns the PermalinkURL field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetPermalinkURL() string { + if c == nil || c.PermalinkURL == nil { + return "" + } + return *c.PermalinkURL +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetStatus() string { + if c == nil || c.Status == nil { + return "" + } + return *c.Status +} + +// GetTotalCommits returns the TotalCommits field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetTotalCommits() int { + if c == nil || c.TotalCommits == nil { + return 0 + } + return *c.TotalCommits +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (c *CommitsSearchResult) GetIncompleteResults() bool { + if c == nil || c.IncompleteResults == nil { + return false + } + return *c.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (c *CommitsSearchResult) GetTotal() int { + if c == nil || c.Total == nil { + return 0 + } + return *c.Total +} + +// GetAdditions returns the Additions field if it's non-nil, zero value otherwise. +func (c *CommitStats) GetAdditions() int { + if c == nil || c.Additions == nil { + return 0 + } + return *c.Additions +} + +// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. +func (c *CommitStats) GetDeletions() int { + if c == nil || c.Deletions == nil { + return 0 + } + return *c.Deletions +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (c *CommitStats) GetTotal() int { + if c == nil || c.Total == nil { + return 0 + } + return *c.Total +} + +// GetCodeOfConduct returns the CodeOfConduct field. +func (c *CommunityHealthFiles) GetCodeOfConduct() *Metric { + if c == nil { + return nil + } + return c.CodeOfConduct +} + +// GetCodeOfConductFile returns the CodeOfConductFile field. +func (c *CommunityHealthFiles) GetCodeOfConductFile() *Metric { + if c == nil { + return nil + } + return c.CodeOfConductFile +} + +// GetContributing returns the Contributing field. +func (c *CommunityHealthFiles) GetContributing() *Metric { + if c == nil { + return nil + } + return c.Contributing +} + +// GetIssueTemplate returns the IssueTemplate field. +func (c *CommunityHealthFiles) GetIssueTemplate() *Metric { + if c == nil { + return nil + } + return c.IssueTemplate +} + +// GetLicense returns the License field. +func (c *CommunityHealthFiles) GetLicense() *Metric { + if c == nil { + return nil + } + return c.License +} + +// GetPullRequestTemplate returns the PullRequestTemplate field. +func (c *CommunityHealthFiles) GetPullRequestTemplate() *Metric { + if c == nil { + return nil + } + return c.PullRequestTemplate +} + +// GetReadme returns the Readme field. +func (c *CommunityHealthFiles) GetReadme() *Metric { + if c == nil { + return nil + } + return c.Readme +} + +// GetContentReportsEnabled returns the ContentReportsEnabled field if it's non-nil, zero value otherwise. +func (c *CommunityHealthMetrics) GetContentReportsEnabled() bool { + if c == nil || c.ContentReportsEnabled == nil { + return false + } + return *c.ContentReportsEnabled +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (c *CommunityHealthMetrics) GetDescription() string { + if c == nil || c.Description == nil { + return "" + } + return *c.Description +} + +// GetDocumentation returns the Documentation field if it's non-nil, zero value otherwise. +func (c *CommunityHealthMetrics) GetDocumentation() string { + if c == nil || c.Documentation == nil { + return "" + } + return *c.Documentation +} + +// GetFiles returns the Files field. +func (c *CommunityHealthMetrics) GetFiles() *CommunityHealthFiles { + if c == nil { + return nil + } + return c.Files +} + +// GetHealthPercentage returns the HealthPercentage field if it's non-nil, zero value otherwise. +func (c *CommunityHealthMetrics) GetHealthPercentage() int { + if c == nil || c.HealthPercentage == nil { + return 0 + } + return *c.HealthPercentage +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (c *CommunityHealthMetrics) GetUpdatedAt() Timestamp { + if c == nil || c.UpdatedAt == nil { + return Timestamp{} + } + return *c.UpdatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *ContentReference) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *ContentReference) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetReference returns the Reference field if it's non-nil, zero value otherwise. +func (c *ContentReference) GetReference() string { + if c == nil || c.Reference == nil { + return "" + } + return *c.Reference +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (c *ContentReferenceEvent) GetAction() string { + if c == nil || c.Action == nil { + return "" + } + return *c.Action +} + +// GetContentReference returns the ContentReference field. +func (c *ContentReferenceEvent) GetContentReference() *ContentReference { + if c == nil { + return nil + } + return c.ContentReference +} + +// GetInstallation returns the Installation field. +func (c *ContentReferenceEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetRepo returns the Repo field. +func (c *ContentReferenceEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetSender returns the Sender field. +func (c *ContentReferenceEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetAvatarURL() string { + if c == nil || c.AvatarURL == nil { + return "" + } + return *c.AvatarURL +} + +// GetContributions returns the Contributions field if it's non-nil, zero value otherwise. +func (c *Contributor) GetContributions() int { + if c == nil || c.Contributions == nil { + return 0 + } + return *c.Contributions +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (c *Contributor) GetEmail() string { + if c == nil || c.Email == nil { + return "" + } + return *c.Email +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetEventsURL() string { + if c == nil || c.EventsURL == nil { + return "" + } + return *c.EventsURL +} + +// GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetFollowersURL() string { + if c == nil || c.FollowersURL == nil { + return "" + } + return *c.FollowersURL +} + +// GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetFollowingURL() string { + if c == nil || c.FollowingURL == nil { + return "" + } + return *c.FollowingURL +} + +// GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetGistsURL() string { + if c == nil || c.GistsURL == nil { + return "" + } + return *c.GistsURL +} + +// GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise. +func (c *Contributor) GetGravatarID() string { + if c == nil || c.GravatarID == nil { + return "" + } + return *c.GravatarID +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *Contributor) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (c *Contributor) GetLogin() string { + if c == nil || c.Login == nil { + return "" + } + return *c.Login +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *Contributor) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *Contributor) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetOrganizationsURL() string { + if c == nil || c.OrganizationsURL == nil { + return "" + } + return *c.OrganizationsURL +} + +// GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetReceivedEventsURL() string { + if c == nil || c.ReceivedEventsURL == nil { + return "" + } + return *c.ReceivedEventsURL +} + +// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetReposURL() string { + if c == nil || c.ReposURL == nil { + return "" + } + return *c.ReposURL +} + +// GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise. +func (c *Contributor) GetSiteAdmin() bool { + if c == nil || c.SiteAdmin == nil { + return false + } + return *c.SiteAdmin +} + +// GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetStarredURL() string { + if c == nil || c.StarredURL == nil { + return "" + } + return *c.StarredURL +} + +// GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetSubscriptionsURL() string { + if c == nil || c.SubscriptionsURL == nil { + return "" + } + return *c.SubscriptionsURL +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (c *Contributor) GetType() string { + if c == nil || c.Type == nil { + return "" + } + return *c.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetAuthor returns the Author field. +func (c *ContributorStats) GetAuthor() *Contributor { + if c == nil { + return nil + } + return c.Author +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (c *ContributorStats) GetTotal() int { + if c == nil || c.Total == nil { + return 0 + } + return *c.Total +} + +// GetCustomModelTrainingDate returns the CustomModelTrainingDate field if it's non-nil, zero value otherwise. +func (c *CopilotDotcomChatModel) GetCustomModelTrainingDate() string { + if c == nil || c.CustomModelTrainingDate == nil { + return "" + } + return *c.CustomModelTrainingDate +} + +// GetCustomModelTrainingDate returns the CustomModelTrainingDate field if it's non-nil, zero value otherwise. +func (c *CopilotDotcomPullRequestsModel) GetCustomModelTrainingDate() string { + if c == nil || c.CustomModelTrainingDate == nil { + return "" + } + return *c.CustomModelTrainingDate +} + +// GetCustomModelTrainingDate returns the CustomModelTrainingDate field if it's non-nil, zero value otherwise. +func (c *CopilotIDEChatModel) GetCustomModelTrainingDate() string { + if c == nil || c.CustomModelTrainingDate == nil { + return "" + } + return *c.CustomModelTrainingDate +} + +// GetCustomModelTrainingDate returns the CustomModelTrainingDate field if it's non-nil, zero value otherwise. +func (c *CopilotIDECodeCompletionsModel) GetCustomModelTrainingDate() string { + if c == nil || c.CustomModelTrainingDate == nil { + return "" + } + return *c.CustomModelTrainingDate +} + +// GetCopilotDotcomChat returns the CopilotDotcomChat field. +func (c *CopilotMetrics) GetCopilotDotcomChat() *CopilotDotcomChat { + if c == nil { + return nil + } + return c.CopilotDotcomChat +} + +// GetCopilotDotcomPullRequests returns the CopilotDotcomPullRequests field. +func (c *CopilotMetrics) GetCopilotDotcomPullRequests() *CopilotDotcomPullRequests { + if c == nil { + return nil + } + return c.CopilotDotcomPullRequests +} + +// GetCopilotIDEChat returns the CopilotIDEChat field. +func (c *CopilotMetrics) GetCopilotIDEChat() *CopilotIDEChat { + if c == nil { + return nil + } + return c.CopilotIDEChat +} + +// GetCopilotIDECodeCompletions returns the CopilotIDECodeCompletions field. +func (c *CopilotMetrics) GetCopilotIDECodeCompletions() *CopilotIDECodeCompletions { + if c == nil { + return nil + } + return c.CopilotIDECodeCompletions +} + +// GetTotalActiveUsers returns the TotalActiveUsers field if it's non-nil, zero value otherwise. +func (c *CopilotMetrics) GetTotalActiveUsers() int { + if c == nil || c.TotalActiveUsers == nil { + return 0 + } + return *c.TotalActiveUsers +} + +// GetTotalEngagedUsers returns the TotalEngagedUsers field if it's non-nil, zero value otherwise. +func (c *CopilotMetrics) GetTotalEngagedUsers() int { + if c == nil || c.TotalEngagedUsers == nil { + return 0 + } + return *c.TotalEngagedUsers +} + +// GetSince returns the Since field if it's non-nil, zero value otherwise. +func (c *CopilotMetricsListOptions) GetSince() time.Time { + if c == nil || c.Since == nil { + return time.Time{} + } + return *c.Since +} + +// GetUntil returns the Until field if it's non-nil, zero value otherwise. +func (c *CopilotMetricsListOptions) GetUntil() time.Time { + if c == nil || c.Until == nil { + return time.Time{} + } + return *c.Until +} + +// GetSeatBreakdown returns the SeatBreakdown field. +func (c *CopilotOrganizationDetails) GetSeatBreakdown() *CopilotSeatBreakdown { + if c == nil { + return nil + } + return c.SeatBreakdown +} + +// GetAssigningTeam returns the AssigningTeam field. +func (c *CopilotSeatDetails) GetAssigningTeam() *Team { + if c == nil { + return nil + } + return c.AssigningTeam +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *CopilotSeatDetails) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetLastActivityAt returns the LastActivityAt field if it's non-nil, zero value otherwise. +func (c *CopilotSeatDetails) GetLastActivityAt() Timestamp { + if c == nil || c.LastActivityAt == nil { + return Timestamp{} + } + return *c.LastActivityAt +} + +// GetLastActivityEditor returns the LastActivityEditor field if it's non-nil, zero value otherwise. +func (c *CopilotSeatDetails) GetLastActivityEditor() string { + if c == nil || c.LastActivityEditor == nil { + return "" + } + return *c.LastActivityEditor +} + +// GetPendingCancellationDate returns the PendingCancellationDate field if it's non-nil, zero value otherwise. +func (c *CopilotSeatDetails) GetPendingCancellationDate() string { + if c == nil || c.PendingCancellationDate == nil { + return "" + } + return *c.PendingCancellationDate +} + +// GetPlanType returns the PlanType field if it's non-nil, zero value otherwise. +func (c *CopilotSeatDetails) GetPlanType() string { + if c == nil || c.PlanType == nil { + return "" + } + return *c.PlanType +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (c *CopilotSeatDetails) GetUpdatedAt() Timestamp { + if c == nil || c.UpdatedAt == nil { + return Timestamp{} + } + return *c.UpdatedAt +} + +// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. +func (c *CreateCheckRunOptions) GetCompletedAt() Timestamp { + if c == nil || c.CompletedAt == nil { + return Timestamp{} + } + return *c.CompletedAt +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (c *CreateCheckRunOptions) GetConclusion() string { + if c == nil || c.Conclusion == nil { + return "" + } + return *c.Conclusion +} + +// GetDetailsURL returns the DetailsURL field if it's non-nil, zero value otherwise. +func (c *CreateCheckRunOptions) GetDetailsURL() string { + if c == nil || c.DetailsURL == nil { + return "" + } + return *c.DetailsURL +} + +// GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise. +func (c *CreateCheckRunOptions) GetExternalID() string { + if c == nil || c.ExternalID == nil { + return "" + } + return *c.ExternalID +} + +// GetOutput returns the Output field. +func (c *CreateCheckRunOptions) GetOutput() *CheckRunOutput { + if c == nil { + return nil + } + return c.Output +} + +// GetStartedAt returns the StartedAt field if it's non-nil, zero value otherwise. +func (c *CreateCheckRunOptions) GetStartedAt() Timestamp { + if c == nil || c.StartedAt == nil { + return Timestamp{} + } + return *c.StartedAt +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (c *CreateCheckRunOptions) GetStatus() string { + if c == nil || c.Status == nil { + return "" + } + return *c.Status +} + +// GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise. +func (c *CreateCheckSuiteOptions) GetHeadBranch() string { + if c == nil || c.HeadBranch == nil { + return "" + } + return *c.HeadBranch +} + +// GetClientIP returns the ClientIP field if it's non-nil, zero value otherwise. +func (c *CreateCodespaceOptions) GetClientIP() string { + if c == nil || c.ClientIP == nil { + return "" + } + return *c.ClientIP +} + +// GetDevcontainerPath returns the DevcontainerPath field if it's non-nil, zero value otherwise. +func (c *CreateCodespaceOptions) GetDevcontainerPath() string { + if c == nil || c.DevcontainerPath == nil { + return "" + } + return *c.DevcontainerPath +} + +// GetDisplayName returns the DisplayName field if it's non-nil, zero value otherwise. +func (c *CreateCodespaceOptions) GetDisplayName() string { + if c == nil || c.DisplayName == nil { + return "" + } + return *c.DisplayName +} + +// GetGeo returns the Geo field if it's non-nil, zero value otherwise. +func (c *CreateCodespaceOptions) GetGeo() string { + if c == nil || c.Geo == nil { + return "" + } + return *c.Geo +} + +// GetIdleTimeoutMinutes returns the IdleTimeoutMinutes field if it's non-nil, zero value otherwise. +func (c *CreateCodespaceOptions) GetIdleTimeoutMinutes() int { + if c == nil || c.IdleTimeoutMinutes == nil { + return 0 + } + return *c.IdleTimeoutMinutes +} + +// GetMachine returns the Machine field if it's non-nil, zero value otherwise. +func (c *CreateCodespaceOptions) GetMachine() string { + if c == nil || c.Machine == nil { + return "" + } + return *c.Machine +} + +// GetMultiRepoPermissionsOptOut returns the MultiRepoPermissionsOptOut field if it's non-nil, zero value otherwise. +func (c *CreateCodespaceOptions) GetMultiRepoPermissionsOptOut() bool { + if c == nil || c.MultiRepoPermissionsOptOut == nil { + return false + } + return *c.MultiRepoPermissionsOptOut +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (c *CreateCodespaceOptions) GetRef() string { + if c == nil || c.Ref == nil { + return "" + } + return *c.Ref +} + +// GetRetentionPeriodMinutes returns the RetentionPeriodMinutes field if it's non-nil, zero value otherwise. +func (c *CreateCodespaceOptions) GetRetentionPeriodMinutes() int { + if c == nil || c.RetentionPeriodMinutes == nil { + return 0 + } + return *c.RetentionPeriodMinutes +} + +// GetWorkingDirectory returns the WorkingDirectory field if it's non-nil, zero value otherwise. +func (c *CreateCodespaceOptions) GetWorkingDirectory() string { + if c == nil || c.WorkingDirectory == nil { + return "" + } + return *c.WorkingDirectory +} + +// GetAllowsPublicRepositories returns the AllowsPublicRepositories field if it's non-nil, zero value otherwise. +func (c *CreateEnterpriseRunnerGroupRequest) GetAllowsPublicRepositories() bool { + if c == nil || c.AllowsPublicRepositories == nil { + return false + } + return *c.AllowsPublicRepositories +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CreateEnterpriseRunnerGroupRequest) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetRestrictedToWorkflows returns the RestrictedToWorkflows field if it's non-nil, zero value otherwise. +func (c *CreateEnterpriseRunnerGroupRequest) GetRestrictedToWorkflows() bool { + if c == nil || c.RestrictedToWorkflows == nil { + return false + } + return *c.RestrictedToWorkflows +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (c *CreateEnterpriseRunnerGroupRequest) GetVisibility() string { + if c == nil || c.Visibility == nil { + return "" + } + return *c.Visibility +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (c *CreateEvent) GetDescription() string { + if c == nil || c.Description == nil { + return "" + } + return *c.Description +} + +// GetInstallation returns the Installation field. +func (c *CreateEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetMasterBranch returns the MasterBranch field if it's non-nil, zero value otherwise. +func (c *CreateEvent) GetMasterBranch() string { + if c == nil || c.MasterBranch == nil { + return "" + } + return *c.MasterBranch +} + +// GetOrg returns the Org field. +func (c *CreateEvent) GetOrg() *Organization { + if c == nil { + return nil + } + return c.Org +} + +// GetPusherType returns the PusherType field if it's non-nil, zero value otherwise. +func (c *CreateEvent) GetPusherType() string { + if c == nil || c.PusherType == nil { + return "" + } + return *c.PusherType +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (c *CreateEvent) GetRef() string { + if c == nil || c.Ref == nil { + return "" + } + return *c.Ref +} + +// GetRefType returns the RefType field if it's non-nil, zero value otherwise. +func (c *CreateEvent) GetRefType() string { + if c == nil || c.RefType == nil { + return "" + } + return *c.RefType +} + +// GetRepo returns the Repo field. +func (c *CreateEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetSender returns the Sender field. +func (c *CreateEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (c *CreateOrgInvitationOptions) GetEmail() string { + if c == nil || c.Email == nil { + return "" + } + return *c.Email +} + +// GetInviteeID returns the InviteeID field if it's non-nil, zero value otherwise. +func (c *CreateOrgInvitationOptions) GetInviteeID() int64 { + if c == nil || c.InviteeID == nil { + return 0 + } + return *c.InviteeID +} + +// GetRole returns the Role field if it's non-nil, zero value otherwise. +func (c *CreateOrgInvitationOptions) GetRole() string { + if c == nil || c.Role == nil { + return "" + } + return *c.Role +} + +// GetBaseRole returns the BaseRole field if it's non-nil, zero value otherwise. +func (c *CreateOrUpdateCustomRepoRoleOptions) GetBaseRole() string { + if c == nil || c.BaseRole == nil { + return "" + } + return *c.BaseRole +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (c *CreateOrUpdateCustomRepoRoleOptions) GetDescription() string { + if c == nil || c.Description == nil { + return "" + } + return *c.Description +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CreateOrUpdateCustomRepoRoleOptions) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetBaseRole returns the BaseRole field if it's non-nil, zero value otherwise. +func (c *CreateOrUpdateOrgRoleOptions) GetBaseRole() string { + if c == nil || c.BaseRole == nil { + return "" + } + return *c.BaseRole +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (c *CreateOrUpdateOrgRoleOptions) GetDescription() string { + if c == nil || c.Description == nil { + return "" + } + return *c.Description +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CreateOrUpdateOrgRoleOptions) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (c *CreateProtectedChanges) GetFrom() bool { + if c == nil || c.From == nil { + return false + } + return *c.From +} + +// GetAllowsPublicRepositories returns the AllowsPublicRepositories field if it's non-nil, zero value otherwise. +func (c *CreateRunnerGroupRequest) GetAllowsPublicRepositories() bool { + if c == nil || c.AllowsPublicRepositories == nil { + return false + } + return *c.AllowsPublicRepositories +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CreateRunnerGroupRequest) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetRestrictedToWorkflows returns the RestrictedToWorkflows field if it's non-nil, zero value otherwise. +func (c *CreateRunnerGroupRequest) GetRestrictedToWorkflows() bool { + if c == nil || c.RestrictedToWorkflows == nil { + return false + } + return *c.RestrictedToWorkflows +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (c *CreateRunnerGroupRequest) GetVisibility() string { + if c == nil || c.Visibility == nil { + return "" + } + return *c.Visibility +} + +// GetCanAdminsBypass returns the CanAdminsBypass field if it's non-nil, zero value otherwise. +func (c *CreateUpdateEnvironment) GetCanAdminsBypass() bool { + if c == nil || c.CanAdminsBypass == nil { + return false + } + return *c.CanAdminsBypass +} + +// GetDeploymentBranchPolicy returns the DeploymentBranchPolicy field. +func (c *CreateUpdateEnvironment) GetDeploymentBranchPolicy() *BranchPolicy { + if c == nil { + return nil + } + return c.DeploymentBranchPolicy +} + +// GetPreventSelfReview returns the PreventSelfReview field if it's non-nil, zero value otherwise. +func (c *CreateUpdateEnvironment) GetPreventSelfReview() bool { + if c == nil || c.PreventSelfReview == nil { + return false + } + return *c.PreventSelfReview +} + +// GetWaitTimer returns the WaitTimer field if it's non-nil, zero value otherwise. +func (c *CreateUpdateEnvironment) GetWaitTimer() int { + if c == nil || c.WaitTimer == nil { + return 0 + } + return *c.WaitTimer +} + +// GetRepositoryID returns the RepositoryID field if it's non-nil, zero value otherwise. +func (c *CreateUpdateRequiredWorkflowOptions) GetRepositoryID() int64 { + if c == nil || c.RepositoryID == nil { + return 0 + } + return *c.RepositoryID +} + +// GetScope returns the Scope field if it's non-nil, zero value otherwise. +func (c *CreateUpdateRequiredWorkflowOptions) GetScope() string { + if c == nil || c.Scope == nil { + return "" + } + return *c.Scope +} + +// GetSelectedRepositoryIDs returns the SelectedRepositoryIDs field. +func (c *CreateUpdateRequiredWorkflowOptions) GetSelectedRepositoryIDs() *SelectedRepoIDs { + if c == nil { + return nil + } + return c.SelectedRepositoryIDs +} + +// GetWorkflowFilePath returns the WorkflowFilePath field if it's non-nil, zero value otherwise. +func (c *CreateUpdateRequiredWorkflowOptions) GetWorkflowFilePath() string { + if c == nil || c.WorkflowFilePath == nil { + return "" + } + return *c.WorkflowFilePath +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (c *CreateUserRequest) GetEmail() string { + if c == nil || c.Email == nil { + return "" + } + return *c.Email +} + +// GetSuspended returns the Suspended field if it's non-nil, zero value otherwise. +func (c *CreateUserRequest) GetSuspended() bool { + if c == nil || c.Suspended == nil { + return false + } + return *c.Suspended +} + +// GetCreated returns the Created field if it's non-nil, zero value otherwise. +func (c *CreationInfo) GetCreated() Timestamp { + if c == nil || c.Created == nil { + return Timestamp{} + } + return *c.Created +} + +// GetAuthorizedCredentialExpiresAt returns the AuthorizedCredentialExpiresAt field if it's non-nil, zero value otherwise. +func (c *CredentialAuthorization) GetAuthorizedCredentialExpiresAt() Timestamp { + if c == nil || c.AuthorizedCredentialExpiresAt == nil { + return Timestamp{} + } + return *c.AuthorizedCredentialExpiresAt +} + +// GetAuthorizedCredentialID returns the AuthorizedCredentialID field if it's non-nil, zero value otherwise. +func (c *CredentialAuthorization) GetAuthorizedCredentialID() int64 { + if c == nil || c.AuthorizedCredentialID == nil { + return 0 + } + return *c.AuthorizedCredentialID +} + +// GetAuthorizedCredentialNote returns the AuthorizedCredentialNote field if it's non-nil, zero value otherwise. +func (c *CredentialAuthorization) GetAuthorizedCredentialNote() string { + if c == nil || c.AuthorizedCredentialNote == nil { + return "" + } + return *c.AuthorizedCredentialNote +} + +// GetAuthorizedCredentialTitle returns the AuthorizedCredentialTitle field if it's non-nil, zero value otherwise. +func (c *CredentialAuthorization) GetAuthorizedCredentialTitle() string { + if c == nil || c.AuthorizedCredentialTitle == nil { + return "" + } + return *c.AuthorizedCredentialTitle +} + +// GetCredentialAccessedAt returns the CredentialAccessedAt field if it's non-nil, zero value otherwise. +func (c *CredentialAuthorization) GetCredentialAccessedAt() Timestamp { + if c == nil || c.CredentialAccessedAt == nil { + return Timestamp{} + } + return *c.CredentialAccessedAt +} + +// GetCredentialAuthorizedAt returns the CredentialAuthorizedAt field if it's non-nil, zero value otherwise. +func (c *CredentialAuthorization) GetCredentialAuthorizedAt() Timestamp { + if c == nil || c.CredentialAuthorizedAt == nil { + return Timestamp{} + } + return *c.CredentialAuthorizedAt +} + +// GetCredentialID returns the CredentialID field if it's non-nil, zero value otherwise. +func (c *CredentialAuthorization) GetCredentialID() int64 { + if c == nil || c.CredentialID == nil { + return 0 + } + return *c.CredentialID +} + +// GetCredentialType returns the CredentialType field if it's non-nil, zero value otherwise. +func (c *CredentialAuthorization) GetCredentialType() string { + if c == nil || c.CredentialType == nil { + return "" + } + return *c.CredentialType +} + +// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. +func (c *CredentialAuthorization) GetFingerprint() string { + if c == nil || c.Fingerprint == nil { + return "" + } + return *c.Fingerprint +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (c *CredentialAuthorization) GetLogin() string { + if c == nil || c.Login == nil { + return "" + } + return *c.Login +} + +// GetTokenLastEight returns the TokenLastEight field if it's non-nil, zero value otherwise. +func (c *CredentialAuthorization) GetTokenLastEight() string { + if c == nil || c.TokenLastEight == nil { + return "" + } + return *c.TokenLastEight +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (c *Credit) GetType() string { + if c == nil || c.Type == nil { + return "" + } + return *c.Type +} + +// GetUser returns the User field. +func (c *Credit) GetUser() *User { + if c == nil { + return nil + } + return c.User +} + +// GetApp returns the App field. +func (c *CustomDeploymentProtectionRule) GetApp() *CustomDeploymentProtectionRuleApp { + if c == nil { + return nil + } + return c.App +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (c *CustomDeploymentProtectionRule) GetEnabled() bool { + if c == nil || c.Enabled == nil { + return false + } + return *c.Enabled +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CustomDeploymentProtectionRule) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *CustomDeploymentProtectionRule) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CustomDeploymentProtectionRuleApp) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetIntegrationURL returns the IntegrationURL field if it's non-nil, zero value otherwise. +func (c *CustomDeploymentProtectionRuleApp) GetIntegrationURL() string { + if c == nil || c.IntegrationURL == nil { + return "" + } + return *c.IntegrationURL +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *CustomDeploymentProtectionRuleApp) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetSlug returns the Slug field if it's non-nil, zero value otherwise. +func (c *CustomDeploymentProtectionRuleApp) GetSlug() string { + if c == nil || c.Slug == nil { + return "" + } + return *c.Slug +} + +// GetIntegrationID returns the IntegrationID field if it's non-nil, zero value otherwise. +func (c *CustomDeploymentProtectionRuleRequest) GetIntegrationID() int64 { + if c == nil || c.IntegrationID == nil { + return 0 + } + return *c.IntegrationID +} + +// GetBaseRole returns the BaseRole field if it's non-nil, zero value otherwise. +func (c *CustomOrgRoles) GetBaseRole() string { + if c == nil || c.BaseRole == nil { + return "" + } + return *c.BaseRole +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *CustomOrgRoles) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (c *CustomOrgRoles) GetDescription() string { + if c == nil || c.Description == nil { + return "" + } + return *c.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CustomOrgRoles) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CustomOrgRoles) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetOrg returns the Org field. +func (c *CustomOrgRoles) GetOrg() *Organization { + if c == nil { + return nil + } + return c.Org +} + +// GetSource returns the Source field if it's non-nil, zero value otherwise. +func (c *CustomOrgRoles) GetSource() string { + if c == nil || c.Source == nil { + return "" + } + return *c.Source +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (c *CustomOrgRoles) GetUpdatedAt() Timestamp { + if c == nil || c.UpdatedAt == nil { + return Timestamp{} + } + return *c.UpdatedAt +} + +// GetDefaultValue returns the DefaultValue field if it's non-nil, zero value otherwise. +func (c *CustomProperty) GetDefaultValue() string { + if c == nil || c.DefaultValue == nil { + return "" + } + return *c.DefaultValue +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (c *CustomProperty) GetDescription() string { + if c == nil || c.Description == nil { + return "" + } + return *c.Description +} + +// GetPropertyName returns the PropertyName field if it's non-nil, zero value otherwise. +func (c *CustomProperty) GetPropertyName() string { + if c == nil || c.PropertyName == nil { + return "" + } + return *c.PropertyName +} + +// GetRequired returns the Required field if it's non-nil, zero value otherwise. +func (c *CustomProperty) GetRequired() bool { + if c == nil || c.Required == nil { + return false + } + return *c.Required +} + +// GetSourceType returns the SourceType field if it's non-nil, zero value otherwise. +func (c *CustomProperty) GetSourceType() string { + if c == nil || c.SourceType == nil { + return "" + } + return *c.SourceType +} + +// GetValuesEditableBy returns the ValuesEditableBy field if it's non-nil, zero value otherwise. +func (c *CustomProperty) GetValuesEditableBy() string { + if c == nil || c.ValuesEditableBy == nil { + return "" + } + return *c.ValuesEditableBy +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (c *CustomPropertyEvent) GetAction() string { + if c == nil || c.Action == nil { + return "" + } + return *c.Action +} + +// GetDefinition returns the Definition field. +func (c *CustomPropertyEvent) GetDefinition() *CustomProperty { + if c == nil { + return nil + } + return c.Definition +} + +// GetEnterprise returns the Enterprise field. +func (c *CustomPropertyEvent) GetEnterprise() *Enterprise { + if c == nil { + return nil + } + return c.Enterprise +} + +// GetInstallation returns the Installation field. +func (c *CustomPropertyEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetOrg returns the Org field. +func (c *CustomPropertyEvent) GetOrg() *Organization { + if c == nil { + return nil + } + return c.Org +} + +// GetSender returns the Sender field. +func (c *CustomPropertyEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (c *CustomPropertyValuesEvent) GetAction() string { + if c == nil || c.Action == nil { + return "" + } + return *c.Action +} + +// GetEnterprise returns the Enterprise field. +func (c *CustomPropertyValuesEvent) GetEnterprise() *Enterprise { + if c == nil { + return nil + } + return c.Enterprise +} + +// GetInstallation returns the Installation field. +func (c *CustomPropertyValuesEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetOrg returns the Org field. +func (c *CustomPropertyValuesEvent) GetOrg() *Organization { + if c == nil { + return nil + } + return c.Org +} + +// GetRepo returns the Repo field. +func (c *CustomPropertyValuesEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetSender returns the Sender field. +func (c *CustomPropertyValuesEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetBaseRole returns the BaseRole field if it's non-nil, zero value otherwise. +func (c *CustomRepoRoles) GetBaseRole() string { + if c == nil || c.BaseRole == nil { + return "" + } + return *c.BaseRole +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *CustomRepoRoles) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (c *CustomRepoRoles) GetDescription() string { + if c == nil || c.Description == nil { + return "" + } + return *c.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CustomRepoRoles) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CustomRepoRoles) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetOrg returns the Org field. +func (c *CustomRepoRoles) GetOrg() *Organization { + if c == nil { + return nil + } + return c.Org +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (c *CustomRepoRoles) GetUpdatedAt() Timestamp { + if c == nil || c.UpdatedAt == nil { + return Timestamp{} + } + return *c.UpdatedAt +} + +// GetQuerySuite returns the QuerySuite field if it's non-nil, zero value otherwise. +func (d *DefaultSetupConfiguration) GetQuerySuite() string { + if d == nil || d.QuerySuite == nil { + return "" + } + return *d.QuerySuite +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (d *DefaultSetupConfiguration) GetState() string { + if d == nil || d.State == nil { + return "" + } + return *d.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *DefaultSetupConfiguration) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetCanApprovePullRequestReviews returns the CanApprovePullRequestReviews field if it's non-nil, zero value otherwise. +func (d *DefaultWorkflowPermissionEnterprise) GetCanApprovePullRequestReviews() bool { + if d == nil || d.CanApprovePullRequestReviews == nil { + return false + } + return *d.CanApprovePullRequestReviews +} + +// GetDefaultWorkflowPermissions returns the DefaultWorkflowPermissions field if it's non-nil, zero value otherwise. +func (d *DefaultWorkflowPermissionEnterprise) GetDefaultWorkflowPermissions() string { + if d == nil || d.DefaultWorkflowPermissions == nil { + return "" + } + return *d.DefaultWorkflowPermissions +} + +// GetCanApprovePullRequestReviews returns the CanApprovePullRequestReviews field if it's non-nil, zero value otherwise. +func (d *DefaultWorkflowPermissionOrganization) GetCanApprovePullRequestReviews() bool { + if d == nil || d.CanApprovePullRequestReviews == nil { + return false + } + return *d.CanApprovePullRequestReviews +} + +// GetDefaultWorkflowPermissions returns the DefaultWorkflowPermissions field if it's non-nil, zero value otherwise. +func (d *DefaultWorkflowPermissionOrganization) GetDefaultWorkflowPermissions() string { + if d == nil || d.DefaultWorkflowPermissions == nil { + return "" + } + return *d.DefaultWorkflowPermissions +} + +// GetCanApprovePullRequestReviews returns the CanApprovePullRequestReviews field if it's non-nil, zero value otherwise. +func (d *DefaultWorkflowPermissionRepository) GetCanApprovePullRequestReviews() bool { + if d == nil || d.CanApprovePullRequestReviews == nil { + return false + } + return *d.CanApprovePullRequestReviews +} + +// GetDefaultWorkflowPermissions returns the DefaultWorkflowPermissions field if it's non-nil, zero value otherwise. +func (d *DefaultWorkflowPermissionRepository) GetDefaultWorkflowPermissions() string { + if d == nil || d.DefaultWorkflowPermissions == nil { + return "" + } + return *d.DefaultWorkflowPermissions +} + +// GetConfirmDeleteURL returns the ConfirmDeleteURL field if it's non-nil, zero value otherwise. +func (d *DeleteAnalysis) GetConfirmDeleteURL() string { + if d == nil || d.ConfirmDeleteURL == nil { + return "" + } + return *d.ConfirmDeleteURL +} + +// GetNextAnalysisURL returns the NextAnalysisURL field if it's non-nil, zero value otherwise. +func (d *DeleteAnalysis) GetNextAnalysisURL() string { + if d == nil || d.NextAnalysisURL == nil { + return "" + } + return *d.NextAnalysisURL +} + +// GetInstallation returns the Installation field. +func (d *DeleteEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetOrg returns the Org field. +func (d *DeleteEvent) GetOrg() *Organization { + if d == nil { + return nil + } + return d.Org +} + +// GetPusherType returns the PusherType field if it's non-nil, zero value otherwise. +func (d *DeleteEvent) GetPusherType() string { + if d == nil || d.PusherType == nil { + return "" + } + return *d.PusherType +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (d *DeleteEvent) GetRef() string { + if d == nil || d.Ref == nil { + return "" + } + return *d.Ref +} + +// GetRefType returns the RefType field if it's non-nil, zero value otherwise. +func (d *DeleteEvent) GetRefType() string { + if d == nil || d.RefType == nil { + return "" + } + return *d.RefType +} + +// GetRepo returns the Repo field. +func (d *DeleteEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DeleteEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetAutoDismissedAt returns the AutoDismissedAt field if it's non-nil, zero value otherwise. +func (d *DependabotAlert) GetAutoDismissedAt() Timestamp { + if d == nil || d.AutoDismissedAt == nil { + return Timestamp{} + } + return *d.AutoDismissedAt +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *DependabotAlert) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetDependency returns the Dependency field. +func (d *DependabotAlert) GetDependency() *Dependency { + if d == nil { + return nil + } + return d.Dependency +} + +// GetDismissedAt returns the DismissedAt field if it's non-nil, zero value otherwise. +func (d *DependabotAlert) GetDismissedAt() Timestamp { + if d == nil || d.DismissedAt == nil { + return Timestamp{} + } + return *d.DismissedAt +} + +// GetDismissedBy returns the DismissedBy field. +func (d *DependabotAlert) GetDismissedBy() *User { + if d == nil { + return nil + } + return d.DismissedBy +} + +// GetDismissedComment returns the DismissedComment field if it's non-nil, zero value otherwise. +func (d *DependabotAlert) GetDismissedComment() string { + if d == nil || d.DismissedComment == nil { + return "" + } + return *d.DismissedComment +} + +// GetDismissedReason returns the DismissedReason field if it's non-nil, zero value otherwise. +func (d *DependabotAlert) GetDismissedReason() string { + if d == nil || d.DismissedReason == nil { + return "" + } + return *d.DismissedReason +} + +// GetFixedAt returns the FixedAt field if it's non-nil, zero value otherwise. +func (d *DependabotAlert) GetFixedAt() Timestamp { + if d == nil || d.FixedAt == nil { + return Timestamp{} + } + return *d.FixedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (d *DependabotAlert) GetHTMLURL() string { + if d == nil || d.HTMLURL == nil { + return "" + } + return *d.HTMLURL +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (d *DependabotAlert) GetNumber() int { + if d == nil || d.Number == nil { + return 0 + } + return *d.Number +} + +// GetRepository returns the Repository field. +func (d *DependabotAlert) GetRepository() *Repository { + if d == nil { + return nil + } + return d.Repository +} + +// GetSecurityAdvisory returns the SecurityAdvisory field. +func (d *DependabotAlert) GetSecurityAdvisory() *DependabotSecurityAdvisory { + if d == nil { + return nil + } + return d.SecurityAdvisory +} + +// GetSecurityVulnerability returns the SecurityVulnerability field. +func (d *DependabotAlert) GetSecurityVulnerability() *AdvisoryVulnerability { + if d == nil { + return nil + } + return d.SecurityVulnerability +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (d *DependabotAlert) GetState() string { + if d == nil || d.State == nil { + return "" + } + return *d.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *DependabotAlert) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (d *DependabotAlert) GetURL() string { + if d == nil || d.URL == nil { + return "" + } + return *d.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (d *DependabotAlertEvent) GetAction() string { + if d == nil || d.Action == nil { + return "" + } + return *d.Action +} + +// GetAlert returns the Alert field. +func (d *DependabotAlertEvent) GetAlert() *DependabotAlert { + if d == nil { + return nil + } + return d.Alert +} + +// GetEnterprise returns the Enterprise field. +func (d *DependabotAlertEvent) GetEnterprise() *Enterprise { + if d == nil { + return nil + } + return d.Enterprise +} + +// GetInstallation returns the Installation field. +func (d *DependabotAlertEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetOrganization returns the Organization field. +func (d *DependabotAlertEvent) GetOrganization() *Organization { + if d == nil { + return nil + } + return d.Organization +} + +// GetRepo returns the Repo field. +func (d *DependabotAlertEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DependabotAlertEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetDismissedComment returns the DismissedComment field if it's non-nil, zero value otherwise. +func (d *DependabotAlertState) GetDismissedComment() string { + if d == nil || d.DismissedComment == nil { + return "" + } + return *d.DismissedComment +} + +// GetDismissedReason returns the DismissedReason field if it's non-nil, zero value otherwise. +func (d *DependabotAlertState) GetDismissedReason() string { + if d == nil || d.DismissedReason == nil { + return "" + } + return *d.DismissedReason +} + +// GetCVEID returns the CVEID field if it's non-nil, zero value otherwise. +func (d *DependabotSecurityAdvisory) GetCVEID() string { + if d == nil || d.CVEID == nil { + return "" + } + return *d.CVEID +} + +// GetCVSS returns the CVSS field. +func (d *DependabotSecurityAdvisory) GetCVSS() *AdvisoryCVSS { + if d == nil { + return nil + } + return d.CVSS +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (d *DependabotSecurityAdvisory) GetDescription() string { + if d == nil || d.Description == nil { + return "" + } + return *d.Description +} + +// GetGHSAID returns the GHSAID field if it's non-nil, zero value otherwise. +func (d *DependabotSecurityAdvisory) GetGHSAID() string { + if d == nil || d.GHSAID == nil { + return "" + } + return *d.GHSAID +} + +// GetPublishedAt returns the PublishedAt field if it's non-nil, zero value otherwise. +func (d *DependabotSecurityAdvisory) GetPublishedAt() Timestamp { + if d == nil || d.PublishedAt == nil { + return Timestamp{} + } + return *d.PublishedAt +} + +// GetSeverity returns the Severity field if it's non-nil, zero value otherwise. +func (d *DependabotSecurityAdvisory) GetSeverity() string { + if d == nil || d.Severity == nil { + return "" + } + return *d.Severity +} + +// GetSummary returns the Summary field if it's non-nil, zero value otherwise. +func (d *DependabotSecurityAdvisory) GetSummary() string { + if d == nil || d.Summary == nil { + return "" + } + return *d.Summary +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *DependabotSecurityAdvisory) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetWithdrawnAt returns the WithdrawnAt field if it's non-nil, zero value otherwise. +func (d *DependabotSecurityAdvisory) GetWithdrawnAt() Timestamp { + if d == nil || d.WithdrawnAt == nil { + return Timestamp{} + } + return *d.WithdrawnAt +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (d *DependabotSecurityUpdates) GetStatus() string { + if d == nil || d.Status == nil { + return "" + } + return *d.Status +} + +// GetManifestPath returns the ManifestPath field if it's non-nil, zero value otherwise. +func (d *Dependency) GetManifestPath() string { + if d == nil || d.ManifestPath == nil { + return "" + } + return *d.ManifestPath +} + +// GetPackage returns the Package field. +func (d *Dependency) GetPackage() *VulnerabilityPackage { + if d == nil { + return nil + } + return d.Package +} + +// GetScope returns the Scope field if it's non-nil, zero value otherwise. +func (d *Dependency) GetScope() string { + if d == nil || d.Scope == nil { + return "" + } + return *d.Scope +} + +// GetLabeledRunners returns the LabeledRunners field if it's non-nil, zero value otherwise. +func (d *DependencyGraphAutosubmitActionOptions) GetLabeledRunners() bool { + if d == nil || d.LabeledRunners == nil { + return false + } + return *d.LabeledRunners +} + +// GetDetector returns the Detector field. +func (d *DependencyGraphSnapshot) GetDetector() *DependencyGraphSnapshotDetector { + if d == nil { + return nil + } + return d.Detector +} + +// GetJob returns the Job field. +func (d *DependencyGraphSnapshot) GetJob() *DependencyGraphSnapshotJob { + if d == nil { + return nil + } + return d.Job +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshot) GetRef() string { + if d == nil || d.Ref == nil { + return "" + } + return *d.Ref +} + +// GetScanned returns the Scanned field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshot) GetScanned() Timestamp { + if d == nil || d.Scanned == nil { + return Timestamp{} + } + return *d.Scanned +} + +// GetSha returns the Sha field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshot) GetSha() string { + if d == nil || d.Sha == nil { + return "" + } + return *d.Sha +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotCreationData) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotCreationData) GetMessage() string { + if d == nil || d.Message == nil { + return "" + } + return *d.Message +} + +// GetResult returns the Result field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotCreationData) GetResult() string { + if d == nil || d.Result == nil { + return "" + } + return *d.Result +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotDetector) GetName() string { + if d == nil || d.Name == nil { + return "" + } + return *d.Name +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotDetector) GetURL() string { + if d == nil || d.URL == nil { + return "" + } + return *d.URL +} + +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotDetector) GetVersion() string { + if d == nil || d.Version == nil { + return "" + } + return *d.Version +} + +// GetCorrelator returns the Correlator field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotJob) GetCorrelator() string { + if d == nil || d.Correlator == nil { + return "" + } + return *d.Correlator +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotJob) GetHTMLURL() string { + if d == nil || d.HTMLURL == nil { + return "" + } + return *d.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotJob) GetID() string { + if d == nil || d.ID == nil { + return "" + } + return *d.ID +} + +// GetFile returns the File field. +func (d *DependencyGraphSnapshotManifest) GetFile() *DependencyGraphSnapshotManifestFile { + if d == nil { + return nil + } + return d.File +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotManifest) GetName() string { + if d == nil || d.Name == nil { + return "" + } + return *d.Name +} + +// GetSourceLocation returns the SourceLocation field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotManifestFile) GetSourceLocation() string { + if d == nil || d.SourceLocation == nil { + return "" + } + return *d.SourceLocation +} + +// GetPackageURL returns the PackageURL field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotResolvedDependency) GetPackageURL() string { + if d == nil || d.PackageURL == nil { + return "" + } + return *d.PackageURL +} + +// GetRelationship returns the Relationship field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotResolvedDependency) GetRelationship() string { + if d == nil || d.Relationship == nil { + return "" + } + return *d.Relationship +} + +// GetScope returns the Scope field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotResolvedDependency) GetScope() string { + if d == nil || d.Scope == nil { + return "" + } + return *d.Scope +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (d *DeployKeyEvent) GetAction() string { + if d == nil || d.Action == nil { + return "" + } + return *d.Action +} + +// GetInstallation returns the Installation field. +func (d *DeployKeyEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetKey returns the Key field. +func (d *DeployKeyEvent) GetKey() *Key { + if d == nil { + return nil + } + return d.Key +} + +// GetOrganization returns the Organization field. +func (d *DeployKeyEvent) GetOrganization() *Organization { + if d == nil { + return nil + } + return d.Organization +} + +// GetRepo returns the Repo field. +func (d *DeployKeyEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DeployKeyEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *Deployment) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetCreator returns the Creator field. +func (d *Deployment) GetCreator() *User { + if d == nil { + return nil + } + return d.Creator +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (d *Deployment) GetDescription() string { + if d == nil || d.Description == nil { + return "" + } + return *d.Description +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (d *Deployment) GetEnvironment() string { + if d == nil || d.Environment == nil { + return "" + } + return *d.Environment +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (d *Deployment) GetID() int64 { + if d == nil || d.ID == nil { + return 0 + } + return *d.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (d *Deployment) GetNodeID() string { + if d == nil || d.NodeID == nil { + return "" + } + return *d.NodeID +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (d *Deployment) GetRef() string { + if d == nil || d.Ref == nil { + return "" + } + return *d.Ref +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (d *Deployment) GetRepositoryURL() string { + if d == nil || d.RepositoryURL == nil { + return "" + } + return *d.RepositoryURL +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (d *Deployment) GetSHA() string { + if d == nil || d.SHA == nil { + return "" + } + return *d.SHA +} + +// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. +func (d *Deployment) GetStatusesURL() string { + if d == nil || d.StatusesURL == nil { + return "" + } + return *d.StatusesURL +} + +// GetTask returns the Task field if it's non-nil, zero value otherwise. +func (d *Deployment) GetTask() string { + if d == nil || d.Task == nil { + return "" + } + return *d.Task +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *Deployment) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (d *Deployment) GetURL() string { + if d == nil || d.URL == nil { + return "" + } + return *d.URL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (d *DeploymentBranchPolicy) GetID() int64 { + if d == nil || d.ID == nil { + return 0 + } + return *d.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (d *DeploymentBranchPolicy) GetName() string { + if d == nil || d.Name == nil { + return "" + } + return *d.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (d *DeploymentBranchPolicy) GetNodeID() string { + if d == nil || d.NodeID == nil { + return "" + } + return *d.NodeID +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (d *DeploymentBranchPolicy) GetType() string { + if d == nil || d.Type == nil { + return "" + } + return *d.Type +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (d *DeploymentBranchPolicyRequest) GetName() string { + if d == nil || d.Name == nil { + return "" + } + return *d.Name +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (d *DeploymentBranchPolicyRequest) GetType() string { + if d == nil || d.Type == nil { + return "" + } + return *d.Type +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (d *DeploymentBranchPolicyResponse) GetTotalCount() int { + if d == nil || d.TotalCount == nil { + return 0 + } + return *d.TotalCount +} + +// GetDeployment returns the Deployment field. +func (d *DeploymentEvent) GetDeployment() *Deployment { + if d == nil { + return nil + } + return d.Deployment +} + +// GetInstallation returns the Installation field. +func (d *DeploymentEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetOrg returns the Org field. +func (d *DeploymentEvent) GetOrg() *Organization { + if d == nil { + return nil + } + return d.Org +} + +// GetRepo returns the Repo field. +func (d *DeploymentEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DeploymentEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetWorkflow returns the Workflow field. +func (d *DeploymentEvent) GetWorkflow() *Workflow { + if d == nil { + return nil + } + return d.Workflow +} + +// GetWorkflowRun returns the WorkflowRun field. +func (d *DeploymentEvent) GetWorkflowRun() *WorkflowRun { + if d == nil { + return nil + } + return d.WorkflowRun +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (d *DeploymentProtectionRuleEvent) GetAction() string { + if d == nil || d.Action == nil { + return "" + } + return *d.Action +} + +// GetDeployment returns the Deployment field. +func (d *DeploymentProtectionRuleEvent) GetDeployment() *Deployment { + if d == nil { + return nil + } + return d.Deployment +} + +// GetDeploymentCallbackURL returns the DeploymentCallbackURL field if it's non-nil, zero value otherwise. +func (d *DeploymentProtectionRuleEvent) GetDeploymentCallbackURL() string { + if d == nil || d.DeploymentCallbackURL == nil { + return "" + } + return *d.DeploymentCallbackURL +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (d *DeploymentProtectionRuleEvent) GetEnvironment() string { + if d == nil || d.Environment == nil { + return "" + } + return *d.Environment +} + +// GetEvent returns the Event field if it's non-nil, zero value otherwise. +func (d *DeploymentProtectionRuleEvent) GetEvent() string { + if d == nil || d.Event == nil { + return "" + } + return *d.Event +} + +// GetInstallation returns the Installation field. +func (d *DeploymentProtectionRuleEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetOrganization returns the Organization field. +func (d *DeploymentProtectionRuleEvent) GetOrganization() *Organization { + if d == nil { + return nil + } + return d.Organization +} + +// GetRepo returns the Repo field. +func (d *DeploymentProtectionRuleEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DeploymentProtectionRuleEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetAutoMerge returns the AutoMerge field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetAutoMerge() bool { + if d == nil || d.AutoMerge == nil { + return false + } + return *d.AutoMerge +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetDescription() string { + if d == nil || d.Description == nil { + return "" + } + return *d.Description +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetEnvironment() string { + if d == nil || d.Environment == nil { + return "" + } + return *d.Environment +} + +// GetProductionEnvironment returns the ProductionEnvironment field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetProductionEnvironment() bool { + if d == nil || d.ProductionEnvironment == nil { + return false + } + return *d.ProductionEnvironment +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetRef() string { + if d == nil || d.Ref == nil { + return "" + } + return *d.Ref +} + +// GetRequiredContexts returns the RequiredContexts field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetRequiredContexts() []string { + if d == nil || d.RequiredContexts == nil { + return nil + } + return *d.RequiredContexts +} + +// GetTask returns the Task field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetTask() string { + if d == nil || d.Task == nil { + return "" + } + return *d.Task +} + +// GetTransientEnvironment returns the TransientEnvironment field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetTransientEnvironment() bool { + if d == nil || d.TransientEnvironment == nil { + return false + } + return *d.TransientEnvironment +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (d *DeploymentReviewEvent) GetAction() string { + if d == nil || d.Action == nil { + return "" + } + return *d.Action +} + +// GetApprover returns the Approver field. +func (d *DeploymentReviewEvent) GetApprover() *User { + if d == nil { + return nil + } + return d.Approver +} + +// GetComment returns the Comment field if it's non-nil, zero value otherwise. +func (d *DeploymentReviewEvent) GetComment() string { + if d == nil || d.Comment == nil { + return "" + } + return *d.Comment +} + +// GetEnterprise returns the Enterprise field. +func (d *DeploymentReviewEvent) GetEnterprise() *Enterprise { + if d == nil { + return nil + } + return d.Enterprise +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (d *DeploymentReviewEvent) GetEnvironment() string { + if d == nil || d.Environment == nil { + return "" + } + return *d.Environment +} + +// GetInstallation returns the Installation field. +func (d *DeploymentReviewEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetOrganization returns the Organization field. +func (d *DeploymentReviewEvent) GetOrganization() *Organization { + if d == nil { + return nil + } + return d.Organization +} + +// GetRepo returns the Repo field. +func (d *DeploymentReviewEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetRequester returns the Requester field. +func (d *DeploymentReviewEvent) GetRequester() *User { + if d == nil { + return nil + } + return d.Requester +} + +// GetSender returns the Sender field. +func (d *DeploymentReviewEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetSince returns the Since field if it's non-nil, zero value otherwise. +func (d *DeploymentReviewEvent) GetSince() string { + if d == nil || d.Since == nil { + return "" + } + return *d.Since +} + +// GetWorkflowJobRun returns the WorkflowJobRun field. +func (d *DeploymentReviewEvent) GetWorkflowJobRun() *WorkflowJobRun { + if d == nil { + return nil + } + return d.WorkflowJobRun +} + +// GetWorkflowRun returns the WorkflowRun field. +func (d *DeploymentReviewEvent) GetWorkflowRun() *WorkflowRun { + if d == nil { + return nil + } + return d.WorkflowRun +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetCreator returns the Creator field. +func (d *DeploymentStatus) GetCreator() *User { + if d == nil { + return nil + } + return d.Creator +} + +// GetDeploymentURL returns the DeploymentURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetDeploymentURL() string { + if d == nil || d.DeploymentURL == nil { + return "" + } + return *d.DeploymentURL +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetDescription() string { + if d == nil || d.Description == nil { + return "" + } + return *d.Description +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetEnvironment() string { + if d == nil || d.Environment == nil { + return "" + } + return *d.Environment +} + +// GetEnvironmentURL returns the EnvironmentURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetEnvironmentURL() string { + if d == nil || d.EnvironmentURL == nil { + return "" + } + return *d.EnvironmentURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetID() int64 { + if d == nil || d.ID == nil { + return 0 + } + return *d.ID +} + +// GetLogURL returns the LogURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetLogURL() string { + if d == nil || d.LogURL == nil { + return "" + } + return *d.LogURL +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetNodeID() string { + if d == nil || d.NodeID == nil { + return "" + } + return *d.NodeID +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetRepositoryURL() string { + if d == nil || d.RepositoryURL == nil { + return "" + } + return *d.RepositoryURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetState() string { + if d == nil || d.State == nil { + return "" + } + return *d.State +} + +// GetTargetURL returns the TargetURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetTargetURL() string { + if d == nil || d.TargetURL == nil { + return "" + } + return *d.TargetURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetURL() string { + if d == nil || d.URL == nil { + return "" + } + return *d.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusEvent) GetAction() string { + if d == nil || d.Action == nil { + return "" + } + return *d.Action +} + +// GetDeployment returns the Deployment field. +func (d *DeploymentStatusEvent) GetDeployment() *Deployment { + if d == nil { + return nil + } + return d.Deployment +} + +// GetDeploymentStatus returns the DeploymentStatus field. +func (d *DeploymentStatusEvent) GetDeploymentStatus() *DeploymentStatus { + if d == nil { + return nil + } + return d.DeploymentStatus +} + +// GetInstallation returns the Installation field. +func (d *DeploymentStatusEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetOrg returns the Org field. +func (d *DeploymentStatusEvent) GetOrg() *Organization { + if d == nil { + return nil + } + return d.Org +} + +// GetRepo returns the Repo field. +func (d *DeploymentStatusEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DeploymentStatusEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetAutoInactive returns the AutoInactive field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetAutoInactive() bool { + if d == nil || d.AutoInactive == nil { + return false + } + return *d.AutoInactive +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetDescription() string { + if d == nil || d.Description == nil { + return "" + } + return *d.Description +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetEnvironment() string { + if d == nil || d.Environment == nil { + return "" + } + return *d.Environment +} + +// GetEnvironmentURL returns the EnvironmentURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetEnvironmentURL() string { + if d == nil || d.EnvironmentURL == nil { + return "" + } + return *d.EnvironmentURL +} + +// GetLogURL returns the LogURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetLogURL() string { + if d == nil || d.LogURL == nil { + return "" + } + return *d.LogURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetState() string { + if d == nil || d.State == nil { + return "" + } + return *d.State +} + +// GetActiveLockReason returns the ActiveLockReason field if it's non-nil, zero value otherwise. +func (d *Discussion) GetActiveLockReason() string { + if d == nil || d.ActiveLockReason == nil { + return "" + } + return *d.ActiveLockReason +} + +// GetAnswerChosenAt returns the AnswerChosenAt field if it's non-nil, zero value otherwise. +func (d *Discussion) GetAnswerChosenAt() Timestamp { + if d == nil || d.AnswerChosenAt == nil { + return Timestamp{} + } + return *d.AnswerChosenAt +} + +// GetAnswerChosenBy returns the AnswerChosenBy field if it's non-nil, zero value otherwise. +func (d *Discussion) GetAnswerChosenBy() string { + if d == nil || d.AnswerChosenBy == nil { + return "" + } + return *d.AnswerChosenBy +} + +// GetAnswerHTMLURL returns the AnswerHTMLURL field if it's non-nil, zero value otherwise. +func (d *Discussion) GetAnswerHTMLURL() string { + if d == nil || d.AnswerHTMLURL == nil { + return "" + } + return *d.AnswerHTMLURL +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (d *Discussion) GetAuthorAssociation() string { + if d == nil || d.AuthorAssociation == nil { + return "" + } + return *d.AuthorAssociation +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (d *Discussion) GetBody() string { + if d == nil || d.Body == nil { + return "" + } + return *d.Body +} + +// GetComments returns the Comments field if it's non-nil, zero value otherwise. +func (d *Discussion) GetComments() int { + if d == nil || d.Comments == nil { + return 0 + } + return *d.Comments +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *Discussion) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetDiscussionCategory returns the DiscussionCategory field. +func (d *Discussion) GetDiscussionCategory() *DiscussionCategory { + if d == nil { + return nil + } + return d.DiscussionCategory +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (d *Discussion) GetHTMLURL() string { + if d == nil || d.HTMLURL == nil { + return "" + } + return *d.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (d *Discussion) GetID() int64 { + if d == nil || d.ID == nil { + return 0 + } + return *d.ID +} + +// GetLocked returns the Locked field if it's non-nil, zero value otherwise. +func (d *Discussion) GetLocked() bool { + if d == nil || d.Locked == nil { + return false + } + return *d.Locked +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (d *Discussion) GetNodeID() string { + if d == nil || d.NodeID == nil { + return "" + } + return *d.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (d *Discussion) GetNumber() int { + if d == nil || d.Number == nil { + return 0 + } + return *d.Number +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (d *Discussion) GetRepositoryURL() string { + if d == nil || d.RepositoryURL == nil { + return "" + } + return *d.RepositoryURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (d *Discussion) GetState() string { + if d == nil || d.State == nil { + return "" + } + return *d.State +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (d *Discussion) GetTitle() string { + if d == nil || d.Title == nil { + return "" + } + return *d.Title +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *Discussion) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetUser returns the User field. +func (d *Discussion) GetUser() *User { + if d == nil { + return nil + } + return d.User +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetDescription() string { + if d == nil || d.Description == nil { + return "" + } + return *d.Description +} + +// GetEmoji returns the Emoji field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetEmoji() string { + if d == nil || d.Emoji == nil { + return "" + } + return *d.Emoji +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetID() int64 { + if d == nil || d.ID == nil { + return 0 + } + return *d.ID +} + +// GetIsAnswerable returns the IsAnswerable field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetIsAnswerable() bool { + if d == nil || d.IsAnswerable == nil { + return false + } + return *d.IsAnswerable +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetName() string { + if d == nil || d.Name == nil { + return "" + } + return *d.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetNodeID() string { + if d == nil || d.NodeID == nil { + return "" + } + return *d.NodeID +} + +// GetRepositoryID returns the RepositoryID field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetRepositoryID() int64 { + if d == nil || d.RepositoryID == nil { + return 0 + } + return *d.RepositoryID +} + +// GetSlug returns the Slug field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetSlug() string { + if d == nil || d.Slug == nil { + return "" + } + return *d.Slug +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetAuthor returns the Author field. +func (d *DiscussionComment) GetAuthor() *User { + if d == nil { + return nil + } + return d.Author +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetBody() string { + if d == nil || d.Body == nil { + return "" + } + return *d.Body +} + +// GetBodyHTML returns the BodyHTML field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetBodyHTML() string { + if d == nil || d.BodyHTML == nil { + return "" + } + return *d.BodyHTML +} + +// GetBodyVersion returns the BodyVersion field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetBodyVersion() string { + if d == nil || d.BodyVersion == nil { + return "" + } + return *d.BodyVersion +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetDiscussionURL returns the DiscussionURL field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetDiscussionURL() string { + if d == nil || d.DiscussionURL == nil { + return "" + } + return *d.DiscussionURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetHTMLURL() string { + if d == nil || d.HTMLURL == nil { + return "" + } + return *d.HTMLURL +} + +// GetLastEditedAt returns the LastEditedAt field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetLastEditedAt() Timestamp { + if d == nil || d.LastEditedAt == nil { + return Timestamp{} + } + return *d.LastEditedAt +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetNodeID() string { + if d == nil || d.NodeID == nil { + return "" + } + return *d.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetNumber() int { + if d == nil || d.Number == nil { + return 0 + } + return *d.Number +} + +// GetReactions returns the Reactions field. +func (d *DiscussionComment) GetReactions() *Reactions { + if d == nil { + return nil + } + return d.Reactions +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetURL() string { + if d == nil || d.URL == nil { + return "" + } + return *d.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (d *DiscussionCommentEvent) GetAction() string { + if d == nil || d.Action == nil { + return "" + } + return *d.Action +} + +// GetComment returns the Comment field. +func (d *DiscussionCommentEvent) GetComment() *CommentDiscussion { + if d == nil { + return nil + } + return d.Comment +} + +// GetDiscussion returns the Discussion field. +func (d *DiscussionCommentEvent) GetDiscussion() *Discussion { + if d == nil { + return nil + } + return d.Discussion +} + +// GetInstallation returns the Installation field. +func (d *DiscussionCommentEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetOrg returns the Org field. +func (d *DiscussionCommentEvent) GetOrg() *Organization { + if d == nil { + return nil + } + return d.Org +} + +// GetRepo returns the Repo field. +func (d *DiscussionCommentEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DiscussionCommentEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (d *DiscussionEvent) GetAction() string { + if d == nil || d.Action == nil { + return "" + } + return *d.Action +} + +// GetDiscussion returns the Discussion field. +func (d *DiscussionEvent) GetDiscussion() *Discussion { + if d == nil { + return nil + } + return d.Discussion +} + +// GetInstallation returns the Installation field. +func (d *DiscussionEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetOrg returns the Org field. +func (d *DiscussionEvent) GetOrg() *Organization { + if d == nil { + return nil + } + return d.Org +} + +// GetRepo returns the Repo field. +func (d *DiscussionEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DiscussionEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetApps returns the Apps field if it's non-nil, zero value otherwise. +func (d *DismissalRestrictionsRequest) GetApps() []string { + if d == nil || d.Apps == nil { + return nil + } + return *d.Apps +} + +// GetTeams returns the Teams field if it's non-nil, zero value otherwise. +func (d *DismissalRestrictionsRequest) GetTeams() []string { + if d == nil || d.Teams == nil { + return nil + } + return *d.Teams +} + +// GetUsers returns the Users field if it's non-nil, zero value otherwise. +func (d *DismissalRestrictionsRequest) GetUsers() []string { + if d == nil || d.Users == nil { + return nil + } + return *d.Users +} + +// GetDismissalCommitID returns the DismissalCommitID field if it's non-nil, zero value otherwise. +func (d *DismissedReview) GetDismissalCommitID() string { + if d == nil || d.DismissalCommitID == nil { + return "" + } + return *d.DismissalCommitID +} + +// GetDismissalMessage returns the DismissalMessage field if it's non-nil, zero value otherwise. +func (d *DismissedReview) GetDismissalMessage() string { + if d == nil || d.DismissalMessage == nil { + return "" + } + return *d.DismissalMessage +} + +// GetReviewID returns the ReviewID field if it's non-nil, zero value otherwise. +func (d *DismissedReview) GetReviewID() int64 { + if d == nil || d.ReviewID == nil { + return 0 + } + return *d.ReviewID +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (d *DismissedReview) GetState() string { + if d == nil || d.State == nil { + return "" + } + return *d.State +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (d *DismissStaleReviewsOnPushChanges) GetFrom() bool { + if d == nil || d.From == nil { + return false + } + return *d.From +} + +// GetClientPayload returns the ClientPayload field if it's non-nil, zero value otherwise. +func (d *DispatchRequestOptions) GetClientPayload() json.RawMessage { + if d == nil || d.ClientPayload == nil { + return json.RawMessage{} + } + return *d.ClientPayload +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetBody() string { + if d == nil || d.Body == nil { + return "" + } + return *d.Body +} + +// GetLine returns the Line field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetLine() int { + if d == nil || d.Line == nil { + return 0 + } + return *d.Line +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetPath() string { + if d == nil || d.Path == nil { + return "" + } + return *d.Path +} + +// GetPosition returns the Position field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetPosition() int { + if d == nil || d.Position == nil { + return 0 + } + return *d.Position +} + +// GetSide returns the Side field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetSide() string { + if d == nil || d.Side == nil { + return "" + } + return *d.Side +} + +// GetStartLine returns the StartLine field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetStartLine() int { + if d == nil || d.StartLine == nil { + return 0 + } + return *d.StartLine +} + +// GetStartSide returns the StartSide field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetStartSide() string { + if d == nil || d.StartSide == nil { + return "" + } + return *d.StartSide +} + +// GetRef returns the Ref field. +func (e *EditBase) GetRef() *EditRef { + if e == nil { + return nil + } + return e.Ref +} + +// GetSHA returns the SHA field. +func (e *EditBase) GetSHA() *EditSHA { + if e == nil { + return nil + } + return e.SHA +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (e *EditBody) GetFrom() string { + if e == nil || e.From == nil { + return "" + } + return *e.From +} + +// GetBase returns the Base field. +func (e *EditChange) GetBase() *EditBase { + if e == nil { + return nil + } + return e.Base +} + +// GetBody returns the Body field. +func (e *EditChange) GetBody() *EditBody { + if e == nil { + return nil + } + return e.Body +} + +// GetDefaultBranch returns the DefaultBranch field. +func (e *EditChange) GetDefaultBranch() *EditDefaultBranch { + if e == nil { + return nil + } + return e.DefaultBranch +} + +// GetOwner returns the Owner field. +func (e *EditChange) GetOwner() *EditOwner { + if e == nil { + return nil + } + return e.Owner +} + +// GetRepo returns the Repo field. +func (e *EditChange) GetRepo() *EditRepo { + if e == nil { + return nil + } + return e.Repo +} + +// GetTitle returns the Title field. +func (e *EditChange) GetTitle() *EditTitle { + if e == nil { + return nil + } + return e.Title +} + +// GetTopics returns the Topics field. +func (e *EditChange) GetTopics() *EditTopics { + if e == nil { + return nil + } + return e.Topics +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (e *EditDefaultBranch) GetFrom() string { + if e == nil || e.From == nil { + return "" + } + return *e.From +} + +// GetOwnerInfo returns the OwnerInfo field. +func (e *EditOwner) GetOwnerInfo() *OwnerInfo { + if e == nil { + return nil + } + return e.OwnerInfo +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (e *EditRef) GetFrom() string { + if e == nil || e.From == nil { + return "" + } + return *e.From +} + +// GetName returns the Name field. +func (e *EditRepo) GetName() *RepoName { + if e == nil { + return nil + } + return e.Name +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (e *EditSHA) GetFrom() string { + if e == nil || e.From == nil { + return "" + } + return *e.From +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (e *EditTitle) GetFrom() string { + if e == nil || e.From == nil { + return "" + } + return *e.From +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetAvatarURL() string { + if e == nil || e.AvatarURL == nil { + return "" + } + return *e.AvatarURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetCreatedAt() Timestamp { + if e == nil || e.CreatedAt == nil { + return Timestamp{} + } + return *e.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetDescription() string { + if e == nil || e.Description == nil { + return "" + } + return *e.Description +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetHTMLURL() string { + if e == nil || e.HTMLURL == nil { + return "" + } + return *e.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetID() int { + if e == nil || e.ID == nil { + return 0 + } + return *e.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetName() string { + if e == nil || e.Name == nil { + return "" + } + return *e.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetNodeID() string { + if e == nil || e.NodeID == nil { + return "" + } + return *e.NodeID +} + +// GetSlug returns the Slug field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetSlug() string { + if e == nil || e.Slug == nil { + return "" + } + return *e.Slug +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetUpdatedAt() Timestamp { + if e == nil || e.UpdatedAt == nil { + return Timestamp{} + } + return *e.UpdatedAt +} + +// GetWebsiteURL returns the WebsiteURL field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetWebsiteURL() string { + if e == nil || e.WebsiteURL == nil { + return "" + } + return *e.WebsiteURL +} + +// GetAllowsPublicRepositories returns the AllowsPublicRepositories field if it's non-nil, zero value otherwise. +func (e *EnterpriseRunnerGroup) GetAllowsPublicRepositories() bool { + if e == nil || e.AllowsPublicRepositories == nil { + return false + } + return *e.AllowsPublicRepositories +} + +// GetDefault returns the Default field if it's non-nil, zero value otherwise. +func (e *EnterpriseRunnerGroup) GetDefault() bool { + if e == nil || e.Default == nil { + return false + } + return *e.Default +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (e *EnterpriseRunnerGroup) GetID() int64 { + if e == nil || e.ID == nil { + return 0 + } + return *e.ID +} + +// GetInherited returns the Inherited field if it's non-nil, zero value otherwise. +func (e *EnterpriseRunnerGroup) GetInherited() bool { + if e == nil || e.Inherited == nil { + return false + } + return *e.Inherited +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (e *EnterpriseRunnerGroup) GetName() string { + if e == nil || e.Name == nil { + return "" + } + return *e.Name +} + +// GetRestrictedToWorkflows returns the RestrictedToWorkflows field if it's non-nil, zero value otherwise. +func (e *EnterpriseRunnerGroup) GetRestrictedToWorkflows() bool { + if e == nil || e.RestrictedToWorkflows == nil { + return false + } + return *e.RestrictedToWorkflows +} + +// GetRunnersURL returns the RunnersURL field if it's non-nil, zero value otherwise. +func (e *EnterpriseRunnerGroup) GetRunnersURL() string { + if e == nil || e.RunnersURL == nil { + return "" + } + return *e.RunnersURL +} + +// GetSelectedOrganizationsURL returns the SelectedOrganizationsURL field if it's non-nil, zero value otherwise. +func (e *EnterpriseRunnerGroup) GetSelectedOrganizationsURL() string { + if e == nil || e.SelectedOrganizationsURL == nil { + return "" + } + return *e.SelectedOrganizationsURL +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (e *EnterpriseRunnerGroup) GetVisibility() string { + if e == nil || e.Visibility == nil { + return "" + } + return *e.Visibility +} + +// GetWorkflowRestrictionsReadOnly returns the WorkflowRestrictionsReadOnly field if it's non-nil, zero value otherwise. +func (e *EnterpriseRunnerGroup) GetWorkflowRestrictionsReadOnly() bool { + if e == nil || e.WorkflowRestrictionsReadOnly == nil { + return false + } + return *e.WorkflowRestrictionsReadOnly +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (e *EnterpriseRunnerGroups) GetTotalCount() int { + if e == nil || e.TotalCount == nil { + return 0 + } + return *e.TotalCount +} + +// GetAdvancedSecurityEnabledForNewRepositories returns the AdvancedSecurityEnabledForNewRepositories field if it's non-nil, zero value otherwise. +func (e *EnterpriseSecurityAnalysisSettings) GetAdvancedSecurityEnabledForNewRepositories() bool { + if e == nil || e.AdvancedSecurityEnabledForNewRepositories == nil { + return false + } + return *e.AdvancedSecurityEnabledForNewRepositories +} + +// GetSecretScanningEnabledForNewRepositories returns the SecretScanningEnabledForNewRepositories field if it's non-nil, zero value otherwise. +func (e *EnterpriseSecurityAnalysisSettings) GetSecretScanningEnabledForNewRepositories() bool { + if e == nil || e.SecretScanningEnabledForNewRepositories == nil { + return false + } + return *e.SecretScanningEnabledForNewRepositories +} + +// GetSecretScanningPushProtectionCustomLink returns the SecretScanningPushProtectionCustomLink field if it's non-nil, zero value otherwise. +func (e *EnterpriseSecurityAnalysisSettings) GetSecretScanningPushProtectionCustomLink() string { + if e == nil || e.SecretScanningPushProtectionCustomLink == nil { + return "" + } + return *e.SecretScanningPushProtectionCustomLink +} + +// GetSecretScanningPushProtectionEnabledForNewRepositories returns the SecretScanningPushProtectionEnabledForNewRepositories field if it's non-nil, zero value otherwise. +func (e *EnterpriseSecurityAnalysisSettings) GetSecretScanningPushProtectionEnabledForNewRepositories() bool { + if e == nil || e.SecretScanningPushProtectionEnabledForNewRepositories == nil { + return false + } + return *e.SecretScanningPushProtectionEnabledForNewRepositories +} + +// GetSecretScanningValidityChecksEnabled returns the SecretScanningValidityChecksEnabled field if it's non-nil, zero value otherwise. +func (e *EnterpriseSecurityAnalysisSettings) GetSecretScanningValidityChecksEnabled() bool { + if e == nil || e.SecretScanningValidityChecksEnabled == nil { + return false + } + return *e.SecretScanningValidityChecksEnabled +} + +// GetCanAdminsBypass returns the CanAdminsBypass field if it's non-nil, zero value otherwise. +func (e *Environment) GetCanAdminsBypass() bool { + if e == nil || e.CanAdminsBypass == nil { + return false + } + return *e.CanAdminsBypass +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (e *Environment) GetCreatedAt() Timestamp { + if e == nil || e.CreatedAt == nil { + return Timestamp{} + } + return *e.CreatedAt +} + +// GetDeploymentBranchPolicy returns the DeploymentBranchPolicy field. +func (e *Environment) GetDeploymentBranchPolicy() *BranchPolicy { + if e == nil { + return nil + } + return e.DeploymentBranchPolicy +} + +// GetEnvironmentName returns the EnvironmentName field if it's non-nil, zero value otherwise. +func (e *Environment) GetEnvironmentName() string { + if e == nil || e.EnvironmentName == nil { + return "" + } + return *e.EnvironmentName +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (e *Environment) GetHTMLURL() string { + if e == nil || e.HTMLURL == nil { + return "" + } + return *e.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (e *Environment) GetID() int64 { + if e == nil || e.ID == nil { + return 0 + } + return *e.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (e *Environment) GetName() string { + if e == nil || e.Name == nil { + return "" + } + return *e.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (e *Environment) GetNodeID() string { + if e == nil || e.NodeID == nil { + return "" + } + return *e.NodeID +} + +// GetOwner returns the Owner field if it's non-nil, zero value otherwise. +func (e *Environment) GetOwner() string { + if e == nil || e.Owner == nil { + return "" + } + return *e.Owner +} + +// GetRepo returns the Repo field if it's non-nil, zero value otherwise. +func (e *Environment) GetRepo() string { + if e == nil || e.Repo == nil { + return "" + } + return *e.Repo +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (e *Environment) GetUpdatedAt() Timestamp { + if e == nil || e.UpdatedAt == nil { + return Timestamp{} + } + return *e.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (e *Environment) GetURL() string { + if e == nil || e.URL == nil { + return "" + } + return *e.URL +} + +// GetWaitTimer returns the WaitTimer field if it's non-nil, zero value otherwise. +func (e *Environment) GetWaitTimer() int { + if e == nil || e.WaitTimer == nil { + return 0 + } + return *e.WaitTimer +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (e *EnvResponse) GetTotalCount() int { + if e == nil || e.TotalCount == nil { + return 0 + } + return *e.TotalCount +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (e *EnvReviewers) GetID() int64 { + if e == nil || e.ID == nil { + return 0 + } + return *e.ID +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (e *EnvReviewers) GetType() string { + if e == nil || e.Type == nil { + return "" + } + return *e.Type +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (e *ErrorBlock) GetCreatedAt() Timestamp { + if e == nil || e.CreatedAt == nil { + return Timestamp{} + } + return *e.CreatedAt +} + +// GetBlock returns the Block field. +func (e *ErrorResponse) GetBlock() *ErrorBlock { + if e == nil { + return nil + } + return e.Block +} + +// GetActor returns the Actor field. +func (e *Event) GetActor() *User { + if e == nil { + return nil + } + return e.Actor +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (e *Event) GetCreatedAt() Timestamp { + if e == nil || e.CreatedAt == nil { + return Timestamp{} + } + return *e.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (e *Event) GetID() string { + if e == nil || e.ID == nil { + return "" + } + return *e.ID +} + +// GetOrg returns the Org field. +func (e *Event) GetOrg() *Organization { + if e == nil { + return nil + } + return e.Org +} + +// GetPublic returns the Public field if it's non-nil, zero value otherwise. +func (e *Event) GetPublic() bool { + if e == nil || e.Public == nil { + return false + } + return *e.Public +} + +// GetRawPayload returns the RawPayload field if it's non-nil, zero value otherwise. +func (e *Event) GetRawPayload() json.RawMessage { + if e == nil || e.RawPayload == nil { + return json.RawMessage{} + } + return *e.RawPayload +} + +// GetRepo returns the Repo field. +func (e *Event) GetRepo() *Repository { + if e == nil { + return nil + } + return e.Repo +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (e *Event) GetType() string { + if e == nil || e.Type == nil { + return "" + } + return *e.Type +} + +// GetGroupID returns the GroupID field if it's non-nil, zero value otherwise. +func (e *ExternalGroup) GetGroupID() int64 { + if e == nil || e.GroupID == nil { + return 0 + } + return *e.GroupID +} + +// GetGroupName returns the GroupName field if it's non-nil, zero value otherwise. +func (e *ExternalGroup) GetGroupName() string { + if e == nil || e.GroupName == nil { + return "" + } + return *e.GroupName +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (e *ExternalGroup) GetUpdatedAt() Timestamp { + if e == nil || e.UpdatedAt == nil { + return Timestamp{} + } + return *e.UpdatedAt +} + +// GetMemberEmail returns the MemberEmail field if it's non-nil, zero value otherwise. +func (e *ExternalGroupMember) GetMemberEmail() string { + if e == nil || e.MemberEmail == nil { + return "" + } + return *e.MemberEmail +} + +// GetMemberID returns the MemberID field if it's non-nil, zero value otherwise. +func (e *ExternalGroupMember) GetMemberID() int64 { + if e == nil || e.MemberID == nil { + return 0 + } + return *e.MemberID +} + +// GetMemberLogin returns the MemberLogin field if it's non-nil, zero value otherwise. +func (e *ExternalGroupMember) GetMemberLogin() string { + if e == nil || e.MemberLogin == nil { + return "" + } + return *e.MemberLogin +} + +// GetMemberName returns the MemberName field if it's non-nil, zero value otherwise. +func (e *ExternalGroupMember) GetMemberName() string { + if e == nil || e.MemberName == nil { + return "" + } + return *e.MemberName +} + +// GetTeamID returns the TeamID field if it's non-nil, zero value otherwise. +func (e *ExternalGroupTeam) GetTeamID() int64 { + if e == nil || e.TeamID == nil { + return 0 + } + return *e.TeamID +} + +// GetTeamName returns the TeamName field if it's non-nil, zero value otherwise. +func (e *ExternalGroupTeam) GetTeamName() string { + if e == nil || e.TeamName == nil { + return "" + } + return *e.TeamName +} + +// GetHRef returns the HRef field if it's non-nil, zero value otherwise. +func (f *FeedLink) GetHRef() string { + if f == nil || f.HRef == nil { + return "" + } + return *f.HRef +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (f *FeedLink) GetType() string { + if f == nil || f.Type == nil { + return "" + } + return *f.Type +} + +// GetCurrentUser returns the CurrentUser field. +func (f *FeedLinks) GetCurrentUser() *FeedLink { + if f == nil { + return nil + } + return f.CurrentUser +} + +// GetCurrentUserActor returns the CurrentUserActor field. +func (f *FeedLinks) GetCurrentUserActor() *FeedLink { + if f == nil { + return nil + } + return f.CurrentUserActor +} + +// GetCurrentUserOrganization returns the CurrentUserOrganization field. +func (f *FeedLinks) GetCurrentUserOrganization() *FeedLink { + if f == nil { + return nil + } + return f.CurrentUserOrganization +} + +// GetCurrentUserPublic returns the CurrentUserPublic field. +func (f *FeedLinks) GetCurrentUserPublic() *FeedLink { + if f == nil { + return nil + } + return f.CurrentUserPublic +} + +// GetTimeline returns the Timeline field. +func (f *FeedLinks) GetTimeline() *FeedLink { + if f == nil { + return nil + } + return f.Timeline +} + +// GetUser returns the User field. +func (f *FeedLinks) GetUser() *FeedLink { + if f == nil { + return nil + } + return f.User +} + +// GetCurrentUserActorURL returns the CurrentUserActorURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetCurrentUserActorURL() string { + if f == nil || f.CurrentUserActorURL == nil { + return "" + } + return *f.CurrentUserActorURL +} + +// GetCurrentUserOrganizationURL returns the CurrentUserOrganizationURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetCurrentUserOrganizationURL() string { + if f == nil || f.CurrentUserOrganizationURL == nil { + return "" + } + return *f.CurrentUserOrganizationURL +} + +// GetCurrentUserPublicURL returns the CurrentUserPublicURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetCurrentUserPublicURL() string { + if f == nil || f.CurrentUserPublicURL == nil { + return "" + } + return *f.CurrentUserPublicURL +} + +// GetCurrentUserURL returns the CurrentUserURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetCurrentUserURL() string { + if f == nil || f.CurrentUserURL == nil { + return "" + } + return *f.CurrentUserURL +} + +// GetLinks returns the Links field. +func (f *Feeds) GetLinks() *FeedLinks { + if f == nil { + return nil + } + return f.Links +} + +// GetTimelineURL returns the TimelineURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetTimelineURL() string { + if f == nil || f.TimelineURL == nil { + return "" + } + return *f.TimelineURL +} + +// GetUserURL returns the UserURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetUserURL() string { + if f == nil || f.UserURL == nil { + return "" + } + return *f.UserURL +} + +// GetIdentifier returns the Identifier field if it's non-nil, zero value otherwise. +func (f *FirstPatchedVersion) GetIdentifier() string { + if f == nil || f.Identifier == nil { + return "" + } + return *f.Identifier +} + +// GetForkee returns the Forkee field. +func (f *ForkEvent) GetForkee() *Repository { + if f == nil { + return nil + } + return f.Forkee +} + +// GetInstallation returns the Installation field. +func (f *ForkEvent) GetInstallation() *Installation { + if f == nil { + return nil + } + return f.Installation +} + +// GetRepo returns the Repo field. +func (f *ForkEvent) GetRepo() *Repository { + if f == nil { + return nil + } + return f.Repo +} + +// GetSender returns the Sender field. +func (f *ForkEvent) GetSender() *User { + if f == nil { + return nil + } + return f.Sender +} + +// GetWorkFolder returns the WorkFolder field if it's non-nil, zero value otherwise. +func (g *GenerateJITConfigRequest) GetWorkFolder() string { + if g == nil || g.WorkFolder == nil { + return "" + } + return *g.WorkFolder +} + +// GetPreviousTagName returns the PreviousTagName field if it's non-nil, zero value otherwise. +func (g *GenerateNotesOptions) GetPreviousTagName() string { + if g == nil || g.PreviousTagName == nil { + return "" + } + return *g.PreviousTagName +} + +// GetTargetCommitish returns the TargetCommitish field if it's non-nil, zero value otherwise. +func (g *GenerateNotesOptions) GetTargetCommitish() string { + if g == nil || g.TargetCommitish == nil { + return "" + } + return *g.TargetCommitish +} + +// GetInclude returns the Include field if it's non-nil, zero value otherwise. +func (g *GetAuditLogOptions) GetInclude() string { + if g == nil || g.Include == nil { + return "" + } + return *g.Include +} + +// GetOrder returns the Order field if it's non-nil, zero value otherwise. +func (g *GetAuditLogOptions) GetOrder() string { + if g == nil || g.Order == nil { + return "" + } + return *g.Order +} + +// GetPhrase returns the Phrase field if it's non-nil, zero value otherwise. +func (g *GetAuditLogOptions) GetPhrase() string { + if g == nil || g.Phrase == nil { + return "" + } + return *g.Phrase +} + +// GetComments returns the Comments field if it's non-nil, zero value otherwise. +func (g *Gist) GetComments() int { + if g == nil || g.Comments == nil { + return 0 + } + return *g.Comments +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (g *Gist) GetCreatedAt() Timestamp { + if g == nil || g.CreatedAt == nil { + return Timestamp{} + } + return *g.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (g *Gist) GetDescription() string { + if g == nil || g.Description == nil { + return "" + } + return *g.Description +} + +// GetFiles returns the Files map if it's non-nil, an empty map otherwise. +func (g *Gist) GetFiles() map[GistFilename]GistFile { + if g == nil || g.Files == nil { + return map[GistFilename]GistFile{} + } + return g.Files +} + +// GetGitPullURL returns the GitPullURL field if it's non-nil, zero value otherwise. +func (g *Gist) GetGitPullURL() string { + if g == nil || g.GitPullURL == nil { + return "" + } + return *g.GitPullURL +} + +// GetGitPushURL returns the GitPushURL field if it's non-nil, zero value otherwise. +func (g *Gist) GetGitPushURL() string { + if g == nil || g.GitPushURL == nil { + return "" + } + return *g.GitPushURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (g *Gist) GetHTMLURL() string { + if g == nil || g.HTMLURL == nil { + return "" + } + return *g.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (g *Gist) GetID() string { + if g == nil || g.ID == nil { + return "" + } + return *g.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (g *Gist) GetNodeID() string { + if g == nil || g.NodeID == nil { + return "" + } + return *g.NodeID +} + +// GetOwner returns the Owner field. +func (g *Gist) GetOwner() *User { + if g == nil { + return nil + } + return g.Owner +} + +// GetPublic returns the Public field if it's non-nil, zero value otherwise. +func (g *Gist) GetPublic() bool { + if g == nil || g.Public == nil { + return false + } + return *g.Public +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (g *Gist) GetUpdatedAt() Timestamp { + if g == nil || g.UpdatedAt == nil { + return Timestamp{} + } + return *g.UpdatedAt +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (g *GistComment) GetBody() string { + if g == nil || g.Body == nil { + return "" + } + return *g.Body +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (g *GistComment) GetCreatedAt() Timestamp { + if g == nil || g.CreatedAt == nil { + return Timestamp{} + } + return *g.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (g *GistComment) GetID() int64 { + if g == nil || g.ID == nil { + return 0 + } + return *g.ID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (g *GistComment) GetURL() string { + if g == nil || g.URL == nil { + return "" + } + return *g.URL +} + +// GetUser returns the User field. +func (g *GistComment) GetUser() *User { + if g == nil { + return nil + } + return g.User +} + +// GetChangeStatus returns the ChangeStatus field. +func (g *GistCommit) GetChangeStatus() *CommitStats { + if g == nil { + return nil + } + return g.ChangeStatus +} + +// GetCommittedAt returns the CommittedAt field if it's non-nil, zero value otherwise. +func (g *GistCommit) GetCommittedAt() Timestamp { + if g == nil || g.CommittedAt == nil { + return Timestamp{} + } + return *g.CommittedAt +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (g *GistCommit) GetNodeID() string { + if g == nil || g.NodeID == nil { + return "" + } + return *g.NodeID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (g *GistCommit) GetURL() string { + if g == nil || g.URL == nil { + return "" + } + return *g.URL +} + +// GetUser returns the User field. +func (g *GistCommit) GetUser() *User { + if g == nil { + return nil + } + return g.User +} + +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (g *GistCommit) GetVersion() string { + if g == nil || g.Version == nil { + return "" + } + return *g.Version +} + +// GetContent returns the Content field if it's non-nil, zero value otherwise. +func (g *GistFile) GetContent() string { + if g == nil || g.Content == nil { + return "" + } + return *g.Content +} + +// GetFilename returns the Filename field if it's non-nil, zero value otherwise. +func (g *GistFile) GetFilename() string { + if g == nil || g.Filename == nil { + return "" + } + return *g.Filename +} + +// GetLanguage returns the Language field if it's non-nil, zero value otherwise. +func (g *GistFile) GetLanguage() string { + if g == nil || g.Language == nil { + return "" + } + return *g.Language +} + +// GetRawURL returns the RawURL field if it's non-nil, zero value otherwise. +func (g *GistFile) GetRawURL() string { + if g == nil || g.RawURL == nil { + return "" + } + return *g.RawURL +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (g *GistFile) GetSize() int { + if g == nil || g.Size == nil { + return 0 + } + return *g.Size +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (g *GistFile) GetType() string { + if g == nil || g.Type == nil { + return "" + } + return *g.Type +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (g *GistFork) GetCreatedAt() Timestamp { + if g == nil || g.CreatedAt == nil { + return Timestamp{} + } + return *g.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (g *GistFork) GetID() string { + if g == nil || g.ID == nil { + return "" + } + return *g.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (g *GistFork) GetNodeID() string { + if g == nil || g.NodeID == nil { + return "" + } + return *g.NodeID +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (g *GistFork) GetUpdatedAt() Timestamp { + if g == nil || g.UpdatedAt == nil { + return Timestamp{} + } + return *g.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (g *GistFork) GetURL() string { + if g == nil || g.URL == nil { + return "" + } + return *g.URL +} + +// GetUser returns the User field. +func (g *GistFork) GetUser() *User { + if g == nil { + return nil + } + return g.User +} + +// GetPrivateGists returns the PrivateGists field if it's non-nil, zero value otherwise. +func (g *GistStats) GetPrivateGists() int { + if g == nil || g.PrivateGists == nil { + return 0 + } + return *g.PrivateGists +} + +// GetPublicGists returns the PublicGists field if it's non-nil, zero value otherwise. +func (g *GistStats) GetPublicGists() int { + if g == nil || g.PublicGists == nil { + return 0 + } + return *g.PublicGists +} + +// GetTotalGists returns the TotalGists field if it's non-nil, zero value otherwise. +func (g *GistStats) GetTotalGists() int { + if g == nil || g.TotalGists == nil { + return 0 + } + return *g.TotalGists +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (g *GitHubAppAuthorizationEvent) GetAction() string { + if g == nil || g.Action == nil { + return "" + } + return *g.Action +} + +// GetInstallation returns the Installation field. +func (g *GitHubAppAuthorizationEvent) GetInstallation() *Installation { + if g == nil { + return nil + } + return g.Installation +} + +// GetSender returns the Sender field. +func (g *GitHubAppAuthorizationEvent) GetSender() *User { + if g == nil { + return nil + } + return g.Sender +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (g *Gitignore) GetName() string { + if g == nil || g.Name == nil { + return "" + } + return *g.Name +} + +// GetSource returns the Source field if it's non-nil, zero value otherwise. +func (g *Gitignore) GetSource() string { + if g == nil || g.Source == nil { + return "" + } + return *g.Source +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (g *GitObject) GetSHA() string { + if g == nil || g.SHA == nil { + return "" + } + return *g.SHA +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (g *GitObject) GetType() string { + if g == nil || g.Type == nil { + return "" + } + return *g.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (g *GitObject) GetURL() string { + if g == nil || g.URL == nil { + return "" + } + return *g.URL +} + +// GetGithubReviewedAt returns the GithubReviewedAt field if it's non-nil, zero value otherwise. +func (g *GlobalSecurityAdvisory) GetGithubReviewedAt() Timestamp { + if g == nil || g.GithubReviewedAt == nil { + return Timestamp{} + } + return *g.GithubReviewedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (g *GlobalSecurityAdvisory) GetID() int64 { + if g == nil || g.ID == nil { + return 0 + } + return *g.ID +} + +// GetNVDPublishedAt returns the NVDPublishedAt field if it's non-nil, zero value otherwise. +func (g *GlobalSecurityAdvisory) GetNVDPublishedAt() Timestamp { + if g == nil || g.NVDPublishedAt == nil { + return Timestamp{} + } + return *g.NVDPublishedAt +} + +// GetRepositoryAdvisoryURL returns the RepositoryAdvisoryURL field if it's non-nil, zero value otherwise. +func (g *GlobalSecurityAdvisory) GetRepositoryAdvisoryURL() string { + if g == nil || g.RepositoryAdvisoryURL == nil { + return "" + } + return *g.RepositoryAdvisoryURL +} + +// GetSourceCodeLocation returns the SourceCodeLocation field if it's non-nil, zero value otherwise. +func (g *GlobalSecurityAdvisory) GetSourceCodeLocation() string { + if g == nil || g.SourceCodeLocation == nil { + return "" + } + return *g.SourceCodeLocation +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (g *GlobalSecurityAdvisory) GetType() string { + if g == nil || g.Type == nil { + return "" + } + return *g.Type +} + +// GetFirstPatchedVersion returns the FirstPatchedVersion field if it's non-nil, zero value otherwise. +func (g *GlobalSecurityVulnerability) GetFirstPatchedVersion() string { + if g == nil || g.FirstPatchedVersion == nil { + return "" + } + return *g.FirstPatchedVersion +} + +// GetPackage returns the Package field. +func (g *GlobalSecurityVulnerability) GetPackage() *VulnerabilityPackage { + if g == nil { + return nil + } + return g.Package +} + +// GetVulnerableVersionRange returns the VulnerableVersionRange field if it's non-nil, zero value otherwise. +func (g *GlobalSecurityVulnerability) GetVulnerableVersionRange() string { + if g == nil || g.VulnerableVersionRange == nil { + return "" + } + return *g.VulnerableVersionRange +} + +// GetInstallation returns the Installation field. +func (g *GollumEvent) GetInstallation() *Installation { + if g == nil { + return nil + } + return g.Installation +} + +// GetOrg returns the Org field. +func (g *GollumEvent) GetOrg() *Organization { + if g == nil { + return nil + } + return g.Org +} + +// GetRepo returns the Repo field. +func (g *GollumEvent) GetRepo() *Repository { + if g == nil { + return nil + } + return g.Repo +} + +// GetSender returns the Sender field. +func (g *GollumEvent) GetSender() *User { + if g == nil { + return nil + } + return g.Sender +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (g *GPGEmail) GetEmail() string { + if g == nil || g.Email == nil { + return "" + } + return *g.Email +} + +// GetVerified returns the Verified field if it's non-nil, zero value otherwise. +func (g *GPGEmail) GetVerified() bool { + if g == nil || g.Verified == nil { + return false + } + return *g.Verified +} + +// GetCanCertify returns the CanCertify field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetCanCertify() bool { + if g == nil || g.CanCertify == nil { + return false + } + return *g.CanCertify +} + +// GetCanEncryptComms returns the CanEncryptComms field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetCanEncryptComms() bool { + if g == nil || g.CanEncryptComms == nil { + return false + } + return *g.CanEncryptComms +} + +// GetCanEncryptStorage returns the CanEncryptStorage field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetCanEncryptStorage() bool { + if g == nil || g.CanEncryptStorage == nil { + return false + } + return *g.CanEncryptStorage +} + +// GetCanSign returns the CanSign field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetCanSign() bool { + if g == nil || g.CanSign == nil { + return false + } + return *g.CanSign +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetCreatedAt() Timestamp { + if g == nil || g.CreatedAt == nil { + return Timestamp{} + } + return *g.CreatedAt +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetExpiresAt() Timestamp { + if g == nil || g.ExpiresAt == nil { + return Timestamp{} + } + return *g.ExpiresAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetID() int64 { + if g == nil || g.ID == nil { + return 0 + } + return *g.ID +} + +// GetKeyID returns the KeyID field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetKeyID() string { + if g == nil || g.KeyID == nil { + return "" + } + return *g.KeyID +} + +// GetPrimaryKeyID returns the PrimaryKeyID field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetPrimaryKeyID() int64 { + if g == nil || g.PrimaryKeyID == nil { + return 0 + } + return *g.PrimaryKeyID +} + +// GetPublicKey returns the PublicKey field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetPublicKey() string { + if g == nil || g.PublicKey == nil { + return "" + } + return *g.PublicKey +} + +// GetRawKey returns the RawKey field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetRawKey() string { + if g == nil || g.RawKey == nil { + return "" + } + return *g.RawKey +} + +// GetApp returns the App field. +func (g *Grant) GetApp() *AuthorizationApp { + if g == nil { + return nil + } + return g.App +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (g *Grant) GetCreatedAt() Timestamp { + if g == nil || g.CreatedAt == nil { + return Timestamp{} + } + return *g.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (g *Grant) GetID() int64 { + if g == nil || g.ID == nil { + return 0 + } + return *g.ID +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (g *Grant) GetUpdatedAt() Timestamp { + if g == nil || g.UpdatedAt == nil { + return Timestamp{} + } + return *g.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (g *Grant) GetURL() string { + if g == nil || g.URL == nil { + return "" + } + return *g.URL +} + +// GetAuthor returns the Author field. +func (h *HeadCommit) GetAuthor() *CommitAuthor { + if h == nil { + return nil + } + return h.Author +} + +// GetCommitter returns the Committer field. +func (h *HeadCommit) GetCommitter() *CommitAuthor { + if h == nil { + return nil + } + return h.Committer +} + +// GetDistinct returns the Distinct field if it's non-nil, zero value otherwise. +func (h *HeadCommit) GetDistinct() bool { + if h == nil || h.Distinct == nil { + return false + } + return *h.Distinct +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (h *HeadCommit) GetID() string { + if h == nil || h.ID == nil { + return "" + } + return *h.ID +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (h *HeadCommit) GetMessage() string { + if h == nil || h.Message == nil { + return "" + } + return *h.Message +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (h *HeadCommit) GetSHA() string { + if h == nil || h.SHA == nil { + return "" + } + return *h.SHA +} + +// GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise. +func (h *HeadCommit) GetTimestamp() Timestamp { + if h == nil || h.Timestamp == nil { + return Timestamp{} + } + return *h.Timestamp +} + +// GetTreeID returns the TreeID field if it's non-nil, zero value otherwise. +func (h *HeadCommit) GetTreeID() string { + if h == nil || h.TreeID == nil { + return "" + } + return *h.TreeID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (h *HeadCommit) GetURL() string { + if h == nil || h.URL == nil { + return "" + } + return *h.URL +} + +// GetActive returns the Active field if it's non-nil, zero value otherwise. +func (h *Hook) GetActive() bool { + if h == nil || h.Active == nil { + return false + } + return *h.Active +} + +// GetConfig returns the Config field. +func (h *Hook) GetConfig() *HookConfig { + if h == nil { + return nil + } + return h.Config +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (h *Hook) GetCreatedAt() Timestamp { + if h == nil || h.CreatedAt == nil { + return Timestamp{} + } + return *h.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (h *Hook) GetID() int64 { + if h == nil || h.ID == nil { + return 0 + } + return *h.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (h *Hook) GetName() string { + if h == nil || h.Name == nil { + return "" + } + return *h.Name +} + +// GetPingURL returns the PingURL field if it's non-nil, zero value otherwise. +func (h *Hook) GetPingURL() string { + if h == nil || h.PingURL == nil { + return "" + } + return *h.PingURL +} + +// GetTestURL returns the TestURL field if it's non-nil, zero value otherwise. +func (h *Hook) GetTestURL() string { + if h == nil || h.TestURL == nil { + return "" + } + return *h.TestURL +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (h *Hook) GetType() string { + if h == nil || h.Type == nil { + return "" + } + return *h.Type +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (h *Hook) GetUpdatedAt() Timestamp { + if h == nil || h.UpdatedAt == nil { + return Timestamp{} + } + return *h.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (h *Hook) GetURL() string { + if h == nil || h.URL == nil { + return "" + } + return *h.URL +} + +// GetContentType returns the ContentType field if it's non-nil, zero value otherwise. +func (h *HookConfig) GetContentType() string { + if h == nil || h.ContentType == nil { + return "" + } + return *h.ContentType +} + +// GetInsecureSSL returns the InsecureSSL field if it's non-nil, zero value otherwise. +func (h *HookConfig) GetInsecureSSL() string { + if h == nil || h.InsecureSSL == nil { + return "" + } + return *h.InsecureSSL +} + +// GetSecret returns the Secret field if it's non-nil, zero value otherwise. +func (h *HookConfig) GetSecret() string { + if h == nil || h.Secret == nil { + return "" + } + return *h.Secret +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (h *HookConfig) GetURL() string { + if h == nil || h.URL == nil { + return "" + } + return *h.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetAction() string { + if h == nil || h.Action == nil { + return "" + } + return *h.Action +} + +// GetDeliveredAt returns the DeliveredAt field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetDeliveredAt() Timestamp { + if h == nil || h.DeliveredAt == nil { + return Timestamp{} + } + return *h.DeliveredAt +} + +// GetDuration returns the Duration field. +func (h *HookDelivery) GetDuration() *float64 { + if h == nil { + return nil + } + return h.Duration +} + +// GetEvent returns the Event field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetEvent() string { + if h == nil || h.Event == nil { + return "" + } + return *h.Event +} + +// GetGUID returns the GUID field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetGUID() string { + if h == nil || h.GUID == nil { + return "" + } + return *h.GUID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetID() int64 { + if h == nil || h.ID == nil { + return 0 + } + return *h.ID +} + +// GetInstallationID returns the InstallationID field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetInstallationID() int64 { + if h == nil || h.InstallationID == nil { + return 0 + } + return *h.InstallationID +} + +// GetRedelivery returns the Redelivery field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetRedelivery() bool { + if h == nil || h.Redelivery == nil { + return false + } + return *h.Redelivery +} + +// GetRepositoryID returns the RepositoryID field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetRepositoryID() int64 { + if h == nil || h.RepositoryID == nil { + return 0 + } + return *h.RepositoryID +} + +// GetRequest returns the Request field. +func (h *HookDelivery) GetRequest() *HookRequest { + if h == nil { + return nil + } + return h.Request +} + +// GetResponse returns the Response field. +func (h *HookDelivery) GetResponse() *HookResponse { + if h == nil { + return nil + } + return h.Response +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetStatus() string { + if h == nil || h.Status == nil { + return "" + } + return *h.Status +} + +// GetStatusCode returns the StatusCode field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetStatusCode() int { + if h == nil || h.StatusCode == nil { + return 0 + } + return *h.StatusCode +} + +// GetHeaders returns the Headers map if it's non-nil, an empty map otherwise. +func (h *HookRequest) GetHeaders() map[string]string { + if h == nil || h.Headers == nil { + return map[string]string{} + } + return h.Headers +} + +// GetRawPayload returns the RawPayload field if it's non-nil, zero value otherwise. +func (h *HookRequest) GetRawPayload() json.RawMessage { + if h == nil || h.RawPayload == nil { + return json.RawMessage{} + } + return *h.RawPayload +} + +// GetHeaders returns the Headers map if it's non-nil, an empty map otherwise. +func (h *HookResponse) GetHeaders() map[string]string { + if h == nil || h.Headers == nil { + return map[string]string{} + } + return h.Headers +} + +// GetRawPayload returns the RawPayload field if it's non-nil, zero value otherwise. +func (h *HookResponse) GetRawPayload() json.RawMessage { + if h == nil || h.RawPayload == nil { + return json.RawMessage{} + } + return *h.RawPayload +} + +// GetActiveHooks returns the ActiveHooks field if it's non-nil, zero value otherwise. +func (h *HookStats) GetActiveHooks() int { + if h == nil || h.ActiveHooks == nil { + return 0 + } + return *h.ActiveHooks +} + +// GetInactiveHooks returns the InactiveHooks field if it's non-nil, zero value otherwise. +func (h *HookStats) GetInactiveHooks() int { + if h == nil || h.InactiveHooks == nil { + return 0 + } + return *h.InactiveHooks +} + +// GetTotalHooks returns the TotalHooks field if it's non-nil, zero value otherwise. +func (h *HookStats) GetTotalHooks() int { + if h == nil || h.TotalHooks == nil { + return 0 + } + return *h.TotalHooks +} + +// GetGroupDescription returns the GroupDescription field if it's non-nil, zero value otherwise. +func (i *IDPGroup) GetGroupDescription() string { + if i == nil || i.GroupDescription == nil { + return "" + } + return *i.GroupDescription +} + +// GetGroupID returns the GroupID field if it's non-nil, zero value otherwise. +func (i *IDPGroup) GetGroupID() string { + if i == nil || i.GroupID == nil { + return "" + } + return *i.GroupID +} + +// GetGroupName returns the GroupName field if it's non-nil, zero value otherwise. +func (i *IDPGroup) GetGroupName() string { + if i == nil || i.GroupName == nil { + return "" + } + return *i.GroupName +} + +// GetAuthorsCount returns the AuthorsCount field if it's non-nil, zero value otherwise. +func (i *Import) GetAuthorsCount() int { + if i == nil || i.AuthorsCount == nil { + return 0 + } + return *i.AuthorsCount +} + +// GetAuthorsURL returns the AuthorsURL field if it's non-nil, zero value otherwise. +func (i *Import) GetAuthorsURL() string { + if i == nil || i.AuthorsURL == nil { + return "" + } + return *i.AuthorsURL +} + +// GetCommitCount returns the CommitCount field if it's non-nil, zero value otherwise. +func (i *Import) GetCommitCount() int { + if i == nil || i.CommitCount == nil { + return 0 + } + return *i.CommitCount +} + +// GetFailedStep returns the FailedStep field if it's non-nil, zero value otherwise. +func (i *Import) GetFailedStep() string { + if i == nil || i.FailedStep == nil { + return "" + } + return *i.FailedStep +} + +// GetHasLargeFiles returns the HasLargeFiles field if it's non-nil, zero value otherwise. +func (i *Import) GetHasLargeFiles() bool { + if i == nil || i.HasLargeFiles == nil { + return false + } + return *i.HasLargeFiles +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (i *Import) GetHTMLURL() string { + if i == nil || i.HTMLURL == nil { + return "" + } + return *i.HTMLURL +} + +// GetHumanName returns the HumanName field if it's non-nil, zero value otherwise. +func (i *Import) GetHumanName() string { + if i == nil || i.HumanName == nil { + return "" + } + return *i.HumanName +} + +// GetLargeFilesCount returns the LargeFilesCount field if it's non-nil, zero value otherwise. +func (i *Import) GetLargeFilesCount() int { + if i == nil || i.LargeFilesCount == nil { + return 0 + } + return *i.LargeFilesCount +} + +// GetLargeFilesSize returns the LargeFilesSize field if it's non-nil, zero value otherwise. +func (i *Import) GetLargeFilesSize() int { + if i == nil || i.LargeFilesSize == nil { + return 0 + } + return *i.LargeFilesSize +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (i *Import) GetMessage() string { + if i == nil || i.Message == nil { + return "" + } + return *i.Message +} + +// GetPercent returns the Percent field if it's non-nil, zero value otherwise. +func (i *Import) GetPercent() int { + if i == nil || i.Percent == nil { + return 0 + } + return *i.Percent +} + +// GetPushPercent returns the PushPercent field if it's non-nil, zero value otherwise. +func (i *Import) GetPushPercent() int { + if i == nil || i.PushPercent == nil { + return 0 + } + return *i.PushPercent +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (i *Import) GetRepositoryURL() string { + if i == nil || i.RepositoryURL == nil { + return "" + } + return *i.RepositoryURL +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (i *Import) GetStatus() string { + if i == nil || i.Status == nil { + return "" + } + return *i.Status +} + +// GetStatusText returns the StatusText field if it's non-nil, zero value otherwise. +func (i *Import) GetStatusText() string { + if i == nil || i.StatusText == nil { + return "" + } + return *i.StatusText +} + +// GetTFVCProject returns the TFVCProject field if it's non-nil, zero value otherwise. +func (i *Import) GetTFVCProject() string { + if i == nil || i.TFVCProject == nil { + return "" + } + return *i.TFVCProject +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (i *Import) GetURL() string { + if i == nil || i.URL == nil { + return "" + } + return *i.URL +} + +// GetUseLFS returns the UseLFS field if it's non-nil, zero value otherwise. +func (i *Import) GetUseLFS() string { + if i == nil || i.UseLFS == nil { + return "" + } + return *i.UseLFS +} + +// GetVCS returns the VCS field if it's non-nil, zero value otherwise. +func (i *Import) GetVCS() string { + if i == nil || i.VCS == nil { + return "" + } + return *i.VCS +} + +// GetVCSPassword returns the VCSPassword field if it's non-nil, zero value otherwise. +func (i *Import) GetVCSPassword() string { + if i == nil || i.VCSPassword == nil { + return "" + } + return *i.VCSPassword +} + +// GetVCSURL returns the VCSURL field if it's non-nil, zero value otherwise. +func (i *Import) GetVCSURL() string { + if i == nil || i.VCSURL == nil { + return "" + } + return *i.VCSURL +} + +// GetVCSUsername returns the VCSUsername field if it's non-nil, zero value otherwise. +func (i *Import) GetVCSUsername() string { + if i == nil || i.VCSUsername == nil { + return "" + } + return *i.VCSUsername +} + +// GetAccessTokensURL returns the AccessTokensURL field if it's non-nil, zero value otherwise. +func (i *Installation) GetAccessTokensURL() string { + if i == nil || i.AccessTokensURL == nil { + return "" + } + return *i.AccessTokensURL +} + +// GetAccount returns the Account field. +func (i *Installation) GetAccount() *User { + if i == nil { + return nil + } + return i.Account +} + +// GetAppID returns the AppID field if it's non-nil, zero value otherwise. +func (i *Installation) GetAppID() int64 { + if i == nil || i.AppID == nil { + return 0 + } + return *i.AppID +} + +// GetAppSlug returns the AppSlug field if it's non-nil, zero value otherwise. +func (i *Installation) GetAppSlug() string { + if i == nil || i.AppSlug == nil { + return "" + } + return *i.AppSlug +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *Installation) GetCreatedAt() Timestamp { + if i == nil || i.CreatedAt == nil { + return Timestamp{} + } + return *i.CreatedAt +} + +// GetHasMultipleSingleFiles returns the HasMultipleSingleFiles field if it's non-nil, zero value otherwise. +func (i *Installation) GetHasMultipleSingleFiles() bool { + if i == nil || i.HasMultipleSingleFiles == nil { + return false + } + return *i.HasMultipleSingleFiles +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (i *Installation) GetHTMLURL() string { + if i == nil || i.HTMLURL == nil { + return "" + } + return *i.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *Installation) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (i *Installation) GetNodeID() string { + if i == nil || i.NodeID == nil { + return "" + } + return *i.NodeID +} + +// GetPermissions returns the Permissions field. +func (i *Installation) GetPermissions() *InstallationPermissions { + if i == nil { + return nil + } + return i.Permissions +} + +// GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise. +func (i *Installation) GetRepositoriesURL() string { + if i == nil || i.RepositoriesURL == nil { + return "" + } + return *i.RepositoriesURL +} + +// GetRepositorySelection returns the RepositorySelection field if it's non-nil, zero value otherwise. +func (i *Installation) GetRepositorySelection() string { + if i == nil || i.RepositorySelection == nil { + return "" + } + return *i.RepositorySelection +} + +// GetSingleFileName returns the SingleFileName field if it's non-nil, zero value otherwise. +func (i *Installation) GetSingleFileName() string { + if i == nil || i.SingleFileName == nil { + return "" + } + return *i.SingleFileName +} + +// GetSuspendedAt returns the SuspendedAt field if it's non-nil, zero value otherwise. +func (i *Installation) GetSuspendedAt() Timestamp { + if i == nil || i.SuspendedAt == nil { + return Timestamp{} + } + return *i.SuspendedAt +} + +// GetSuspendedBy returns the SuspendedBy field. +func (i *Installation) GetSuspendedBy() *User { + if i == nil { + return nil + } + return i.SuspendedBy +} + +// GetTargetID returns the TargetID field if it's non-nil, zero value otherwise. +func (i *Installation) GetTargetID() int64 { + if i == nil || i.TargetID == nil { + return 0 + } + return *i.TargetID +} + +// GetTargetType returns the TargetType field if it's non-nil, zero value otherwise. +func (i *Installation) GetTargetType() string { + if i == nil || i.TargetType == nil { + return "" + } + return *i.TargetType +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (i *Installation) GetUpdatedAt() Timestamp { + if i == nil || i.UpdatedAt == nil { + return Timestamp{} + } + return *i.UpdatedAt +} + +// GetLogin returns the Login field. +func (i *InstallationChanges) GetLogin() *InstallationLoginChange { + if i == nil { + return nil + } + return i.Login +} + +// GetSlug returns the Slug field. +func (i *InstallationChanges) GetSlug() *InstallationSlugChange { + if i == nil { + return nil + } + return i.Slug +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (i *InstallationEvent) GetAction() string { + if i == nil || i.Action == nil { + return "" + } + return *i.Action +} + +// GetInstallation returns the Installation field. +func (i *InstallationEvent) GetInstallation() *Installation { + if i == nil { + return nil + } + return i.Installation +} + +// GetOrg returns the Org field. +func (i *InstallationEvent) GetOrg() *Organization { + if i == nil { + return nil + } + return i.Org +} + +// GetRequester returns the Requester field. +func (i *InstallationEvent) GetRequester() *User { + if i == nil { + return nil + } + return i.Requester +} + +// GetSender returns the Sender field. +func (i *InstallationEvent) GetSender() *User { + if i == nil { + return nil + } + return i.Sender +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (i *InstallationLoginChange) GetFrom() string { + if i == nil || i.From == nil { + return "" + } + return *i.From +} + +// GetActions returns the Actions field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetActions() string { + if i == nil || i.Actions == nil { + return "" + } + return *i.Actions +} + +// GetActionsVariables returns the ActionsVariables field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetActionsVariables() string { + if i == nil || i.ActionsVariables == nil { + return "" + } + return *i.ActionsVariables +} + +// GetAdministration returns the Administration field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetAdministration() string { + if i == nil || i.Administration == nil { + return "" + } + return *i.Administration +} + +// GetAttestations returns the Attestations field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetAttestations() string { + if i == nil || i.Attestations == nil { + return "" + } + return *i.Attestations +} + +// GetBlocking returns the Blocking field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetBlocking() string { + if i == nil || i.Blocking == nil { + return "" + } + return *i.Blocking +} + +// GetChecks returns the Checks field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetChecks() string { + if i == nil || i.Checks == nil { + return "" + } + return *i.Checks +} + +// GetCodespaces returns the Codespaces field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetCodespaces() string { + if i == nil || i.Codespaces == nil { + return "" + } + return *i.Codespaces +} + +// GetCodespacesLifecycleAdmin returns the CodespacesLifecycleAdmin field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetCodespacesLifecycleAdmin() string { + if i == nil || i.CodespacesLifecycleAdmin == nil { + return "" + } + return *i.CodespacesLifecycleAdmin +} + +// GetCodespacesMetadata returns the CodespacesMetadata field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetCodespacesMetadata() string { + if i == nil || i.CodespacesMetadata == nil { + return "" + } + return *i.CodespacesMetadata +} + +// GetCodespacesSecrets returns the CodespacesSecrets field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetCodespacesSecrets() string { + if i == nil || i.CodespacesSecrets == nil { + return "" + } + return *i.CodespacesSecrets +} + +// GetCodespacesUserSecrets returns the CodespacesUserSecrets field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetCodespacesUserSecrets() string { + if i == nil || i.CodespacesUserSecrets == nil { + return "" + } + return *i.CodespacesUserSecrets +} + +// GetContentReferences returns the ContentReferences field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetContentReferences() string { + if i == nil || i.ContentReferences == nil { + return "" + } + return *i.ContentReferences +} + +// GetContents returns the Contents field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetContents() string { + if i == nil || i.Contents == nil { + return "" + } + return *i.Contents +} + +// GetCopilotMessages returns the CopilotMessages field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetCopilotMessages() string { + if i == nil || i.CopilotMessages == nil { + return "" + } + return *i.CopilotMessages +} + +// GetDependabotSecrets returns the DependabotSecrets field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetDependabotSecrets() string { + if i == nil || i.DependabotSecrets == nil { + return "" + } + return *i.DependabotSecrets +} + +// GetDeployments returns the Deployments field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetDeployments() string { + if i == nil || i.Deployments == nil { + return "" + } + return *i.Deployments +} + +// GetDiscussions returns the Discussions field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetDiscussions() string { + if i == nil || i.Discussions == nil { + return "" + } + return *i.Discussions +} + +// GetEmails returns the Emails field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetEmails() string { + if i == nil || i.Emails == nil { + return "" + } + return *i.Emails +} + +// GetEnvironments returns the Environments field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetEnvironments() string { + if i == nil || i.Environments == nil { + return "" + } + return *i.Environments +} + +// GetFollowers returns the Followers field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetFollowers() string { + if i == nil || i.Followers == nil { + return "" + } + return *i.Followers +} + +// GetGists returns the Gists field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetGists() string { + if i == nil || i.Gists == nil { + return "" + } + return *i.Gists +} + +// GetGitSigningSSHPublicKeys returns the GitSigningSSHPublicKeys field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetGitSigningSSHPublicKeys() string { + if i == nil || i.GitSigningSSHPublicKeys == nil { + return "" + } + return *i.GitSigningSSHPublicKeys +} + +// GetGPGKeys returns the GPGKeys field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetGPGKeys() string { + if i == nil || i.GPGKeys == nil { + return "" + } + return *i.GPGKeys +} + +// GetInteractionLimits returns the InteractionLimits field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetInteractionLimits() string { + if i == nil || i.InteractionLimits == nil { + return "" + } + return *i.InteractionLimits +} + +// GetIssues returns the Issues field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetIssues() string { + if i == nil || i.Issues == nil { + return "" + } + return *i.Issues +} + +// GetKeys returns the Keys field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetKeys() string { + if i == nil || i.Keys == nil { + return "" + } + return *i.Keys +} + +// GetMembers returns the Members field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetMembers() string { + if i == nil || i.Members == nil { + return "" + } + return *i.Members +} + +// GetMergeQueues returns the MergeQueues field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetMergeQueues() string { + if i == nil || i.MergeQueues == nil { + return "" + } + return *i.MergeQueues +} + +// GetMetadata returns the Metadata field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetMetadata() string { + if i == nil || i.Metadata == nil { + return "" + } + return *i.Metadata +} + +// GetOrganizationActionsVariables returns the OrganizationActionsVariables field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationActionsVariables() string { + if i == nil || i.OrganizationActionsVariables == nil { + return "" + } + return *i.OrganizationActionsVariables +} + +// GetOrganizationAdministration returns the OrganizationAdministration field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationAdministration() string { + if i == nil || i.OrganizationAdministration == nil { + return "" + } + return *i.OrganizationAdministration +} + +// GetOrganizationAnnouncementBanners returns the OrganizationAnnouncementBanners field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationAnnouncementBanners() string { + if i == nil || i.OrganizationAnnouncementBanners == nil { + return "" + } + return *i.OrganizationAnnouncementBanners +} + +// GetOrganizationAPIInsights returns the OrganizationAPIInsights field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationAPIInsights() string { + if i == nil || i.OrganizationAPIInsights == nil { + return "" + } + return *i.OrganizationAPIInsights +} + +// GetOrganizationCodespaces returns the OrganizationCodespaces field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationCodespaces() string { + if i == nil || i.OrganizationCodespaces == nil { + return "" + } + return *i.OrganizationCodespaces +} + +// GetOrganizationCodespacesSecrets returns the OrganizationCodespacesSecrets field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationCodespacesSecrets() string { + if i == nil || i.OrganizationCodespacesSecrets == nil { + return "" + } + return *i.OrganizationCodespacesSecrets +} + +// GetOrganizationCodespacesSettings returns the OrganizationCodespacesSettings field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationCodespacesSettings() string { + if i == nil || i.OrganizationCodespacesSettings == nil { + return "" + } + return *i.OrganizationCodespacesSettings +} + +// GetOrganizationCopilotSeatManagement returns the OrganizationCopilotSeatManagement field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationCopilotSeatManagement() string { + if i == nil || i.OrganizationCopilotSeatManagement == nil { + return "" + } + return *i.OrganizationCopilotSeatManagement +} + +// GetOrganizationCustomOrgRoles returns the OrganizationCustomOrgRoles field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationCustomOrgRoles() string { + if i == nil || i.OrganizationCustomOrgRoles == nil { + return "" + } + return *i.OrganizationCustomOrgRoles +} + +// GetOrganizationCustomProperties returns the OrganizationCustomProperties field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationCustomProperties() string { + if i == nil || i.OrganizationCustomProperties == nil { + return "" + } + return *i.OrganizationCustomProperties +} + +// GetOrganizationCustomRoles returns the OrganizationCustomRoles field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationCustomRoles() string { + if i == nil || i.OrganizationCustomRoles == nil { + return "" + } + return *i.OrganizationCustomRoles +} + +// GetOrganizationDependabotSecrets returns the OrganizationDependabotSecrets field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationDependabotSecrets() string { + if i == nil || i.OrganizationDependabotSecrets == nil { + return "" + } + return *i.OrganizationDependabotSecrets +} + +// GetOrganizationEvents returns the OrganizationEvents field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationEvents() string { + if i == nil || i.OrganizationEvents == nil { + return "" + } + return *i.OrganizationEvents +} + +// GetOrganizationHooks returns the OrganizationHooks field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationHooks() string { + if i == nil || i.OrganizationHooks == nil { + return "" + } + return *i.OrganizationHooks +} + +// GetOrganizationKnowledgeBases returns the OrganizationKnowledgeBases field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationKnowledgeBases() string { + if i == nil || i.OrganizationKnowledgeBases == nil { + return "" + } + return *i.OrganizationKnowledgeBases +} + +// GetOrganizationPackages returns the OrganizationPackages field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationPackages() string { + if i == nil || i.OrganizationPackages == nil { + return "" + } + return *i.OrganizationPackages +} + +// GetOrganizationPersonalAccessTokenRequests returns the OrganizationPersonalAccessTokenRequests field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationPersonalAccessTokenRequests() string { + if i == nil || i.OrganizationPersonalAccessTokenRequests == nil { + return "" + } + return *i.OrganizationPersonalAccessTokenRequests +} + +// GetOrganizationPersonalAccessTokens returns the OrganizationPersonalAccessTokens field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationPersonalAccessTokens() string { + if i == nil || i.OrganizationPersonalAccessTokens == nil { + return "" + } + return *i.OrganizationPersonalAccessTokens +} + +// GetOrganizationPlan returns the OrganizationPlan field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationPlan() string { + if i == nil || i.OrganizationPlan == nil { + return "" + } + return *i.OrganizationPlan +} + +// GetOrganizationPreReceiveHooks returns the OrganizationPreReceiveHooks field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationPreReceiveHooks() string { + if i == nil || i.OrganizationPreReceiveHooks == nil { + return "" + } + return *i.OrganizationPreReceiveHooks +} + +// GetOrganizationProjects returns the OrganizationProjects field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationProjects() string { + if i == nil || i.OrganizationProjects == nil { + return "" + } + return *i.OrganizationProjects +} + +// GetOrganizationSecrets returns the OrganizationSecrets field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationSecrets() string { + if i == nil || i.OrganizationSecrets == nil { + return "" + } + return *i.OrganizationSecrets +} + +// GetOrganizationSelfHostedRunners returns the OrganizationSelfHostedRunners field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationSelfHostedRunners() string { + if i == nil || i.OrganizationSelfHostedRunners == nil { + return "" + } + return *i.OrganizationSelfHostedRunners +} + +// GetOrganizationUserBlocking returns the OrganizationUserBlocking field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationUserBlocking() string { + if i == nil || i.OrganizationUserBlocking == nil { + return "" + } + return *i.OrganizationUserBlocking +} + +// GetPackages returns the Packages field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetPackages() string { + if i == nil || i.Packages == nil { + return "" + } + return *i.Packages +} + +// GetPages returns the Pages field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetPages() string { + if i == nil || i.Pages == nil { + return "" + } + return *i.Pages +} + +// GetPlan returns the Plan field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetPlan() string { + if i == nil || i.Plan == nil { + return "" + } + return *i.Plan +} + +// GetProfile returns the Profile field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetProfile() string { + if i == nil || i.Profile == nil { + return "" + } + return *i.Profile +} + +// GetPullRequests returns the PullRequests field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetPullRequests() string { + if i == nil || i.PullRequests == nil { + return "" + } + return *i.PullRequests +} + +// GetRepositoryAdvisories returns the RepositoryAdvisories field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetRepositoryAdvisories() string { + if i == nil || i.RepositoryAdvisories == nil { + return "" + } + return *i.RepositoryAdvisories +} + +// GetRepositoryCustomProperties returns the RepositoryCustomProperties field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetRepositoryCustomProperties() string { + if i == nil || i.RepositoryCustomProperties == nil { + return "" + } + return *i.RepositoryCustomProperties +} + +// GetRepositoryHooks returns the RepositoryHooks field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetRepositoryHooks() string { + if i == nil || i.RepositoryHooks == nil { + return "" + } + return *i.RepositoryHooks +} + +// GetRepositoryPreReceiveHooks returns the RepositoryPreReceiveHooks field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetRepositoryPreReceiveHooks() string { + if i == nil || i.RepositoryPreReceiveHooks == nil { + return "" + } + return *i.RepositoryPreReceiveHooks +} + +// GetRepositoryProjects returns the RepositoryProjects field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetRepositoryProjects() string { + if i == nil || i.RepositoryProjects == nil { + return "" + } + return *i.RepositoryProjects +} + +// GetSecrets returns the Secrets field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetSecrets() string { + if i == nil || i.Secrets == nil { + return "" + } + return *i.Secrets +} + +// GetSecretScanningAlerts returns the SecretScanningAlerts field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetSecretScanningAlerts() string { + if i == nil || i.SecretScanningAlerts == nil { + return "" + } + return *i.SecretScanningAlerts +} + +// GetSecurityEvents returns the SecurityEvents field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetSecurityEvents() string { + if i == nil || i.SecurityEvents == nil { + return "" + } + return *i.SecurityEvents +} + +// GetSingleFile returns the SingleFile field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetSingleFile() string { + if i == nil || i.SingleFile == nil { + return "" + } + return *i.SingleFile +} + +// GetStarring returns the Starring field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetStarring() string { + if i == nil || i.Starring == nil { + return "" + } + return *i.Starring +} + +// GetStatuses returns the Statuses field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetStatuses() string { + if i == nil || i.Statuses == nil { + return "" + } + return *i.Statuses +} + +// GetTeamDiscussions returns the TeamDiscussions field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetTeamDiscussions() string { + if i == nil || i.TeamDiscussions == nil { + return "" + } + return *i.TeamDiscussions +} + +// GetUserEvents returns the UserEvents field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetUserEvents() string { + if i == nil || i.UserEvents == nil { + return "" + } + return *i.UserEvents +} + +// GetVulnerabilityAlerts returns the VulnerabilityAlerts field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetVulnerabilityAlerts() string { + if i == nil || i.VulnerabilityAlerts == nil { + return "" + } + return *i.VulnerabilityAlerts +} + +// GetWatching returns the Watching field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetWatching() string { + if i == nil || i.Watching == nil { + return "" + } + return *i.Watching +} + +// GetWorkflows returns the Workflows field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetWorkflows() string { + if i == nil || i.Workflows == nil { + return "" + } + return *i.Workflows +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (i *InstallationRepositoriesEvent) GetAction() string { + if i == nil || i.Action == nil { + return "" + } + return *i.Action +} + +// GetInstallation returns the Installation field. +func (i *InstallationRepositoriesEvent) GetInstallation() *Installation { + if i == nil { + return nil + } + return i.Installation +} + +// GetOrg returns the Org field. +func (i *InstallationRepositoriesEvent) GetOrg() *Organization { + if i == nil { + return nil + } + return i.Org +} + +// GetRepositorySelection returns the RepositorySelection field if it's non-nil, zero value otherwise. +func (i *InstallationRepositoriesEvent) GetRepositorySelection() string { + if i == nil || i.RepositorySelection == nil { + return "" + } + return *i.RepositorySelection +} + +// GetSender returns the Sender field. +func (i *InstallationRepositoriesEvent) GetSender() *User { + if i == nil { + return nil + } + return i.Sender +} + +// GetAccount returns the Account field. +func (i *InstallationRequest) GetAccount() *User { + if i == nil { + return nil + } + return i.Account +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *InstallationRequest) GetCreatedAt() Timestamp { + if i == nil || i.CreatedAt == nil { + return Timestamp{} + } + return *i.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *InstallationRequest) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (i *InstallationRequest) GetNodeID() string { + if i == nil || i.NodeID == nil { + return "" + } + return *i.NodeID +} + +// GetRequester returns the Requester field. +func (i *InstallationRequest) GetRequester() *User { + if i == nil { + return nil + } + return i.Requester +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (i *InstallationSlugChange) GetFrom() string { + if i == nil || i.From == nil { + return "" + } + return *i.From +} + +// GetAccount returns the Account field. +func (i *InstallationTargetEvent) GetAccount() *User { + if i == nil { + return nil + } + return i.Account +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (i *InstallationTargetEvent) GetAction() string { + if i == nil || i.Action == nil { + return "" + } + return *i.Action +} + +// GetChanges returns the Changes field. +func (i *InstallationTargetEvent) GetChanges() *InstallationChanges { + if i == nil { + return nil + } + return i.Changes +} + +// GetEnterprise returns the Enterprise field. +func (i *InstallationTargetEvent) GetEnterprise() *Enterprise { + if i == nil { + return nil + } + return i.Enterprise +} + +// GetInstallation returns the Installation field. +func (i *InstallationTargetEvent) GetInstallation() *Installation { + if i == nil { + return nil + } + return i.Installation +} + +// GetOrganization returns the Organization field. +func (i *InstallationTargetEvent) GetOrganization() *Organization { + if i == nil { + return nil + } + return i.Organization +} + +// GetRepository returns the Repository field. +func (i *InstallationTargetEvent) GetRepository() *Repository { + if i == nil { + return nil + } + return i.Repository +} + +// GetSender returns the Sender field. +func (i *InstallationTargetEvent) GetSender() *User { + if i == nil { + return nil + } + return i.Sender +} + +// GetTargetType returns the TargetType field if it's non-nil, zero value otherwise. +func (i *InstallationTargetEvent) GetTargetType() string { + if i == nil || i.TargetType == nil { + return "" + } + return *i.TargetType +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (i *InstallationToken) GetExpiresAt() Timestamp { + if i == nil || i.ExpiresAt == nil { + return Timestamp{} + } + return *i.ExpiresAt +} + +// GetPermissions returns the Permissions field. +func (i *InstallationToken) GetPermissions() *InstallationPermissions { + if i == nil { + return nil + } + return i.Permissions +} + +// GetToken returns the Token field if it's non-nil, zero value otherwise. +func (i *InstallationToken) GetToken() string { + if i == nil || i.Token == nil { + return "" + } + return *i.Token +} + +// GetPermissions returns the Permissions field. +func (i *InstallationTokenListRepoOptions) GetPermissions() *InstallationPermissions { + if i == nil { + return nil + } + return i.Permissions +} + +// GetPermissions returns the Permissions field. +func (i *InstallationTokenOptions) GetPermissions() *InstallationPermissions { + if i == nil { + return nil + } + return i.Permissions +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (i *InteractionRestriction) GetExpiresAt() Timestamp { + if i == nil || i.ExpiresAt == nil { + return Timestamp{} + } + return *i.ExpiresAt +} + +// GetLimit returns the Limit field if it's non-nil, zero value otherwise. +func (i *InteractionRestriction) GetLimit() string { + if i == nil || i.Limit == nil { + return "" + } + return *i.Limit +} + +// GetOrigin returns the Origin field if it's non-nil, zero value otherwise. +func (i *InteractionRestriction) GetOrigin() string { + if i == nil || i.Origin == nil { + return "" + } + return *i.Origin +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *Invitation) GetCreatedAt() Timestamp { + if i == nil || i.CreatedAt == nil { + return Timestamp{} + } + return *i.CreatedAt +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (i *Invitation) GetEmail() string { + if i == nil || i.Email == nil { + return "" + } + return *i.Email +} + +// GetFailedAt returns the FailedAt field if it's non-nil, zero value otherwise. +func (i *Invitation) GetFailedAt() Timestamp { + if i == nil || i.FailedAt == nil { + return Timestamp{} + } + return *i.FailedAt +} + +// GetFailedReason returns the FailedReason field if it's non-nil, zero value otherwise. +func (i *Invitation) GetFailedReason() string { + if i == nil || i.FailedReason == nil { + return "" + } + return *i.FailedReason +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *Invitation) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetInvitationTeamURL returns the InvitationTeamURL field if it's non-nil, zero value otherwise. +func (i *Invitation) GetInvitationTeamURL() string { + if i == nil || i.InvitationTeamURL == nil { + return "" + } + return *i.InvitationTeamURL +} + +// GetInviter returns the Inviter field. +func (i *Invitation) GetInviter() *User { + if i == nil { + return nil + } + return i.Inviter +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (i *Invitation) GetLogin() string { + if i == nil || i.Login == nil { + return "" + } + return *i.Login +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (i *Invitation) GetNodeID() string { + if i == nil || i.NodeID == nil { + return "" + } + return *i.NodeID +} + +// GetRole returns the Role field if it's non-nil, zero value otherwise. +func (i *Invitation) GetRole() string { + if i == nil || i.Role == nil { + return "" + } + return *i.Role +} + +// GetTeamCount returns the TeamCount field if it's non-nil, zero value otherwise. +func (i *Invitation) GetTeamCount() int { + if i == nil || i.TeamCount == nil { + return 0 + } + return *i.TeamCount +} + +// GetActiveLockReason returns the ActiveLockReason field if it's non-nil, zero value otherwise. +func (i *Issue) GetActiveLockReason() string { + if i == nil || i.ActiveLockReason == nil { + return "" + } + return *i.ActiveLockReason +} + +// GetAssignee returns the Assignee field. +func (i *Issue) GetAssignee() *User { + if i == nil { + return nil + } + return i.Assignee +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (i *Issue) GetAuthorAssociation() string { + if i == nil || i.AuthorAssociation == nil { + return "" + } + return *i.AuthorAssociation +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (i *Issue) GetBody() string { + if i == nil || i.Body == nil { + return "" + } + return *i.Body +} + +// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. +func (i *Issue) GetClosedAt() Timestamp { + if i == nil || i.ClosedAt == nil { + return Timestamp{} + } + return *i.ClosedAt +} + +// GetClosedBy returns the ClosedBy field. +func (i *Issue) GetClosedBy() *User { + if i == nil { + return nil + } + return i.ClosedBy +} + +// GetComments returns the Comments field if it's non-nil, zero value otherwise. +func (i *Issue) GetComments() int { + if i == nil || i.Comments == nil { + return 0 + } + return *i.Comments +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (i *Issue) GetCommentsURL() string { + if i == nil || i.CommentsURL == nil { + return "" + } + return *i.CommentsURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *Issue) GetCreatedAt() Timestamp { + if i == nil || i.CreatedAt == nil { + return Timestamp{} + } + return *i.CreatedAt +} + +// GetDraft returns the Draft field if it's non-nil, zero value otherwise. +func (i *Issue) GetDraft() bool { + if i == nil || i.Draft == nil { + return false + } + return *i.Draft +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (i *Issue) GetEventsURL() string { + if i == nil || i.EventsURL == nil { + return "" + } + return *i.EventsURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (i *Issue) GetHTMLURL() string { + if i == nil || i.HTMLURL == nil { + return "" + } + return *i.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *Issue) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetLabelsURL returns the LabelsURL field if it's non-nil, zero value otherwise. +func (i *Issue) GetLabelsURL() string { + if i == nil || i.LabelsURL == nil { + return "" + } + return *i.LabelsURL +} + +// GetLocked returns the Locked field if it's non-nil, zero value otherwise. +func (i *Issue) GetLocked() bool { + if i == nil || i.Locked == nil { + return false + } + return *i.Locked +} + +// GetMilestone returns the Milestone field. +func (i *Issue) GetMilestone() *Milestone { + if i == nil { + return nil + } + return i.Milestone +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (i *Issue) GetNodeID() string { + if i == nil || i.NodeID == nil { + return "" + } + return *i.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (i *Issue) GetNumber() int { + if i == nil || i.Number == nil { + return 0 + } + return *i.Number +} + +// GetPullRequestLinks returns the PullRequestLinks field. +func (i *Issue) GetPullRequestLinks() *PullRequestLinks { + if i == nil { + return nil + } + return i.PullRequestLinks +} + +// GetReactions returns the Reactions field. +func (i *Issue) GetReactions() *Reactions { + if i == nil { + return nil + } + return i.Reactions +} + +// GetRepository returns the Repository field. +func (i *Issue) GetRepository() *Repository { + if i == nil { + return nil + } + return i.Repository +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (i *Issue) GetRepositoryURL() string { + if i == nil || i.RepositoryURL == nil { + return "" + } + return *i.RepositoryURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (i *Issue) GetState() string { + if i == nil || i.State == nil { + return "" + } + return *i.State +} + +// GetStateReason returns the StateReason field if it's non-nil, zero value otherwise. +func (i *Issue) GetStateReason() string { + if i == nil || i.StateReason == nil { + return "" + } + return *i.StateReason +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (i *Issue) GetTitle() string { + if i == nil || i.Title == nil { + return "" + } + return *i.Title +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (i *Issue) GetUpdatedAt() Timestamp { + if i == nil || i.UpdatedAt == nil { + return Timestamp{} + } + return *i.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (i *Issue) GetURL() string { + if i == nil || i.URL == nil { + return "" + } + return *i.URL +} + +// GetUser returns the User field. +func (i *Issue) GetUser() *User { + if i == nil { + return nil + } + return i.User +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetAuthorAssociation() string { + if i == nil || i.AuthorAssociation == nil { + return "" + } + return *i.AuthorAssociation +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetBody() string { + if i == nil || i.Body == nil { + return "" + } + return *i.Body +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetCreatedAt() Timestamp { + if i == nil || i.CreatedAt == nil { + return Timestamp{} + } + return *i.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetHTMLURL() string { + if i == nil || i.HTMLURL == nil { + return "" + } + return *i.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetIssueURL returns the IssueURL field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetIssueURL() string { + if i == nil || i.IssueURL == nil { + return "" + } + return *i.IssueURL +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetNodeID() string { + if i == nil || i.NodeID == nil { + return "" + } + return *i.NodeID +} + +// GetReactions returns the Reactions field. +func (i *IssueComment) GetReactions() *Reactions { + if i == nil { + return nil + } + return i.Reactions +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetUpdatedAt() Timestamp { + if i == nil || i.UpdatedAt == nil { + return Timestamp{} + } + return *i.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetURL() string { + if i == nil || i.URL == nil { + return "" + } + return *i.URL +} + +// GetUser returns the User field. +func (i *IssueComment) GetUser() *User { + if i == nil { + return nil + } + return i.User +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (i *IssueCommentEvent) GetAction() string { + if i == nil || i.Action == nil { + return "" + } + return *i.Action +} + +// GetChanges returns the Changes field. +func (i *IssueCommentEvent) GetChanges() *EditChange { + if i == nil { + return nil + } + return i.Changes +} + +// GetComment returns the Comment field. +func (i *IssueCommentEvent) GetComment() *IssueComment { + if i == nil { + return nil + } + return i.Comment +} + +// GetInstallation returns the Installation field. +func (i *IssueCommentEvent) GetInstallation() *Installation { + if i == nil { + return nil + } + return i.Installation +} + +// GetIssue returns the Issue field. +func (i *IssueCommentEvent) GetIssue() *Issue { + if i == nil { + return nil + } + return i.Issue +} + +// GetOrganization returns the Organization field. +func (i *IssueCommentEvent) GetOrganization() *Organization { + if i == nil { + return nil + } + return i.Organization +} + +// GetRepo returns the Repo field. +func (i *IssueCommentEvent) GetRepo() *Repository { + if i == nil { + return nil + } + return i.Repo +} + +// GetSender returns the Sender field. +func (i *IssueCommentEvent) GetSender() *User { + if i == nil { + return nil + } + return i.Sender +} + +// GetActor returns the Actor field. +func (i *IssueEvent) GetActor() *User { + if i == nil { + return nil + } + return i.Actor +} + +// GetAssignee returns the Assignee field. +func (i *IssueEvent) GetAssignee() *User { + if i == nil { + return nil + } + return i.Assignee +} + +// GetAssigner returns the Assigner field. +func (i *IssueEvent) GetAssigner() *User { + if i == nil { + return nil + } + return i.Assigner +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetCommitID() string { + if i == nil || i.CommitID == nil { + return "" + } + return *i.CommitID +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetCreatedAt() Timestamp { + if i == nil || i.CreatedAt == nil { + return Timestamp{} + } + return *i.CreatedAt +} + +// GetDismissedReview returns the DismissedReview field. +func (i *IssueEvent) GetDismissedReview() *DismissedReview { + if i == nil { + return nil + } + return i.DismissedReview +} + +// GetEvent returns the Event field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetEvent() string { + if i == nil || i.Event == nil { + return "" + } + return *i.Event +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetIssue returns the Issue field. +func (i *IssueEvent) GetIssue() *Issue { + if i == nil { + return nil + } + return i.Issue +} + +// GetLabel returns the Label field. +func (i *IssueEvent) GetLabel() *Label { + if i == nil { + return nil + } + return i.Label +} + +// GetLockReason returns the LockReason field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetLockReason() string { + if i == nil || i.LockReason == nil { + return "" + } + return *i.LockReason +} + +// GetMilestone returns the Milestone field. +func (i *IssueEvent) GetMilestone() *Milestone { + if i == nil { + return nil + } + return i.Milestone +} + +// GetPerformedViaGithubApp returns the PerformedViaGithubApp field. +func (i *IssueEvent) GetPerformedViaGithubApp() *App { + if i == nil { + return nil + } + return i.PerformedViaGithubApp +} + +// GetRename returns the Rename field. +func (i *IssueEvent) GetRename() *Rename { + if i == nil { + return nil + } + return i.Rename +} + +// GetRepository returns the Repository field. +func (i *IssueEvent) GetRepository() *Repository { + if i == nil { + return nil + } + return i.Repository +} + +// GetRequestedReviewer returns the RequestedReviewer field. +func (i *IssueEvent) GetRequestedReviewer() *User { + if i == nil { + return nil + } + return i.RequestedReviewer +} + +// GetRequestedTeam returns the RequestedTeam field. +func (i *IssueEvent) GetRequestedTeam() *Team { + if i == nil { + return nil + } + return i.RequestedTeam +} + +// GetReviewRequester returns the ReviewRequester field. +func (i *IssueEvent) GetReviewRequester() *User { + if i == nil { + return nil + } + return i.ReviewRequester +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetURL() string { + if i == nil || i.URL == nil { + return "" + } + return *i.URL +} + +// GetAssignee returns the Assignee field if it's non-nil, zero value otherwise. +func (i *IssueImport) GetAssignee() string { + if i == nil || i.Assignee == nil { + return "" + } + return *i.Assignee +} + +// GetClosed returns the Closed field if it's non-nil, zero value otherwise. +func (i *IssueImport) GetClosed() bool { + if i == nil || i.Closed == nil { + return false + } + return *i.Closed +} + +// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. +func (i *IssueImport) GetClosedAt() Timestamp { + if i == nil || i.ClosedAt == nil { + return Timestamp{} + } + return *i.ClosedAt +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *IssueImport) GetCreatedAt() Timestamp { + if i == nil || i.CreatedAt == nil { + return Timestamp{} + } + return *i.CreatedAt +} + +// GetMilestone returns the Milestone field if it's non-nil, zero value otherwise. +func (i *IssueImport) GetMilestone() int { + if i == nil || i.Milestone == nil { + return 0 + } + return *i.Milestone +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (i *IssueImport) GetUpdatedAt() Timestamp { + if i == nil || i.UpdatedAt == nil { + return Timestamp{} + } + return *i.UpdatedAt +} + +// GetCode returns the Code field if it's non-nil, zero value otherwise. +func (i *IssueImportError) GetCode() string { + if i == nil || i.Code == nil { + return "" + } + return *i.Code +} + +// GetField returns the Field field if it's non-nil, zero value otherwise. +func (i *IssueImportError) GetField() string { + if i == nil || i.Field == nil { + return "" + } + return *i.Field +} + +// GetLocation returns the Location field if it's non-nil, zero value otherwise. +func (i *IssueImportError) GetLocation() string { + if i == nil || i.Location == nil { + return "" + } + return *i.Location +} + +// GetResource returns the Resource field if it's non-nil, zero value otherwise. +func (i *IssueImportError) GetResource() string { + if i == nil || i.Resource == nil { + return "" + } + return *i.Resource +} + +// GetValue returns the Value field if it's non-nil, zero value otherwise. +func (i *IssueImportError) GetValue() string { + if i == nil || i.Value == nil { + return "" + } + return *i.Value +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetCreatedAt() Timestamp { + if i == nil || i.CreatedAt == nil { + return Timestamp{} + } + return *i.CreatedAt +} + +// GetDocumentationURL returns the DocumentationURL field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetDocumentationURL() string { + if i == nil || i.DocumentationURL == nil { + return "" + } + return *i.DocumentationURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetID() int { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetImportIssuesURL returns the ImportIssuesURL field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetImportIssuesURL() string { + if i == nil || i.ImportIssuesURL == nil { + return "" + } + return *i.ImportIssuesURL +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetMessage() string { + if i == nil || i.Message == nil { + return "" + } + return *i.Message +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetRepositoryURL() string { + if i == nil || i.RepositoryURL == nil { + return "" + } + return *i.RepositoryURL +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetStatus() string { + if i == nil || i.Status == nil { + return "" + } + return *i.Status +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetUpdatedAt() Timestamp { + if i == nil || i.UpdatedAt == nil { + return Timestamp{} + } + return *i.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetURL() string { + if i == nil || i.URL == nil { + return "" + } + return *i.URL +} + +// GetDirection returns the Direction field if it's non-nil, zero value otherwise. +func (i *IssueListCommentsOptions) GetDirection() string { + if i == nil || i.Direction == nil { + return "" + } + return *i.Direction +} + +// GetSince returns the Since field if it's non-nil, zero value otherwise. +func (i *IssueListCommentsOptions) GetSince() time.Time { + if i == nil || i.Since == nil { + return time.Time{} + } + return *i.Since +} + +// GetSort returns the Sort field if it's non-nil, zero value otherwise. +func (i *IssueListCommentsOptions) GetSort() string { + if i == nil || i.Sort == nil { + return "" + } + return *i.Sort +} + +// GetAssignee returns the Assignee field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetAssignee() string { + if i == nil || i.Assignee == nil { + return "" + } + return *i.Assignee +} + +// GetAssignees returns the Assignees field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetAssignees() []string { + if i == nil || i.Assignees == nil { + return nil + } + return *i.Assignees +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetBody() string { + if i == nil || i.Body == nil { + return "" + } + return *i.Body +} + +// GetLabels returns the Labels field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetLabels() []string { + if i == nil || i.Labels == nil { + return nil + } + return *i.Labels +} + +// GetMilestone returns the Milestone field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetMilestone() int { + if i == nil || i.Milestone == nil { + return 0 + } + return *i.Milestone +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetState() string { + if i == nil || i.State == nil { + return "" + } + return *i.State +} + +// GetStateReason returns the StateReason field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetStateReason() string { + if i == nil || i.StateReason == nil { + return "" + } + return *i.StateReason +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetTitle() string { + if i == nil || i.Title == nil { + return "" + } + return *i.Title +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (i *IssuesEvent) GetAction() string { + if i == nil || i.Action == nil { + return "" + } + return *i.Action +} + +// GetAssignee returns the Assignee field. +func (i *IssuesEvent) GetAssignee() *User { + if i == nil { + return nil + } + return i.Assignee +} + +// GetChanges returns the Changes field. +func (i *IssuesEvent) GetChanges() *EditChange { + if i == nil { + return nil + } + return i.Changes +} + +// GetInstallation returns the Installation field. +func (i *IssuesEvent) GetInstallation() *Installation { + if i == nil { + return nil + } + return i.Installation +} + +// GetIssue returns the Issue field. +func (i *IssuesEvent) GetIssue() *Issue { + if i == nil { + return nil + } + return i.Issue +} + +// GetLabel returns the Label field. +func (i *IssuesEvent) GetLabel() *Label { + if i == nil { + return nil + } + return i.Label +} + +// GetMilestone returns the Milestone field. +func (i *IssuesEvent) GetMilestone() *Milestone { + if i == nil { + return nil + } + return i.Milestone +} + +// GetOrg returns the Org field. +func (i *IssuesEvent) GetOrg() *Organization { + if i == nil { + return nil + } + return i.Org +} + +// GetRepo returns the Repo field. +func (i *IssuesEvent) GetRepo() *Repository { + if i == nil { + return nil + } + return i.Repo +} + +// GetSender returns the Sender field. +func (i *IssuesEvent) GetSender() *User { + if i == nil { + return nil + } + return i.Sender +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (i *IssuesSearchResult) GetIncompleteResults() bool { + if i == nil || i.IncompleteResults == nil { + return false + } + return *i.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (i *IssuesSearchResult) GetTotal() int { + if i == nil || i.Total == nil { + return 0 + } + return *i.Total +} + +// GetClosedIssues returns the ClosedIssues field if it's non-nil, zero value otherwise. +func (i *IssueStats) GetClosedIssues() int { + if i == nil || i.ClosedIssues == nil { + return 0 + } + return *i.ClosedIssues +} + +// GetOpenIssues returns the OpenIssues field if it's non-nil, zero value otherwise. +func (i *IssueStats) GetOpenIssues() int { + if i == nil || i.OpenIssues == nil { + return 0 + } + return *i.OpenIssues +} + +// GetTotalIssues returns the TotalIssues field if it's non-nil, zero value otherwise. +func (i *IssueStats) GetTotalIssues() int { + if i == nil || i.TotalIssues == nil { + return 0 + } + return *i.TotalIssues +} + +// GetEncodedJITConfig returns the EncodedJITConfig field if it's non-nil, zero value otherwise. +func (j *JITRunnerConfig) GetEncodedJITConfig() string { + if j == nil || j.EncodedJITConfig == nil { + return "" + } + return *j.EncodedJITConfig +} + +// GetRunner returns the Runner field. +func (j *JITRunnerConfig) GetRunner() *Runner { + if j == nil { + return nil + } + return j.Runner +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (j *Jobs) GetTotalCount() int { + if j == nil || j.TotalCount == nil { + return 0 + } + return *j.TotalCount +} + +// GetAddedBy returns the AddedBy field if it's non-nil, zero value otherwise. +func (k *Key) GetAddedBy() string { + if k == nil || k.AddedBy == nil { + return "" + } + return *k.AddedBy +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (k *Key) GetCreatedAt() Timestamp { + if k == nil || k.CreatedAt == nil { + return Timestamp{} + } + return *k.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (k *Key) GetID() int64 { + if k == nil || k.ID == nil { + return 0 + } + return *k.ID +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (k *Key) GetKey() string { + if k == nil || k.Key == nil { + return "" + } + return *k.Key +} + +// GetLastUsed returns the LastUsed field if it's non-nil, zero value otherwise. +func (k *Key) GetLastUsed() Timestamp { + if k == nil || k.LastUsed == nil { + return Timestamp{} + } + return *k.LastUsed +} + +// GetReadOnly returns the ReadOnly field if it's non-nil, zero value otherwise. +func (k *Key) GetReadOnly() bool { + if k == nil || k.ReadOnly == nil { + return false + } + return *k.ReadOnly +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (k *Key) GetTitle() string { + if k == nil || k.Title == nil { + return "" + } + return *k.Title +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (k *Key) GetURL() string { + if k == nil || k.URL == nil { + return "" + } + return *k.URL +} + +// GetVerified returns the Verified field if it's non-nil, zero value otherwise. +func (k *Key) GetVerified() bool { + if k == nil || k.Verified == nil { + return false + } + return *k.Verified +} + +// GetColor returns the Color field if it's non-nil, zero value otherwise. +func (l *Label) GetColor() string { + if l == nil || l.Color == nil { + return "" + } + return *l.Color +} + +// GetDefault returns the Default field if it's non-nil, zero value otherwise. +func (l *Label) GetDefault() bool { + if l == nil || l.Default == nil { + return false + } + return *l.Default +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (l *Label) GetDescription() string { + if l == nil || l.Description == nil { + return "" + } + return *l.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (l *Label) GetID() int64 { + if l == nil || l.ID == nil { + return 0 + } + return *l.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (l *Label) GetName() string { + if l == nil || l.Name == nil { + return "" + } + return *l.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (l *Label) GetNodeID() string { + if l == nil || l.NodeID == nil { + return "" + } + return *l.NodeID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (l *Label) GetURL() string { + if l == nil || l.URL == nil { + return "" + } + return *l.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (l *LabelEvent) GetAction() string { + if l == nil || l.Action == nil { + return "" + } + return *l.Action +} + +// GetChanges returns the Changes field. +func (l *LabelEvent) GetChanges() *EditChange { + if l == nil { + return nil + } + return l.Changes +} + +// GetInstallation returns the Installation field. +func (l *LabelEvent) GetInstallation() *Installation { + if l == nil { + return nil + } + return l.Installation +} + +// GetLabel returns the Label field. +func (l *LabelEvent) GetLabel() *Label { + if l == nil { + return nil + } + return l.Label +} + +// GetOrg returns the Org field. +func (l *LabelEvent) GetOrg() *Organization { + if l == nil { + return nil + } + return l.Org +} + +// GetRepo returns the Repo field. +func (l *LabelEvent) GetRepo() *Repository { + if l == nil { + return nil + } + return l.Repo +} + +// GetSender returns the Sender field. +func (l *LabelEvent) GetSender() *User { + if l == nil { + return nil + } + return l.Sender +} + +// GetColor returns the Color field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetColor() string { + if l == nil || l.Color == nil { + return "" + } + return *l.Color +} + +// GetDefault returns the Default field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetDefault() bool { + if l == nil || l.Default == nil { + return false + } + return *l.Default +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetDescription() string { + if l == nil || l.Description == nil { + return "" + } + return *l.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetID() int64 { + if l == nil || l.ID == nil { + return 0 + } + return *l.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetName() string { + if l == nil || l.Name == nil { + return "" + } + return *l.Name +} + +// GetScore returns the Score field. +func (l *LabelResult) GetScore() *float64 { + if l == nil { + return nil + } + return l.Score +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetURL() string { + if l == nil || l.URL == nil { + return "" + } + return *l.URL +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (l *LabelsSearchResult) GetIncompleteResults() bool { + if l == nil || l.IncompleteResults == nil { + return false + } + return *l.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (l *LabelsSearchResult) GetTotal() int { + if l == nil || l.Total == nil { + return 0 + } + return *l.Total +} + +// GetOID returns the OID field if it's non-nil, zero value otherwise. +func (l *LargeFile) GetOID() string { + if l == nil || l.OID == nil { + return "" + } + return *l.OID +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (l *LargeFile) GetPath() string { + if l == nil || l.Path == nil { + return "" + } + return *l.Path +} + +// GetRefName returns the RefName field if it's non-nil, zero value otherwise. +func (l *LargeFile) GetRefName() string { + if l == nil || l.RefName == nil { + return "" + } + return *l.RefName +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (l *LargeFile) GetSize() int { + if l == nil || l.Size == nil { + return 0 + } + return *l.Size +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (l *License) GetBody() string { + if l == nil || l.Body == nil { + return "" + } + return *l.Body +} + +// GetConditions returns the Conditions field if it's non-nil, zero value otherwise. +func (l *License) GetConditions() []string { + if l == nil || l.Conditions == nil { + return nil + } + return *l.Conditions +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (l *License) GetDescription() string { + if l == nil || l.Description == nil { + return "" + } + return *l.Description +} + +// GetFeatured returns the Featured field if it's non-nil, zero value otherwise. +func (l *License) GetFeatured() bool { + if l == nil || l.Featured == nil { + return false + } + return *l.Featured +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (l *License) GetHTMLURL() string { + if l == nil || l.HTMLURL == nil { + return "" + } + return *l.HTMLURL +} + +// GetImplementation returns the Implementation field if it's non-nil, zero value otherwise. +func (l *License) GetImplementation() string { + if l == nil || l.Implementation == nil { + return "" + } + return *l.Implementation +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (l *License) GetKey() string { + if l == nil || l.Key == nil { + return "" + } + return *l.Key +} + +// GetLimitations returns the Limitations field if it's non-nil, zero value otherwise. +func (l *License) GetLimitations() []string { + if l == nil || l.Limitations == nil { + return nil + } + return *l.Limitations +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (l *License) GetName() string { + if l == nil || l.Name == nil { + return "" + } + return *l.Name +} + +// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise. +func (l *License) GetPermissions() []string { + if l == nil || l.Permissions == nil { + return nil + } + return *l.Permissions +} + +// GetSPDXID returns the SPDXID field if it's non-nil, zero value otherwise. +func (l *License) GetSPDXID() string { + if l == nil || l.SPDXID == nil { + return "" + } + return *l.SPDXID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (l *License) GetURL() string { + if l == nil || l.URL == nil { + return "" + } + return *l.URL +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (l *LinearHistoryRequirementEnforcementLevelChanges) GetFrom() string { + if l == nil || l.From == nil { + return "" + } + return *l.From +} + +// GetDirection returns the Direction field if it's non-nil, zero value otherwise. +func (l *ListAlertsOptions) GetDirection() string { + if l == nil || l.Direction == nil { + return "" + } + return *l.Direction +} + +// GetEcosystem returns the Ecosystem field if it's non-nil, zero value otherwise. +func (l *ListAlertsOptions) GetEcosystem() string { + if l == nil || l.Ecosystem == nil { + return "" + } + return *l.Ecosystem +} + +// GetPackage returns the Package field if it's non-nil, zero value otherwise. +func (l *ListAlertsOptions) GetPackage() string { + if l == nil || l.Package == nil { + return "" + } + return *l.Package +} + +// GetScope returns the Scope field if it's non-nil, zero value otherwise. +func (l *ListAlertsOptions) GetScope() string { + if l == nil || l.Scope == nil { + return "" + } + return *l.Scope +} + +// GetSeverity returns the Severity field if it's non-nil, zero value otherwise. +func (l *ListAlertsOptions) GetSeverity() string { + if l == nil || l.Severity == nil { + return "" + } + return *l.Severity +} + +// GetSort returns the Sort field if it's non-nil, zero value otherwise. +func (l *ListAlertsOptions) GetSort() string { + if l == nil || l.Sort == nil { + return "" + } + return *l.Sort +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (l *ListAlertsOptions) GetState() string { + if l == nil || l.State == nil { + return "" + } + return *l.State +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (l *ListArtifactsOptions) GetName() string { + if l == nil || l.Name == nil { + return "" + } + return *l.Name +} + +// GetAppID returns the AppID field if it's non-nil, zero value otherwise. +func (l *ListCheckRunsOptions) GetAppID() int64 { + if l == nil || l.AppID == nil { + return 0 + } + return *l.AppID +} + +// GetCheckName returns the CheckName field if it's non-nil, zero value otherwise. +func (l *ListCheckRunsOptions) GetCheckName() string { + if l == nil || l.CheckName == nil { + return "" + } + return *l.CheckName +} + +// GetFilter returns the Filter field if it's non-nil, zero value otherwise. +func (l *ListCheckRunsOptions) GetFilter() string { + if l == nil || l.Filter == nil { + return "" + } + return *l.Filter +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (l *ListCheckRunsOptions) GetStatus() string { + if l == nil || l.Status == nil { + return "" + } + return *l.Status +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (l *ListCheckRunsResults) GetTotal() int { + if l == nil || l.Total == nil { + return 0 + } + return *l.Total +} + +// GetAppID returns the AppID field if it's non-nil, zero value otherwise. +func (l *ListCheckSuiteOptions) GetAppID() int { + if l == nil || l.AppID == nil { + return 0 + } + return *l.AppID +} + +// GetCheckName returns the CheckName field if it's non-nil, zero value otherwise. +func (l *ListCheckSuiteOptions) GetCheckName() string { + if l == nil || l.CheckName == nil { + return "" + } + return *l.CheckName +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (l *ListCheckSuiteResults) GetTotal() int { + if l == nil || l.Total == nil { + return 0 + } + return *l.Total +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (l *ListCodespaces) GetTotalCount() int { + if l == nil || l.TotalCount == nil { + return 0 + } + return *l.TotalCount +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (l *ListCustomDeploymentRuleIntegrationsResponse) GetTotalCount() int { + if l == nil || l.TotalCount == nil { + return 0 + } + return *l.TotalCount +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (l *ListDeploymentProtectionRuleResponse) GetTotalCount() int { + if l == nil || l.TotalCount == nil { + return 0 + } + return *l.TotalCount +} + +// GetDisplayName returns the DisplayName field if it's non-nil, zero value otherwise. +func (l *ListExternalGroupsOptions) GetDisplayName() string { + if l == nil || l.DisplayName == nil { + return "" + } + return *l.DisplayName +} + +// GetAffects returns the Affects field if it's non-nil, zero value otherwise. +func (l *ListGlobalSecurityAdvisoriesOptions) GetAffects() string { + if l == nil || l.Affects == nil { + return "" + } + return *l.Affects +} + +// GetCVEID returns the CVEID field if it's non-nil, zero value otherwise. +func (l *ListGlobalSecurityAdvisoriesOptions) GetCVEID() string { + if l == nil || l.CVEID == nil { + return "" + } + return *l.CVEID +} + +// GetEcosystem returns the Ecosystem field if it's non-nil, zero value otherwise. +func (l *ListGlobalSecurityAdvisoriesOptions) GetEcosystem() string { + if l == nil || l.Ecosystem == nil { + return "" + } + return *l.Ecosystem +} + +// GetGHSAID returns the GHSAID field if it's non-nil, zero value otherwise. +func (l *ListGlobalSecurityAdvisoriesOptions) GetGHSAID() string { + if l == nil || l.GHSAID == nil { + return "" + } + return *l.GHSAID +} + +// GetIsWithdrawn returns the IsWithdrawn field if it's non-nil, zero value otherwise. +func (l *ListGlobalSecurityAdvisoriesOptions) GetIsWithdrawn() bool { + if l == nil || l.IsWithdrawn == nil { + return false + } + return *l.IsWithdrawn +} + +// GetModified returns the Modified field if it's non-nil, zero value otherwise. +func (l *ListGlobalSecurityAdvisoriesOptions) GetModified() string { + if l == nil || l.Modified == nil { + return "" + } + return *l.Modified +} + +// GetPublished returns the Published field if it's non-nil, zero value otherwise. +func (l *ListGlobalSecurityAdvisoriesOptions) GetPublished() string { + if l == nil || l.Published == nil { + return "" + } + return *l.Published +} + +// GetSeverity returns the Severity field if it's non-nil, zero value otherwise. +func (l *ListGlobalSecurityAdvisoriesOptions) GetSeverity() string { + if l == nil || l.Severity == nil { + return "" + } + return *l.Severity +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (l *ListGlobalSecurityAdvisoriesOptions) GetType() string { + if l == nil || l.Type == nil { + return "" + } + return *l.Type +} + +// GetUpdated returns the Updated field if it's non-nil, zero value otherwise. +func (l *ListGlobalSecurityAdvisoriesOptions) GetUpdated() string { + if l == nil || l.Updated == nil { + return "" + } + return *l.Updated +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (l *ListOrganizations) GetTotalCount() int { + if l == nil || l.TotalCount == nil { + return 0 + } + return *l.TotalCount +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (l *ListRepositories) GetTotalCount() int { + if l == nil || l.TotalCount == nil { + return 0 + } + return *l.TotalCount +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (l *ListRunnersOptions) GetName() string { + if l == nil || l.Name == nil { + return "" + } + return *l.Name +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (l *ListSCIMProvisionedIdentitiesOptions) GetCount() int { + if l == nil || l.Count == nil { + return 0 + } + return *l.Count +} + +// GetFilter returns the Filter field if it's non-nil, zero value otherwise. +func (l *ListSCIMProvisionedIdentitiesOptions) GetFilter() string { + if l == nil || l.Filter == nil { + return "" + } + return *l.Filter +} + +// GetStartIndex returns the StartIndex field if it's non-nil, zero value otherwise. +func (l *ListSCIMProvisionedIdentitiesOptions) GetStartIndex() int { + if l == nil || l.StartIndex == nil { + return 0 + } + return *l.StartIndex +} + +// GetEndColumn returns the EndColumn field if it's non-nil, zero value otherwise. +func (l *Location) GetEndColumn() int { + if l == nil || l.EndColumn == nil { + return 0 + } + return *l.EndColumn +} + +// GetEndLine returns the EndLine field if it's non-nil, zero value otherwise. +func (l *Location) GetEndLine() int { + if l == nil || l.EndLine == nil { + return 0 + } + return *l.EndLine +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (l *Location) GetPath() string { + if l == nil || l.Path == nil { + return "" + } + return *l.Path +} + +// GetStartColumn returns the StartColumn field if it's non-nil, zero value otherwise. +func (l *Location) GetStartColumn() int { + if l == nil || l.StartColumn == nil { + return 0 + } + return *l.StartColumn +} + +// GetStartLine returns the StartLine field if it's non-nil, zero value otherwise. +func (l *Location) GetStartLine() int { + if l == nil || l.StartLine == nil { + return 0 + } + return *l.StartLine +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (l *LockBranch) GetEnabled() bool { + if l == nil || l.Enabled == nil { + return false + } + return *l.Enabled +} + +// GetEffectiveDate returns the EffectiveDate field if it's non-nil, zero value otherwise. +func (m *MarketplacePendingChange) GetEffectiveDate() Timestamp { + if m == nil || m.EffectiveDate == nil { + return Timestamp{} + } + return *m.EffectiveDate +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (m *MarketplacePendingChange) GetID() int64 { + if m == nil || m.ID == nil { + return 0 + } + return *m.ID +} + +// GetPlan returns the Plan field. +func (m *MarketplacePendingChange) GetPlan() *MarketplacePlan { + if m == nil { + return nil + } + return m.Plan +} + +// GetUnitCount returns the UnitCount field if it's non-nil, zero value otherwise. +func (m *MarketplacePendingChange) GetUnitCount() int { + if m == nil || m.UnitCount == nil { + return 0 + } + return *m.UnitCount +} + +// GetAccountsURL returns the AccountsURL field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetAccountsURL() string { + if m == nil || m.AccountsURL == nil { + return "" + } + return *m.AccountsURL +} + +// GetBullets returns the Bullets field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetBullets() []string { + if m == nil || m.Bullets == nil { + return nil + } + return *m.Bullets +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetDescription() string { + if m == nil || m.Description == nil { + return "" + } + return *m.Description +} + +// GetHasFreeTrial returns the HasFreeTrial field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetHasFreeTrial() bool { + if m == nil || m.HasFreeTrial == nil { + return false + } + return *m.HasFreeTrial +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetID() int64 { + if m == nil || m.ID == nil { + return 0 + } + return *m.ID +} + +// GetMonthlyPriceInCents returns the MonthlyPriceInCents field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetMonthlyPriceInCents() int { + if m == nil || m.MonthlyPriceInCents == nil { + return 0 + } + return *m.MonthlyPriceInCents +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetName() string { + if m == nil || m.Name == nil { + return "" + } + return *m.Name +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetNumber() int { + if m == nil || m.Number == nil { + return 0 + } + return *m.Number +} + +// GetPriceModel returns the PriceModel field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetPriceModel() string { + if m == nil || m.PriceModel == nil { + return "" + } + return *m.PriceModel +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetState() string { + if m == nil || m.State == nil { + return "" + } + return *m.State +} + +// GetUnitName returns the UnitName field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetUnitName() string { + if m == nil || m.UnitName == nil { + return "" + } + return *m.UnitName +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetYearlyPriceInCents returns the YearlyPriceInCents field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetYearlyPriceInCents() int { + if m == nil || m.YearlyPriceInCents == nil { + return 0 + } + return *m.YearlyPriceInCents +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (m *MarketplacePlanAccount) GetID() int64 { + if m == nil || m.ID == nil { + return 0 + } + return *m.ID +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (m *MarketplacePlanAccount) GetLogin() string { + if m == nil || m.Login == nil { + return "" + } + return *m.Login +} + +// GetMarketplacePendingChange returns the MarketplacePendingChange field. +func (m *MarketplacePlanAccount) GetMarketplacePendingChange() *MarketplacePendingChange { + if m == nil { + return nil + } + return m.MarketplacePendingChange +} + +// GetMarketplacePurchase returns the MarketplacePurchase field. +func (m *MarketplacePlanAccount) GetMarketplacePurchase() *MarketplacePurchase { + if m == nil { + return nil + } + return m.MarketplacePurchase +} + +// GetOrganizationBillingEmail returns the OrganizationBillingEmail field if it's non-nil, zero value otherwise. +func (m *MarketplacePlanAccount) GetOrganizationBillingEmail() string { + if m == nil || m.OrganizationBillingEmail == nil { + return "" + } + return *m.OrganizationBillingEmail +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (m *MarketplacePlanAccount) GetType() string { + if m == nil || m.Type == nil { + return "" + } + return *m.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *MarketplacePlanAccount) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetAccount returns the Account field. +func (m *MarketplacePurchase) GetAccount() *MarketplacePurchaseAccount { + if m == nil { + return nil + } + return m.Account +} + +// GetBillingCycle returns the BillingCycle field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchase) GetBillingCycle() string { + if m == nil || m.BillingCycle == nil { + return "" + } + return *m.BillingCycle +} + +// GetFreeTrialEndsOn returns the FreeTrialEndsOn field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchase) GetFreeTrialEndsOn() Timestamp { + if m == nil || m.FreeTrialEndsOn == nil { + return Timestamp{} + } + return *m.FreeTrialEndsOn +} + +// GetNextBillingDate returns the NextBillingDate field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchase) GetNextBillingDate() Timestamp { + if m == nil || m.NextBillingDate == nil { + return Timestamp{} + } + return *m.NextBillingDate +} + +// GetOnFreeTrial returns the OnFreeTrial field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchase) GetOnFreeTrial() bool { + if m == nil || m.OnFreeTrial == nil { + return false + } + return *m.OnFreeTrial +} + +// GetPlan returns the Plan field. +func (m *MarketplacePurchase) GetPlan() *MarketplacePlan { + if m == nil { + return nil + } + return m.Plan +} + +// GetUnitCount returns the UnitCount field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchase) GetUnitCount() int { + if m == nil || m.UnitCount == nil { + return 0 + } + return *m.UnitCount +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchase) GetUpdatedAt() Timestamp { + if m == nil || m.UpdatedAt == nil { + return Timestamp{} + } + return *m.UpdatedAt +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchaseAccount) GetEmail() string { + if m == nil || m.Email == nil { + return "" + } + return *m.Email +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchaseAccount) GetID() int64 { + if m == nil || m.ID == nil { + return 0 + } + return *m.ID +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchaseAccount) GetLogin() string { + if m == nil || m.Login == nil { + return "" + } + return *m.Login +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchaseAccount) GetNodeID() string { + if m == nil || m.NodeID == nil { + return "" + } + return *m.NodeID +} + +// GetOrganizationBillingEmail returns the OrganizationBillingEmail field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchaseAccount) GetOrganizationBillingEmail() string { + if m == nil || m.OrganizationBillingEmail == nil { + return "" + } + return *m.OrganizationBillingEmail +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchaseAccount) GetType() string { + if m == nil || m.Type == nil { + return "" + } + return *m.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchaseAccount) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchaseEvent) GetAction() string { + if m == nil || m.Action == nil { + return "" + } + return *m.Action +} + +// GetEffectiveDate returns the EffectiveDate field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchaseEvent) GetEffectiveDate() Timestamp { + if m == nil || m.EffectiveDate == nil { + return Timestamp{} + } + return *m.EffectiveDate +} + +// GetInstallation returns the Installation field. +func (m *MarketplacePurchaseEvent) GetInstallation() *Installation { + if m == nil { + return nil + } + return m.Installation +} + +// GetMarketplacePurchase returns the MarketplacePurchase field. +func (m *MarketplacePurchaseEvent) GetMarketplacePurchase() *MarketplacePurchase { + if m == nil { + return nil + } + return m.MarketplacePurchase +} + +// GetOrg returns the Org field. +func (m *MarketplacePurchaseEvent) GetOrg() *Organization { + if m == nil { + return nil + } + return m.Org +} + +// GetPreviousMarketplacePurchase returns the PreviousMarketplacePurchase field. +func (m *MarketplacePurchaseEvent) GetPreviousMarketplacePurchase() *MarketplacePurchase { + if m == nil { + return nil + } + return m.PreviousMarketplacePurchase +} + +// GetSender returns the Sender field. +func (m *MarketplacePurchaseEvent) GetSender() *User { + if m == nil { + return nil + } + return m.Sender +} + +// GetText returns the Text field if it's non-nil, zero value otherwise. +func (m *Match) GetText() string { + if m == nil || m.Text == nil { + return "" + } + return *m.Text +} + +// GetPermission returns the Permission field. +func (m *MemberChanges) GetPermission() *MemberChangesPermission { + if m == nil { + return nil + } + return m.Permission +} + +// GetRoleName returns the RoleName field. +func (m *MemberChanges) GetRoleName() *MemberChangesRoleName { + if m == nil { + return nil + } + return m.RoleName +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (m *MemberChangesPermission) GetFrom() string { + if m == nil || m.From == nil { + return "" + } + return *m.From +} + +// GetTo returns the To field if it's non-nil, zero value otherwise. +func (m *MemberChangesPermission) GetTo() string { + if m == nil || m.To == nil { + return "" + } + return *m.To +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (m *MemberChangesRoleName) GetFrom() string { + if m == nil || m.From == nil { + return "" + } + return *m.From +} + +// GetTo returns the To field if it's non-nil, zero value otherwise. +func (m *MemberChangesRoleName) GetTo() string { + if m == nil || m.To == nil { + return "" + } + return *m.To +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (m *MemberEvent) GetAction() string { + if m == nil || m.Action == nil { + return "" + } + return *m.Action +} + +// GetChanges returns the Changes field. +func (m *MemberEvent) GetChanges() *MemberChanges { + if m == nil { + return nil + } + return m.Changes +} + +// GetInstallation returns the Installation field. +func (m *MemberEvent) GetInstallation() *Installation { + if m == nil { + return nil + } + return m.Installation +} + +// GetMember returns the Member field. +func (m *MemberEvent) GetMember() *User { + if m == nil { + return nil + } + return m.Member +} + +// GetOrg returns the Org field. +func (m *MemberEvent) GetOrg() *Organization { + if m == nil { + return nil + } + return m.Org +} + +// GetRepo returns the Repo field. +func (m *MemberEvent) GetRepo() *Repository { + if m == nil { + return nil + } + return m.Repo +} + +// GetSender returns the Sender field. +func (m *MemberEvent) GetSender() *User { + if m == nil { + return nil + } + return m.Sender +} + +// GetOrganization returns the Organization field. +func (m *Membership) GetOrganization() *Organization { + if m == nil { + return nil + } + return m.Organization +} + +// GetOrganizationURL returns the OrganizationURL field if it's non-nil, zero value otherwise. +func (m *Membership) GetOrganizationURL() string { + if m == nil || m.OrganizationURL == nil { + return "" + } + return *m.OrganizationURL +} + +// GetRole returns the Role field if it's non-nil, zero value otherwise. +func (m *Membership) GetRole() string { + if m == nil || m.Role == nil { + return "" + } + return *m.Role +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (m *Membership) GetState() string { + if m == nil || m.State == nil { + return "" + } + return *m.State +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *Membership) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetUser returns the User field. +func (m *Membership) GetUser() *User { + if m == nil { + return nil + } + return m.User +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (m *MembershipEvent) GetAction() string { + if m == nil || m.Action == nil { + return "" + } + return *m.Action +} + +// GetInstallation returns the Installation field. +func (m *MembershipEvent) GetInstallation() *Installation { + if m == nil { + return nil + } + return m.Installation +} + +// GetMember returns the Member field. +func (m *MembershipEvent) GetMember() *User { + if m == nil { + return nil + } + return m.Member +} + +// GetOrg returns the Org field. +func (m *MembershipEvent) GetOrg() *Organization { + if m == nil { + return nil + } + return m.Org +} + +// GetScope returns the Scope field if it's non-nil, zero value otherwise. +func (m *MembershipEvent) GetScope() string { + if m == nil || m.Scope == nil { + return "" + } + return *m.Scope +} + +// GetSender returns the Sender field. +func (m *MembershipEvent) GetSender() *User { + if m == nil { + return nil + } + return m.Sender +} + +// GetTeam returns the Team field. +func (m *MembershipEvent) GetTeam() *Team { + if m == nil { + return nil + } + return m.Team +} + +// GetBaseRef returns the BaseRef field if it's non-nil, zero value otherwise. +func (m *MergeGroup) GetBaseRef() string { + if m == nil || m.BaseRef == nil { + return "" + } + return *m.BaseRef +} + +// GetBaseSHA returns the BaseSHA field if it's non-nil, zero value otherwise. +func (m *MergeGroup) GetBaseSHA() string { + if m == nil || m.BaseSHA == nil { + return "" + } + return *m.BaseSHA +} + +// GetHeadCommit returns the HeadCommit field. +func (m *MergeGroup) GetHeadCommit() *Commit { + if m == nil { + return nil + } + return m.HeadCommit +} + +// GetHeadRef returns the HeadRef field if it's non-nil, zero value otherwise. +func (m *MergeGroup) GetHeadRef() string { + if m == nil || m.HeadRef == nil { + return "" + } + return *m.HeadRef +} + +// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. +func (m *MergeGroup) GetHeadSHA() string { + if m == nil || m.HeadSHA == nil { + return "" + } + return *m.HeadSHA +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (m *MergeGroupEvent) GetAction() string { + if m == nil || m.Action == nil { + return "" + } + return *m.Action +} + +// GetInstallation returns the Installation field. +func (m *MergeGroupEvent) GetInstallation() *Installation { + if m == nil { + return nil + } + return m.Installation +} + +// GetMergeGroup returns the MergeGroup field. +func (m *MergeGroupEvent) GetMergeGroup() *MergeGroup { + if m == nil { + return nil + } + return m.MergeGroup +} + +// GetOrg returns the Org field. +func (m *MergeGroupEvent) GetOrg() *Organization { + if m == nil { + return nil + } + return m.Org +} + +// GetRepo returns the Repo field. +func (m *MergeGroupEvent) GetRepo() *Repository { + if m == nil { + return nil + } + return m.Repo +} + +// GetSender returns the Sender field. +func (m *MergeGroupEvent) GetSender() *User { + if m == nil { + return nil + } + return m.Sender +} + +// GetText returns the Text field if it's non-nil, zero value otherwise. +func (m *Message) GetText() string { + if m == nil || m.Text == nil { + return "" + } + return *m.Text +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (m *MetaEvent) GetAction() string { + if m == nil || m.Action == nil { + return "" + } + return *m.Action +} + +// GetHook returns the Hook field. +func (m *MetaEvent) GetHook() *Hook { + if m == nil { + return nil + } + return m.Hook +} + +// GetHookID returns the HookID field if it's non-nil, zero value otherwise. +func (m *MetaEvent) GetHookID() int64 { + if m == nil || m.HookID == nil { + return 0 + } + return *m.HookID +} + +// GetInstallation returns the Installation field. +func (m *MetaEvent) GetInstallation() *Installation { + if m == nil { + return nil + } + return m.Installation +} + +// GetOrg returns the Org field. +func (m *MetaEvent) GetOrg() *Organization { + if m == nil { + return nil + } + return m.Org +} + +// GetRepo returns the Repo field. +func (m *MetaEvent) GetRepo() *Repository { + if m == nil { + return nil + } + return m.Repo +} + +// GetSender returns the Sender field. +func (m *MetaEvent) GetSender() *User { + if m == nil { + return nil + } + return m.Sender +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (m *Metric) GetHTMLURL() string { + if m == nil || m.HTMLURL == nil { + return "" + } + return *m.HTMLURL +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (m *Metric) GetKey() string { + if m == nil || m.Key == nil { + return "" + } + return *m.Key +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (m *Metric) GetName() string { + if m == nil || m.Name == nil { + return "" + } + return *m.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (m *Metric) GetNodeID() string { + if m == nil || m.NodeID == nil { + return "" + } + return *m.NodeID +} + +// GetSPDXID returns the SPDXID field if it's non-nil, zero value otherwise. +func (m *Metric) GetSPDXID() string { + if m == nil || m.SPDXID == nil { + return "" + } + return *m.SPDXID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *Metric) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (m *Migration) GetCreatedAt() string { + if m == nil || m.CreatedAt == nil { + return "" + } + return *m.CreatedAt +} + +// GetExcludeAttachments returns the ExcludeAttachments field if it's non-nil, zero value otherwise. +func (m *Migration) GetExcludeAttachments() bool { + if m == nil || m.ExcludeAttachments == nil { + return false + } + return *m.ExcludeAttachments +} + +// GetGUID returns the GUID field if it's non-nil, zero value otherwise. +func (m *Migration) GetGUID() string { + if m == nil || m.GUID == nil { + return "" + } + return *m.GUID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (m *Migration) GetID() int64 { + if m == nil || m.ID == nil { + return 0 + } + return *m.ID +} + +// GetLockRepositories returns the LockRepositories field if it's non-nil, zero value otherwise. +func (m *Migration) GetLockRepositories() bool { + if m == nil || m.LockRepositories == nil { + return false + } + return *m.LockRepositories +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (m *Migration) GetState() string { + if m == nil || m.State == nil { + return "" + } + return *m.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (m *Migration) GetUpdatedAt() string { + if m == nil || m.UpdatedAt == nil { + return "" + } + return *m.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *Migration) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. +func (m *Milestone) GetClosedAt() Timestamp { + if m == nil || m.ClosedAt == nil { + return Timestamp{} + } + return *m.ClosedAt +} + +// GetClosedIssues returns the ClosedIssues field if it's non-nil, zero value otherwise. +func (m *Milestone) GetClosedIssues() int { + if m == nil || m.ClosedIssues == nil { + return 0 + } + return *m.ClosedIssues +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (m *Milestone) GetCreatedAt() Timestamp { + if m == nil || m.CreatedAt == nil { + return Timestamp{} + } + return *m.CreatedAt +} + +// GetCreator returns the Creator field. +func (m *Milestone) GetCreator() *User { + if m == nil { + return nil + } + return m.Creator +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (m *Milestone) GetDescription() string { + if m == nil || m.Description == nil { + return "" + } + return *m.Description +} + +// GetDueOn returns the DueOn field if it's non-nil, zero value otherwise. +func (m *Milestone) GetDueOn() Timestamp { + if m == nil || m.DueOn == nil { + return Timestamp{} + } + return *m.DueOn +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (m *Milestone) GetHTMLURL() string { + if m == nil || m.HTMLURL == nil { + return "" + } + return *m.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (m *Milestone) GetID() int64 { + if m == nil || m.ID == nil { + return 0 + } + return *m.ID +} + +// GetLabelsURL returns the LabelsURL field if it's non-nil, zero value otherwise. +func (m *Milestone) GetLabelsURL() string { + if m == nil || m.LabelsURL == nil { + return "" + } + return *m.LabelsURL +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (m *Milestone) GetNodeID() string { + if m == nil || m.NodeID == nil { + return "" + } + return *m.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (m *Milestone) GetNumber() int { + if m == nil || m.Number == nil { + return 0 + } + return *m.Number +} + +// GetOpenIssues returns the OpenIssues field if it's non-nil, zero value otherwise. +func (m *Milestone) GetOpenIssues() int { + if m == nil || m.OpenIssues == nil { + return 0 + } + return *m.OpenIssues +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (m *Milestone) GetState() string { + if m == nil || m.State == nil { + return "" + } + return *m.State +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (m *Milestone) GetTitle() string { + if m == nil || m.Title == nil { + return "" + } + return *m.Title +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (m *Milestone) GetUpdatedAt() Timestamp { + if m == nil || m.UpdatedAt == nil { + return Timestamp{} + } + return *m.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *Milestone) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (m *MilestoneEvent) GetAction() string { + if m == nil || m.Action == nil { + return "" + } + return *m.Action +} + +// GetChanges returns the Changes field. +func (m *MilestoneEvent) GetChanges() *EditChange { + if m == nil { + return nil + } + return m.Changes +} + +// GetInstallation returns the Installation field. +func (m *MilestoneEvent) GetInstallation() *Installation { + if m == nil { + return nil + } + return m.Installation +} + +// GetMilestone returns the Milestone field. +func (m *MilestoneEvent) GetMilestone() *Milestone { + if m == nil { + return nil + } + return m.Milestone +} + +// GetOrg returns the Org field. +func (m *MilestoneEvent) GetOrg() *Organization { + if m == nil { + return nil + } + return m.Org +} + +// GetRepo returns the Repo field. +func (m *MilestoneEvent) GetRepo() *Repository { + if m == nil { + return nil + } + return m.Repo +} + +// GetSender returns the Sender field. +func (m *MilestoneEvent) GetSender() *User { + if m == nil { + return nil + } + return m.Sender +} + +// GetClosedMilestones returns the ClosedMilestones field if it's non-nil, zero value otherwise. +func (m *MilestoneStats) GetClosedMilestones() int { + if m == nil || m.ClosedMilestones == nil { + return 0 + } + return *m.ClosedMilestones +} + +// GetOpenMilestones returns the OpenMilestones field if it's non-nil, zero value otherwise. +func (m *MilestoneStats) GetOpenMilestones() int { + if m == nil || m.OpenMilestones == nil { + return 0 + } + return *m.OpenMilestones +} + +// GetTotalMilestones returns the TotalMilestones field if it's non-nil, zero value otherwise. +func (m *MilestoneStats) GetTotalMilestones() int { + if m == nil || m.TotalMilestones == nil { + return 0 + } + return *m.TotalMilestones +} + +// GetAnalysisKey returns the AnalysisKey field if it's non-nil, zero value otherwise. +func (m *MostRecentInstance) GetAnalysisKey() string { + if m == nil || m.AnalysisKey == nil { + return "" + } + return *m.AnalysisKey +} + +// GetCategory returns the Category field if it's non-nil, zero value otherwise. +func (m *MostRecentInstance) GetCategory() string { + if m == nil || m.Category == nil { + return "" + } + return *m.Category +} + +// GetCommitSHA returns the CommitSHA field if it's non-nil, zero value otherwise. +func (m *MostRecentInstance) GetCommitSHA() string { + if m == nil || m.CommitSHA == nil { + return "" + } + return *m.CommitSHA +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (m *MostRecentInstance) GetEnvironment() string { + if m == nil || m.Environment == nil { + return "" + } + return *m.Environment +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (m *MostRecentInstance) GetHTMLURL() string { + if m == nil || m.HTMLURL == nil { + return "" + } + return *m.HTMLURL +} + +// GetLocation returns the Location field. +func (m *MostRecentInstance) GetLocation() *Location { + if m == nil { + return nil + } + return m.Location +} + +// GetMessage returns the Message field. +func (m *MostRecentInstance) GetMessage() *Message { + if m == nil { + return nil + } + return m.Message +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (m *MostRecentInstance) GetRef() string { + if m == nil || m.Ref == nil { + return "" + } + return *m.Ref +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (m *MostRecentInstance) GetState() string { + if m == nil || m.State == nil { + return "" + } + return *m.State +} + +// GetBase returns the Base field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetBase() string { + if n == nil || n.Base == nil { + return "" + } + return *n.Base +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetBody() string { + if n == nil || n.Body == nil { + return "" + } + return *n.Body +} + +// GetDraft returns the Draft field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetDraft() bool { + if n == nil || n.Draft == nil { + return false + } + return *n.Draft +} + +// GetHead returns the Head field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetHead() string { + if n == nil || n.Head == nil { + return "" + } + return *n.Head +} + +// GetHeadRepo returns the HeadRepo field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetHeadRepo() string { + if n == nil || n.HeadRepo == nil { + return "" + } + return *n.HeadRepo +} + +// GetIssue returns the Issue field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetIssue() int { + if n == nil || n.Issue == nil { + return 0 + } + return *n.Issue +} + +// GetMaintainerCanModify returns the MaintainerCanModify field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetMaintainerCanModify() bool { + if n == nil || n.MaintainerCanModify == nil { + return false + } + return *n.MaintainerCanModify +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetTitle() string { + if n == nil || n.Title == nil { + return "" + } + return *n.Title +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetDescription() string { + if n == nil || n.Description == nil { + return "" + } + return *n.Description +} + +// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetLDAPDN() string { + if n == nil || n.LDAPDN == nil { + return "" + } + return *n.LDAPDN +} + +// GetNotificationSetting returns the NotificationSetting field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetNotificationSetting() string { + if n == nil || n.NotificationSetting == nil { + return "" + } + return *n.NotificationSetting +} + +// GetParentTeamID returns the ParentTeamID field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetParentTeamID() int64 { + if n == nil || n.ParentTeamID == nil { + return 0 + } + return *n.ParentTeamID +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetPermission() string { + if n == nil || n.Permission == nil { + return "" + } + return *n.Permission +} + +// GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetPrivacy() string { + if n == nil || n.Privacy == nil { + return "" + } + return *n.Privacy +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (n *Notification) GetID() string { + if n == nil || n.ID == nil { + return "" + } + return *n.ID +} + +// GetLastReadAt returns the LastReadAt field if it's non-nil, zero value otherwise. +func (n *Notification) GetLastReadAt() Timestamp { + if n == nil || n.LastReadAt == nil { + return Timestamp{} + } + return *n.LastReadAt +} + +// GetReason returns the Reason field if it's non-nil, zero value otherwise. +func (n *Notification) GetReason() string { + if n == nil || n.Reason == nil { + return "" + } + return *n.Reason +} + +// GetRepository returns the Repository field. +func (n *Notification) GetRepository() *Repository { + if n == nil { + return nil + } + return n.Repository +} + +// GetSubject returns the Subject field. +func (n *Notification) GetSubject() *NotificationSubject { + if n == nil { + return nil + } + return n.Subject +} + +// GetUnread returns the Unread field if it's non-nil, zero value otherwise. +func (n *Notification) GetUnread() bool { + if n == nil || n.Unread == nil { + return false + } + return *n.Unread +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (n *Notification) GetUpdatedAt() Timestamp { + if n == nil || n.UpdatedAt == nil { + return Timestamp{} + } + return *n.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (n *Notification) GetURL() string { + if n == nil || n.URL == nil { + return "" + } + return *n.URL +} + +// GetLatestCommentURL returns the LatestCommentURL field if it's non-nil, zero value otherwise. +func (n *NotificationSubject) GetLatestCommentURL() string { + if n == nil || n.LatestCommentURL == nil { + return "" + } + return *n.LatestCommentURL +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (n *NotificationSubject) GetTitle() string { + if n == nil || n.Title == nil { + return "" + } + return *n.Title +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (n *NotificationSubject) GetType() string { + if n == nil || n.Type == nil { + return "" + } + return *n.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (n *NotificationSubject) GetURL() string { + if n == nil || n.URL == nil { + return "" + } + return *n.URL +} + +// GetClientID returns the ClientID field if it's non-nil, zero value otherwise. +func (o *OAuthAPP) GetClientID() string { + if o == nil || o.ClientID == nil { + return "" + } + return *o.ClientID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (o *OAuthAPP) GetName() string { + if o == nil || o.Name == nil { + return "" + } + return *o.Name +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (o *OAuthAPP) GetURL() string { + if o == nil || o.URL == nil { + return "" + } + return *o.URL +} + +// GetUseDefault returns the UseDefault field if it's non-nil, zero value otherwise. +func (o *OIDCSubjectClaimCustomTemplate) GetUseDefault() bool { + if o == nil || o.UseDefault == nil { + return false + } + return *o.UseDefault +} + +// GetAdvancedSecurityEnabledForNewRepos returns the AdvancedSecurityEnabledForNewRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetAdvancedSecurityEnabledForNewRepos() bool { + if o == nil || o.AdvancedSecurityEnabledForNewRepos == nil { + return false + } + return *o.AdvancedSecurityEnabledForNewRepos +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetAvatarURL() string { + if o == nil || o.AvatarURL == nil { + return "" + } + return *o.AvatarURL +} + +// GetBillingEmail returns the BillingEmail field if it's non-nil, zero value otherwise. +func (o *Organization) GetBillingEmail() string { + if o == nil || o.BillingEmail == nil { + return "" + } + return *o.BillingEmail +} + +// GetBlog returns the Blog field if it's non-nil, zero value otherwise. +func (o *Organization) GetBlog() string { + if o == nil || o.Blog == nil { + return "" + } + return *o.Blog +} + +// GetCollaborators returns the Collaborators field if it's non-nil, zero value otherwise. +func (o *Organization) GetCollaborators() int { + if o == nil || o.Collaborators == nil { + return 0 + } + return *o.Collaborators +} + +// GetCompany returns the Company field if it's non-nil, zero value otherwise. +func (o *Organization) GetCompany() string { + if o == nil || o.Company == nil { + return "" + } + return *o.Company +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (o *Organization) GetCreatedAt() Timestamp { + if o == nil || o.CreatedAt == nil { + return Timestamp{} + } + return *o.CreatedAt +} + +// GetDefaultRepoPermission returns the DefaultRepoPermission field if it's non-nil, zero value otherwise. +func (o *Organization) GetDefaultRepoPermission() string { + if o == nil || o.DefaultRepoPermission == nil { + return "" + } + return *o.DefaultRepoPermission +} + +// GetDefaultRepoSettings returns the DefaultRepoSettings field if it's non-nil, zero value otherwise. +func (o *Organization) GetDefaultRepoSettings() string { + if o == nil || o.DefaultRepoSettings == nil { + return "" + } + return *o.DefaultRepoSettings +} + +// GetDependabotAlertsEnabledForNewRepos returns the DependabotAlertsEnabledForNewRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetDependabotAlertsEnabledForNewRepos() bool { + if o == nil || o.DependabotAlertsEnabledForNewRepos == nil { + return false + } + return *o.DependabotAlertsEnabledForNewRepos +} + +// GetDependabotSecurityUpdatesEnabledForNewRepos returns the DependabotSecurityUpdatesEnabledForNewRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetDependabotSecurityUpdatesEnabledForNewRepos() bool { + if o == nil || o.DependabotSecurityUpdatesEnabledForNewRepos == nil { + return false + } + return *o.DependabotSecurityUpdatesEnabledForNewRepos +} + +// GetDependencyGraphEnabledForNewRepos returns the DependencyGraphEnabledForNewRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetDependencyGraphEnabledForNewRepos() bool { + if o == nil || o.DependencyGraphEnabledForNewRepos == nil { + return false + } + return *o.DependencyGraphEnabledForNewRepos +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (o *Organization) GetDescription() string { + if o == nil || o.Description == nil { + return "" + } + return *o.Description +} + +// GetDiskUsage returns the DiskUsage field if it's non-nil, zero value otherwise. +func (o *Organization) GetDiskUsage() int { + if o == nil || o.DiskUsage == nil { + return 0 + } + return *o.DiskUsage +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (o *Organization) GetEmail() string { + if o == nil || o.Email == nil { + return "" + } + return *o.Email +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetEventsURL() string { + if o == nil || o.EventsURL == nil { + return "" + } + return *o.EventsURL +} + +// GetFollowers returns the Followers field if it's non-nil, zero value otherwise. +func (o *Organization) GetFollowers() int { + if o == nil || o.Followers == nil { + return 0 + } + return *o.Followers +} + +// GetFollowing returns the Following field if it's non-nil, zero value otherwise. +func (o *Organization) GetFollowing() int { + if o == nil || o.Following == nil { + return 0 + } + return *o.Following +} + +// GetHasOrganizationProjects returns the HasOrganizationProjects field if it's non-nil, zero value otherwise. +func (o *Organization) GetHasOrganizationProjects() bool { + if o == nil || o.HasOrganizationProjects == nil { + return false + } + return *o.HasOrganizationProjects +} + +// GetHasRepositoryProjects returns the HasRepositoryProjects field if it's non-nil, zero value otherwise. +func (o *Organization) GetHasRepositoryProjects() bool { + if o == nil || o.HasRepositoryProjects == nil { + return false + } + return *o.HasRepositoryProjects +} + +// GetHooksURL returns the HooksURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetHooksURL() string { + if o == nil || o.HooksURL == nil { + return "" + } + return *o.HooksURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetHTMLURL() string { + if o == nil || o.HTMLURL == nil { + return "" + } + return *o.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (o *Organization) GetID() int64 { + if o == nil || o.ID == nil { + return 0 + } + return *o.ID +} + +// GetIssuesURL returns the IssuesURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetIssuesURL() string { + if o == nil || o.IssuesURL == nil { + return "" + } + return *o.IssuesURL +} + +// GetIsVerified returns the IsVerified field if it's non-nil, zero value otherwise. +func (o *Organization) GetIsVerified() bool { + if o == nil || o.IsVerified == nil { + return false + } + return *o.IsVerified +} + +// GetLocation returns the Location field if it's non-nil, zero value otherwise. +func (o *Organization) GetLocation() string { + if o == nil || o.Location == nil { + return "" + } + return *o.Location +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (o *Organization) GetLogin() string { + if o == nil || o.Login == nil { + return "" + } + return *o.Login +} + +// GetMembersAllowedRepositoryCreationType returns the MembersAllowedRepositoryCreationType field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersAllowedRepositoryCreationType() string { + if o == nil || o.MembersAllowedRepositoryCreationType == nil { + return "" + } + return *o.MembersAllowedRepositoryCreationType +} + +// GetMembersCanCreateInternalRepos returns the MembersCanCreateInternalRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanCreateInternalRepos() bool { + if o == nil || o.MembersCanCreateInternalRepos == nil { + return false + } + return *o.MembersCanCreateInternalRepos +} + +// GetMembersCanCreatePages returns the MembersCanCreatePages field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanCreatePages() bool { + if o == nil || o.MembersCanCreatePages == nil { + return false + } + return *o.MembersCanCreatePages +} + +// GetMembersCanCreatePrivatePages returns the MembersCanCreatePrivatePages field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanCreatePrivatePages() bool { + if o == nil || o.MembersCanCreatePrivatePages == nil { + return false + } + return *o.MembersCanCreatePrivatePages +} + +// GetMembersCanCreatePrivateRepos returns the MembersCanCreatePrivateRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanCreatePrivateRepos() bool { + if o == nil || o.MembersCanCreatePrivateRepos == nil { + return false + } + return *o.MembersCanCreatePrivateRepos +} + +// GetMembersCanCreatePublicPages returns the MembersCanCreatePublicPages field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanCreatePublicPages() bool { + if o == nil || o.MembersCanCreatePublicPages == nil { + return false + } + return *o.MembersCanCreatePublicPages +} + +// GetMembersCanCreatePublicRepos returns the MembersCanCreatePublicRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanCreatePublicRepos() bool { + if o == nil || o.MembersCanCreatePublicRepos == nil { + return false + } + return *o.MembersCanCreatePublicRepos +} + +// GetMembersCanCreateRepos returns the MembersCanCreateRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanCreateRepos() bool { + if o == nil || o.MembersCanCreateRepos == nil { + return false + } + return *o.MembersCanCreateRepos +} + +// GetMembersCanForkPrivateRepos returns the MembersCanForkPrivateRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanForkPrivateRepos() bool { + if o == nil || o.MembersCanForkPrivateRepos == nil { + return false + } + return *o.MembersCanForkPrivateRepos +} + +// GetMembersURL returns the MembersURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersURL() string { + if o == nil || o.MembersURL == nil { + return "" + } + return *o.MembersURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (o *Organization) GetName() string { + if o == nil || o.Name == nil { + return "" + } + return *o.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (o *Organization) GetNodeID() string { + if o == nil || o.NodeID == nil { + return "" + } + return *o.NodeID +} + +// GetOwnedPrivateRepos returns the OwnedPrivateRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetOwnedPrivateRepos() int64 { + if o == nil || o.OwnedPrivateRepos == nil { + return 0 + } + return *o.OwnedPrivateRepos +} + +// GetPlan returns the Plan field. +func (o *Organization) GetPlan() *Plan { + if o == nil { + return nil + } + return o.Plan +} + +// GetPrivateGists returns the PrivateGists field if it's non-nil, zero value otherwise. +func (o *Organization) GetPrivateGists() int { + if o == nil || o.PrivateGists == nil { + return 0 + } + return *o.PrivateGists +} + +// GetPublicGists returns the PublicGists field if it's non-nil, zero value otherwise. +func (o *Organization) GetPublicGists() int { + if o == nil || o.PublicGists == nil { + return 0 + } + return *o.PublicGists +} + +// GetPublicMembersURL returns the PublicMembersURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetPublicMembersURL() string { + if o == nil || o.PublicMembersURL == nil { + return "" + } + return *o.PublicMembersURL +} + +// GetPublicRepos returns the PublicRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetPublicRepos() int { + if o == nil || o.PublicRepos == nil { + return 0 + } + return *o.PublicRepos +} + +// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetReposURL() string { + if o == nil || o.ReposURL == nil { + return "" + } + return *o.ReposURL +} + +// GetSecretScanningEnabledForNewRepos returns the SecretScanningEnabledForNewRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetSecretScanningEnabledForNewRepos() bool { + if o == nil || o.SecretScanningEnabledForNewRepos == nil { + return false + } + return *o.SecretScanningEnabledForNewRepos +} + +// GetSecretScanningPushProtectionEnabledForNewRepos returns the SecretScanningPushProtectionEnabledForNewRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetSecretScanningPushProtectionEnabledForNewRepos() bool { + if o == nil || o.SecretScanningPushProtectionEnabledForNewRepos == nil { + return false + } + return *o.SecretScanningPushProtectionEnabledForNewRepos +} + +// GetSecretScanningValidityChecksEnabled returns the SecretScanningValidityChecksEnabled field if it's non-nil, zero value otherwise. +func (o *Organization) GetSecretScanningValidityChecksEnabled() bool { + if o == nil || o.SecretScanningValidityChecksEnabled == nil { + return false + } + return *o.SecretScanningValidityChecksEnabled +} + +// GetTotalPrivateRepos returns the TotalPrivateRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetTotalPrivateRepos() int64 { + if o == nil || o.TotalPrivateRepos == nil { + return 0 + } + return *o.TotalPrivateRepos +} + +// GetTwitterUsername returns the TwitterUsername field if it's non-nil, zero value otherwise. +func (o *Organization) GetTwitterUsername() string { + if o == nil || o.TwitterUsername == nil { + return "" + } + return *o.TwitterUsername +} + +// GetTwoFactorRequirementEnabled returns the TwoFactorRequirementEnabled field if it's non-nil, zero value otherwise. +func (o *Organization) GetTwoFactorRequirementEnabled() bool { + if o == nil || o.TwoFactorRequirementEnabled == nil { + return false + } + return *o.TwoFactorRequirementEnabled +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (o *Organization) GetType() string { + if o == nil || o.Type == nil { + return "" + } + return *o.Type +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (o *Organization) GetUpdatedAt() Timestamp { + if o == nil || o.UpdatedAt == nil { + return Timestamp{} + } + return *o.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (o *Organization) GetURL() string { + if o == nil || o.URL == nil { + return "" + } + return *o.URL +} + +// GetWebCommitSignoffRequired returns the WebCommitSignoffRequired field if it's non-nil, zero value otherwise. +func (o *Organization) GetWebCommitSignoffRequired() bool { + if o == nil || o.WebCommitSignoffRequired == nil { + return false + } + return *o.WebCommitSignoffRequired +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (o *OrganizationCustomRepoRoles) GetTotalCount() int { + if o == nil || o.TotalCount == nil { + return 0 + } + return *o.TotalCount +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (o *OrganizationCustomRoles) GetTotalCount() int { + if o == nil || o.TotalCount == nil { + return 0 + } + return *o.TotalCount +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (o *OrganizationEvent) GetAction() string { + if o == nil || o.Action == nil { + return "" + } + return *o.Action +} + +// GetInstallation returns the Installation field. +func (o *OrganizationEvent) GetInstallation() *Installation { + if o == nil { + return nil + } + return o.Installation +} + +// GetInvitation returns the Invitation field. +func (o *OrganizationEvent) GetInvitation() *Invitation { + if o == nil { + return nil + } + return o.Invitation +} + +// GetMembership returns the Membership field. +func (o *OrganizationEvent) GetMembership() *Membership { + if o == nil { + return nil + } + return o.Membership +} + +// GetOrganization returns the Organization field. +func (o *OrganizationEvent) GetOrganization() *Organization { + if o == nil { + return nil + } + return o.Organization +} + +// GetSender returns the Sender field. +func (o *OrganizationEvent) GetSender() *User { + if o == nil { + return nil + } + return o.Sender +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (o *OrganizationInstallations) GetTotalCount() int { + if o == nil || o.TotalCount == nil { + return 0 + } + return *o.TotalCount +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (o *OrgBlockEvent) GetAction() string { + if o == nil || o.Action == nil { + return "" + } + return *o.Action +} + +// GetBlockedUser returns the BlockedUser field. +func (o *OrgBlockEvent) GetBlockedUser() *User { + if o == nil { + return nil + } + return o.BlockedUser +} + +// GetInstallation returns the Installation field. +func (o *OrgBlockEvent) GetInstallation() *Installation { + if o == nil { + return nil + } + return o.Installation +} + +// GetOrganization returns the Organization field. +func (o *OrgBlockEvent) GetOrganization() *Organization { + if o == nil { + return nil + } + return o.Organization +} + +// GetSender returns the Sender field. +func (o *OrgBlockEvent) GetSender() *User { + if o == nil { + return nil + } + return o.Sender +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (o *OrgRequiredWorkflow) GetCreatedAt() Timestamp { + if o == nil || o.CreatedAt == nil { + return Timestamp{} + } + return *o.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (o *OrgRequiredWorkflow) GetID() int64 { + if o == nil || o.ID == nil { + return 0 + } + return *o.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (o *OrgRequiredWorkflow) GetName() string { + if o == nil || o.Name == nil { + return "" + } + return *o.Name +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (o *OrgRequiredWorkflow) GetPath() string { + if o == nil || o.Path == nil { + return "" + } + return *o.Path +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (o *OrgRequiredWorkflow) GetRef() string { + if o == nil || o.Ref == nil { + return "" + } + return *o.Ref +} + +// GetRepository returns the Repository field. +func (o *OrgRequiredWorkflow) GetRepository() *Repository { + if o == nil { + return nil + } + return o.Repository +} + +// GetScope returns the Scope field if it's non-nil, zero value otherwise. +func (o *OrgRequiredWorkflow) GetScope() string { + if o == nil || o.Scope == nil { + return "" + } + return *o.Scope +} + +// GetSelectedRepositoriesURL returns the SelectedRepositoriesURL field if it's non-nil, zero value otherwise. +func (o *OrgRequiredWorkflow) GetSelectedRepositoriesURL() string { + if o == nil || o.SelectedRepositoriesURL == nil { + return "" + } + return *o.SelectedRepositoriesURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (o *OrgRequiredWorkflow) GetState() string { + if o == nil || o.State == nil { + return "" + } + return *o.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (o *OrgRequiredWorkflow) GetUpdatedAt() Timestamp { + if o == nil || o.UpdatedAt == nil { + return Timestamp{} + } + return *o.UpdatedAt +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (o *OrgRequiredWorkflows) GetTotalCount() int { + if o == nil || o.TotalCount == nil { + return 0 + } + return *o.TotalCount +} + +// GetDisabledOrgs returns the DisabledOrgs field if it's non-nil, zero value otherwise. +func (o *OrgStats) GetDisabledOrgs() int { + if o == nil || o.DisabledOrgs == nil { + return 0 + } + return *o.DisabledOrgs +} + +// GetTotalOrgs returns the TotalOrgs field if it's non-nil, zero value otherwise. +func (o *OrgStats) GetTotalOrgs() int { + if o == nil || o.TotalOrgs == nil { + return 0 + } + return *o.TotalOrgs +} + +// GetTotalTeamMembers returns the TotalTeamMembers field if it's non-nil, zero value otherwise. +func (o *OrgStats) GetTotalTeamMembers() int { + if o == nil || o.TotalTeamMembers == nil { + return 0 + } + return *o.TotalTeamMembers +} + +// GetTotalTeams returns the TotalTeams field if it's non-nil, zero value otherwise. +func (o *OrgStats) GetTotalTeams() int { + if o == nil || o.TotalTeams == nil { + return 0 + } + return *o.TotalTeams +} + +// GetOrg returns the Org field. +func (o *OwnerInfo) GetOrg() *User { + if o == nil { + return nil + } + return o.Org +} + +// GetUser returns the User field. +func (o *OwnerInfo) GetUser() *User { + if o == nil { + return nil + } + return o.User +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *Package) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *Package) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *Package) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *Package) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetOwner returns the Owner field. +func (p *Package) GetOwner() *User { + if p == nil { + return nil + } + return p.Owner +} + +// GetPackageType returns the PackageType field if it's non-nil, zero value otherwise. +func (p *Package) GetPackageType() string { + if p == nil || p.PackageType == nil { + return "" + } + return *p.PackageType +} + +// GetPackageVersion returns the PackageVersion field. +func (p *Package) GetPackageVersion() *PackageVersion { + if p == nil { + return nil + } + return p.PackageVersion +} + +// GetRegistry returns the Registry field. +func (p *Package) GetRegistry() *PackageRegistry { + if p == nil { + return nil + } + return p.Registry +} + +// GetRepository returns the Repository field. +func (p *Package) GetRepository() *Repository { + if p == nil { + return nil + } + return p.Repository +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *Package) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *Package) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetVersionCount returns the VersionCount field if it's non-nil, zero value otherwise. +func (p *Package) GetVersionCount() int64 { + if p == nil || p.VersionCount == nil { + return 0 + } + return *p.VersionCount +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (p *Package) GetVisibility() string { + if p == nil || p.Visibility == nil { + return "" + } + return *p.Visibility +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PackageEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetInstallation returns the Installation field. +func (p *PackageEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *PackageEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetPackage returns the Package field. +func (p *PackageEvent) GetPackage() *Package { + if p == nil { + return nil + } + return p.Package +} + +// GetRepo returns the Repo field. +func (p *PackageEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PackageEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetAuthor returns the Author field. +func (p *PackageFile) GetAuthor() *User { + if p == nil { + return nil + } + return p.Author +} + +// GetContentType returns the ContentType field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetContentType() string { + if p == nil || p.ContentType == nil { + return "" + } + return *p.ContentType +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetDownloadURL returns the DownloadURL field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetDownloadURL() string { + if p == nil || p.DownloadURL == nil { + return "" + } + return *p.DownloadURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetMD5 returns the MD5 field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetMD5() string { + if p == nil || p.MD5 == nil { + return "" + } + return *p.MD5 +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetSHA1 returns the SHA1 field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetSHA1() string { + if p == nil || p.SHA1 == nil { + return "" + } + return *p.SHA1 +} + +// GetSHA256 returns the SHA256 field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetSHA256() string { + if p == nil || p.SHA256 == nil { + return "" + } + return *p.SHA256 +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetSize() int64 { + if p == nil || p.Size == nil { + return 0 + } + return *p.Size +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetPackageType returns the PackageType field if it's non-nil, zero value otherwise. +func (p *PackageListOptions) GetPackageType() string { + if p == nil || p.PackageType == nil { + return "" + } + return *p.PackageType +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *PackageListOptions) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (p *PackageListOptions) GetVisibility() string { + if p == nil || p.Visibility == nil { + return "" + } + return *p.Visibility +} + +// GetContainer returns the Container field. +func (p *PackageMetadata) GetContainer() *PackageContainerMetadata { + if p == nil { + return nil + } + return p.Container +} + +// GetPackageType returns the PackageType field if it's non-nil, zero value otherwise. +func (p *PackageMetadata) GetPackageType() string { + if p == nil || p.PackageType == nil { + return "" + } + return *p.PackageType +} + +// GetAboutURL returns the AboutURL field if it's non-nil, zero value otherwise. +func (p *PackageRegistry) GetAboutURL() string { + if p == nil || p.AboutURL == nil { + return "" + } + return *p.AboutURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PackageRegistry) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (p *PackageRegistry) GetType() string { + if p == nil || p.Type == nil { + return "" + } + return *p.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PackageRegistry) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetVendor returns the Vendor field if it's non-nil, zero value otherwise. +func (p *PackageRegistry) GetVendor() string { + if p == nil || p.Vendor == nil { + return "" + } + return *p.Vendor +} + +// GetAuthor returns the Author field. +func (p *PackageRelease) GetAuthor() *User { + if p == nil { + return nil + } + return p.Author +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetDraft returns the Draft field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetDraft() bool { + if p == nil || p.Draft == nil { + return false + } + return *p.Draft +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetPrerelease returns the Prerelease field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetPrerelease() bool { + if p == nil || p.Prerelease == nil { + return false + } + return *p.Prerelease +} + +// GetPublishedAt returns the PublishedAt field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetPublishedAt() Timestamp { + if p == nil || p.PublishedAt == nil { + return Timestamp{} + } + return *p.PublishedAt +} + +// GetTagName returns the TagName field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetTagName() string { + if p == nil || p.TagName == nil { + return "" + } + return *p.TagName +} + +// GetTargetCommitish returns the TargetCommitish field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetTargetCommitish() string { + if p == nil || p.TargetCommitish == nil { + return "" + } + return *p.TargetCommitish +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetAuthor returns the Author field. +func (p *PackageVersion) GetAuthor() *User { + if p == nil { + return nil + } + return p.Author +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetBodyHTML returns the BodyHTML field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetBodyHTML() string { + if p == nil || p.BodyHTML == nil { + return "" + } + return *p.BodyHTML +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetDraft returns the Draft field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetDraft() bool { + if p == nil || p.Draft == nil { + return false + } + return *p.Draft +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetInstallationCommand returns the InstallationCommand field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetInstallationCommand() string { + if p == nil || p.InstallationCommand == nil { + return "" + } + return *p.InstallationCommand +} + +// GetManifest returns the Manifest field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetManifest() string { + if p == nil || p.Manifest == nil { + return "" + } + return *p.Manifest +} + +// GetMetadata returns the Metadata field. +func (p *PackageVersion) GetMetadata() *PackageMetadata { + if p == nil { + return nil + } + return p.Metadata +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetPackageHTMLURL returns the PackageHTMLURL field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetPackageHTMLURL() string { + if p == nil || p.PackageHTMLURL == nil { + return "" + } + return *p.PackageHTMLURL +} + +// GetPrerelease returns the Prerelease field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetPrerelease() bool { + if p == nil || p.Prerelease == nil { + return false + } + return *p.Prerelease +} + +// GetRelease returns the Release field. +func (p *PackageVersion) GetRelease() *PackageRelease { + if p == nil { + return nil + } + return p.Release +} + +// GetSummary returns the Summary field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetSummary() string { + if p == nil || p.Summary == nil { + return "" + } + return *p.Summary +} + +// GetTagName returns the TagName field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetTagName() string { + if p == nil || p.TagName == nil { + return "" + } + return *p.TagName +} + +// GetTargetCommitish returns the TargetCommitish field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetTargetCommitish() string { + if p == nil || p.TargetCommitish == nil { + return "" + } + return *p.TargetCommitish +} + +// GetTargetOID returns the TargetOID field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetTargetOID() string { + if p == nil || p.TargetOID == nil { + return "" + } + return *p.TargetOID +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetVersion() string { + if p == nil || p.Version == nil { + return "" + } + return *p.Version +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *Page) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *Page) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetPageName returns the PageName field if it's non-nil, zero value otherwise. +func (p *Page) GetPageName() string { + if p == nil || p.PageName == nil { + return "" + } + return *p.PageName +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (p *Page) GetSHA() string { + if p == nil || p.SHA == nil { + return "" + } + return *p.SHA +} + +// GetSummary returns the Summary field if it's non-nil, zero value otherwise. +func (p *Page) GetSummary() string { + if p == nil || p.Summary == nil { + return "" + } + return *p.Summary +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (p *Page) GetTitle() string { + if p == nil || p.Title == nil { + return "" + } + return *p.Title +} + +// GetBuild returns the Build field. +func (p *PageBuildEvent) GetBuild() *PagesBuild { + if p == nil { + return nil + } + return p.Build +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PageBuildEvent) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetInstallation returns the Installation field. +func (p *PageBuildEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *PageBuildEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetRepo returns the Repo field. +func (p *PageBuildEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PageBuildEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetBuildType returns the BuildType field if it's non-nil, zero value otherwise. +func (p *Pages) GetBuildType() string { + if p == nil || p.BuildType == nil { + return "" + } + return *p.BuildType +} + +// GetCNAME returns the CNAME field if it's non-nil, zero value otherwise. +func (p *Pages) GetCNAME() string { + if p == nil || p.CNAME == nil { + return "" + } + return *p.CNAME +} + +// GetCustom404 returns the Custom404 field if it's non-nil, zero value otherwise. +func (p *Pages) GetCustom404() bool { + if p == nil || p.Custom404 == nil { + return false + } + return *p.Custom404 +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *Pages) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetHTTPSCertificate returns the HTTPSCertificate field. +func (p *Pages) GetHTTPSCertificate() *PagesHTTPSCertificate { + if p == nil { + return nil + } + return p.HTTPSCertificate +} + +// GetHTTPSEnforced returns the HTTPSEnforced field if it's non-nil, zero value otherwise. +func (p *Pages) GetHTTPSEnforced() bool { + if p == nil || p.HTTPSEnforced == nil { + return false + } + return *p.HTTPSEnforced +} + +// GetPublic returns the Public field if it's non-nil, zero value otherwise. +func (p *Pages) GetPublic() bool { + if p == nil || p.Public == nil { + return false + } + return *p.Public +} + +// GetSource returns the Source field. +func (p *Pages) GetSource() *PagesSource { + if p == nil { + return nil + } + return p.Source +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (p *Pages) GetStatus() string { + if p == nil || p.Status == nil { + return "" + } + return *p.Status +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *Pages) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetCommit returns the Commit field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetCommit() string { + if p == nil || p.Commit == nil { + return "" + } + return *p.Commit +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetDuration returns the Duration field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetDuration() int { + if p == nil || p.Duration == nil { + return 0 + } + return *p.Duration +} + +// GetError returns the Error field. +func (p *PagesBuild) GetError() *PagesError { + if p == nil { + return nil + } + return p.Error +} + +// GetPusher returns the Pusher field. +func (p *PagesBuild) GetPusher() *User { + if p == nil { + return nil + } + return p.Pusher +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetStatus() string { + if p == nil || p.Status == nil { + return "" + } + return *p.Status +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetCAAError returns the CAAError field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetCAAError() string { + if p == nil || p.CAAError == nil { + return "" + } + return *p.CAAError +} + +// GetDNSResolves returns the DNSResolves field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetDNSResolves() bool { + if p == nil || p.DNSResolves == nil { + return false + } + return *p.DNSResolves +} + +// GetEnforcesHTTPS returns the EnforcesHTTPS field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetEnforcesHTTPS() bool { + if p == nil || p.EnforcesHTTPS == nil { + return false + } + return *p.EnforcesHTTPS +} + +// GetHasCNAMERecord returns the HasCNAMERecord field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetHasCNAMERecord() bool { + if p == nil || p.HasCNAMERecord == nil { + return false + } + return *p.HasCNAMERecord +} + +// GetHasMXRecordsPresent returns the HasMXRecordsPresent field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetHasMXRecordsPresent() bool { + if p == nil || p.HasMXRecordsPresent == nil { + return false + } + return *p.HasMXRecordsPresent +} + +// GetHost returns the Host field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetHost() string { + if p == nil || p.Host == nil { + return "" + } + return *p.Host +} + +// GetHTTPSError returns the HTTPSError field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetHTTPSError() string { + if p == nil || p.HTTPSError == nil { + return "" + } + return *p.HTTPSError +} + +// GetIsApexDomain returns the IsApexDomain field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsApexDomain() bool { + if p == nil || p.IsApexDomain == nil { + return false + } + return *p.IsApexDomain +} + +// GetIsARecord returns the IsARecord field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsARecord() bool { + if p == nil || p.IsARecord == nil { + return false + } + return *p.IsARecord +} + +// GetIsCloudflareIP returns the IsCloudflareIP field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsCloudflareIP() bool { + if p == nil || p.IsCloudflareIP == nil { + return false + } + return *p.IsCloudflareIP +} + +// GetIsCNAMEToFastly returns the IsCNAMEToFastly field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsCNAMEToFastly() bool { + if p == nil || p.IsCNAMEToFastly == nil { + return false + } + return *p.IsCNAMEToFastly +} + +// GetIsCNAMEToGithubUserDomain returns the IsCNAMEToGithubUserDomain field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsCNAMEToGithubUserDomain() bool { + if p == nil || p.IsCNAMEToGithubUserDomain == nil { + return false + } + return *p.IsCNAMEToGithubUserDomain +} + +// GetIsCNAMEToPagesDotGithubDotCom returns the IsCNAMEToPagesDotGithubDotCom field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsCNAMEToPagesDotGithubDotCom() bool { + if p == nil || p.IsCNAMEToPagesDotGithubDotCom == nil { + return false + } + return *p.IsCNAMEToPagesDotGithubDotCom +} + +// GetIsFastlyIP returns the IsFastlyIP field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsFastlyIP() bool { + if p == nil || p.IsFastlyIP == nil { + return false + } + return *p.IsFastlyIP +} + +// GetIsHTTPSEligible returns the IsHTTPSEligible field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsHTTPSEligible() bool { + if p == nil || p.IsHTTPSEligible == nil { + return false + } + return *p.IsHTTPSEligible +} + +// GetIsNonGithubPagesIPPresent returns the IsNonGithubPagesIPPresent field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsNonGithubPagesIPPresent() bool { + if p == nil || p.IsNonGithubPagesIPPresent == nil { + return false + } + return *p.IsNonGithubPagesIPPresent +} + +// GetIsOldIPAddress returns the IsOldIPAddress field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsOldIPAddress() bool { + if p == nil || p.IsOldIPAddress == nil { + return false + } + return *p.IsOldIPAddress +} + +// GetIsPagesDomain returns the IsPagesDomain field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsPagesDomain() bool { + if p == nil || p.IsPagesDomain == nil { + return false + } + return *p.IsPagesDomain +} + +// GetIsPointedToGithubPagesIP returns the IsPointedToGithubPagesIP field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsPointedToGithubPagesIP() bool { + if p == nil || p.IsPointedToGithubPagesIP == nil { + return false + } + return *p.IsPointedToGithubPagesIP +} + +// GetIsProxied returns the IsProxied field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsProxied() bool { + if p == nil || p.IsProxied == nil { + return false + } + return *p.IsProxied +} + +// GetIsServedByPages returns the IsServedByPages field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsServedByPages() bool { + if p == nil || p.IsServedByPages == nil { + return false + } + return *p.IsServedByPages +} + +// GetIsValid returns the IsValid field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsValid() bool { + if p == nil || p.IsValid == nil { + return false + } + return *p.IsValid +} + +// GetIsValidDomain returns the IsValidDomain field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsValidDomain() bool { + if p == nil || p.IsValidDomain == nil { + return false + } + return *p.IsValidDomain +} + +// GetNameservers returns the Nameservers field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetNameservers() string { + if p == nil || p.Nameservers == nil { + return "" + } + return *p.Nameservers +} + +// GetReason returns the Reason field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetReason() string { + if p == nil || p.Reason == nil { + return "" + } + return *p.Reason +} + +// GetRespondsToHTTPS returns the RespondsToHTTPS field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetRespondsToHTTPS() bool { + if p == nil || p.RespondsToHTTPS == nil { + return false + } + return *p.RespondsToHTTPS +} + +// GetShouldBeARecord returns the ShouldBeARecord field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetShouldBeARecord() bool { + if p == nil || p.ShouldBeARecord == nil { + return false + } + return *p.ShouldBeARecord +} + +// GetURI returns the URI field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetURI() string { + if p == nil || p.URI == nil { + return "" + } + return *p.URI +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (p *PagesError) GetMessage() string { + if p == nil || p.Message == nil { + return "" + } + return *p.Message +} + +// GetAltDomain returns the AltDomain field. +func (p *PagesHealthCheckResponse) GetAltDomain() *PagesDomain { + if p == nil { + return nil + } + return p.AltDomain +} + +// GetDomain returns the Domain field. +func (p *PagesHealthCheckResponse) GetDomain() *PagesDomain { + if p == nil { + return nil + } + return p.Domain +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (p *PagesHTTPSCertificate) GetDescription() string { + if p == nil || p.Description == nil { + return "" + } + return *p.Description +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (p *PagesHTTPSCertificate) GetExpiresAt() string { + if p == nil || p.ExpiresAt == nil { + return "" + } + return *p.ExpiresAt +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *PagesHTTPSCertificate) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetBranch returns the Branch field if it's non-nil, zero value otherwise. +func (p *PagesSource) GetBranch() string { + if p == nil || p.Branch == nil { + return "" + } + return *p.Branch +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (p *PagesSource) GetPath() string { + if p == nil || p.Path == nil { + return "" + } + return *p.Path +} + +// GetTotalPages returns the TotalPages field if it's non-nil, zero value otherwise. +func (p *PageStats) GetTotalPages() int { + if p == nil || p.TotalPages == nil { + return 0 + } + return *p.TotalPages +} + +// GetBuildType returns the BuildType field if it's non-nil, zero value otherwise. +func (p *PagesUpdate) GetBuildType() string { + if p == nil || p.BuildType == nil { + return "" + } + return *p.BuildType +} + +// GetCNAME returns the CNAME field if it's non-nil, zero value otherwise. +func (p *PagesUpdate) GetCNAME() string { + if p == nil || p.CNAME == nil { + return "" + } + return *p.CNAME +} + +// GetHTTPSEnforced returns the HTTPSEnforced field if it's non-nil, zero value otherwise. +func (p *PagesUpdate) GetHTTPSEnforced() bool { + if p == nil || p.HTTPSEnforced == nil { + return false + } + return *p.HTTPSEnforced +} + +// GetPublic returns the Public field if it's non-nil, zero value otherwise. +func (p *PagesUpdate) GetPublic() bool { + if p == nil || p.Public == nil { + return false + } + return *p.Public +} + +// GetSource returns the Source field. +func (p *PagesUpdate) GetSource() *PagesSource { + if p == nil { + return nil + } + return p.Source +} + +// GetCurrentUserCanApprove returns the CurrentUserCanApprove field if it's non-nil, zero value otherwise. +func (p *PendingDeployment) GetCurrentUserCanApprove() bool { + if p == nil || p.CurrentUserCanApprove == nil { + return false + } + return *p.CurrentUserCanApprove +} + +// GetEnvironment returns the Environment field. +func (p *PendingDeployment) GetEnvironment() *PendingDeploymentEnvironment { + if p == nil { + return nil + } + return p.Environment +} + +// GetWaitTimer returns the WaitTimer field if it's non-nil, zero value otherwise. +func (p *PendingDeployment) GetWaitTimer() int64 { + if p == nil || p.WaitTimer == nil { + return 0 + } + return *p.WaitTimer +} + +// GetWaitTimerStartedAt returns the WaitTimerStartedAt field if it's non-nil, zero value otherwise. +func (p *PendingDeployment) GetWaitTimerStartedAt() Timestamp { + if p == nil || p.WaitTimerStartedAt == nil { + return Timestamp{} + } + return *p.WaitTimerStartedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PendingDeploymentEnvironment) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PendingDeploymentEnvironment) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PendingDeploymentEnvironment) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *PendingDeploymentEnvironment) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PendingDeploymentEnvironment) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetAccessGrantedAt returns the AccessGrantedAt field if it's non-nil, zero value otherwise. +func (p *PersonalAccessToken) GetAccessGrantedAt() Timestamp { + if p == nil || p.AccessGrantedAt == nil { + return Timestamp{} + } + return *p.AccessGrantedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PersonalAccessToken) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetOwner returns the Owner field. +func (p *PersonalAccessToken) GetOwner() *User { + if p == nil { + return nil + } + return p.Owner +} + +// GetPermissions returns the Permissions field. +func (p *PersonalAccessToken) GetPermissions() *PersonalAccessTokenPermissions { + if p == nil { + return nil + } + return p.Permissions +} + +// GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise. +func (p *PersonalAccessToken) GetRepositoriesURL() string { + if p == nil || p.RepositoriesURL == nil { + return "" + } + return *p.RepositoriesURL +} + +// GetRepositorySelection returns the RepositorySelection field if it's non-nil, zero value otherwise. +func (p *PersonalAccessToken) GetRepositorySelection() string { + if p == nil || p.RepositorySelection == nil { + return "" + } + return *p.RepositorySelection +} + +// GetTokenExpired returns the TokenExpired field if it's non-nil, zero value otherwise. +func (p *PersonalAccessToken) GetTokenExpired() bool { + if p == nil || p.TokenExpired == nil { + return false + } + return *p.TokenExpired +} + +// GetTokenExpiresAt returns the TokenExpiresAt field if it's non-nil, zero value otherwise. +func (p *PersonalAccessToken) GetTokenExpiresAt() Timestamp { + if p == nil || p.TokenExpiresAt == nil { + return Timestamp{} + } + return *p.TokenExpiresAt +} + +// GetTokenLastUsedAt returns the TokenLastUsedAt field if it's non-nil, zero value otherwise. +func (p *PersonalAccessToken) GetTokenLastUsedAt() Timestamp { + if p == nil || p.TokenLastUsedAt == nil { + return Timestamp{} + } + return *p.TokenLastUsedAt +} + +// GetOrg returns the Org map if it's non-nil, an empty map otherwise. +func (p *PersonalAccessTokenPermissions) GetOrg() map[string]string { + if p == nil || p.Org == nil { + return map[string]string{} + } + return p.Org +} + +// GetOther returns the Other map if it's non-nil, an empty map otherwise. +func (p *PersonalAccessTokenPermissions) GetOther() map[string]string { + if p == nil || p.Other == nil { + return map[string]string{} + } + return p.Other +} + +// GetRepo returns the Repo map if it's non-nil, an empty map otherwise. +func (p *PersonalAccessTokenPermissions) GetRepo() map[string]string { + if p == nil || p.Repo == nil { + return map[string]string{} + } + return p.Repo +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PersonalAccessTokenRequest) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PersonalAccessTokenRequest) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetOrg returns the Org field. +func (p *PersonalAccessTokenRequest) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetOwner returns the Owner field. +func (p *PersonalAccessTokenRequest) GetOwner() *User { + if p == nil { + return nil + } + return p.Owner +} + +// GetPermissionsAdded returns the PermissionsAdded field. +func (p *PersonalAccessTokenRequest) GetPermissionsAdded() *PersonalAccessTokenPermissions { + if p == nil { + return nil + } + return p.PermissionsAdded +} + +// GetPermissionsResult returns the PermissionsResult field. +func (p *PersonalAccessTokenRequest) GetPermissionsResult() *PersonalAccessTokenPermissions { + if p == nil { + return nil + } + return p.PermissionsResult +} + +// GetPermissionsUpgraded returns the PermissionsUpgraded field. +func (p *PersonalAccessTokenRequest) GetPermissionsUpgraded() *PersonalAccessTokenPermissions { + if p == nil { + return nil + } + return p.PermissionsUpgraded +} + +// GetRepositoryCount returns the RepositoryCount field if it's non-nil, zero value otherwise. +func (p *PersonalAccessTokenRequest) GetRepositoryCount() int64 { + if p == nil || p.RepositoryCount == nil { + return 0 + } + return *p.RepositoryCount +} + +// GetRepositorySelection returns the RepositorySelection field if it's non-nil, zero value otherwise. +func (p *PersonalAccessTokenRequest) GetRepositorySelection() string { + if p == nil || p.RepositorySelection == nil { + return "" + } + return *p.RepositorySelection +} + +// GetTokenExpired returns the TokenExpired field if it's non-nil, zero value otherwise. +func (p *PersonalAccessTokenRequest) GetTokenExpired() bool { + if p == nil || p.TokenExpired == nil { + return false + } + return *p.TokenExpired +} + +// GetTokenExpiresAt returns the TokenExpiresAt field if it's non-nil, zero value otherwise. +func (p *PersonalAccessTokenRequest) GetTokenExpiresAt() Timestamp { + if p == nil || p.TokenExpiresAt == nil { + return Timestamp{} + } + return *p.TokenExpiresAt +} + +// GetTokenLastUsedAt returns the TokenLastUsedAt field if it's non-nil, zero value otherwise. +func (p *PersonalAccessTokenRequest) GetTokenLastUsedAt() Timestamp { + if p == nil || p.TokenLastUsedAt == nil { + return Timestamp{} + } + return *p.TokenLastUsedAt +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PersonalAccessTokenRequestEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetInstallation returns the Installation field. +func (p *PersonalAccessTokenRequestEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *PersonalAccessTokenRequestEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetPersonalAccessTokenRequest returns the PersonalAccessTokenRequest field. +func (p *PersonalAccessTokenRequestEvent) GetPersonalAccessTokenRequest() *PersonalAccessTokenRequest { + if p == nil { + return nil + } + return p.PersonalAccessTokenRequest +} + +// GetSender returns the Sender field. +func (p *PersonalAccessTokenRequestEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetHook returns the Hook field. +func (p *PingEvent) GetHook() *Hook { + if p == nil { + return nil + } + return p.Hook +} + +// GetHookID returns the HookID field if it's non-nil, zero value otherwise. +func (p *PingEvent) GetHookID() int64 { + if p == nil || p.HookID == nil { + return 0 + } + return *p.HookID +} + +// GetInstallation returns the Installation field. +func (p *PingEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *PingEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetRepo returns the Repo field. +func (p *PingEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PingEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetZen returns the Zen field if it's non-nil, zero value otherwise. +func (p *PingEvent) GetZen() string { + if p == nil || p.Zen == nil { + return "" + } + return *p.Zen +} + +// GetCollaborators returns the Collaborators field if it's non-nil, zero value otherwise. +func (p *Plan) GetCollaborators() int { + if p == nil || p.Collaborators == nil { + return 0 + } + return *p.Collaborators +} + +// GetFilledSeats returns the FilledSeats field if it's non-nil, zero value otherwise. +func (p *Plan) GetFilledSeats() int { + if p == nil || p.FilledSeats == nil { + return 0 + } + return *p.FilledSeats +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *Plan) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetPrivateRepos returns the PrivateRepos field if it's non-nil, zero value otherwise. +func (p *Plan) GetPrivateRepos() int64 { + if p == nil || p.PrivateRepos == nil { + return 0 + } + return *p.PrivateRepos +} + +// GetSeats returns the Seats field if it's non-nil, zero value otherwise. +func (p *Plan) GetSeats() int { + if p == nil || p.Seats == nil { + return 0 + } + return *p.Seats +} + +// GetSpace returns the Space field if it's non-nil, zero value otherwise. +func (p *Plan) GetSpace() int { + if p == nil || p.Space == nil { + return 0 + } + return *p.Space +} + +// GetConfigURL returns the ConfigURL field if it's non-nil, zero value otherwise. +func (p *PreReceiveHook) GetConfigURL() string { + if p == nil || p.ConfigURL == nil { + return "" + } + return *p.ConfigURL +} + +// GetEnforcement returns the Enforcement field if it's non-nil, zero value otherwise. +func (p *PreReceiveHook) GetEnforcement() string { + if p == nil || p.Enforcement == nil { + return "" + } + return *p.Enforcement +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PreReceiveHook) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PreReceiveHook) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetHRef returns the HRef field if it's non-nil, zero value otherwise. +func (p *PRLink) GetHRef() string { + if p == nil || p.HRef == nil { + return "" + } + return *p.HRef +} + +// GetComments returns the Comments field. +func (p *PRLinks) GetComments() *PRLink { + if p == nil { + return nil + } + return p.Comments +} + +// GetCommits returns the Commits field. +func (p *PRLinks) GetCommits() *PRLink { + if p == nil { + return nil + } + return p.Commits +} + +// GetHTML returns the HTML field. +func (p *PRLinks) GetHTML() *PRLink { + if p == nil { + return nil + } + return p.HTML +} + +// GetIssue returns the Issue field. +func (p *PRLinks) GetIssue() *PRLink { + if p == nil { + return nil + } + return p.Issue +} + +// GetReviewComment returns the ReviewComment field. +func (p *PRLinks) GetReviewComment() *PRLink { + if p == nil { + return nil + } + return p.ReviewComment +} + +// GetReviewComments returns the ReviewComments field. +func (p *PRLinks) GetReviewComments() *PRLink { + if p == nil { + return nil + } + return p.ReviewComments +} + +// GetSelf returns the Self field. +func (p *PRLinks) GetSelf() *PRLink { + if p == nil { + return nil + } + return p.Self +} + +// GetStatuses returns the Statuses field. +func (p *PRLinks) GetStatuses() *PRLink { + if p == nil { + return nil + } + return p.Statuses +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (p *ProjectBody) GetFrom() string { + if p == nil || p.From == nil { + return "" + } + return *p.From +} + +// GetNote returns the Note field. +func (p *ProjectCardChange) GetNote() *ProjectCardNote { + if p == nil { + return nil + } + return p.Note +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (p *ProjectCardNote) GetFrom() string { + if p == nil || p.From == nil { + return "" + } + return *p.From +} + +// GetBody returns the Body field. +func (p *ProjectChange) GetBody() *ProjectBody { + if p == nil { + return nil + } + return p.Body +} + +// GetName returns the Name field. +func (p *ProjectChange) GetName() *ProjectName { + if p == nil { + return nil + } + return p.Name +} + +// GetName returns the Name field. +func (p *ProjectColumnChange) GetName() *ProjectColumnName { + if p == nil { + return nil + } + return p.Name +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (p *ProjectColumnName) GetFrom() string { + if p == nil || p.From == nil { + return "" + } + return *p.From +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (p *ProjectName) GetFrom() string { + if p == nil || p.From == nil { + return "" + } + return *p.From +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetClosedAt() Timestamp { + if p == nil || p.ClosedAt == nil { + return Timestamp{} + } + return *p.ClosedAt +} + +// GetColumnsURL returns the ColumnsURL field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetColumnsURL() string { + if p == nil || p.ColumnsURL == nil { + return "" + } + return *p.ColumnsURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetCreator returns the Creator field. +func (p *ProjectV2) GetCreator() *User { + if p == nil { + return nil + } + return p.Creator +} + +// GetDeletedAt returns the DeletedAt field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetDeletedAt() Timestamp { + if p == nil || p.DeletedAt == nil { + return Timestamp{} + } + return *p.DeletedAt +} + +// GetDeletedBy returns the DeletedBy field. +func (p *ProjectV2) GetDeletedBy() *User { + if p == nil { + return nil + } + return p.DeletedBy +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetDescription() string { + if p == nil || p.Description == nil { + return "" + } + return *p.Description +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetNumber() int { + if p == nil || p.Number == nil { + return 0 + } + return *p.Number +} + +// GetOrganizationPermission returns the OrganizationPermission field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetOrganizationPermission() string { + if p == nil || p.OrganizationPermission == nil { + return "" + } + return *p.OrganizationPermission +} + +// GetOwner returns the Owner field. +func (p *ProjectV2) GetOwner() *User { + if p == nil { + return nil + } + return p.Owner +} + +// GetOwnerURL returns the OwnerURL field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetOwnerURL() string { + if p == nil || p.OwnerURL == nil { + return "" + } + return *p.OwnerURL +} + +// GetPrivate returns the Private field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetPrivate() bool { + if p == nil || p.Private == nil { + return false + } + return *p.Private +} + +// GetPublic returns the Public field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetPublic() bool { + if p == nil || p.Public == nil { + return false + } + return *p.Public +} + +// GetShortDescription returns the ShortDescription field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetShortDescription() string { + if p == nil || p.ShortDescription == nil { + return "" + } + return *p.ShortDescription +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetTitle() string { + if p == nil || p.Title == nil { + return "" + } + return *p.Title +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *ProjectV2Event) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetInstallation returns the Installation field. +func (p *ProjectV2Event) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *ProjectV2Event) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetProjectsV2 returns the ProjectsV2 field. +func (p *ProjectV2Event) GetProjectsV2() *ProjectV2 { + if p == nil { + return nil + } + return p.ProjectsV2 +} + +// GetSender returns the Sender field. +func (p *ProjectV2Event) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetArchivedAt returns the ArchivedAt field if it's non-nil, zero value otherwise. +func (p *ProjectV2Item) GetArchivedAt() Timestamp { + if p == nil || p.ArchivedAt == nil { + return Timestamp{} + } + return *p.ArchivedAt +} + +// GetContentNodeID returns the ContentNodeID field if it's non-nil, zero value otherwise. +func (p *ProjectV2Item) GetContentNodeID() string { + if p == nil || p.ContentNodeID == nil { + return "" + } + return *p.ContentNodeID +} + +// GetContentType returns the ContentType field if it's non-nil, zero value otherwise. +func (p *ProjectV2Item) GetContentType() string { + if p == nil || p.ContentType == nil { + return "" + } + return *p.ContentType +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *ProjectV2Item) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetCreator returns the Creator field. +func (p *ProjectV2Item) GetCreator() *User { + if p == nil { + return nil + } + return p.Creator +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *ProjectV2Item) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *ProjectV2Item) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetProjectNodeID returns the ProjectNodeID field if it's non-nil, zero value otherwise. +func (p *ProjectV2Item) GetProjectNodeID() string { + if p == nil || p.ProjectNodeID == nil { + return "" + } + return *p.ProjectNodeID +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *ProjectV2Item) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetArchivedAt returns the ArchivedAt field. +func (p *ProjectV2ItemChange) GetArchivedAt() *ArchivedAt { + if p == nil { + return nil + } + return p.ArchivedAt +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *ProjectV2ItemEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetChanges returns the Changes field. +func (p *ProjectV2ItemEvent) GetChanges() *ProjectV2ItemChange { + if p == nil { + return nil + } + return p.Changes +} + +// GetInstallation returns the Installation field. +func (p *ProjectV2ItemEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *ProjectV2ItemEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetProjectV2Item returns the ProjectV2Item field. +func (p *ProjectV2ItemEvent) GetProjectV2Item() *ProjectV2Item { + if p == nil { + return nil + } + return p.ProjectV2Item +} + +// GetSender returns the Sender field. +func (p *ProjectV2ItemEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetAllowDeletions returns the AllowDeletions field. +func (p *Protection) GetAllowDeletions() *AllowDeletions { + if p == nil { + return nil + } + return p.AllowDeletions +} + +// GetAllowForcePushes returns the AllowForcePushes field. +func (p *Protection) GetAllowForcePushes() *AllowForcePushes { + if p == nil { + return nil + } + return p.AllowForcePushes +} + +// GetAllowForkSyncing returns the AllowForkSyncing field. +func (p *Protection) GetAllowForkSyncing() *AllowForkSyncing { + if p == nil { + return nil + } + return p.AllowForkSyncing +} + +// GetBlockCreations returns the BlockCreations field. +func (p *Protection) GetBlockCreations() *BlockCreations { + if p == nil { + return nil + } + return p.BlockCreations +} + +// GetEnforceAdmins returns the EnforceAdmins field. +func (p *Protection) GetEnforceAdmins() *AdminEnforcement { + if p == nil { + return nil + } + return p.EnforceAdmins +} + +// GetLockBranch returns the LockBranch field. +func (p *Protection) GetLockBranch() *LockBranch { + if p == nil { + return nil + } + return p.LockBranch +} + +// GetRequiredConversationResolution returns the RequiredConversationResolution field. +func (p *Protection) GetRequiredConversationResolution() *RequiredConversationResolution { + if p == nil { + return nil + } + return p.RequiredConversationResolution +} + +// GetRequiredPullRequestReviews returns the RequiredPullRequestReviews field. +func (p *Protection) GetRequiredPullRequestReviews() *PullRequestReviewsEnforcement { + if p == nil { + return nil + } + return p.RequiredPullRequestReviews +} + +// GetRequiredSignatures returns the RequiredSignatures field. +func (p *Protection) GetRequiredSignatures() *SignaturesProtectedBranch { + if p == nil { + return nil + } + return p.RequiredSignatures +} + +// GetRequiredStatusChecks returns the RequiredStatusChecks field. +func (p *Protection) GetRequiredStatusChecks() *RequiredStatusChecks { + if p == nil { + return nil + } + return p.RequiredStatusChecks +} + +// GetRequireLinearHistory returns the RequireLinearHistory field. +func (p *Protection) GetRequireLinearHistory() *RequireLinearHistory { + if p == nil { + return nil + } + return p.RequireLinearHistory +} + +// GetRestrictions returns the Restrictions field. +func (p *Protection) GetRestrictions() *BranchRestrictions { + if p == nil { + return nil + } + return p.Restrictions +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *Protection) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetAdminEnforced returns the AdminEnforced field. +func (p *ProtectionChanges) GetAdminEnforced() *AdminEnforcedChanges { + if p == nil { + return nil + } + return p.AdminEnforced +} + +// GetAllowDeletionsEnforcementLevel returns the AllowDeletionsEnforcementLevel field. +func (p *ProtectionChanges) GetAllowDeletionsEnforcementLevel() *AllowDeletionsEnforcementLevelChanges { + if p == nil { + return nil + } + return p.AllowDeletionsEnforcementLevel +} + +// GetAuthorizedActorNames returns the AuthorizedActorNames field. +func (p *ProtectionChanges) GetAuthorizedActorNames() *AuthorizedActorNames { + if p == nil { + return nil + } + return p.AuthorizedActorNames +} + +// GetAuthorizedActorsOnly returns the AuthorizedActorsOnly field. +func (p *ProtectionChanges) GetAuthorizedActorsOnly() *AuthorizedActorsOnly { + if p == nil { + return nil + } + return p.AuthorizedActorsOnly +} + +// GetAuthorizedDismissalActorsOnly returns the AuthorizedDismissalActorsOnly field. +func (p *ProtectionChanges) GetAuthorizedDismissalActorsOnly() *AuthorizedDismissalActorsOnlyChanges { + if p == nil { + return nil + } + return p.AuthorizedDismissalActorsOnly +} + +// GetCreateProtected returns the CreateProtected field. +func (p *ProtectionChanges) GetCreateProtected() *CreateProtectedChanges { + if p == nil { + return nil + } + return p.CreateProtected +} + +// GetDismissStaleReviewsOnPush returns the DismissStaleReviewsOnPush field. +func (p *ProtectionChanges) GetDismissStaleReviewsOnPush() *DismissStaleReviewsOnPushChanges { + if p == nil { + return nil + } + return p.DismissStaleReviewsOnPush +} + +// GetLinearHistoryRequirementEnforcementLevel returns the LinearHistoryRequirementEnforcementLevel field. +func (p *ProtectionChanges) GetLinearHistoryRequirementEnforcementLevel() *LinearHistoryRequirementEnforcementLevelChanges { + if p == nil { + return nil + } + return p.LinearHistoryRequirementEnforcementLevel +} + +// GetPullRequestReviewsEnforcementLevel returns the PullRequestReviewsEnforcementLevel field. +func (p *ProtectionChanges) GetPullRequestReviewsEnforcementLevel() *PullRequestReviewsEnforcementLevelChanges { + if p == nil { + return nil + } + return p.PullRequestReviewsEnforcementLevel +} + +// GetRequireCodeOwnerReview returns the RequireCodeOwnerReview field. +func (p *ProtectionChanges) GetRequireCodeOwnerReview() *RequireCodeOwnerReviewChanges { + if p == nil { + return nil + } + return p.RequireCodeOwnerReview +} + +// GetRequiredConversationResolutionLevel returns the RequiredConversationResolutionLevel field. +func (p *ProtectionChanges) GetRequiredConversationResolutionLevel() *RequiredConversationResolutionLevelChanges { + if p == nil { + return nil + } + return p.RequiredConversationResolutionLevel +} + +// GetRequiredDeploymentsEnforcementLevel returns the RequiredDeploymentsEnforcementLevel field. +func (p *ProtectionChanges) GetRequiredDeploymentsEnforcementLevel() *RequiredDeploymentsEnforcementLevelChanges { + if p == nil { + return nil + } + return p.RequiredDeploymentsEnforcementLevel +} + +// GetRequiredStatusChecks returns the RequiredStatusChecks field. +func (p *ProtectionChanges) GetRequiredStatusChecks() *RequiredStatusChecksChanges { + if p == nil { + return nil + } + return p.RequiredStatusChecks +} + +// GetRequiredStatusChecksEnforcementLevel returns the RequiredStatusChecksEnforcementLevel field. +func (p *ProtectionChanges) GetRequiredStatusChecksEnforcementLevel() *RequiredStatusChecksEnforcementLevelChanges { + if p == nil { + return nil + } + return p.RequiredStatusChecksEnforcementLevel +} + +// GetSignatureRequirementEnforcementLevel returns the SignatureRequirementEnforcementLevel field. +func (p *ProtectionChanges) GetSignatureRequirementEnforcementLevel() *SignatureRequirementEnforcementLevelChanges { + if p == nil { + return nil + } + return p.SignatureRequirementEnforcementLevel +} + +// GetAllowDeletions returns the AllowDeletions field if it's non-nil, zero value otherwise. +func (p *ProtectionRequest) GetAllowDeletions() bool { + if p == nil || p.AllowDeletions == nil { + return false + } + return *p.AllowDeletions +} + +// GetAllowForcePushes returns the AllowForcePushes field if it's non-nil, zero value otherwise. +func (p *ProtectionRequest) GetAllowForcePushes() bool { + if p == nil || p.AllowForcePushes == nil { + return false + } + return *p.AllowForcePushes +} + +// GetAllowForkSyncing returns the AllowForkSyncing field if it's non-nil, zero value otherwise. +func (p *ProtectionRequest) GetAllowForkSyncing() bool { + if p == nil || p.AllowForkSyncing == nil { + return false + } + return *p.AllowForkSyncing +} + +// GetBlockCreations returns the BlockCreations field if it's non-nil, zero value otherwise. +func (p *ProtectionRequest) GetBlockCreations() bool { + if p == nil || p.BlockCreations == nil { + return false + } + return *p.BlockCreations +} + +// GetLockBranch returns the LockBranch field if it's non-nil, zero value otherwise. +func (p *ProtectionRequest) GetLockBranch() bool { + if p == nil || p.LockBranch == nil { + return false + } + return *p.LockBranch +} + +// GetRequiredConversationResolution returns the RequiredConversationResolution field if it's non-nil, zero value otherwise. +func (p *ProtectionRequest) GetRequiredConversationResolution() bool { + if p == nil || p.RequiredConversationResolution == nil { + return false + } + return *p.RequiredConversationResolution +} + +// GetRequiredPullRequestReviews returns the RequiredPullRequestReviews field. +func (p *ProtectionRequest) GetRequiredPullRequestReviews() *PullRequestReviewsEnforcementRequest { + if p == nil { + return nil + } + return p.RequiredPullRequestReviews +} + +// GetRequiredStatusChecks returns the RequiredStatusChecks field. +func (p *ProtectionRequest) GetRequiredStatusChecks() *RequiredStatusChecks { + if p == nil { + return nil + } + return p.RequiredStatusChecks +} + +// GetRequireLinearHistory returns the RequireLinearHistory field if it's non-nil, zero value otherwise. +func (p *ProtectionRequest) GetRequireLinearHistory() bool { + if p == nil || p.RequireLinearHistory == nil { + return false + } + return *p.RequireLinearHistory +} + +// GetRestrictions returns the Restrictions field. +func (p *ProtectionRequest) GetRestrictions() *BranchRestrictionsRequest { + if p == nil { + return nil + } + return p.Restrictions +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *ProtectionRule) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *ProtectionRule) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetPreventSelfReview returns the PreventSelfReview field if it's non-nil, zero value otherwise. +func (p *ProtectionRule) GetPreventSelfReview() bool { + if p == nil || p.PreventSelfReview == nil { + return false + } + return *p.PreventSelfReview +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (p *ProtectionRule) GetType() string { + if p == nil || p.Type == nil { + return "" + } + return *p.Type +} + +// GetWaitTimer returns the WaitTimer field if it's non-nil, zero value otherwise. +func (p *ProtectionRule) GetWaitTimer() int { + if p == nil || p.WaitTimer == nil { + return 0 + } + return *p.WaitTimer +} + +// GetInstallation returns the Installation field. +func (p *PublicEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *PublicEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetRepo returns the Repo field. +func (p *PublicEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PublicEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (p *PublicKey) GetKey() string { + if p == nil || p.Key == nil { + return "" + } + return *p.Key +} + +// GetKeyID returns the KeyID field if it's non-nil, zero value otherwise. +func (p *PublicKey) GetKeyID() string { + if p == nil || p.KeyID == nil { + return "" + } + return *p.KeyID +} + +// GetActiveLockReason returns the ActiveLockReason field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetActiveLockReason() string { + if p == nil || p.ActiveLockReason == nil { + return "" + } + return *p.ActiveLockReason +} + +// GetAdditions returns the Additions field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetAdditions() int { + if p == nil || p.Additions == nil { + return 0 + } + return *p.Additions +} + +// GetAssignee returns the Assignee field. +func (p *PullRequest) GetAssignee() *User { + if p == nil { + return nil + } + return p.Assignee +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetAuthorAssociation() string { + if p == nil || p.AuthorAssociation == nil { + return "" + } + return *p.AuthorAssociation +} + +// GetAutoMerge returns the AutoMerge field. +func (p *PullRequest) GetAutoMerge() *PullRequestAutoMerge { + if p == nil { + return nil + } + return p.AutoMerge +} + +// GetBase returns the Base field. +func (p *PullRequest) GetBase() *PullRequestBranch { + if p == nil { + return nil + } + return p.Base +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetChangedFiles returns the ChangedFiles field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetChangedFiles() int { + if p == nil || p.ChangedFiles == nil { + return 0 + } + return *p.ChangedFiles +} + +// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetClosedAt() Timestamp { + if p == nil || p.ClosedAt == nil { + return Timestamp{} + } + return *p.ClosedAt +} + +// GetComments returns the Comments field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetComments() int { + if p == nil || p.Comments == nil { + return 0 + } + return *p.Comments +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetCommentsURL() string { + if p == nil || p.CommentsURL == nil { + return "" + } + return *p.CommentsURL +} + +// GetCommits returns the Commits field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetCommits() int { + if p == nil || p.Commits == nil { + return 0 + } + return *p.Commits +} + +// GetCommitsURL returns the CommitsURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetCommitsURL() string { + if p == nil || p.CommitsURL == nil { + return "" + } + return *p.CommitsURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetDeletions() int { + if p == nil || p.Deletions == nil { + return 0 + } + return *p.Deletions +} + +// GetDiffURL returns the DiffURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetDiffURL() string { + if p == nil || p.DiffURL == nil { + return "" + } + return *p.DiffURL +} + +// GetDraft returns the Draft field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetDraft() bool { + if p == nil || p.Draft == nil { + return false + } + return *p.Draft +} + +// GetHead returns the Head field. +func (p *PullRequest) GetHead() *PullRequestBranch { + if p == nil { + return nil + } + return p.Head +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetIssueURL returns the IssueURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetIssueURL() string { + if p == nil || p.IssueURL == nil { + return "" + } + return *p.IssueURL +} + +// GetLinks returns the Links field. +func (p *PullRequest) GetLinks() *PRLinks { + if p == nil { + return nil + } + return p.Links +} + +// GetLocked returns the Locked field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetLocked() bool { + if p == nil || p.Locked == nil { + return false + } + return *p.Locked +} + +// GetMaintainerCanModify returns the MaintainerCanModify field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMaintainerCanModify() bool { + if p == nil || p.MaintainerCanModify == nil { + return false + } + return *p.MaintainerCanModify +} + +// GetMergeable returns the Mergeable field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMergeable() bool { + if p == nil || p.Mergeable == nil { + return false + } + return *p.Mergeable +} + +// GetMergeableState returns the MergeableState field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMergeableState() string { + if p == nil || p.MergeableState == nil { + return "" + } + return *p.MergeableState +} + +// GetMergeCommitSHA returns the MergeCommitSHA field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMergeCommitSHA() string { + if p == nil || p.MergeCommitSHA == nil { + return "" + } + return *p.MergeCommitSHA +} + +// GetMerged returns the Merged field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMerged() bool { + if p == nil || p.Merged == nil { + return false + } + return *p.Merged +} + +// GetMergedAt returns the MergedAt field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMergedAt() Timestamp { + if p == nil || p.MergedAt == nil { + return Timestamp{} + } + return *p.MergedAt +} + +// GetMergedBy returns the MergedBy field. +func (p *PullRequest) GetMergedBy() *User { + if p == nil { + return nil + } + return p.MergedBy +} + +// GetMilestone returns the Milestone field. +func (p *PullRequest) GetMilestone() *Milestone { + if p == nil { + return nil + } + return p.Milestone +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetNumber() int { + if p == nil || p.Number == nil { + return 0 + } + return *p.Number +} + +// GetPatchURL returns the PatchURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetPatchURL() string { + if p == nil || p.PatchURL == nil { + return "" + } + return *p.PatchURL +} + +// GetRebaseable returns the Rebaseable field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetRebaseable() bool { + if p == nil || p.Rebaseable == nil { + return false + } + return *p.Rebaseable +} + +// GetReviewComments returns the ReviewComments field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetReviewComments() int { + if p == nil || p.ReviewComments == nil { + return 0 + } + return *p.ReviewComments +} + +// GetReviewCommentsURL returns the ReviewCommentsURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetReviewCommentsURL() string { + if p == nil || p.ReviewCommentsURL == nil { + return "" + } + return *p.ReviewCommentsURL +} + +// GetReviewCommentURL returns the ReviewCommentURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetReviewCommentURL() string { + if p == nil || p.ReviewCommentURL == nil { + return "" + } + return *p.ReviewCommentURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetStatusesURL() string { + if p == nil || p.StatusesURL == nil { + return "" + } + return *p.StatusesURL +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetTitle() string { + if p == nil || p.Title == nil { + return "" + } + return *p.Title +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetUser returns the User field. +func (p *PullRequest) GetUser() *User { + if p == nil { + return nil + } + return p.User +} + +// GetCommitMessage returns the CommitMessage field if it's non-nil, zero value otherwise. +func (p *PullRequestAutoMerge) GetCommitMessage() string { + if p == nil || p.CommitMessage == nil { + return "" + } + return *p.CommitMessage +} + +// GetCommitTitle returns the CommitTitle field if it's non-nil, zero value otherwise. +func (p *PullRequestAutoMerge) GetCommitTitle() string { + if p == nil || p.CommitTitle == nil { + return "" + } + return *p.CommitTitle +} + +// GetEnabledBy returns the EnabledBy field. +func (p *PullRequestAutoMerge) GetEnabledBy() *User { + if p == nil { + return nil + } + return p.EnabledBy +} + +// GetMergeMethod returns the MergeMethod field if it's non-nil, zero value otherwise. +func (p *PullRequestAutoMerge) GetMergeMethod() string { + if p == nil || p.MergeMethod == nil { + return "" + } + return *p.MergeMethod +} + +// GetLabel returns the Label field if it's non-nil, zero value otherwise. +func (p *PullRequestBranch) GetLabel() string { + if p == nil || p.Label == nil { + return "" + } + return *p.Label +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (p *PullRequestBranch) GetRef() string { + if p == nil || p.Ref == nil { + return "" + } + return *p.Ref +} + +// GetRepo returns the Repo field. +func (p *PullRequestBranch) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (p *PullRequestBranch) GetSHA() string { + if p == nil || p.SHA == nil { + return "" + } + return *p.SHA +} + +// GetUser returns the User field. +func (p *PullRequestBranch) GetUser() *User { + if p == nil { + return nil + } + return p.User +} + +// GetExpectedHeadSHA returns the ExpectedHeadSHA field if it's non-nil, zero value otherwise. +func (p *PullRequestBranchUpdateOptions) GetExpectedHeadSHA() string { + if p == nil || p.ExpectedHeadSHA == nil { + return "" + } + return *p.ExpectedHeadSHA +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (p *PullRequestBranchUpdateResponse) GetMessage() string { + if p == nil || p.Message == nil { + return "" + } + return *p.Message +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PullRequestBranchUpdateResponse) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetAuthorAssociation() string { + if p == nil || p.AuthorAssociation == nil { + return "" + } + return *p.AuthorAssociation +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetCommitID() string { + if p == nil || p.CommitID == nil { + return "" + } + return *p.CommitID +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetDiffHunk returns the DiffHunk field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetDiffHunk() string { + if p == nil || p.DiffHunk == nil { + return "" + } + return *p.DiffHunk +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetInReplyTo returns the InReplyTo field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetInReplyTo() int64 { + if p == nil || p.InReplyTo == nil { + return 0 + } + return *p.InReplyTo +} + +// GetLine returns the Line field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetLine() int { + if p == nil || p.Line == nil { + return 0 + } + return *p.Line +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetOriginalCommitID returns the OriginalCommitID field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetOriginalCommitID() string { + if p == nil || p.OriginalCommitID == nil { + return "" + } + return *p.OriginalCommitID +} + +// GetOriginalLine returns the OriginalLine field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetOriginalLine() int { + if p == nil || p.OriginalLine == nil { + return 0 + } + return *p.OriginalLine +} + +// GetOriginalPosition returns the OriginalPosition field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetOriginalPosition() int { + if p == nil || p.OriginalPosition == nil { + return 0 + } + return *p.OriginalPosition +} + +// GetOriginalStartLine returns the OriginalStartLine field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetOriginalStartLine() int { + if p == nil || p.OriginalStartLine == nil { + return 0 + } + return *p.OriginalStartLine +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetPath() string { + if p == nil || p.Path == nil { + return "" + } + return *p.Path +} + +// GetPosition returns the Position field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetPosition() int { + if p == nil || p.Position == nil { + return 0 + } + return *p.Position +} + +// GetPullRequestReviewID returns the PullRequestReviewID field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetPullRequestReviewID() int64 { + if p == nil || p.PullRequestReviewID == nil { + return 0 + } + return *p.PullRequestReviewID +} + +// GetPullRequestURL returns the PullRequestURL field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetPullRequestURL() string { + if p == nil || p.PullRequestURL == nil { + return "" + } + return *p.PullRequestURL +} + +// GetReactions returns the Reactions field. +func (p *PullRequestComment) GetReactions() *Reactions { + if p == nil { + return nil + } + return p.Reactions +} + +// GetSide returns the Side field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetSide() string { + if p == nil || p.Side == nil { + return "" + } + return *p.Side +} + +// GetStartLine returns the StartLine field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetStartLine() int { + if p == nil || p.StartLine == nil { + return 0 + } + return *p.StartLine +} + +// GetStartSide returns the StartSide field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetStartSide() string { + if p == nil || p.StartSide == nil { + return "" + } + return *p.StartSide +} + +// GetSubjectType returns the SubjectType field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetSubjectType() string { + if p == nil || p.SubjectType == nil { + return "" + } + return *p.SubjectType +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetUser returns the User field. +func (p *PullRequestComment) GetUser() *User { + if p == nil { + return nil + } + return p.User +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PullRequestEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetAfter returns the After field if it's non-nil, zero value otherwise. +func (p *PullRequestEvent) GetAfter() string { + if p == nil || p.After == nil { + return "" + } + return *p.After +} + +// GetAssignee returns the Assignee field. +func (p *PullRequestEvent) GetAssignee() *User { + if p == nil { + return nil + } + return p.Assignee +} + +// GetBefore returns the Before field if it's non-nil, zero value otherwise. +func (p *PullRequestEvent) GetBefore() string { + if p == nil || p.Before == nil { + return "" + } + return *p.Before +} + +// GetChanges returns the Changes field. +func (p *PullRequestEvent) GetChanges() *EditChange { + if p == nil { + return nil + } + return p.Changes +} + +// GetInstallation returns the Installation field. +func (p *PullRequestEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetLabel returns the Label field. +func (p *PullRequestEvent) GetLabel() *Label { + if p == nil { + return nil + } + return p.Label +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (p *PullRequestEvent) GetNumber() int { + if p == nil || p.Number == nil { + return 0 + } + return *p.Number +} + +// GetOrganization returns the Organization field. +func (p *PullRequestEvent) GetOrganization() *Organization { + if p == nil { + return nil + } + return p.Organization +} + +// GetPerformedViaGithubApp returns the PerformedViaGithubApp field. +func (p *PullRequestEvent) GetPerformedViaGithubApp() *App { + if p == nil { + return nil + } + return p.PerformedViaGithubApp +} + +// GetPullRequest returns the PullRequest field. +func (p *PullRequestEvent) GetPullRequest() *PullRequest { + if p == nil { + return nil + } + return p.PullRequest +} + +// GetRepo returns the Repo field. +func (p *PullRequestEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetRequestedReviewer returns the RequestedReviewer field. +func (p *PullRequestEvent) GetRequestedReviewer() *User { + if p == nil { + return nil + } + return p.RequestedReviewer +} + +// GetRequestedTeam returns the RequestedTeam field. +func (p *PullRequestEvent) GetRequestedTeam() *Team { + if p == nil { + return nil + } + return p.RequestedTeam +} + +// GetSender returns the Sender field. +func (p *PullRequestEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetDiffURL returns the DiffURL field if it's non-nil, zero value otherwise. +func (p *PullRequestLinks) GetDiffURL() string { + if p == nil || p.DiffURL == nil { + return "" + } + return *p.DiffURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PullRequestLinks) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetMergedAt returns the MergedAt field if it's non-nil, zero value otherwise. +func (p *PullRequestLinks) GetMergedAt() Timestamp { + if p == nil || p.MergedAt == nil { + return Timestamp{} + } + return *p.MergedAt +} + +// GetPatchURL returns the PatchURL field if it's non-nil, zero value otherwise. +func (p *PullRequestLinks) GetPatchURL() string { + if p == nil || p.PatchURL == nil { + return "" + } + return *p.PatchURL +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PullRequestLinks) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetMerged returns the Merged field if it's non-nil, zero value otherwise. +func (p *PullRequestMergeResult) GetMerged() bool { + if p == nil || p.Merged == nil { + return false + } + return *p.Merged +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (p *PullRequestMergeResult) GetMessage() string { + if p == nil || p.Message == nil { + return "" + } + return *p.Message +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (p *PullRequestMergeResult) GetSHA() string { + if p == nil || p.SHA == nil { + return "" + } + return *p.SHA +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetAuthorAssociation() string { + if p == nil || p.AuthorAssociation == nil { + return "" + } + return *p.AuthorAssociation +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetCommitID() string { + if p == nil || p.CommitID == nil { + return "" + } + return *p.CommitID +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetPullRequestURL returns the PullRequestURL field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetPullRequestURL() string { + if p == nil || p.PullRequestURL == nil { + return "" + } + return *p.PullRequestURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetSubmittedAt returns the SubmittedAt field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetSubmittedAt() Timestamp { + if p == nil || p.SubmittedAt == nil { + return Timestamp{} + } + return *p.SubmittedAt +} + +// GetUser returns the User field. +func (p *PullRequestReview) GetUser() *User { + if p == nil { + return nil + } + return p.User +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewCommentEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetChanges returns the Changes field. +func (p *PullRequestReviewCommentEvent) GetChanges() *EditChange { + if p == nil { + return nil + } + return p.Changes +} + +// GetComment returns the Comment field. +func (p *PullRequestReviewCommentEvent) GetComment() *PullRequestComment { + if p == nil { + return nil + } + return p.Comment +} + +// GetInstallation returns the Installation field. +func (p *PullRequestReviewCommentEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *PullRequestReviewCommentEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetPullRequest returns the PullRequest field. +func (p *PullRequestReviewCommentEvent) GetPullRequest() *PullRequest { + if p == nil { + return nil + } + return p.PullRequest +} + +// GetRepo returns the Repo field. +func (p *PullRequestReviewCommentEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PullRequestReviewCommentEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewDismissalRequest) GetMessage() string { + if p == nil || p.Message == nil { + return "" + } + return *p.Message +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetInstallation returns the Installation field. +func (p *PullRequestReviewEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrganization returns the Organization field. +func (p *PullRequestReviewEvent) GetOrganization() *Organization { + if p == nil { + return nil + } + return p.Organization +} + +// GetPullRequest returns the PullRequest field. +func (p *PullRequestReviewEvent) GetPullRequest() *PullRequest { + if p == nil { + return nil + } + return p.PullRequest +} + +// GetRepo returns the Repo field. +func (p *PullRequestReviewEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetReview returns the Review field. +func (p *PullRequestReviewEvent) GetReview() *PullRequestReview { + if p == nil { + return nil + } + return p.Review +} + +// GetSender returns the Sender field. +func (p *PullRequestReviewEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewRequest) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewRequest) GetCommitID() string { + if p == nil || p.CommitID == nil { + return "" + } + return *p.CommitID +} + +// GetEvent returns the Event field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewRequest) GetEvent() string { + if p == nil || p.Event == nil { + return "" + } + return *p.Event +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewRequest) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetBypassPullRequestAllowances returns the BypassPullRequestAllowances field. +func (p *PullRequestReviewsEnforcement) GetBypassPullRequestAllowances() *BypassPullRequestAllowances { + if p == nil { + return nil + } + return p.BypassPullRequestAllowances +} + +// GetDismissalRestrictions returns the DismissalRestrictions field. +func (p *PullRequestReviewsEnforcement) GetDismissalRestrictions() *DismissalRestrictions { + if p == nil { + return nil + } + return p.DismissalRestrictions +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewsEnforcementLevelChanges) GetFrom() string { + if p == nil || p.From == nil { + return "" + } + return *p.From +} + +// GetBypassPullRequestAllowancesRequest returns the BypassPullRequestAllowancesRequest field. +func (p *PullRequestReviewsEnforcementRequest) GetBypassPullRequestAllowancesRequest() *BypassPullRequestAllowancesRequest { + if p == nil { + return nil + } + return p.BypassPullRequestAllowancesRequest +} + +// GetDismissalRestrictionsRequest returns the DismissalRestrictionsRequest field. +func (p *PullRequestReviewsEnforcementRequest) GetDismissalRestrictionsRequest() *DismissalRestrictionsRequest { + if p == nil { + return nil + } + return p.DismissalRestrictionsRequest +} + +// GetRequireLastPushApproval returns the RequireLastPushApproval field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewsEnforcementRequest) GetRequireLastPushApproval() bool { + if p == nil || p.RequireLastPushApproval == nil { + return false + } + return *p.RequireLastPushApproval +} + +// GetBypassPullRequestAllowancesRequest returns the BypassPullRequestAllowancesRequest field. +func (p *PullRequestReviewsEnforcementUpdate) GetBypassPullRequestAllowancesRequest() *BypassPullRequestAllowancesRequest { + if p == nil { + return nil + } + return p.BypassPullRequestAllowancesRequest +} + +// GetDismissalRestrictionsRequest returns the DismissalRestrictionsRequest field. +func (p *PullRequestReviewsEnforcementUpdate) GetDismissalRestrictionsRequest() *DismissalRestrictionsRequest { + if p == nil { + return nil + } + return p.DismissalRestrictionsRequest +} + +// GetDismissStaleReviews returns the DismissStaleReviews field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewsEnforcementUpdate) GetDismissStaleReviews() bool { + if p == nil || p.DismissStaleReviews == nil { + return false + } + return *p.DismissStaleReviews +} + +// GetRequireCodeOwnerReviews returns the RequireCodeOwnerReviews field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewsEnforcementUpdate) GetRequireCodeOwnerReviews() bool { + if p == nil || p.RequireCodeOwnerReviews == nil { + return false + } + return *p.RequireCodeOwnerReviews +} + +// GetRequireLastPushApproval returns the RequireLastPushApproval field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewsEnforcementUpdate) GetRequireLastPushApproval() bool { + if p == nil || p.RequireLastPushApproval == nil { + return false + } + return *p.RequireLastPushApproval +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewThreadEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetInstallation returns the Installation field. +func (p *PullRequestReviewThreadEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *PullRequestReviewThreadEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetPullRequest returns the PullRequest field. +func (p *PullRequestReviewThreadEvent) GetPullRequest() *PullRequest { + if p == nil { + return nil + } + return p.PullRequest +} + +// GetRepo returns the Repo field. +func (p *PullRequestReviewThreadEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PullRequestReviewThreadEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetThread returns the Thread field. +func (p *PullRequestReviewThreadEvent) GetThread() *PullRequestThread { + if p == nil { + return nil + } + return p.Thread +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PullRequestTargetEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetAfter returns the After field if it's non-nil, zero value otherwise. +func (p *PullRequestTargetEvent) GetAfter() string { + if p == nil || p.After == nil { + return "" + } + return *p.After +} + +// GetAssignee returns the Assignee field. +func (p *PullRequestTargetEvent) GetAssignee() *User { + if p == nil { + return nil + } + return p.Assignee +} + +// GetBefore returns the Before field if it's non-nil, zero value otherwise. +func (p *PullRequestTargetEvent) GetBefore() string { + if p == nil || p.Before == nil { + return "" + } + return *p.Before +} + +// GetChanges returns the Changes field. +func (p *PullRequestTargetEvent) GetChanges() *EditChange { + if p == nil { + return nil + } + return p.Changes +} + +// GetInstallation returns the Installation field. +func (p *PullRequestTargetEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetLabel returns the Label field. +func (p *PullRequestTargetEvent) GetLabel() *Label { + if p == nil { + return nil + } + return p.Label +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (p *PullRequestTargetEvent) GetNumber() int { + if p == nil || p.Number == nil { + return 0 + } + return *p.Number +} + +// GetOrganization returns the Organization field. +func (p *PullRequestTargetEvent) GetOrganization() *Organization { + if p == nil { + return nil + } + return p.Organization +} + +// GetPerformedViaGithubApp returns the PerformedViaGithubApp field. +func (p *PullRequestTargetEvent) GetPerformedViaGithubApp() *App { + if p == nil { + return nil + } + return p.PerformedViaGithubApp +} + +// GetPullRequest returns the PullRequest field. +func (p *PullRequestTargetEvent) GetPullRequest() *PullRequest { + if p == nil { + return nil + } + return p.PullRequest +} + +// GetRepo returns the Repo field. +func (p *PullRequestTargetEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetRequestedReviewer returns the RequestedReviewer field. +func (p *PullRequestTargetEvent) GetRequestedReviewer() *User { + if p == nil { + return nil + } + return p.RequestedReviewer +} + +// GetRequestedTeam returns the RequestedTeam field. +func (p *PullRequestTargetEvent) GetRequestedTeam() *Team { + if p == nil { + return nil + } + return p.RequestedTeam +} + +// GetSender returns the Sender field. +func (p *PullRequestTargetEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PullRequestThread) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *PullRequestThread) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetMergablePulls returns the MergablePulls field if it's non-nil, zero value otherwise. +func (p *PullStats) GetMergablePulls() int { + if p == nil || p.MergablePulls == nil { + return 0 + } + return *p.MergablePulls +} + +// GetMergedPulls returns the MergedPulls field if it's non-nil, zero value otherwise. +func (p *PullStats) GetMergedPulls() int { + if p == nil || p.MergedPulls == nil { + return 0 + } + return *p.MergedPulls +} + +// GetTotalPulls returns the TotalPulls field if it's non-nil, zero value otherwise. +func (p *PullStats) GetTotalPulls() int { + if p == nil || p.TotalPulls == nil { + return 0 + } + return *p.TotalPulls +} + +// GetUnmergablePulls returns the UnmergablePulls field if it's non-nil, zero value otherwise. +func (p *PullStats) GetUnmergablePulls() int { + if p == nil || p.UnmergablePulls == nil { + return 0 + } + return *p.UnmergablePulls +} + +// GetCommits returns the Commits field if it's non-nil, zero value otherwise. +func (p *PunchCard) GetCommits() int { + if p == nil || p.Commits == nil { + return 0 + } + return *p.Commits +} + +// GetDay returns the Day field if it's non-nil, zero value otherwise. +func (p *PunchCard) GetDay() int { + if p == nil || p.Day == nil { + return 0 + } + return *p.Day +} + +// GetHour returns the Hour field if it's non-nil, zero value otherwise. +func (p *PunchCard) GetHour() int { + if p == nil || p.Hour == nil { + return 0 + } + return *p.Hour +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetAfter returns the After field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetAfter() string { + if p == nil || p.After == nil { + return "" + } + return *p.After +} + +// GetBaseRef returns the BaseRef field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetBaseRef() string { + if p == nil || p.BaseRef == nil { + return "" + } + return *p.BaseRef +} + +// GetBefore returns the Before field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetBefore() string { + if p == nil || p.Before == nil { + return "" + } + return *p.Before +} + +// GetCommits returns the Commits slice if it's non-nil, nil otherwise. +func (p *PushEvent) GetCommits() []*HeadCommit { + if p == nil || p.Commits == nil { + return nil + } + return p.Commits +} + +// GetCompare returns the Compare field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetCompare() string { + if p == nil || p.Compare == nil { + return "" + } + return *p.Compare +} + +// GetCreated returns the Created field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetCreated() bool { + if p == nil || p.Created == nil { + return false + } + return *p.Created +} + +// GetDeleted returns the Deleted field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetDeleted() bool { + if p == nil || p.Deleted == nil { + return false + } + return *p.Deleted +} + +// GetDistinctSize returns the DistinctSize field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetDistinctSize() int { + if p == nil || p.DistinctSize == nil { + return 0 + } + return *p.DistinctSize +} + +// GetForced returns the Forced field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetForced() bool { + if p == nil || p.Forced == nil { + return false + } + return *p.Forced +} + +// GetHead returns the Head field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetHead() string { + if p == nil || p.Head == nil { + return "" + } + return *p.Head +} + +// GetHeadCommit returns the HeadCommit field. +func (p *PushEvent) GetHeadCommit() *HeadCommit { + if p == nil { + return nil + } + return p.HeadCommit +} + +// GetInstallation returns the Installation field. +func (p *PushEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrganization returns the Organization field. +func (p *PushEvent) GetOrganization() *Organization { + if p == nil { + return nil + } + return p.Organization +} + +// GetPusher returns the Pusher field. +func (p *PushEvent) GetPusher() *CommitAuthor { + if p == nil { + return nil + } + return p.Pusher +} + +// GetPushID returns the PushID field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetPushID() int64 { + if p == nil || p.PushID == nil { + return 0 + } + return *p.PushID +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetRef() string { + if p == nil || p.Ref == nil { + return "" + } + return *p.Ref +} + +// GetRepo returns the Repo field. +func (p *PushEvent) GetRepo() *PushEventRepository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PushEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetSize() int { + if p == nil || p.Size == nil { + return 0 + } + return *p.Size +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (p *PushEventRepoOwner) GetEmail() string { + if p == nil || p.Email == nil { + return "" + } + return *p.Email +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PushEventRepoOwner) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetArchived returns the Archived field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetArchived() bool { + if p == nil || p.Archived == nil { + return false + } + return *p.Archived +} + +// GetArchiveURL returns the ArchiveURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetArchiveURL() string { + if p == nil || p.ArchiveURL == nil { + return "" + } + return *p.ArchiveURL +} + +// GetCloneURL returns the CloneURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetCloneURL() string { + if p == nil || p.CloneURL == nil { + return "" + } + return *p.CloneURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetDefaultBranch returns the DefaultBranch field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetDefaultBranch() string { + if p == nil || p.DefaultBranch == nil { + return "" + } + return *p.DefaultBranch +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetDescription() string { + if p == nil || p.Description == nil { + return "" + } + return *p.Description +} + +// GetDisabled returns the Disabled field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetDisabled() bool { + if p == nil || p.Disabled == nil { + return false + } + return *p.Disabled +} + +// GetFork returns the Fork field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetFork() bool { + if p == nil || p.Fork == nil { + return false + } + return *p.Fork +} + +// GetForksCount returns the ForksCount field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetForksCount() int { + if p == nil || p.ForksCount == nil { + return 0 + } + return *p.ForksCount +} + +// GetFullName returns the FullName field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetFullName() string { + if p == nil || p.FullName == nil { + return "" + } + return *p.FullName +} + +// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetGitURL() string { + if p == nil || p.GitURL == nil { + return "" + } + return *p.GitURL +} + +// GetHasDownloads returns the HasDownloads field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHasDownloads() bool { + if p == nil || p.HasDownloads == nil { + return false + } + return *p.HasDownloads +} + +// GetHasIssues returns the HasIssues field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHasIssues() bool { + if p == nil || p.HasIssues == nil { + return false + } + return *p.HasIssues +} + +// GetHasPages returns the HasPages field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHasPages() bool { + if p == nil || p.HasPages == nil { + return false + } + return *p.HasPages +} + +// GetHasWiki returns the HasWiki field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHasWiki() bool { + if p == nil || p.HasWiki == nil { + return false + } + return *p.HasWiki +} + +// GetHomepage returns the Homepage field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHomepage() string { + if p == nil || p.Homepage == nil { + return "" + } + return *p.Homepage +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetLanguage returns the Language field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetLanguage() string { + if p == nil || p.Language == nil { + return "" + } + return *p.Language +} + +// GetMasterBranch returns the MasterBranch field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetMasterBranch() string { + if p == nil || p.MasterBranch == nil { + return "" + } + return *p.MasterBranch +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetOpenIssuesCount returns the OpenIssuesCount field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetOpenIssuesCount() int { + if p == nil || p.OpenIssuesCount == nil { + return 0 + } + return *p.OpenIssuesCount +} + +// GetOrganization returns the Organization field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetOrganization() string { + if p == nil || p.Organization == nil { + return "" + } + return *p.Organization +} + +// GetOwner returns the Owner field. +func (p *PushEventRepository) GetOwner() *User { + if p == nil { + return nil + } + return p.Owner +} + +// GetPrivate returns the Private field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetPrivate() bool { + if p == nil || p.Private == nil { + return false + } + return *p.Private +} + +// GetPullsURL returns the PullsURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetPullsURL() string { + if p == nil || p.PullsURL == nil { + return "" + } + return *p.PullsURL +} + +// GetPushedAt returns the PushedAt field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetPushedAt() Timestamp { + if p == nil || p.PushedAt == nil { + return Timestamp{} + } + return *p.PushedAt +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetSize() int { + if p == nil || p.Size == nil { + return 0 + } + return *p.Size +} + +// GetSSHURL returns the SSHURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetSSHURL() string { + if p == nil || p.SSHURL == nil { + return "" + } + return *p.SSHURL +} + +// GetStargazersCount returns the StargazersCount field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetStargazersCount() int { + if p == nil || p.StargazersCount == nil { + return 0 + } + return *p.StargazersCount +} + +// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetStatusesURL() string { + if p == nil || p.StatusesURL == nil { + return "" + } + return *p.StatusesURL +} + +// GetSVNURL returns the SVNURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetSVNURL() string { + if p == nil || p.SVNURL == nil { + return "" + } + return *p.SVNURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetWatchersCount returns the WatchersCount field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetWatchersCount() int { + if p == nil || p.WatchersCount == nil { + return 0 + } + return *p.WatchersCount +} + +// GetActionsRunnerRegistration returns the ActionsRunnerRegistration field. +func (r *RateLimits) GetActionsRunnerRegistration() *Rate { + if r == nil { + return nil + } + return r.ActionsRunnerRegistration +} + +// GetAuditLog returns the AuditLog field. +func (r *RateLimits) GetAuditLog() *Rate { + if r == nil { + return nil + } + return r.AuditLog +} + +// GetCodeScanningUpload returns the CodeScanningUpload field. +func (r *RateLimits) GetCodeScanningUpload() *Rate { + if r == nil { + return nil + } + return r.CodeScanningUpload +} + +// GetCodeSearch returns the CodeSearch field. +func (r *RateLimits) GetCodeSearch() *Rate { + if r == nil { + return nil + } + return r.CodeSearch +} + +// GetCore returns the Core field. +func (r *RateLimits) GetCore() *Rate { + if r == nil { + return nil + } + return r.Core +} + +// GetDependencySnapshots returns the DependencySnapshots field. +func (r *RateLimits) GetDependencySnapshots() *Rate { + if r == nil { + return nil + } + return r.DependencySnapshots +} + +// GetGraphQL returns the GraphQL field. +func (r *RateLimits) GetGraphQL() *Rate { + if r == nil { + return nil + } + return r.GraphQL +} + +// GetIntegrationManifest returns the IntegrationManifest field. +func (r *RateLimits) GetIntegrationManifest() *Rate { + if r == nil { + return nil + } + return r.IntegrationManifest +} + +// GetSCIM returns the SCIM field. +func (r *RateLimits) GetSCIM() *Rate { + if r == nil { + return nil + } + return r.SCIM +} + +// GetSearch returns the Search field. +func (r *RateLimits) GetSearch() *Rate { + if r == nil { + return nil + } + return r.Search +} + +// GetSourceImport returns the SourceImport field. +func (r *RateLimits) GetSourceImport() *Rate { + if r == nil { + return nil + } + return r.SourceImport +} + +// GetContent returns the Content field if it's non-nil, zero value otherwise. +func (r *Reaction) GetContent() string { + if r == nil || r.Content == nil { + return "" + } + return *r.Content +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *Reaction) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *Reaction) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetUser returns the User field. +func (r *Reaction) GetUser() *User { + if r == nil { + return nil + } + return r.User +} + +// GetConfused returns the Confused field if it's non-nil, zero value otherwise. +func (r *Reactions) GetConfused() int { + if r == nil || r.Confused == nil { + return 0 + } + return *r.Confused +} + +// GetEyes returns the Eyes field if it's non-nil, zero value otherwise. +func (r *Reactions) GetEyes() int { + if r == nil || r.Eyes == nil { + return 0 + } + return *r.Eyes +} + +// GetHeart returns the Heart field if it's non-nil, zero value otherwise. +func (r *Reactions) GetHeart() int { + if r == nil || r.Heart == nil { + return 0 + } + return *r.Heart +} + +// GetHooray returns the Hooray field if it's non-nil, zero value otherwise. +func (r *Reactions) GetHooray() int { + if r == nil || r.Hooray == nil { + return 0 + } + return *r.Hooray +} + +// GetLaugh returns the Laugh field if it's non-nil, zero value otherwise. +func (r *Reactions) GetLaugh() int { + if r == nil || r.Laugh == nil { + return 0 + } + return *r.Laugh +} + +// GetMinusOne returns the MinusOne field if it's non-nil, zero value otherwise. +func (r *Reactions) GetMinusOne() int { + if r == nil || r.MinusOne == nil { + return 0 + } + return *r.MinusOne +} + +// GetPlusOne returns the PlusOne field if it's non-nil, zero value otherwise. +func (r *Reactions) GetPlusOne() int { + if r == nil || r.PlusOne == nil { + return 0 + } + return *r.PlusOne +} + +// GetRocket returns the Rocket field if it's non-nil, zero value otherwise. +func (r *Reactions) GetRocket() int { + if r == nil || r.Rocket == nil { + return 0 + } + return *r.Rocket +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (r *Reactions) GetTotalCount() int { + if r == nil || r.TotalCount == nil { + return 0 + } + return *r.TotalCount +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *Reactions) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *Reference) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetObject returns the Object field. +func (r *Reference) GetObject() *GitObject { + if r == nil { + return nil + } + return r.Object +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (r *Reference) GetRef() string { + if r == nil || r.Ref == nil { + return "" + } + return *r.Ref +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *Reference) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (r *ReferencedWorkflow) GetPath() string { + if r == nil || r.Path == nil { + return "" + } + return *r.Path +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (r *ReferencedWorkflow) GetRef() string { + if r == nil || r.Ref == nil { + return "" + } + return *r.Ref +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (r *ReferencedWorkflow) GetSHA() string { + if r == nil || r.SHA == nil { + return "" + } + return *r.SHA +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (r *RegistrationToken) GetExpiresAt() Timestamp { + if r == nil || r.ExpiresAt == nil { + return Timestamp{} + } + return *r.ExpiresAt +} + +// GetToken returns the Token field if it's non-nil, zero value otherwise. +func (r *RegistrationToken) GetToken() string { + if r == nil || r.Token == nil { + return "" + } + return *r.Token +} + +// GetBrowserDownloadURL returns the BrowserDownloadURL field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetBrowserDownloadURL() string { + if r == nil || r.BrowserDownloadURL == nil { + return "" + } + return *r.BrowserDownloadURL +} + +// GetContentType returns the ContentType field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetContentType() string { + if r == nil || r.ContentType == nil { + return "" + } + return *r.ContentType +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetDownloadCount returns the DownloadCount field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetDownloadCount() int { + if r == nil || r.DownloadCount == nil { + return 0 + } + return *r.DownloadCount +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetLabel returns the Label field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetLabel() string { + if r == nil || r.Label == nil { + return "" + } + return *r.Label +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetSize() int { + if r == nil || r.Size == nil { + return 0 + } + return *r.Size +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetState() string { + if r == nil || r.State == nil { + return "" + } + return *r.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetUpdatedAt() Timestamp { + if r == nil || r.UpdatedAt == nil { + return Timestamp{} + } + return *r.UpdatedAt +} + +// GetUploader returns the Uploader field. +func (r *ReleaseAsset) GetUploader() *User { + if r == nil { + return nil + } + return r.Uploader +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (r *ReleaseEvent) GetAction() string { + if r == nil || r.Action == nil { + return "" + } + return *r.Action +} + +// GetInstallation returns the Installation field. +func (r *ReleaseEvent) GetInstallation() *Installation { + if r == nil { + return nil + } + return r.Installation +} + +// GetOrg returns the Org field. +func (r *ReleaseEvent) GetOrg() *Organization { + if r == nil { + return nil + } + return r.Org +} + +// GetRelease returns the Release field. +func (r *ReleaseEvent) GetRelease() *RepositoryRelease { + if r == nil { + return nil + } + return r.Release +} + +// GetRepo returns the Repo field. +func (r *ReleaseEvent) GetRepo() *Repository { + if r == nil { + return nil + } + return r.Repo +} + +// GetSender returns the Sender field. +func (r *ReleaseEvent) GetSender() *User { + if r == nil { + return nil + } + return r.Sender +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (r *RemoveToken) GetExpiresAt() Timestamp { + if r == nil || r.ExpiresAt == nil { + return Timestamp{} + } + return *r.ExpiresAt +} + +// GetToken returns the Token field if it's non-nil, zero value otherwise. +func (r *RemoveToken) GetToken() string { + if r == nil || r.Token == nil { + return "" + } + return *r.Token +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (r *Rename) GetFrom() string { + if r == nil || r.From == nil { + return "" + } + return *r.From +} + +// GetTo returns the To field if it's non-nil, zero value otherwise. +func (r *Rename) GetTo() string { + if r == nil || r.To == nil { + return "" + } + return *r.To +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (r *RenameOrgResponse) GetMessage() string { + if r == nil || r.Message == nil { + return "" + } + return *r.Message +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RenameOrgResponse) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (r *RepoAdvisoryCredit) GetLogin() string { + if r == nil || r.Login == nil { + return "" + } + return *r.Login +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (r *RepoAdvisoryCredit) GetType() string { + if r == nil || r.Type == nil { + return "" + } + return *r.Type +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (r *RepoAdvisoryCreditDetailed) GetState() string { + if r == nil || r.State == nil { + return "" + } + return *r.State +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (r *RepoAdvisoryCreditDetailed) GetType() string { + if r == nil || r.Type == nil { + return "" + } + return *r.Type +} + +// GetUser returns the User field. +func (r *RepoAdvisoryCreditDetailed) GetUser() *User { + if r == nil { + return nil + } + return r.User +} + +// GetDownloadLocation returns the DownloadLocation field if it's non-nil, zero value otherwise. +func (r *RepoDependencies) GetDownloadLocation() string { + if r == nil || r.DownloadLocation == nil { + return "" + } + return *r.DownloadLocation +} + +// GetFilesAnalyzed returns the FilesAnalyzed field if it's non-nil, zero value otherwise. +func (r *RepoDependencies) GetFilesAnalyzed() bool { + if r == nil || r.FilesAnalyzed == nil { + return false + } + return *r.FilesAnalyzed +} + +// GetLicenseConcluded returns the LicenseConcluded field if it's non-nil, zero value otherwise. +func (r *RepoDependencies) GetLicenseConcluded() string { + if r == nil || r.LicenseConcluded == nil { + return "" + } + return *r.LicenseConcluded +} + +// GetLicenseDeclared returns the LicenseDeclared field if it's non-nil, zero value otherwise. +func (r *RepoDependencies) GetLicenseDeclared() string { + if r == nil || r.LicenseDeclared == nil { + return "" + } + return *r.LicenseDeclared +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepoDependencies) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetSPDXID returns the SPDXID field if it's non-nil, zero value otherwise. +func (r *RepoDependencies) GetSPDXID() string { + if r == nil || r.SPDXID == nil { + return "" + } + return *r.SPDXID +} + +// GetVersionInfo returns the VersionInfo field if it's non-nil, zero value otherwise. +func (r *RepoDependencies) GetVersionInfo() string { + if r == nil || r.VersionInfo == nil { + return "" + } + return *r.VersionInfo +} + +// GetBranch returns the Branch field if it's non-nil, zero value otherwise. +func (r *RepoMergeUpstreamRequest) GetBranch() string { + if r == nil || r.Branch == nil { + return "" + } + return *r.Branch +} + +// GetBaseBranch returns the BaseBranch field if it's non-nil, zero value otherwise. +func (r *RepoMergeUpstreamResult) GetBaseBranch() string { + if r == nil || r.BaseBranch == nil { + return "" + } + return *r.BaseBranch +} + +// GetMergeType returns the MergeType field if it's non-nil, zero value otherwise. +func (r *RepoMergeUpstreamResult) GetMergeType() string { + if r == nil || r.MergeType == nil { + return "" + } + return *r.MergeType +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (r *RepoMergeUpstreamResult) GetMessage() string { + if r == nil || r.Message == nil { + return "" + } + return *r.Message +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (r *RepoName) GetFrom() string { + if r == nil || r.From == nil { + return "" + } + return *r.From +} + +// GetBadgeURL returns the BadgeURL field if it's non-nil, zero value otherwise. +func (r *RepoRequiredWorkflow) GetBadgeURL() string { + if r == nil || r.BadgeURL == nil { + return "" + } + return *r.BadgeURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepoRequiredWorkflow) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepoRequiredWorkflow) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepoRequiredWorkflow) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepoRequiredWorkflow) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *RepoRequiredWorkflow) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (r *RepoRequiredWorkflow) GetPath() string { + if r == nil || r.Path == nil { + return "" + } + return *r.Path +} + +// GetSourceRepository returns the SourceRepository field. +func (r *RepoRequiredWorkflow) GetSourceRepository() *Repository { + if r == nil { + return nil + } + return r.SourceRepository +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (r *RepoRequiredWorkflow) GetState() string { + if r == nil || r.State == nil { + return "" + } + return *r.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (r *RepoRequiredWorkflow) GetUpdatedAt() Timestamp { + if r == nil || r.UpdatedAt == nil { + return Timestamp{} + } + return *r.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepoRequiredWorkflow) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (r *RepoRequiredWorkflows) GetTotalCount() int { + if r == nil || r.TotalCount == nil { + return 0 + } + return *r.TotalCount +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (r *RepositoriesSearchResult) GetIncompleteResults() bool { + if r == nil || r.IncompleteResults == nil { + return false + } + return *r.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (r *RepositoriesSearchResult) GetTotal() int { + if r == nil || r.Total == nil { + return 0 + } + return *r.Total +} + +// GetAllowAutoMerge returns the AllowAutoMerge field if it's non-nil, zero value otherwise. +func (r *Repository) GetAllowAutoMerge() bool { + if r == nil || r.AllowAutoMerge == nil { + return false + } + return *r.AllowAutoMerge +} + +// GetAllowForking returns the AllowForking field if it's non-nil, zero value otherwise. +func (r *Repository) GetAllowForking() bool { + if r == nil || r.AllowForking == nil { + return false + } + return *r.AllowForking +} + +// GetAllowMergeCommit returns the AllowMergeCommit field if it's non-nil, zero value otherwise. +func (r *Repository) GetAllowMergeCommit() bool { + if r == nil || r.AllowMergeCommit == nil { + return false + } + return *r.AllowMergeCommit +} + +// GetAllowRebaseMerge returns the AllowRebaseMerge field if it's non-nil, zero value otherwise. +func (r *Repository) GetAllowRebaseMerge() bool { + if r == nil || r.AllowRebaseMerge == nil { + return false + } + return *r.AllowRebaseMerge +} + +// GetAllowSquashMerge returns the AllowSquashMerge field if it's non-nil, zero value otherwise. +func (r *Repository) GetAllowSquashMerge() bool { + if r == nil || r.AllowSquashMerge == nil { + return false + } + return *r.AllowSquashMerge +} + +// GetAllowUpdateBranch returns the AllowUpdateBranch field if it's non-nil, zero value otherwise. +func (r *Repository) GetAllowUpdateBranch() bool { + if r == nil || r.AllowUpdateBranch == nil { + return false + } + return *r.AllowUpdateBranch +} + +// GetArchived returns the Archived field if it's non-nil, zero value otherwise. +func (r *Repository) GetArchived() bool { + if r == nil || r.Archived == nil { + return false + } + return *r.Archived +} + +// GetArchiveURL returns the ArchiveURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetArchiveURL() string { + if r == nil || r.ArchiveURL == nil { + return "" + } + return *r.ArchiveURL +} + +// GetAssigneesURL returns the AssigneesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetAssigneesURL() string { + if r == nil || r.AssigneesURL == nil { + return "" + } + return *r.AssigneesURL +} + +// GetAutoInit returns the AutoInit field if it's non-nil, zero value otherwise. +func (r *Repository) GetAutoInit() bool { + if r == nil || r.AutoInit == nil { + return false + } + return *r.AutoInit +} + +// GetBlobsURL returns the BlobsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetBlobsURL() string { + if r == nil || r.BlobsURL == nil { + return "" + } + return *r.BlobsURL +} + +// GetBranchesURL returns the BranchesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetBranchesURL() string { + if r == nil || r.BranchesURL == nil { + return "" + } + return *r.BranchesURL +} + +// GetCloneURL returns the CloneURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetCloneURL() string { + if r == nil || r.CloneURL == nil { + return "" + } + return *r.CloneURL +} + +// GetCodeOfConduct returns the CodeOfConduct field. +func (r *Repository) GetCodeOfConduct() *CodeOfConduct { + if r == nil { + return nil + } + return r.CodeOfConduct +} + +// GetCollaboratorsURL returns the CollaboratorsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetCollaboratorsURL() string { + if r == nil || r.CollaboratorsURL == nil { + return "" + } + return *r.CollaboratorsURL +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetCommentsURL() string { + if r == nil || r.CommentsURL == nil { + return "" + } + return *r.CommentsURL +} + +// GetCommitsURL returns the CommitsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetCommitsURL() string { + if r == nil || r.CommitsURL == nil { + return "" + } + return *r.CommitsURL +} + +// GetCompareURL returns the CompareURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetCompareURL() string { + if r == nil || r.CompareURL == nil { + return "" + } + return *r.CompareURL +} + +// GetContentsURL returns the ContentsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetContentsURL() string { + if r == nil || r.ContentsURL == nil { + return "" + } + return *r.ContentsURL +} + +// GetContributorsURL returns the ContributorsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetContributorsURL() string { + if r == nil || r.ContributorsURL == nil { + return "" + } + return *r.ContributorsURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *Repository) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetDefaultBranch returns the DefaultBranch field if it's non-nil, zero value otherwise. +func (r *Repository) GetDefaultBranch() string { + if r == nil || r.DefaultBranch == nil { + return "" + } + return *r.DefaultBranch +} + +// GetDeleteBranchOnMerge returns the DeleteBranchOnMerge field if it's non-nil, zero value otherwise. +func (r *Repository) GetDeleteBranchOnMerge() bool { + if r == nil || r.DeleteBranchOnMerge == nil { + return false + } + return *r.DeleteBranchOnMerge +} + +// GetDeploymentsURL returns the DeploymentsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetDeploymentsURL() string { + if r == nil || r.DeploymentsURL == nil { + return "" + } + return *r.DeploymentsURL +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (r *Repository) GetDescription() string { + if r == nil || r.Description == nil { + return "" + } + return *r.Description +} + +// GetDisabled returns the Disabled field if it's non-nil, zero value otherwise. +func (r *Repository) GetDisabled() bool { + if r == nil || r.Disabled == nil { + return false + } + return *r.Disabled +} + +// GetDownloadsURL returns the DownloadsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetDownloadsURL() string { + if r == nil || r.DownloadsURL == nil { + return "" + } + return *r.DownloadsURL +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetEventsURL() string { + if r == nil || r.EventsURL == nil { + return "" + } + return *r.EventsURL +} + +// GetFork returns the Fork field if it's non-nil, zero value otherwise. +func (r *Repository) GetFork() bool { + if r == nil || r.Fork == nil { + return false + } + return *r.Fork +} + +// GetForksCount returns the ForksCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetForksCount() int { + if r == nil || r.ForksCount == nil { + return 0 + } + return *r.ForksCount +} + +// GetForksURL returns the ForksURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetForksURL() string { + if r == nil || r.ForksURL == nil { + return "" + } + return *r.ForksURL +} + +// GetFullName returns the FullName field if it's non-nil, zero value otherwise. +func (r *Repository) GetFullName() string { + if r == nil || r.FullName == nil { + return "" + } + return *r.FullName +} + +// GetGitCommitsURL returns the GitCommitsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetGitCommitsURL() string { + if r == nil || r.GitCommitsURL == nil { + return "" + } + return *r.GitCommitsURL +} + +// GetGitignoreTemplate returns the GitignoreTemplate field if it's non-nil, zero value otherwise. +func (r *Repository) GetGitignoreTemplate() string { + if r == nil || r.GitignoreTemplate == nil { + return "" + } + return *r.GitignoreTemplate +} + +// GetGitRefsURL returns the GitRefsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetGitRefsURL() string { + if r == nil || r.GitRefsURL == nil { + return "" + } + return *r.GitRefsURL +} + +// GetGitTagsURL returns the GitTagsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetGitTagsURL() string { + if r == nil || r.GitTagsURL == nil { + return "" + } + return *r.GitTagsURL +} + +// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetGitURL() string { + if r == nil || r.GitURL == nil { + return "" + } + return *r.GitURL +} + +// GetHasDiscussions returns the HasDiscussions field if it's non-nil, zero value otherwise. +func (r *Repository) GetHasDiscussions() bool { + if r == nil || r.HasDiscussions == nil { + return false + } + return *r.HasDiscussions +} + +// GetHasDownloads returns the HasDownloads field if it's non-nil, zero value otherwise. +func (r *Repository) GetHasDownloads() bool { + if r == nil || r.HasDownloads == nil { + return false + } + return *r.HasDownloads +} + +// GetHasIssues returns the HasIssues field if it's non-nil, zero value otherwise. +func (r *Repository) GetHasIssues() bool { + if r == nil || r.HasIssues == nil { + return false + } + return *r.HasIssues +} + +// GetHasPages returns the HasPages field if it's non-nil, zero value otherwise. +func (r *Repository) GetHasPages() bool { + if r == nil || r.HasPages == nil { + return false + } + return *r.HasPages +} + +// GetHasProjects returns the HasProjects field if it's non-nil, zero value otherwise. +func (r *Repository) GetHasProjects() bool { + if r == nil || r.HasProjects == nil { + return false + } + return *r.HasProjects +} + +// GetHasWiki returns the HasWiki field if it's non-nil, zero value otherwise. +func (r *Repository) GetHasWiki() bool { + if r == nil || r.HasWiki == nil { + return false + } + return *r.HasWiki +} + +// GetHomepage returns the Homepage field if it's non-nil, zero value otherwise. +func (r *Repository) GetHomepage() string { + if r == nil || r.Homepage == nil { + return "" + } + return *r.Homepage +} + +// GetHooksURL returns the HooksURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetHooksURL() string { + if r == nil || r.HooksURL == nil { + return "" + } + return *r.HooksURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *Repository) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetIssueCommentURL returns the IssueCommentURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetIssueCommentURL() string { + if r == nil || r.IssueCommentURL == nil { + return "" + } + return *r.IssueCommentURL +} + +// GetIssueEventsURL returns the IssueEventsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetIssueEventsURL() string { + if r == nil || r.IssueEventsURL == nil { + return "" + } + return *r.IssueEventsURL +} + +// GetIssuesURL returns the IssuesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetIssuesURL() string { + if r == nil || r.IssuesURL == nil { + return "" + } + return *r.IssuesURL +} + +// GetIsTemplate returns the IsTemplate field if it's non-nil, zero value otherwise. +func (r *Repository) GetIsTemplate() bool { + if r == nil || r.IsTemplate == nil { + return false + } + return *r.IsTemplate +} + +// GetKeysURL returns the KeysURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetKeysURL() string { + if r == nil || r.KeysURL == nil { + return "" + } + return *r.KeysURL +} + +// GetLabelsURL returns the LabelsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetLabelsURL() string { + if r == nil || r.LabelsURL == nil { + return "" + } + return *r.LabelsURL +} + +// GetLanguage returns the Language field if it's non-nil, zero value otherwise. +func (r *Repository) GetLanguage() string { + if r == nil || r.Language == nil { + return "" + } + return *r.Language +} + +// GetLanguagesURL returns the LanguagesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetLanguagesURL() string { + if r == nil || r.LanguagesURL == nil { + return "" + } + return *r.LanguagesURL +} + +// GetLicense returns the License field. +func (r *Repository) GetLicense() *License { + if r == nil { + return nil + } + return r.License +} + +// GetLicenseTemplate returns the LicenseTemplate field if it's non-nil, zero value otherwise. +func (r *Repository) GetLicenseTemplate() string { + if r == nil || r.LicenseTemplate == nil { + return "" + } + return *r.LicenseTemplate +} + +// GetMasterBranch returns the MasterBranch field if it's non-nil, zero value otherwise. +func (r *Repository) GetMasterBranch() string { + if r == nil || r.MasterBranch == nil { + return "" + } + return *r.MasterBranch +} + +// GetMergeCommitMessage returns the MergeCommitMessage field if it's non-nil, zero value otherwise. +func (r *Repository) GetMergeCommitMessage() string { + if r == nil || r.MergeCommitMessage == nil { + return "" + } + return *r.MergeCommitMessage +} + +// GetMergeCommitTitle returns the MergeCommitTitle field if it's non-nil, zero value otherwise. +func (r *Repository) GetMergeCommitTitle() string { + if r == nil || r.MergeCommitTitle == nil { + return "" + } + return *r.MergeCommitTitle +} + +// GetMergesURL returns the MergesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetMergesURL() string { + if r == nil || r.MergesURL == nil { + return "" + } + return *r.MergesURL +} + +// GetMilestonesURL returns the MilestonesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetMilestonesURL() string { + if r == nil || r.MilestonesURL == nil { + return "" + } + return *r.MilestonesURL +} + +// GetMirrorURL returns the MirrorURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetMirrorURL() string { + if r == nil || r.MirrorURL == nil { + return "" + } + return *r.MirrorURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *Repository) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetNetworkCount returns the NetworkCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetNetworkCount() int { + if r == nil || r.NetworkCount == nil { + return 0 + } + return *r.NetworkCount +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *Repository) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetNotificationsURL returns the NotificationsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetNotificationsURL() string { + if r == nil || r.NotificationsURL == nil { + return "" + } + return *r.NotificationsURL +} + +// GetOpenIssues returns the OpenIssues field if it's non-nil, zero value otherwise. +func (r *Repository) GetOpenIssues() int { + if r == nil || r.OpenIssues == nil { + return 0 + } + return *r.OpenIssues +} + +// GetOpenIssuesCount returns the OpenIssuesCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetOpenIssuesCount() int { + if r == nil || r.OpenIssuesCount == nil { + return 0 + } + return *r.OpenIssuesCount +} + +// GetOrganization returns the Organization field. +func (r *Repository) GetOrganization() *Organization { + if r == nil { + return nil + } + return r.Organization +} + +// GetOwner returns the Owner field. +func (r *Repository) GetOwner() *User { + if r == nil { + return nil + } + return r.Owner +} + +// GetParent returns the Parent field. +func (r *Repository) GetParent() *Repository { + if r == nil { + return nil + } + return r.Parent +} + +// GetPermissions returns the Permissions map if it's non-nil, an empty map otherwise. +func (r *Repository) GetPermissions() map[string]bool { + if r == nil || r.Permissions == nil { + return map[string]bool{} + } + return r.Permissions +} + +// GetPrivate returns the Private field if it's non-nil, zero value otherwise. +func (r *Repository) GetPrivate() bool { + if r == nil || r.Private == nil { + return false + } + return *r.Private +} + +// GetPullsURL returns the PullsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetPullsURL() string { + if r == nil || r.PullsURL == nil { + return "" + } + return *r.PullsURL +} + +// GetPushedAt returns the PushedAt field if it's non-nil, zero value otherwise. +func (r *Repository) GetPushedAt() Timestamp { + if r == nil || r.PushedAt == nil { + return Timestamp{} + } + return *r.PushedAt +} + +// GetReleasesURL returns the ReleasesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetReleasesURL() string { + if r == nil || r.ReleasesURL == nil { + return "" + } + return *r.ReleasesURL +} + +// GetRoleName returns the RoleName field if it's non-nil, zero value otherwise. +func (r *Repository) GetRoleName() string { + if r == nil || r.RoleName == nil { + return "" + } + return *r.RoleName +} + +// GetSecurityAndAnalysis returns the SecurityAndAnalysis field. +func (r *Repository) GetSecurityAndAnalysis() *SecurityAndAnalysis { + if r == nil { + return nil + } + return r.SecurityAndAnalysis +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (r *Repository) GetSize() int { + if r == nil || r.Size == nil { + return 0 + } + return *r.Size +} + +// GetSource returns the Source field. +func (r *Repository) GetSource() *Repository { + if r == nil { + return nil + } + return r.Source +} + +// GetSquashMergeCommitMessage returns the SquashMergeCommitMessage field if it's non-nil, zero value otherwise. +func (r *Repository) GetSquashMergeCommitMessage() string { + if r == nil || r.SquashMergeCommitMessage == nil { + return "" + } + return *r.SquashMergeCommitMessage +} + +// GetSquashMergeCommitTitle returns the SquashMergeCommitTitle field if it's non-nil, zero value otherwise. +func (r *Repository) GetSquashMergeCommitTitle() string { + if r == nil || r.SquashMergeCommitTitle == nil { + return "" + } + return *r.SquashMergeCommitTitle +} + +// GetSSHURL returns the SSHURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetSSHURL() string { + if r == nil || r.SSHURL == nil { + return "" + } + return *r.SSHURL +} + +// GetStargazersCount returns the StargazersCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetStargazersCount() int { + if r == nil || r.StargazersCount == nil { + return 0 + } + return *r.StargazersCount +} + +// GetStargazersURL returns the StargazersURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetStargazersURL() string { + if r == nil || r.StargazersURL == nil { + return "" + } + return *r.StargazersURL +} + +// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetStatusesURL() string { + if r == nil || r.StatusesURL == nil { + return "" + } + return *r.StatusesURL +} + +// GetSubscribersCount returns the SubscribersCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetSubscribersCount() int { + if r == nil || r.SubscribersCount == nil { + return 0 + } + return *r.SubscribersCount +} + +// GetSubscribersURL returns the SubscribersURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetSubscribersURL() string { + if r == nil || r.SubscribersURL == nil { + return "" + } + return *r.SubscribersURL +} + +// GetSubscriptionURL returns the SubscriptionURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetSubscriptionURL() string { + if r == nil || r.SubscriptionURL == nil { + return "" + } + return *r.SubscriptionURL +} + +// GetSVNURL returns the SVNURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetSVNURL() string { + if r == nil || r.SVNURL == nil { + return "" + } + return *r.SVNURL +} + +// GetTagsURL returns the TagsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetTagsURL() string { + if r == nil || r.TagsURL == nil { + return "" + } + return *r.TagsURL +} + +// GetTeamID returns the TeamID field if it's non-nil, zero value otherwise. +func (r *Repository) GetTeamID() int64 { + if r == nil || r.TeamID == nil { + return 0 + } + return *r.TeamID +} + +// GetTeamsURL returns the TeamsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetTeamsURL() string { + if r == nil || r.TeamsURL == nil { + return "" + } + return *r.TeamsURL +} + +// GetTemplateRepository returns the TemplateRepository field. +func (r *Repository) GetTemplateRepository() *Repository { + if r == nil { + return nil + } + return r.TemplateRepository +} + +// GetTreesURL returns the TreesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetTreesURL() string { + if r == nil || r.TreesURL == nil { + return "" + } + return *r.TreesURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (r *Repository) GetUpdatedAt() Timestamp { + if r == nil || r.UpdatedAt == nil { + return Timestamp{} + } + return *r.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *Repository) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetUseSquashPRTitleAsDefault returns the UseSquashPRTitleAsDefault field if it's non-nil, zero value otherwise. +func (r *Repository) GetUseSquashPRTitleAsDefault() bool { + if r == nil || r.UseSquashPRTitleAsDefault == nil { + return false + } + return *r.UseSquashPRTitleAsDefault +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (r *Repository) GetVisibility() string { + if r == nil || r.Visibility == nil { + return "" + } + return *r.Visibility +} + +// GetWatchers returns the Watchers field if it's non-nil, zero value otherwise. +func (r *Repository) GetWatchers() int { + if r == nil || r.Watchers == nil { + return 0 + } + return *r.Watchers +} + +// GetWatchersCount returns the WatchersCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetWatchersCount() int { + if r == nil || r.WatchersCount == nil { + return 0 + } + return *r.WatchersCount +} + +// GetWebCommitSignoffRequired returns the WebCommitSignoffRequired field if it's non-nil, zero value otherwise. +func (r *Repository) GetWebCommitSignoffRequired() bool { + if r == nil || r.WebCommitSignoffRequired == nil { + return false + } + return *r.WebCommitSignoffRequired +} + +// GetAccessLevel returns the AccessLevel field if it's non-nil, zero value otherwise. +func (r *RepositoryActionsAccessLevel) GetAccessLevel() string { + if r == nil || r.AccessLevel == nil { + return "" + } + return *r.AccessLevel +} + +// GetAdvancedSecurityCommitters returns the AdvancedSecurityCommitters field if it's non-nil, zero value otherwise. +func (r *RepositoryActiveCommitters) GetAdvancedSecurityCommitters() int { + if r == nil || r.AdvancedSecurityCommitters == nil { + return 0 + } + return *r.AdvancedSecurityCommitters +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepositoryActiveCommitters) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetConfiguration returns the Configuration field. +func (r *RepositoryCodeSecurityConfiguration) GetConfiguration() *CodeSecurityConfiguration { + if r == nil { + return nil + } + return r.Configuration +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (r *RepositoryCodeSecurityConfiguration) GetState() string { + if r == nil || r.State == nil { + return "" + } + return *r.State +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetBody() string { + if r == nil || r.Body == nil { + return "" + } + return *r.Body +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetCommitID() string { + if r == nil || r.CommitID == nil { + return "" + } + return *r.CommitID +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetPath() string { + if r == nil || r.Path == nil { + return "" + } + return *r.Path +} + +// GetPosition returns the Position field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetPosition() int { + if r == nil || r.Position == nil { + return 0 + } + return *r.Position +} + +// GetReactions returns the Reactions field. +func (r *RepositoryComment) GetReactions() *Reactions { + if r == nil { + return nil + } + return r.Reactions +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetUpdatedAt() Timestamp { + if r == nil || r.UpdatedAt == nil { + return Timestamp{} + } + return *r.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetUser returns the User field. +func (r *RepositoryComment) GetUser() *User { + if r == nil { + return nil + } + return r.User +} + +// GetAuthor returns the Author field. +func (r *RepositoryCommit) GetAuthor() *User { + if r == nil { + return nil + } + return r.Author +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (r *RepositoryCommit) GetCommentsURL() string { + if r == nil || r.CommentsURL == nil { + return "" + } + return *r.CommentsURL +} + +// GetCommit returns the Commit field. +func (r *RepositoryCommit) GetCommit() *Commit { + if r == nil { + return nil + } + return r.Commit +} + +// GetCommitter returns the Committer field. +func (r *RepositoryCommit) GetCommitter() *User { + if r == nil { + return nil + } + return r.Committer +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryCommit) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *RepositoryCommit) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (r *RepositoryCommit) GetSHA() string { + if r == nil || r.SHA == nil { + return "" + } + return *r.SHA +} + +// GetStats returns the Stats field. +func (r *RepositoryCommit) GetStats() *CommitStats { + if r == nil { + return nil + } + return r.Stats +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryCommit) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetDownloadURL returns the DownloadURL field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetDownloadURL() string { + if r == nil || r.DownloadURL == nil { + return "" + } + return *r.DownloadURL +} + +// GetEncoding returns the Encoding field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetEncoding() string { + if r == nil || r.Encoding == nil { + return "" + } + return *r.Encoding +} + +// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetGitURL() string { + if r == nil || r.GitURL == nil { + return "" + } + return *r.GitURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetPath() string { + if r == nil || r.Path == nil { + return "" + } + return *r.Path +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetSHA() string { + if r == nil || r.SHA == nil { + return "" + } + return *r.SHA +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetSize() int { + if r == nil || r.Size == nil { + return 0 + } + return *r.Size +} + +// GetSubmoduleGitURL returns the SubmoduleGitURL field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetSubmoduleGitURL() string { + if r == nil || r.SubmoduleGitURL == nil { + return "" + } + return *r.SubmoduleGitURL +} + +// GetTarget returns the Target field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetTarget() string { + if r == nil || r.Target == nil { + return "" + } + return *r.Target +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetType() string { + if r == nil || r.Type == nil { + return "" + } + return *r.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetAuthor returns the Author field. +func (r *RepositoryContentFileOptions) GetAuthor() *CommitAuthor { + if r == nil { + return nil + } + return r.Author +} + +// GetBranch returns the Branch field if it's non-nil, zero value otherwise. +func (r *RepositoryContentFileOptions) GetBranch() string { + if r == nil || r.Branch == nil { + return "" + } + return *r.Branch +} + +// GetCommitter returns the Committer field. +func (r *RepositoryContentFileOptions) GetCommitter() *CommitAuthor { + if r == nil { + return nil + } + return r.Committer +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (r *RepositoryContentFileOptions) GetMessage() string { + if r == nil || r.Message == nil { + return "" + } + return *r.Message +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (r *RepositoryContentFileOptions) GetSHA() string { + if r == nil || r.SHA == nil { + return "" + } + return *r.SHA +} + +// GetContent returns the Content field. +func (r *RepositoryContentResponse) GetContent() *RepositoryContent { + if r == nil { + return nil + } + return r.Content +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (r *RepositoryDispatchEvent) GetAction() string { + if r == nil || r.Action == nil { + return "" + } + return *r.Action +} + +// GetBranch returns the Branch field if it's non-nil, zero value otherwise. +func (r *RepositoryDispatchEvent) GetBranch() string { + if r == nil || r.Branch == nil { + return "" + } + return *r.Branch +} + +// GetInstallation returns the Installation field. +func (r *RepositoryDispatchEvent) GetInstallation() *Installation { + if r == nil { + return nil + } + return r.Installation +} + +// GetOrg returns the Org field. +func (r *RepositoryDispatchEvent) GetOrg() *Organization { + if r == nil { + return nil + } + return r.Org +} + +// GetRepo returns the Repo field. +func (r *RepositoryDispatchEvent) GetRepo() *Repository { + if r == nil { + return nil + } + return r.Repo +} + +// GetSender returns the Sender field. +func (r *RepositoryDispatchEvent) GetSender() *User { + if r == nil { + return nil + } + return r.Sender +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (r *RepositoryEvent) GetAction() string { + if r == nil || r.Action == nil { + return "" + } + return *r.Action +} + +// GetChanges returns the Changes field. +func (r *RepositoryEvent) GetChanges() *EditChange { + if r == nil { + return nil + } + return r.Changes +} + +// GetInstallation returns the Installation field. +func (r *RepositoryEvent) GetInstallation() *Installation { + if r == nil { + return nil + } + return r.Installation +} + +// GetOrg returns the Org field. +func (r *RepositoryEvent) GetOrg() *Organization { + if r == nil { + return nil + } + return r.Org +} + +// GetRepo returns the Repo field. +func (r *RepositoryEvent) GetRepo() *Repository { + if r == nil { + return nil + } + return r.Repo +} + +// GetSender returns the Sender field. +func (r *RepositoryEvent) GetSender() *User { + if r == nil { + return nil + } + return r.Sender +} + +// GetOrg returns the Org field. +func (r *RepositoryImportEvent) GetOrg() *Organization { + if r == nil { + return nil + } + return r.Org +} + +// GetRepo returns the Repo field. +func (r *RepositoryImportEvent) GetRepo() *Repository { + if r == nil { + return nil + } + return r.Repo +} + +// GetSender returns the Sender field. +func (r *RepositoryImportEvent) GetSender() *User { + if r == nil { + return nil + } + return r.Sender +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (r *RepositoryImportEvent) GetStatus() string { + if r == nil || r.Status == nil { + return "" + } + return *r.Status +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryInvitation) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetExpired returns the Expired field if it's non-nil, zero value otherwise. +func (r *RepositoryInvitation) GetExpired() bool { + if r == nil || r.Expired == nil { + return false + } + return *r.Expired +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryInvitation) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepositoryInvitation) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetInvitee returns the Invitee field. +func (r *RepositoryInvitation) GetInvitee() *User { + if r == nil { + return nil + } + return r.Invitee +} + +// GetInviter returns the Inviter field. +func (r *RepositoryInvitation) GetInviter() *User { + if r == nil { + return nil + } + return r.Inviter +} + +// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise. +func (r *RepositoryInvitation) GetPermissions() string { + if r == nil || r.Permissions == nil { + return "" + } + return *r.Permissions +} + +// GetRepo returns the Repo field. +func (r *RepositoryInvitation) GetRepo() *Repository { + if r == nil { + return nil + } + return r.Repo +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryInvitation) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetContent returns the Content field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetContent() string { + if r == nil || r.Content == nil { + return "" + } + return *r.Content +} + +// GetDownloadURL returns the DownloadURL field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetDownloadURL() string { + if r == nil || r.DownloadURL == nil { + return "" + } + return *r.DownloadURL +} + +// GetEncoding returns the Encoding field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetEncoding() string { + if r == nil || r.Encoding == nil { + return "" + } + return *r.Encoding +} + +// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetGitURL() string { + if r == nil || r.GitURL == nil { + return "" + } + return *r.GitURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetLicense returns the License field. +func (r *RepositoryLicense) GetLicense() *License { + if r == nil { + return nil + } + return r.License +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetPath() string { + if r == nil || r.Path == nil { + return "" + } + return *r.Path +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetSHA() string { + if r == nil || r.SHA == nil { + return "" + } + return *r.SHA +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetSize() int { + if r == nil || r.Size == nil { + return 0 + } + return *r.Size +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetType() string { + if r == nil || r.Type == nil { + return "" + } + return *r.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetBase returns the Base field if it's non-nil, zero value otherwise. +func (r *RepositoryMergeRequest) GetBase() string { + if r == nil || r.Base == nil { + return "" + } + return *r.Base +} + +// GetCommitMessage returns the CommitMessage field if it's non-nil, zero value otherwise. +func (r *RepositoryMergeRequest) GetCommitMessage() string { + if r == nil || r.CommitMessage == nil { + return "" + } + return *r.CommitMessage +} + +// GetHead returns the Head field if it's non-nil, zero value otherwise. +func (r *RepositoryMergeRequest) GetHead() string { + if r == nil || r.Head == nil { + return "" + } + return *r.Head +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (r *RepositoryPermissionLevel) GetPermission() string { + if r == nil || r.Permission == nil { + return "" + } + return *r.Permission +} + +// GetRoleName returns the RoleName field if it's non-nil, zero value otherwise. +func (r *RepositoryPermissionLevel) GetRoleName() string { + if r == nil || r.RoleName == nil { + return "" + } + return *r.RoleName +} + +// GetUser returns the User field. +func (r *RepositoryPermissionLevel) GetUser() *User { + if r == nil { + return nil + } + return r.User +} + +// GetAssetsURL returns the AssetsURL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetAssetsURL() string { + if r == nil || r.AssetsURL == nil { + return "" + } + return *r.AssetsURL +} + +// GetAuthor returns the Author field. +func (r *RepositoryRelease) GetAuthor() *User { + if r == nil { + return nil + } + return r.Author +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetBody() string { + if r == nil || r.Body == nil { + return "" + } + return *r.Body +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetDiscussionCategoryName returns the DiscussionCategoryName field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetDiscussionCategoryName() string { + if r == nil || r.DiscussionCategoryName == nil { + return "" + } + return *r.DiscussionCategoryName +} + +// GetDraft returns the Draft field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetDraft() bool { + if r == nil || r.Draft == nil { + return false + } + return *r.Draft +} + +// GetGenerateReleaseNotes returns the GenerateReleaseNotes field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetGenerateReleaseNotes() bool { + if r == nil || r.GenerateReleaseNotes == nil { + return false + } + return *r.GenerateReleaseNotes +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetMakeLatest returns the MakeLatest field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetMakeLatest() string { + if r == nil || r.MakeLatest == nil { + return "" + } + return *r.MakeLatest +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetPrerelease returns the Prerelease field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetPrerelease() bool { + if r == nil || r.Prerelease == nil { + return false + } + return *r.Prerelease +} + +// GetPublishedAt returns the PublishedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetPublishedAt() Timestamp { + if r == nil || r.PublishedAt == nil { + return Timestamp{} + } + return *r.PublishedAt +} + +// GetTagName returns the TagName field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetTagName() string { + if r == nil || r.TagName == nil { + return "" + } + return *r.TagName +} + +// GetTarballURL returns the TarballURL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetTarballURL() string { + if r == nil || r.TarballURL == nil { + return "" + } + return *r.TarballURL +} + +// GetTargetCommitish returns the TargetCommitish field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetTargetCommitish() string { + if r == nil || r.TargetCommitish == nil { + return "" + } + return *r.TargetCommitish +} + +// GetUploadURL returns the UploadURL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetUploadURL() string { + if r == nil || r.UploadURL == nil { + return "" + } + return *r.UploadURL +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetZipballURL returns the ZipballURL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetZipballURL() string { + if r == nil || r.ZipballURL == nil { + return "" + } + return *r.ZipballURL +} + +// GetParameters returns the Parameters field if it's non-nil, zero value otherwise. +func (r *RepositoryRule) GetParameters() json.RawMessage { + if r == nil || r.Parameters == nil { + return json.RawMessage{} + } + return *r.Parameters +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryRuleset) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetCurrentUserCanBypass returns the CurrentUserCanBypass field if it's non-nil, zero value otherwise. +func (r *RepositoryRuleset) GetCurrentUserCanBypass() string { + if r == nil || r.CurrentUserCanBypass == nil { + return "" + } + return *r.CurrentUserCanBypass +} + +// GetLinks returns the Links field. +func (r *RepositoryRuleset) GetLinks() *RepositoryRulesetLink { + if r == nil { + return nil + } + return r.Links +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *RepositoryRuleset) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetSourceType returns the SourceType field if it's non-nil, zero value otherwise. +func (r *RepositoryRuleset) GetSourceType() string { + if r == nil || r.SourceType == nil { + return "" + } + return *r.SourceType +} + +// GetTarget returns the Target field if it's non-nil, zero value otherwise. +func (r *RepositoryRuleset) GetTarget() string { + if r == nil || r.Target == nil { + return "" + } + return *r.Target +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryRuleset) GetUpdatedAt() Timestamp { + if r == nil || r.UpdatedAt == nil { + return Timestamp{} + } + return *r.UpdatedAt +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetCodeScanningRule) GetParameters() *RuleCodeScanningParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetConditions returns the Conditions field. +func (r *RepositoryRulesetEditedChanges) GetConditions() *RepositoryRulesetEditedConditions { + if r == nil { + return nil + } + return r.Conditions +} + +// GetEnforcement returns the Enforcement field. +func (r *RepositoryRulesetEditedChanges) GetEnforcement() *RepositoryRulesetEditedSource { + if r == nil { + return nil + } + return r.Enforcement +} + +// GetName returns the Name field. +func (r *RepositoryRulesetEditedChanges) GetName() *RepositoryRulesetEditedSource { + if r == nil { + return nil + } + return r.Name +} + +// GetRules returns the Rules field. +func (r *RepositoryRulesetEditedChanges) GetRules() *RepositoryRulesetEditedRules { + if r == nil { + return nil + } + return r.Rules +} + +// GetConfiguration returns the Configuration field. +func (r *RepositoryRulesetEditedRuleChanges) GetConfiguration() *RepositoryRulesetEditedSources { + if r == nil { + return nil + } + return r.Configuration +} + +// GetPattern returns the Pattern field. +func (r *RepositoryRulesetEditedRuleChanges) GetPattern() *RepositoryRulesetEditedSources { + if r == nil { + return nil + } + return r.Pattern +} + +// GetRuleType returns the RuleType field. +func (r *RepositoryRulesetEditedRuleChanges) GetRuleType() *RepositoryRulesetEditedSources { + if r == nil { + return nil + } + return r.RuleType +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (r *RepositoryRulesetEditedSource) GetFrom() string { + if r == nil || r.From == nil { + return "" + } + return *r.From +} + +// GetChanges returns the Changes field. +func (r *RepositoryRulesetEditedUpdatedConditions) GetChanges() *RepositoryRulesetUpdatedConditionsEdited { + if r == nil { + return nil + } + return r.Changes +} + +// GetCondition returns the Condition field. +func (r *RepositoryRulesetEditedUpdatedConditions) GetCondition() *RepositoryRulesetRefCondition { + if r == nil { + return nil + } + return r.Condition +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (r *RepositoryRulesetEvent) GetAction() string { + if r == nil || r.Action == nil { + return "" + } + return *r.Action +} + +// GetChanges returns the Changes field. +func (r *RepositoryRulesetEvent) GetChanges() *RepositoryRulesetEditedChanges { + if r == nil { + return nil + } + return r.Changes +} + +// GetEnterprise returns the Enterprise field. +func (r *RepositoryRulesetEvent) GetEnterprise() *Enterprise { + if r == nil { + return nil + } + return r.Enterprise +} + +// GetInstallation returns the Installation field. +func (r *RepositoryRulesetEvent) GetInstallation() *Installation { + if r == nil { + return nil + } + return r.Installation +} + +// GetOrganization returns the Organization field. +func (r *RepositoryRulesetEvent) GetOrganization() *Organization { + if r == nil { + return nil + } + return r.Organization +} + +// GetRepository returns the Repository field. +func (r *RepositoryRulesetEvent) GetRepository() *Repository { + if r == nil { + return nil + } + return r.Repository +} + +// GetRepositoryRuleset returns the RepositoryRuleset field. +func (r *RepositoryRulesetEvent) GetRepositoryRuleset() *RepositoryRuleset { + if r == nil { + return nil + } + return r.RepositoryRuleset +} + +// GetSender returns the Sender field. +func (r *RepositoryRulesetEvent) GetSender() *User { + if r == nil { + return nil + } + return r.Sender +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetFileExtensionRestrictionRule) GetParameters() *RuleFileExtensionRestrictionParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetFilePathRestrictionRule) GetParameters() *RuleFileParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetHTML returns the HTML field. +func (r *RepositoryRulesetLink) GetHTML() *RulesetLink { + if r == nil { + return nil + } + return r.HTML +} + +// GetSelf returns the Self field. +func (r *RepositoryRulesetLink) GetSelf() *RulesetLink { + if r == nil { + return nil + } + return r.Self +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetMaxFilePathLengthRule) GetParameters() *RuleMaxFilePathLengthParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetMaxFileSizeRule) GetParameters() *RuleMaxFileSizeParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetMergeQueueRule) GetParameters() *MergeQueueRuleParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetPatternRule) GetParameters() *RulePatternParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetPullRequestRule) GetParameters() *PullRequestRuleParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetRefName returns the RefName field. +func (r *RepositoryRulesetRefCondition) GetRefName() *RulesetRefConditionParameters { + if r == nil { + return nil + } + return r.RefName +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetRequiredDeploymentsRule) GetParameters() *RequiredDeploymentEnvironmentsRuleParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetRequiredStatusChecksRule) GetParameters() *RequiredStatusChecksRuleParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetBranchNamePattern returns the BranchNamePattern field. +func (r *RepositoryRulesetRule) GetBranchNamePattern() *RepositoryRulesetPatternRule { + if r == nil { + return nil + } + return r.BranchNamePattern +} + +// GetCodeScanning returns the CodeScanning field. +func (r *RepositoryRulesetRule) GetCodeScanning() *RepositoryRulesetCodeScanningRule { + if r == nil { + return nil + } + return r.CodeScanning +} + +// GetCommitAuthorEmailPattern returns the CommitAuthorEmailPattern field. +func (r *RepositoryRulesetRule) GetCommitAuthorEmailPattern() *RepositoryRulesetPatternRule { + if r == nil { + return nil + } + return r.CommitAuthorEmailPattern +} + +// GetCommitMessagePattern returns the CommitMessagePattern field. +func (r *RepositoryRulesetRule) GetCommitMessagePattern() *RepositoryRulesetPatternRule { + if r == nil { + return nil + } + return r.CommitMessagePattern +} + +// GetCommitterEmailPattern returns the CommitterEmailPattern field. +func (r *RepositoryRulesetRule) GetCommitterEmailPattern() *RepositoryRulesetPatternRule { + if r == nil { + return nil + } + return r.CommitterEmailPattern +} + +// GetCreation returns the Creation field. +func (r *RepositoryRulesetRule) GetCreation() *RepositoryRulesetRuleType { + if r == nil { + return nil + } + return r.Creation +} + +// GetDeletion returns the Deletion field. +func (r *RepositoryRulesetRule) GetDeletion() *RepositoryRulesetRuleType { + if r == nil { + return nil + } + return r.Deletion +} + +// GetFileExtensionRestriction returns the FileExtensionRestriction field. +func (r *RepositoryRulesetRule) GetFileExtensionRestriction() *RepositoryRulesetFileExtensionRestrictionRule { + if r == nil { + return nil + } + return r.FileExtensionRestriction +} + +// GetFilePathRestriction returns the FilePathRestriction field. +func (r *RepositoryRulesetRule) GetFilePathRestriction() *RepositoryRulesetFilePathRestrictionRule { + if r == nil { + return nil + } + return r.FilePathRestriction +} + +// GetMaxFilePathLength returns the MaxFilePathLength field. +func (r *RepositoryRulesetRule) GetMaxFilePathLength() *RepositoryRulesetMaxFilePathLengthRule { + if r == nil { + return nil + } + return r.MaxFilePathLength +} + +// GetMaxFileSize returns the MaxFileSize field. +func (r *RepositoryRulesetRule) GetMaxFileSize() *RepositoryRulesetMaxFileSizeRule { + if r == nil { + return nil + } + return r.MaxFileSize +} + +// GetMergeQueue returns the MergeQueue field. +func (r *RepositoryRulesetRule) GetMergeQueue() *RepositoryRulesetMergeQueueRule { + if r == nil { + return nil + } + return r.MergeQueue +} + +// GetNonFastForward returns the NonFastForward field. +func (r *RepositoryRulesetRule) GetNonFastForward() *RepositoryRulesetRuleType { + if r == nil { + return nil + } + return r.NonFastForward +} + +// GetPullRequest returns the PullRequest field. +func (r *RepositoryRulesetRule) GetPullRequest() *RepositoryRulesetPullRequestRule { + if r == nil { + return nil + } + return r.PullRequest +} + +// GetRequiredDeployments returns the RequiredDeployments field. +func (r *RepositoryRulesetRule) GetRequiredDeployments() *RepositoryRulesetRequiredDeploymentsRule { + if r == nil { + return nil + } + return r.RequiredDeployments +} + +// GetRequiredLinearHistory returns the RequiredLinearHistory field. +func (r *RepositoryRulesetRule) GetRequiredLinearHistory() *RepositoryRulesetRuleType { + if r == nil { + return nil + } + return r.RequiredLinearHistory +} + +// GetRequiredSignatures returns the RequiredSignatures field. +func (r *RepositoryRulesetRule) GetRequiredSignatures() *RepositoryRulesetRuleType { + if r == nil { + return nil + } + return r.RequiredSignatures +} + +// GetRequiredStatusChecks returns the RequiredStatusChecks field. +func (r *RepositoryRulesetRule) GetRequiredStatusChecks() *RepositoryRulesetRequiredStatusChecksRule { + if r == nil { + return nil + } + return r.RequiredStatusChecks +} + +// GetTagNamePattern returns the TagNamePattern field. +func (r *RepositoryRulesetRule) GetTagNamePattern() *RepositoryRulesetPatternRule { + if r == nil { + return nil + } + return r.TagNamePattern +} + +// GetUpdate returns the Update field. +func (r *RepositoryRulesetRule) GetUpdate() *RepositoryRulesetUpdateRule { + if r == nil { + return nil + } + return r.Update +} + +// GetWorkflows returns the Workflows field. +func (r *RepositoryRulesetRule) GetWorkflows() *RepositoryRulesetWorkflowsRule { + if r == nil { + return nil + } + return r.Workflows +} + +// GetConditionType returns the ConditionType field. +func (r *RepositoryRulesetUpdatedConditionsEdited) GetConditionType() *RepositoryRulesetEditedSource { + if r == nil { + return nil + } + return r.ConditionType +} + +// GetExclude returns the Exclude field. +func (r *RepositoryRulesetUpdatedConditionsEdited) GetExclude() *RepositoryRulesetEditedSources { + if r == nil { + return nil + } + return r.Exclude +} + +// GetInclude returns the Include field. +func (r *RepositoryRulesetUpdatedConditionsEdited) GetInclude() *RepositoryRulesetEditedSources { + if r == nil { + return nil + } + return r.Include +} + +// GetTarget returns the Target field. +func (r *RepositoryRulesetUpdatedConditionsEdited) GetTarget() *RepositoryRulesetEditedSource { + if r == nil { + return nil + } + return r.Target +} + +// GetChanges returns the Changes field. +func (r *RepositoryRulesetUpdatedRules) GetChanges() *RepositoryRulesetEditedRuleChanges { + if r == nil { + return nil + } + return r.Changes +} + +// GetRule returns the Rule field. +func (r *RepositoryRulesetUpdatedRules) GetRule() *RepositoryRulesetRule { + if r == nil { + return nil + } + return r.Rule +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetUpdateRule) GetParameters() *UpdateAllowsFetchAndMergeRuleParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetWorkflowsRule) GetParameters() *RequiredWorkflowsRuleParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetCommit returns the Commit field. +func (r *RepositoryTag) GetCommit() *Commit { + if r == nil { + return nil + } + return r.Commit +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepositoryTag) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetTarballURL returns the TarballURL field if it's non-nil, zero value otherwise. +func (r *RepositoryTag) GetTarballURL() string { + if r == nil || r.TarballURL == nil { + return "" + } + return *r.TarballURL +} + +// GetZipballURL returns the ZipballURL field if it's non-nil, zero value otherwise. +func (r *RepositoryTag) GetZipballURL() string { + if r == nil || r.ZipballURL == nil { + return "" + } + return *r.ZipballURL +} + +// GetAffectedPackageName returns the AffectedPackageName field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetAffectedPackageName() string { + if r == nil || r.AffectedPackageName == nil { + return "" + } + return *r.AffectedPackageName +} + +// GetAffectedRange returns the AffectedRange field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetAffectedRange() string { + if r == nil || r.AffectedRange == nil { + return "" + } + return *r.AffectedRange +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetDismissedAt returns the DismissedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetDismissedAt() Timestamp { + if r == nil || r.DismissedAt == nil { + return Timestamp{} + } + return *r.DismissedAt +} + +// GetDismisser returns the Dismisser field. +func (r *RepositoryVulnerabilityAlert) GetDismisser() *User { + if r == nil { + return nil + } + return r.Dismisser +} + +// GetDismissReason returns the DismissReason field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetDismissReason() string { + if r == nil || r.DismissReason == nil { + return "" + } + return *r.DismissReason +} + +// GetExternalIdentifier returns the ExternalIdentifier field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetExternalIdentifier() string { + if r == nil || r.ExternalIdentifier == nil { + return "" + } + return *r.ExternalIdentifier +} + +// GetExternalReference returns the ExternalReference field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetExternalReference() string { + if r == nil || r.ExternalReference == nil { + return "" + } + return *r.ExternalReference +} + +// GetFixedIn returns the FixedIn field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetFixedIn() string { + if r == nil || r.FixedIn == nil { + return "" + } + return *r.FixedIn +} + +// GetGitHubSecurityAdvisoryID returns the GitHubSecurityAdvisoryID field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetGitHubSecurityAdvisoryID() string { + if r == nil || r.GitHubSecurityAdvisoryID == nil { + return "" + } + return *r.GitHubSecurityAdvisoryID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetSeverity returns the Severity field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetSeverity() string { + if r == nil || r.Severity == nil { + return "" + } + return *r.Severity +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlertEvent) GetAction() string { + if r == nil || r.Action == nil { + return "" + } + return *r.Action +} + +// GetAlert returns the Alert field. +func (r *RepositoryVulnerabilityAlertEvent) GetAlert() *RepositoryVulnerabilityAlert { + if r == nil { + return nil + } + return r.Alert +} + +// GetInstallation returns the Installation field. +func (r *RepositoryVulnerabilityAlertEvent) GetInstallation() *Installation { + if r == nil { + return nil + } + return r.Installation +} + +// GetOrg returns the Org field. +func (r *RepositoryVulnerabilityAlertEvent) GetOrg() *Organization { + if r == nil { + return nil + } + return r.Org +} + +// GetRepository returns the Repository field. +func (r *RepositoryVulnerabilityAlertEvent) GetRepository() *Repository { + if r == nil { + return nil + } + return r.Repository +} + +// GetSender returns the Sender field. +func (r *RepositoryVulnerabilityAlertEvent) GetSender() *User { + if r == nil { + return nil + } + return r.Sender +} + +// GetForkRepos returns the ForkRepos field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetForkRepos() int { + if r == nil || r.ForkRepos == nil { + return 0 + } + return *r.ForkRepos +} + +// GetOrgRepos returns the OrgRepos field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetOrgRepos() int { + if r == nil || r.OrgRepos == nil { + return 0 + } + return *r.OrgRepos +} + +// GetRootRepos returns the RootRepos field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetRootRepos() int { + if r == nil || r.RootRepos == nil { + return 0 + } + return *r.RootRepos +} + +// GetTotalPushes returns the TotalPushes field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetTotalPushes() int { + if r == nil || r.TotalPushes == nil { + return 0 + } + return *r.TotalPushes +} + +// GetTotalRepos returns the TotalRepos field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetTotalRepos() int { + if r == nil || r.TotalRepos == nil { + return 0 + } + return *r.TotalRepos +} + +// GetTotalWikis returns the TotalWikis field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetTotalWikis() int { + if r == nil || r.TotalWikis == nil { + return 0 + } + return *r.TotalWikis +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetAvatarURL() string { + if r == nil || r.AvatarURL == nil { + return "" + } + return *r.AvatarURL +} + +// GetContext returns the Context field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetContext() string { + if r == nil || r.Context == nil { + return "" + } + return *r.Context +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetCreator returns the Creator field. +func (r *RepoStatus) GetCreator() *User { + if r == nil { + return nil + } + return r.Creator +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetDescription() string { + if r == nil || r.Description == nil { + return "" + } + return *r.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetState() string { + if r == nil || r.State == nil { + return "" + } + return *r.State +} + +// GetTargetURL returns the TargetURL field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetTargetURL() string { + if r == nil || r.TargetURL == nil { + return "" + } + return *r.TargetURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetUpdatedAt() Timestamp { + if r == nil || r.UpdatedAt == nil { + return Timestamp{} + } + return *r.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (r *RequireCodeOwnerReviewChanges) GetFrom() bool { + if r == nil || r.From == nil { + return false + } + return *r.From +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (r *RequiredConversationResolutionLevelChanges) GetFrom() string { + if r == nil || r.From == nil { + return "" + } + return *r.From +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (r *RequiredDeploymentsEnforcementLevelChanges) GetFrom() string { + if r == nil || r.From == nil { + return "" + } + return *r.From +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (r *RequiredReviewer) GetType() string { + if r == nil || r.Type == nil { + return "" + } + return *r.Type +} + +// GetAppID returns the AppID field if it's non-nil, zero value otherwise. +func (r *RequiredStatusCheck) GetAppID() int64 { + if r == nil || r.AppID == nil { + return 0 + } + return *r.AppID +} + +// GetChecks returns the Checks field if it's non-nil, zero value otherwise. +func (r *RequiredStatusChecks) GetChecks() []*RequiredStatusCheck { + if r == nil || r.Checks == nil { + return nil + } + return *r.Checks +} + +// GetContexts returns the Contexts field if it's non-nil, zero value otherwise. +func (r *RequiredStatusChecks) GetContexts() []string { + if r == nil || r.Contexts == nil { + return nil + } + return *r.Contexts +} + +// GetContextsURL returns the ContextsURL field if it's non-nil, zero value otherwise. +func (r *RequiredStatusChecks) GetContextsURL() string { + if r == nil || r.ContextsURL == nil { + return "" + } + return *r.ContextsURL +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RequiredStatusChecks) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (r *RequiredStatusChecksEnforcementLevelChanges) GetFrom() string { + if r == nil || r.From == nil { + return "" + } + return *r.From +} + +// GetStrict returns the Strict field if it's non-nil, zero value otherwise. +func (r *RequiredStatusChecksRequest) GetStrict() bool { + if r == nil || r.Strict == nil { + return false + } + return *r.Strict +} + +// GetDoNotEnforceOnCreate returns the DoNotEnforceOnCreate field if it's non-nil, zero value otherwise. +func (r *RequiredStatusChecksRuleParameters) GetDoNotEnforceOnCreate() bool { + if r == nil || r.DoNotEnforceOnCreate == nil { + return false + } + return *r.DoNotEnforceOnCreate +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (r *RequiredWorkflowSelectedRepos) GetTotalCount() int { + if r == nil || r.TotalCount == nil { + return 0 + } + return *r.TotalCount +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *ReviewersRequest) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetReason returns the Reason field if it's non-nil, zero value otherwise. +func (r *ReviewPersonalAccessTokenRequestOptions) GetReason() string { + if r == nil || r.Reason == nil { + return "" + } + return *r.Reason +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (r *Rule) GetDescription() string { + if r == nil || r.Description == nil { + return "" + } + return *r.Description +} + +// GetFullDescription returns the FullDescription field if it's non-nil, zero value otherwise. +func (r *Rule) GetFullDescription() string { + if r == nil || r.FullDescription == nil { + return "" + } + return *r.FullDescription +} + +// GetHelp returns the Help field if it's non-nil, zero value otherwise. +func (r *Rule) GetHelp() string { + if r == nil || r.Help == nil { + return "" + } + return *r.Help +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *Rule) GetID() string { + if r == nil || r.ID == nil { + return "" + } + return *r.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *Rule) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetSecuritySeverityLevel returns the SecuritySeverityLevel field if it's non-nil, zero value otherwise. +func (r *Rule) GetSecuritySeverityLevel() string { + if r == nil || r.SecuritySeverityLevel == nil { + return "" + } + return *r.SecuritySeverityLevel +} + +// GetSeverity returns the Severity field if it's non-nil, zero value otherwise. +func (r *Rule) GetSeverity() string { + if r == nil || r.Severity == nil { + return "" + } + return *r.Severity +} + +// GetRestrictedFilePaths returns the RestrictedFilePaths field if it's non-nil, zero value otherwise. +func (r *RuleFileParameters) GetRestrictedFilePaths() []string { + if r == nil || r.RestrictedFilePaths == nil { + return nil + } + return *r.RestrictedFilePaths +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RulePatternParameters) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetNegate returns the Negate field if it's non-nil, zero value otherwise. +func (r *RulePatternParameters) GetNegate() bool { + if r == nil || r.Negate == nil { + return false + } + return *r.Negate +} + +// GetIntegrationID returns the IntegrationID field if it's non-nil, zero value otherwise. +func (r *RuleRequiredStatusChecks) GetIntegrationID() int64 { + if r == nil || r.IntegrationID == nil { + return 0 + } + return *r.IntegrationID +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (r *RuleRequiredWorkflow) GetRef() string { + if r == nil || r.Ref == nil { + return "" + } + return *r.Ref +} + +// GetRepositoryID returns the RepositoryID field if it's non-nil, zero value otherwise. +func (r *RuleRequiredWorkflow) GetRepositoryID() int64 { + if r == nil || r.RepositoryID == nil { + return 0 + } + return *r.RepositoryID +} + +// GetSha returns the Sha field if it's non-nil, zero value otherwise. +func (r *RuleRequiredWorkflow) GetSha() string { + if r == nil || r.Sha == nil { + return "" + } + return *r.Sha +} + +// GetConditions returns the Conditions field. +func (r *Ruleset) GetConditions() *RulesetConditions { + if r == nil { + return nil + } + return r.Conditions +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *Ruleset) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *Ruleset) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetLinks returns the Links field. +func (r *Ruleset) GetLinks() *RulesetLinks { + if r == nil { + return nil + } + return r.Links +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *Ruleset) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetSourceType returns the SourceType field if it's non-nil, zero value otherwise. +func (r *Ruleset) GetSourceType() string { + if r == nil || r.SourceType == nil { + return "" + } + return *r.SourceType +} + +// GetTarget returns the Target field if it's non-nil, zero value otherwise. +func (r *Ruleset) GetTarget() string { + if r == nil || r.Target == nil { + return "" + } + return *r.Target +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (r *Ruleset) GetUpdatedAt() Timestamp { + if r == nil || r.UpdatedAt == nil { + return Timestamp{} + } + return *r.UpdatedAt +} + +// GetRefName returns the RefName field. +func (r *RulesetConditions) GetRefName() *RulesetRefConditionParameters { + if r == nil { + return nil + } + return r.RefName +} + +// GetRepositoryID returns the RepositoryID field. +func (r *RulesetConditions) GetRepositoryID() *RulesetRepositoryIDsConditionParameters { + if r == nil { + return nil + } + return r.RepositoryID +} + +// GetRepositoryName returns the RepositoryName field. +func (r *RulesetConditions) GetRepositoryName() *RulesetRepositoryNamesConditionParameters { + if r == nil { + return nil + } + return r.RepositoryName +} + +// GetRepositoryProperty returns the RepositoryProperty field. +func (r *RulesetConditions) GetRepositoryProperty() *RulesetRepositoryPropertyConditionParameters { + if r == nil { + return nil + } + return r.RepositoryProperty +} + +// GetHRef returns the HRef field if it's non-nil, zero value otherwise. +func (r *RulesetLink) GetHRef() string { + if r == nil || r.HRef == nil { + return "" + } + return *r.HRef +} + +// GetSelf returns the Self field. +func (r *RulesetLinks) GetSelf() *RulesetLink { + if r == nil { + return nil + } + return r.Self +} + +// GetProtected returns the Protected field if it's non-nil, zero value otherwise. +func (r *RulesetRepositoryNamesConditionParameters) GetProtected() bool { + if r == nil || r.Protected == nil { + return false + } + return *r.Protected +} + +// GetSource returns the Source field if it's non-nil, zero value otherwise. +func (r *RulesetRepositoryPropertyTargetParameters) GetSource() string { + if r == nil || r.Source == nil { + return "" + } + return *r.Source +} + +// GetBusy returns the Busy field if it's non-nil, zero value otherwise. +func (r *Runner) GetBusy() bool { + if r == nil || r.Busy == nil { + return false + } + return *r.Busy +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *Runner) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *Runner) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetOS returns the OS field if it's non-nil, zero value otherwise. +func (r *Runner) GetOS() string { + if r == nil || r.OS == nil { + return "" + } + return *r.OS +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (r *Runner) GetStatus() string { + if r == nil || r.Status == nil { + return "" + } + return *r.Status +} + +// GetArchitecture returns the Architecture field if it's non-nil, zero value otherwise. +func (r *RunnerApplicationDownload) GetArchitecture() string { + if r == nil || r.Architecture == nil { + return "" + } + return *r.Architecture +} + +// GetDownloadURL returns the DownloadURL field if it's non-nil, zero value otherwise. +func (r *RunnerApplicationDownload) GetDownloadURL() string { + if r == nil || r.DownloadURL == nil { + return "" + } + return *r.DownloadURL +} + +// GetFilename returns the Filename field if it's non-nil, zero value otherwise. +func (r *RunnerApplicationDownload) GetFilename() string { + if r == nil || r.Filename == nil { + return "" + } + return *r.Filename +} + +// GetOS returns the OS field if it's non-nil, zero value otherwise. +func (r *RunnerApplicationDownload) GetOS() string { + if r == nil || r.OS == nil { + return "" + } + return *r.OS +} + +// GetSHA256Checksum returns the SHA256Checksum field if it's non-nil, zero value otherwise. +func (r *RunnerApplicationDownload) GetSHA256Checksum() string { + if r == nil || r.SHA256Checksum == nil { + return "" + } + return *r.SHA256Checksum +} + +// GetTempDownloadToken returns the TempDownloadToken field if it's non-nil, zero value otherwise. +func (r *RunnerApplicationDownload) GetTempDownloadToken() string { + if r == nil || r.TempDownloadToken == nil { + return "" + } + return *r.TempDownloadToken +} + +// GetAllowsPublicRepositories returns the AllowsPublicRepositories field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetAllowsPublicRepositories() bool { + if r == nil || r.AllowsPublicRepositories == nil { + return false + } + return *r.AllowsPublicRepositories +} + +// GetDefault returns the Default field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetDefault() bool { + if r == nil || r.Default == nil { + return false + } + return *r.Default +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetInherited returns the Inherited field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetInherited() bool { + if r == nil || r.Inherited == nil { + return false + } + return *r.Inherited +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetRestrictedToWorkflows returns the RestrictedToWorkflows field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetRestrictedToWorkflows() bool { + if r == nil || r.RestrictedToWorkflows == nil { + return false + } + return *r.RestrictedToWorkflows +} + +// GetRunnersURL returns the RunnersURL field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetRunnersURL() string { + if r == nil || r.RunnersURL == nil { + return "" + } + return *r.RunnersURL +} + +// GetSelectedRepositoriesURL returns the SelectedRepositoriesURL field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetSelectedRepositoriesURL() string { + if r == nil || r.SelectedRepositoriesURL == nil { + return "" + } + return *r.SelectedRepositoriesURL +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetVisibility() string { + if r == nil || r.Visibility == nil { + return "" + } + return *r.Visibility +} + +// GetWorkflowRestrictionsReadOnly returns the WorkflowRestrictionsReadOnly field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetWorkflowRestrictionsReadOnly() bool { + if r == nil || r.WorkflowRestrictionsReadOnly == nil { + return false + } + return *r.WorkflowRestrictionsReadOnly +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RunnerLabels) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RunnerLabels) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (r *RunnerLabels) GetType() string { + if r == nil || r.Type == nil { + return "" + } + return *r.Type +} + +// GetCheckoutURI returns the CheckoutURI field if it's non-nil, zero value otherwise. +func (s *SarifAnalysis) GetCheckoutURI() string { + if s == nil || s.CheckoutURI == nil { + return "" + } + return *s.CheckoutURI +} + +// GetCommitSHA returns the CommitSHA field if it's non-nil, zero value otherwise. +func (s *SarifAnalysis) GetCommitSHA() string { + if s == nil || s.CommitSHA == nil { + return "" + } + return *s.CommitSHA +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (s *SarifAnalysis) GetRef() string { + if s == nil || s.Ref == nil { + return "" + } + return *s.Ref +} + +// GetSarif returns the Sarif field if it's non-nil, zero value otherwise. +func (s *SarifAnalysis) GetSarif() string { + if s == nil || s.Sarif == nil { + return "" + } + return *s.Sarif +} + +// GetStartedAt returns the StartedAt field if it's non-nil, zero value otherwise. +func (s *SarifAnalysis) GetStartedAt() Timestamp { + if s == nil || s.StartedAt == nil { + return Timestamp{} + } + return *s.StartedAt +} + +// GetToolName returns the ToolName field if it's non-nil, zero value otherwise. +func (s *SarifAnalysis) GetToolName() string { + if s == nil || s.ToolName == nil { + return "" + } + return *s.ToolName +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *SarifID) GetID() string { + if s == nil || s.ID == nil { + return "" + } + return *s.ID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *SarifID) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetAnalysesURL returns the AnalysesURL field if it's non-nil, zero value otherwise. +func (s *SARIFUpload) GetAnalysesURL() string { + if s == nil || s.AnalysesURL == nil { + return "" + } + return *s.AnalysesURL +} + +// GetProcessingStatus returns the ProcessingStatus field if it's non-nil, zero value otherwise. +func (s *SARIFUpload) GetProcessingStatus() string { + if s == nil || s.ProcessingStatus == nil { + return "" + } + return *s.ProcessingStatus +} + +// GetSBOM returns the SBOM field. +func (s *SBOM) GetSBOM() *SBOMInfo { + if s == nil { + return nil + } + return s.SBOM +} + +// GetCreationInfo returns the CreationInfo field. +func (s *SBOMInfo) GetCreationInfo() *CreationInfo { + if s == nil { + return nil + } + return s.CreationInfo +} + +// GetDataLicense returns the DataLicense field if it's non-nil, zero value otherwise. +func (s *SBOMInfo) GetDataLicense() string { + if s == nil || s.DataLicense == nil { + return "" + } + return *s.DataLicense +} + +// GetDocumentNamespace returns the DocumentNamespace field if it's non-nil, zero value otherwise. +func (s *SBOMInfo) GetDocumentNamespace() string { + if s == nil || s.DocumentNamespace == nil { + return "" + } + return *s.DocumentNamespace +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (s *SBOMInfo) GetName() string { + if s == nil || s.Name == nil { + return "" + } + return *s.Name +} + +// GetSPDXID returns the SPDXID field if it's non-nil, zero value otherwise. +func (s *SBOMInfo) GetSPDXID() string { + if s == nil || s.SPDXID == nil { + return "" + } + return *s.SPDXID +} + +// GetSPDXVersion returns the SPDXVersion field if it's non-nil, zero value otherwise. +func (s *SBOMInfo) GetSPDXVersion() string { + if s == nil || s.SPDXVersion == nil { + return "" + } + return *s.SPDXVersion +} + +// GetAnalysisKey returns the AnalysisKey field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetAnalysisKey() string { + if s == nil || s.AnalysisKey == nil { + return "" + } + return *s.AnalysisKey +} + +// GetCategory returns the Category field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetCategory() string { + if s == nil || s.Category == nil { + return "" + } + return *s.Category +} + +// GetCommitSHA returns the CommitSHA field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetCommitSHA() string { + if s == nil || s.CommitSHA == nil { + return "" + } + return *s.CommitSHA +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetCreatedAt() Timestamp { + if s == nil || s.CreatedAt == nil { + return Timestamp{} + } + return *s.CreatedAt +} + +// GetDeletable returns the Deletable field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetDeletable() bool { + if s == nil || s.Deletable == nil { + return false + } + return *s.Deletable +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetEnvironment() string { + if s == nil || s.Environment == nil { + return "" + } + return *s.Environment +} + +// GetError returns the Error field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetError() string { + if s == nil || s.Error == nil { + return "" + } + return *s.Error +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetID() int64 { + if s == nil || s.ID == nil { + return 0 + } + return *s.ID +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetRef() string { + if s == nil || s.Ref == nil { + return "" + } + return *s.Ref +} + +// GetResultsCount returns the ResultsCount field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetResultsCount() int { + if s == nil || s.ResultsCount == nil { + return 0 + } + return *s.ResultsCount +} + +// GetRulesCount returns the RulesCount field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetRulesCount() int { + if s == nil || s.RulesCount == nil { + return 0 + } + return *s.RulesCount +} + +// GetSarifID returns the SarifID field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetSarifID() string { + if s == nil || s.SarifID == nil { + return "" + } + return *s.SarifID +} + +// GetTool returns the Tool field. +func (s *ScanningAnalysis) GetTool() *Tool { + if s == nil { + return nil + } + return s.Tool +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetWarning returns the Warning field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetWarning() string { + if s == nil || s.Warning == nil { + return "" + } + return *s.Warning +} + +// GetCreated returns the Created field if it's non-nil, zero value otherwise. +func (s *SCIMMeta) GetCreated() Timestamp { + if s == nil || s.Created == nil { + return Timestamp{} + } + return *s.Created +} + +// GetLastModified returns the LastModified field if it's non-nil, zero value otherwise. +func (s *SCIMMeta) GetLastModified() Timestamp { + if s == nil || s.LastModified == nil { + return Timestamp{} + } + return *s.LastModified +} + +// GetLocation returns the Location field if it's non-nil, zero value otherwise. +func (s *SCIMMeta) GetLocation() string { + if s == nil || s.Location == nil { + return "" + } + return *s.Location +} + +// GetResourceType returns the ResourceType field if it's non-nil, zero value otherwise. +func (s *SCIMMeta) GetResourceType() string { + if s == nil || s.ResourceType == nil { + return "" + } + return *s.ResourceType +} + +// GetItemsPerPage returns the ItemsPerPage field if it's non-nil, zero value otherwise. +func (s *SCIMProvisionedIdentities) GetItemsPerPage() int { + if s == nil || s.ItemsPerPage == nil { + return 0 + } + return *s.ItemsPerPage +} + +// GetStartIndex returns the StartIndex field if it's non-nil, zero value otherwise. +func (s *SCIMProvisionedIdentities) GetStartIndex() int { + if s == nil || s.StartIndex == nil { + return 0 + } + return *s.StartIndex +} + +// GetTotalResults returns the TotalResults field if it's non-nil, zero value otherwise. +func (s *SCIMProvisionedIdentities) GetTotalResults() int { + if s == nil || s.TotalResults == nil { + return 0 + } + return *s.TotalResults +} + +// GetActive returns the Active field if it's non-nil, zero value otherwise. +func (s *SCIMUserAttributes) GetActive() bool { + if s == nil || s.Active == nil { + return false + } + return *s.Active +} + +// GetDisplayName returns the DisplayName field if it's non-nil, zero value otherwise. +func (s *SCIMUserAttributes) GetDisplayName() string { + if s == nil || s.DisplayName == nil { + return "" + } + return *s.DisplayName +} + +// GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise. +func (s *SCIMUserAttributes) GetExternalID() string { + if s == nil || s.ExternalID == nil { + return "" + } + return *s.ExternalID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *SCIMUserAttributes) GetID() string { + if s == nil || s.ID == nil { + return "" + } + return *s.ID +} + +// GetMeta returns the Meta field. +func (s *SCIMUserAttributes) GetMeta() *SCIMMeta { + if s == nil { + return nil + } + return s.Meta +} + +// GetPrimary returns the Primary field if it's non-nil, zero value otherwise. +func (s *SCIMUserEmail) GetPrimary() bool { + if s == nil || s.Primary == nil { + return false + } + return *s.Primary +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (s *SCIMUserEmail) GetType() string { + if s == nil || s.Type == nil { + return "" + } + return *s.Type +} + +// GetFormatted returns the Formatted field if it's non-nil, zero value otherwise. +func (s *SCIMUserName) GetFormatted() string { + if s == nil || s.Formatted == nil { + return "" + } + return *s.Formatted +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (s *SecretScanning) GetStatus() string { + if s == nil || s.Status == nil { + return "" + } + return *s.Status +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetCreatedAt() Timestamp { + if s == nil || s.CreatedAt == nil { + return Timestamp{} + } + return *s.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetHTMLURL() string { + if s == nil || s.HTMLURL == nil { + return "" + } + return *s.HTMLURL +} + +// GetLocationsURL returns the LocationsURL field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetLocationsURL() string { + if s == nil || s.LocationsURL == nil { + return "" + } + return *s.LocationsURL +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetNumber() int { + if s == nil || s.Number == nil { + return 0 + } + return *s.Number +} + +// GetPushProtectionBypassed returns the PushProtectionBypassed field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetPushProtectionBypassed() bool { + if s == nil || s.PushProtectionBypassed == nil { + return false + } + return *s.PushProtectionBypassed +} + +// GetPushProtectionBypassedAt returns the PushProtectionBypassedAt field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetPushProtectionBypassedAt() Timestamp { + if s == nil || s.PushProtectionBypassedAt == nil { + return Timestamp{} + } + return *s.PushProtectionBypassedAt +} + +// GetPushProtectionBypassedBy returns the PushProtectionBypassedBy field. +func (s *SecretScanningAlert) GetPushProtectionBypassedBy() *User { + if s == nil { + return nil + } + return s.PushProtectionBypassedBy +} + +// GetRepository returns the Repository field. +func (s *SecretScanningAlert) GetRepository() *Repository { + if s == nil { + return nil + } + return s.Repository +} + +// GetResolution returns the Resolution field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetResolution() string { + if s == nil || s.Resolution == nil { + return "" + } + return *s.Resolution +} + +// GetResolutionComment returns the ResolutionComment field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetResolutionComment() string { + if s == nil || s.ResolutionComment == nil { + return "" + } + return *s.ResolutionComment +} + +// GetResolvedAt returns the ResolvedAt field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetResolvedAt() Timestamp { + if s == nil || s.ResolvedAt == nil { + return Timestamp{} + } + return *s.ResolvedAt +} + +// GetResolvedBy returns the ResolvedBy field. +func (s *SecretScanningAlert) GetResolvedBy() *User { + if s == nil { + return nil + } + return s.ResolvedBy +} + +// GetSecret returns the Secret field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetSecret() string { + if s == nil || s.Secret == nil { + return "" + } + return *s.Secret +} + +// GetSecretType returns the SecretType field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetSecretType() string { + if s == nil || s.SecretType == nil { + return "" + } + return *s.SecretType +} + +// GetSecretTypeDisplayName returns the SecretTypeDisplayName field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetSecretTypeDisplayName() string { + if s == nil || s.SecretTypeDisplayName == nil { + return "" + } + return *s.SecretTypeDisplayName +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetState() string { + if s == nil || s.State == nil { + return "" + } + return *s.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetUpdatedAt() Timestamp { + if s == nil || s.UpdatedAt == nil { + return Timestamp{} + } + return *s.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertEvent) GetAction() string { + if s == nil || s.Action == nil { + return "" + } + return *s.Action +} + +// GetAlert returns the Alert field. +func (s *SecretScanningAlertEvent) GetAlert() *SecretScanningAlert { + if s == nil { + return nil + } + return s.Alert +} + +// GetEnterprise returns the Enterprise field. +func (s *SecretScanningAlertEvent) GetEnterprise() *Enterprise { + if s == nil { + return nil + } + return s.Enterprise +} + +// GetInstallation returns the Installation field. +func (s *SecretScanningAlertEvent) GetInstallation() *Installation { + if s == nil { + return nil + } + return s.Installation +} + +// GetOrganization returns the Organization field. +func (s *SecretScanningAlertEvent) GetOrganization() *Organization { + if s == nil { + return nil + } + return s.Organization +} + +// GetRepo returns the Repo field. +func (s *SecretScanningAlertEvent) GetRepo() *Repository { + if s == nil { + return nil + } + return s.Repo +} + +// GetSender returns the Sender field. +func (s *SecretScanningAlertEvent) GetSender() *User { + if s == nil { + return nil + } + return s.Sender +} + +// GetDetails returns the Details field. +func (s *SecretScanningAlertLocation) GetDetails() *SecretScanningAlertLocationDetails { + if s == nil { + return nil + } + return s.Details +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocation) GetType() string { + if s == nil || s.Type == nil { + return "" + } + return *s.Type +} + +// GetBlobSHA returns the BlobSHA field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetBlobSHA() string { + if s == nil || s.BlobSHA == nil { + return "" + } + return *s.BlobSHA +} + +// GetBlobURL returns the BlobURL field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetBlobURL() string { + if s == nil || s.BlobURL == nil { + return "" + } + return *s.BlobURL +} + +// GetCommitSHA returns the CommitSHA field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetCommitSHA() string { + if s == nil || s.CommitSHA == nil { + return "" + } + return *s.CommitSHA +} + +// GetCommitURL returns the CommitURL field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetCommitURL() string { + if s == nil || s.CommitURL == nil { + return "" + } + return *s.CommitURL +} + +// GetEndColumn returns the EndColumn field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetEndColumn() int { + if s == nil || s.EndColumn == nil { + return 0 + } + return *s.EndColumn +} + +// GetEndLine returns the EndLine field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetEndLine() int { + if s == nil || s.EndLine == nil { + return 0 + } + return *s.EndLine +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetPath() string { + if s == nil || s.Path == nil { + return "" + } + return *s.Path +} + +// GetPullRequestCommentURL returns the PullRequestCommentURL field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetPullRequestCommentURL() string { + if s == nil || s.PullRequestCommentURL == nil { + return "" + } + return *s.PullRequestCommentURL +} + +// GetStartColumn returns the StartColumn field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetStartColumn() int { + if s == nil || s.StartColumn == nil { + return 0 + } + return *s.StartColumn +} + +// GetStartline returns the Startline field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetStartline() int { + if s == nil || s.Startline == nil { + return 0 + } + return *s.Startline +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationEvent) GetAction() string { + if s == nil || s.Action == nil { + return "" + } + return *s.Action +} + +// GetAlert returns the Alert field. +func (s *SecretScanningAlertLocationEvent) GetAlert() *SecretScanningAlert { + if s == nil { + return nil + } + return s.Alert +} + +// GetInstallation returns the Installation field. +func (s *SecretScanningAlertLocationEvent) GetInstallation() *Installation { + if s == nil { + return nil + } + return s.Installation +} + +// GetLocation returns the Location field. +func (s *SecretScanningAlertLocationEvent) GetLocation() *SecretScanningAlertLocation { + if s == nil { + return nil + } + return s.Location +} + +// GetOrganization returns the Organization field. +func (s *SecretScanningAlertLocationEvent) GetOrganization() *Organization { + if s == nil { + return nil + } + return s.Organization +} + +// GetRepo returns the Repo field. +func (s *SecretScanningAlertLocationEvent) GetRepo() *Repository { + if s == nil { + return nil + } + return s.Repo +} + +// GetSender returns the Sender field. +func (s *SecretScanningAlertLocationEvent) GetSender() *User { + if s == nil { + return nil + } + return s.Sender +} + +// GetResolution returns the Resolution field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertUpdateOptions) GetResolution() string { + if s == nil || s.Resolution == nil { + return "" + } + return *s.Resolution +} + +// GetResolutionComment returns the ResolutionComment field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertUpdateOptions) GetResolutionComment() string { + if s == nil || s.ResolutionComment == nil { + return "" + } + return *s.ResolutionComment +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (s *SecretScanningPushProtection) GetStatus() string { + if s == nil || s.Status == nil { + return "" + } + return *s.Status +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (s *SecretScanningValidityChecks) GetStatus() string { + if s == nil || s.Status == nil { + return "" + } + return *s.Status +} + +// GetAuthor returns the Author field. +func (s *SecurityAdvisory) GetAuthor() *User { + if s == nil { + return nil + } + return s.Author +} + +// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetClosedAt() Timestamp { + if s == nil || s.ClosedAt == nil { + return Timestamp{} + } + return *s.ClosedAt +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetCreatedAt() Timestamp { + if s == nil || s.CreatedAt == nil { + return Timestamp{} + } + return *s.CreatedAt +} + +// GetCVEID returns the CVEID field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetCVEID() string { + if s == nil || s.CVEID == nil { + return "" + } + return *s.CVEID +} + +// GetCVSS returns the CVSS field. +func (s *SecurityAdvisory) GetCVSS() *AdvisoryCVSS { + if s == nil { + return nil + } + return s.CVSS +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetDescription() string { + if s == nil || s.Description == nil { + return "" + } + return *s.Description +} + +// GetGHSAID returns the GHSAID field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetGHSAID() string { + if s == nil || s.GHSAID == nil { + return "" + } + return *s.GHSAID +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetHTMLURL() string { + if s == nil || s.HTMLURL == nil { + return "" + } + return *s.HTMLURL +} + +// GetPrivateFork returns the PrivateFork field. +func (s *SecurityAdvisory) GetPrivateFork() *Repository { + if s == nil { + return nil + } + return s.PrivateFork +} + +// GetPublishedAt returns the PublishedAt field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetPublishedAt() Timestamp { + if s == nil || s.PublishedAt == nil { + return Timestamp{} + } + return *s.PublishedAt +} + +// GetPublisher returns the Publisher field. +func (s *SecurityAdvisory) GetPublisher() *User { + if s == nil { + return nil + } + return s.Publisher +} + +// GetSeverity returns the Severity field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetSeverity() string { + if s == nil || s.Severity == nil { + return "" + } + return *s.Severity +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetState() string { + if s == nil || s.State == nil { + return "" + } + return *s.State +} + +// GetSubmission returns the Submission field. +func (s *SecurityAdvisory) GetSubmission() *SecurityAdvisorySubmission { + if s == nil { + return nil + } + return s.Submission +} + +// GetSummary returns the Summary field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetSummary() string { + if s == nil || s.Summary == nil { + return "" + } + return *s.Summary +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetUpdatedAt() Timestamp { + if s == nil || s.UpdatedAt == nil { + return Timestamp{} + } + return *s.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetWithdrawnAt returns the WithdrawnAt field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetWithdrawnAt() Timestamp { + if s == nil || s.WithdrawnAt == nil { + return Timestamp{} + } + return *s.WithdrawnAt +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisoryEvent) GetAction() string { + if s == nil || s.Action == nil { + return "" + } + return *s.Action +} + +// GetEnterprise returns the Enterprise field. +func (s *SecurityAdvisoryEvent) GetEnterprise() *Enterprise { + if s == nil { + return nil + } + return s.Enterprise +} + +// GetInstallation returns the Installation field. +func (s *SecurityAdvisoryEvent) GetInstallation() *Installation { + if s == nil { + return nil + } + return s.Installation +} + +// GetOrganization returns the Organization field. +func (s *SecurityAdvisoryEvent) GetOrganization() *Organization { + if s == nil { + return nil + } + return s.Organization +} + +// GetRepository returns the Repository field. +func (s *SecurityAdvisoryEvent) GetRepository() *Repository { + if s == nil { + return nil + } + return s.Repository +} + +// GetSecurityAdvisory returns the SecurityAdvisory field. +func (s *SecurityAdvisoryEvent) GetSecurityAdvisory() *SecurityAdvisory { + if s == nil { + return nil + } + return s.SecurityAdvisory +} + +// GetSender returns the Sender field. +func (s *SecurityAdvisoryEvent) GetSender() *User { + if s == nil { + return nil + } + return s.Sender +} + +// GetAccepted returns the Accepted field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisorySubmission) GetAccepted() bool { + if s == nil || s.Accepted == nil { + return false + } + return *s.Accepted +} + +// GetAdvancedSecurity returns the AdvancedSecurity field. +func (s *SecurityAndAnalysis) GetAdvancedSecurity() *AdvancedSecurity { + if s == nil { + return nil + } + return s.AdvancedSecurity +} + +// GetDependabotSecurityUpdates returns the DependabotSecurityUpdates field. +func (s *SecurityAndAnalysis) GetDependabotSecurityUpdates() *DependabotSecurityUpdates { + if s == nil { + return nil + } + return s.DependabotSecurityUpdates +} + +// GetSecretScanning returns the SecretScanning field. +func (s *SecurityAndAnalysis) GetSecretScanning() *SecretScanning { + if s == nil { + return nil + } + return s.SecretScanning +} + +// GetSecretScanningPushProtection returns the SecretScanningPushProtection field. +func (s *SecurityAndAnalysis) GetSecretScanningPushProtection() *SecretScanningPushProtection { + if s == nil { + return nil + } + return s.SecretScanningPushProtection +} + +// GetSecretScanningValidityChecks returns the SecretScanningValidityChecks field. +func (s *SecurityAndAnalysis) GetSecretScanningValidityChecks() *SecretScanningValidityChecks { + if s == nil { + return nil + } + return s.SecretScanningValidityChecks +} + +// GetFrom returns the From field. +func (s *SecurityAndAnalysisChange) GetFrom() *SecurityAndAnalysisChangeFrom { + if s == nil { + return nil + } + return s.From +} + +// GetSecurityAndAnalysis returns the SecurityAndAnalysis field. +func (s *SecurityAndAnalysisChangeFrom) GetSecurityAndAnalysis() *SecurityAndAnalysis { + if s == nil { + return nil + } + return s.SecurityAndAnalysis +} + +// GetChanges returns the Changes field. +func (s *SecurityAndAnalysisEvent) GetChanges() *SecurityAndAnalysisChange { + if s == nil { + return nil + } + return s.Changes +} + +// GetEnterprise returns the Enterprise field. +func (s *SecurityAndAnalysisEvent) GetEnterprise() *Enterprise { + if s == nil { + return nil + } + return s.Enterprise +} + +// GetInstallation returns the Installation field. +func (s *SecurityAndAnalysisEvent) GetInstallation() *Installation { + if s == nil { + return nil + } + return s.Installation +} + +// GetOrganization returns the Organization field. +func (s *SecurityAndAnalysisEvent) GetOrganization() *Organization { + if s == nil { + return nil + } + return s.Organization +} + +// GetRepository returns the Repository field. +func (s *SecurityAndAnalysisEvent) GetRepository() *Repository { + if s == nil { + return nil + } + return s.Repository +} + +// GetSender returns the Sender field. +func (s *SecurityAndAnalysisEvent) GetSender() *User { + if s == nil { + return nil + } + return s.Sender +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (s *SelectedReposList) GetTotalCount() int { + if s == nil || s.TotalCount == nil { + return 0 + } + return *s.TotalCount +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (s *SignatureRequirementEnforcementLevelChanges) GetFrom() string { + if s == nil || s.From == nil { + return "" + } + return *s.From +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (s *SignaturesProtectedBranch) GetEnabled() bool { + if s == nil || s.Enabled == nil { + return false + } + return *s.Enabled +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *SignaturesProtectedBranch) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetPayload returns the Payload field if it's non-nil, zero value otherwise. +func (s *SignatureVerification) GetPayload() string { + if s == nil || s.Payload == nil { + return "" + } + return *s.Payload +} + +// GetReason returns the Reason field if it's non-nil, zero value otherwise. +func (s *SignatureVerification) GetReason() string { + if s == nil || s.Reason == nil { + return "" + } + return *s.Reason +} + +// GetSignature returns the Signature field if it's non-nil, zero value otherwise. +func (s *SignatureVerification) GetSignature() string { + if s == nil || s.Signature == nil { + return "" + } + return *s.Signature +} + +// GetVerified returns the Verified field if it's non-nil, zero value otherwise. +func (s *SignatureVerification) GetVerified() bool { + if s == nil || s.Verified == nil { + return false + } + return *s.Verified +} + +// GetActor returns the Actor field. +func (s *Source) GetActor() *User { + if s == nil { + return nil + } + return s.Actor +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *Source) GetID() int64 { + if s == nil || s.ID == nil { + return 0 + } + return *s.ID +} + +// GetIssue returns the Issue field. +func (s *Source) GetIssue() *Issue { + if s == nil { + return nil + } + return s.Issue +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (s *Source) GetType() string { + if s == nil || s.Type == nil { + return "" + } + return *s.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *Source) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetEmail() string { + if s == nil || s.Email == nil { + return "" + } + return *s.Email +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetID() int64 { + if s == nil || s.ID == nil { + return 0 + } + return *s.ID +} + +// GetImportURL returns the ImportURL field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetImportURL() string { + if s == nil || s.ImportURL == nil { + return "" + } + return *s.ImportURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetName() string { + if s == nil || s.Name == nil { + return "" + } + return *s.Name +} + +// GetRemoteID returns the RemoteID field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetRemoteID() string { + if s == nil || s.RemoteID == nil { + return "" + } + return *s.RemoteID +} + +// GetRemoteName returns the RemoteName field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetRemoteName() string { + if s == nil || s.RemoteName == nil { + return "" + } + return *s.RemoteName +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetPrivacyLevel returns the PrivacyLevel field if it's non-nil, zero value otherwise. +func (s *SponsorshipChanges) GetPrivacyLevel() string { + if s == nil || s.PrivacyLevel == nil { + return "" + } + return *s.PrivacyLevel +} + +// GetTier returns the Tier field. +func (s *SponsorshipChanges) GetTier() *SponsorshipTier { + if s == nil { + return nil + } + return s.Tier +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (s *SponsorshipEvent) GetAction() string { + if s == nil || s.Action == nil { + return "" + } + return *s.Action +} + +// GetChanges returns the Changes field. +func (s *SponsorshipEvent) GetChanges() *SponsorshipChanges { + if s == nil { + return nil + } + return s.Changes +} + +// GetEffectiveDate returns the EffectiveDate field if it's non-nil, zero value otherwise. +func (s *SponsorshipEvent) GetEffectiveDate() string { + if s == nil || s.EffectiveDate == nil { + return "" + } + return *s.EffectiveDate +} + +// GetInstallation returns the Installation field. +func (s *SponsorshipEvent) GetInstallation() *Installation { + if s == nil { + return nil + } + return s.Installation +} + +// GetOrganization returns the Organization field. +func (s *SponsorshipEvent) GetOrganization() *Organization { + if s == nil { + return nil + } + return s.Organization +} + +// GetRepository returns the Repository field. +func (s *SponsorshipEvent) GetRepository() *Repository { + if s == nil { + return nil + } + return s.Repository +} + +// GetSender returns the Sender field. +func (s *SponsorshipEvent) GetSender() *User { + if s == nil { + return nil + } + return s.Sender +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (s *SponsorshipTier) GetFrom() string { + if s == nil || s.From == nil { + return "" + } + return *s.From +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (s *SSHSigningKey) GetCreatedAt() Timestamp { + if s == nil || s.CreatedAt == nil { + return Timestamp{} + } + return *s.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *SSHSigningKey) GetID() int64 { + if s == nil || s.ID == nil { + return 0 + } + return *s.ID +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (s *SSHSigningKey) GetKey() string { + if s == nil || s.Key == nil { + return "" + } + return *s.Key +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (s *SSHSigningKey) GetTitle() string { + if s == nil || s.Title == nil { + return "" + } + return *s.Title +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (s *StarEvent) GetAction() string { + if s == nil || s.Action == nil { + return "" + } + return *s.Action +} + +// GetInstallation returns the Installation field. +func (s *StarEvent) GetInstallation() *Installation { + if s == nil { + return nil + } + return s.Installation +} + +// GetOrg returns the Org field. +func (s *StarEvent) GetOrg() *Organization { + if s == nil { + return nil + } + return s.Org +} + +// GetRepo returns the Repo field. +func (s *StarEvent) GetRepo() *Repository { + if s == nil { + return nil + } + return s.Repo +} + +// GetSender returns the Sender field. +func (s *StarEvent) GetSender() *User { + if s == nil { + return nil + } + return s.Sender +} + +// GetStarredAt returns the StarredAt field if it's non-nil, zero value otherwise. +func (s *StarEvent) GetStarredAt() Timestamp { + if s == nil || s.StarredAt == nil { + return Timestamp{} + } + return *s.StarredAt +} + +// GetStarredAt returns the StarredAt field if it's non-nil, zero value otherwise. +func (s *Stargazer) GetStarredAt() Timestamp { + if s == nil || s.StarredAt == nil { + return Timestamp{} + } + return *s.StarredAt +} + +// GetUser returns the User field. +func (s *Stargazer) GetUser() *User { + if s == nil { + return nil + } + return s.User +} + +// GetRepository returns the Repository field. +func (s *StarredRepository) GetRepository() *Repository { + if s == nil { + return nil + } + return s.Repository +} + +// GetStarredAt returns the StarredAt field if it's non-nil, zero value otherwise. +func (s *StarredRepository) GetStarredAt() Timestamp { + if s == nil || s.StarredAt == nil { + return Timestamp{} + } + return *s.StarredAt +} + +// GetCommit returns the Commit field. +func (s *StatusEvent) GetCommit() *RepositoryCommit { + if s == nil { + return nil + } + return s.Commit +} + +// GetContext returns the Context field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetContext() string { + if s == nil || s.Context == nil { + return "" + } + return *s.Context +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetCreatedAt() Timestamp { + if s == nil || s.CreatedAt == nil { + return Timestamp{} + } + return *s.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetDescription() string { + if s == nil || s.Description == nil { + return "" + } + return *s.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetID() int64 { + if s == nil || s.ID == nil { + return 0 + } + return *s.ID +} + +// GetInstallation returns the Installation field. +func (s *StatusEvent) GetInstallation() *Installation { + if s == nil { + return nil + } + return s.Installation +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetName() string { + if s == nil || s.Name == nil { + return "" + } + return *s.Name +} + +// GetOrg returns the Org field. +func (s *StatusEvent) GetOrg() *Organization { + if s == nil { + return nil + } + return s.Org +} + +// GetRepo returns the Repo field. +func (s *StatusEvent) GetRepo() *Repository { + if s == nil { + return nil + } + return s.Repo +} + +// GetSender returns the Sender field. +func (s *StatusEvent) GetSender() *User { + if s == nil { + return nil + } + return s.Sender +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetSHA() string { + if s == nil || s.SHA == nil { + return "" + } + return *s.SHA +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetState() string { + if s == nil || s.State == nil { + return "" + } + return *s.State +} + +// GetTargetURL returns the TargetURL field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetTargetURL() string { + if s == nil || s.TargetURL == nil { + return "" + } + return *s.TargetURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetUpdatedAt() Timestamp { + if s == nil || s.UpdatedAt == nil { + return Timestamp{} + } + return *s.UpdatedAt +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (s *Subscription) GetCreatedAt() Timestamp { + if s == nil || s.CreatedAt == nil { + return Timestamp{} + } + return *s.CreatedAt +} + +// GetIgnored returns the Ignored field if it's non-nil, zero value otherwise. +func (s *Subscription) GetIgnored() bool { + if s == nil || s.Ignored == nil { + return false + } + return *s.Ignored +} + +// GetReason returns the Reason field if it's non-nil, zero value otherwise. +func (s *Subscription) GetReason() string { + if s == nil || s.Reason == nil { + return "" + } + return *s.Reason +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (s *Subscription) GetRepositoryURL() string { + if s == nil || s.RepositoryURL == nil { + return "" + } + return *s.RepositoryURL +} + +// GetSubscribed returns the Subscribed field if it's non-nil, zero value otherwise. +func (s *Subscription) GetSubscribed() bool { + if s == nil || s.Subscribed == nil { + return false + } + return *s.Subscribed +} + +// GetThreadURL returns the ThreadURL field if it's non-nil, zero value otherwise. +func (s *Subscription) GetThreadURL() string { + if s == nil || s.ThreadURL == nil { + return "" + } + return *s.ThreadURL +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *Subscription) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (t *Tag) GetMessage() string { + if t == nil || t.Message == nil { + return "" + } + return *t.Message +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (t *Tag) GetNodeID() string { + if t == nil || t.NodeID == nil { + return "" + } + return *t.NodeID +} + +// GetObject returns the Object field. +func (t *Tag) GetObject() *GitObject { + if t == nil { + return nil + } + return t.Object +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (t *Tag) GetSHA() string { + if t == nil || t.SHA == nil { + return "" + } + return *t.SHA +} + +// GetTag returns the Tag field if it's non-nil, zero value otherwise. +func (t *Tag) GetTag() string { + if t == nil || t.Tag == nil { + return "" + } + return *t.Tag +} + +// GetTagger returns the Tagger field. +func (t *Tag) GetTagger() *CommitAuthor { + if t == nil { + return nil + } + return t.Tagger +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *Tag) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetVerification returns the Verification field. +func (t *Tag) GetVerification() *SignatureVerification { + if t == nil { + return nil + } + return t.Verification +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (t *TagProtection) GetID() int64 { + if t == nil || t.ID == nil { + return 0 + } + return *t.ID +} + +// GetPattern returns the Pattern field if it's non-nil, zero value otherwise. +func (t *TagProtection) GetPattern() string { + if t == nil || t.Pattern == nil { + return "" + } + return *t.Pattern +} + +// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. +func (t *TaskStep) GetCompletedAt() Timestamp { + if t == nil || t.CompletedAt == nil { + return Timestamp{} + } + return *t.CompletedAt +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (t *TaskStep) GetConclusion() string { + if t == nil || t.Conclusion == nil { + return "" + } + return *t.Conclusion +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (t *TaskStep) GetName() string { + if t == nil || t.Name == nil { + return "" + } + return *t.Name +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (t *TaskStep) GetNumber() int64 { + if t == nil || t.Number == nil { + return 0 + } + return *t.Number +} + +// GetStartedAt returns the StartedAt field if it's non-nil, zero value otherwise. +func (t *TaskStep) GetStartedAt() Timestamp { + if t == nil || t.StartedAt == nil { + return Timestamp{} + } + return *t.StartedAt +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (t *TaskStep) GetStatus() string { + if t == nil || t.Status == nil { + return "" + } + return *t.Status +} + +// GetAssignment returns the Assignment field if it's non-nil, zero value otherwise. +func (t *Team) GetAssignment() string { + if t == nil || t.Assignment == nil { + return "" + } + return *t.Assignment +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (t *Team) GetDescription() string { + if t == nil || t.Description == nil { + return "" + } + return *t.Description +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (t *Team) GetHTMLURL() string { + if t == nil || t.HTMLURL == nil { + return "" + } + return *t.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (t *Team) GetID() int64 { + if t == nil || t.ID == nil { + return 0 + } + return *t.ID +} + +// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. +func (t *Team) GetLDAPDN() string { + if t == nil || t.LDAPDN == nil { + return "" + } + return *t.LDAPDN +} + +// GetMembersCount returns the MembersCount field if it's non-nil, zero value otherwise. +func (t *Team) GetMembersCount() int { + if t == nil || t.MembersCount == nil { + return 0 + } + return *t.MembersCount +} + +// GetMembersURL returns the MembersURL field if it's non-nil, zero value otherwise. +func (t *Team) GetMembersURL() string { + if t == nil || t.MembersURL == nil { + return "" + } + return *t.MembersURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (t *Team) GetName() string { + if t == nil || t.Name == nil { + return "" + } + return *t.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (t *Team) GetNodeID() string { + if t == nil || t.NodeID == nil { + return "" + } + return *t.NodeID +} + +// GetOrganization returns the Organization field. +func (t *Team) GetOrganization() *Organization { + if t == nil { + return nil + } + return t.Organization +} + +// GetParent returns the Parent field. +func (t *Team) GetParent() *Team { + if t == nil { + return nil + } + return t.Parent +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (t *Team) GetPermission() string { + if t == nil || t.Permission == nil { + return "" + } + return *t.Permission +} + +// GetPermissions returns the Permissions map if it's non-nil, an empty map otherwise. +func (t *Team) GetPermissions() map[string]bool { + if t == nil || t.Permissions == nil { + return map[string]bool{} + } + return t.Permissions +} + +// GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise. +func (t *Team) GetPrivacy() string { + if t == nil || t.Privacy == nil { + return "" + } + return *t.Privacy +} + +// GetReposCount returns the ReposCount field if it's non-nil, zero value otherwise. +func (t *Team) GetReposCount() int { + if t == nil || t.ReposCount == nil { + return 0 + } + return *t.ReposCount +} + +// GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise. +func (t *Team) GetRepositoriesURL() string { + if t == nil || t.RepositoriesURL == nil { + return "" + } + return *t.RepositoriesURL +} + +// GetSlug returns the Slug field if it's non-nil, zero value otherwise. +func (t *Team) GetSlug() string { + if t == nil || t.Slug == nil { + return "" + } + return *t.Slug +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *Team) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetInstallation returns the Installation field. +func (t *TeamAddEvent) GetInstallation() *Installation { + if t == nil { + return nil + } + return t.Installation +} + +// GetOrg returns the Org field. +func (t *TeamAddEvent) GetOrg() *Organization { + if t == nil { + return nil + } + return t.Org +} + +// GetRepo returns the Repo field. +func (t *TeamAddEvent) GetRepo() *Repository { + if t == nil { + return nil + } + return t.Repo +} + +// GetSender returns the Sender field. +func (t *TeamAddEvent) GetSender() *User { + if t == nil { + return nil + } + return t.Sender +} + +// GetTeam returns the Team field. +func (t *TeamAddEvent) GetTeam() *Team { + if t == nil { + return nil + } + return t.Team +} + +// GetDescription returns the Description field. +func (t *TeamChange) GetDescription() *TeamDescription { + if t == nil { + return nil + } + return t.Description +} + +// GetName returns the Name field. +func (t *TeamChange) GetName() *TeamName { + if t == nil { + return nil + } + return t.Name +} + +// GetPrivacy returns the Privacy field. +func (t *TeamChange) GetPrivacy() *TeamPrivacy { + if t == nil { + return nil + } + return t.Privacy +} + +// GetRepository returns the Repository field. +func (t *TeamChange) GetRepository() *TeamRepository { + if t == nil { + return nil + } + return t.Repository +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (t *TeamDescription) GetFrom() string { + if t == nil || t.From == nil { + return "" + } + return *t.From +} + +// GetAuthor returns the Author field. +func (t *TeamDiscussion) GetAuthor() *User { + if t == nil { + return nil + } + return t.Author +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetBody() string { + if t == nil || t.Body == nil { + return "" + } + return *t.Body +} + +// GetBodyHTML returns the BodyHTML field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetBodyHTML() string { + if t == nil || t.BodyHTML == nil { + return "" + } + return *t.BodyHTML +} + +// GetBodyVersion returns the BodyVersion field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetBodyVersion() string { + if t == nil || t.BodyVersion == nil { + return "" + } + return *t.BodyVersion +} + +// GetCommentsCount returns the CommentsCount field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetCommentsCount() int { + if t == nil || t.CommentsCount == nil { + return 0 + } + return *t.CommentsCount +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetCommentsURL() string { + if t == nil || t.CommentsURL == nil { + return "" + } + return *t.CommentsURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetCreatedAt() Timestamp { + if t == nil || t.CreatedAt == nil { + return Timestamp{} + } + return *t.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetHTMLURL() string { + if t == nil || t.HTMLURL == nil { + return "" + } + return *t.HTMLURL +} + +// GetLastEditedAt returns the LastEditedAt field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetLastEditedAt() Timestamp { + if t == nil || t.LastEditedAt == nil { + return Timestamp{} + } + return *t.LastEditedAt +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetNodeID() string { + if t == nil || t.NodeID == nil { + return "" + } + return *t.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetNumber() int { + if t == nil || t.Number == nil { + return 0 + } + return *t.Number +} + +// GetPinned returns the Pinned field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetPinned() bool { + if t == nil || t.Pinned == nil { + return false + } + return *t.Pinned +} + +// GetPrivate returns the Private field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetPrivate() bool { + if t == nil || t.Private == nil { + return false + } + return *t.Private +} + +// GetReactions returns the Reactions field. +func (t *TeamDiscussion) GetReactions() *Reactions { + if t == nil { + return nil + } + return t.Reactions +} + +// GetTeamURL returns the TeamURL field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetTeamURL() string { + if t == nil || t.TeamURL == nil { + return "" + } + return *t.TeamURL +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetTitle() string { + if t == nil || t.Title == nil { + return "" + } + return *t.Title +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetUpdatedAt() Timestamp { + if t == nil || t.UpdatedAt == nil { + return Timestamp{} + } + return *t.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (t *TeamEvent) GetAction() string { + if t == nil || t.Action == nil { + return "" + } + return *t.Action +} + +// GetChanges returns the Changes field. +func (t *TeamEvent) GetChanges() *TeamChange { + if t == nil { + return nil + } + return t.Changes +} + +// GetInstallation returns the Installation field. +func (t *TeamEvent) GetInstallation() *Installation { + if t == nil { + return nil + } + return t.Installation +} + +// GetOrg returns the Org field. +func (t *TeamEvent) GetOrg() *Organization { + if t == nil { + return nil + } + return t.Org +} + +// GetRepo returns the Repo field. +func (t *TeamEvent) GetRepo() *Repository { + if t == nil { + return nil + } + return t.Repo +} + +// GetSender returns the Sender field. +func (t *TeamEvent) GetSender() *User { + if t == nil { + return nil + } + return t.Sender +} + +// GetTeam returns the Team field. +func (t *TeamEvent) GetTeam() *Team { + if t == nil { + return nil + } + return t.Team +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetDescription() string { + if t == nil || t.Description == nil { + return "" + } + return *t.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetID() int64 { + if t == nil || t.ID == nil { + return 0 + } + return *t.ID +} + +// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetLDAPDN() string { + if t == nil || t.LDAPDN == nil { + return "" + } + return *t.LDAPDN +} + +// GetMembersURL returns the MembersURL field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetMembersURL() string { + if t == nil || t.MembersURL == nil { + return "" + } + return *t.MembersURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetName() string { + if t == nil || t.Name == nil { + return "" + } + return *t.Name +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetPermission() string { + if t == nil || t.Permission == nil { + return "" + } + return *t.Permission +} + +// GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetPrivacy() string { + if t == nil || t.Privacy == nil { + return "" + } + return *t.Privacy +} + +// GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetRepositoriesURL() string { + if t == nil || t.RepositoriesURL == nil { + return "" + } + return *t.RepositoriesURL +} + +// GetSlug returns the Slug field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetSlug() string { + if t == nil || t.Slug == nil { + return "" + } + return *t.Slug +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (t *TeamName) GetFrom() string { + if t == nil || t.From == nil { + return "" + } + return *t.From +} + +// GetFrom returns the From field. +func (t *TeamPermissions) GetFrom() *TeamPermissionsFrom { + if t == nil { + return nil + } + return t.From +} + +// GetAdmin returns the Admin field if it's non-nil, zero value otherwise. +func (t *TeamPermissionsFrom) GetAdmin() bool { + if t == nil || t.Admin == nil { + return false + } + return *t.Admin +} + +// GetPull returns the Pull field if it's non-nil, zero value otherwise. +func (t *TeamPermissionsFrom) GetPull() bool { + if t == nil || t.Pull == nil { + return false + } + return *t.Pull +} + +// GetPush returns the Push field if it's non-nil, zero value otherwise. +func (t *TeamPermissionsFrom) GetPush() bool { + if t == nil || t.Push == nil { + return false + } + return *t.Push +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (t *TeamPrivacy) GetFrom() string { + if t == nil || t.From == nil { + return "" + } + return *t.From +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (t *TeamProjectOptions) GetPermission() string { + if t == nil || t.Permission == nil { + return "" + } + return *t.Permission +} + +// GetPermissions returns the Permissions field. +func (t *TeamRepository) GetPermissions() *TeamPermissions { + if t == nil { + return nil + } + return t.Permissions +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (t *TemplateRepoRequest) GetDescription() string { + if t == nil || t.Description == nil { + return "" + } + return *t.Description +} + +// GetIncludeAllBranches returns the IncludeAllBranches field if it's non-nil, zero value otherwise. +func (t *TemplateRepoRequest) GetIncludeAllBranches() bool { + if t == nil || t.IncludeAllBranches == nil { + return false + } + return *t.IncludeAllBranches +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (t *TemplateRepoRequest) GetName() string { + if t == nil || t.Name == nil { + return "" + } + return *t.Name +} + +// GetOwner returns the Owner field if it's non-nil, zero value otherwise. +func (t *TemplateRepoRequest) GetOwner() string { + if t == nil || t.Owner == nil { + return "" + } + return *t.Owner +} + +// GetPrivate returns the Private field if it's non-nil, zero value otherwise. +func (t *TemplateRepoRequest) GetPrivate() bool { + if t == nil || t.Private == nil { + return false + } + return *t.Private +} + +// GetFragment returns the Fragment field if it's non-nil, zero value otherwise. +func (t *TextMatch) GetFragment() string { + if t == nil || t.Fragment == nil { + return "" + } + return *t.Fragment +} + +// GetObjectType returns the ObjectType field if it's non-nil, zero value otherwise. +func (t *TextMatch) GetObjectType() string { + if t == nil || t.ObjectType == nil { + return "" + } + return *t.ObjectType +} + +// GetObjectURL returns the ObjectURL field if it's non-nil, zero value otherwise. +func (t *TextMatch) GetObjectURL() string { + if t == nil || t.ObjectURL == nil { + return "" + } + return *t.ObjectURL +} + +// GetProperty returns the Property field if it's non-nil, zero value otherwise. +func (t *TextMatch) GetProperty() string { + if t == nil || t.Property == nil { + return "" + } + return *t.Property +} + +// GetActor returns the Actor field. +func (t *Timeline) GetActor() *User { + if t == nil { + return nil + } + return t.Actor +} + +// GetAssignee returns the Assignee field. +func (t *Timeline) GetAssignee() *User { + if t == nil { + return nil + } + return t.Assignee +} + +// GetAssigner returns the Assigner field. +func (t *Timeline) GetAssigner() *User { + if t == nil { + return nil + } + return t.Assigner +} + +// GetAuthor returns the Author field. +func (t *Timeline) GetAuthor() *CommitAuthor { + if t == nil { + return nil + } + return t.Author +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (t *Timeline) GetBody() string { + if t == nil || t.Body == nil { + return "" + } + return *t.Body +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (t *Timeline) GetCommitID() string { + if t == nil || t.CommitID == nil { + return "" + } + return *t.CommitID +} + +// GetCommitter returns the Committer field. +func (t *Timeline) GetCommitter() *CommitAuthor { + if t == nil { + return nil + } + return t.Committer +} + +// GetCommitURL returns the CommitURL field if it's non-nil, zero value otherwise. +func (t *Timeline) GetCommitURL() string { + if t == nil || t.CommitURL == nil { + return "" + } + return *t.CommitURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (t *Timeline) GetCreatedAt() Timestamp { + if t == nil || t.CreatedAt == nil { + return Timestamp{} + } + return *t.CreatedAt +} + +// GetEvent returns the Event field if it's non-nil, zero value otherwise. +func (t *Timeline) GetEvent() string { + if t == nil || t.Event == nil { + return "" + } + return *t.Event +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (t *Timeline) GetID() int64 { + if t == nil || t.ID == nil { + return 0 + } + return *t.ID +} + +// GetLabel returns the Label field. +func (t *Timeline) GetLabel() *Label { + if t == nil { + return nil + } + return t.Label +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (t *Timeline) GetMessage() string { + if t == nil || t.Message == nil { + return "" + } + return *t.Message +} + +// GetMilestone returns the Milestone field. +func (t *Timeline) GetMilestone() *Milestone { + if t == nil { + return nil + } + return t.Milestone +} + +// GetPerformedViaGithubApp returns the PerformedViaGithubApp field. +func (t *Timeline) GetPerformedViaGithubApp() *App { + if t == nil { + return nil + } + return t.PerformedViaGithubApp +} + +// GetRename returns the Rename field. +func (t *Timeline) GetRename() *Rename { + if t == nil { + return nil + } + return t.Rename +} + +// GetRequestedTeam returns the RequestedTeam field. +func (t *Timeline) GetRequestedTeam() *Team { + if t == nil { + return nil + } + return t.RequestedTeam +} + +// GetRequester returns the Requester field. +func (t *Timeline) GetRequester() *User { + if t == nil { + return nil + } + return t.Requester +} + +// GetReviewer returns the Reviewer field. +func (t *Timeline) GetReviewer() *User { + if t == nil { + return nil + } + return t.Reviewer +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (t *Timeline) GetSHA() string { + if t == nil || t.SHA == nil { + return "" + } + return *t.SHA +} + +// GetSource returns the Source field. +func (t *Timeline) GetSource() *Source { + if t == nil { + return nil + } + return t.Source +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (t *Timeline) GetState() string { + if t == nil || t.State == nil { + return "" + } + return *t.State +} + +// GetSubmittedAt returns the SubmittedAt field if it's non-nil, zero value otherwise. +func (t *Timeline) GetSubmittedAt() Timestamp { + if t == nil || t.SubmittedAt == nil { + return Timestamp{} + } + return *t.SubmittedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *Timeline) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetUser returns the User field. +func (t *Timeline) GetUser() *User { + if t == nil { + return nil + } + return t.User +} + +// GetGUID returns the GUID field if it's non-nil, zero value otherwise. +func (t *Tool) GetGUID() string { + if t == nil || t.GUID == nil { + return "" + } + return *t.GUID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (t *Tool) GetName() string { + if t == nil || t.Name == nil { + return "" + } + return *t.Name +} + +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (t *Tool) GetVersion() string { + if t == nil || t.Version == nil { + return "" + } + return *t.Version +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetCreatedAt() Timestamp { + if t == nil || t.CreatedAt == nil { + return Timestamp{} + } + return *t.CreatedAt +} + +// GetCreatedBy returns the CreatedBy field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetCreatedBy() string { + if t == nil || t.CreatedBy == nil { + return "" + } + return *t.CreatedBy +} + +// GetCurated returns the Curated field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetCurated() bool { + if t == nil || t.Curated == nil { + return false + } + return *t.Curated +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetDescription() string { + if t == nil || t.Description == nil { + return "" + } + return *t.Description +} + +// GetDisplayName returns the DisplayName field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetDisplayName() string { + if t == nil || t.DisplayName == nil { + return "" + } + return *t.DisplayName +} + +// GetFeatured returns the Featured field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetFeatured() bool { + if t == nil || t.Featured == nil { + return false + } + return *t.Featured +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetName() string { + if t == nil || t.Name == nil { + return "" + } + return *t.Name +} + +// GetScore returns the Score field. +func (t *TopicResult) GetScore() *float64 { + if t == nil { + return nil + } + return t.Score +} + +// GetShortDescription returns the ShortDescription field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetShortDescription() string { + if t == nil || t.ShortDescription == nil { + return "" + } + return *t.ShortDescription +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetUpdatedAt() string { + if t == nil || t.UpdatedAt == nil { + return "" + } + return *t.UpdatedAt +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (t *TopicsSearchResult) GetIncompleteResults() bool { + if t == nil || t.IncompleteResults == nil { + return false + } + return *t.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (t *TopicsSearchResult) GetTotal() int { + if t == nil || t.Total == nil { + return 0 + } + return *t.Total +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (t *TrafficClones) GetCount() int { + if t == nil || t.Count == nil { + return 0 + } + return *t.Count +} + +// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. +func (t *TrafficClones) GetUniques() int { + if t == nil || t.Uniques == nil { + return 0 + } + return *t.Uniques +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (t *TrafficData) GetCount() int { + if t == nil || t.Count == nil { + return 0 + } + return *t.Count +} + +// GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise. +func (t *TrafficData) GetTimestamp() Timestamp { + if t == nil || t.Timestamp == nil { + return Timestamp{} + } + return *t.Timestamp +} + +// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. +func (t *TrafficData) GetUniques() int { + if t == nil || t.Uniques == nil { + return 0 + } + return *t.Uniques +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (t *TrafficPath) GetCount() int { + if t == nil || t.Count == nil { + return 0 + } + return *t.Count +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (t *TrafficPath) GetPath() string { + if t == nil || t.Path == nil { + return "" + } + return *t.Path +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (t *TrafficPath) GetTitle() string { + if t == nil || t.Title == nil { + return "" + } + return *t.Title +} + +// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. +func (t *TrafficPath) GetUniques() int { + if t == nil || t.Uniques == nil { + return 0 + } + return *t.Uniques +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (t *TrafficReferrer) GetCount() int { + if t == nil || t.Count == nil { + return 0 + } + return *t.Count +} + +// GetReferrer returns the Referrer field if it's non-nil, zero value otherwise. +func (t *TrafficReferrer) GetReferrer() string { + if t == nil || t.Referrer == nil { + return "" + } + return *t.Referrer +} + +// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. +func (t *TrafficReferrer) GetUniques() int { + if t == nil || t.Uniques == nil { + return 0 + } + return *t.Uniques +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (t *TrafficViews) GetCount() int { + if t == nil || t.Count == nil { + return 0 + } + return *t.Count +} + +// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. +func (t *TrafficViews) GetUniques() int { + if t == nil || t.Uniques == nil { + return 0 + } + return *t.Uniques +} + +// GetNewName returns the NewName field if it's non-nil, zero value otherwise. +func (t *TransferRequest) GetNewName() string { + if t == nil || t.NewName == nil { + return "" + } + return *t.NewName +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (t *Tree) GetSHA() string { + if t == nil || t.SHA == nil { + return "" + } + return *t.SHA +} + +// GetTruncated returns the Truncated field if it's non-nil, zero value otherwise. +func (t *Tree) GetTruncated() bool { + if t == nil || t.Truncated == nil { + return false + } + return *t.Truncated +} + +// GetContent returns the Content field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetContent() string { + if t == nil || t.Content == nil { + return "" + } + return *t.Content +} + +// GetMode returns the Mode field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetMode() string { + if t == nil || t.Mode == nil { + return "" + } + return *t.Mode +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetPath() string { + if t == nil || t.Path == nil { + return "" + } + return *t.Path +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetSHA() string { + if t == nil || t.SHA == nil { + return "" + } + return *t.SHA +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetSize() int { + if t == nil || t.Size == nil { + return 0 + } + return *t.Size +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetType() string { + if t == nil || t.Type == nil { + return "" + } + return *t.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (u *UpdateAttributeForSCIMUserOperations) GetPath() string { + if u == nil || u.Path == nil { + return "" + } + return *u.Path +} + +// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. +func (u *UpdateCheckRunOptions) GetCompletedAt() Timestamp { + if u == nil || u.CompletedAt == nil { + return Timestamp{} + } + return *u.CompletedAt +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (u *UpdateCheckRunOptions) GetConclusion() string { + if u == nil || u.Conclusion == nil { + return "" + } + return *u.Conclusion +} + +// GetDetailsURL returns the DetailsURL field if it's non-nil, zero value otherwise. +func (u *UpdateCheckRunOptions) GetDetailsURL() string { + if u == nil || u.DetailsURL == nil { + return "" + } + return *u.DetailsURL +} + +// GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise. +func (u *UpdateCheckRunOptions) GetExternalID() string { + if u == nil || u.ExternalID == nil { + return "" + } + return *u.ExternalID +} + +// GetOutput returns the Output field. +func (u *UpdateCheckRunOptions) GetOutput() *CheckRunOutput { + if u == nil { + return nil + } + return u.Output +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (u *UpdateCheckRunOptions) GetStatus() string { + if u == nil || u.Status == nil { + return "" + } + return *u.Status +} + +// GetQuerySuite returns the QuerySuite field if it's non-nil, zero value otherwise. +func (u *UpdateDefaultSetupConfigurationOptions) GetQuerySuite() string { + if u == nil || u.QuerySuite == nil { + return "" + } + return *u.QuerySuite +} + +// GetRunID returns the RunID field if it's non-nil, zero value otherwise. +func (u *UpdateDefaultSetupConfigurationResponse) GetRunID() int64 { + if u == nil || u.RunID == nil { + return 0 + } + return *u.RunID +} + +// GetRunURL returns the RunURL field if it's non-nil, zero value otherwise. +func (u *UpdateDefaultSetupConfigurationResponse) GetRunURL() string { + if u == nil || u.RunURL == nil { + return "" + } + return *u.RunURL +} + +// GetAllowsPublicRepositories returns the AllowsPublicRepositories field if it's non-nil, zero value otherwise. +func (u *UpdateEnterpriseRunnerGroupRequest) GetAllowsPublicRepositories() bool { + if u == nil || u.AllowsPublicRepositories == nil { + return false + } + return *u.AllowsPublicRepositories +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (u *UpdateEnterpriseRunnerGroupRequest) GetName() string { + if u == nil || u.Name == nil { + return "" + } + return *u.Name +} + +// GetRestrictedToWorkflows returns the RestrictedToWorkflows field if it's non-nil, zero value otherwise. +func (u *UpdateEnterpriseRunnerGroupRequest) GetRestrictedToWorkflows() bool { + if u == nil || u.RestrictedToWorkflows == nil { + return false + } + return *u.RestrictedToWorkflows +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (u *UpdateEnterpriseRunnerGroupRequest) GetVisibility() string { + if u == nil || u.Visibility == nil { + return "" + } + return *u.Visibility +} + +// GetAllowsPublicRepositories returns the AllowsPublicRepositories field if it's non-nil, zero value otherwise. +func (u *UpdateRunnerGroupRequest) GetAllowsPublicRepositories() bool { + if u == nil || u.AllowsPublicRepositories == nil { + return false + } + return *u.AllowsPublicRepositories +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (u *UpdateRunnerGroupRequest) GetName() string { + if u == nil || u.Name == nil { + return "" + } + return *u.Name +} + +// GetRestrictedToWorkflows returns the RestrictedToWorkflows field if it's non-nil, zero value otherwise. +func (u *UpdateRunnerGroupRequest) GetRestrictedToWorkflows() bool { + if u == nil || u.RestrictedToWorkflows == nil { + return false + } + return *u.RestrictedToWorkflows +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (u *UpdateRunnerGroupRequest) GetVisibility() string { + if u == nil || u.Visibility == nil { + return "" + } + return *u.Visibility +} + +// GetAssignment returns the Assignment field if it's non-nil, zero value otherwise. +func (u *User) GetAssignment() string { + if u == nil || u.Assignment == nil { + return "" + } + return *u.Assignment +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (u *User) GetAvatarURL() string { + if u == nil || u.AvatarURL == nil { + return "" + } + return *u.AvatarURL +} + +// GetBio returns the Bio field if it's non-nil, zero value otherwise. +func (u *User) GetBio() string { + if u == nil || u.Bio == nil { + return "" + } + return *u.Bio +} + +// GetBlog returns the Blog field if it's non-nil, zero value otherwise. +func (u *User) GetBlog() string { + if u == nil || u.Blog == nil { + return "" + } + return *u.Blog +} + +// GetCollaborators returns the Collaborators field if it's non-nil, zero value otherwise. +func (u *User) GetCollaborators() int { + if u == nil || u.Collaborators == nil { + return 0 + } + return *u.Collaborators +} + +// GetCompany returns the Company field if it's non-nil, zero value otherwise. +func (u *User) GetCompany() string { + if u == nil || u.Company == nil { + return "" + } + return *u.Company +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (u *User) GetCreatedAt() Timestamp { + if u == nil || u.CreatedAt == nil { + return Timestamp{} + } + return *u.CreatedAt +} + +// GetDiskUsage returns the DiskUsage field if it's non-nil, zero value otherwise. +func (u *User) GetDiskUsage() int { + if u == nil || u.DiskUsage == nil { + return 0 + } + return *u.DiskUsage +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (u *User) GetEmail() string { + if u == nil || u.Email == nil { + return "" + } + return *u.Email +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (u *User) GetEventsURL() string { + if u == nil || u.EventsURL == nil { + return "" + } + return *u.EventsURL +} + +// GetFollowers returns the Followers field if it's non-nil, zero value otherwise. +func (u *User) GetFollowers() int { + if u == nil || u.Followers == nil { + return 0 + } + return *u.Followers +} + +// GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise. +func (u *User) GetFollowersURL() string { + if u == nil || u.FollowersURL == nil { + return "" + } + return *u.FollowersURL +} + +// GetFollowing returns the Following field if it's non-nil, zero value otherwise. +func (u *User) GetFollowing() int { + if u == nil || u.Following == nil { + return 0 + } + return *u.Following +} + +// GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise. +func (u *User) GetFollowingURL() string { + if u == nil || u.FollowingURL == nil { + return "" + } + return *u.FollowingURL +} + +// GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise. +func (u *User) GetGistsURL() string { + if u == nil || u.GistsURL == nil { + return "" + } + return *u.GistsURL +} + +// GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise. +func (u *User) GetGravatarID() string { + if u == nil || u.GravatarID == nil { + return "" + } + return *u.GravatarID +} + +// GetHireable returns the Hireable field if it's non-nil, zero value otherwise. +func (u *User) GetHireable() bool { + if u == nil || u.Hireable == nil { + return false + } + return *u.Hireable +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (u *User) GetHTMLURL() string { + if u == nil || u.HTMLURL == nil { + return "" + } + return *u.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (u *User) GetID() int64 { + if u == nil || u.ID == nil { + return 0 + } + return *u.ID +} + +// GetInheritedFrom returns the InheritedFrom field. +func (u *User) GetInheritedFrom() *Team { + if u == nil { + return nil + } + return u.InheritedFrom +} + +// GetLdapDn returns the LdapDn field if it's non-nil, zero value otherwise. +func (u *User) GetLdapDn() string { + if u == nil || u.LdapDn == nil { + return "" + } + return *u.LdapDn +} + +// GetLocation returns the Location field if it's non-nil, zero value otherwise. +func (u *User) GetLocation() string { + if u == nil || u.Location == nil { + return "" + } + return *u.Location +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (u *User) GetLogin() string { + if u == nil || u.Login == nil { + return "" + } + return *u.Login +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (u *User) GetName() string { + if u == nil || u.Name == nil { + return "" + } + return *u.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (u *User) GetNodeID() string { + if u == nil || u.NodeID == nil { + return "" + } + return *u.NodeID +} + +// GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise. +func (u *User) GetOrganizationsURL() string { + if u == nil || u.OrganizationsURL == nil { + return "" + } + return *u.OrganizationsURL +} + +// GetOwnedPrivateRepos returns the OwnedPrivateRepos field if it's non-nil, zero value otherwise. +func (u *User) GetOwnedPrivateRepos() int64 { + if u == nil || u.OwnedPrivateRepos == nil { + return 0 + } + return *u.OwnedPrivateRepos +} + +// GetPermissions returns the Permissions map if it's non-nil, an empty map otherwise. +func (u *User) GetPermissions() map[string]bool { + if u == nil || u.Permissions == nil { + return map[string]bool{} + } + return u.Permissions +} + +// GetPlan returns the Plan field. +func (u *User) GetPlan() *Plan { + if u == nil { + return nil + } + return u.Plan +} + +// GetPrivateGists returns the PrivateGists field if it's non-nil, zero value otherwise. +func (u *User) GetPrivateGists() int { + if u == nil || u.PrivateGists == nil { + return 0 + } + return *u.PrivateGists +} + +// GetPublicGists returns the PublicGists field if it's non-nil, zero value otherwise. +func (u *User) GetPublicGists() int { + if u == nil || u.PublicGists == nil { + return 0 + } + return *u.PublicGists +} + +// GetPublicRepos returns the PublicRepos field if it's non-nil, zero value otherwise. +func (u *User) GetPublicRepos() int { + if u == nil || u.PublicRepos == nil { + return 0 + } + return *u.PublicRepos +} + +// GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise. +func (u *User) GetReceivedEventsURL() string { + if u == nil || u.ReceivedEventsURL == nil { + return "" + } + return *u.ReceivedEventsURL +} + +// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. +func (u *User) GetReposURL() string { + if u == nil || u.ReposURL == nil { + return "" + } + return *u.ReposURL +} + +// GetRoleName returns the RoleName field if it's non-nil, zero value otherwise. +func (u *User) GetRoleName() string { + if u == nil || u.RoleName == nil { + return "" + } + return *u.RoleName +} + +// GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise. +func (u *User) GetSiteAdmin() bool { + if u == nil || u.SiteAdmin == nil { + return false + } + return *u.SiteAdmin +} + +// GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise. +func (u *User) GetStarredURL() string { + if u == nil || u.StarredURL == nil { + return "" + } + return *u.StarredURL +} + +// GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise. +func (u *User) GetSubscriptionsURL() string { + if u == nil || u.SubscriptionsURL == nil { + return "" + } + return *u.SubscriptionsURL +} + +// GetSuspendedAt returns the SuspendedAt field if it's non-nil, zero value otherwise. +func (u *User) GetSuspendedAt() Timestamp { + if u == nil || u.SuspendedAt == nil { + return Timestamp{} + } + return *u.SuspendedAt +} + +// GetTotalPrivateRepos returns the TotalPrivateRepos field if it's non-nil, zero value otherwise. +func (u *User) GetTotalPrivateRepos() int64 { + if u == nil || u.TotalPrivateRepos == nil { + return 0 + } + return *u.TotalPrivateRepos +} + +// GetTwitterUsername returns the TwitterUsername field if it's non-nil, zero value otherwise. +func (u *User) GetTwitterUsername() string { + if u == nil || u.TwitterUsername == nil { + return "" + } + return *u.TwitterUsername +} + +// GetTwoFactorAuthentication returns the TwoFactorAuthentication field if it's non-nil, zero value otherwise. +func (u *User) GetTwoFactorAuthentication() bool { + if u == nil || u.TwoFactorAuthentication == nil { + return false + } + return *u.TwoFactorAuthentication +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (u *User) GetType() string { + if u == nil || u.Type == nil { + return "" + } + return *u.Type +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (u *User) GetUpdatedAt() Timestamp { + if u == nil || u.UpdatedAt == nil { + return Timestamp{} + } + return *u.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (u *User) GetURL() string { + if u == nil || u.URL == nil { + return "" + } + return *u.URL +} + +// GetApp returns the App field. +func (u *UserAuthorization) GetApp() *OAuthAPP { + if u == nil { + return nil + } + return u.App +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetCreatedAt() Timestamp { + if u == nil || u.CreatedAt == nil { + return Timestamp{} + } + return *u.CreatedAt +} + +// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetFingerprint() string { + if u == nil || u.Fingerprint == nil { + return "" + } + return *u.Fingerprint +} + +// GetHashedToken returns the HashedToken field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetHashedToken() string { + if u == nil || u.HashedToken == nil { + return "" + } + return *u.HashedToken +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetID() int64 { + if u == nil || u.ID == nil { + return 0 + } + return *u.ID +} + +// GetNote returns the Note field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetNote() string { + if u == nil || u.Note == nil { + return "" + } + return *u.Note +} + +// GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetNoteURL() string { + if u == nil || u.NoteURL == nil { + return "" + } + return *u.NoteURL +} + +// GetToken returns the Token field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetToken() string { + if u == nil || u.Token == nil { + return "" + } + return *u.Token +} + +// GetTokenLastEight returns the TokenLastEight field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetTokenLastEight() string { + if u == nil || u.TokenLastEight == nil { + return "" + } + return *u.TokenLastEight +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetUpdatedAt() Timestamp { + if u == nil || u.UpdatedAt == nil { + return Timestamp{} + } + return *u.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetURL() string { + if u == nil || u.URL == nil { + return "" + } + return *u.URL +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (u *UserContext) GetMessage() string { + if u == nil || u.Message == nil { + return "" + } + return *u.Message +} + +// GetOcticon returns the Octicon field if it's non-nil, zero value otherwise. +func (u *UserContext) GetOcticon() string { + if u == nil || u.Octicon == nil { + return "" + } + return *u.Octicon +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (u *UserEmail) GetEmail() string { + if u == nil || u.Email == nil { + return "" + } + return *u.Email +} + +// GetPrimary returns the Primary field if it's non-nil, zero value otherwise. +func (u *UserEmail) GetPrimary() bool { + if u == nil || u.Primary == nil { + return false + } + return *u.Primary +} + +// GetVerified returns the Verified field if it's non-nil, zero value otherwise. +func (u *UserEmail) GetVerified() bool { + if u == nil || u.Verified == nil { + return false + } + return *u.Verified +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (u *UserEmail) GetVisibility() string { + if u == nil || u.Visibility == nil { + return "" + } + return *u.Visibility +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (u *UserEvent) GetAction() string { + if u == nil || u.Action == nil { + return "" + } + return *u.Action +} + +// GetEnterprise returns the Enterprise field. +func (u *UserEvent) GetEnterprise() *Enterprise { + if u == nil { + return nil + } + return u.Enterprise +} + +// GetInstallation returns the Installation field. +func (u *UserEvent) GetInstallation() *Installation { + if u == nil { + return nil + } + return u.Installation +} + +// GetSender returns the Sender field. +func (u *UserEvent) GetSender() *User { + if u == nil { + return nil + } + return u.Sender +} + +// GetUser returns the User field. +func (u *UserEvent) GetUser() *User { + if u == nil { + return nil + } + return u.User +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetAvatarURL() string { + if u == nil || u.AvatarURL == nil { + return "" + } + return *u.AvatarURL +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetEventsURL() string { + if u == nil || u.EventsURL == nil { + return "" + } + return *u.EventsURL +} + +// GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetFollowersURL() string { + if u == nil || u.FollowersURL == nil { + return "" + } + return *u.FollowersURL +} + +// GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetFollowingURL() string { + if u == nil || u.FollowingURL == nil { + return "" + } + return *u.FollowingURL +} + +// GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetGistsURL() string { + if u == nil || u.GistsURL == nil { + return "" + } + return *u.GistsURL +} + +// GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetGravatarID() string { + if u == nil || u.GravatarID == nil { + return "" + } + return *u.GravatarID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetID() int64 { + if u == nil || u.ID == nil { + return 0 + } + return *u.ID +} + +// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetLDAPDN() string { + if u == nil || u.LDAPDN == nil { + return "" + } + return *u.LDAPDN +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetLogin() string { + if u == nil || u.Login == nil { + return "" + } + return *u.Login +} + +// GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetOrganizationsURL() string { + if u == nil || u.OrganizationsURL == nil { + return "" + } + return *u.OrganizationsURL +} + +// GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetReceivedEventsURL() string { + if u == nil || u.ReceivedEventsURL == nil { + return "" + } + return *u.ReceivedEventsURL +} + +// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetReposURL() string { + if u == nil || u.ReposURL == nil { + return "" + } + return *u.ReposURL +} + +// GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetSiteAdmin() bool { + if u == nil || u.SiteAdmin == nil { + return false + } + return *u.SiteAdmin +} + +// GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetStarredURL() string { + if u == nil || u.StarredURL == nil { + return "" + } + return *u.StarredURL +} + +// GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetSubscriptionsURL() string { + if u == nil || u.SubscriptionsURL == nil { + return "" + } + return *u.SubscriptionsURL +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetType() string { + if u == nil || u.Type == nil { + return "" + } + return *u.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetURL() string { + if u == nil || u.URL == nil { + return "" + } + return *u.URL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetCreatedAt() string { + if u == nil || u.CreatedAt == nil { + return "" + } + return *u.CreatedAt +} + +// GetExcludeAttachments returns the ExcludeAttachments field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetExcludeAttachments() bool { + if u == nil || u.ExcludeAttachments == nil { + return false + } + return *u.ExcludeAttachments +} + +// GetGUID returns the GUID field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetGUID() string { + if u == nil || u.GUID == nil { + return "" + } + return *u.GUID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetID() int64 { + if u == nil || u.ID == nil { + return 0 + } + return *u.ID +} + +// GetLockRepositories returns the LockRepositories field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetLockRepositories() bool { + if u == nil || u.LockRepositories == nil { + return false + } + return *u.LockRepositories +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetState() string { + if u == nil || u.State == nil { + return "" + } + return *u.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetUpdatedAt() string { + if u == nil || u.UpdatedAt == nil { + return "" + } + return *u.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetURL() string { + if u == nil || u.URL == nil { + return "" + } + return *u.URL +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (u *UsersSearchResult) GetIncompleteResults() bool { + if u == nil || u.IncompleteResults == nil { + return false + } + return *u.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (u *UsersSearchResult) GetTotal() int { + if u == nil || u.Total == nil { + return 0 + } + return *u.Total +} + +// GetAdminUsers returns the AdminUsers field if it's non-nil, zero value otherwise. +func (u *UserStats) GetAdminUsers() int { + if u == nil || u.AdminUsers == nil { + return 0 + } + return *u.AdminUsers +} + +// GetSuspendedUsers returns the SuspendedUsers field if it's non-nil, zero value otherwise. +func (u *UserStats) GetSuspendedUsers() int { + if u == nil || u.SuspendedUsers == nil { + return 0 + } + return *u.SuspendedUsers +} + +// GetTotalUsers returns the TotalUsers field if it's non-nil, zero value otherwise. +func (u *UserStats) GetTotalUsers() int { + if u == nil || u.TotalUsers == nil { + return 0 + } + return *u.TotalUsers +} + +// GetReason returns the Reason field if it's non-nil, zero value otherwise. +func (u *UserSuspendOptions) GetReason() string { + if u == nil || u.Reason == nil { + return "" + } + return *u.Reason +} + +// GetEcosystem returns the Ecosystem field if it's non-nil, zero value otherwise. +func (v *VulnerabilityPackage) GetEcosystem() string { + if v == nil || v.Ecosystem == nil { + return "" + } + return *v.Ecosystem +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (v *VulnerabilityPackage) GetName() string { + if v == nil || v.Name == nil { + return "" + } + return *v.Name +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (w *WatchEvent) GetAction() string { + if w == nil || w.Action == nil { + return "" + } + return *w.Action +} + +// GetInstallation returns the Installation field. +func (w *WatchEvent) GetInstallation() *Installation { + if w == nil { + return nil + } + return w.Installation +} + +// GetOrg returns the Org field. +func (w *WatchEvent) GetOrg() *Organization { + if w == nil { + return nil + } + return w.Org +} + +// GetRepo returns the Repo field. +func (w *WatchEvent) GetRepo() *Repository { + if w == nil { + return nil + } + return w.Repo +} + +// GetSender returns the Sender field. +func (w *WatchEvent) GetSender() *User { + if w == nil { + return nil + } + return w.Sender +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (w *WeeklyCommitActivity) GetTotal() int { + if w == nil || w.Total == nil { + return 0 + } + return *w.Total +} + +// GetWeek returns the Week field if it's non-nil, zero value otherwise. +func (w *WeeklyCommitActivity) GetWeek() Timestamp { + if w == nil || w.Week == nil { + return Timestamp{} + } + return *w.Week +} + +// GetAdditions returns the Additions field if it's non-nil, zero value otherwise. +func (w *WeeklyStats) GetAdditions() int { + if w == nil || w.Additions == nil { + return 0 + } + return *w.Additions +} + +// GetCommits returns the Commits field if it's non-nil, zero value otherwise. +func (w *WeeklyStats) GetCommits() int { + if w == nil || w.Commits == nil { + return 0 + } + return *w.Commits +} + +// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. +func (w *WeeklyStats) GetDeletions() int { + if w == nil || w.Deletions == nil { + return 0 + } + return *w.Deletions +} + +// GetWeek returns the Week field if it's non-nil, zero value otherwise. +func (w *WeeklyStats) GetWeek() Timestamp { + if w == nil || w.Week == nil { + return Timestamp{} + } + return *w.Week +} + +// GetBadgeURL returns the BadgeURL field if it's non-nil, zero value otherwise. +func (w *Workflow) GetBadgeURL() string { + if w == nil || w.BadgeURL == nil { + return "" + } + return *w.BadgeURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (w *Workflow) GetCreatedAt() Timestamp { + if w == nil || w.CreatedAt == nil { + return Timestamp{} + } + return *w.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (w *Workflow) GetHTMLURL() string { + if w == nil || w.HTMLURL == nil { + return "" + } + return *w.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (w *Workflow) GetID() int64 { + if w == nil || w.ID == nil { + return 0 + } + return *w.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (w *Workflow) GetName() string { + if w == nil || w.Name == nil { + return "" + } + return *w.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (w *Workflow) GetNodeID() string { + if w == nil || w.NodeID == nil { + return "" + } + return *w.NodeID +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (w *Workflow) GetPath() string { + if w == nil || w.Path == nil { + return "" + } + return *w.Path +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (w *Workflow) GetState() string { + if w == nil || w.State == nil { + return "" + } + return *w.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (w *Workflow) GetUpdatedAt() Timestamp { + if w == nil || w.UpdatedAt == nil { + return Timestamp{} + } + return *w.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (w *Workflow) GetURL() string { + if w == nil || w.URL == nil { + return "" + } + return *w.URL +} + +// GetTotalMS returns the TotalMS field if it's non-nil, zero value otherwise. +func (w *WorkflowBill) GetTotalMS() int64 { + if w == nil || w.TotalMS == nil { + return 0 + } + return *w.TotalMS +} + +// GetInstallation returns the Installation field. +func (w *WorkflowDispatchEvent) GetInstallation() *Installation { + if w == nil { + return nil + } + return w.Installation +} + +// GetOrg returns the Org field. +func (w *WorkflowDispatchEvent) GetOrg() *Organization { + if w == nil { + return nil + } + return w.Org +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (w *WorkflowDispatchEvent) GetRef() string { + if w == nil || w.Ref == nil { + return "" + } + return *w.Ref +} + +// GetRepo returns the Repo field. +func (w *WorkflowDispatchEvent) GetRepo() *Repository { + if w == nil { + return nil + } + return w.Repo +} + +// GetSender returns the Sender field. +func (w *WorkflowDispatchEvent) GetSender() *User { + if w == nil { + return nil + } + return w.Sender +} + +// GetWorkflow returns the Workflow field if it's non-nil, zero value otherwise. +func (w *WorkflowDispatchEvent) GetWorkflow() string { + if w == nil || w.Workflow == nil { + return "" + } + return *w.Workflow +} + +// GetCheckRunURL returns the CheckRunURL field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetCheckRunURL() string { + if w == nil || w.CheckRunURL == nil { + return "" + } + return *w.CheckRunURL +} + +// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetCompletedAt() Timestamp { + if w == nil || w.CompletedAt == nil { + return Timestamp{} + } + return *w.CompletedAt +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetConclusion() string { + if w == nil || w.Conclusion == nil { + return "" + } + return *w.Conclusion +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetCreatedAt() Timestamp { + if w == nil || w.CreatedAt == nil { + return Timestamp{} + } + return *w.CreatedAt +} + +// GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetHeadBranch() string { + if w == nil || w.HeadBranch == nil { + return "" + } + return *w.HeadBranch +} + +// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetHeadSHA() string { + if w == nil || w.HeadSHA == nil { + return "" + } + return *w.HeadSHA +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetHTMLURL() string { + if w == nil || w.HTMLURL == nil { + return "" + } + return *w.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetID() int64 { + if w == nil || w.ID == nil { + return 0 + } + return *w.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetName() string { + if w == nil || w.Name == nil { + return "" + } + return *w.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetNodeID() string { + if w == nil || w.NodeID == nil { + return "" + } + return *w.NodeID +} + +// GetRunAttempt returns the RunAttempt field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetRunAttempt() int64 { + if w == nil || w.RunAttempt == nil { + return 0 + } + return *w.RunAttempt +} + +// GetRunID returns the RunID field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetRunID() int64 { + if w == nil || w.RunID == nil { + return 0 + } + return *w.RunID +} + +// GetRunnerGroupID returns the RunnerGroupID field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetRunnerGroupID() int64 { + if w == nil || w.RunnerGroupID == nil { + return 0 + } + return *w.RunnerGroupID +} + +// GetRunnerGroupName returns the RunnerGroupName field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetRunnerGroupName() string { + if w == nil || w.RunnerGroupName == nil { + return "" + } + return *w.RunnerGroupName +} + +// GetRunnerID returns the RunnerID field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetRunnerID() int64 { + if w == nil || w.RunnerID == nil { + return 0 + } + return *w.RunnerID +} + +// GetRunnerName returns the RunnerName field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetRunnerName() string { + if w == nil || w.RunnerName == nil { + return "" + } + return *w.RunnerName +} + +// GetRunURL returns the RunURL field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetRunURL() string { + if w == nil || w.RunURL == nil { + return "" + } + return *w.RunURL +} + +// GetStartedAt returns the StartedAt field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetStartedAt() Timestamp { + if w == nil || w.StartedAt == nil { + return Timestamp{} + } + return *w.StartedAt +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetStatus() string { + if w == nil || w.Status == nil { + return "" + } + return *w.Status +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetURL() string { + if w == nil || w.URL == nil { + return "" + } + return *w.URL +} + +// GetWorkflowName returns the WorkflowName field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetWorkflowName() string { + if w == nil || w.WorkflowName == nil { + return "" + } + return *w.WorkflowName +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (w *WorkflowJobEvent) GetAction() string { + if w == nil || w.Action == nil { + return "" + } + return *w.Action +} + +// GetDeployment returns the Deployment field. +func (w *WorkflowJobEvent) GetDeployment() *Deployment { + if w == nil { + return nil + } + return w.Deployment +} + +// GetInstallation returns the Installation field. +func (w *WorkflowJobEvent) GetInstallation() *Installation { + if w == nil { + return nil + } + return w.Installation +} + +// GetOrg returns the Org field. +func (w *WorkflowJobEvent) GetOrg() *Organization { + if w == nil { + return nil + } + return w.Org +} + +// GetRepo returns the Repo field. +func (w *WorkflowJobEvent) GetRepo() *Repository { + if w == nil { + return nil + } + return w.Repo +} + +// GetSender returns the Sender field. +func (w *WorkflowJobEvent) GetSender() *User { + if w == nil { + return nil + } + return w.Sender +} + +// GetWorkflowJob returns the WorkflowJob field. +func (w *WorkflowJobEvent) GetWorkflowJob() *WorkflowJob { + if w == nil { + return nil + } + return w.WorkflowJob +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (w *WorkflowJobRun) GetConclusion() string { + if w == nil || w.Conclusion == nil { + return "" + } + return *w.Conclusion +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (w *WorkflowJobRun) GetCreatedAt() Timestamp { + if w == nil || w.CreatedAt == nil { + return Timestamp{} + } + return *w.CreatedAt +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (w *WorkflowJobRun) GetEnvironment() string { + if w == nil || w.Environment == nil { + return "" + } + return *w.Environment +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (w *WorkflowJobRun) GetHTMLURL() string { + if w == nil || w.HTMLURL == nil { + return "" + } + return *w.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (w *WorkflowJobRun) GetID() int64 { + if w == nil || w.ID == nil { + return 0 + } + return *w.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (w *WorkflowJobRun) GetName() string { + if w == nil || w.Name == nil { + return "" + } + return *w.Name +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (w *WorkflowJobRun) GetStatus() string { + if w == nil || w.Status == nil { + return "" + } + return *w.Status +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (w *WorkflowJobRun) GetUpdatedAt() Timestamp { + if w == nil || w.UpdatedAt == nil { + return Timestamp{} + } + return *w.UpdatedAt +} + +// GetActor returns the Actor field. +func (w *WorkflowRun) GetActor() *User { + if w == nil { + return nil + } + return w.Actor +} + +// GetArtifactsURL returns the ArtifactsURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetArtifactsURL() string { + if w == nil || w.ArtifactsURL == nil { + return "" + } + return *w.ArtifactsURL +} + +// GetCancelURL returns the CancelURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetCancelURL() string { + if w == nil || w.CancelURL == nil { + return "" + } + return *w.CancelURL +} + +// GetCheckSuiteID returns the CheckSuiteID field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetCheckSuiteID() int64 { + if w == nil || w.CheckSuiteID == nil { + return 0 + } + return *w.CheckSuiteID +} + +// GetCheckSuiteNodeID returns the CheckSuiteNodeID field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetCheckSuiteNodeID() string { + if w == nil || w.CheckSuiteNodeID == nil { + return "" + } + return *w.CheckSuiteNodeID +} + +// GetCheckSuiteURL returns the CheckSuiteURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetCheckSuiteURL() string { + if w == nil || w.CheckSuiteURL == nil { + return "" + } + return *w.CheckSuiteURL +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetConclusion() string { + if w == nil || w.Conclusion == nil { + return "" + } + return *w.Conclusion +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetCreatedAt() Timestamp { + if w == nil || w.CreatedAt == nil { + return Timestamp{} + } + return *w.CreatedAt +} + +// GetDisplayTitle returns the DisplayTitle field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetDisplayTitle() string { + if w == nil || w.DisplayTitle == nil { + return "" + } + return *w.DisplayTitle +} + +// GetEvent returns the Event field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetEvent() string { + if w == nil || w.Event == nil { + return "" + } + return *w.Event +} + +// GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetHeadBranch() string { + if w == nil || w.HeadBranch == nil { + return "" + } + return *w.HeadBranch +} + +// GetHeadCommit returns the HeadCommit field. +func (w *WorkflowRun) GetHeadCommit() *HeadCommit { + if w == nil { + return nil + } + return w.HeadCommit +} + +// GetHeadRepository returns the HeadRepository field. +func (w *WorkflowRun) GetHeadRepository() *Repository { + if w == nil { + return nil + } + return w.HeadRepository +} + +// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetHeadSHA() string { + if w == nil || w.HeadSHA == nil { + return "" + } + return *w.HeadSHA +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetHTMLURL() string { + if w == nil || w.HTMLURL == nil { + return "" + } + return *w.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetID() int64 { + if w == nil || w.ID == nil { + return 0 + } + return *w.ID +} + +// GetJobsURL returns the JobsURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetJobsURL() string { + if w == nil || w.JobsURL == nil { + return "" + } + return *w.JobsURL +} + +// GetLogsURL returns the LogsURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetLogsURL() string { + if w == nil || w.LogsURL == nil { + return "" + } + return *w.LogsURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetName() string { + if w == nil || w.Name == nil { + return "" + } + return *w.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetNodeID() string { + if w == nil || w.NodeID == nil { + return "" + } + return *w.NodeID +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetPath() string { + if w == nil || w.Path == nil { + return "" + } + return *w.Path +} + +// GetPreviousAttemptURL returns the PreviousAttemptURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetPreviousAttemptURL() string { + if w == nil || w.PreviousAttemptURL == nil { + return "" + } + return *w.PreviousAttemptURL +} + +// GetRepository returns the Repository field. +func (w *WorkflowRun) GetRepository() *Repository { + if w == nil { + return nil + } + return w.Repository +} + +// GetRerunURL returns the RerunURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetRerunURL() string { + if w == nil || w.RerunURL == nil { + return "" + } + return *w.RerunURL +} + +// GetRunAttempt returns the RunAttempt field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetRunAttempt() int { + if w == nil || w.RunAttempt == nil { + return 0 + } + return *w.RunAttempt +} + +// GetRunNumber returns the RunNumber field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetRunNumber() int { + if w == nil || w.RunNumber == nil { + return 0 + } + return *w.RunNumber +} + +// GetRunStartedAt returns the RunStartedAt field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetRunStartedAt() Timestamp { + if w == nil || w.RunStartedAt == nil { + return Timestamp{} + } + return *w.RunStartedAt +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetStatus() string { + if w == nil || w.Status == nil { + return "" + } + return *w.Status +} + +// GetTriggeringActor returns the TriggeringActor field. +func (w *WorkflowRun) GetTriggeringActor() *User { + if w == nil { + return nil + } + return w.TriggeringActor +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetUpdatedAt() Timestamp { + if w == nil || w.UpdatedAt == nil { + return Timestamp{} + } + return *w.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetURL() string { + if w == nil || w.URL == nil { + return "" + } + return *w.URL +} + +// GetWorkflowID returns the WorkflowID field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetWorkflowID() int64 { + if w == nil || w.WorkflowID == nil { + return 0 + } + return *w.WorkflowID +} + +// GetWorkflowURL returns the WorkflowURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetWorkflowURL() string { + if w == nil || w.WorkflowURL == nil { + return "" + } + return *w.WorkflowURL +} + +// GetExcludePullRequests returns the ExcludePullRequests field if it's non-nil, zero value otherwise. +func (w *WorkflowRunAttemptOptions) GetExcludePullRequests() bool { + if w == nil || w.ExcludePullRequests == nil { + return false + } + return *w.ExcludePullRequests +} + +// GetJobs returns the Jobs field if it's non-nil, zero value otherwise. +func (w *WorkflowRunBill) GetJobs() int { + if w == nil || w.Jobs == nil { + return 0 + } + return *w.Jobs +} + +// GetTotalMS returns the TotalMS field if it's non-nil, zero value otherwise. +func (w *WorkflowRunBill) GetTotalMS() int64 { + if w == nil || w.TotalMS == nil { + return 0 + } + return *w.TotalMS +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (w *WorkflowRunEvent) GetAction() string { + if w == nil || w.Action == nil { + return "" + } + return *w.Action +} + +// GetInstallation returns the Installation field. +func (w *WorkflowRunEvent) GetInstallation() *Installation { + if w == nil { + return nil + } + return w.Installation +} + +// GetOrg returns the Org field. +func (w *WorkflowRunEvent) GetOrg() *Organization { + if w == nil { + return nil + } + return w.Org +} + +// GetRepo returns the Repo field. +func (w *WorkflowRunEvent) GetRepo() *Repository { + if w == nil { + return nil + } + return w.Repo +} + +// GetSender returns the Sender field. +func (w *WorkflowRunEvent) GetSender() *User { + if w == nil { + return nil + } + return w.Sender +} + +// GetWorkflow returns the Workflow field. +func (w *WorkflowRunEvent) GetWorkflow() *Workflow { + if w == nil { + return nil + } + return w.Workflow +} + +// GetWorkflowRun returns the WorkflowRun field. +func (w *WorkflowRunEvent) GetWorkflowRun() *WorkflowRun { + if w == nil { + return nil + } + return w.WorkflowRun +} + +// GetDurationMS returns the DurationMS field if it's non-nil, zero value otherwise. +func (w *WorkflowRunJobRun) GetDurationMS() int64 { + if w == nil || w.DurationMS == nil { + return 0 + } + return *w.DurationMS +} + +// GetJobID returns the JobID field if it's non-nil, zero value otherwise. +func (w *WorkflowRunJobRun) GetJobID() int { + if w == nil || w.JobID == nil { + return 0 + } + return *w.JobID +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (w *WorkflowRuns) GetTotalCount() int { + if w == nil || w.TotalCount == nil { + return 0 + } + return *w.TotalCount +} + +// GetBillable returns the Billable field. +func (w *WorkflowRunUsage) GetBillable() *WorkflowRunBillMap { + if w == nil { + return nil + } + return w.Billable +} + +// GetRunDurationMS returns the RunDurationMS field if it's non-nil, zero value otherwise. +func (w *WorkflowRunUsage) GetRunDurationMS() int64 { + if w == nil || w.RunDurationMS == nil { + return 0 + } + return *w.RunDurationMS +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (w *Workflows) GetTotalCount() int { + if w == nil || w.TotalCount == nil { + return 0 + } + return *w.TotalCount +} + +// GetBillable returns the Billable field. +func (w *WorkflowUsage) GetBillable() *WorkflowBillMap { + if w == nil { + return nil + } + return w.Billable +} diff --git a/vendor/github.com/google/go-github/v68/github/github.go b/vendor/github.com/google/go-github/v68/github/github.go new file mode 100644 index 0000000000..4e5a33c67e --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/github.go @@ -0,0 +1,1618 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate go run gen-accessors.go +//go:generate go run gen-stringify-test.go +//go:generate ../script/metadata.sh update-go + +package github + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "net/url" + "reflect" + "strconv" + "strings" + "sync" + "time" + + "github.com/google/go-querystring/query" +) + +const ( + Version = "v68.0.0" + + defaultAPIVersion = "2022-11-28" + defaultBaseURL = "https://api.github.com/" + defaultUserAgent = "go-github" + "/" + Version + uploadBaseURL = "https://uploads.github.com/" + + headerAPIVersion = "X-Github-Api-Version" + headerRateLimit = "X-Ratelimit-Limit" + headerRateRemaining = "X-Ratelimit-Remaining" + headerRateReset = "X-Ratelimit-Reset" + headerOTP = "X-Github-Otp" + headerRetryAfter = "Retry-After" + + headerTokenExpiration = "Github-Authentication-Token-Expiration" + + mediaTypeV3 = "application/vnd.github.v3+json" + defaultMediaType = "application/octet-stream" + mediaTypeV3SHA = "application/vnd.github.v3.sha" + mediaTypeV3Diff = "application/vnd.github.v3.diff" + mediaTypeV3Patch = "application/vnd.github.v3.patch" + mediaTypeOrgPermissionRepo = "application/vnd.github.v3.repository+json" + mediaTypeIssueImportAPI = "application/vnd.github.golden-comet-preview+json" + + // Media Type values to access preview APIs + // These media types will be added to the API request as headers + // and used to enable particular features on GitHub API that are still in preview. + // After some time, specific media types will be promoted (to a "stable" state). + // From then on, the preview headers are not required anymore to activate the additional + // feature on GitHub.com's API. However, this API header might still be needed for users + // to run a GitHub Enterprise Server on-premise. + // It's not uncommon for GitHub Enterprise Server customers to run older versions which + // would probably rely on the preview headers for some time. + // While the header promotion is going out for GitHub.com, it may be some time before it + // even arrives in GitHub Enterprise Server. + // We keep those preview headers around to avoid breaking older GitHub Enterprise Server + // versions. Additionally, non-functional (preview) headers don't create any side effects + // on GitHub Cloud version. + // + // See https://github.com/google/go-github/pull/2125 for full context. + + // https://developer.github.com/changes/2014-12-09-new-attributes-for-stars-api/ + mediaTypeStarringPreview = "application/vnd.github.v3.star+json" + + // https://help.github.com/enterprise/2.4/admin/guides/migrations/exporting-the-github-com-organization-s-repositories/ + mediaTypeMigrationsPreview = "application/vnd.github.wyandotte-preview+json" + + // https://developer.github.com/changes/2016-04-06-deployment-and-deployment-status-enhancements/ + mediaTypeDeploymentStatusPreview = "application/vnd.github.ant-man-preview+json" + + // https://developer.github.com/changes/2018-10-16-deployments-environments-states-and-auto-inactive-updates/ + mediaTypeExpandDeploymentStatusPreview = "application/vnd.github.flash-preview+json" + + // https://developer.github.com/changes/2016-05-12-reactions-api-preview/ + mediaTypeReactionsPreview = "application/vnd.github.squirrel-girl-preview" + + // https://developer.github.com/changes/2016-05-23-timeline-preview-api/ + mediaTypeTimelinePreview = "application/vnd.github.mockingbird-preview+json" + + // https://developer.github.com/changes/2016-09-14-projects-api/ + mediaTypeProjectsPreview = "application/vnd.github.inertia-preview+json" + + // https://developer.github.com/changes/2017-01-05-commit-search-api/ + mediaTypeCommitSearchPreview = "application/vnd.github.cloak-preview+json" + + // https://developer.github.com/changes/2017-02-28-user-blocking-apis-and-webhook/ + mediaTypeBlockUsersPreview = "application/vnd.github.giant-sentry-fist-preview+json" + + // https://developer.github.com/changes/2017-05-23-coc-api/ + mediaTypeCodesOfConductPreview = "application/vnd.github.scarlet-witch-preview+json" + + // https://developer.github.com/changes/2017-07-17-update-topics-on-repositories/ + mediaTypeTopicsPreview = "application/vnd.github.mercy-preview+json" + + // https://developer.github.com/changes/2018-03-16-protected-branches-required-approving-reviews/ + mediaTypeRequiredApprovingReviewsPreview = "application/vnd.github.luke-cage-preview+json" + + // https://developer.github.com/changes/2018-05-07-new-checks-api-public-beta/ + mediaTypeCheckRunsPreview = "application/vnd.github.antiope-preview+json" + + // https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/ + mediaTypePreReceiveHooksPreview = "application/vnd.github.eye-scream-preview" + + // https://developer.github.com/changes/2018-02-22-protected-branches-required-signatures/ + mediaTypeSignaturePreview = "application/vnd.github.zzzax-preview+json" + + // https://developer.github.com/changes/2018-09-05-project-card-events/ + mediaTypeProjectCardDetailsPreview = "application/vnd.github.starfox-preview+json" + + // https://developer.github.com/changes/2018-12-18-interactions-preview/ + mediaTypeInteractionRestrictionsPreview = "application/vnd.github.sombra-preview+json" + + // https://developer.github.com/changes/2019-03-14-enabling-disabling-pages/ + mediaTypeEnablePagesAPIPreview = "application/vnd.github.switcheroo-preview+json" + + // https://developer.github.com/changes/2019-04-24-vulnerability-alerts/ + mediaTypeRequiredVulnerabilityAlertsPreview = "application/vnd.github.dorian-preview+json" + + // https://developer.github.com/changes/2019-05-29-update-branch-api/ + mediaTypeUpdatePullRequestBranchPreview = "application/vnd.github.lydian-preview+json" + + // https://developer.github.com/changes/2019-04-11-pulls-branches-for-commit/ + mediaTypeListPullsOrBranchesForCommitPreview = "application/vnd.github.groot-preview+json" + + // https://docs.github.com/rest/previews/#repository-creation-permissions + mediaTypeMemberAllowedRepoCreationTypePreview = "application/vnd.github.surtur-preview+json" + + // https://docs.github.com/rest/previews/#create-and-use-repository-templates + mediaTypeRepositoryTemplatePreview = "application/vnd.github.baptiste-preview+json" + + // https://developer.github.com/changes/2019-10-03-multi-line-comments/ + mediaTypeMultiLineCommentsPreview = "application/vnd.github.comfort-fade-preview+json" + + // https://developer.github.com/changes/2019-11-05-deprecated-passwords-and-authorizations-api/ + mediaTypeOAuthAppPreview = "application/vnd.github.doctor-strange-preview+json" + + // https://developer.github.com/changes/2019-12-03-internal-visibility-changes/ + mediaTypeRepositoryVisibilityPreview = "application/vnd.github.nebula-preview+json" + + // https://developer.github.com/changes/2018-12-10-content-attachments-api/ + mediaTypeContentAttachmentsPreview = "application/vnd.github.corsair-preview+json" +) + +var errNonNilContext = errors.New("context must be non-nil") + +// A Client manages communication with the GitHub API. +type Client struct { + clientMu sync.Mutex // clientMu protects the client during calls that modify the CheckRedirect func. + client *http.Client // HTTP client used to communicate with the API. + + // Base URL for API requests. Defaults to the public GitHub API, but can be + // set to a domain endpoint to use with GitHub Enterprise. BaseURL should + // always be specified with a trailing slash. + BaseURL *url.URL + + // Base URL for uploading files. + UploadURL *url.URL + + // User agent used when communicating with the GitHub API. + UserAgent string + + rateMu sync.Mutex + rateLimits [Categories]Rate // Rate limits for the client as determined by the most recent API calls. + secondaryRateLimitReset time.Time // Secondary rate limit reset for the client as determined by the most recent API calls. + + common service // Reuse a single struct instead of allocating one for each service on the heap. + + // Services used for talking to different parts of the GitHub API. + Actions *ActionsService + Activity *ActivityService + Admin *AdminService + Apps *AppsService + Authorizations *AuthorizationsService + Billing *BillingService + Checks *ChecksService + CodeScanning *CodeScanningService + CodesOfConduct *CodesOfConductService + Codespaces *CodespacesService + Copilot *CopilotService + Dependabot *DependabotService + DependencyGraph *DependencyGraphService + Emojis *EmojisService + Enterprise *EnterpriseService + Gists *GistsService + Git *GitService + Gitignores *GitignoresService + Interactions *InteractionsService + IssueImport *IssueImportService + Issues *IssuesService + Licenses *LicensesService + Markdown *MarkdownService + Marketplace *MarketplaceService + Meta *MetaService + Migrations *MigrationService + Organizations *OrganizationsService + PullRequests *PullRequestsService + RateLimit *RateLimitService + Reactions *ReactionsService + Repositories *RepositoriesService + SCIM *SCIMService + Search *SearchService + SecretScanning *SecretScanningService + SecurityAdvisories *SecurityAdvisoriesService + Teams *TeamsService + Users *UsersService +} + +type service struct { + client *Client +} + +// Client returns the http.Client used by this GitHub client. +// This should only be used for requests to the GitHub API because +// request headers will contain an authorization token. +func (c *Client) Client() *http.Client { + c.clientMu.Lock() + defer c.clientMu.Unlock() + clientCopy := *c.client + return &clientCopy +} + +// ListOptions specifies the optional parameters to various List methods that +// support offset pagination. +type ListOptions struct { + // For paginated result sets, page of results to retrieve. + Page int `url:"page,omitempty"` + + // For paginated result sets, the number of results to include per page. + PerPage int `url:"per_page,omitempty"` +} + +// ListCursorOptions specifies the optional parameters to various List methods that +// support cursor pagination. +type ListCursorOptions struct { + // For paginated result sets, page of results to retrieve. + Page string `url:"page,omitempty"` + + // For paginated result sets, the number of results to include per page. + PerPage int `url:"per_page,omitempty"` + + // For paginated result sets, the number of results per page (max 100), starting from the first matching result. + // This parameter must not be used in combination with last. + First int `url:"first,omitempty"` + + // For paginated result sets, the number of results per page (max 100), starting from the last matching result. + // This parameter must not be used in combination with first. + Last int `url:"last,omitempty"` + + // A cursor, as given in the Link header. If specified, the query only searches for events after this cursor. + After string `url:"after,omitempty"` + + // A cursor, as given in the Link header. If specified, the query only searches for events before this cursor. + Before string `url:"before,omitempty"` + + // A cursor, as given in the Link header. If specified, the query continues the search using this cursor. + Cursor string `url:"cursor,omitempty"` +} + +// UploadOptions specifies the parameters to methods that support uploads. +type UploadOptions struct { + Name string `url:"name,omitempty"` + Label string `url:"label,omitempty"` + MediaType string `url:"-"` +} + +// RawType represents type of raw format of a request instead of JSON. +type RawType uint8 + +const ( + // Diff format. + Diff RawType = 1 + iota + // Patch format. + Patch +) + +// RawOptions specifies parameters when user wants to get raw format of +// a response instead of JSON. +type RawOptions struct { + Type RawType +} + +// addOptions adds the parameters in opts as URL query parameters to s. opts +// must be a struct whose fields may contain "url" tags. +func addOptions(s string, opts interface{}) (string, error) { + v := reflect.ValueOf(opts) + if v.Kind() == reflect.Ptr && v.IsNil() { + return s, nil + } + + u, err := url.Parse(s) + if err != nil { + return s, err + } + + qs, err := query.Values(opts) + if err != nil { + return s, err + } + + u.RawQuery = qs.Encode() + return u.String(), nil +} + +// NewClient returns a new GitHub API client. If a nil httpClient is +// provided, a new http.Client will be used. To use API methods which require +// authentication, either use Client.WithAuthToken or provide NewClient with +// an http.Client that will perform the authentication for you (such as that +// provided by the golang.org/x/oauth2 library). +func NewClient(httpClient *http.Client) *Client { + if httpClient == nil { + httpClient = &http.Client{} + } + httpClient2 := *httpClient + c := &Client{client: &httpClient2} + c.initialize() + return c +} + +// WithAuthToken returns a copy of the client configured to use the provided token for the Authorization header. +func (c *Client) WithAuthToken(token string) *Client { + c2 := c.copy() + defer c2.initialize() + transport := c2.client.Transport + if transport == nil { + transport = http.DefaultTransport + } + c2.client.Transport = roundTripperFunc( + func(req *http.Request) (*http.Response, error) { + req = req.Clone(req.Context()) + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token)) + return transport.RoundTrip(req) + }, + ) + return c2 +} + +// WithEnterpriseURLs returns a copy of the client configured to use the provided base and +// upload URLs. If the base URL does not have the suffix "/api/v3/", it will be added +// automatically. If the upload URL does not have the suffix "/api/uploads", it will be +// added automatically. +// +// Note that WithEnterpriseURLs is a convenience helper only; +// its behavior is equivalent to setting the BaseURL and UploadURL fields. +// +// Another important thing is that by default, the GitHub Enterprise URL format +// should be http(s)://[hostname]/api/v3/ or you will always receive the 406 status code. +// The upload URL format should be http(s)://[hostname]/api/uploads/. +func (c *Client) WithEnterpriseURLs(baseURL, uploadURL string) (*Client, error) { + c2 := c.copy() + defer c2.initialize() + var err error + c2.BaseURL, err = url.Parse(baseURL) + if err != nil { + return nil, err + } + + if !strings.HasSuffix(c2.BaseURL.Path, "/") { + c2.BaseURL.Path += "/" + } + if !strings.HasSuffix(c2.BaseURL.Path, "/api/v3/") && + !strings.HasPrefix(c2.BaseURL.Host, "api.") && + !strings.Contains(c2.BaseURL.Host, ".api.") { + c2.BaseURL.Path += "api/v3/" + } + + c2.UploadURL, err = url.Parse(uploadURL) + if err != nil { + return nil, err + } + + if !strings.HasSuffix(c2.UploadURL.Path, "/") { + c2.UploadURL.Path += "/" + } + if !strings.HasSuffix(c2.UploadURL.Path, "/api/uploads/") && + !strings.HasPrefix(c2.UploadURL.Host, "api.") && + !strings.Contains(c2.UploadURL.Host, ".api.") { + c2.UploadURL.Path += "api/uploads/" + } + return c2, nil +} + +// initialize sets default values and initializes services. +func (c *Client) initialize() { + if c.client == nil { + c.client = &http.Client{} + } + if c.BaseURL == nil { + c.BaseURL, _ = url.Parse(defaultBaseURL) + } + if c.UploadURL == nil { + c.UploadURL, _ = url.Parse(uploadBaseURL) + } + if c.UserAgent == "" { + c.UserAgent = defaultUserAgent + } + c.common.client = c + c.Actions = (*ActionsService)(&c.common) + c.Activity = (*ActivityService)(&c.common) + c.Admin = (*AdminService)(&c.common) + c.Apps = (*AppsService)(&c.common) + c.Authorizations = (*AuthorizationsService)(&c.common) + c.Billing = (*BillingService)(&c.common) + c.Checks = (*ChecksService)(&c.common) + c.CodeScanning = (*CodeScanningService)(&c.common) + c.Codespaces = (*CodespacesService)(&c.common) + c.CodesOfConduct = (*CodesOfConductService)(&c.common) + c.Copilot = (*CopilotService)(&c.common) + c.Dependabot = (*DependabotService)(&c.common) + c.DependencyGraph = (*DependencyGraphService)(&c.common) + c.Emojis = (*EmojisService)(&c.common) + c.Enterprise = (*EnterpriseService)(&c.common) + c.Gists = (*GistsService)(&c.common) + c.Git = (*GitService)(&c.common) + c.Gitignores = (*GitignoresService)(&c.common) + c.Interactions = (*InteractionsService)(&c.common) + c.IssueImport = (*IssueImportService)(&c.common) + c.Issues = (*IssuesService)(&c.common) + c.Licenses = (*LicensesService)(&c.common) + c.Markdown = (*MarkdownService)(&c.common) + c.Marketplace = &MarketplaceService{client: c} + c.Meta = (*MetaService)(&c.common) + c.Migrations = (*MigrationService)(&c.common) + c.Organizations = (*OrganizationsService)(&c.common) + c.PullRequests = (*PullRequestsService)(&c.common) + c.RateLimit = (*RateLimitService)(&c.common) + c.Reactions = (*ReactionsService)(&c.common) + c.Repositories = (*RepositoriesService)(&c.common) + c.SCIM = (*SCIMService)(&c.common) + c.Search = (*SearchService)(&c.common) + c.SecretScanning = (*SecretScanningService)(&c.common) + c.SecurityAdvisories = (*SecurityAdvisoriesService)(&c.common) + c.Teams = (*TeamsService)(&c.common) + c.Users = (*UsersService)(&c.common) +} + +// copy returns a copy of the current client. It must be initialized before use. +func (c *Client) copy() *Client { + c.clientMu.Lock() + // can't use *c here because that would copy mutexes by value. + clone := Client{ + client: &http.Client{}, + UserAgent: c.UserAgent, + BaseURL: c.BaseURL, + UploadURL: c.UploadURL, + secondaryRateLimitReset: c.secondaryRateLimitReset, + } + c.clientMu.Unlock() + if c.client != nil { + clone.client.Transport = c.client.Transport + clone.client.CheckRedirect = c.client.CheckRedirect + clone.client.Jar = c.client.Jar + clone.client.Timeout = c.client.Timeout + } + c.rateMu.Lock() + copy(clone.rateLimits[:], c.rateLimits[:]) + c.rateMu.Unlock() + return &clone +} + +// NewClientWithEnvProxy enhances NewClient with the HttpProxy env. +func NewClientWithEnvProxy() *Client { + return NewClient(&http.Client{Transport: &http.Transport{Proxy: http.ProxyFromEnvironment}}) +} + +// NewTokenClient returns a new GitHub API client authenticated with the provided token. +// Deprecated: Use NewClient(nil).WithAuthToken(token) instead. +func NewTokenClient(_ context.Context, token string) *Client { + // This always returns a nil error. + return NewClient(nil).WithAuthToken(token) +} + +// NewEnterpriseClient returns a new GitHub API client with provided +// base URL and upload URL (often is your GitHub Enterprise hostname). +// +// Deprecated: Use NewClient(httpClient).WithEnterpriseURLs(baseURL, uploadURL) instead. +func NewEnterpriseClient(baseURL, uploadURL string, httpClient *http.Client) (*Client, error) { + return NewClient(httpClient).WithEnterpriseURLs(baseURL, uploadURL) +} + +// RequestOption represents an option that can modify an http.Request. +type RequestOption func(req *http.Request) + +// WithVersion overrides the GitHub v3 API version for this individual request. +// For more information, see: +// https://github.blog/2022-11-28-to-infinity-and-beyond-enabling-the-future-of-githubs-rest-api-with-api-versioning/ +func WithVersion(version string) RequestOption { + return func(req *http.Request) { + req.Header.Set(headerAPIVersion, version) + } +} + +// NewRequest creates an API request. A relative URL can be provided in urlStr, +// in which case it is resolved relative to the BaseURL of the Client. +// Relative URLs should always be specified without a preceding slash. If +// specified, the value pointed to by body is JSON encoded and included as the +// request body. +func (c *Client) NewRequest(method, urlStr string, body interface{}, opts ...RequestOption) (*http.Request, error) { + if !strings.HasSuffix(c.BaseURL.Path, "/") { + return nil, fmt.Errorf("BaseURL must have a trailing slash, but %q does not", c.BaseURL) + } + + u, err := c.BaseURL.Parse(urlStr) + if err != nil { + return nil, err + } + + var buf io.ReadWriter + if body != nil { + buf = &bytes.Buffer{} + enc := json.NewEncoder(buf) + enc.SetEscapeHTML(false) + err := enc.Encode(body) + if err != nil { + return nil, err + } + } + + req, err := http.NewRequest(method, u.String(), buf) + if err != nil { + return nil, err + } + + if body != nil { + req.Header.Set("Content-Type", "application/json") + } + req.Header.Set("Accept", mediaTypeV3) + if c.UserAgent != "" { + req.Header.Set("User-Agent", c.UserAgent) + } + req.Header.Set(headerAPIVersion, defaultAPIVersion) + + for _, opt := range opts { + opt(req) + } + + return req, nil +} + +// NewFormRequest creates an API request. A relative URL can be provided in urlStr, +// in which case it is resolved relative to the BaseURL of the Client. +// Relative URLs should always be specified without a preceding slash. +// Body is sent with Content-Type: application/x-www-form-urlencoded. +func (c *Client) NewFormRequest(urlStr string, body io.Reader, opts ...RequestOption) (*http.Request, error) { + if !strings.HasSuffix(c.BaseURL.Path, "/") { + return nil, fmt.Errorf("BaseURL must have a trailing slash, but %q does not", c.BaseURL) + } + + u, err := c.BaseURL.Parse(urlStr) + if err != nil { + return nil, err + } + + req, err := http.NewRequest(http.MethodPost, u.String(), body) + if err != nil { + return nil, err + } + + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + req.Header.Set("Accept", mediaTypeV3) + if c.UserAgent != "" { + req.Header.Set("User-Agent", c.UserAgent) + } + req.Header.Set(headerAPIVersion, defaultAPIVersion) + + for _, opt := range opts { + opt(req) + } + + return req, nil +} + +// NewUploadRequest creates an upload request. A relative URL can be provided in +// urlStr, in which case it is resolved relative to the UploadURL of the Client. +// Relative URLs should always be specified without a preceding slash. +func (c *Client) NewUploadRequest(urlStr string, reader io.Reader, size int64, mediaType string, opts ...RequestOption) (*http.Request, error) { + if !strings.HasSuffix(c.UploadURL.Path, "/") { + return nil, fmt.Errorf("UploadURL must have a trailing slash, but %q does not", c.UploadURL) + } + u, err := c.UploadURL.Parse(urlStr) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", u.String(), reader) + if err != nil { + return nil, err + } + + req.ContentLength = size + + if mediaType == "" { + mediaType = defaultMediaType + } + req.Header.Set("Content-Type", mediaType) + req.Header.Set("Accept", mediaTypeV3) + req.Header.Set("User-Agent", c.UserAgent) + req.Header.Set(headerAPIVersion, defaultAPIVersion) + + for _, opt := range opts { + opt(req) + } + + return req, nil +} + +// Response is a GitHub API response. This wraps the standard http.Response +// returned from GitHub and provides convenient access to things like +// pagination links. +type Response struct { + *http.Response + + // These fields provide the page values for paginating through a set of + // results. Any or all of these may be set to the zero value for + // responses that are not part of a paginated set, or for which there + // are no additional pages. + // + // These fields support what is called "offset pagination" and should + // be used with the ListOptions struct. + NextPage int + PrevPage int + FirstPage int + LastPage int + + // Additionally, some APIs support "cursor pagination" instead of offset. + // This means that a token points directly to the next record which + // can lead to O(1) performance compared to O(n) performance provided + // by offset pagination. + // + // For APIs that support cursor pagination (such as + // TeamsService.ListIDPGroupsInOrganization), the following field + // will be populated to point to the next page. + // + // To use this token, set ListCursorOptions.Page to this value before + // calling the endpoint again. + NextPageToken string + + // For APIs that support cursor pagination, such as RepositoriesService.ListHookDeliveries, + // the following field will be populated to point to the next page. + // Set ListCursorOptions.Cursor to this value when calling the endpoint again. + Cursor string + + // For APIs that support before/after pagination, such as OrganizationsService.AuditLog. + Before string + After string + + // Explicitly specify the Rate type so Rate's String() receiver doesn't + // propagate to Response. + Rate Rate + + // token's expiration date. Timestamp is 0001-01-01 when token doesn't expire. + // So it is valid for TokenExpiration.Equal(Timestamp{}) or TokenExpiration.Time.After(time.Now()) + TokenExpiration Timestamp +} + +// newResponse creates a new Response for the provided http.Response. +// r must not be nil. +func newResponse(r *http.Response) *Response { + response := &Response{Response: r} + response.populatePageValues() + response.Rate = parseRate(r) + response.TokenExpiration = parseTokenExpiration(r) + return response +} + +// populatePageValues parses the HTTP Link response headers and populates the +// various pagination link values in the Response. +func (r *Response) populatePageValues() { + if links, ok := r.Response.Header["Link"]; ok && len(links) > 0 { + for _, link := range strings.Split(links[0], ",") { + segments := strings.Split(strings.TrimSpace(link), ";") + + // link must at least have href and rel + if len(segments) < 2 { + continue + } + + // ensure href is properly formatted + if !strings.HasPrefix(segments[0], "<") || !strings.HasSuffix(segments[0], ">") { + continue + } + + // try to pull out page parameter + url, err := url.Parse(segments[0][1 : len(segments[0])-1]) + if err != nil { + continue + } + + q := url.Query() + + if cursor := q.Get("cursor"); cursor != "" { + for _, segment := range segments[1:] { + switch strings.TrimSpace(segment) { + case `rel="next"`: + r.Cursor = cursor + } + } + + continue + } + + page := q.Get("page") + since := q.Get("since") + before := q.Get("before") + after := q.Get("after") + + if page == "" && before == "" && after == "" && since == "" { + continue + } + + if since != "" && page == "" { + page = since + } + + for _, segment := range segments[1:] { + switch strings.TrimSpace(segment) { + case `rel="next"`: + if r.NextPage, err = strconv.Atoi(page); err != nil { + r.NextPageToken = page + } + r.After = after + case `rel="prev"`: + r.PrevPage, _ = strconv.Atoi(page) + r.Before = before + case `rel="first"`: + r.FirstPage, _ = strconv.Atoi(page) + case `rel="last"`: + r.LastPage, _ = strconv.Atoi(page) + } + } + } + } +} + +// parseRate parses the rate related headers. +func parseRate(r *http.Response) Rate { + var rate Rate + if limit := r.Header.Get(headerRateLimit); limit != "" { + rate.Limit, _ = strconv.Atoi(limit) + } + if remaining := r.Header.Get(headerRateRemaining); remaining != "" { + rate.Remaining, _ = strconv.Atoi(remaining) + } + if reset := r.Header.Get(headerRateReset); reset != "" { + if v, _ := strconv.ParseInt(reset, 10, 64); v != 0 { + rate.Reset = Timestamp{time.Unix(v, 0)} + } + } + return rate +} + +// parseSecondaryRate parses the secondary rate related headers, +// and returns the time to retry after. +func parseSecondaryRate(r *http.Response) *time.Duration { + // According to GitHub support, the "Retry-After" header value will be + // an integer which represents the number of seconds that one should + // wait before resuming making requests. + if v := r.Header.Get(headerRetryAfter); v != "" { + retryAfterSeconds, _ := strconv.ParseInt(v, 10, 64) // Error handling is noop. + retryAfter := time.Duration(retryAfterSeconds) * time.Second + return &retryAfter + } + + // According to GitHub support, endpoints might return x-ratelimit-reset instead, + // as an integer which represents the number of seconds since epoch UTC, + // representing the time to resume making requests. + if v := r.Header.Get(headerRateReset); v != "" { + secondsSinceEpoch, _ := strconv.ParseInt(v, 10, 64) // Error handling is noop. + retryAfter := time.Until(time.Unix(secondsSinceEpoch, 0)) + return &retryAfter + } + + return nil +} + +// parseTokenExpiration parses the TokenExpiration related headers. +// Returns 0001-01-01 if the header is not defined or could not be parsed. +func parseTokenExpiration(r *http.Response) Timestamp { + if v := r.Header.Get(headerTokenExpiration); v != "" { + if t, err := time.Parse("2006-01-02 15:04:05 MST", v); err == nil { + return Timestamp{t.Local()} + } + // Some tokens include the timezone offset instead of the timezone. + // https://github.com/google/go-github/issues/2649 + if t, err := time.Parse("2006-01-02 15:04:05 -0700", v); err == nil { + return Timestamp{t.Local()} + } + } + return Timestamp{} // 0001-01-01 00:00:00 +} + +type requestContext uint8 + +const ( + bypassRateLimitCheck requestContext = iota + SleepUntilPrimaryRateLimitResetWhenRateLimited +) + +// BareDo sends an API request and lets you handle the api response. If an error +// or API Error occurs, the error will contain more information. Otherwise you +// are supposed to read and close the response's Body. If rate limit is exceeded +// and reset time is in the future, BareDo returns *RateLimitError immediately +// without making a network API call. +// +// The provided ctx must be non-nil, if it is nil an error is returned. If it is +// canceled or times out, ctx.Err() will be returned. +func (c *Client) BareDo(ctx context.Context, req *http.Request) (*Response, error) { + if ctx == nil { + return nil, errNonNilContext + } + + req = withContext(ctx, req) + + rateLimitCategory := GetRateLimitCategory(req.Method, req.URL.Path) + + if bypass := ctx.Value(bypassRateLimitCheck); bypass == nil { + // If we've hit rate limit, don't make further requests before Reset time. + if err := c.checkRateLimitBeforeDo(req, rateLimitCategory); err != nil { + return &Response{ + Response: err.Response, + Rate: err.Rate, + }, err + } + // If we've hit a secondary rate limit, don't make further requests before Retry After. + if err := c.checkSecondaryRateLimitBeforeDo(req); err != nil { + return &Response{ + Response: err.Response, + }, err + } + } + + resp, err := c.client.Do(req) + var response *Response + if resp != nil { + response = newResponse(resp) + } + + if err != nil { + // If we got an error, and the context has been canceled, + // the context's error is probably more useful. + select { + case <-ctx.Done(): + return response, ctx.Err() + default: + } + + // If the error type is *url.Error, sanitize its URL before returning. + if e, ok := err.(*url.Error); ok { + if url, err := url.Parse(e.URL); err == nil { + e.URL = sanitizeURL(url).String() + return response, e + } + } + + return response, err + } + + // Don't update the rate limits if this was a cached response. + // X-From-Cache is set by https://github.com/gregjones/httpcache + if response.Header.Get("X-From-Cache") == "" { + c.rateMu.Lock() + c.rateLimits[rateLimitCategory] = response.Rate + c.rateMu.Unlock() + } + + err = CheckResponse(resp) + if err != nil { + defer resp.Body.Close() + // Special case for AcceptedErrors. If an AcceptedError + // has been encountered, the response's payload will be + // added to the AcceptedError and returned. + // + // Issue #1022 + aerr, ok := err.(*AcceptedError) + if ok { + b, readErr := io.ReadAll(resp.Body) + if readErr != nil { + return response, readErr + } + + aerr.Raw = b + err = aerr + } + + rateLimitError, ok := err.(*RateLimitError) + if ok && req.Context().Value(SleepUntilPrimaryRateLimitResetWhenRateLimited) != nil { + if err := sleepUntilResetWithBuffer(req.Context(), rateLimitError.Rate.Reset.Time); err != nil { + return response, err + } + // retry the request once when the rate limit has reset + return c.BareDo(context.WithValue(req.Context(), SleepUntilPrimaryRateLimitResetWhenRateLimited, nil), req) + } + + // Update the secondary rate limit if we hit it. + rerr, ok := err.(*AbuseRateLimitError) + if ok && rerr.RetryAfter != nil { + c.rateMu.Lock() + c.secondaryRateLimitReset = time.Now().Add(*rerr.RetryAfter) + c.rateMu.Unlock() + } + } + return response, err +} + +// Do sends an API request and returns the API response. The API response is +// JSON decoded and stored in the value pointed to by v, or returned as an +// error if an API error has occurred. If v implements the io.Writer interface, +// the raw response body will be written to v, without attempting to first +// decode it. If v is nil, and no error happens, the response is returned as is. +// If rate limit is exceeded and reset time is in the future, Do returns +// *RateLimitError immediately without making a network API call. +// +// The provided ctx must be non-nil, if it is nil an error is returned. If it +// is canceled or times out, ctx.Err() will be returned. +func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}) (*Response, error) { + resp, err := c.BareDo(ctx, req) + if err != nil { + return resp, err + } + defer resp.Body.Close() + + switch v := v.(type) { + case nil: + case io.Writer: + _, err = io.Copy(v, resp.Body) + default: + decErr := json.NewDecoder(resp.Body).Decode(v) + if decErr == io.EOF { + decErr = nil // ignore EOF errors caused by empty response body + } + if decErr != nil { + err = decErr + } + } + return resp, err +} + +// checkRateLimitBeforeDo does not make any network calls, but uses existing knowledge from +// current client state in order to quickly check if *RateLimitError can be immediately returned +// from Client.Do, and if so, returns it so that Client.Do can skip making a network API call unnecessarily. +// Otherwise it returns nil, and Client.Do should proceed normally. +func (c *Client) checkRateLimitBeforeDo(req *http.Request, rateLimitCategory RateLimitCategory) *RateLimitError { + c.rateMu.Lock() + rate := c.rateLimits[rateLimitCategory] + c.rateMu.Unlock() + if !rate.Reset.Time.IsZero() && rate.Remaining == 0 && time.Now().Before(rate.Reset.Time) { + // Create a fake response. + resp := &http.Response{ + Status: http.StatusText(http.StatusForbidden), + StatusCode: http.StatusForbidden, + Request: req, + Header: make(http.Header), + Body: io.NopCloser(strings.NewReader("")), + } + + if req.Context().Value(SleepUntilPrimaryRateLimitResetWhenRateLimited) != nil { + if err := sleepUntilResetWithBuffer(req.Context(), rate.Reset.Time); err == nil { + return nil + } + return &RateLimitError{ + Rate: rate, + Response: resp, + Message: fmt.Sprintf("Context cancelled while waiting for rate limit to reset until %v, not making remote request.", rate.Reset.Time), + } + } + + return &RateLimitError{ + Rate: rate, + Response: resp, + Message: fmt.Sprintf("API rate limit of %v still exceeded until %v, not making remote request.", rate.Limit, rate.Reset.Time), + } + } + + return nil +} + +// checkSecondaryRateLimitBeforeDo does not make any network calls, but uses existing knowledge from +// current client state in order to quickly check if *AbuseRateLimitError can be immediately returned +// from Client.Do, and if so, returns it so that Client.Do can skip making a network API call unnecessarily. +// Otherwise it returns nil, and Client.Do should proceed normally. +func (c *Client) checkSecondaryRateLimitBeforeDo(req *http.Request) *AbuseRateLimitError { + c.rateMu.Lock() + secondary := c.secondaryRateLimitReset + c.rateMu.Unlock() + if !secondary.IsZero() && time.Now().Before(secondary) { + // Create a fake response. + resp := &http.Response{ + Status: http.StatusText(http.StatusForbidden), + StatusCode: http.StatusForbidden, + Request: req, + Header: make(http.Header), + Body: io.NopCloser(strings.NewReader("")), + } + + retryAfter := time.Until(secondary) + return &AbuseRateLimitError{ + Response: resp, + Message: fmt.Sprintf("API secondary rate limit exceeded until %v, not making remote request.", secondary), + RetryAfter: &retryAfter, + } + } + + return nil +} + +// compareHTTPResponse returns whether two http.Response objects are equal or not. +// Currently, only StatusCode is checked. This function is used when implementing the +// Is(error) bool interface for the custom error types in this package. +func compareHTTPResponse(r1, r2 *http.Response) bool { + if r1 == nil && r2 == nil { + return true + } + + if r1 != nil && r2 != nil { + return r1.StatusCode == r2.StatusCode + } + return false +} + +/* +An ErrorResponse reports one or more errors caused by an API request. + +GitHub API docs: https://docs.github.com/rest/#client-errors +*/ +type ErrorResponse struct { + Response *http.Response `json:"-"` // HTTP response that caused this error + Message string `json:"message"` // error message + Errors []Error `json:"errors"` // more detail on individual errors + // Block is only populated on certain types of errors such as code 451. + Block *ErrorBlock `json:"block,omitempty"` + // Most errors will also include a documentation_url field pointing + // to some content that might help you resolve the error, see + // https://docs.github.com/rest/#client-errors + DocumentationURL string `json:"documentation_url,omitempty"` +} + +// ErrorBlock contains a further explanation for the reason of an error. +// See https://developer.github.com/changes/2016-03-17-the-451-status-code-is-now-supported/ +// for more information. +type ErrorBlock struct { + Reason string `json:"reason,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` +} + +func (r *ErrorResponse) Error() string { + if r.Response != nil && r.Response.Request != nil { + return fmt.Sprintf("%v %v: %d %v %+v", + r.Response.Request.Method, sanitizeURL(r.Response.Request.URL), + r.Response.StatusCode, r.Message, r.Errors) + } + + if r.Response != nil { + return fmt.Sprintf("%d %v %+v", r.Response.StatusCode, r.Message, r.Errors) + } + + return fmt.Sprintf("%v %+v", r.Message, r.Errors) +} + +// Is returns whether the provided error equals this error. +func (r *ErrorResponse) Is(target error) bool { + v, ok := target.(*ErrorResponse) + if !ok { + return false + } + + if r.Message != v.Message || (r.DocumentationURL != v.DocumentationURL) || + !compareHTTPResponse(r.Response, v.Response) { + return false + } + + // Compare Errors. + if len(r.Errors) != len(v.Errors) { + return false + } + for idx := range r.Errors { + if r.Errors[idx] != v.Errors[idx] { + return false + } + } + + // Compare Block. + if (r.Block != nil && v.Block == nil) || (r.Block == nil && v.Block != nil) { + return false + } + if r.Block != nil && v.Block != nil { + if r.Block.Reason != v.Block.Reason { + return false + } + if (r.Block.CreatedAt != nil && v.Block.CreatedAt == nil) || (r.Block.CreatedAt == + nil && v.Block.CreatedAt != nil) { + return false + } + if r.Block.CreatedAt != nil && v.Block.CreatedAt != nil { + if *(r.Block.CreatedAt) != *(v.Block.CreatedAt) { + return false + } + } + } + + return true +} + +// TwoFactorAuthError occurs when using HTTP Basic Authentication for a user +// that has two-factor authentication enabled. The request can be reattempted +// by providing a one-time password in the request. +type TwoFactorAuthError ErrorResponse + +func (r *TwoFactorAuthError) Error() string { return (*ErrorResponse)(r).Error() } + +// RateLimitError occurs when GitHub returns 403 Forbidden response with a rate limit +// remaining value of 0. +type RateLimitError struct { + Rate Rate // Rate specifies last known rate limit for the client + Response *http.Response // HTTP response that caused this error + Message string `json:"message"` // error message +} + +func (r *RateLimitError) Error() string { + return fmt.Sprintf("%v %v: %d %v %v", + r.Response.Request.Method, sanitizeURL(r.Response.Request.URL), + r.Response.StatusCode, r.Message, formatRateReset(time.Until(r.Rate.Reset.Time))) +} + +// Is returns whether the provided error equals this error. +func (r *RateLimitError) Is(target error) bool { + v, ok := target.(*RateLimitError) + if !ok { + return false + } + + return r.Rate == v.Rate && + r.Message == v.Message && + compareHTTPResponse(r.Response, v.Response) +} + +// AcceptedError occurs when GitHub returns 202 Accepted response with an +// empty body, which means a job was scheduled on the GitHub side to process +// the information needed and cache it. +// Technically, 202 Accepted is not a real error, it's just used to +// indicate that results are not ready yet, but should be available soon. +// The request can be repeated after some time. +type AcceptedError struct { + // Raw contains the response body. + Raw []byte +} + +func (*AcceptedError) Error() string { + return "job scheduled on GitHub side; try again later" +} + +// Is returns whether the provided error equals this error. +func (ae *AcceptedError) Is(target error) bool { + v, ok := target.(*AcceptedError) + if !ok { + return false + } + return bytes.Equal(ae.Raw, v.Raw) +} + +// AbuseRateLimitError occurs when GitHub returns 403 Forbidden response with the +// "documentation_url" field value equal to "https://docs.github.com/rest/overview/rate-limits-for-the-rest-api#about-secondary-rate-limits". +type AbuseRateLimitError struct { + Response *http.Response // HTTP response that caused this error + Message string `json:"message"` // error message + + // RetryAfter is provided with some abuse rate limit errors. If present, + // it is the amount of time that the client should wait before retrying. + // Otherwise, the client should try again later (after an unspecified amount of time). + RetryAfter *time.Duration +} + +func (r *AbuseRateLimitError) Error() string { + return fmt.Sprintf("%v %v: %d %v", + r.Response.Request.Method, sanitizeURL(r.Response.Request.URL), + r.Response.StatusCode, r.Message) +} + +// Is returns whether the provided error equals this error. +func (r *AbuseRateLimitError) Is(target error) bool { + v, ok := target.(*AbuseRateLimitError) + if !ok { + return false + } + + return r.Message == v.Message && + r.RetryAfter == v.RetryAfter && + compareHTTPResponse(r.Response, v.Response) +} + +// sanitizeURL redacts the client_secret parameter from the URL which may be +// exposed to the user. +func sanitizeURL(uri *url.URL) *url.URL { + if uri == nil { + return nil + } + params := uri.Query() + if len(params.Get("client_secret")) > 0 { + params.Set("client_secret", "REDACTED") + uri.RawQuery = params.Encode() + } + return uri +} + +/* +An Error reports more details on an individual error in an ErrorResponse. +These are the possible validation error codes: + + missing: + resource does not exist + missing_field: + a required field on a resource has not been set + invalid: + the formatting of a field is invalid + already_exists: + another resource has the same valid as this field + custom: + some resources return this (e.g. github.User.CreateKey()), additional + information is set in the Message field of the Error + +GitHub error responses structure are often undocumented and inconsistent. +Sometimes error is just a simple string (Issue #540). +In such cases, Message represents an error message as a workaround. + +GitHub API docs: https://docs.github.com/rest/#client-errors +*/ +type Error struct { + Resource string `json:"resource"` // resource on which the error occurred + Field string `json:"field"` // field on which the error occurred + Code string `json:"code"` // validation error code + Message string `json:"message"` // Message describing the error. Errors with Code == "custom" will always have this set. +} + +func (e *Error) Error() string { + return fmt.Sprintf("%v error caused by %v field on %v resource", + e.Code, e.Field, e.Resource) +} + +func (e *Error) UnmarshalJSON(data []byte) error { + type aliasError Error // avoid infinite recursion by using type alias. + if err := json.Unmarshal(data, (*aliasError)(e)); err != nil { + return json.Unmarshal(data, &e.Message) // data can be json string. + } + return nil +} + +// CheckResponse checks the API response for errors, and returns them if +// present. A response is considered an error if it has a status code outside +// the 200 range or equal to 202 Accepted. +// API error responses are expected to have response +// body, and a JSON response body that maps to ErrorResponse. +// +// The error type will be *RateLimitError for rate limit exceeded errors, +// *AcceptedError for 202 Accepted status codes, +// and *TwoFactorAuthError for two-factor authentication errors. +func CheckResponse(r *http.Response) error { + if r.StatusCode == http.StatusAccepted { + return &AcceptedError{} + } + if c := r.StatusCode; 200 <= c && c <= 299 { + return nil + } + + errorResponse := &ErrorResponse{Response: r} + data, err := io.ReadAll(r.Body) + if err == nil && data != nil { + err = json.Unmarshal(data, errorResponse) + if err != nil { + // reset the response as if this never happened + errorResponse = &ErrorResponse{Response: r} + } + } + // Re-populate error response body because GitHub error responses are often + // undocumented and inconsistent. + // Issue #1136, #540. + r.Body = io.NopCloser(bytes.NewBuffer(data)) + switch { + case r.StatusCode == http.StatusUnauthorized && strings.HasPrefix(r.Header.Get(headerOTP), "required"): + return (*TwoFactorAuthError)(errorResponse) + case r.StatusCode == http.StatusForbidden && r.Header.Get(headerRateRemaining) == "0": + return &RateLimitError{ + Rate: parseRate(r), + Response: errorResponse.Response, + Message: errorResponse.Message, + } + case r.StatusCode == http.StatusForbidden && + (strings.HasSuffix(errorResponse.DocumentationURL, "#abuse-rate-limits") || + strings.HasSuffix(errorResponse.DocumentationURL, "secondary-rate-limits")): + abuseRateLimitError := &AbuseRateLimitError{ + Response: errorResponse.Response, + Message: errorResponse.Message, + } + if retryAfter := parseSecondaryRate(r); retryAfter != nil { + abuseRateLimitError.RetryAfter = retryAfter + } + return abuseRateLimitError + default: + return errorResponse + } +} + +// parseBoolResponse determines the boolean result from a GitHub API response. +// Several GitHub API methods return boolean responses indicated by the HTTP +// status code in the response (true indicated by a 204, false indicated by a +// 404). This helper function will determine that result and hide the 404 +// error if present. Any other error will be returned through as-is. +func parseBoolResponse(err error) (bool, error) { + if err == nil { + return true, nil + } + + if err, ok := err.(*ErrorResponse); ok && err.Response.StatusCode == http.StatusNotFound { + // Simply false. In this one case, we do not pass the error through. + return false, nil + } + + // some other real error occurred + return false, err +} + +type RateLimitCategory uint8 + +const ( + CoreCategory RateLimitCategory = iota + SearchCategory + GraphqlCategory + IntegrationManifestCategory + SourceImportCategory + CodeScanningUploadCategory + ActionsRunnerRegistrationCategory + ScimCategory + DependencySnapshotsCategory + CodeSearchCategory + AuditLogCategory + + Categories // An array of this length will be able to contain all rate limit categories. +) + +// GetRateLimitCategory returns the rate limit RateLimitCategory of the endpoint, determined by HTTP method and Request.URL.Path. +func GetRateLimitCategory(method, path string) RateLimitCategory { + switch { + // https://docs.github.com/rest/rate-limit#about-rate-limits + default: + // NOTE: coreCategory is returned for actionsRunnerRegistrationCategory too, + // because no API found for this category. + return CoreCategory + + // https://docs.github.com/en/rest/search/search#search-code + case strings.HasPrefix(path, "/search/code") && + method == http.MethodGet: + return CodeSearchCategory + + case strings.HasPrefix(path, "/search/"): + return SearchCategory + case path == "/graphql": + return GraphqlCategory + case strings.HasPrefix(path, "/app-manifests/") && + strings.HasSuffix(path, "/conversions") && + method == http.MethodPost: + return IntegrationManifestCategory + + // https://docs.github.com/rest/migrations/source-imports#start-an-import + case strings.HasPrefix(path, "/repos/") && + strings.HasSuffix(path, "/import") && + method == http.MethodPut: + return SourceImportCategory + + // https://docs.github.com/rest/code-scanning#upload-an-analysis-as-sarif-data + case strings.HasSuffix(path, "/code-scanning/sarifs"): + return CodeScanningUploadCategory + + // https://docs.github.com/enterprise-cloud@latest/rest/scim + case strings.HasPrefix(path, "/scim/"): + return ScimCategory + + // https://docs.github.com/en/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository + case strings.HasPrefix(path, "/repos/") && + strings.HasSuffix(path, "/dependency-graph/snapshots") && + method == http.MethodPost: + return DependencySnapshotsCategory + + // https://docs.github.com/en/enterprise-cloud@latest/rest/orgs/orgs?apiVersion=2022-11-28#get-the-audit-log-for-an-organization + case strings.HasSuffix(path, "/audit-log"): + return AuditLogCategory + } +} + +// RateLimits returns the rate limits for the current client. +// +// Deprecated: Use RateLimitService.Get instead. +func (c *Client) RateLimits(ctx context.Context) (*RateLimits, *Response, error) { + return c.RateLimit.Get(ctx) +} + +func setCredentialsAsHeaders(req *http.Request, id, secret string) *http.Request { + // To set extra headers, we must make a copy of the Request so + // that we don't modify the Request we were given. This is required by the + // specification of http.RoundTripper. + // + // Since we are going to modify only req.Header here, we only need a deep copy + // of req.Header. + convertedRequest := new(http.Request) + *convertedRequest = *req + convertedRequest.Header = make(http.Header, len(req.Header)) + + for k, s := range req.Header { + convertedRequest.Header[k] = append([]string(nil), s...) + } + convertedRequest.SetBasicAuth(id, secret) + return convertedRequest +} + +/* +UnauthenticatedRateLimitedTransport allows you to make unauthenticated calls +that need to use a higher rate limit associated with your OAuth application. + + t := &github.UnauthenticatedRateLimitedTransport{ + ClientID: "your app's client ID", + ClientSecret: "your app's client secret", + } + client := github.NewClient(t.Client()) + +This will add the client id and secret as a base64-encoded string in the format +ClientID:ClientSecret and apply it as an "Authorization": "Basic" header. + +See https://docs.github.com/rest/#unauthenticated-rate-limited-requests for +more information. +*/ +type UnauthenticatedRateLimitedTransport struct { + // ClientID is the GitHub OAuth client ID of the current application, which + // can be found by selecting its entry in the list at + // https://github.com/settings/applications. + ClientID string + + // ClientSecret is the GitHub OAuth client secret of the current + // application. + ClientSecret string + + // Transport is the underlying HTTP transport to use when making requests. + // It will default to http.DefaultTransport if nil. + Transport http.RoundTripper +} + +// RoundTrip implements the RoundTripper interface. +func (t *UnauthenticatedRateLimitedTransport) RoundTrip(req *http.Request) (*http.Response, error) { + if t.ClientID == "" { + return nil, errors.New("t.ClientID is empty") + } + if t.ClientSecret == "" { + return nil, errors.New("t.ClientSecret is empty") + } + + req2 := setCredentialsAsHeaders(req, t.ClientID, t.ClientSecret) + // Make the HTTP request. + return t.transport().RoundTrip(req2) +} + +// Client returns an *http.Client that makes requests which are subject to the +// rate limit of your OAuth application. +func (t *UnauthenticatedRateLimitedTransport) Client() *http.Client { + return &http.Client{Transport: t} +} + +func (t *UnauthenticatedRateLimitedTransport) transport() http.RoundTripper { + if t.Transport != nil { + return t.Transport + } + return http.DefaultTransport +} + +// BasicAuthTransport is an http.RoundTripper that authenticates all requests +// using HTTP Basic Authentication with the provided username and password. It +// additionally supports users who have two-factor authentication enabled on +// their GitHub account. +type BasicAuthTransport struct { + Username string // GitHub username + Password string // GitHub password + OTP string // one-time password for users with two-factor auth enabled + + // Transport is the underlying HTTP transport to use when making requests. + // It will default to http.DefaultTransport if nil. + Transport http.RoundTripper +} + +// RoundTrip implements the RoundTripper interface. +func (t *BasicAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) { + req2 := setCredentialsAsHeaders(req, t.Username, t.Password) + if t.OTP != "" { + req2.Header.Set(headerOTP, t.OTP) + } + return t.transport().RoundTrip(req2) +} + +// Client returns an *http.Client that makes requests that are authenticated +// using HTTP Basic Authentication. +func (t *BasicAuthTransport) Client() *http.Client { + return &http.Client{Transport: t} +} + +func (t *BasicAuthTransport) transport() http.RoundTripper { + if t.Transport != nil { + return t.Transport + } + return http.DefaultTransport +} + +// formatRateReset formats d to look like "[rate reset in 2s]" or +// "[rate reset in 87m02s]" for the positive durations. And like "[rate limit was reset 87m02s ago]" +// for the negative cases. +func formatRateReset(d time.Duration) string { + isNegative := d < 0 + if isNegative { + d *= -1 + } + secondsTotal := int(0.5 + d.Seconds()) + minutes := secondsTotal / 60 + seconds := secondsTotal - minutes*60 + + var timeString string + if minutes > 0 { + timeString = fmt.Sprintf("%dm%02ds", minutes, seconds) + } else { + timeString = fmt.Sprintf("%ds", seconds) + } + + if isNegative { + return fmt.Sprintf("[rate limit was reset %v ago]", timeString) + } + return fmt.Sprintf("[rate reset in %v]", timeString) +} + +func sleepUntilResetWithBuffer(ctx context.Context, reset time.Time) error { + buffer := time.Second + timer := time.NewTimer(time.Until(reset) + buffer) + select { + case <-ctx.Done(): + if !timer.Stop() { + <-timer.C + } + return ctx.Err() + case <-timer.C: + } + return nil +} + +// When using roundTripWithOptionalFollowRedirect, note that it +// is the responsibility of the caller to close the response body. +func (c *Client) roundTripWithOptionalFollowRedirect(ctx context.Context, u string, maxRedirects int, opts ...RequestOption) (*http.Response, error) { + req, err := c.NewRequest("GET", u, nil, opts...) + if err != nil { + return nil, err + } + + var resp *http.Response + // Use http.DefaultTransport if no custom Transport is configured + req = withContext(ctx, req) + if c.client.Transport == nil { + resp, err = http.DefaultTransport.RoundTrip(req) + } else { + resp, err = c.client.Transport.RoundTrip(req) + } + if err != nil { + return nil, err + } + + // If redirect response is returned, follow it + if maxRedirects > 0 && resp.StatusCode == http.StatusMovedPermanently { + _ = resp.Body.Close() + u = resp.Header.Get("Location") + resp, err = c.roundTripWithOptionalFollowRedirect(ctx, u, maxRedirects-1, opts...) + } + return resp, err +} + +// Ptr is a helper routine that allocates a new T value +// to store v and returns a pointer to it. +func Ptr[T any](v T) *T { + return &v +} + +// Bool is a helper routine that allocates a new bool value +// to store v and returns a pointer to it. +// +// Deprecated: use Ptr instead. +func Bool(v bool) *bool { return &v } + +// Int is a helper routine that allocates a new int value +// to store v and returns a pointer to it. +// +// Deprecated: use Ptr instead. +func Int(v int) *int { return &v } + +// Int64 is a helper routine that allocates a new int64 value +// to store v and returns a pointer to it. +// +// Deprecated: use Ptr instead. +func Int64(v int64) *int64 { return &v } + +// String is a helper routine that allocates a new string value +// to store v and returns a pointer to it. +// +// Deprecated: use Ptr instead. +func String(v string) *string { return &v } + +// roundTripperFunc creates a RoundTripper (transport). +type roundTripperFunc func(*http.Request) (*http.Response, error) + +func (fn roundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) { + return fn(r) +} diff --git a/vendor/github.com/google/go-github/v68/github/gitignore.go b/vendor/github.com/google/go-github/v68/github/gitignore.go new file mode 100644 index 0000000000..34cf285e14 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/gitignore.go @@ -0,0 +1,68 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GitignoresService provides access to the gitignore related functions in the +// GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/gitignore/ +type GitignoresService service + +// Gitignore represents a .gitignore file as returned by the GitHub API. +type Gitignore struct { + Name *string `json:"name,omitempty"` + Source *string `json:"source,omitempty"` +} + +func (g Gitignore) String() string { + return Stringify(g) +} + +// List all available Gitignore templates. +// +// GitHub API docs: https://docs.github.com/rest/gitignore/gitignore#get-all-gitignore-templates +// +//meta:operation GET /gitignore/templates +func (s *GitignoresService) List(ctx context.Context) ([]string, *Response, error) { + req, err := s.client.NewRequest("GET", "gitignore/templates", nil) + if err != nil { + return nil, nil, err + } + + var availableTemplates []string + resp, err := s.client.Do(ctx, req, &availableTemplates) + if err != nil { + return nil, resp, err + } + + return availableTemplates, resp, nil +} + +// Get a Gitignore by name. +// +// GitHub API docs: https://docs.github.com/rest/gitignore/gitignore#get-a-gitignore-template +// +//meta:operation GET /gitignore/templates/{name} +func (s *GitignoresService) Get(ctx context.Context, name string) (*Gitignore, *Response, error) { + u := fmt.Sprintf("gitignore/templates/%v", name) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + gitignore := new(Gitignore) + resp, err := s.client.Do(ctx, req, gitignore) + if err != nil { + return nil, resp, err + } + + return gitignore, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/interactions.go b/vendor/github.com/google/go-github/v68/github/interactions.go new file mode 100644 index 0000000000..2268273dd4 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/interactions.go @@ -0,0 +1,28 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +// InteractionsService handles communication with the repository and organization related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/interactions/ +type InteractionsService service + +// InteractionRestriction represents the interaction restrictions for repository and organization. +type InteractionRestriction struct { + // Specifies the group of GitHub users who can + // comment, open issues, or create pull requests for the given repository. + // Possible values are: "existing_users", "contributors_only" and "collaborators_only". + Limit *string `json:"limit,omitempty"` + + // Origin specifies the type of the resource to interact with. + // Possible values are: "repository" and "organization". + Origin *string `json:"origin,omitempty"` + + // ExpiresAt specifies the time after which the interaction restrictions expire. + // The default expiry time is 24 hours from the time restriction is created. + ExpiresAt *Timestamp `json:"expires_at,omitempty"` +} diff --git a/vendor/github.com/google/go-github/v68/github/interactions_orgs.go b/vendor/github.com/google/go-github/v68/github/interactions_orgs.go new file mode 100644 index 0000000000..47998c4eef --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/interactions_orgs.go @@ -0,0 +1,86 @@ +// Copyright 2019 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetRestrictionsForOrg fetches the interaction restrictions for an organization. +// +// GitHub API docs: https://docs.github.com/rest/interactions/orgs#get-interaction-restrictions-for-an-organization +// +//meta:operation GET /orgs/{org}/interaction-limits +func (s *InteractionsService) GetRestrictionsForOrg(ctx context.Context, organization string) (*InteractionRestriction, *Response, error) { + u := fmt.Sprintf("orgs/%v/interaction-limits", organization) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) + + organizationInteractions := new(InteractionRestriction) + + resp, err := s.client.Do(ctx, req, organizationInteractions) + if err != nil { + return nil, resp, err + } + + return organizationInteractions, resp, nil +} + +// UpdateRestrictionsForOrg adds or updates the interaction restrictions for an organization. +// +// limit specifies the group of GitHub users who can comment, open issues, or create pull requests +// in public repositories for the given organization. +// Possible values are: "existing_users", "contributors_only", "collaborators_only". +// +// GitHub API docs: https://docs.github.com/rest/interactions/orgs#set-interaction-restrictions-for-an-organization +// +//meta:operation PUT /orgs/{org}/interaction-limits +func (s *InteractionsService) UpdateRestrictionsForOrg(ctx context.Context, organization, limit string) (*InteractionRestriction, *Response, error) { + u := fmt.Sprintf("orgs/%v/interaction-limits", organization) + + interaction := &InteractionRestriction{Limit: Ptr(limit)} + + req, err := s.client.NewRequest("PUT", u, interaction) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) + + organizationInteractions := new(InteractionRestriction) + + resp, err := s.client.Do(ctx, req, organizationInteractions) + if err != nil { + return nil, resp, err + } + + return organizationInteractions, resp, nil +} + +// RemoveRestrictionsFromOrg removes the interaction restrictions for an organization. +// +// GitHub API docs: https://docs.github.com/rest/interactions/orgs#remove-interaction-restrictions-for-an-organization +// +//meta:operation DELETE /orgs/{org}/interaction-limits +func (s *InteractionsService) RemoveRestrictionsFromOrg(ctx context.Context, organization string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/interaction-limits", organization) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/interactions_repos.go b/vendor/github.com/google/go-github/v68/github/interactions_repos.go new file mode 100644 index 0000000000..58fd4f04f3 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/interactions_repos.go @@ -0,0 +1,86 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetRestrictionsForRepo fetches the interaction restrictions for a repository. +// +// GitHub API docs: https://docs.github.com/rest/interactions/repos#get-interaction-restrictions-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/interaction-limits +func (s *InteractionsService) GetRestrictionsForRepo(ctx context.Context, owner, repo string) (*InteractionRestriction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/interaction-limits", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) + + repositoryInteractions := new(InteractionRestriction) + + resp, err := s.client.Do(ctx, req, repositoryInteractions) + if err != nil { + return nil, resp, err + } + + return repositoryInteractions, resp, nil +} + +// UpdateRestrictionsForRepo adds or updates the interaction restrictions for a repository. +// +// limit specifies the group of GitHub users who can comment, open issues, or create pull requests +// for the given repository. +// Possible values are: "existing_users", "contributors_only", "collaborators_only". +// +// GitHub API docs: https://docs.github.com/rest/interactions/repos#set-interaction-restrictions-for-a-repository +// +//meta:operation PUT /repos/{owner}/{repo}/interaction-limits +func (s *InteractionsService) UpdateRestrictionsForRepo(ctx context.Context, owner, repo, limit string) (*InteractionRestriction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/interaction-limits", owner, repo) + + interaction := &InteractionRestriction{Limit: Ptr(limit)} + + req, err := s.client.NewRequest("PUT", u, interaction) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) + + repositoryInteractions := new(InteractionRestriction) + + resp, err := s.client.Do(ctx, req, repositoryInteractions) + if err != nil { + return nil, resp, err + } + + return repositoryInteractions, resp, nil +} + +// RemoveRestrictionsFromRepo removes the interaction restrictions for a repository. +// +// GitHub API docs: https://docs.github.com/rest/interactions/repos#remove-interaction-restrictions-for-a-repository +// +//meta:operation DELETE /repos/{owner}/{repo}/interaction-limits +func (s *InteractionsService) RemoveRestrictionsFromRepo(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/interaction-limits", owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/issue_import.go b/vendor/github.com/google/go-github/v68/github/issue_import.go new file mode 100644 index 0000000000..4f06371085 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/issue_import.go @@ -0,0 +1,154 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "context" + "encoding/json" + "fmt" +) + +// IssueImportService handles communication with the issue import related +// methods of the Issue Import GitHub API. +type IssueImportService service + +// IssueImportRequest represents a request to create an issue. +// +// https://gist.github.com/jonmagic/5282384165e0f86ef105#supported-issue-and-comment-fields +type IssueImportRequest struct { + IssueImport IssueImport `json:"issue"` + Comments []*Comment `json:"comments,omitempty"` +} + +// IssueImport represents body of issue to import. +type IssueImport struct { + Title string `json:"title"` + Body string `json:"body"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + ClosedAt *Timestamp `json:"closed_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Assignee *string `json:"assignee,omitempty"` + Milestone *int `json:"milestone,omitempty"` + Closed *bool `json:"closed,omitempty"` + Labels []string `json:"labels,omitempty"` +} + +// Comment represents comments of issue to import. +type Comment struct { + CreatedAt *Timestamp `json:"created_at,omitempty"` + Body string `json:"body"` +} + +// IssueImportResponse represents the response of an issue import create request. +// +// https://gist.github.com/jonmagic/5282384165e0f86ef105#import-issue-response +type IssueImportResponse struct { + ID *int `json:"id,omitempty"` + Status *string `json:"status,omitempty"` + URL *string `json:"url,omitempty"` + ImportIssuesURL *string `json:"import_issues_url,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Message *string `json:"message,omitempty"` + DocumentationURL *string `json:"documentation_url,omitempty"` + Errors []*IssueImportError `json:"errors,omitempty"` +} + +// IssueImportError represents errors of an issue import create request. +type IssueImportError struct { + Location *string `json:"location,omitempty"` + Resource *string `json:"resource,omitempty"` + Field *string `json:"field,omitempty"` + Value *string `json:"value,omitempty"` + Code *string `json:"code,omitempty"` +} + +// Create a new imported issue on the specified repository. +// +// GitHub API docs: https://gist.github.com/jonmagic/5282384165e0f86ef105#start-an-issue-import +// +//meta:operation POST /repos/{owner}/{repo}/import/issues +func (s *IssueImportService) Create(ctx context.Context, owner, repo string, issue *IssueImportRequest) (*IssueImportResponse, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import/issues", owner, repo) + req, err := s.client.NewRequest("POST", u, issue) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeIssueImportAPI) + + i := new(IssueImportResponse) + resp, err := s.client.Do(ctx, req, i) + if err != nil { + aerr, ok := err.(*AcceptedError) + if ok { + if err := json.Unmarshal(aerr.Raw, i); err != nil { + return i, resp, err + } + return i, resp, err + } + return nil, resp, err + } + + return i, resp, nil +} + +// CheckStatus checks the status of an imported issue. +// +// GitHub API docs: https://gist.github.com/jonmagic/5282384165e0f86ef105#import-status-request +// +//meta:operation GET /repos/{owner}/{repo}/import/issues/{issue_number} +func (s *IssueImportService) CheckStatus(ctx context.Context, owner, repo string, issueID int64) (*IssueImportResponse, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import/issues/%v", owner, repo, issueID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeIssueImportAPI) + + i := new(IssueImportResponse) + resp, err := s.client.Do(ctx, req, i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} + +// CheckStatusSince checks the status of multiple imported issues since a given date. +// +// GitHub API docs: https://gist.github.com/jonmagic/5282384165e0f86ef105#check-status-of-multiple-issues +// +//meta:operation GET /repos/{owner}/{repo}/import/issues +func (s *IssueImportService) CheckStatusSince(ctx context.Context, owner, repo string, since Timestamp) ([]*IssueImportResponse, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import/issues?since=%v", owner, repo, since.Format("2006-01-02")) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeIssueImportAPI) + + var b bytes.Buffer + resp, err := s.client.Do(ctx, req, &b) + if err != nil { + return nil, resp, err + } + + var i []*IssueImportResponse + err = json.Unmarshal(b.Bytes(), &i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/issues.go b/vendor/github.com/google/go-github/v68/github/issues.go new file mode 100644 index 0000000000..a2652b3497 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/issues.go @@ -0,0 +1,383 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// IssuesService handles communication with the issue related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/issues/ +type IssuesService service + +// Issue represents a GitHub issue on a repository. +// +// Note: As far as the GitHub API is concerned, every pull request is an issue, +// but not every issue is a pull request. Some endpoints, events, and webhooks +// may also return pull requests via this struct. If PullRequestLinks is nil, +// this is an issue, and if PullRequestLinks is not nil, this is a pull request. +// The IsPullRequest helper method can be used to check that. +type Issue struct { + ID *int64 `json:"id,omitempty"` + Number *int `json:"number,omitempty"` + State *string `json:"state,omitempty"` + // StateReason can be one of: "completed", "not_planned", "reopened". + StateReason *string `json:"state_reason,omitempty"` + Locked *bool `json:"locked,omitempty"` + Title *string `json:"title,omitempty"` + Body *string `json:"body,omitempty"` + AuthorAssociation *string `json:"author_association,omitempty"` + User *User `json:"user,omitempty"` + Labels []*Label `json:"labels,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Comments *int `json:"comments,omitempty"` + ClosedAt *Timestamp `json:"closed_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + ClosedBy *User `json:"closed_by,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + EventsURL *string `json:"events_url,omitempty"` + LabelsURL *string `json:"labels_url,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` + Milestone *Milestone `json:"milestone,omitempty"` + PullRequestLinks *PullRequestLinks `json:"pull_request,omitempty"` + Repository *Repository `json:"repository,omitempty"` + Reactions *Reactions `json:"reactions,omitempty"` + Assignees []*User `json:"assignees,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Draft *bool `json:"draft,omitempty"` + + // TextMatches is only populated from search results that request text matches + // See: search.go and https://docs.github.com/rest/search/#text-match-metadata + TextMatches []*TextMatch `json:"text_matches,omitempty"` + + // ActiveLockReason is populated only when LockReason is provided while locking the issue. + // Possible values are: "off-topic", "too heated", "resolved", and "spam". + ActiveLockReason *string `json:"active_lock_reason,omitempty"` +} + +func (i Issue) String() string { + return Stringify(i) +} + +// IsPullRequest reports whether the issue is also a pull request. It uses the +// method recommended by GitHub's API documentation, which is to check whether +// PullRequestLinks is non-nil. +func (i Issue) IsPullRequest() bool { + return i.PullRequestLinks != nil +} + +// IssueRequest represents a request to create/edit an issue. +// It is separate from Issue above because otherwise Labels +// and Assignee fail to serialize to the correct JSON. +type IssueRequest struct { + Title *string `json:"title,omitempty"` + Body *string `json:"body,omitempty"` + Labels *[]string `json:"labels,omitempty"` + Assignee *string `json:"assignee,omitempty"` + State *string `json:"state,omitempty"` + // StateReason can be 'completed' or 'not_planned'. + StateReason *string `json:"state_reason,omitempty"` + Milestone *int `json:"milestone,omitempty"` + Assignees *[]string `json:"assignees,omitempty"` +} + +// IssueListOptions specifies the optional parameters to the IssuesService.List +// and IssuesService.ListByOrg methods. +type IssueListOptions struct { + // Filter specifies which issues to list. Possible values are: assigned, + // created, mentioned, subscribed, all. Default is "assigned". + Filter string `url:"filter,omitempty"` + + // State filters issues based on their state. Possible values are: open, + // closed, all. Default is "open". + State string `url:"state,omitempty"` + + // Labels filters issues based on their label. + Labels []string `url:"labels,comma,omitempty"` + + // Sort specifies how to sort issues. Possible values are: created, updated, + // and comments. Default value is "created". + Sort string `url:"sort,omitempty"` + + // Direction in which to sort issues. Possible values are: asc, desc. + // Default is "desc". + Direction string `url:"direction,omitempty"` + + // Since filters issues by time. + Since time.Time `url:"since,omitempty"` + + ListOptions +} + +// PullRequestLinks object is added to the Issue object when it's an issue included +// in the IssueCommentEvent webhook payload, if the webhook is fired by a comment on a PR. +type PullRequestLinks struct { + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + DiffURL *string `json:"diff_url,omitempty"` + PatchURL *string `json:"patch_url,omitempty"` + MergedAt *Timestamp `json:"merged_at,omitempty"` +} + +// List the issues for the authenticated user. If all is true, list issues +// across all the user's visible repositories including owned, member, and +// organization repositories; if false, list only owned and member +// repositories. +// +// GitHub API docs: https://docs.github.com/rest/issues/issues#list-issues-assigned-to-the-authenticated-user +// GitHub API docs: https://docs.github.com/rest/issues/issues#list-user-account-issues-assigned-to-the-authenticated-user +// +//meta:operation GET /issues +//meta:operation GET /user/issues +func (s *IssuesService) List(ctx context.Context, all bool, opts *IssueListOptions) ([]*Issue, *Response, error) { + var u string + if all { + u = "issues" + } else { + u = "user/issues" + } + return s.listIssues(ctx, u, opts) +} + +// ListByOrg fetches the issues in the specified organization for the +// authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/issues/issues#list-organization-issues-assigned-to-the-authenticated-user +// +//meta:operation GET /orgs/{org}/issues +func (s *IssuesService) ListByOrg(ctx context.Context, org string, opts *IssueListOptions) ([]*Issue, *Response, error) { + u := fmt.Sprintf("orgs/%v/issues", org) + return s.listIssues(ctx, u, opts) +} + +func (s *IssuesService) listIssues(ctx context.Context, u string, opts *IssueListOptions) ([]*Issue, *Response, error) { + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var issues []*Issue + resp, err := s.client.Do(ctx, req, &issues) + if err != nil { + return nil, resp, err + } + + return issues, resp, nil +} + +// IssueListByRepoOptions specifies the optional parameters to the +// IssuesService.ListByRepo method. +type IssueListByRepoOptions struct { + // Milestone limits issues for the specified milestone. Possible values are + // a milestone number, "none" for issues with no milestone, "*" for issues + // with any milestone. + Milestone string `url:"milestone,omitempty"` + + // State filters issues based on their state. Possible values are: open, + // closed, all. Default is "open". + State string `url:"state,omitempty"` + + // Assignee filters issues based on their assignee. Possible values are a + // user name, "none" for issues that are not assigned, "*" for issues with + // any assigned user. + Assignee string `url:"assignee,omitempty"` + + // Creator filters issues based on their creator. + Creator string `url:"creator,omitempty"` + + // Mentioned filters issues to those mentioned a specific user. + Mentioned string `url:"mentioned,omitempty"` + + // Labels filters issues based on their label. + Labels []string `url:"labels,omitempty,comma"` + + // Sort specifies how to sort issues. Possible values are: created, updated, + // and comments. Default value is "created". + Sort string `url:"sort,omitempty"` + + // Direction in which to sort issues. Possible values are: asc, desc. + // Default is "desc". + Direction string `url:"direction,omitempty"` + + // Since filters issues by time. + Since time.Time `url:"since,omitempty"` + + ListOptions +} + +// ListByRepo lists the issues for the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/issues/issues#list-repository-issues +// +//meta:operation GET /repos/{owner}/{repo}/issues +func (s *IssuesService) ListByRepo(ctx context.Context, owner string, repo string, opts *IssueListByRepoOptions) ([]*Issue, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var issues []*Issue + resp, err := s.client.Do(ctx, req, &issues) + if err != nil { + return nil, resp, err + } + + return issues, resp, nil +} + +// Get a single issue. +// +// GitHub API docs: https://docs.github.com/rest/issues/issues#get-an-issue +// +//meta:operation GET /repos/{owner}/{repo}/issues/{issue_number} +func (s *IssuesService) Get(ctx context.Context, owner string, repo string, number int) (*Issue, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + issue := new(Issue) + resp, err := s.client.Do(ctx, req, issue) + if err != nil { + return nil, resp, err + } + + return issue, resp, nil +} + +// Create a new issue on the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/issues/issues#create-an-issue +// +//meta:operation POST /repos/{owner}/{repo}/issues +func (s *IssuesService) Create(ctx context.Context, owner string, repo string, issue *IssueRequest) (*Issue, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues", owner, repo) + req, err := s.client.NewRequest("POST", u, issue) + if err != nil { + return nil, nil, err + } + + i := new(Issue) + resp, err := s.client.Do(ctx, req, i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} + +// Edit (update) an issue. +// +// GitHub API docs: https://docs.github.com/rest/issues/issues#update-an-issue +// +//meta:operation PATCH /repos/{owner}/{repo}/issues/{issue_number} +func (s *IssuesService) Edit(ctx context.Context, owner string, repo string, number int, issue *IssueRequest) (*Issue, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number) + req, err := s.client.NewRequest("PATCH", u, issue) + if err != nil { + return nil, nil, err + } + + i := new(Issue) + resp, err := s.client.Do(ctx, req, i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} + +// RemoveMilestone removes a milestone from an issue. +// +// This is a helper method to explicitly update an issue with a `null` milestone, thereby removing it. +// +// GitHub API docs: https://docs.github.com/rest/issues/issues#update-an-issue +// +//meta:operation PATCH /repos/{owner}/{repo}/issues/{issue_number} +func (s *IssuesService) RemoveMilestone(ctx context.Context, owner, repo string, issueNumber int) (*Issue, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%v", owner, repo, issueNumber) + req, err := s.client.NewRequest("PATCH", u, &struct { + Milestone *Milestone `json:"milestone"` + }{}) + if err != nil { + return nil, nil, err + } + + i := new(Issue) + resp, err := s.client.Do(ctx, req, i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} + +// LockIssueOptions specifies the optional parameters to the +// IssuesService.Lock method. +type LockIssueOptions struct { + // LockReason specifies the reason to lock this issue. + // Providing a lock reason can help make it clearer to contributors why an issue + // was locked. Possible values are: "off-topic", "too heated", "resolved", and "spam". + LockReason string `json:"lock_reason,omitempty"` +} + +// Lock an issue's conversation. +// +// GitHub API docs: https://docs.github.com/rest/issues/issues#lock-an-issue +// +//meta:operation PUT /repos/{owner}/{repo}/issues/{issue_number}/lock +func (s *IssuesService) Lock(ctx context.Context, owner string, repo string, number int, opts *LockIssueOptions) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/lock", owner, repo, number) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Unlock an issue's conversation. +// +// GitHub API docs: https://docs.github.com/rest/issues/issues#unlock-an-issue +// +//meta:operation DELETE /repos/{owner}/{repo}/issues/{issue_number}/lock +func (s *IssuesService) Unlock(ctx context.Context, owner string, repo string, number int) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/lock", owner, repo, number) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/issues_assignees.go b/vendor/github.com/google/go-github/v68/github/issues_assignees.go new file mode 100644 index 0000000000..fd065771ed --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/issues_assignees.go @@ -0,0 +1,103 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListAssignees fetches all available assignees (owners and collaborators) to +// which issues may be assigned. +// +// GitHub API docs: https://docs.github.com/rest/issues/assignees#list-assignees +// +//meta:operation GET /repos/{owner}/{repo}/assignees +func (s *IssuesService) ListAssignees(ctx context.Context, owner, repo string, opts *ListOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/assignees", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var assignees []*User + resp, err := s.client.Do(ctx, req, &assignees) + if err != nil { + return nil, resp, err + } + + return assignees, resp, nil +} + +// IsAssignee checks if a user is an assignee for the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/issues/assignees#check-if-a-user-can-be-assigned +// +//meta:operation GET /repos/{owner}/{repo}/assignees/{assignee} +func (s *IssuesService) IsAssignee(ctx context.Context, owner, repo, user string) (bool, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/assignees/%v", owner, repo, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + assignee, err := parseBoolResponse(err) + return assignee, resp, err +} + +// AddAssignees adds the provided GitHub users as assignees to the issue. +// +// GitHub API docs: https://docs.github.com/rest/issues/assignees#add-assignees-to-an-issue +// +//meta:operation POST /repos/{owner}/{repo}/issues/{issue_number}/assignees +func (s *IssuesService) AddAssignees(ctx context.Context, owner, repo string, number int, assignees []string) (*Issue, *Response, error) { + users := &struct { + Assignees []string `json:"assignees,omitempty"` + }{Assignees: assignees} + u := fmt.Sprintf("repos/%v/%v/issues/%v/assignees", owner, repo, number) + req, err := s.client.NewRequest("POST", u, users) + if err != nil { + return nil, nil, err + } + + issue := &Issue{} + resp, err := s.client.Do(ctx, req, issue) + if err != nil { + return nil, resp, err + } + + return issue, resp, nil +} + +// RemoveAssignees removes the provided GitHub users as assignees from the issue. +// +// GitHub API docs: https://docs.github.com/rest/issues/assignees#remove-assignees-from-an-issue +// +//meta:operation DELETE /repos/{owner}/{repo}/issues/{issue_number}/assignees +func (s *IssuesService) RemoveAssignees(ctx context.Context, owner, repo string, number int, assignees []string) (*Issue, *Response, error) { + users := &struct { + Assignees []string `json:"assignees,omitempty"` + }{Assignees: assignees} + u := fmt.Sprintf("repos/%v/%v/issues/%v/assignees", owner, repo, number) + req, err := s.client.NewRequest("DELETE", u, users) + if err != nil { + return nil, nil, err + } + + issue := &Issue{} + resp, err := s.client.Do(ctx, req, issue) + if err != nil { + return nil, resp, err + } + + return issue, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/issues_comments.go b/vendor/github.com/google/go-github/v68/github/issues_comments.go new file mode 100644 index 0000000000..74a4e60f7c --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/issues_comments.go @@ -0,0 +1,165 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// IssueComment represents a comment left on an issue. +type IssueComment struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Body *string `json:"body,omitempty"` + User *User `json:"user,omitempty"` + Reactions *Reactions `json:"reactions,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + // AuthorAssociation is the comment author's relationship to the issue's repository. + // Possible values are "COLLABORATOR", "CONTRIBUTOR", "FIRST_TIMER", "FIRST_TIME_CONTRIBUTOR", "MEMBER", "OWNER", or "NONE". + AuthorAssociation *string `json:"author_association,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + IssueURL *string `json:"issue_url,omitempty"` +} + +func (i IssueComment) String() string { + return Stringify(i) +} + +// IssueListCommentsOptions specifies the optional parameters to the +// IssuesService.ListComments method. +type IssueListCommentsOptions struct { + // Sort specifies how to sort comments. Possible values are: created, updated. + Sort *string `url:"sort,omitempty"` + + // Direction in which to sort comments. Possible values are: asc, desc. + Direction *string `url:"direction,omitempty"` + + // Since filters comments by time. + Since *time.Time `url:"since,omitempty"` + + ListOptions +} + +// ListComments lists all comments on the specified issue. Specifying an issue +// number of 0 will return all comments on all issues for the repository. +// +// GitHub API docs: https://docs.github.com/rest/issues/comments#list-issue-comments +// GitHub API docs: https://docs.github.com/rest/issues/comments#list-issue-comments-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/issues/comments +//meta:operation GET /repos/{owner}/{repo}/issues/{issue_number}/comments +func (s *IssuesService) ListComments(ctx context.Context, owner string, repo string, number int, opts *IssueListCommentsOptions) ([]*IssueComment, *Response, error) { + var u string + if number == 0 { + u = fmt.Sprintf("repos/%v/%v/issues/comments", owner, repo) + } else { + u = fmt.Sprintf("repos/%v/%v/issues/%d/comments", owner, repo, number) + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var comments []*IssueComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// GetComment fetches the specified issue comment. +// +// GitHub API docs: https://docs.github.com/rest/issues/comments#get-an-issue-comment +// +//meta:operation GET /repos/{owner}/{repo}/issues/comments/{comment_id} +func (s *IssuesService) GetComment(ctx context.Context, owner string, repo string, commentID int64) (*IssueComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + comment := new(IssueComment) + resp, err := s.client.Do(ctx, req, comment) + if err != nil { + return nil, resp, err + } + + return comment, resp, nil +} + +// CreateComment creates a new comment on the specified issue. +// +// GitHub API docs: https://docs.github.com/rest/issues/comments#create-an-issue-comment +// +//meta:operation POST /repos/{owner}/{repo}/issues/{issue_number}/comments +func (s *IssuesService) CreateComment(ctx context.Context, owner string, repo string, number int, comment *IssueComment) (*IssueComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/comments", owner, repo, number) + req, err := s.client.NewRequest("POST", u, comment) + if err != nil { + return nil, nil, err + } + c := new(IssueComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// EditComment updates an issue comment. +// A non-nil comment.Body must be provided. Other comment fields should be left nil. +// +// GitHub API docs: https://docs.github.com/rest/issues/comments#update-an-issue-comment +// +//meta:operation PATCH /repos/{owner}/{repo}/issues/comments/{comment_id} +func (s *IssuesService) EditComment(ctx context.Context, owner string, repo string, commentID int64, comment *IssueComment) (*IssueComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID) + req, err := s.client.NewRequest("PATCH", u, comment) + if err != nil { + return nil, nil, err + } + c := new(IssueComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// DeleteComment deletes an issue comment. +// +// GitHub API docs: https://docs.github.com/rest/issues/comments#delete-an-issue-comment +// +//meta:operation DELETE /repos/{owner}/{repo}/issues/comments/{comment_id} +func (s *IssuesService) DeleteComment(ctx context.Context, owner string, repo string, commentID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/issues_events.go b/vendor/github.com/google/go-github/v68/github/issues_events.go new file mode 100644 index 0000000000..8e234d7e02 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/issues_events.go @@ -0,0 +1,189 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// IssueEvent represents an event that occurred around an Issue or Pull Request. +type IssueEvent struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + + // The User that generated this event. + Actor *User `json:"actor,omitempty"` + + // The action corresponding to the event. + Action string `json:"action,omitempty"` + + // Event identifies the actual type of Event that occurred. Possible + // values are: + // + // closed + // The Actor closed the issue. + // If the issue was closed by commit message, CommitID holds the SHA1 hash of the commit. + // + // merged + // The Actor merged into master a branch containing a commit mentioning the issue. + // CommitID holds the SHA1 of the merge commit. + // + // referenced + // The Actor committed to master a commit mentioning the issue in its commit message. + // CommitID holds the SHA1 of the commit. + // + // reopened, unlocked + // The Actor did that to the issue. + // + // locked + // The Actor locked the issue. + // LockReason holds the reason of locking the issue (if provided while locking). + // + // renamed + // The Actor changed the issue title from Rename.From to Rename.To. + // + // mentioned + // Someone unspecified @mentioned the Actor [sic] in an issue comment body. + // + // assigned, unassigned + // The Assigner assigned the issue to or removed the assignment from the Assignee. + // + // labeled, unlabeled + // The Actor added or removed the Label from the issue. + // + // milestoned, demilestoned + // The Actor added or removed the issue from the Milestone. + // + // subscribed, unsubscribed + // The Actor subscribed to or unsubscribed from notifications for an issue. + // + // head_ref_deleted, head_ref_restored + // The pull request’s branch was deleted or restored. + // + // review_dismissed + // The review was dismissed and `DismissedReview` will be populated below. + // + // review_requested, review_request_removed + // The Actor requested or removed the request for a review. + // RequestedReviewer or RequestedTeam, and ReviewRequester will be populated below. + // + Event *string `json:"event,omitempty"` + + CreatedAt *Timestamp `json:"created_at,omitempty"` + Issue *Issue `json:"issue,omitempty"` + + // Only present on certain events; see above. + Repository *Repository `json:"repository,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Assigner *User `json:"assigner,omitempty"` + CommitID *string `json:"commit_id,omitempty"` + Milestone *Milestone `json:"milestone,omitempty"` + Label *Label `json:"label,omitempty"` + Rename *Rename `json:"rename,omitempty"` + LockReason *string `json:"lock_reason,omitempty"` + DismissedReview *DismissedReview `json:"dismissed_review,omitempty"` + RequestedReviewer *User `json:"requested_reviewer,omitempty"` + RequestedTeam *Team `json:"requested_team,omitempty"` + ReviewRequester *User `json:"review_requester,omitempty"` + PerformedViaGithubApp *App `json:"performed_via_github_app,omitempty"` +} + +// DismissedReview represents details for 'dismissed_review' events. +type DismissedReview struct { + // State represents the state of the dismissed review. + // Possible values are: "commented", "approved", and "changes_requested". + State *string `json:"state,omitempty"` + ReviewID *int64 `json:"review_id,omitempty"` + DismissalMessage *string `json:"dismissal_message,omitempty"` + DismissalCommitID *string `json:"dismissal_commit_id,omitempty"` +} + +// ListIssueEvents lists events for the specified issue. +// +// GitHub API docs: https://docs.github.com/rest/issues/events#list-issue-events +// +//meta:operation GET /repos/{owner}/{repo}/issues/{issue_number}/events +func (s *IssuesService) ListIssueEvents(ctx context.Context, owner, repo string, number int, opts *ListOptions) ([]*IssueEvent, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%v/events", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeProjectCardDetailsPreview) + + var events []*IssueEvent + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListRepositoryEvents lists events for the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/issues/events#list-issue-events-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/issues/events +func (s *IssuesService) ListRepositoryEvents(ctx context.Context, owner, repo string, opts *ListOptions) ([]*IssueEvent, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/events", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*IssueEvent + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// GetEvent returns the specified issue event. +// +// GitHub API docs: https://docs.github.com/rest/issues/events#get-an-issue-event +// +//meta:operation GET /repos/{owner}/{repo}/issues/events/{event_id} +func (s *IssuesService) GetEvent(ctx context.Context, owner, repo string, id int64) (*IssueEvent, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/events/%v", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + event := new(IssueEvent) + resp, err := s.client.Do(ctx, req, event) + if err != nil { + return nil, resp, err + } + + return event, resp, nil +} + +// Rename contains details for 'renamed' events. +type Rename struct { + From *string `json:"from,omitempty"` + To *string `json:"to,omitempty"` +} + +func (r Rename) String() string { + return Stringify(r) +} diff --git a/vendor/github.com/google/go-github/v68/github/issues_labels.go b/vendor/github.com/google/go-github/v68/github/issues_labels.go new file mode 100644 index 0000000000..b97b00f3e8 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/issues_labels.go @@ -0,0 +1,253 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Label represents a GitHub label on an Issue. +type Label struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + Name *string `json:"name,omitempty"` + Color *string `json:"color,omitempty"` + Description *string `json:"description,omitempty"` + Default *bool `json:"default,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +func (l Label) String() string { + return Stringify(l) +} + +// ListLabels lists all labels for a repository. +// +// GitHub API docs: https://docs.github.com/rest/issues/labels#list-labels-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/labels +func (s *IssuesService) ListLabels(ctx context.Context, owner string, repo string, opts *ListOptions) ([]*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/labels", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var labels []*Label + resp, err := s.client.Do(ctx, req, &labels) + if err != nil { + return nil, resp, err + } + + return labels, resp, nil +} + +// GetLabel gets a single label. +// +// GitHub API docs: https://docs.github.com/rest/issues/labels#get-a-label +// +//meta:operation GET /repos/{owner}/{repo}/labels/{name} +func (s *IssuesService) GetLabel(ctx context.Context, owner string, repo string, name string) (*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + label := new(Label) + resp, err := s.client.Do(ctx, req, label) + if err != nil { + return nil, resp, err + } + + return label, resp, nil +} + +// CreateLabel creates a new label on the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/issues/labels#create-a-label +// +//meta:operation POST /repos/{owner}/{repo}/labels +func (s *IssuesService) CreateLabel(ctx context.Context, owner string, repo string, label *Label) (*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/labels", owner, repo) + req, err := s.client.NewRequest("POST", u, label) + if err != nil { + return nil, nil, err + } + + l := new(Label) + resp, err := s.client.Do(ctx, req, l) + if err != nil { + return nil, resp, err + } + + return l, resp, nil +} + +// EditLabel edits a label. +// +// GitHub API docs: https://docs.github.com/rest/issues/labels#update-a-label +// +//meta:operation PATCH /repos/{owner}/{repo}/labels/{name} +func (s *IssuesService) EditLabel(ctx context.Context, owner string, repo string, name string, label *Label) (*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name) + req, err := s.client.NewRequest("PATCH", u, label) + if err != nil { + return nil, nil, err + } + + l := new(Label) + resp, err := s.client.Do(ctx, req, l) + if err != nil { + return nil, resp, err + } + + return l, resp, nil +} + +// DeleteLabel deletes a label. +// +// GitHub API docs: https://docs.github.com/rest/issues/labels#delete-a-label +// +//meta:operation DELETE /repos/{owner}/{repo}/labels/{name} +func (s *IssuesService) DeleteLabel(ctx context.Context, owner string, repo string, name string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// ListLabelsByIssue lists all labels for an issue. +// +// GitHub API docs: https://docs.github.com/rest/issues/labels#list-labels-for-an-issue +// +//meta:operation GET /repos/{owner}/{repo}/issues/{issue_number}/labels +func (s *IssuesService) ListLabelsByIssue(ctx context.Context, owner string, repo string, number int, opts *ListOptions) ([]*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var labels []*Label + resp, err := s.client.Do(ctx, req, &labels) + if err != nil { + return nil, resp, err + } + + return labels, resp, nil +} + +// AddLabelsToIssue adds labels to an issue. +// +// GitHub API docs: https://docs.github.com/rest/issues/labels#add-labels-to-an-issue +// +//meta:operation POST /repos/{owner}/{repo}/issues/{issue_number}/labels +func (s *IssuesService) AddLabelsToIssue(ctx context.Context, owner string, repo string, number int, labels []string) ([]*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number) + req, err := s.client.NewRequest("POST", u, labels) + if err != nil { + return nil, nil, err + } + + var l []*Label + resp, err := s.client.Do(ctx, req, &l) + if err != nil { + return nil, resp, err + } + + return l, resp, nil +} + +// RemoveLabelForIssue removes a label for an issue. +// +// GitHub API docs: https://docs.github.com/rest/issues/labels#remove-a-label-from-an-issue +// +//meta:operation DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels/{name} +func (s *IssuesService) RemoveLabelForIssue(ctx context.Context, owner string, repo string, number int, label string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/labels/%v", owner, repo, number, label) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ReplaceLabelsForIssue replaces all labels for an issue. +// +// GitHub API docs: https://docs.github.com/rest/issues/labels#set-labels-for-an-issue +// +//meta:operation PUT /repos/{owner}/{repo}/issues/{issue_number}/labels +func (s *IssuesService) ReplaceLabelsForIssue(ctx context.Context, owner string, repo string, number int, labels []string) ([]*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number) + req, err := s.client.NewRequest("PUT", u, labels) + if err != nil { + return nil, nil, err + } + + var l []*Label + resp, err := s.client.Do(ctx, req, &l) + if err != nil { + return nil, resp, err + } + + return l, resp, nil +} + +// RemoveLabelsForIssue removes all labels for an issue. +// +// GitHub API docs: https://docs.github.com/rest/issues/labels#remove-all-labels-from-an-issue +// +//meta:operation DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels +func (s *IssuesService) RemoveLabelsForIssue(ctx context.Context, owner string, repo string, number int) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListLabelsForMilestone lists labels for every issue in a milestone. +// +// GitHub API docs: https://docs.github.com/rest/issues/labels#list-labels-for-issues-in-a-milestone +// +//meta:operation GET /repos/{owner}/{repo}/milestones/{milestone_number}/labels +func (s *IssuesService) ListLabelsForMilestone(ctx context.Context, owner string, repo string, number int, opts *ListOptions) ([]*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/milestones/%d/labels", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var labels []*Label + resp, err := s.client.Do(ctx, req, &labels) + if err != nil { + return nil, resp, err + } + + return labels, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/issues_milestones.go b/vendor/github.com/google/go-github/v68/github/issues_milestones.go new file mode 100644 index 0000000000..6c31bcd054 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/issues_milestones.go @@ -0,0 +1,157 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Milestone represents a GitHub repository milestone. +type Milestone struct { + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + LabelsURL *string `json:"labels_url,omitempty"` + ID *int64 `json:"id,omitempty"` + Number *int `json:"number,omitempty"` + State *string `json:"state,omitempty"` + Title *string `json:"title,omitempty"` + Description *string `json:"description,omitempty"` + Creator *User `json:"creator,omitempty"` + OpenIssues *int `json:"open_issues,omitempty"` + ClosedIssues *int `json:"closed_issues,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + ClosedAt *Timestamp `json:"closed_at,omitempty"` + DueOn *Timestamp `json:"due_on,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +func (m Milestone) String() string { + return Stringify(m) +} + +// MilestoneListOptions specifies the optional parameters to the +// IssuesService.ListMilestones method. +type MilestoneListOptions struct { + // State filters milestones based on their state. Possible values are: + // open, closed, all. Default is "open". + State string `url:"state,omitempty"` + + // Sort specifies how to sort milestones. Possible values are: due_on, completeness. + // Default value is "due_on". + Sort string `url:"sort,omitempty"` + + // Direction in which to sort milestones. Possible values are: asc, desc. + // Default is "asc". + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// ListMilestones lists all milestones for a repository. +// +// GitHub API docs: https://docs.github.com/rest/issues/milestones#list-milestones +// +//meta:operation GET /repos/{owner}/{repo}/milestones +func (s *IssuesService) ListMilestones(ctx context.Context, owner string, repo string, opts *MilestoneListOptions) ([]*Milestone, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/milestones", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var milestones []*Milestone + resp, err := s.client.Do(ctx, req, &milestones) + if err != nil { + return nil, resp, err + } + + return milestones, resp, nil +} + +// GetMilestone gets a single milestone. +// +// GitHub API docs: https://docs.github.com/rest/issues/milestones#get-a-milestone +// +//meta:operation GET /repos/{owner}/{repo}/milestones/{milestone_number} +func (s *IssuesService) GetMilestone(ctx context.Context, owner string, repo string, number int) (*Milestone, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + milestone := new(Milestone) + resp, err := s.client.Do(ctx, req, milestone) + if err != nil { + return nil, resp, err + } + + return milestone, resp, nil +} + +// CreateMilestone creates a new milestone on the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/issues/milestones#create-a-milestone +// +//meta:operation POST /repos/{owner}/{repo}/milestones +func (s *IssuesService) CreateMilestone(ctx context.Context, owner string, repo string, milestone *Milestone) (*Milestone, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/milestones", owner, repo) + req, err := s.client.NewRequest("POST", u, milestone) + if err != nil { + return nil, nil, err + } + + m := new(Milestone) + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// EditMilestone edits a milestone. +// +// GitHub API docs: https://docs.github.com/rest/issues/milestones#update-a-milestone +// +//meta:operation PATCH /repos/{owner}/{repo}/milestones/{milestone_number} +func (s *IssuesService) EditMilestone(ctx context.Context, owner string, repo string, number int, milestone *Milestone) (*Milestone, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number) + req, err := s.client.NewRequest("PATCH", u, milestone) + if err != nil { + return nil, nil, err + } + + m := new(Milestone) + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeleteMilestone deletes a milestone. +// +// GitHub API docs: https://docs.github.com/rest/issues/milestones#delete-a-milestone +// +//meta:operation DELETE /repos/{owner}/{repo}/milestones/{milestone_number} +func (s *IssuesService) DeleteMilestone(ctx context.Context, owner string, repo string, number int) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/issues_timeline.go b/vendor/github.com/google/go-github/v68/github/issues_timeline.go new file mode 100644 index 0000000000..903f5b89c3 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/issues_timeline.go @@ -0,0 +1,202 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "strings" +) + +// Timeline represents an event that occurred around an Issue or Pull Request. +// +// It is similar to an IssueEvent but may contain more information. +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/events/issue-event-types +type Timeline struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + CommitURL *string `json:"commit_url,omitempty"` + + // The User object that generated the event. + Actor *User `json:"actor,omitempty"` + + // The person who commented on the issue. + User *User `json:"user,omitempty"` + + // The person who authored the commit. + Author *CommitAuthor `json:"author,omitempty"` + // The person who committed the commit on behalf of the author. + Committer *CommitAuthor `json:"committer,omitempty"` + // The SHA of the commit in the pull request. + SHA *string `json:"sha,omitempty"` + // The commit message. + Message *string `json:"message,omitempty"` + // A list of parent commits. + Parents []*Commit `json:"parents,omitempty"` + + // Event identifies the actual type of Event that occurred. Possible values + // are: + // + // assigned + // The issue was assigned to the assignee. + // + // closed + // The issue was closed by the actor. When the commit_id is present, it + // identifies the commit that closed the issue using "closes / fixes #NN" + // syntax. + // + // commented + // A comment was added to the issue. + // + // committed + // A commit was added to the pull request's 'HEAD' branch. Only provided + // for pull requests. + // + // cross-referenced + // The issue was referenced from another issue. The 'source' attribute + // contains the 'id', 'actor', and 'url' of the reference's source. + // + // demilestoned + // The issue was removed from a milestone. + // + // head_ref_deleted + // The pull request's branch was deleted. + // + // head_ref_restored + // The pull request's branch was restored. + // + // labeled + // A label was added to the issue. + // + // locked + // The issue was locked by the actor. + // + // mentioned + // The actor was @mentioned in an issue body. + // + // merged + // The issue was merged by the actor. The 'commit_id' attribute is the + // SHA1 of the HEAD commit that was merged. + // + // milestoned + // The issue was added to a milestone. + // + // referenced + // The issue was referenced from a commit message. The 'commit_id' + // attribute is the commit SHA1 of where that happened. + // + // renamed + // The issue title was changed. + // + // reopened + // The issue was reopened by the actor. + // + // reviewed + // The pull request was reviewed. + // + // review_requested + // The actor requested a review from a user or team. + // Reviewer and Requester/RequestedTeam will be populated. + // + // review_request_removed + // The actor removed a review request from a user or team. + // Reviewer and Requester/RequestedTeam will be populated. + // + // subscribed + // The actor subscribed to receive notifications for an issue. + // + // unassigned + // The assignee was unassigned from the issue. + // + // unlabeled + // A label was removed from the issue. + // + // unlocked + // The issue was unlocked by the actor. + // + // unsubscribed + // The actor unsubscribed to stop receiving notifications for an issue. + // + Event *string `json:"event,omitempty"` + + // The string SHA of a commit that referenced this Issue or Pull Request. + CommitID *string `json:"commit_id,omitempty"` + // The timestamp indicating when the event occurred. + CreatedAt *Timestamp `json:"created_at,omitempty"` + // The Label object including `name` and `color` attributes. Only provided for + // 'labeled' and 'unlabeled' events. + Label *Label `json:"label,omitempty"` + // The User object which was assigned to (or unassigned from) this Issue or + // Pull Request. Only provided for 'assigned' and 'unassigned' events. + Assignee *User `json:"assignee,omitempty"` + Assigner *User `json:"assigner,omitempty"` + + // The Milestone object including a 'title' attribute. + // Only provided for 'milestoned' and 'demilestoned' events. + Milestone *Milestone `json:"milestone,omitempty"` + // The 'id', 'actor', and 'url' for the source of a reference from another issue. + // Only provided for 'cross-referenced' events. + Source *Source `json:"source,omitempty"` + // An object containing rename details including 'from' and 'to' attributes. + // Only provided for 'renamed' events. + Rename *Rename `json:"rename,omitempty"` + // The state of a submitted review. Can be one of: 'commented', + // 'changes_requested' or 'approved'. + // Only provided for 'reviewed' events. + State *string `json:"state,omitempty"` + + // The person requested to review the pull request. + Reviewer *User `json:"requested_reviewer,omitempty"` + // RequestedTeam contains the team requested to review the pull request. + RequestedTeam *Team `json:"requested_team,omitempty"` + // The person who requested a review. + Requester *User `json:"review_requester,omitempty"` + + // The review summary text. + Body *string `json:"body,omitempty"` + SubmittedAt *Timestamp `json:"submitted_at,omitempty"` + + PerformedViaGithubApp *App `json:"performed_via_github_app,omitempty"` +} + +// Source represents a reference's source. +type Source struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + Actor *User `json:"actor,omitempty"` + Type *string `json:"type,omitempty"` + Issue *Issue `json:"issue,omitempty"` +} + +// ListIssueTimeline lists events for the specified issue. +// +// GitHub API docs: https://docs.github.com/rest/issues/timeline#list-timeline-events-for-an-issue +// +//meta:operation GET /repos/{owner}/{repo}/issues/{issue_number}/timeline +func (s *IssuesService) ListIssueTimeline(ctx context.Context, owner, repo string, number int, opts *ListOptions) ([]*Timeline, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%v/timeline", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeTimelinePreview, mediaTypeProjectCardDetailsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var events []*Timeline + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/licenses.go b/vendor/github.com/google/go-github/v68/github/licenses.go new file mode 100644 index 0000000000..34b8a3d8af --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/licenses.go @@ -0,0 +1,101 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// LicensesService handles communication with the license related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/licenses/ +type LicensesService service + +// RepositoryLicense represents the license for a repository. +type RepositoryLicense struct { + Name *string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` + + SHA *string `json:"sha,omitempty"` + Size *int `json:"size,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + GitURL *string `json:"git_url,omitempty"` + DownloadURL *string `json:"download_url,omitempty"` + Type *string `json:"type,omitempty"` + Content *string `json:"content,omitempty"` + Encoding *string `json:"encoding,omitempty"` + License *License `json:"license,omitempty"` +} + +func (l RepositoryLicense) String() string { + return Stringify(l) +} + +// License represents an open source license. +type License struct { + Key *string `json:"key,omitempty"` + Name *string `json:"name,omitempty"` + URL *string `json:"url,omitempty"` + + SPDXID *string `json:"spdx_id,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + Featured *bool `json:"featured,omitempty"` + Description *string `json:"description,omitempty"` + Implementation *string `json:"implementation,omitempty"` + Permissions *[]string `json:"permissions,omitempty"` + Conditions *[]string `json:"conditions,omitempty"` + Limitations *[]string `json:"limitations,omitempty"` + Body *string `json:"body,omitempty"` +} + +func (l License) String() string { + return Stringify(l) +} + +// List popular open source licenses. +// +// GitHub API docs: https://docs.github.com/rest/licenses/licenses#get-all-commonly-used-licenses +// +//meta:operation GET /licenses +func (s *LicensesService) List(ctx context.Context) ([]*License, *Response, error) { + req, err := s.client.NewRequest("GET", "licenses", nil) + if err != nil { + return nil, nil, err + } + + var licenses []*License + resp, err := s.client.Do(ctx, req, &licenses) + if err != nil { + return nil, resp, err + } + + return licenses, resp, nil +} + +// Get extended metadata for one license. +// +// GitHub API docs: https://docs.github.com/rest/licenses/licenses#get-a-license +// +//meta:operation GET /licenses/{license} +func (s *LicensesService) Get(ctx context.Context, licenseName string) (*License, *Response, error) { + u := fmt.Sprintf("licenses/%s", licenseName) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + license := new(License) + resp, err := s.client.Do(ctx, req, license) + if err != nil { + return nil, resp, err + } + + return license, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/markdown.go b/vendor/github.com/google/go-github/v68/github/markdown.go new file mode 100644 index 0000000000..0fd896c6c8 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/markdown.go @@ -0,0 +1,69 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "context" +) + +// MarkdownService provides access to markdown-related functions in the GitHub API. +type MarkdownService service + +// MarkdownOptions specifies optional parameters to the Render method. +type MarkdownOptions struct { + // Mode identifies the rendering mode. Possible values are: + // markdown - render a document as plain Render, just like + // README files are rendered. + // + // gfm - to render a document as user-content, e.g. like user + // comments or issues are rendered. In GFM mode, hard line breaks are + // always taken into account, and issue and user mentions are linked + // accordingly. + // + // Default is "markdown". + Mode string + + // Context identifies the repository context. Only taken into account + // when rendering as "gfm". + Context string +} + +type markdownRenderRequest struct { + Text *string `json:"text,omitempty"` + Mode *string `json:"mode,omitempty"` + Context *string `json:"context,omitempty"` +} + +// Render renders an arbitrary Render document. +// +// GitHub API docs: https://docs.github.com/rest/markdown/markdown#render-a-markdown-document +// +//meta:operation POST /markdown +func (s *MarkdownService) Render(ctx context.Context, text string, opts *MarkdownOptions) (string, *Response, error) { + request := &markdownRenderRequest{Text: Ptr(text)} + if opts != nil { + if opts.Mode != "" { + request.Mode = Ptr(opts.Mode) + } + if opts.Context != "" { + request.Context = Ptr(opts.Context) + } + } + + req, err := s.client.NewRequest("POST", "markdown", request) + if err != nil { + return "", nil, err + } + + buf := new(bytes.Buffer) + resp, err := s.client.Do(ctx, req, buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/messages.go b/vendor/github.com/google/go-github/v68/github/messages.go new file mode 100644 index 0000000000..59b214b355 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/messages.go @@ -0,0 +1,356 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file provides functions for validating payloads from GitHub Webhooks. +// GitHub API docs: https://developer.github.com/webhooks/securing/#validating-payloads-from-github + +package github + +import ( + "crypto/hmac" + "crypto/sha1" + "crypto/sha256" + "crypto/sha512" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "hash" + "io" + "mime" + "net/http" + "net/url" + "reflect" + "sort" + "strings" +) + +const ( + // sha1Prefix is the prefix used by GitHub before the HMAC hexdigest. + sha1Prefix = "sha1" + // sha256Prefix and sha512Prefix are provided for future compatibility. + sha256Prefix = "sha256" + sha512Prefix = "sha512" + // SHA1SignatureHeader is the GitHub header key used to pass the HMAC-SHA1 hexdigest. + SHA1SignatureHeader = "X-Hub-Signature" + // SHA256SignatureHeader is the GitHub header key used to pass the HMAC-SHA256 hexdigest. + SHA256SignatureHeader = "X-Hub-Signature-256" + // EventTypeHeader is the GitHub header key used to pass the event type. + EventTypeHeader = "X-Github-Event" + // DeliveryIDHeader is the GitHub header key used to pass the unique ID for the webhook event. + DeliveryIDHeader = "X-Github-Delivery" +) + +var ( + // eventTypeMapping maps webhooks types to their corresponding go-github struct types. + eventTypeMapping = map[string]interface{}{ + "branch_protection_configuration": &BranchProtectionConfigurationEvent{}, + "branch_protection_rule": &BranchProtectionRuleEvent{}, + "check_run": &CheckRunEvent{}, + "check_suite": &CheckSuiteEvent{}, + "code_scanning_alert": &CodeScanningAlertEvent{}, + "commit_comment": &CommitCommentEvent{}, + "content_reference": &ContentReferenceEvent{}, + "create": &CreateEvent{}, + "custom_property": &CustomPropertyEvent{}, + "custom_property_values": &CustomPropertyValuesEvent{}, + "delete": &DeleteEvent{}, + "dependabot_alert": &DependabotAlertEvent{}, + "deploy_key": &DeployKeyEvent{}, + "deployment": &DeploymentEvent{}, + "deployment_review": &DeploymentReviewEvent{}, + "deployment_status": &DeploymentStatusEvent{}, + "deployment_protection_rule": &DeploymentProtectionRuleEvent{}, + "discussion": &DiscussionEvent{}, + "discussion_comment": &DiscussionCommentEvent{}, + "fork": &ForkEvent{}, + "github_app_authorization": &GitHubAppAuthorizationEvent{}, + "gollum": &GollumEvent{}, + "installation": &InstallationEvent{}, + "installation_repositories": &InstallationRepositoriesEvent{}, + "installation_target": &InstallationTargetEvent{}, + "issue_comment": &IssueCommentEvent{}, + "issues": &IssuesEvent{}, + "label": &LabelEvent{}, + "marketplace_purchase": &MarketplacePurchaseEvent{}, + "member": &MemberEvent{}, + "membership": &MembershipEvent{}, + "merge_group": &MergeGroupEvent{}, + "meta": &MetaEvent{}, + "milestone": &MilestoneEvent{}, + "organization": &OrganizationEvent{}, + "org_block": &OrgBlockEvent{}, + "package": &PackageEvent{}, + "page_build": &PageBuildEvent{}, + "personal_access_token_request": &PersonalAccessTokenRequestEvent{}, + "ping": &PingEvent{}, + "projects_v2": &ProjectV2Event{}, + "projects_v2_item": &ProjectV2ItemEvent{}, + "public": &PublicEvent{}, + "pull_request": &PullRequestEvent{}, + "pull_request_review": &PullRequestReviewEvent{}, + "pull_request_review_comment": &PullRequestReviewCommentEvent{}, + "pull_request_review_thread": &PullRequestReviewThreadEvent{}, + "pull_request_target": &PullRequestTargetEvent{}, + "push": &PushEvent{}, + "repository": &RepositoryEvent{}, + "repository_dispatch": &RepositoryDispatchEvent{}, + "repository_import": &RepositoryImportEvent{}, + "repository_ruleset": &RepositoryRulesetEvent{}, + "repository_vulnerability_alert": &RepositoryVulnerabilityAlertEvent{}, + "release": &ReleaseEvent{}, + "secret_scanning_alert": &SecretScanningAlertEvent{}, + "secret_scanning_alert_location": &SecretScanningAlertLocationEvent{}, + "security_advisory": &SecurityAdvisoryEvent{}, + "security_and_analysis": &SecurityAndAnalysisEvent{}, + "sponsorship": &SponsorshipEvent{}, + "star": &StarEvent{}, + "status": &StatusEvent{}, + "team": &TeamEvent{}, + "team_add": &TeamAddEvent{}, + "user": &UserEvent{}, + "watch": &WatchEvent{}, + "workflow_dispatch": &WorkflowDispatchEvent{}, + "workflow_job": &WorkflowJobEvent{}, + "workflow_run": &WorkflowRunEvent{}, + } + // Forward mapping of event types to the string names of the structs. + messageToTypeName = make(map[string]string, len(eventTypeMapping)) + // Inverse map of the above. + typeToMessageMapping = make(map[string]string, len(eventTypeMapping)) +) + +func init() { + for k, v := range eventTypeMapping { + typename := reflect.TypeOf(v).Elem().Name() + messageToTypeName[k] = typename + typeToMessageMapping[typename] = k + } +} + +// genMAC generates the HMAC signature for a message provided the secret key +// and hashFunc. +func genMAC(message, key []byte, hashFunc func() hash.Hash) []byte { + mac := hmac.New(hashFunc, key) + mac.Write(message) + return mac.Sum(nil) +} + +// checkMAC reports whether messageMAC is a valid HMAC tag for message. +func checkMAC(message, messageMAC, key []byte, hashFunc func() hash.Hash) bool { + expectedMAC := genMAC(message, key, hashFunc) + return hmac.Equal(messageMAC, expectedMAC) +} + +// messageMAC returns the hex-decoded HMAC tag from the signature and its +// corresponding hash function. +func messageMAC(signature string) ([]byte, func() hash.Hash, error) { + if signature == "" { + return nil, nil, errors.New("missing signature") + } + sigParts := strings.SplitN(signature, "=", 2) + if len(sigParts) != 2 { + return nil, nil, fmt.Errorf("error parsing signature %q", signature) + } + + var hashFunc func() hash.Hash + switch sigParts[0] { + case sha1Prefix: + hashFunc = sha1.New + case sha256Prefix: + hashFunc = sha256.New + case sha512Prefix: + hashFunc = sha512.New + default: + return nil, nil, fmt.Errorf("unknown hash type prefix: %q", sigParts[0]) + } + + buf, err := hex.DecodeString(sigParts[1]) + if err != nil { + return nil, nil, fmt.Errorf("error decoding signature %q: %v", signature, err) + } + return buf, hashFunc, nil +} + +// ValidatePayloadFromBody validates an incoming GitHub Webhook event request body +// and returns the (JSON) payload. +// The Content-Type header of the payload can be "application/json" or "application/x-www-form-urlencoded". +// If the Content-Type is neither then an error is returned. +// secretToken is the GitHub Webhook secret token. +// If your webhook does not contain a secret token, you can pass an empty secretToken. +// Webhooks without a secret token are not secure and should be avoided. +// +// Example usage: +// +// func (s *GitHubEventMonitor) ServeHTTP(w http.ResponseWriter, r *http.Request) { +// // read signature from request +// signature := "" +// payload, err := github.ValidatePayloadFromBody(r.Header.Get("Content-Type"), r.Body, signature, s.webhookSecretKey) +// if err != nil { ... } +// // Process payload... +// } +func ValidatePayloadFromBody(contentType string, readable io.Reader, signature string, secretToken []byte) (payload []byte, err error) { + var body []byte // Raw body that GitHub uses to calculate the signature. + + switch contentType { + case "application/json": + var err error + if body, err = io.ReadAll(readable); err != nil { + return nil, err + } + + // If the content type is application/json, + // the JSON payload is just the original body. + payload = body + + case "application/x-www-form-urlencoded": + // payloadFormParam is the name of the form parameter that the JSON payload + // will be in if a webhook has its content type set to application/x-www-form-urlencoded. + const payloadFormParam = "payload" + + var err error + if body, err = io.ReadAll(readable); err != nil { + return nil, err + } + + // If the content type is application/x-www-form-urlencoded, + // the JSON payload will be under the "payload" form param. + form, err := url.ParseQuery(string(body)) + if err != nil { + return nil, err + } + payload = []byte(form.Get(payloadFormParam)) + + default: + return nil, fmt.Errorf("webhook request has unsupported Content-Type %q", contentType) + } + + // Validate the signature if present or if one is expected (secretToken is non-empty). + if len(secretToken) > 0 || len(signature) > 0 { + if err := ValidateSignature(signature, body, secretToken); err != nil { + return nil, err + } + } + + return payload, nil +} + +// ValidatePayload validates an incoming GitHub Webhook event request +// and returns the (JSON) payload. +// The Content-Type header of the payload can be "application/json" or "application/x-www-form-urlencoded". +// If the Content-Type is neither then an error is returned. +// secretToken is the GitHub Webhook secret token. +// If your webhook does not contain a secret token, you can pass nil or an empty slice. +// This is intended for local development purposes only and all webhooks should ideally set up a secret token. +// +// Example usage: +// +// func (s *GitHubEventMonitor) ServeHTTP(w http.ResponseWriter, r *http.Request) { +// payload, err := github.ValidatePayload(r, s.webhookSecretKey) +// if err != nil { ... } +// // Process payload... +// } +func ValidatePayload(r *http.Request, secretToken []byte) (payload []byte, err error) { + signature := r.Header.Get(SHA256SignatureHeader) + if signature == "" { + signature = r.Header.Get(SHA1SignatureHeader) + } + + contentType, _, err := mime.ParseMediaType(r.Header.Get("Content-Type")) + if err != nil { + return nil, err + } + + return ValidatePayloadFromBody(contentType, r.Body, signature, secretToken) +} + +// ValidateSignature validates the signature for the given payload. +// signature is the GitHub hash signature delivered in the X-Hub-Signature header. +// payload is the JSON payload sent by GitHub Webhooks. +// secretToken is the GitHub Webhook secret token. +// +// GitHub API docs: https://developer.github.com/webhooks/securing/#validating-payloads-from-github +func ValidateSignature(signature string, payload, secretToken []byte) error { + messageMAC, hashFunc, err := messageMAC(signature) + if err != nil { + return err + } + if !checkMAC(payload, messageMAC, secretToken, hashFunc) { + return errors.New("payload signature check failed") + } + return nil +} + +// WebHookType returns the event type of webhook request r. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/events/github-event-types +func WebHookType(r *http.Request) string { + return r.Header.Get(EventTypeHeader) +} + +// DeliveryID returns the unique delivery ID of webhook request r. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/events/github-event-types +func DeliveryID(r *http.Request) string { + return r.Header.Get(DeliveryIDHeader) +} + +// ParseWebHook parses the event payload. For recognized event types, a +// value of the corresponding struct type will be returned (as returned +// by Event.ParsePayload()). An error will be returned for unrecognized event +// types. +// +// Example usage: +// +// func (s *GitHubEventMonitor) ServeHTTP(w http.ResponseWriter, r *http.Request) { +// payload, err := github.ValidatePayload(r, s.webhookSecretKey) +// if err != nil { ... } +// event, err := github.ParseWebHook(github.WebHookType(r), payload) +// if err != nil { ... } +// switch event := event.(type) { +// case *github.CommitCommentEvent: +// processCommitCommentEvent(event) +// case *github.CreateEvent: +// processCreateEvent(event) +// ... +// } +// } +func ParseWebHook(messageType string, payload []byte) (interface{}, error) { + eventType, ok := messageToTypeName[messageType] + if !ok { + return nil, fmt.Errorf("unknown X-Github-Event in message: %v", messageType) + } + + event := Event{ + Type: &eventType, + RawPayload: (*json.RawMessage)(&payload), + } + return event.ParsePayload() +} + +// MessageTypes returns a sorted list of all the known GitHub event type strings +// supported by go-github. +func MessageTypes() []string { + types := make([]string, 0, len(eventTypeMapping)) + for t := range eventTypeMapping { + types = append(types, t) + } + sort.Strings(types) + return types +} + +// EventForType returns an empty struct matching the specified GitHub event type. +// If messageType does not match any known event types, it returns nil. +func EventForType(messageType string) interface{} { + prototype := eventTypeMapping[messageType] + if prototype == nil { + return nil + } + // return a _copy_ of the pointed-to-object. Unfortunately, for this we + // need to use reflection. If we store the actual objects in the map, + // we still need to use reflection to convert from `any` to the actual + // type, so this was deemed the lesser of two evils. (#2865) + return reflect.New(reflect.TypeOf(prototype).Elem()).Interface() +} diff --git a/vendor/github.com/google/go-github/v68/github/meta.go b/vendor/github.com/google/go-github/v68/github/meta.go new file mode 100644 index 0000000000..cc90b618b1 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/meta.go @@ -0,0 +1,184 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "context" + "fmt" + "net/url" +) + +// MetaService provides access to functions in the GitHub API that GitHub categorizes as "meta". +type MetaService service + +// APIMeta represents metadata about the GitHub API. +type APIMeta struct { + // An array of IP addresses in CIDR format specifying the addresses + // that incoming service hooks will originate from on GitHub.com. + Hooks []string `json:"hooks,omitempty"` + + // An array of IP addresses in CIDR format specifying the Git servers + // for GitHub.com. + Git []string `json:"git,omitempty"` + + // Whether authentication with username and password is supported. + // (GitHub Enterprise instances using CAS or OAuth for authentication + // will return false. Features like Basic Authentication with a + // username and password, sudo mode, and two-factor authentication are + // not supported on these servers.) + VerifiablePasswordAuthentication *bool `json:"verifiable_password_authentication,omitempty"` + + // An array of IP addresses in CIDR format specifying the addresses + // which serve GitHub Packages. + Packages []string `json:"packages,omitempty"` + + // An array of IP addresses in CIDR format specifying the addresses + // which serve GitHub Pages websites. + Pages []string `json:"pages,omitempty"` + + // An array of IP addresses specifying the addresses that source imports + // will originate from on GitHub.com. + Importer []string `json:"importer,omitempty"` + + // An array of IP addresses specifying the addresses that source imports + // will originate from on GitHub Enterprise Cloud. + GithubEnterpriseImporter []string `json:"github_enterprise_importer,omitempty"` + + // An array of IP addresses in CIDR format specifying the IP addresses + // GitHub Actions will originate from. + Actions []string `json:"actions,omitempty"` + + // An array of IP addresses in CIDR format specifying the IP addresses + // Dependabot will originate from. + Dependabot []string `json:"dependabot,omitempty"` + + // A map of algorithms to SSH key fingerprints. + SSHKeyFingerprints map[string]string `json:"ssh_key_fingerprints,omitempty"` + + // An array of SSH keys. + SSHKeys []string `json:"ssh_keys,omitempty"` + + // An array of IP addresses in CIDR format specifying the addresses + // which serve GitHub websites. + Web []string `json:"web,omitempty"` + + // An array of IP addresses in CIDR format specifying the addresses + // which serve GitHub APIs. + API []string `json:"api,omitempty"` + + // GitHub services and their associated domains. Note that many of these domains + // are represented as wildcards (e.g. "*.github.com"). + Domains *APIMetaDomains `json:"domains,omitempty"` +} + +// APIMetaDomains represents the domains associated with GitHub services. +type APIMetaDomains struct { + Website []string `json:"website,omitempty"` + Codespaces []string `json:"codespaces,omitempty"` + Copilot []string `json:"copilot,omitempty"` + Packages []string `json:"packages,omitempty"` + Actions []string `json:"actions,omitempty"` + ArtifactAttestations *APIMetaArtifactAttestations `json:"artifact_attestations,omitempty"` +} + +// APIMetaArtifactAttestations represents the artifact attestation services domains. +type APIMetaArtifactAttestations struct { + TrustDomain string `json:"trust_domain,omitempty"` + Services []string `json:"services,omitempty"` +} + +// Get returns information about GitHub.com, the service. Or, if you access +// this endpoint on your organization’s GitHub Enterprise installation, this +// endpoint provides information about that installation. +// +// GitHub API docs: https://docs.github.com/rest/meta/meta#get-github-meta-information +// +//meta:operation GET /meta +func (s *MetaService) Get(ctx context.Context) (*APIMeta, *Response, error) { + req, err := s.client.NewRequest("GET", "meta", nil) + if err != nil { + return nil, nil, err + } + + meta := new(APIMeta) + resp, err := s.client.Do(ctx, req, meta) + if err != nil { + return nil, resp, err + } + + return meta, resp, nil +} + +// APIMeta returns information about GitHub.com. +// +// Deprecated: Use MetaService.Get instead. +func (c *Client) APIMeta(ctx context.Context) (*APIMeta, *Response, error) { + return c.Meta.Get(ctx) +} + +// Octocat returns an ASCII art octocat with the specified message in a speech +// bubble. If message is empty, a random zen phrase is used. +// +// GitHub API docs: https://docs.github.com/rest/meta/meta#get-octocat +// +//meta:operation GET /octocat +func (s *MetaService) Octocat(ctx context.Context, message string) (string, *Response, error) { + u := "octocat" + if message != "" { + u = fmt.Sprintf("%s?s=%s", u, url.QueryEscape(message)) + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return "", nil, err + } + + buf := new(bytes.Buffer) + resp, err := s.client.Do(ctx, req, buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// Octocat returns an ASCII art octocat with the specified message in a speech +// bubble. If message is empty, a random zen phrase is used. +// +// Deprecated: Use MetaService.Octocat instead. +func (c *Client) Octocat(ctx context.Context, message string) (string, *Response, error) { + return c.Meta.Octocat(ctx, message) +} + +// Zen returns a random line from The Zen of GitHub. +// +// See also: http://warpspire.com/posts/taste/ +// +// GitHub API docs: https://docs.github.com/rest/meta/meta#get-the-zen-of-github +// +//meta:operation GET /zen +func (s *MetaService) Zen(ctx context.Context) (string, *Response, error) { + req, err := s.client.NewRequest("GET", "zen", nil) + if err != nil { + return "", nil, err + } + + buf := new(bytes.Buffer) + resp, err := s.client.Do(ctx, req, buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// Zen returns a random line from The Zen of GitHub. +// +// Deprecated: Use MetaService.Zen instead. +func (c *Client) Zen(ctx context.Context) (string, *Response, error) { + return c.Meta.Zen(ctx) +} diff --git a/vendor/github.com/google/go-github/v68/github/migrations.go b/vendor/github.com/google/go-github/v68/github/migrations.go new file mode 100644 index 0000000000..766c4c38e1 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/migrations.go @@ -0,0 +1,240 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "errors" + "fmt" + "net/http" + "strings" +) + +// MigrationService provides access to the migration related functions +// in the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/migration/ +type MigrationService service + +// Migration represents a GitHub migration (archival). +type Migration struct { + ID *int64 `json:"id,omitempty"` + GUID *string `json:"guid,omitempty"` + // State is the current state of a migration. + // Possible values are: + // "pending" which means the migration hasn't started yet, + // "exporting" which means the migration is in progress, + // "exported" which means the migration finished successfully, or + // "failed" which means the migration failed. + State *string `json:"state,omitempty"` + // LockRepositories indicates whether repositories are locked (to prevent + // manipulation) while migrating data. + LockRepositories *bool `json:"lock_repositories,omitempty"` + // ExcludeAttachments indicates whether attachments should be excluded from + // the migration (to reduce migration archive file size). + ExcludeAttachments *bool `json:"exclude_attachments,omitempty"` + URL *string `json:"url,omitempty"` + CreatedAt *string `json:"created_at,omitempty"` + UpdatedAt *string `json:"updated_at,omitempty"` + Repositories []*Repository `json:"repositories,omitempty"` +} + +func (m Migration) String() string { + return Stringify(m) +} + +// MigrationOptions specifies the optional parameters to Migration methods. +type MigrationOptions struct { + // LockRepositories indicates whether repositories should be locked (to prevent + // manipulation) while migrating data. + LockRepositories bool + + // ExcludeAttachments indicates whether attachments should be excluded from + // the migration (to reduce migration archive file size). + ExcludeAttachments bool +} + +// startMigration represents the body of a StartMigration request. +type startMigration struct { + // Repositories is a slice of repository names to migrate. + Repositories []string `json:"repositories,omitempty"` + + // LockRepositories indicates whether repositories should be locked (to prevent + // manipulation) while migrating data. + LockRepositories *bool `json:"lock_repositories,omitempty"` + + // ExcludeAttachments indicates whether attachments should be excluded from + // the migration (to reduce migration archive file size). + ExcludeAttachments *bool `json:"exclude_attachments,omitempty"` +} + +// StartMigration starts the generation of a migration archive. +// repos is a slice of repository names to migrate. +// +// GitHub API docs: https://docs.github.com/rest/migrations/orgs#start-an-organization-migration +// +//meta:operation POST /orgs/{org}/migrations +func (s *MigrationService) StartMigration(ctx context.Context, org string, repos []string, opts *MigrationOptions) (*Migration, *Response, error) { + u := fmt.Sprintf("orgs/%v/migrations", org) + + body := &startMigration{Repositories: repos} + if opts != nil { + body.LockRepositories = Ptr(opts.LockRepositories) + body.ExcludeAttachments = Ptr(opts.ExcludeAttachments) + } + + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + m := &Migration{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// ListMigrations lists the most recent migrations. +// +// GitHub API docs: https://docs.github.com/rest/migrations/orgs#list-organization-migrations +// +//meta:operation GET /orgs/{org}/migrations +func (s *MigrationService) ListMigrations(ctx context.Context, org string, opts *ListOptions) ([]*Migration, *Response, error) { + u := fmt.Sprintf("orgs/%v/migrations", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + var m []*Migration + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// MigrationStatus gets the status of a specific migration archive. +// id is the migration ID. +// +// GitHub API docs: https://docs.github.com/rest/migrations/orgs#get-an-organization-migration-status +// +//meta:operation GET /orgs/{org}/migrations/{migration_id} +func (s *MigrationService) MigrationStatus(ctx context.Context, org string, id int64) (*Migration, *Response, error) { + u := fmt.Sprintf("orgs/%v/migrations/%v", org, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + m := &Migration{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// MigrationArchiveURL fetches a migration archive URL. +// id is the migration ID. +// +// GitHub API docs: https://docs.github.com/rest/migrations/orgs#download-an-organization-migration-archive +// +//meta:operation GET /orgs/{org}/migrations/{migration_id}/archive +func (s *MigrationService) MigrationArchiveURL(ctx context.Context, org string, id int64) (url string, err error) { + u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return "", err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + s.client.clientMu.Lock() + defer s.client.clientMu.Unlock() + + // Disable the redirect mechanism because AWS fails if the GitHub auth token is provided. + var loc string + saveRedirect := s.client.client.CheckRedirect + s.client.client.CheckRedirect = func(req *http.Request, via []*http.Request) error { + loc = req.URL.String() + return errors.New("disable redirect") + } + defer func() { s.client.client.CheckRedirect = saveRedirect }() + + _, err = s.client.Do(ctx, req, nil) // expect error from disable redirect + if err == nil { + return "", errors.New("expected redirect, none provided") + } + if !strings.Contains(err.Error(), "disable redirect") { + return "", err + } + return loc, nil +} + +// DeleteMigration deletes a previous migration archive. +// id is the migration ID. +// +// GitHub API docs: https://docs.github.com/rest/migrations/orgs#delete-an-organization-migration-archive +// +//meta:operation DELETE /orgs/{org}/migrations/{migration_id}/archive +func (s *MigrationService) DeleteMigration(ctx context.Context, org string, id int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + return s.client.Do(ctx, req, nil) +} + +// UnlockRepo unlocks a repository that was locked for migration. +// id is the migration ID. +// You should unlock each migrated repository and delete them when the migration +// is complete and you no longer need the source data. +// +// GitHub API docs: https://docs.github.com/rest/migrations/orgs#unlock-an-organization-repository +// +//meta:operation DELETE /orgs/{org}/migrations/{migration_id}/repos/{repo_name}/lock +func (s *MigrationService) UnlockRepo(ctx context.Context, org string, id int64, repo string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/migrations/%v/repos/%v/lock", org, id, repo) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/migrations_source_import.go b/vendor/github.com/google/go-github/v68/github/migrations_source_import.go new file mode 100644 index 0000000000..f484b77d47 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/migrations_source_import.go @@ -0,0 +1,321 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Import represents a repository import request. +type Import struct { + // The URL of the originating repository. + VCSURL *string `json:"vcs_url,omitempty"` + // The originating VCS type. Can be one of 'subversion', 'git', + // 'mercurial', or 'tfvc'. Without this parameter, the import job will + // take additional time to detect the VCS type before beginning the + // import. This detection step will be reflected in the response. + VCS *string `json:"vcs,omitempty"` + // VCSUsername and VCSPassword are only used for StartImport calls that + // are importing a password-protected repository. + VCSUsername *string `json:"vcs_username,omitempty"` + VCSPassword *string `json:"vcs_password,omitempty"` + // For a tfvc import, the name of the project that is being imported. + TFVCProject *string `json:"tfvc_project,omitempty"` + + // LFS related fields that may be preset in the Import Progress response + + // Describes whether the import has been opted in or out of using Git + // LFS. The value can be 'opt_in', 'opt_out', or 'undecided' if no + // action has been taken. + UseLFS *string `json:"use_lfs,omitempty"` + // Describes whether files larger than 100MB were found during the + // importing step. + HasLargeFiles *bool `json:"has_large_files,omitempty"` + // The total size in gigabytes of files larger than 100MB found in the + // originating repository. + LargeFilesSize *int `json:"large_files_size,omitempty"` + // The total number of files larger than 100MB found in the originating + // repository. To see a list of these files, call LargeFiles. + LargeFilesCount *int `json:"large_files_count,omitempty"` + + // Identifies the current status of an import. An import that does not + // have errors will progress through these steps: + // + // detecting - the "detection" step of the import is in progress + // because the request did not include a VCS parameter. The + // import is identifying the type of source control present at + // the URL. + // importing - the "raw" step of the import is in progress. This is + // where commit data is fetched from the original repository. + // The import progress response will include CommitCount (the + // total number of raw commits that will be imported) and + // Percent (0 - 100, the current progress through the import). + // mapping - the "rewrite" step of the import is in progress. This + // is where SVN branches are converted to Git branches, and + // where author updates are applied. The import progress + // response does not include progress information. + // pushing - the "push" step of the import is in progress. This is + // where the importer updates the repository on GitHub. The + // import progress response will include PushPercent, which is + // the percent value reported by git push when it is "Writing + // objects". + // complete - the import is complete, and the repository is ready + // on GitHub. + // + // If there are problems, you will see one of these in the status field: + // + // auth_failed - the import requires authentication in order to + // connect to the original repository. Make an UpdateImport + // request, and include VCSUsername and VCSPassword. + // error - the import encountered an error. The import progress + // response will include the FailedStep and an error message. + // Contact GitHub support for more information. + // detection_needs_auth - the importer requires authentication for + // the originating repository to continue detection. Make an + // UpdateImport request, and include VCSUsername and + // VCSPassword. + // detection_found_nothing - the importer didn't recognize any + // source control at the URL. + // detection_found_multiple - the importer found several projects + // or repositories at the provided URL. When this is the case, + // the Import Progress response will also include a + // ProjectChoices field with the possible project choices as + // values. Make an UpdateImport request, and include VCS and + // (if applicable) TFVCProject. + Status *string `json:"status,omitempty"` + CommitCount *int `json:"commit_count,omitempty"` + StatusText *string `json:"status_text,omitempty"` + AuthorsCount *int `json:"authors_count,omitempty"` + Percent *int `json:"percent,omitempty"` + PushPercent *int `json:"push_percent,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + AuthorsURL *string `json:"authors_url,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` + Message *string `json:"message,omitempty"` + FailedStep *string `json:"failed_step,omitempty"` + + // Human readable display name, provided when the Import appears as + // part of ProjectChoices. + HumanName *string `json:"human_name,omitempty"` + + // When the importer finds several projects or repositories at the + // provided URLs, this will identify the available choices. Call + // UpdateImport with the selected Import value. + ProjectChoices []*Import `json:"project_choices,omitempty"` +} + +func (i Import) String() string { + return Stringify(i) +} + +// SourceImportAuthor identifies an author imported from a source repository. +// +// GitHub API docs: https://docs.github.com/rest/migration/source_imports/#get-commit-authors +type SourceImportAuthor struct { + ID *int64 `json:"id,omitempty"` + RemoteID *string `json:"remote_id,omitempty"` + RemoteName *string `json:"remote_name,omitempty"` + Email *string `json:"email,omitempty"` + Name *string `json:"name,omitempty"` + URL *string `json:"url,omitempty"` + ImportURL *string `json:"import_url,omitempty"` +} + +func (a SourceImportAuthor) String() string { + return Stringify(a) +} + +// LargeFile identifies a file larger than 100MB found during a repository import. +// +// GitHub API docs: https://docs.github.com/rest/migration/source_imports/#get-large-files +type LargeFile struct { + RefName *string `json:"ref_name,omitempty"` + Path *string `json:"path,omitempty"` + OID *string `json:"oid,omitempty"` + Size *int `json:"size,omitempty"` +} + +func (f LargeFile) String() string { + return Stringify(f) +} + +// StartImport initiates a repository import. +// +// GitHub API docs: https://docs.github.com/rest/migrations/source-imports#start-an-import +// +//meta:operation PUT /repos/{owner}/{repo}/import +func (s *MigrationService) StartImport(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import", owner, repo) + req, err := s.client.NewRequest("PUT", u, in) + if err != nil { + return nil, nil, err + } + + out := new(Import) + resp, err := s.client.Do(ctx, req, out) + if err != nil { + return nil, resp, err + } + + return out, resp, nil +} + +// ImportProgress queries for the status and progress of an ongoing repository import. +// +// GitHub API docs: https://docs.github.com/rest/migrations/source-imports#get-an-import-status +// +//meta:operation GET /repos/{owner}/{repo}/import +func (s *MigrationService) ImportProgress(ctx context.Context, owner, repo string) (*Import, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + out := new(Import) + resp, err := s.client.Do(ctx, req, out) + if err != nil { + return nil, resp, err + } + + return out, resp, nil +} + +// UpdateImport initiates a repository import. +// +// GitHub API docs: https://docs.github.com/rest/migrations/source-imports#update-an-import +// +//meta:operation PATCH /repos/{owner}/{repo}/import +func (s *MigrationService) UpdateImport(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import", owner, repo) + req, err := s.client.NewRequest("PATCH", u, in) + if err != nil { + return nil, nil, err + } + + out := new(Import) + resp, err := s.client.Do(ctx, req, out) + if err != nil { + return nil, resp, err + } + + return out, resp, nil +} + +// CommitAuthors gets the authors mapped from the original repository. +// +// Each type of source control system represents authors in a different way. +// For example, a Git commit author has a display name and an email address, +// but a Subversion commit author just has a username. The GitHub Importer will +// make the author information valid, but the author might not be correct. For +// example, it will change the bare Subversion username "hubot" into something +// like "hubot ". +// +// This method and MapCommitAuthor allow you to provide correct Git author +// information. +// +// GitHub API docs: https://docs.github.com/rest/migrations/source-imports#get-commit-authors +// +//meta:operation GET /repos/{owner}/{repo}/import/authors +func (s *MigrationService) CommitAuthors(ctx context.Context, owner, repo string) ([]*SourceImportAuthor, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import/authors", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var authors []*SourceImportAuthor + resp, err := s.client.Do(ctx, req, &authors) + if err != nil { + return nil, resp, err + } + + return authors, resp, nil +} + +// MapCommitAuthor updates an author's identity for the import. Your +// application can continue updating authors any time before you push new +// commits to the repository. +// +// GitHub API docs: https://docs.github.com/rest/migrations/source-imports#map-a-commit-author +// +//meta:operation PATCH /repos/{owner}/{repo}/import/authors/{author_id} +func (s *MigrationService) MapCommitAuthor(ctx context.Context, owner, repo string, id int64, author *SourceImportAuthor) (*SourceImportAuthor, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import/authors/%v", owner, repo, id) + req, err := s.client.NewRequest("PATCH", u, author) + if err != nil { + return nil, nil, err + } + + out := new(SourceImportAuthor) + resp, err := s.client.Do(ctx, req, out) + if err != nil { + return nil, resp, err + } + + return out, resp, nil +} + +// SetLFSPreference sets whether imported repositories should use Git LFS for +// files larger than 100MB. Only the UseLFS field on the provided Import is +// used. +// +// GitHub API docs: https://docs.github.com/rest/migrations/source-imports#update-git-lfs-preference +// +//meta:operation PATCH /repos/{owner}/{repo}/import/lfs +func (s *MigrationService) SetLFSPreference(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import/lfs", owner, repo) + req, err := s.client.NewRequest("PATCH", u, in) + if err != nil { + return nil, nil, err + } + + out := new(Import) + resp, err := s.client.Do(ctx, req, out) + if err != nil { + return nil, resp, err + } + + return out, resp, nil +} + +// LargeFiles lists files larger than 100MB found during the import. +// +// GitHub API docs: https://docs.github.com/rest/migrations/source-imports#get-large-files +// +//meta:operation GET /repos/{owner}/{repo}/import/large_files +func (s *MigrationService) LargeFiles(ctx context.Context, owner, repo string) ([]*LargeFile, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import/large_files", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var files []*LargeFile + resp, err := s.client.Do(ctx, req, &files) + if err != nil { + return nil, resp, err + } + + return files, resp, nil +} + +// CancelImport stops an import for a repository. +// +// GitHub API docs: https://docs.github.com/rest/migrations/source-imports#cancel-an-import +// +//meta:operation DELETE /repos/{owner}/{repo}/import +func (s *MigrationService) CancelImport(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/import", owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/migrations_user.go b/vendor/github.com/google/go-github/v68/github/migrations_user.go new file mode 100644 index 0000000000..a7bd79499a --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/migrations_user.go @@ -0,0 +1,230 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "errors" + "fmt" + "net/http" +) + +// UserMigration represents a GitHub migration (archival). +type UserMigration struct { + ID *int64 `json:"id,omitempty"` + GUID *string `json:"guid,omitempty"` + // State is the current state of a migration. + // Possible values are: + // "pending" which means the migration hasn't started yet, + // "exporting" which means the migration is in progress, + // "exported" which means the migration finished successfully, or + // "failed" which means the migration failed. + State *string `json:"state,omitempty"` + // LockRepositories indicates whether repositories are locked (to prevent + // manipulation) while migrating data. + LockRepositories *bool `json:"lock_repositories,omitempty"` + // ExcludeAttachments indicates whether attachments should be excluded from + // the migration (to reduce migration archive file size). + ExcludeAttachments *bool `json:"exclude_attachments,omitempty"` + URL *string `json:"url,omitempty"` + CreatedAt *string `json:"created_at,omitempty"` + UpdatedAt *string `json:"updated_at,omitempty"` + Repositories []*Repository `json:"repositories,omitempty"` +} + +func (m UserMigration) String() string { + return Stringify(m) +} + +// UserMigrationOptions specifies the optional parameters to Migration methods. +type UserMigrationOptions struct { + // LockRepositories indicates whether repositories should be locked (to prevent + // manipulation) while migrating data. + LockRepositories bool + + // ExcludeAttachments indicates whether attachments should be excluded from + // the migration (to reduce migration archive file size). + ExcludeAttachments bool +} + +// startUserMigration represents the body of a StartMigration request. +type startUserMigration struct { + // Repositories is a slice of repository names to migrate. + Repositories []string `json:"repositories,omitempty"` + + // LockRepositories indicates whether repositories should be locked (to prevent + // manipulation) while migrating data. + LockRepositories *bool `json:"lock_repositories,omitempty"` + + // ExcludeAttachments indicates whether attachments should be excluded from + // the migration (to reduce migration archive file size). + ExcludeAttachments *bool `json:"exclude_attachments,omitempty"` +} + +// StartUserMigration starts the generation of a migration archive. +// repos is a slice of repository names to migrate. +// +// GitHub API docs: https://docs.github.com/rest/migrations/users#start-a-user-migration +// +//meta:operation POST /user/migrations +func (s *MigrationService) StartUserMigration(ctx context.Context, repos []string, opts *UserMigrationOptions) (*UserMigration, *Response, error) { + u := "user/migrations" + + body := &startUserMigration{Repositories: repos} + if opts != nil { + body.LockRepositories = Ptr(opts.LockRepositories) + body.ExcludeAttachments = Ptr(opts.ExcludeAttachments) + } + + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + m := &UserMigration{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// ListUserMigrations lists the most recent migrations. +// +// GitHub API docs: https://docs.github.com/rest/migrations/users#list-user-migrations +// +//meta:operation GET /user/migrations +func (s *MigrationService) ListUserMigrations(ctx context.Context, opts *ListOptions) ([]*UserMigration, *Response, error) { + u := "user/migrations" + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + var m []*UserMigration + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// UserMigrationStatus gets the status of a specific migration archive. +// id is the migration ID. +// +// GitHub API docs: https://docs.github.com/rest/migrations/users#get-a-user-migration-status +// +//meta:operation GET /user/migrations/{migration_id} +func (s *MigrationService) UserMigrationStatus(ctx context.Context, id int64) (*UserMigration, *Response, error) { + u := fmt.Sprintf("user/migrations/%v", id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + m := &UserMigration{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// UserMigrationArchiveURL gets the URL for a specific migration archive. +// id is the migration ID. +// +// GitHub API docs: https://docs.github.com/rest/migrations/users#download-a-user-migration-archive +// +//meta:operation GET /user/migrations/{migration_id}/archive +func (s *MigrationService) UserMigrationArchiveURL(ctx context.Context, id int64) (string, error) { + url := fmt.Sprintf("user/migrations/%v/archive", id) + + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return "", err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + m := &UserMigration{} + + var loc string + originalRedirect := s.client.client.CheckRedirect + s.client.client.CheckRedirect = func(req *http.Request, via []*http.Request) error { + loc = req.URL.String() + return http.ErrUseLastResponse + } + defer func() { + s.client.client.CheckRedirect = originalRedirect + }() + resp, err := s.client.Do(ctx, req, m) + if err == nil { + return "", errors.New("expected redirect, none provided") + } + loc = resp.Header.Get("Location") + return loc, nil +} + +// DeleteUserMigration will delete a previous migration archive. +// id is the migration ID. +// +// GitHub API docs: https://docs.github.com/rest/migrations/users#delete-a-user-migration-archive +// +//meta:operation DELETE /user/migrations/{migration_id}/archive +func (s *MigrationService) DeleteUserMigration(ctx context.Context, id int64) (*Response, error) { + url := fmt.Sprintf("user/migrations/%v/archive", id) + + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + return s.client.Do(ctx, req, nil) +} + +// UnlockUserRepo will unlock a repo that was locked for migration. +// id is migration ID. +// You should unlock each migrated repository and delete them when the migration +// is complete and you no longer need the source data. +// +// GitHub API docs: https://docs.github.com/rest/migrations/users#unlock-a-user-repository +// +//meta:operation DELETE /user/migrations/{migration_id}/repos/{repo_name}/lock +func (s *MigrationService) UnlockUserRepo(ctx context.Context, id int64, repo string) (*Response, error) { + url := fmt.Sprintf("user/migrations/%v/repos/%v/lock", id, repo) + + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs.go b/vendor/github.com/google/go-github/v68/github/orgs.go new file mode 100644 index 0000000000..27c0f10284 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs.go @@ -0,0 +1,318 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// OrganizationsService provides access to the organization related functions +// in the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/orgs/ +type OrganizationsService service + +// Organization represents a GitHub organization account. +type Organization struct { + Login *string `json:"login,omitempty"` + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + AvatarURL *string `json:"avatar_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + Name *string `json:"name,omitempty"` + Company *string `json:"company,omitempty"` + Blog *string `json:"blog,omitempty"` + Location *string `json:"location,omitempty"` + Email *string `json:"email,omitempty"` + TwitterUsername *string `json:"twitter_username,omitempty"` + Description *string `json:"description,omitempty"` + PublicRepos *int `json:"public_repos,omitempty"` + PublicGists *int `json:"public_gists,omitempty"` + Followers *int `json:"followers,omitempty"` + Following *int `json:"following,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + TotalPrivateRepos *int64 `json:"total_private_repos,omitempty"` + OwnedPrivateRepos *int64 `json:"owned_private_repos,omitempty"` + PrivateGists *int `json:"private_gists,omitempty"` + DiskUsage *int `json:"disk_usage,omitempty"` + Collaborators *int `json:"collaborators,omitempty"` + BillingEmail *string `json:"billing_email,omitempty"` + Type *string `json:"type,omitempty"` + Plan *Plan `json:"plan,omitempty"` + TwoFactorRequirementEnabled *bool `json:"two_factor_requirement_enabled,omitempty"` + IsVerified *bool `json:"is_verified,omitempty"` + HasOrganizationProjects *bool `json:"has_organization_projects,omitempty"` + HasRepositoryProjects *bool `json:"has_repository_projects,omitempty"` + + // DefaultRepoPermission can be one of: "read", "write", "admin", or "none". (Default: "read"). + // It is only used in OrganizationsService.Edit. + DefaultRepoPermission *string `json:"default_repository_permission,omitempty"` + // DefaultRepoSettings can be one of: "read", "write", "admin", or "none". (Default: "read"). + // It is only used in OrganizationsService.Get. + DefaultRepoSettings *string `json:"default_repository_settings,omitempty"` + + // MembersCanCreateRepos default value is true and is only used in Organizations.Edit. + MembersCanCreateRepos *bool `json:"members_can_create_repositories,omitempty"` + + // https://developer.github.com/changes/2019-12-03-internal-visibility-changes/#rest-v3-api + MembersCanCreatePublicRepos *bool `json:"members_can_create_public_repositories,omitempty"` + MembersCanCreatePrivateRepos *bool `json:"members_can_create_private_repositories,omitempty"` + MembersCanCreateInternalRepos *bool `json:"members_can_create_internal_repositories,omitempty"` + + // MembersCanForkPrivateRepos toggles whether organization members can fork private organization repositories. + MembersCanForkPrivateRepos *bool `json:"members_can_fork_private_repositories,omitempty"` + + // MembersAllowedRepositoryCreationType denotes if organization members can create repositories + // and the type of repositories they can create. Possible values are: "all", "private", or "none". + // + // Deprecated: Use MembersCanCreatePublicRepos, MembersCanCreatePrivateRepos, MembersCanCreateInternalRepos + // instead. The new fields overrides the existing MembersAllowedRepositoryCreationType during 'edit' + // operation and does not consider 'internal' repositories during 'get' operation + MembersAllowedRepositoryCreationType *string `json:"members_allowed_repository_creation_type,omitempty"` + + // MembersCanCreatePages toggles whether organization members can create GitHub Pages sites. + MembersCanCreatePages *bool `json:"members_can_create_pages,omitempty"` + // MembersCanCreatePublicPages toggles whether organization members can create public GitHub Pages sites. + MembersCanCreatePublicPages *bool `json:"members_can_create_public_pages,omitempty"` + // MembersCanCreatePrivatePages toggles whether organization members can create private GitHub Pages sites. + MembersCanCreatePrivatePages *bool `json:"members_can_create_private_pages,omitempty"` + // WebCommitSignoffRequire toggles + WebCommitSignoffRequired *bool `json:"web_commit_signoff_required,omitempty"` + // AdvancedSecurityAuditLogEnabled toggles whether the advanced security audit log is enabled. + AdvancedSecurityEnabledForNewRepos *bool `json:"advanced_security_enabled_for_new_repositories,omitempty"` + // DependabotAlertsEnabled toggles whether dependabot alerts are enabled. + DependabotAlertsEnabledForNewRepos *bool `json:"dependabot_alerts_enabled_for_new_repositories,omitempty"` + // DependabotSecurityUpdatesEnabled toggles whether dependabot security updates are enabled. + DependabotSecurityUpdatesEnabledForNewRepos *bool `json:"dependabot_security_updates_enabled_for_new_repositories,omitempty"` + // DependabotGraphEnabledForNewRepos toggles whether dependabot graph is enabled on new repositories. + DependencyGraphEnabledForNewRepos *bool `json:"dependency_graph_enabled_for_new_repositories,omitempty"` + // SecretScanningEnabled toggles whether secret scanning is enabled on new repositories. + SecretScanningEnabledForNewRepos *bool `json:"secret_scanning_enabled_for_new_repositories,omitempty"` + // SecretScanningPushProtectionEnabledForNewRepos toggles whether secret scanning push protection is enabled on new repositories. + SecretScanningPushProtectionEnabledForNewRepos *bool `json:"secret_scanning_push_protection_enabled_for_new_repositories,omitempty"` + // SecretScanningValidityChecksEnabled toggles whether secret scanning validity check is enabled. + SecretScanningValidityChecksEnabled *bool `json:"secret_scanning_validity_checks_enabled,omitempty"` + + // API URLs + URL *string `json:"url,omitempty"` + EventsURL *string `json:"events_url,omitempty"` + HooksURL *string `json:"hooks_url,omitempty"` + IssuesURL *string `json:"issues_url,omitempty"` + MembersURL *string `json:"members_url,omitempty"` + PublicMembersURL *string `json:"public_members_url,omitempty"` + ReposURL *string `json:"repos_url,omitempty"` +} + +// OrganizationInstallations represents GitHub app installations for an organization. +type OrganizationInstallations struct { + TotalCount *int `json:"total_count,omitempty"` + Installations []*Installation `json:"installations,omitempty"` +} + +func (o Organization) String() string { + return Stringify(o) +} + +// Plan represents the payment plan for an account. See plans at https://github.com/plans. +type Plan struct { + Name *string `json:"name,omitempty"` + Space *int `json:"space,omitempty"` + Collaborators *int `json:"collaborators,omitempty"` + PrivateRepos *int64 `json:"private_repos,omitempty"` + FilledSeats *int `json:"filled_seats,omitempty"` + Seats *int `json:"seats,omitempty"` +} + +func (p Plan) String() string { + return Stringify(p) +} + +// OrganizationsListOptions specifies the optional parameters to the +// OrganizationsService.ListAll method. +type OrganizationsListOptions struct { + // Since filters Organizations by ID. + Since int64 `url:"since,omitempty"` + + // Note: Pagination is powered exclusively by the Since parameter, + // ListOptions.Page has no effect. + // ListOptions.PerPage controls an undocumented GitHub API parameter. + ListOptions +} + +// ListAll lists all organizations, in the order that they were created on GitHub. +// +// Note: Pagination is powered exclusively by the since parameter. To continue +// listing the next set of organizations, use the ID of the last-returned organization +// as the opts.Since parameter for the next call. +// +// GitHub API docs: https://docs.github.com/rest/orgs/orgs#list-organizations +// +//meta:operation GET /organizations +func (s *OrganizationsService) ListAll(ctx context.Context, opts *OrganizationsListOptions) ([]*Organization, *Response, error) { + u, err := addOptions("organizations", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + orgs := []*Organization{} + resp, err := s.client.Do(ctx, req, &orgs) + if err != nil { + return nil, resp, err + } + return orgs, resp, nil +} + +// List the organizations for a user. Passing the empty string will list +// organizations for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/orgs/orgs#list-organizations-for-a-user +// GitHub API docs: https://docs.github.com/rest/orgs/orgs#list-organizations-for-the-authenticated-user +// +//meta:operation GET /user/orgs +//meta:operation GET /users/{username}/orgs +func (s *OrganizationsService) List(ctx context.Context, user string, opts *ListOptions) ([]*Organization, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/orgs", user) + } else { + u = "user/orgs" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var orgs []*Organization + resp, err := s.client.Do(ctx, req, &orgs) + if err != nil { + return nil, resp, err + } + + return orgs, resp, nil +} + +// Get fetches an organization by name. +// +// GitHub API docs: https://docs.github.com/rest/orgs/orgs#get-an-organization +// +//meta:operation GET /orgs/{org} +func (s *OrganizationsService) Get(ctx context.Context, org string) (*Organization, *Response, error) { + u := fmt.Sprintf("orgs/%v", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMemberAllowedRepoCreationTypePreview) + + organization := new(Organization) + resp, err := s.client.Do(ctx, req, organization) + if err != nil { + return nil, resp, err + } + + return organization, resp, nil +} + +// GetByID fetches an organization. +// +// Note: GetByID uses the undocumented GitHub API endpoint "GET /organizations/{organization_id}". +// +//meta:operation GET /organizations/{organization_id} +func (s *OrganizationsService) GetByID(ctx context.Context, id int64) (*Organization, *Response, error) { + u := fmt.Sprintf("organizations/%d", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + organization := new(Organization) + resp, err := s.client.Do(ctx, req, organization) + if err != nil { + return nil, resp, err + } + + return organization, resp, nil +} + +// Edit an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/orgs#update-an-organization +// +//meta:operation PATCH /orgs/{org} +func (s *OrganizationsService) Edit(ctx context.Context, name string, org *Organization) (*Organization, *Response, error) { + u := fmt.Sprintf("orgs/%v", name) + req, err := s.client.NewRequest("PATCH", u, org) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMemberAllowedRepoCreationTypePreview) + + o := new(Organization) + resp, err := s.client.Do(ctx, req, o) + if err != nil { + return nil, resp, err + } + + return o, resp, nil +} + +// Delete an organization by name. +// +// GitHub API docs: https://docs.github.com/rest/orgs/orgs#delete-an-organization +// +//meta:operation DELETE /orgs/{org} +func (s *OrganizationsService) Delete(ctx context.Context, org string) (*Response, error) { + u := fmt.Sprintf("orgs/%v", org) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListInstallations lists installations for an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/orgs#list-app-installations-for-an-organization +// +//meta:operation GET /orgs/{org}/installations +func (s *OrganizationsService) ListInstallations(ctx context.Context, org string, opts *ListOptions) (*OrganizationInstallations, *Response, error) { + u := fmt.Sprintf("orgs/%v/installations", org) + + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + result := new(OrganizationInstallations) + resp, err := s.client.Do(ctx, req, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_actions_allowed.go b/vendor/github.com/google/go-github/v68/github/orgs_actions_allowed.go new file mode 100644 index 0000000000..b115e094a4 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_actions_allowed.go @@ -0,0 +1,34 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" +) + +// GetActionsAllowed gets the actions that are allowed in an organization. +// +// Deprecated: please use `client.Actions.GetActionsAllowed` instead. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#get-allowed-actions-and-reusable-workflows-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/permissions/selected-actions +func (s *OrganizationsService) GetActionsAllowed(ctx context.Context, org string) (*ActionsAllowed, *Response, error) { + s2 := (*ActionsService)(s) + return s2.GetActionsAllowed(ctx, org) +} + +// EditActionsAllowed sets the actions that are allowed in an organization. +// +// Deprecated: please use `client.Actions.EditActionsAllowed` instead. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#set-allowed-actions-and-reusable-workflows-for-an-organization +// +//meta:operation PUT /orgs/{org}/actions/permissions/selected-actions +func (s *OrganizationsService) EditActionsAllowed(ctx context.Context, org string, actionsAllowed ActionsAllowed) (*ActionsAllowed, *Response, error) { + s2 := (*ActionsService)(s) + return s2.EditActionsAllowed(ctx, org, actionsAllowed) +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_actions_permissions.go b/vendor/github.com/google/go-github/v68/github/orgs_actions_permissions.go new file mode 100644 index 0000000000..97df1c967e --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_actions_permissions.go @@ -0,0 +1,34 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" +) + +// GetActionsPermissions gets the GitHub Actions permissions policy for repositories and allowed actions in an organization. +// +// Deprecated: please use `client.Actions.GetActionsPermissions` instead. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#get-github-actions-permissions-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/permissions +func (s *OrganizationsService) GetActionsPermissions(ctx context.Context, org string) (*ActionsPermissions, *Response, error) { + s2 := (*ActionsService)(s) + return s2.GetActionsPermissions(ctx, org) +} + +// EditActionsPermissions sets the permissions policy for repositories and allowed actions in an organization. +// +// Deprecated: please use `client.Actions.EditActionsPermissions` instead. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#set-github-actions-permissions-for-an-organization +// +//meta:operation PUT /orgs/{org}/actions/permissions +func (s *OrganizationsService) EditActionsPermissions(ctx context.Context, org string, actionsPermissions ActionsPermissions) (*ActionsPermissions, *Response, error) { + s2 := (*ActionsService)(s) + return s2.EditActionsPermissions(ctx, org, actionsPermissions) +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_attestations.go b/vendor/github.com/google/go-github/v68/github/orgs_attestations.go new file mode 100644 index 0000000000..3d5793c18f --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_attestations.go @@ -0,0 +1,40 @@ +// Copyright 2024 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListAttestations returns a collection of artifact attestations +// with a given subject digest that are associated with repositories +// owned by an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/orgs#list-attestations +// +//meta:operation GET /orgs/{org}/attestations/{subject_digest} +func (s *OrganizationsService) ListAttestations(ctx context.Context, org, subjectDigest string, opts *ListOptions) (*AttestationsResponse, *Response, error) { + var u = fmt.Sprintf("orgs/%v/attestations/%v", org, subjectDigest) + + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var attestations *AttestationsResponse + resp, err := s.client.Do(ctx, req, &attestations) + if err != nil { + return nil, resp, err + } + + return attestations, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_audit_log.go b/vendor/github.com/google/go-github/v68/github/orgs_audit_log.go new file mode 100644 index 0000000000..025c5d0232 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_audit_log.go @@ -0,0 +1,142 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" +) + +// GetAuditLogOptions sets up optional parameters to query audit-log endpoint. +type GetAuditLogOptions struct { + Phrase *string `url:"phrase,omitempty"` // A search phrase. (Optional.) + Include *string `url:"include,omitempty"` // Event type includes. Can be one of "web", "git", "all". Default: "web". (Optional.) + Order *string `url:"order,omitempty"` // The order of audit log events. Can be one of "asc" or "desc". Default: "desc". (Optional.) + + ListCursorOptions +} + +// ActorLocation contains information about reported location for an actor. +type ActorLocation struct { + CountryCode *string `json:"country_code,omitempty"` +} + +// AuditEntry describes the fields that may be represented by various audit-log "action" entries. +// There are many other fields that may be present depending on the action. You can access those +// in AdditionalFields. +// For a list of actions see - https://docs.github.com/github/setting-up-and-managing-organizations-and-teams/reviewing-the-audit-log-for-your-organization#audit-log-actions +type AuditEntry struct { + Action *string `json:"action,omitempty"` // The name of the action that was performed, for example `user.login` or `repo.create`. + Actor *string `json:"actor,omitempty"` // The actor who performed the action. + ActorID *int64 `json:"actor_id,omitempty"` + ActorLocation *ActorLocation `json:"actor_location,omitempty"` + Business *string `json:"business,omitempty"` + BusinessID *int64 `json:"business_id,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + DocumentID *string `json:"_document_id,omitempty"` + ExternalIdentityNameID *string `json:"external_identity_nameid,omitempty"` + ExternalIdentityUsername *string `json:"external_identity_username,omitempty"` + HashedToken *string `json:"hashed_token,omitempty"` + Org *string `json:"org,omitempty"` + OrgID *int64 `json:"org_id,omitempty"` + Timestamp *Timestamp `json:"@timestamp,omitempty"` // The time the audit log event occurred, given as a [Unix timestamp](http://en.wikipedia.org/wiki/Unix_time). + TokenID *int64 `json:"token_id,omitempty"` + TokenScopes *string `json:"token_scopes,omitempty"` + User *string `json:"user,omitempty"` // The user that was affected by the action performed (if available). + UserID *int64 `json:"user_id,omitempty"` + + // Some events types have a data field that contains additional information about the event. + Data map[string]interface{} `json:"data,omitempty"` + + // All fields that are not explicitly defined in the struct are captured here. + AdditionalFields map[string]interface{} `json:"-"` +} + +func (a *AuditEntry) UnmarshalJSON(data []byte) error { + type entryAlias AuditEntry + var v entryAlias + if err := json.Unmarshal(data, &v); err != nil { + return err + } + + rawDefinedFields, err := json.Marshal(v) + if err != nil { + return err + } + definedFields := map[string]interface{}{} + if err := json.Unmarshal(rawDefinedFields, &definedFields); err != nil { + return err + } + + if err := json.Unmarshal(data, &v.AdditionalFields); err != nil { + return err + } + + for key, val := range v.AdditionalFields { + if _, ok := definedFields[key]; ok || val == nil { + delete(v.AdditionalFields, key) + } + } + + *a = AuditEntry(v) + if len(v.AdditionalFields) == 0 { + a.AdditionalFields = nil + } + return nil +} + +func (a *AuditEntry) MarshalJSON() ([]byte, error) { + type entryAlias AuditEntry + v := entryAlias(*a) + defBytes, err := json.Marshal(v) + if err != nil { + return nil, err + } + if len(a.AdditionalFields) == 0 { + return defBytes, err + } + resMap := map[string]interface{}{} + if err := json.Unmarshal(defBytes, &resMap); err != nil { + return nil, err + } + for key, val := range a.AdditionalFields { + if val == nil { + continue + } + if _, ok := resMap[key]; ok { + return nil, fmt.Errorf("unexpected field in AdditionalFields: %v", key) + } + resMap[key] = val + } + return json.Marshal(resMap) +} + +// GetAuditLog gets the audit-log entries for an organization. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/orgs#get-the-audit-log-for-an-organization +// +//meta:operation GET /orgs/{org}/audit-log +func (s *OrganizationsService) GetAuditLog(ctx context.Context, org string, opts *GetAuditLogOptions) ([]*AuditEntry, *Response, error) { + u := fmt.Sprintf("orgs/%v/audit-log", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var auditEntries []*AuditEntry + resp, err := s.client.Do(ctx, req, &auditEntries) + if err != nil { + return nil, resp, err + } + + return auditEntries, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_codesecurity_configurations.go b/vendor/github.com/google/go-github/v68/github/orgs_codesecurity_configurations.go new file mode 100644 index 0000000000..b25845a4e8 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_codesecurity_configurations.go @@ -0,0 +1,284 @@ +// Copyright 2024 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" +) + +// DependencyGraphAutosubmitActionOptions represents the options for the DependencyGraphAutosubmitAction. +type DependencyGraphAutosubmitActionOptions struct { + LabeledRunners *bool `json:"labeled_runners,omitempty"` +} + +// CodeSecurityConfiguration represents a code security configuration. +type CodeSecurityConfiguration struct { + ID *int64 `json:"id,omitempty"` + TargetType *string `json:"target_type,omitempty"` + Name *string `json:"name"` + Description *string `json:"description,omitempty"` + AdvancedSecurity *string `json:"advanced_security,omitempty"` + DependencyGraph *string `json:"dependency_graph,omitempty"` + DependencyGraphAutosubmitAction *string `json:"dependency_graph_autosubmit_action,omitempty"` + DependencyGraphAutosubmitActionOptions *DependencyGraphAutosubmitActionOptions `json:"dependency_graph_autosubmit_action_options,omitempty"` + DependabotAlerts *string `json:"dependabot_alerts,omitempty"` + DependabotSecurityUpdates *string `json:"dependabot_security_updates,omitempty"` + CodeScanningDefaultSetup *string `json:"code_scanning_default_setup,omitempty"` + SecretScanning *string `json:"secret_scanning,omitempty"` + SecretScanningPushProtection *string `json:"secret_scanning_push_protection,omitempty"` + SecretScanningValidityChecks *string `json:"secret_scanning_validity_checks,omitempty"` + SecretScanningNonProviderPatterns *string `json:"secret_scanning_non_provider_patterns,omitempty"` + PrivateVulnerabilityReporting *string `json:"private_vulnerability_reporting,omitempty"` + Enforcement *string `json:"enforcement,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +// CodeSecurityConfigurationWithDefaultForNewRepos represents a code security configuration with default for new repos param. +type CodeSecurityConfigurationWithDefaultForNewRepos struct { + Configuration *CodeSecurityConfiguration `json:"configuration"` + DefaultForNewRepos *string `json:"default_for_new_repos"` +} + +// RepositoryCodeSecurityConfiguration represents a code security configuration for a repository. +type RepositoryCodeSecurityConfiguration struct { + State *string `json:"state,omitempty"` + Configuration *CodeSecurityConfiguration `json:"configuration,omitempty"` +} + +// GetCodeSecurityConfigurations gets code security configurations for an organization. +// +// GitHub API docs: https://docs.github.com/rest/code-security/configurations#get-code-security-configurations-for-an-organization +// +//meta:operation GET /orgs/{org}/code-security/configurations +func (s *OrganizationsService) GetCodeSecurityConfigurations(ctx context.Context, org string) ([]*CodeSecurityConfiguration, *Response, error) { + u := fmt.Sprintf("orgs/%v/code-security/configurations", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var configurations []*CodeSecurityConfiguration + resp, err := s.client.Do(ctx, req, &configurations) + if err != nil { + return nil, resp, err + } + return configurations, resp, nil +} + +// CreateCodeSecurityConfiguration creates a code security configuration for an organization. +// +// GitHub API docs: https://docs.github.com/rest/code-security/configurations#create-a-code-security-configuration +// +//meta:operation POST /orgs/{org}/code-security/configurations +func (s *OrganizationsService) CreateCodeSecurityConfiguration(ctx context.Context, org string, c *CodeSecurityConfiguration) (*CodeSecurityConfiguration, *Response, error) { + u := fmt.Sprintf("orgs/%v/code-security/configurations", org) + + req, err := s.client.NewRequest("POST", u, c) + if err != nil { + return nil, nil, err + } + + var configuration *CodeSecurityConfiguration + resp, err := s.client.Do(ctx, req, &configuration) + if err != nil { + return nil, resp, err + } + return configuration, resp, nil +} + +// GetDefaultCodeSecurityConfigurations gets default code security configurations for an organization. +// +// GitHub API docs: https://docs.github.com/rest/code-security/configurations#get-default-code-security-configurations +// +//meta:operation GET /orgs/{org}/code-security/configurations/defaults +func (s *OrganizationsService) GetDefaultCodeSecurityConfigurations(ctx context.Context, org string) ([]*CodeSecurityConfiguration, *Response, error) { + u := fmt.Sprintf("orgs/%v/code-security/configurations/defaults", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var configurations []*CodeSecurityConfiguration + resp, err := s.client.Do(ctx, req, &configurations) + if err != nil { + return nil, resp, err + } + return configurations, resp, nil +} + +// DetachCodeSecurityConfigurationsFromRepositories detaches code security configuration from an organization's repositories. +// +// GitHub API docs: https://docs.github.com/rest/code-security/configurations#detach-configurations-from-repositories +// +//meta:operation DELETE /orgs/{org}/code-security/configurations/detach +func (s *OrganizationsService) DetachCodeSecurityConfigurationsFromRepositories(ctx context.Context, org string, repoIDs []int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/code-security/configurations/detach", org) + type selectedRepoIDs struct { + SelectedIDs []int64 `json:"selected_repository_ids"` + } + req, err := s.client.NewRequest("DELETE", u, selectedRepoIDs{SelectedIDs: repoIDs}) + if err != nil { + return nil, err + } + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + return resp, nil +} + +// GetCodeSecurityConfiguration gets a code security configuration available in an organization. +// +// GitHub API docs: https://docs.github.com/rest/code-security/configurations#get-a-code-security-configuration +// +//meta:operation GET /orgs/{org}/code-security/configurations/{configuration_id} +func (s *OrganizationsService) GetCodeSecurityConfiguration(ctx context.Context, org string, id int64) (*CodeSecurityConfiguration, *Response, error) { + u := fmt.Sprintf("orgs/%v/code-security/configurations/%v", org, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var configuration *CodeSecurityConfiguration + resp, err := s.client.Do(ctx, req, &configuration) + if err != nil { + return nil, resp, err + } + return configuration, resp, nil +} + +// UpdateCodeSecurityConfiguration updates a code security configuration for an organization. +// +// GitHub API docs: https://docs.github.com/rest/code-security/configurations#update-a-code-security-configuration +// +//meta:operation PATCH /orgs/{org}/code-security/configurations/{configuration_id} +func (s *OrganizationsService) UpdateCodeSecurityConfiguration(ctx context.Context, org string, id int64, c *CodeSecurityConfiguration) (*CodeSecurityConfiguration, *Response, error) { + u := fmt.Sprintf("orgs/%v/code-security/configurations/%v", org, id) + + req, err := s.client.NewRequest("PATCH", u, c) + if err != nil { + return nil, nil, err + } + + var configuration *CodeSecurityConfiguration + resp, err := s.client.Do(ctx, req, &configuration) + if err != nil { + return nil, resp, err + } + return configuration, resp, nil +} + +// DeleteCodeSecurityConfiguration deletes a code security configuration for an organization. +// +// GitHub API docs: https://docs.github.com/rest/code-security/configurations#delete-a-code-security-configuration +// +//meta:operation DELETE /orgs/{org}/code-security/configurations/{configuration_id} +func (s *OrganizationsService) DeleteCodeSecurityConfiguration(ctx context.Context, org string, id int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/code-security/configurations/%v", org, id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + return resp, nil +} + +// AttachCodeSecurityConfigurationsToRepositories attaches code security configurations to repositories for an organization. +// +// GitHub API docs: https://docs.github.com/rest/code-security/configurations#attach-a-configuration-to-repositories +// +//meta:operation POST /orgs/{org}/code-security/configurations/{configuration_id}/attach +func (s *OrganizationsService) AttachCodeSecurityConfigurationsToRepositories(ctx context.Context, org string, id int64, scope string, repoIDs []int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/code-security/configurations/%v/attach", org, id) + type selectedRepoIDs struct { + Scope string `json:"scope"` + SelectedIDs []int64 `json:"selected_repository_ids,omitempty"` + } + req, err := s.client.NewRequest("POST", u, selectedRepoIDs{Scope: scope, SelectedIDs: repoIDs}) + if err != nil { + return nil, err + } + resp, err := s.client.Do(ctx, req, nil) + if err != nil && resp.StatusCode != http.StatusAccepted { // StatusAccepted(202) is the expected status code as job is queued for processing + return resp, err + } + return resp, nil +} + +// SetDefaultCodeSecurityConfiguration sets a code security configuration as the default for an organization. +// +// GitHub API docs: https://docs.github.com/rest/code-security/configurations#set-a-code-security-configuration-as-a-default-for-an-organization +// +//meta:operation PUT /orgs/{org}/code-security/configurations/{configuration_id}/defaults +func (s *OrganizationsService) SetDefaultCodeSecurityConfiguration(ctx context.Context, org string, id int64, newReposParam string) (*CodeSecurityConfigurationWithDefaultForNewRepos, *Response, error) { + u := fmt.Sprintf("orgs/%v/code-security/configurations/%v/defaults", org, id) + type configParam struct { + DefaultForNewRepos string `json:"default_for_new_repos"` + } + req, err := s.client.NewRequest("PUT", u, configParam{DefaultForNewRepos: newReposParam}) + if err != nil { + return nil, nil, err + } + var c *CodeSecurityConfigurationWithDefaultForNewRepos + resp, err := s.client.Do(ctx, req, &c) + if err != nil { + return nil, resp, err + } + return c, resp, nil +} + +// GetRepositoriesForCodeSecurityConfiguration gets repositories associated with a code security configuration. +// +// GitHub API docs: https://docs.github.com/rest/code-security/configurations#get-repositories-associated-with-a-code-security-configuration +// +//meta:operation GET /orgs/{org}/code-security/configurations/{configuration_id}/repositories +func (s *OrganizationsService) GetRepositoriesForCodeSecurityConfiguration(ctx context.Context, org string, id int64) ([]*Repository, *Response, error) { + u := fmt.Sprintf("orgs/%v/code-security/configurations/%v/repositories", org, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var repositories []*Repository + resp, err := s.client.Do(ctx, req, &repositories) + if err != nil { + return nil, resp, err + } + return repositories, resp, nil +} + +// GetCodeSecurityConfigurationForRepository gets code security configuration that manages a repository's code security settings. +// +// GitHub API docs: https://docs.github.com/rest/code-security/configurations#get-the-code-security-configuration-associated-with-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/code-security-configuration +func (s *OrganizationsService) GetCodeSecurityConfigurationForRepository(ctx context.Context, org, repo string) (*RepositoryCodeSecurityConfiguration, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-security-configuration", org, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + var repoConfig *RepositoryCodeSecurityConfiguration + resp, err := s.client.Do(ctx, req, &repoConfig) + if err != nil { + return nil, resp, err + } + return repoConfig, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_credential_authorizations.go b/vendor/github.com/google/go-github/v68/github/orgs_credential_authorizations.go new file mode 100644 index 0000000000..dca42433c3 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_credential_authorizations.go @@ -0,0 +1,109 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" +) + +// CredentialAuthorization represents a credential authorized through SAML SSO. +type CredentialAuthorization struct { + // User login that owns the underlying credential. + Login *string `json:"login,omitempty"` + + // Unique identifier for the credential. + CredentialID *int64 `json:"credential_id,omitempty"` + + // Human-readable description of the credential type. + CredentialType *string `json:"credential_type,omitempty"` + + // Last eight characters of the credential. + // Only included in responses with credential_type of personal access token. + TokenLastEight *string `json:"token_last_eight,omitempty"` + + // Date when the credential was authorized for use. + CredentialAuthorizedAt *Timestamp `json:"credential_authorized_at,omitempty"` + + // Date when the credential was last accessed. + // May be null if it was never accessed. + CredentialAccessedAt *Timestamp `json:"credential_accessed_at,omitempty"` + + // List of oauth scopes the token has been granted. + Scopes []string `json:"scopes,omitempty"` + + // Unique string to distinguish the credential. + // Only included in responses with credential_type of SSH Key. + Fingerprint *string `json:"fingerprint,omitempty"` + + AuthorizedCredentialID *int64 `json:"authorized_credential_id,omitempty"` + + // The title given to the ssh key. + // This will only be present when the credential is an ssh key. + AuthorizedCredentialTitle *string `json:"authorized_credential_title,omitempty"` + + // The note given to the token. + // This will only be present when the credential is a token. + AuthorizedCredentialNote *string `json:"authorized_credential_note,omitempty"` + + // The expiry for the token. + // This will only be present when the credential is a token. + AuthorizedCredentialExpiresAt *Timestamp `json:"authorized_credential_expires_at,omitempty"` +} + +// CredentialAuthorizationsListOptions adds the Login option as supported by the +// list SAML SSO authorizations for organizations endpoint alongside paging options +// such as Page and PerPage. +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/orgs#list-saml-sso-authorizations-for-an-organization +type CredentialAuthorizationsListOptions struct { + ListOptions + // For credentials authorizations for an organization, limit the list of authorizations to a specific login (aka github username) + Login string `url:"login,omitempty"` +} + +// ListCredentialAuthorizations lists credentials authorized through SAML SSO +// for a given organization. Only available with GitHub Enterprise Cloud. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/orgs#list-saml-sso-authorizations-for-an-organization +// +//meta:operation GET /orgs/{org}/credential-authorizations +func (s *OrganizationsService) ListCredentialAuthorizations(ctx context.Context, org string, opts *CredentialAuthorizationsListOptions) ([]*CredentialAuthorization, *Response, error) { + u := fmt.Sprintf("orgs/%v/credential-authorizations", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest(http.MethodGet, u, nil) + if err != nil { + return nil, nil, err + } + + var creds []*CredentialAuthorization + resp, err := s.client.Do(ctx, req, &creds) + if err != nil { + return nil, resp, err + } + + return creds, resp, nil +} + +// RemoveCredentialAuthorization revokes the SAML SSO authorization for a given +// credential within an organization. Only available with GitHub Enterprise Cloud. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/orgs#remove-a-saml-sso-authorization-for-an-organization +// +//meta:operation DELETE /orgs/{org}/credential-authorizations/{credential_id} +func (s *OrganizationsService) RemoveCredentialAuthorization(ctx context.Context, org string, credentialID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/credential-authorizations/%v", org, credentialID) + req, err := s.client.NewRequest(http.MethodDelete, u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_custom_repository_roles.go b/vendor/github.com/google/go-github/v68/github/orgs_custom_repository_roles.go new file mode 100644 index 0000000000..44408db141 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_custom_repository_roles.go @@ -0,0 +1,154 @@ +// Copyright 2024 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// OrganizationCustomRepoRoles represents custom repository roles available in specified organization. +type OrganizationCustomRepoRoles struct { + TotalCount *int `json:"total_count,omitempty"` + CustomRepoRoles []*CustomRepoRoles `json:"custom_roles,omitempty"` +} + +// CustomRepoRoles represents custom repository roles for an organization. +// See https://docs.github.com/enterprise-cloud@latest/organizations/managing-peoples-access-to-your-organization-with-roles/managing-custom-repository-roles-for-an-organization +// for more information. +type CustomRepoRoles struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + BaseRole *string `json:"base_role,omitempty"` + Permissions []string `json:"permissions,omitempty"` + Org *Organization `json:"organization,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +// CreateOrUpdateCustomRepoRoleOptions represents options required to create or update a custom repository role. +type CreateOrUpdateCustomRepoRoleOptions struct { + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + BaseRole *string `json:"base_role,omitempty"` + Permissions []string `json:"permissions"` +} + +// ListCustomRepoRoles lists the custom repository roles available in this organization. +// In order to see custom repository roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/custom-roles#list-custom-repository-roles-in-an-organization +// +//meta:operation GET /orgs/{org}/custom-repository-roles +func (s *OrganizationsService) ListCustomRepoRoles(ctx context.Context, org string) (*OrganizationCustomRepoRoles, *Response, error) { + u := fmt.Sprintf("orgs/%v/custom-repository-roles", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + customRepoRoles := new(OrganizationCustomRepoRoles) + resp, err := s.client.Do(ctx, req, customRepoRoles) + if err != nil { + return nil, resp, err + } + + return customRepoRoles, resp, nil +} + +// GetCustomRepoRole gets a custom repository roles available in this organization. +// In order to see custom repository roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/custom-roles#get-a-custom-repository-role +// +//meta:operation GET /orgs/{org}/custom-repository-roles/{role_id} +func (s *OrganizationsService) GetCustomRepoRole(ctx context.Context, org string, roleID int64) (*CustomRepoRoles, *Response, error) { + u := fmt.Sprintf("orgs/%v/custom-repository-roles/%v", org, roleID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + resultingRole := new(CustomRepoRoles) + resp, err := s.client.Do(ctx, req, resultingRole) + if err != nil { + return nil, resp, err + } + + return resultingRole, resp, nil +} + +// CreateCustomRepoRole creates a custom repository role in this organization. +// In order to create custom repository roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/custom-roles#create-a-custom-repository-role +// +//meta:operation POST /orgs/{org}/custom-repository-roles +func (s *OrganizationsService) CreateCustomRepoRole(ctx context.Context, org string, opts *CreateOrUpdateCustomRepoRoleOptions) (*CustomRepoRoles, *Response, error) { + u := fmt.Sprintf("orgs/%v/custom-repository-roles", org) + + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + resultingRole := new(CustomRepoRoles) + resp, err := s.client.Do(ctx, req, resultingRole) + if err != nil { + return nil, resp, err + } + + return resultingRole, resp, err +} + +// UpdateCustomRepoRole updates a custom repository role in this organization. +// In order to update custom repository roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/custom-roles#update-a-custom-repository-role +// +//meta:operation PATCH /orgs/{org}/custom-repository-roles/{role_id} +func (s *OrganizationsService) UpdateCustomRepoRole(ctx context.Context, org string, roleID int64, opts *CreateOrUpdateCustomRepoRoleOptions) (*CustomRepoRoles, *Response, error) { + u := fmt.Sprintf("orgs/%v/custom-repository-roles/%v", org, roleID) + + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + resultingRole := new(CustomRepoRoles) + resp, err := s.client.Do(ctx, req, resultingRole) + if err != nil { + return nil, resp, err + } + + return resultingRole, resp, err +} + +// DeleteCustomRepoRole deletes an existing custom repository role in this organization. +// In order to delete custom repository roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/custom-roles#delete-a-custom-repository-role +// +//meta:operation DELETE /orgs/{org}/custom-repository-roles/{role_id} +func (s *OrganizationsService) DeleteCustomRepoRole(ctx context.Context, org string, roleID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/custom-repository-roles/%v", org, roleID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resultingRole := new(CustomRepoRoles) + resp, err := s.client.Do(ctx, req, resultingRole) + if err != nil { + return resp, err + } + + return resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_hooks.go b/vendor/github.com/google/go-github/v68/github/orgs_hooks.go new file mode 100644 index 0000000000..c2eef77c92 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_hooks.go @@ -0,0 +1,142 @@ +// Copyright 2015 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListHooks lists all Hooks for the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/webhooks#list-organization-webhooks +// +//meta:operation GET /orgs/{org}/hooks +func (s *OrganizationsService) ListHooks(ctx context.Context, org string, opts *ListOptions) ([]*Hook, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var hooks []*Hook + resp, err := s.client.Do(ctx, req, &hooks) + if err != nil { + return nil, resp, err + } + + return hooks, resp, nil +} + +// GetHook returns a single specified Hook. +// +// GitHub API docs: https://docs.github.com/rest/orgs/webhooks#get-an-organization-webhook +// +//meta:operation GET /orgs/{org}/hooks/{hook_id} +func (s *OrganizationsService) GetHook(ctx context.Context, org string, id int64) (*Hook, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + hook := new(Hook) + resp, err := s.client.Do(ctx, req, hook) + if err != nil { + return nil, resp, err + } + + return hook, resp, nil +} + +// CreateHook creates a Hook for the specified org. +// Config is a required field. +// +// Note that only a subset of the hook fields are used and hook must +// not be nil. +// +// GitHub API docs: https://docs.github.com/rest/orgs/webhooks#create-an-organization-webhook +// +//meta:operation POST /orgs/{org}/hooks +func (s *OrganizationsService) CreateHook(ctx context.Context, org string, hook *Hook) (*Hook, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks", org) + + hookReq := &createHookRequest{ + Name: "web", + Events: hook.Events, + Active: hook.Active, + Config: hook.Config, + } + + req, err := s.client.NewRequest("POST", u, hookReq) + if err != nil { + return nil, nil, err + } + + h := new(Hook) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// EditHook updates a specified Hook. +// +// GitHub API docs: https://docs.github.com/rest/orgs/webhooks#update-an-organization-webhook +// +//meta:operation PATCH /orgs/{org}/hooks/{hook_id} +func (s *OrganizationsService) EditHook(ctx context.Context, org string, id int64, hook *Hook) (*Hook, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) + req, err := s.client.NewRequest("PATCH", u, hook) + if err != nil { + return nil, nil, err + } + + h := new(Hook) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// PingHook triggers a 'ping' event to be sent to the Hook. +// +// GitHub API docs: https://docs.github.com/rest/orgs/webhooks#ping-an-organization-webhook +// +//meta:operation POST /orgs/{org}/hooks/{hook_id}/pings +func (s *OrganizationsService) PingHook(ctx context.Context, org string, id int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%d/pings", org, id) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteHook deletes a specified Hook. +// +// GitHub API docs: https://docs.github.com/rest/orgs/webhooks#delete-an-organization-webhook +// +//meta:operation DELETE /orgs/{org}/hooks/{hook_id} +func (s *OrganizationsService) DeleteHook(ctx context.Context, org string, id int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_hooks_configuration.go b/vendor/github.com/google/go-github/v68/github/orgs_hooks_configuration.go new file mode 100644 index 0000000000..aeb616fc4c --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_hooks_configuration.go @@ -0,0 +1,53 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetHookConfiguration returns the configuration for the specified organization webhook. +// +// GitHub API docs: https://docs.github.com/rest/orgs/webhooks#get-a-webhook-configuration-for-an-organization +// +//meta:operation GET /orgs/{org}/hooks/{hook_id}/config +func (s *OrganizationsService) GetHookConfiguration(ctx context.Context, org string, id int64) (*HookConfig, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%v/config", org, id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + config := new(HookConfig) + resp, err := s.client.Do(ctx, req, config) + if err != nil { + return nil, resp, err + } + + return config, resp, nil +} + +// EditHookConfiguration updates the configuration for the specified organization webhook. +// +// GitHub API docs: https://docs.github.com/rest/orgs/webhooks#update-a-webhook-configuration-for-an-organization +// +//meta:operation PATCH /orgs/{org}/hooks/{hook_id}/config +func (s *OrganizationsService) EditHookConfiguration(ctx context.Context, org string, id int64, config *HookConfig) (*HookConfig, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%v/config", org, id) + req, err := s.client.NewRequest("PATCH", u, config) + if err != nil { + return nil, nil, err + } + + c := new(HookConfig) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_hooks_deliveries.go b/vendor/github.com/google/go-github/v68/github/orgs_hooks_deliveries.go new file mode 100644 index 0000000000..c1c3012402 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_hooks_deliveries.go @@ -0,0 +1,79 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListHookDeliveries lists webhook deliveries for a webhook configured in an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/webhooks#list-deliveries-for-an-organization-webhook +// +//meta:operation GET /orgs/{org}/hooks/{hook_id}/deliveries +func (s *OrganizationsService) ListHookDeliveries(ctx context.Context, org string, id int64, opts *ListCursorOptions) ([]*HookDelivery, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%v/deliveries", org, id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + deliveries := []*HookDelivery{} + resp, err := s.client.Do(ctx, req, &deliveries) + if err != nil { + return nil, resp, err + } + + return deliveries, resp, nil +} + +// GetHookDelivery returns a delivery for a webhook configured in an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/webhooks#get-a-webhook-delivery-for-an-organization-webhook +// +//meta:operation GET /orgs/{org}/hooks/{hook_id}/deliveries/{delivery_id} +func (s *OrganizationsService) GetHookDelivery(ctx context.Context, owner string, hookID, deliveryID int64) (*HookDelivery, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%v/deliveries/%v", owner, hookID, deliveryID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + h := new(HookDelivery) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// RedeliverHookDelivery redelivers a delivery for a webhook configured in an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/webhooks#redeliver-a-delivery-for-an-organization-webhook +// +//meta:operation POST /orgs/{org}/hooks/{hook_id}/deliveries/{delivery_id}/attempts +func (s *OrganizationsService) RedeliverHookDelivery(ctx context.Context, owner string, hookID, deliveryID int64) (*HookDelivery, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%v/deliveries/%v/attempts", owner, hookID, deliveryID) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + h := new(HookDelivery) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_members.go b/vendor/github.com/google/go-github/v68/github/orgs_members.go new file mode 100644 index 0000000000..d818d7f9f8 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_members.go @@ -0,0 +1,436 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Membership represents the status of a user's membership in an organization or team. +type Membership struct { + URL *string `json:"url,omitempty"` + + // State is the user's status within the organization or team. + // Possible values are: "active", "pending" + State *string `json:"state,omitempty"` + + // Role identifies the user's role within the organization or team. + // Possible values for organization membership: + // member - non-owner organization member + // admin - organization owner + // + // Possible values for team membership are: + // member - a normal member of the team + // maintainer - a team maintainer. Able to add/remove other team + // members, promote other team members to team + // maintainer, and edit the team’s name and description + Role *string `json:"role,omitempty"` + + // For organization membership, the API URL of the organization. + OrganizationURL *string `json:"organization_url,omitempty"` + + // For organization membership, the organization the membership is for. + Organization *Organization `json:"organization,omitempty"` + + // For organization membership, the user the membership is for. + User *User `json:"user,omitempty"` +} + +func (m Membership) String() string { + return Stringify(m) +} + +// ListMembersOptions specifies optional parameters to the +// OrganizationsService.ListMembers method. +type ListMembersOptions struct { + // If true (or if the authenticated user is not an owner of the + // organization), list only publicly visible members. + PublicOnly bool `url:"-"` + + // Filter members returned in the list. Possible values are: + // 2fa_disabled, all. Default is "all". + Filter string `url:"filter,omitempty"` + + // Role filters members returned by their role in the organization. + // Possible values are: + // all - all members of the organization, regardless of role + // admin - organization owners + // member - non-owner organization members + // + // Default is "all". + Role string `url:"role,omitempty"` + + ListOptions +} + +// ListMembers lists the members for an organization. If the authenticated +// user is an owner of the organization, this will return both concealed and +// public members, otherwise it will only return public members. +// +// GitHub API docs: https://docs.github.com/rest/orgs/members#list-organization-members +// GitHub API docs: https://docs.github.com/rest/orgs/members#list-public-organization-members +// +//meta:operation GET /orgs/{org}/members +//meta:operation GET /orgs/{org}/public_members +func (s *OrganizationsService) ListMembers(ctx context.Context, org string, opts *ListMembersOptions) ([]*User, *Response, error) { + var u string + if opts != nil && opts.PublicOnly { + u = fmt.Sprintf("orgs/%v/public_members", org) + } else { + u = fmt.Sprintf("orgs/%v/members", org) + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var members []*User + resp, err := s.client.Do(ctx, req, &members) + if err != nil { + return nil, resp, err + } + + return members, resp, nil +} + +// IsMember checks if a user is a member of an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/members#check-organization-membership-for-a-user +// +//meta:operation GET /orgs/{org}/members/{username} +func (s *OrganizationsService) IsMember(ctx context.Context, org, user string) (bool, *Response, error) { + u := fmt.Sprintf("orgs/%v/members/%v", org, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + member, err := parseBoolResponse(err) + return member, resp, err +} + +// IsPublicMember checks if a user is a public member of an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/members#check-public-organization-membership-for-a-user +// +//meta:operation GET /orgs/{org}/public_members/{username} +func (s *OrganizationsService) IsPublicMember(ctx context.Context, org, user string) (bool, *Response, error) { + u := fmt.Sprintf("orgs/%v/public_members/%v", org, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + member, err := parseBoolResponse(err) + return member, resp, err +} + +// RemoveMember removes a user from all teams of an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/members#remove-an-organization-member +// +//meta:operation DELETE /orgs/{org}/members/{username} +func (s *OrganizationsService) RemoveMember(ctx context.Context, org, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/members/%v", org, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// CancelInvite cancels an organization invitation. +// +// GitHub API docs: https://docs.github.com/rest/orgs/members#cancel-an-organization-invitation +// +//meta:operation DELETE /orgs/{org}/invitations/{invitation_id} +func (s *OrganizationsService) CancelInvite(ctx context.Context, org string, invitationID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/invitations/%v", org, invitationID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// PublicizeMembership publicizes a user's membership in an organization. (A +// user cannot publicize the membership for another user.) +// +// GitHub API docs: https://docs.github.com/rest/orgs/members#set-public-organization-membership-for-the-authenticated-user +// +//meta:operation PUT /orgs/{org}/public_members/{username} +func (s *OrganizationsService) PublicizeMembership(ctx context.Context, org, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/public_members/%v", org, user) + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ConcealMembership conceals a user's membership in an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/members#remove-public-organization-membership-for-the-authenticated-user +// +//meta:operation DELETE /orgs/{org}/public_members/{username} +func (s *OrganizationsService) ConcealMembership(ctx context.Context, org, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/public_members/%v", org, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListOrgMembershipsOptions specifies optional parameters to the +// OrganizationsService.ListOrgMemberships method. +type ListOrgMembershipsOptions struct { + // Filter memberships to include only those with the specified state. + // Possible values are: "active", "pending". + State string `url:"state,omitempty"` + + ListOptions +} + +// ListOrgMemberships lists the organization memberships for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/orgs/members#list-organization-memberships-for-the-authenticated-user +// +//meta:operation GET /user/memberships/orgs +func (s *OrganizationsService) ListOrgMemberships(ctx context.Context, opts *ListOrgMembershipsOptions) ([]*Membership, *Response, error) { + u := "user/memberships/orgs" + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var memberships []*Membership + resp, err := s.client.Do(ctx, req, &memberships) + if err != nil { + return nil, resp, err + } + + return memberships, resp, nil +} + +// GetOrgMembership gets the membership for a user in a specified organization. +// Passing an empty string for user will get the membership for the +// authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/orgs/members#get-an-organization-membership-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/rest/orgs/members#get-organization-membership-for-a-user +// +//meta:operation GET /orgs/{org}/memberships/{username} +//meta:operation GET /user/memberships/orgs/{org} +func (s *OrganizationsService) GetOrgMembership(ctx context.Context, user, org string) (*Membership, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("orgs/%v/memberships/%v", org, user) + } else { + u = fmt.Sprintf("user/memberships/orgs/%v", org) + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + membership := new(Membership) + resp, err := s.client.Do(ctx, req, membership) + if err != nil { + return nil, resp, err + } + + return membership, resp, nil +} + +// EditOrgMembership edits the membership for user in specified organization. +// Passing an empty string for user will edit the membership for the +// authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/orgs/members#set-organization-membership-for-a-user +// GitHub API docs: https://docs.github.com/rest/orgs/members#update-an-organization-membership-for-the-authenticated-user +// +//meta:operation PUT /orgs/{org}/memberships/{username} +//meta:operation PATCH /user/memberships/orgs/{org} +func (s *OrganizationsService) EditOrgMembership(ctx context.Context, user, org string, membership *Membership) (*Membership, *Response, error) { + var u, method string + if user != "" { + u = fmt.Sprintf("orgs/%v/memberships/%v", org, user) + method = "PUT" + } else { + u = fmt.Sprintf("user/memberships/orgs/%v", org) + method = "PATCH" + } + + req, err := s.client.NewRequest(method, u, membership) + if err != nil { + return nil, nil, err + } + + m := new(Membership) + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// RemoveOrgMembership removes user from the specified organization. If the +// user has been invited to the organization, this will cancel their invitation. +// +// GitHub API docs: https://docs.github.com/rest/orgs/members#remove-organization-membership-for-a-user +// +//meta:operation DELETE /orgs/{org}/memberships/{username} +func (s *OrganizationsService) RemoveOrgMembership(ctx context.Context, user, org string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/memberships/%v", org, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListPendingOrgInvitations returns a list of pending invitations. +// +// GitHub API docs: https://docs.github.com/rest/orgs/members#list-pending-organization-invitations +// +//meta:operation GET /orgs/{org}/invitations +func (s *OrganizationsService) ListPendingOrgInvitations(ctx context.Context, org string, opts *ListOptions) ([]*Invitation, *Response, error) { + u := fmt.Sprintf("orgs/%v/invitations", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pendingInvitations []*Invitation + resp, err := s.client.Do(ctx, req, &pendingInvitations) + if err != nil { + return nil, resp, err + } + + return pendingInvitations, resp, nil +} + +// CreateOrgInvitationOptions specifies the parameters to the OrganizationService.Invite +// method. +type CreateOrgInvitationOptions struct { + // GitHub user ID for the person you are inviting. Not required if you provide Email. + InviteeID *int64 `json:"invitee_id,omitempty"` + // Email address of the person you are inviting, which can be an existing GitHub user. + // Not required if you provide InviteeID + Email *string `json:"email,omitempty"` + // Specify role for new member. Can be one of: + // * admin - Organization owners with full administrative rights to the + // organization and complete access to all repositories and teams. + // * direct_member - Non-owner organization members with ability to see + // other members and join teams by invitation. + // * billing_manager - Non-owner organization members with ability to + // manage the billing settings of your organization. + // Default is "direct_member". + Role *string `json:"role,omitempty"` + TeamID []int64 `json:"team_ids,omitempty"` +} + +// CreateOrgInvitation invites people to an organization by using their GitHub user ID or their email address. +// In order to create invitations in an organization, +// the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/rest/orgs/members#create-an-organization-invitation +// +//meta:operation POST /orgs/{org}/invitations +func (s *OrganizationsService) CreateOrgInvitation(ctx context.Context, org string, opts *CreateOrgInvitationOptions) (*Invitation, *Response, error) { + u := fmt.Sprintf("orgs/%v/invitations", org) + + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + var invitation *Invitation + resp, err := s.client.Do(ctx, req, &invitation) + if err != nil { + return nil, resp, err + } + + return invitation, resp, nil +} + +// ListOrgInvitationTeams lists all teams associated with an invitation. In order to see invitations in an organization, +// the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/rest/orgs/members#list-organization-invitation-teams +// +//meta:operation GET /orgs/{org}/invitations/{invitation_id}/teams +func (s *OrganizationsService) ListOrgInvitationTeams(ctx context.Context, org, invitationID string, opts *ListOptions) ([]*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/invitations/%v/teams", org, invitationID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var orgInvitationTeams []*Team + resp, err := s.client.Do(ctx, req, &orgInvitationTeams) + if err != nil { + return nil, resp, err + } + + return orgInvitationTeams, resp, nil +} + +// ListFailedOrgInvitations returns a list of failed invitations. +// +// GitHub API docs: https://docs.github.com/rest/orgs/members#list-failed-organization-invitations +// +//meta:operation GET /orgs/{org}/failed_invitations +func (s *OrganizationsService) ListFailedOrgInvitations(ctx context.Context, org string, opts *ListOptions) ([]*Invitation, *Response, error) { + u := fmt.Sprintf("orgs/%v/failed_invitations", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var failedInvitations []*Invitation + resp, err := s.client.Do(ctx, req, &failedInvitations) + if err != nil { + return nil, resp, err + } + + return failedInvitations, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_organization_roles.go b/vendor/github.com/google/go-github/v68/github/orgs_organization_roles.go new file mode 100644 index 0000000000..0954b92d41 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_organization_roles.go @@ -0,0 +1,295 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// OrganizationCustomRoles represents custom organization roles available in specified organization. +type OrganizationCustomRoles struct { + TotalCount *int `json:"total_count,omitempty"` + CustomRepoRoles []*CustomOrgRoles `json:"roles,omitempty"` +} + +// CustomOrgRoles represents custom organization role available in specified organization. +type CustomOrgRoles struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + Permissions []string `json:"permissions,omitempty"` + Org *Organization `json:"organization,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Source *string `json:"source,omitempty"` + BaseRole *string `json:"base_role,omitempty"` +} + +// CreateOrUpdateOrgRoleOptions represents options required to create or update a custom organization role. +type CreateOrUpdateOrgRoleOptions struct { + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + Permissions []string `json:"permissions"` + BaseRole *string `json:"base_role,omitempty"` +} + +// ListRoles lists the custom roles available in this organization. +// In order to see custom roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#get-all-organization-roles-for-an-organization +// +//meta:operation GET /orgs/{org}/organization-roles +func (s *OrganizationsService) ListRoles(ctx context.Context, org string) (*OrganizationCustomRoles, *Response, error) { + u := fmt.Sprintf("orgs/%v/organization-roles", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + customRepoRoles := new(OrganizationCustomRoles) + resp, err := s.client.Do(ctx, req, customRepoRoles) + if err != nil { + return nil, resp, err + } + + return customRepoRoles, resp, nil +} + +// GetOrgRole gets an organization role in this organization. +// In order to get organization roles in an organization, the authenticated user must be an organization owner, or have access via an organization role. +// +// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#get-an-organization-role +// +//meta:operation GET /orgs/{org}/organization-roles/{role_id} +func (s *OrganizationsService) GetOrgRole(ctx context.Context, org string, roleID int64) (*CustomOrgRoles, *Response, error) { + u := fmt.Sprintf("orgs/%v/organization-roles/%v", org, roleID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + resultingRole := new(CustomOrgRoles) + resp, err := s.client.Do(ctx, req, resultingRole) + if err != nil { + return nil, resp, err + } + + return resultingRole, resp, err +} + +// CreateCustomOrgRole creates a custom role in this organization. +// In order to create custom roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/organization-roles#create-a-custom-organization-role +// +//meta:operation POST /orgs/{org}/organization-roles +func (s *OrganizationsService) CreateCustomOrgRole(ctx context.Context, org string, opts *CreateOrUpdateOrgRoleOptions) (*CustomOrgRoles, *Response, error) { + u := fmt.Sprintf("orgs/%v/organization-roles", org) + + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + resultingRole := new(CustomOrgRoles) + resp, err := s.client.Do(ctx, req, resultingRole) + if err != nil { + return nil, resp, err + } + + return resultingRole, resp, err +} + +// UpdateCustomOrgRole updates a custom role in this organization. +// In order to update custom roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/organization-roles#update-a-custom-organization-role +// +//meta:operation PATCH /orgs/{org}/organization-roles/{role_id} +func (s *OrganizationsService) UpdateCustomOrgRole(ctx context.Context, org string, roleID int64, opts *CreateOrUpdateOrgRoleOptions) (*CustomOrgRoles, *Response, error) { + u := fmt.Sprintf("orgs/%v/organization-roles/%v", org, roleID) + + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + resultingRole := new(CustomOrgRoles) + resp, err := s.client.Do(ctx, req, resultingRole) + if err != nil { + return nil, resp, err + } + + return resultingRole, resp, err +} + +// DeleteCustomOrgRole deletes an existing custom role in this organization. +// In order to delete custom roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/organization-roles#delete-a-custom-organization-role +// +//meta:operation DELETE /orgs/{org}/organization-roles/{role_id} +func (s *OrganizationsService) DeleteCustomOrgRole(ctx context.Context, org string, roleID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/organization-roles/%v", org, roleID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resultingRole := new(CustomOrgRoles) + resp, err := s.client.Do(ctx, req, resultingRole) + if err != nil { + return resp, err + } + + return resp, nil +} + +// AssignOrgRoleToTeam assigns an existing organization role to a team in this organization. +// In order to assign organization roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#assign-an-organization-role-to-a-team +// +//meta:operation PUT /orgs/{org}/organization-roles/teams/{team_slug}/{role_id} +func (s *OrganizationsService) AssignOrgRoleToTeam(ctx context.Context, org, teamSlug string, roleID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/organization-roles/teams/%v/%v", org, teamSlug, roleID) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// RemoveOrgRoleFromTeam removes an existing organization role assignment from a team in this organization. +// In order to remove organization role assignments in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#remove-an-organization-role-from-a-team +// +//meta:operation DELETE /orgs/{org}/organization-roles/teams/{team_slug}/{role_id} +func (s *OrganizationsService) RemoveOrgRoleFromTeam(ctx context.Context, org, teamSlug string, roleID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/organization-roles/teams/%v/%v", org, teamSlug, roleID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// AssignOrgRoleToUser assigns an existing organization role to a user in this organization. +// In order to assign organization roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#assign-an-organization-role-to-a-user +// +//meta:operation PUT /orgs/{org}/organization-roles/users/{username}/{role_id} +func (s *OrganizationsService) AssignOrgRoleToUser(ctx context.Context, org, username string, roleID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/organization-roles/users/%v/%v", org, username, roleID) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// RemoveOrgRoleFromUser removes an existing organization role assignment from a user in this organization. +// In order to remove organization role assignments in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#remove-an-organization-role-from-a-user +// +//meta:operation DELETE /orgs/{org}/organization-roles/users/{username}/{role_id} +func (s *OrganizationsService) RemoveOrgRoleFromUser(ctx context.Context, org, username string, roleID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/organization-roles/users/%v/%v", org, username, roleID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// ListTeamsAssignedToOrgRole returns all teams assigned to a specific organization role. +// In order to list teams assigned to an organization role, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#list-teams-that-are-assigned-to-an-organization-role +// +//meta:operation GET /orgs/{org}/organization-roles/{role_id}/teams +func (s *OrganizationsService) ListTeamsAssignedToOrgRole(ctx context.Context, org string, roleID int64, opts *ListOptions) ([]*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/organization-roles/%v/teams", org, roleID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// ListUsersAssignedToOrgRole returns all users assigned to a specific organization role. +// In order to list users assigned to an organization role, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#list-users-that-are-assigned-to-an-organization-role +// +//meta:operation GET /orgs/{org}/organization-roles/{role_id}/users +func (s *OrganizationsService) ListUsersAssignedToOrgRole(ctx context.Context, org string, roleID int64, opts *ListOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("orgs/%v/organization-roles/%v/users", org, roleID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var users []*User + resp, err := s.client.Do(ctx, req, &users) + if err != nil { + return nil, resp, err + } + + return users, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_outside_collaborators.go b/vendor/github.com/google/go-github/v68/github/orgs_outside_collaborators.go new file mode 100644 index 0000000000..56034d7260 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_outside_collaborators.go @@ -0,0 +1,87 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListOutsideCollaboratorsOptions specifies optional parameters to the +// OrganizationsService.ListOutsideCollaborators method. +type ListOutsideCollaboratorsOptions struct { + // Filter outside collaborators returned in the list. Possible values are: + // 2fa_disabled, all. Default is "all". + Filter string `url:"filter,omitempty"` + + ListOptions +} + +// ListOutsideCollaborators lists outside collaborators of organization's repositories. +// This will only work if the authenticated +// user is an owner of the organization. +// +// Warning: The API may change without advance notice during the preview period. +// Preview features are not supported for production use. +// +// GitHub API docs: https://docs.github.com/rest/orgs/outside-collaborators#list-outside-collaborators-for-an-organization +// +//meta:operation GET /orgs/{org}/outside_collaborators +func (s *OrganizationsService) ListOutsideCollaborators(ctx context.Context, org string, opts *ListOutsideCollaboratorsOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("orgs/%v/outside_collaborators", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var members []*User + resp, err := s.client.Do(ctx, req, &members) + if err != nil { + return nil, resp, err + } + + return members, resp, nil +} + +// RemoveOutsideCollaborator removes a user from the list of outside collaborators; +// consequently, removing them from all the organization's repositories. +// +// GitHub API docs: https://docs.github.com/rest/orgs/outside-collaborators#remove-outside-collaborator-from-an-organization +// +//meta:operation DELETE /orgs/{org}/outside_collaborators/{username} +func (s *OrganizationsService) RemoveOutsideCollaborator(ctx context.Context, org string, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/outside_collaborators/%v", org, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ConvertMemberToOutsideCollaborator reduces the permission level of a member of the +// organization to that of an outside collaborator. Therefore, they will only +// have access to the repositories that their current team membership allows. +// Responses for converting a non-member or the last owner to an outside collaborator +// are listed in GitHub API docs. +// +// GitHub API docs: https://docs.github.com/rest/orgs/outside-collaborators#convert-an-organization-member-to-outside-collaborator +// +//meta:operation PUT /orgs/{org}/outside_collaborators/{username} +func (s *OrganizationsService) ConvertMemberToOutsideCollaborator(ctx context.Context, org string, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/outside_collaborators/%v", org, user) + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_packages.go b/vendor/github.com/google/go-github/v68/github/orgs_packages.go new file mode 100644 index 0000000000..edd8e508fb --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_packages.go @@ -0,0 +1,180 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/url" +) + +// ListPackages lists the packages for an organization. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#list-packages-for-an-organization +// +//meta:operation GET /orgs/{org}/packages +func (s *OrganizationsService) ListPackages(ctx context.Context, org string, opts *PackageListOptions) ([]*Package, *Response, error) { + u := fmt.Sprintf("orgs/%v/packages", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var packages []*Package + resp, err := s.client.Do(ctx, req, &packages) + if err != nil { + return nil, resp, err + } + + return packages, resp, nil +} + +// GetPackage gets a package by name from an organization. +// +// Note that packageName is escaped for the URL path so that you don't need to. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#get-a-package-for-an-organization +// +//meta:operation GET /orgs/{org}/packages/{package_type}/{package_name} +func (s *OrganizationsService) GetPackage(ctx context.Context, org, packageType, packageName string) (*Package, *Response, error) { + u := fmt.Sprintf("orgs/%v/packages/%v/%v", org, packageType, url.PathEscape(packageName)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pack *Package + resp, err := s.client.Do(ctx, req, &pack) + if err != nil { + return nil, resp, err + } + + return pack, resp, nil +} + +// DeletePackage deletes a package from an organization. +// +// Note that packageName is escaped for the URL path so that you don't need to. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#delete-a-package-for-an-organization +// +//meta:operation DELETE /orgs/{org}/packages/{package_type}/{package_name} +func (s *OrganizationsService) DeletePackage(ctx context.Context, org, packageType, packageName string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/packages/%v/%v", org, packageType, url.PathEscape(packageName)) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RestorePackage restores a package to an organization. +// +// Note that packageName is escaped for the URL path so that you don't need to. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#restore-a-package-for-an-organization +// +//meta:operation POST /orgs/{org}/packages/{package_type}/{package_name}/restore +func (s *OrganizationsService) RestorePackage(ctx context.Context, org, packageType, packageName string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/packages/%v/%v/restore", org, packageType, url.PathEscape(packageName)) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// PackageGetAllVersions gets all versions of a package in an organization. +// +// Note that packageName is escaped for the URL path so that you don't need to. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#list-package-versions-for-a-package-owned-by-an-organization +// +//meta:operation GET /orgs/{org}/packages/{package_type}/{package_name}/versions +func (s *OrganizationsService) PackageGetAllVersions(ctx context.Context, org, packageType, packageName string, opts *PackageListOptions) ([]*PackageVersion, *Response, error) { + u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions", org, packageType, url.PathEscape(packageName)) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var versions []*PackageVersion + resp, err := s.client.Do(ctx, req, &versions) + if err != nil { + return nil, resp, err + } + + return versions, resp, nil +} + +// PackageGetVersion gets a specific version of a package in an organization. +// +// Note that packageName is escaped for the URL path so that you don't need to. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#get-a-package-version-for-an-organization +// +//meta:operation GET /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id} +func (s *OrganizationsService) PackageGetVersion(ctx context.Context, org, packageType, packageName string, packageVersionID int64) (*PackageVersion, *Response, error) { + u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions/%v", org, packageType, url.PathEscape(packageName), packageVersionID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var version *PackageVersion + resp, err := s.client.Do(ctx, req, &version) + if err != nil { + return nil, resp, err + } + + return version, resp, nil +} + +// PackageDeleteVersion deletes a package version from an organization. +// +// Note that packageName is escaped for the URL path so that you don't need to. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#delete-package-version-for-an-organization +// +//meta:operation DELETE /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id} +func (s *OrganizationsService) PackageDeleteVersion(ctx context.Context, org, packageType, packageName string, packageVersionID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions/%v", org, packageType, url.PathEscape(packageName), packageVersionID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// PackageRestoreVersion restores a package version to an organization. +// +// Note that packageName is escaped for the URL path so that you don't need to. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#restore-package-version-for-an-organization +// +//meta:operation POST /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}/restore +func (s *OrganizationsService) PackageRestoreVersion(ctx context.Context, org, packageType, packageName string, packageVersionID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions/%v/restore", org, packageType, url.PathEscape(packageName), packageVersionID) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_personal_access_tokens.go b/vendor/github.com/google/go-github/v68/github/orgs_personal_access_tokens.go new file mode 100644 index 0000000000..af083744e8 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_personal_access_tokens.go @@ -0,0 +1,167 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" + "net/url" + "strings" +) + +// PersonalAccessToken represents the minimal representation of an organization programmatic access grant. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/personal-access-tokens?apiVersion=2022-11-28 +type PersonalAccessToken struct { + // "Unique identifier of the fine-grained personal access token. + // The `pat_id` used to get details about an approved fine-grained personal access token. + ID *int64 `json:"id"` + + // Owner is the GitHub user associated with the token. + Owner *User `json:"owner"` + + // RepositorySelection is the type of repository selection requested. + // Possible values are: "none", "all", "subset". + RepositorySelection *string `json:"repository_selection"` + + // URL to the list of repositories the fine-grained personal access token can access. + // Only follow when `repository_selection` is `subset`. + RepositoriesURL *string `json:"repositories_url"` + + // Permissions are the permissions requested, categorized by type. + Permissions *PersonalAccessTokenPermissions `json:"permissions"` + + // Date and time when the fine-grained personal access token was approved to access the organization. + AccessGrantedAt *Timestamp `json:"access_granted_at"` + + // Whether the associated fine-grained personal access token has expired. + TokenExpired *bool `json:"token_expired"` + + // Date and time when the associated fine-grained personal access token expires. + TokenExpiresAt *Timestamp `json:"token_expires_at"` + + // Date and time when the associated fine-grained personal access token was last used for authentication. + TokenLastUsedAt *Timestamp `json:"token_last_used_at"` +} + +// ListFineGrainedPATOptions specifies optional parameters to ListFineGrainedPersonalAccessTokens. +type ListFineGrainedPATOptions struct { + // The property by which to sort the results. + // Default: created_at + // Value: created_at + Sort string `url:"sort,omitempty"` + + // The direction to sort the results by. + // Default: desc + // Value: asc, desc + Direction string `url:"direction,omitempty"` + + // A list of owner usernames to use to filter the results. + Owner []string `url:"-"` + + // The name of the repository to use to filter the results. + Repository string `url:"repository,omitempty"` + + // The permission to use to filter the results. + Permission string `url:"permission,omitempty"` + + // Only show fine-grained personal access tokens used before the given time. + // This is a timestamp in ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ. + LastUsedBefore string `url:"last_used_before,omitempty"` + + // Only show fine-grained personal access tokens used after the given time. + // This is a timestamp in ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ. + LastUsedAfter string `url:"last_used_after,omitempty"` + + ListOptions +} + +// ListFineGrainedPersonalAccessTokens lists approved fine-grained personal access tokens owned by organization members that can access organization resources. +// Only GitHub Apps can call this API, using the `Personal access tokens` organization permissions (read). +// +// GitHub API docs: https://docs.github.com/rest/orgs/personal-access-tokens#list-fine-grained-personal-access-tokens-with-access-to-organization-resources +// +//meta:operation GET /orgs/{org}/personal-access-tokens +func (s *OrganizationsService) ListFineGrainedPersonalAccessTokens(ctx context.Context, org string, opts *ListFineGrainedPATOptions) ([]*PersonalAccessToken, *Response, error) { + u := fmt.Sprintf("orgs/%v/personal-access-tokens", org) + // The `owner` parameter is a special case that uses the `owner[]=...` format and needs a custom function to format it correctly. + u, err := addListFineGrainedPATOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest(http.MethodGet, u, opts) + if err != nil { + return nil, nil, err + } + + var pats []*PersonalAccessToken + + resp, err := s.client.Do(ctx, req, &pats) + if err != nil { + return nil, resp, err + } + + return pats, resp, nil +} + +// ReviewPersonalAccessTokenRequestOptions specifies the parameters to the ReviewPersonalAccessTokenRequest method. +type ReviewPersonalAccessTokenRequestOptions struct { + Action string `json:"action"` + Reason *string `json:"reason,omitempty"` +} + +// ReviewPersonalAccessTokenRequest approves or denies a pending request to access organization resources via a fine-grained personal access token. +// Only GitHub Apps can call this API, using the `organization_personal_access_token_requests: write` permission. +// `action` can be one of `approve` or `deny`. +// +// GitHub API docs: https://docs.github.com/rest/orgs/personal-access-tokens#review-a-request-to-access-organization-resources-with-a-fine-grained-personal-access-token +// +//meta:operation POST /orgs/{org}/personal-access-token-requests/{pat_request_id} +func (s *OrganizationsService) ReviewPersonalAccessTokenRequest(ctx context.Context, org string, requestID int64, opts ReviewPersonalAccessTokenRequestOptions) (*Response, error) { + u := fmt.Sprintf("orgs/%v/personal-access-token-requests/%v", org, requestID) + + req, err := s.client.NewRequest(http.MethodPost, u, &opts) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// addListFineGrainedPATOptions adds the owner parameter to the URL query string with the correct format if it is set. +// +// GitHub API expects the owner parameter to be a list of strings in the `owner[]=...` format. +// For multiple owner values, the owner parameter is repeated in the query string. +// +// Example: +// owner[]=user1&owner[]=user2 +// This will filter the results to only include fine-grained personal access tokens owned by `user1` and `user2`. +// +// This function ensures the owner parameter is formatted correctly in the URL query string. +func addListFineGrainedPATOptions(s string, opts *ListFineGrainedPATOptions) (string, error) { + u, err := addOptions(s, opts) + if err != nil { + return s, err + } + + if len(opts.Owner) > 0 { + ownerVals := make([]string, len(opts.Owner)) + for i, owner := range opts.Owner { + ownerVals[i] = fmt.Sprintf("owner[]=%s", url.QueryEscape(owner)) + } + ownerQuery := strings.Join(ownerVals, "&") + + if strings.Contains(u, "?") { + u += "&" + ownerQuery + } else { + u += "?" + ownerQuery + } + } + + return u, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_properties.go b/vendor/github.com/google/go-github/v68/github/orgs_properties.go new file mode 100644 index 0000000000..f59d9f467e --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_properties.go @@ -0,0 +1,243 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "errors" + "fmt" +) + +// CustomProperty represents an organization custom property object. +type CustomProperty struct { + // PropertyName is required for most endpoints except when calling CreateOrUpdateCustomProperty; + // where this is sent in the path and thus can be omitted. + PropertyName *string `json:"property_name,omitempty"` + // SourceType is the source type of the property where it has been created. Can be one of: organization, enterprise. + SourceType *string `json:"source_type,omitempty"` + // The type of the value for the property. Can be one of: string, single_select, multi_select, true_false. + ValueType string `json:"value_type"` + // Whether the property is required. + Required *bool `json:"required,omitempty"` + // Default value of the property. + DefaultValue *string `json:"default_value,omitempty"` + // Short description of the property. + Description *string `json:"description,omitempty"` + // An ordered list of the allowed values of the property. The property can have up to 200 + // allowed values. + AllowedValues []string `json:"allowed_values,omitempty"` + // Who can edit the values of the property. Can be one of: org_actors, org_and_repo_actors, nil (null). + ValuesEditableBy *string `json:"values_editable_by,omitempty"` +} + +// RepoCustomPropertyValue represents a repository custom property value. +type RepoCustomPropertyValue struct { + RepositoryID int64 `json:"repository_id"` + RepositoryName string `json:"repository_name"` + RepositoryFullName string `json:"repository_full_name"` + Properties []*CustomPropertyValue `json:"properties"` +} + +// CustomPropertyValue represents a custom property value. +type CustomPropertyValue struct { + PropertyName string `json:"property_name"` + Value interface{} `json:"value"` +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +// This helps us handle the fact that Value can be either a string, []string, or nil. +func (cpv *CustomPropertyValue) UnmarshalJSON(data []byte) error { + type aliasCustomPropertyValue CustomPropertyValue + aux := &struct { + *aliasCustomPropertyValue + }{ + aliasCustomPropertyValue: (*aliasCustomPropertyValue)(cpv), + } + if err := json.Unmarshal(data, &aux); err != nil { + return err + } + + switch v := aux.Value.(type) { + case nil: + cpv.Value = nil + case string: + cpv.Value = v + case []interface{}: + strSlice := make([]string, len(v)) + for i, item := range v { + str, ok := item.(string) + if !ok { + return errors.New("non-string value in string array") + } + strSlice[i] = str + } + cpv.Value = strSlice + default: + return fmt.Errorf("unexpected value type: %T", v) + } + return nil +} + +// GetAllCustomProperties gets all custom properties that are defined for the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/custom-properties#get-all-custom-properties-for-an-organization +// +//meta:operation GET /orgs/{org}/properties/schema +func (s *OrganizationsService) GetAllCustomProperties(ctx context.Context, org string) ([]*CustomProperty, *Response, error) { + u := fmt.Sprintf("orgs/%v/properties/schema", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var customProperties []*CustomProperty + resp, err := s.client.Do(ctx, req, &customProperties) + if err != nil { + return nil, resp, err + } + + return customProperties, resp, nil +} + +// CreateOrUpdateCustomProperties creates new or updates existing custom properties that are defined for the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/custom-properties#create-or-update-custom-properties-for-an-organization +// +//meta:operation PATCH /orgs/{org}/properties/schema +func (s *OrganizationsService) CreateOrUpdateCustomProperties(ctx context.Context, org string, properties []*CustomProperty) ([]*CustomProperty, *Response, error) { + u := fmt.Sprintf("orgs/%v/properties/schema", org) + + params := struct { + Properties []*CustomProperty `json:"properties"` + }{ + Properties: properties, + } + + req, err := s.client.NewRequest("PATCH", u, params) + if err != nil { + return nil, nil, err + } + + var customProperties []*CustomProperty + resp, err := s.client.Do(ctx, req, &customProperties) + if err != nil { + return nil, resp, err + } + + return customProperties, resp, nil +} + +// GetCustomProperty gets a custom property that is defined for the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/custom-properties#get-a-custom-property-for-an-organization +// +//meta:operation GET /orgs/{org}/properties/schema/{custom_property_name} +func (s *OrganizationsService) GetCustomProperty(ctx context.Context, org, name string) (*CustomProperty, *Response, error) { + u := fmt.Sprintf("orgs/%v/properties/schema/%v", org, name) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var customProperty *CustomProperty + resp, err := s.client.Do(ctx, req, &customProperty) + if err != nil { + return nil, resp, err + } + + return customProperty, resp, nil +} + +// CreateOrUpdateCustomProperty creates a new or updates an existing custom property that is defined for the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/custom-properties#create-or-update-a-custom-property-for-an-organization +// +//meta:operation PUT /orgs/{org}/properties/schema/{custom_property_name} +func (s *OrganizationsService) CreateOrUpdateCustomProperty(ctx context.Context, org, customPropertyName string, property *CustomProperty) (*CustomProperty, *Response, error) { + u := fmt.Sprintf("orgs/%v/properties/schema/%v", org, customPropertyName) + + req, err := s.client.NewRequest("PUT", u, property) + if err != nil { + return nil, nil, err + } + + var customProperty *CustomProperty + resp, err := s.client.Do(ctx, req, &customProperty) + if err != nil { + return nil, resp, err + } + + return customProperty, resp, nil +} + +// RemoveCustomProperty removes a custom property that is defined for the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/custom-properties#remove-a-custom-property-for-an-organization +// +//meta:operation DELETE /orgs/{org}/properties/schema/{custom_property_name} +func (s *OrganizationsService) RemoveCustomProperty(ctx context.Context, org, customPropertyName string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/properties/schema/%v", org, customPropertyName) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListCustomPropertyValues lists all custom property values for repositories in the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/custom-properties#list-custom-property-values-for-organization-repositories +// +//meta:operation GET /orgs/{org}/properties/values +func (s *OrganizationsService) ListCustomPropertyValues(ctx context.Context, org string, opts *ListOptions) ([]*RepoCustomPropertyValue, *Response, error) { + u := fmt.Sprintf("orgs/%v/properties/values", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var repoCustomPropertyValues []*RepoCustomPropertyValue + resp, err := s.client.Do(ctx, req, &repoCustomPropertyValues) + if err != nil { + return nil, resp, err + } + + return repoCustomPropertyValues, resp, nil +} + +// CreateOrUpdateRepoCustomPropertyValues creates new or updates existing custom property values across multiple repositories for the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/custom-properties#create-or-update-custom-property-values-for-organization-repositories +// +//meta:operation PATCH /orgs/{org}/properties/values +func (s *OrganizationsService) CreateOrUpdateRepoCustomPropertyValues(ctx context.Context, org string, repoNames []string, properties []*CustomPropertyValue) (*Response, error) { + u := fmt.Sprintf("orgs/%v/properties/values", org) + + params := struct { + RepositoryNames []string `json:"repository_names"` + Properties []*CustomPropertyValue `json:"properties"` + }{ + RepositoryNames: repoNames, + Properties: properties, + } + + req, err := s.client.NewRequest("PATCH", u, params) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_rules.go b/vendor/github.com/google/go-github/v68/github/orgs_rules.go new file mode 100644 index 0000000000..37c06a7333 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_rules.go @@ -0,0 +1,115 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetAllOrganizationRulesets gets all the rulesets for the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/rules#get-all-organization-repository-rulesets +// +//meta:operation GET /orgs/{org}/rulesets +func (s *OrganizationsService) GetAllOrganizationRulesets(ctx context.Context, org string) ([]*Ruleset, *Response, error) { + u := fmt.Sprintf("orgs/%v/rulesets", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var rulesets []*Ruleset + resp, err := s.client.Do(ctx, req, &rulesets) + if err != nil { + return nil, resp, err + } + + return rulesets, resp, nil +} + +// CreateOrganizationRuleset creates a ruleset for the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/rules#create-an-organization-repository-ruleset +// +//meta:operation POST /orgs/{org}/rulesets +func (s *OrganizationsService) CreateOrganizationRuleset(ctx context.Context, org string, rs *Ruleset) (*Ruleset, *Response, error) { + u := fmt.Sprintf("orgs/%v/rulesets", org) + + req, err := s.client.NewRequest("POST", u, rs) + if err != nil { + return nil, nil, err + } + + var ruleset *Ruleset + resp, err := s.client.Do(ctx, req, &ruleset) + if err != nil { + return nil, resp, err + } + + return ruleset, resp, nil +} + +// GetOrganizationRuleset gets a ruleset from the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/rules#get-an-organization-repository-ruleset +// +//meta:operation GET /orgs/{org}/rulesets/{ruleset_id} +func (s *OrganizationsService) GetOrganizationRuleset(ctx context.Context, org string, rulesetID int64) (*Ruleset, *Response, error) { + u := fmt.Sprintf("orgs/%v/rulesets/%v", org, rulesetID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var ruleset *Ruleset + resp, err := s.client.Do(ctx, req, &ruleset) + if err != nil { + return nil, resp, err + } + + return ruleset, resp, nil +} + +// UpdateOrganizationRuleset updates a ruleset from the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/rules#update-an-organization-repository-ruleset +// +//meta:operation PUT /orgs/{org}/rulesets/{ruleset_id} +func (s *OrganizationsService) UpdateOrganizationRuleset(ctx context.Context, org string, rulesetID int64, rs *Ruleset) (*Ruleset, *Response, error) { + u := fmt.Sprintf("orgs/%v/rulesets/%v", org, rulesetID) + + req, err := s.client.NewRequest("PUT", u, rs) + if err != nil { + return nil, nil, err + } + + var ruleset *Ruleset + resp, err := s.client.Do(ctx, req, &ruleset) + if err != nil { + return nil, resp, err + } + + return ruleset, resp, nil +} + +// DeleteOrganizationRuleset deletes a ruleset from the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/rules#delete-an-organization-repository-ruleset +// +//meta:operation DELETE /orgs/{org}/rulesets/{ruleset_id} +func (s *OrganizationsService) DeleteOrganizationRuleset(ctx context.Context, org string, rulesetID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/rulesets/%v", org, rulesetID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_security_managers.go b/vendor/github.com/google/go-github/v68/github/orgs_security_managers.go new file mode 100644 index 0000000000..0803772732 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_security_managers.go @@ -0,0 +1,63 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListSecurityManagerTeams lists all security manager teams for an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/security-managers#list-security-manager-teams +// +//meta:operation GET /orgs/{org}/security-managers +func (s *OrganizationsService) ListSecurityManagerTeams(ctx context.Context, org string) ([]*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/security-managers", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// AddSecurityManagerTeam adds a team to the list of security managers for an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/security-managers#add-a-security-manager-team +// +//meta:operation PUT /orgs/{org}/security-managers/teams/{team_slug} +func (s *OrganizationsService) AddSecurityManagerTeam(ctx context.Context, org, team string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/security-managers/teams/%v", org, team) + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveSecurityManagerTeam removes a team from the list of security managers for an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/security-managers#remove-a-security-manager-team +// +//meta:operation DELETE /orgs/{org}/security-managers/teams/{team_slug} +func (s *OrganizationsService) RemoveSecurityManagerTeam(ctx context.Context, org, team string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/security-managers/teams/%v", org, team) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_users_blocking.go b/vendor/github.com/google/go-github/v68/github/orgs_users_blocking.go new file mode 100644 index 0000000000..62bd9116cd --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_users_blocking.go @@ -0,0 +1,99 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListBlockedUsers lists all the users blocked by an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/blocking#list-users-blocked-by-an-organization +// +//meta:operation GET /orgs/{org}/blocks +func (s *OrganizationsService) ListBlockedUsers(ctx context.Context, org string, opts *ListOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("orgs/%v/blocks", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + var blockedUsers []*User + resp, err := s.client.Do(ctx, req, &blockedUsers) + if err != nil { + return nil, resp, err + } + + return blockedUsers, resp, nil +} + +// IsBlocked reports whether specified user is blocked from an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/blocking#check-if-a-user-is-blocked-by-an-organization +// +//meta:operation GET /orgs/{org}/blocks/{username} +func (s *OrganizationsService) IsBlocked(ctx context.Context, org string, user string) (bool, *Response, error) { + u := fmt.Sprintf("orgs/%v/blocks/%v", org, user) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + resp, err := s.client.Do(ctx, req, nil) + isBlocked, err := parseBoolResponse(err) + return isBlocked, resp, err +} + +// BlockUser blocks specified user from an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/blocking#block-a-user-from-an-organization +// +//meta:operation PUT /orgs/{org}/blocks/{username} +func (s *OrganizationsService) BlockUser(ctx context.Context, org string, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/blocks/%v", org, user) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + return s.client.Do(ctx, req, nil) +} + +// UnblockUser unblocks specified user from an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/blocking#unblock-a-user-from-an-organization +// +//meta:operation DELETE /orgs/{org}/blocks/{username} +func (s *OrganizationsService) UnblockUser(ctx context.Context, org string, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/blocks/%v", org, user) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/packages.go b/vendor/github.com/google/go-github/v68/github/packages.go new file mode 100644 index 0000000000..ef7df07405 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/packages.go @@ -0,0 +1,143 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +// Package represents a GitHub package. +type Package struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + PackageType *string `json:"package_type,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Owner *User `json:"owner,omitempty"` + PackageVersion *PackageVersion `json:"package_version,omitempty"` + Registry *PackageRegistry `json:"registry,omitempty"` + URL *string `json:"url,omitempty"` + VersionCount *int64 `json:"version_count,omitempty"` + Visibility *string `json:"visibility,omitempty"` + Repository *Repository `json:"repository,omitempty"` +} + +func (p Package) String() string { + return Stringify(p) +} + +// PackageVersion represents a GitHub package version. +type PackageVersion struct { + ID *int64 `json:"id,omitempty"` + Version *string `json:"version,omitempty"` + Summary *string `json:"summary,omitempty"` + Body *string `json:"body,omitempty"` + BodyHTML *string `json:"body_html,omitempty"` + Release *PackageRelease `json:"release,omitempty"` + Manifest *string `json:"manifest,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + TagName *string `json:"tag_name,omitempty"` + TargetCommitish *string `json:"target_commitish,omitempty"` + TargetOID *string `json:"target_oid,omitempty"` + Draft *bool `json:"draft,omitempty"` + Prerelease *bool `json:"prerelease,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + PackageFiles []*PackageFile `json:"package_files,omitempty"` + Author *User `json:"author,omitempty"` + InstallationCommand *string `json:"installation_command,omitempty"` + Metadata *PackageMetadata `json:"metadata,omitempty"` + PackageHTMLURL *string `json:"package_html_url,omitempty"` + Name *string `json:"name,omitempty"` + URL *string `json:"url,omitempty"` +} + +func (pv PackageVersion) String() string { + return Stringify(pv) +} + +// PackageRelease represents a GitHub package version release. +type PackageRelease struct { + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + ID *int64 `json:"id,omitempty"` + TagName *string `json:"tag_name,omitempty"` + TargetCommitish *string `json:"target_commitish,omitempty"` + Name *string `json:"name,omitempty"` + Draft *bool `json:"draft,omitempty"` + Author *User `json:"author,omitempty"` + Prerelease *bool `json:"prerelease,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + PublishedAt *Timestamp `json:"published_at,omitempty"` +} + +func (r PackageRelease) String() string { + return Stringify(r) +} + +// PackageFile represents a GitHub package version release file. +type PackageFile struct { + DownloadURL *string `json:"download_url,omitempty"` + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + SHA256 *string `json:"sha256,omitempty"` + SHA1 *string `json:"sha1,omitempty"` + MD5 *string `json:"md5,omitempty"` + ContentType *string `json:"content_type,omitempty"` + State *string `json:"state,omitempty"` + Author *User `json:"author,omitempty"` + Size *int64 `json:"size,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +func (pf PackageFile) String() string { + return Stringify(pf) +} + +// PackageRegistry represents a GitHub package registry. +type PackageRegistry struct { + AboutURL *string `json:"about_url,omitempty"` + Name *string `json:"name,omitempty"` + Type *string `json:"type,omitempty"` + URL *string `json:"url,omitempty"` + Vendor *string `json:"vendor,omitempty"` +} + +func (r PackageRegistry) String() string { + return Stringify(r) +} + +// PackageListOptions represents the optional list options for a package. +type PackageListOptions struct { + // Visibility of packages "public", "internal" or "private". + Visibility *string `url:"visibility,omitempty"` + + // PackageType represents the type of package. + // It can be one of "npm", "maven", "rubygems", "nuget", "docker", or "container". + PackageType *string `url:"package_type,omitempty"` + + // State of package either "active" or "deleted". + State *string `url:"state,omitempty"` + + ListOptions +} + +// PackageMetadata represents metadata from a package. +type PackageMetadata struct { + PackageType *string `json:"package_type,omitempty"` + Container *PackageContainerMetadata `json:"container,omitempty"` +} + +func (r PackageMetadata) String() string { + return Stringify(r) +} + +// PackageContainerMetadata represents container metadata for docker container packages. +type PackageContainerMetadata struct { + Tags []string `json:"tags,omitempty"` +} + +func (r PackageContainerMetadata) String() string { + return Stringify(r) +} diff --git a/vendor/github.com/google/go-github/v68/github/pulls.go b/vendor/github.com/google/go-github/v68/github/pulls.go new file mode 100644 index 0000000000..35ceda4467 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/pulls.go @@ -0,0 +1,516 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "context" + "errors" + "fmt" +) + +// PullRequestsService handles communication with the pull request related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/pulls/ +type PullRequestsService service + +// PullRequestAutoMerge represents the "auto_merge" response for a PullRequest. +type PullRequestAutoMerge struct { + EnabledBy *User `json:"enabled_by,omitempty"` + MergeMethod *string `json:"merge_method,omitempty"` + CommitTitle *string `json:"commit_title,omitempty"` + CommitMessage *string `json:"commit_message,omitempty"` +} + +// PullRequest represents a GitHub pull request on a repository. +type PullRequest struct { + ID *int64 `json:"id,omitempty"` + Number *int `json:"number,omitempty"` + State *string `json:"state,omitempty"` + Locked *bool `json:"locked,omitempty"` + Title *string `json:"title,omitempty"` + Body *string `json:"body,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + ClosedAt *Timestamp `json:"closed_at,omitempty"` + MergedAt *Timestamp `json:"merged_at,omitempty"` + Labels []*Label `json:"labels,omitempty"` + User *User `json:"user,omitempty"` + Draft *bool `json:"draft,omitempty"` + Merged *bool `json:"merged,omitempty"` + Mergeable *bool `json:"mergeable,omitempty"` + MergeableState *string `json:"mergeable_state,omitempty"` + MergedBy *User `json:"merged_by,omitempty"` + MergeCommitSHA *string `json:"merge_commit_sha,omitempty"` + Rebaseable *bool `json:"rebaseable,omitempty"` + Comments *int `json:"comments,omitempty"` + Commits *int `json:"commits,omitempty"` + Additions *int `json:"additions,omitempty"` + Deletions *int `json:"deletions,omitempty"` + ChangedFiles *int `json:"changed_files,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + IssueURL *string `json:"issue_url,omitempty"` + StatusesURL *string `json:"statuses_url,omitempty"` + DiffURL *string `json:"diff_url,omitempty"` + PatchURL *string `json:"patch_url,omitempty"` + CommitsURL *string `json:"commits_url,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + ReviewCommentsURL *string `json:"review_comments_url,omitempty"` + ReviewCommentURL *string `json:"review_comment_url,omitempty"` + ReviewComments *int `json:"review_comments,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Assignees []*User `json:"assignees,omitempty"` + Milestone *Milestone `json:"milestone,omitempty"` + MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` + AuthorAssociation *string `json:"author_association,omitempty"` + NodeID *string `json:"node_id,omitempty"` + RequestedReviewers []*User `json:"requested_reviewers,omitempty"` + AutoMerge *PullRequestAutoMerge `json:"auto_merge,omitempty"` + + // RequestedTeams is populated as part of the PullRequestEvent. + // See, https://docs.github.com/developers/webhooks-and-events/github-event-types#pullrequestevent for an example. + RequestedTeams []*Team `json:"requested_teams,omitempty"` + + Links *PRLinks `json:"_links,omitempty"` + Head *PullRequestBranch `json:"head,omitempty"` + Base *PullRequestBranch `json:"base,omitempty"` + + // ActiveLockReason is populated only when LockReason is provided while locking the pull request. + // Possible values are: "off-topic", "too heated", "resolved", and "spam". + ActiveLockReason *string `json:"active_lock_reason,omitempty"` +} + +func (p PullRequest) String() string { + return Stringify(p) +} + +// PRLink represents a single link object from GitHub pull request _links. +type PRLink struct { + HRef *string `json:"href,omitempty"` +} + +// PRLinks represents the "_links" object in a GitHub pull request. +type PRLinks struct { + Self *PRLink `json:"self,omitempty"` + HTML *PRLink `json:"html,omitempty"` + Issue *PRLink `json:"issue,omitempty"` + Comments *PRLink `json:"comments,omitempty"` + ReviewComments *PRLink `json:"review_comments,omitempty"` + ReviewComment *PRLink `json:"review_comment,omitempty"` + Commits *PRLink `json:"commits,omitempty"` + Statuses *PRLink `json:"statuses,omitempty"` +} + +// PullRequestBranch represents a base or head branch in a GitHub pull request. +type PullRequestBranch struct { + Label *string `json:"label,omitempty"` + Ref *string `json:"ref,omitempty"` + SHA *string `json:"sha,omitempty"` + Repo *Repository `json:"repo,omitempty"` + User *User `json:"user,omitempty"` +} + +// PullRequestListOptions specifies the optional parameters to the +// PullRequestsService.List method. +type PullRequestListOptions struct { + // State filters pull requests based on their state. Possible values are: + // open, closed, all. Default is "open". + State string `url:"state,omitempty"` + + // Head filters pull requests by head user and branch name in the format of: + // "user:ref-name". + Head string `url:"head,omitempty"` + + // Base filters pull requests by base branch name. + Base string `url:"base,omitempty"` + + // Sort specifies how to sort pull requests. Possible values are: created, + // updated, popularity, long-running. Default is "created". + Sort string `url:"sort,omitempty"` + + // Direction in which to sort pull requests. Possible values are: asc, desc. + // If Sort is "created" or not specified, Default is "desc", otherwise Default + // is "asc" + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// List the pull requests for the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/pulls/pulls#list-pull-requests +// +//meta:operation GET /repos/{owner}/{repo}/pulls +func (s *PullRequestsService) List(ctx context.Context, owner string, repo string, opts *PullRequestListOptions) ([]*PullRequest, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pulls []*PullRequest + resp, err := s.client.Do(ctx, req, &pulls) + if err != nil { + return nil, resp, err + } + + return pulls, resp, nil +} + +// ListPullRequestsWithCommit returns pull requests associated with a commit SHA. +// +// The results may include open and closed pull requests. +// By default, the PullRequestListOptions State filters for "open". +// +// GitHub API docs: https://docs.github.com/rest/commits/commits#list-pull-requests-associated-with-a-commit +// +//meta:operation GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls +func (s *PullRequestsService) ListPullRequestsWithCommit(ctx context.Context, owner, repo, sha string, opts *ListOptions) ([]*PullRequest, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/pulls", owner, repo, sha) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeListPullsOrBranchesForCommitPreview) + var pulls []*PullRequest + resp, err := s.client.Do(ctx, req, &pulls) + if err != nil { + return nil, resp, err + } + + return pulls, resp, nil +} + +// Get a single pull request. +// +// GitHub API docs: https://docs.github.com/rest/pulls/pulls#get-a-pull-request +// +//meta:operation GET /repos/{owner}/{repo}/pulls/{pull_number} +func (s *PullRequestsService) Get(ctx context.Context, owner string, repo string, number int) (*PullRequest, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + pull := new(PullRequest) + resp, err := s.client.Do(ctx, req, pull) + if err != nil { + return nil, resp, err + } + + return pull, resp, nil +} + +// GetRaw gets a single pull request in raw (diff or patch) format. +// +// GitHub API docs: https://docs.github.com/rest/pulls/pulls#get-a-pull-request +// +//meta:operation GET /repos/{owner}/{repo}/pulls/{pull_number} +func (s *PullRequestsService) GetRaw(ctx context.Context, owner string, repo string, number int, opts RawOptions) (string, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return "", nil, err + } + + switch opts.Type { + case Diff: + req.Header.Set("Accept", mediaTypeV3Diff) + case Patch: + req.Header.Set("Accept", mediaTypeV3Patch) + default: + return "", nil, fmt.Errorf("unsupported raw type %d", opts.Type) + } + + var buf bytes.Buffer + resp, err := s.client.Do(ctx, req, &buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// NewPullRequest represents a new pull request to be created. +type NewPullRequest struct { + Title *string `json:"title,omitempty"` + // The name of the branch where your changes are implemented. For + // cross-repository pull requests in the same network, namespace head with + // a user like this: username:branch. + Head *string `json:"head,omitempty"` + HeadRepo *string `json:"head_repo,omitempty"` + // The name of the branch you want the changes pulled into. This should be + // an existing branch on the current repository. You cannot submit a pull + // request to one repository that requests a merge to a base of another + // repository. + Base *string `json:"base,omitempty"` + Body *string `json:"body,omitempty"` + Issue *int `json:"issue,omitempty"` + MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` + Draft *bool `json:"draft,omitempty"` +} + +// Create a new pull request on the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/pulls/pulls#create-a-pull-request +// +//meta:operation POST /repos/{owner}/{repo}/pulls +func (s *PullRequestsService) Create(ctx context.Context, owner string, repo string, pull *NewPullRequest) (*PullRequest, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls", owner, repo) + req, err := s.client.NewRequest("POST", u, pull) + if err != nil { + return nil, nil, err + } + + p := new(PullRequest) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// PullRequestBranchUpdateOptions specifies the optional parameters to the +// PullRequestsService.UpdateBranch method. +type PullRequestBranchUpdateOptions struct { + // ExpectedHeadSHA specifies the most recent commit on the pull request's branch. + // Default value is the SHA of the pull request's current HEAD ref. + ExpectedHeadSHA *string `json:"expected_head_sha,omitempty"` +} + +// PullRequestBranchUpdateResponse specifies the response of pull request branch update. +type PullRequestBranchUpdateResponse struct { + Message *string `json:"message,omitempty"` + URL *string `json:"url,omitempty"` +} + +// UpdateBranch updates the pull request branch with latest upstream changes. +// +// This method might return an AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it has now scheduled the update of the pull request branch in a background task. +// A follow up request, after a delay of a second or so, should result +// in a successful request. +// +// GitHub API docs: https://docs.github.com/rest/pulls/pulls#update-a-pull-request-branch +// +//meta:operation PUT /repos/{owner}/{repo}/pulls/{pull_number}/update-branch +func (s *PullRequestsService) UpdateBranch(ctx context.Context, owner, repo string, number int, opts *PullRequestBranchUpdateOptions) (*PullRequestBranchUpdateResponse, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/update-branch", owner, repo, number) + + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeUpdatePullRequestBranchPreview) + + p := new(PullRequestBranchUpdateResponse) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +type pullRequestUpdate struct { + Title *string `json:"title,omitempty"` + Body *string `json:"body,omitempty"` + State *string `json:"state,omitempty"` + Base *string `json:"base,omitempty"` + MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` +} + +// Edit a pull request. +// pull must not be nil. +// +// The following fields are editable: Title, Body, State, Base.Ref and MaintainerCanModify. +// Base.Ref updates the base branch of the pull request. +// +// GitHub API docs: https://docs.github.com/rest/pulls/pulls#update-a-pull-request +// +//meta:operation PATCH /repos/{owner}/{repo}/pulls/{pull_number} +func (s *PullRequestsService) Edit(ctx context.Context, owner string, repo string, number int, pull *PullRequest) (*PullRequest, *Response, error) { + if pull == nil { + return nil, nil, errors.New("pull must be provided") + } + + u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number) + + update := &pullRequestUpdate{ + Title: pull.Title, + Body: pull.Body, + State: pull.State, + MaintainerCanModify: pull.MaintainerCanModify, + } + // avoid updating the base branch when closing the Pull Request + // - otherwise the GitHub API server returns a "Validation Failed" error: + // "Cannot change base branch of closed pull request". + if pull.Base != nil && pull.GetState() != "closed" { + update.Base = pull.Base.Ref + } + + req, err := s.client.NewRequest("PATCH", u, update) + if err != nil { + return nil, nil, err + } + + p := new(PullRequest) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// ListCommits lists the commits in a pull request. +// +// GitHub API docs: https://docs.github.com/rest/pulls/pulls#list-commits-on-a-pull-request +// +//meta:operation GET /repos/{owner}/{repo}/pulls/{pull_number}/commits +func (s *PullRequestsService) ListCommits(ctx context.Context, owner string, repo string, number int, opts *ListOptions) ([]*RepositoryCommit, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/commits", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var commits []*RepositoryCommit + resp, err := s.client.Do(ctx, req, &commits) + if err != nil { + return nil, resp, err + } + + return commits, resp, nil +} + +// ListFiles lists the files in a pull request. +// +// GitHub API docs: https://docs.github.com/rest/pulls/pulls#list-pull-requests-files +// +//meta:operation GET /repos/{owner}/{repo}/pulls/{pull_number}/files +func (s *PullRequestsService) ListFiles(ctx context.Context, owner string, repo string, number int, opts *ListOptions) ([]*CommitFile, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/files", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var commitFiles []*CommitFile + resp, err := s.client.Do(ctx, req, &commitFiles) + if err != nil { + return nil, resp, err + } + + return commitFiles, resp, nil +} + +// IsMerged checks if a pull request has been merged. +// +// GitHub API docs: https://docs.github.com/rest/pulls/pulls#check-if-a-pull-request-has-been-merged +// +//meta:operation GET /repos/{owner}/{repo}/pulls/{pull_number}/merge +func (s *PullRequestsService) IsMerged(ctx context.Context, owner string, repo string, number int) (bool, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/merge", owner, repo, number) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + merged, err := parseBoolResponse(err) + return merged, resp, err +} + +// PullRequestMergeResult represents the result of merging a pull request. +type PullRequestMergeResult struct { + SHA *string `json:"sha,omitempty"` + Merged *bool `json:"merged,omitempty"` + Message *string `json:"message,omitempty"` +} + +// PullRequestOptions lets you define how a pull request will be merged. +type PullRequestOptions struct { + CommitTitle string // Title for the automatic commit message. (Optional.) + SHA string // SHA that pull request head must match to allow merge. (Optional.) + + // The merge method to use. Possible values include: "merge", "squash", and "rebase" with the default being merge. (Optional.) + MergeMethod string + + // If false, an empty string commit message will use the default commit message. If true, an empty string commit message will be used. + DontDefaultIfBlank bool +} + +type pullRequestMergeRequest struct { + CommitMessage *string `json:"commit_message,omitempty"` + CommitTitle string `json:"commit_title,omitempty"` + MergeMethod string `json:"merge_method,omitempty"` + SHA string `json:"sha,omitempty"` +} + +// Merge a pull request. +// commitMessage is an extra detail to append to automatic commit message. +// +// GitHub API docs: https://docs.github.com/rest/pulls/pulls#merge-a-pull-request +// +//meta:operation PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge +func (s *PullRequestsService) Merge(ctx context.Context, owner string, repo string, number int, commitMessage string, options *PullRequestOptions) (*PullRequestMergeResult, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/merge", owner, repo, number) + + pullRequestBody := &pullRequestMergeRequest{} + if commitMessage != "" { + pullRequestBody.CommitMessage = &commitMessage + } + if options != nil { + pullRequestBody.CommitTitle = options.CommitTitle + pullRequestBody.MergeMethod = options.MergeMethod + pullRequestBody.SHA = options.SHA + if options.DontDefaultIfBlank && commitMessage == "" { + pullRequestBody.CommitMessage = &commitMessage + } + } + req, err := s.client.NewRequest("PUT", u, pullRequestBody) + if err != nil { + return nil, nil, err + } + + mergeResult := new(PullRequestMergeResult) + resp, err := s.client.Do(ctx, req, mergeResult) + if err != nil { + return nil, resp, err + } + + return mergeResult, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/pulls_comments.go b/vendor/github.com/google/go-github/v68/github/pulls_comments.go new file mode 100644 index 0000000000..a9ffe8d7cc --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/pulls_comments.go @@ -0,0 +1,217 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "strings" + "time" +) + +// PullRequestComment represents a comment left on a pull request. +type PullRequestComment struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + InReplyTo *int64 `json:"in_reply_to_id,omitempty"` + Body *string `json:"body,omitempty"` + Path *string `json:"path,omitempty"` + DiffHunk *string `json:"diff_hunk,omitempty"` + PullRequestReviewID *int64 `json:"pull_request_review_id,omitempty"` + Position *int `json:"position,omitempty"` + OriginalPosition *int `json:"original_position,omitempty"` + StartLine *int `json:"start_line,omitempty"` + Line *int `json:"line,omitempty"` + OriginalLine *int `json:"original_line,omitempty"` + OriginalStartLine *int `json:"original_start_line,omitempty"` + Side *string `json:"side,omitempty"` + StartSide *string `json:"start_side,omitempty"` + CommitID *string `json:"commit_id,omitempty"` + OriginalCommitID *string `json:"original_commit_id,omitempty"` + User *User `json:"user,omitempty"` + Reactions *Reactions `json:"reactions,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + // AuthorAssociation is the comment author's relationship to the pull request's repository. + // Possible values are "COLLABORATOR", "CONTRIBUTOR", "FIRST_TIMER", "FIRST_TIME_CONTRIBUTOR", "MEMBER", "OWNER", or "NONE". + AuthorAssociation *string `json:"author_association,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + PullRequestURL *string `json:"pull_request_url,omitempty"` + // Can be one of: LINE, FILE from https://docs.github.com/rest/pulls/comments#create-a-review-comment-for-a-pull-request + SubjectType *string `json:"subject_type,omitempty"` +} + +func (p PullRequestComment) String() string { + return Stringify(p) +} + +// PullRequestListCommentsOptions specifies the optional parameters to the +// PullRequestsService.ListComments method. +type PullRequestListCommentsOptions struct { + // Sort specifies how to sort comments. Possible values are: created, updated. + Sort string `url:"sort,omitempty"` + + // Direction in which to sort comments. Possible values are: asc, desc. + Direction string `url:"direction,omitempty"` + + // Since filters comments by time. + Since time.Time `url:"since,omitempty"` + + ListOptions +} + +// ListComments lists all comments on the specified pull request. Specifying a +// pull request number of 0 will return all comments on all pull requests for +// the repository. +// +// GitHub API docs: https://docs.github.com/rest/pulls/comments#list-review-comments-in-a-repository +// GitHub API docs: https://docs.github.com/rest/pulls/comments#list-review-comments-on-a-pull-request +// +//meta:operation GET /repos/{owner}/{repo}/pulls/comments +//meta:operation GET /repos/{owner}/{repo}/pulls/{pull_number}/comments +func (s *PullRequestsService) ListComments(ctx context.Context, owner, repo string, number int, opts *PullRequestListCommentsOptions) ([]*PullRequestComment, *Response, error) { + var u string + if number == 0 { + u = fmt.Sprintf("repos/%v/%v/pulls/comments", owner, repo) + } else { + u = fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number) + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeMultiLineCommentsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var comments []*PullRequestComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// GetComment fetches the specified pull request comment. +// +// GitHub API docs: https://docs.github.com/rest/pulls/comments#get-a-review-comment-for-a-pull-request +// +//meta:operation GET /repos/{owner}/{repo}/pulls/comments/{comment_id} +func (s *PullRequestsService) GetComment(ctx context.Context, owner, repo string, commentID int64) (*PullRequestComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeMultiLineCommentsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + comment := new(PullRequestComment) + resp, err := s.client.Do(ctx, req, comment) + if err != nil { + return nil, resp, err + } + + return comment, resp, nil +} + +// CreateComment creates a new comment on the specified pull request. +// +// GitHub API docs: https://docs.github.com/rest/pulls/comments#create-a-review-comment-for-a-pull-request +// +//meta:operation POST /repos/{owner}/{repo}/pulls/{pull_number}/comments +func (s *PullRequestsService) CreateComment(ctx context.Context, owner, repo string, number int, comment *PullRequestComment) (*PullRequestComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number) + req, err := s.client.NewRequest("POST", u, comment) + if err != nil { + return nil, nil, err + } + // TODO: remove custom Accept headers when their respective API fully launches. + acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeMultiLineCommentsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + c := new(PullRequestComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// CreateCommentInReplyTo creates a new comment as a reply to an existing pull request comment. +// +// GitHub API docs: https://docs.github.com/rest/pulls/comments#create-a-review-comment-for-a-pull-request +// +//meta:operation POST /repos/{owner}/{repo}/pulls/{pull_number}/comments +func (s *PullRequestsService) CreateCommentInReplyTo(ctx context.Context, owner, repo string, number int, body string, commentID int64) (*PullRequestComment, *Response, error) { + comment := &struct { + Body string `json:"body,omitempty"` + InReplyTo int64 `json:"in_reply_to,omitempty"` + }{ + Body: body, + InReplyTo: commentID, + } + u := fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number) + req, err := s.client.NewRequest("POST", u, comment) + if err != nil { + return nil, nil, err + } + + c := new(PullRequestComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// EditComment updates a pull request comment. +// A non-nil comment.Body must be provided. Other comment fields should be left nil. +// +// GitHub API docs: https://docs.github.com/rest/pulls/comments#update-a-review-comment-for-a-pull-request +// +//meta:operation PATCH /repos/{owner}/{repo}/pulls/comments/{comment_id} +func (s *PullRequestsService) EditComment(ctx context.Context, owner, repo string, commentID int64, comment *PullRequestComment) (*PullRequestComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID) + req, err := s.client.NewRequest("PATCH", u, comment) + if err != nil { + return nil, nil, err + } + + c := new(PullRequestComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// DeleteComment deletes a pull request comment. +// +// GitHub API docs: https://docs.github.com/rest/pulls/comments#delete-a-review-comment-for-a-pull-request +// +//meta:operation DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id} +func (s *PullRequestsService) DeleteComment(ctx context.Context, owner, repo string, commentID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/pulls_reviewers.go b/vendor/github.com/google/go-github/v68/github/pulls_reviewers.go new file mode 100644 index 0000000000..9dd60ae688 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/pulls_reviewers.go @@ -0,0 +1,106 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ReviewersRequest specifies users and teams for a pull request review request. +type ReviewersRequest struct { + NodeID *string `json:"node_id,omitempty"` + Reviewers []string `json:"reviewers,omitempty"` + TeamReviewers []string `json:"team_reviewers,omitempty"` +} + +// Reviewers represents reviewers of a pull request. +type Reviewers struct { + Users []*User `json:"users,omitempty"` + Teams []*Team `json:"teams,omitempty"` +} + +type removeReviewersRequest struct { + NodeID *string `json:"node_id,omitempty"` + // Note the lack of omitempty! See comment in RemoveReviewers. + Reviewers []string `json:"reviewers"` + TeamReviewers []string `json:"team_reviewers,omitempty"` +} + +// RequestReviewers creates a review request for the provided reviewers for the specified pull request. +// +// GitHub API docs: https://docs.github.com/rest/pulls/review-requests#request-reviewers-for-a-pull-request +// +//meta:operation POST /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers +func (s *PullRequestsService) RequestReviewers(ctx context.Context, owner, repo string, number int, reviewers ReviewersRequest) (*PullRequest, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, number) + req, err := s.client.NewRequest("POST", u, &reviewers) + if err != nil { + return nil, nil, err + } + + r := new(PullRequest) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// ListReviewers lists reviewers whose reviews have been requested on the specified pull request. +// +// GitHub API docs: https://docs.github.com/rest/pulls/review-requests#get-all-requested-reviewers-for-a-pull-request +// +//meta:operation GET /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers +func (s *PullRequestsService) ListReviewers(ctx context.Context, owner, repo string, number int, opts *ListOptions) (*Reviewers, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/requested_reviewers", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + reviewers := new(Reviewers) + resp, err := s.client.Do(ctx, req, reviewers) + if err != nil { + return nil, resp, err + } + + return reviewers, resp, nil +} + +// RemoveReviewers removes the review request for the provided reviewers for the specified pull request. +// +// GitHub API docs: https://docs.github.com/rest/pulls/review-requests#remove-requested-reviewers-from-a-pull-request +// +//meta:operation DELETE /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers +func (s *PullRequestsService) RemoveReviewers(ctx context.Context, owner, repo string, number int, reviewers ReviewersRequest) (*Response, error) { + // reviewers.Reviewers may be empty if the caller wants to remove teams, but not users. Unlike AddReviewers, + // "reviewers" is a required param here. Reference: https://github.com/google/go-github/issues/3336 + removeRequest := removeReviewersRequest{ + NodeID: reviewers.NodeID, + Reviewers: reviewers.Reviewers, + TeamReviewers: reviewers.TeamReviewers, + } + + if removeRequest.Reviewers == nil { + // GitHub accepts the empty list, but rejects null. Removing `omitempty` is not enough - we also have to promote nil to []. + removeRequest.Reviewers = []string{} + } + + u := fmt.Sprintf("repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, number) + req, err := s.client.NewRequest("DELETE", u, &removeRequest) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/pulls_reviews.go b/vendor/github.com/google/go-github/v68/github/pulls_reviews.go new file mode 100644 index 0000000000..27b8dc37d5 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/pulls_reviews.go @@ -0,0 +1,329 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "errors" + "fmt" +) + +var ErrMixedCommentStyles = errors.New("cannot use both position and side/line form comments") + +// PullRequestReview represents a review of a pull request. +type PullRequestReview struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + User *User `json:"user,omitempty"` + Body *string `json:"body,omitempty"` + SubmittedAt *Timestamp `json:"submitted_at,omitempty"` + CommitID *string `json:"commit_id,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + PullRequestURL *string `json:"pull_request_url,omitempty"` + State *string `json:"state,omitempty"` + // AuthorAssociation is the comment author's relationship to the issue's repository. + // Possible values are "COLLABORATOR", "CONTRIBUTOR", "FIRST_TIMER", "FIRST_TIME_CONTRIBUTOR", "MEMBER", "OWNER", or "NONE". + AuthorAssociation *string `json:"author_association,omitempty"` +} + +func (p PullRequestReview) String() string { + return Stringify(p) +} + +// DraftReviewComment represents a comment part of the review. +type DraftReviewComment struct { + Path *string `json:"path,omitempty"` + Position *int `json:"position,omitempty"` + Body *string `json:"body,omitempty"` + + // The new comfort-fade-preview fields + StartSide *string `json:"start_side,omitempty"` + Side *string `json:"side,omitempty"` + StartLine *int `json:"start_line,omitempty"` + Line *int `json:"line,omitempty"` +} + +func (c DraftReviewComment) String() string { + return Stringify(c) +} + +// PullRequestReviewRequest represents a request to create a review. +type PullRequestReviewRequest struct { + NodeID *string `json:"node_id,omitempty"` + CommitID *string `json:"commit_id,omitempty"` + Body *string `json:"body,omitempty"` + Event *string `json:"event,omitempty"` + Comments []*DraftReviewComment `json:"comments,omitempty"` +} + +func (r PullRequestReviewRequest) String() string { + return Stringify(r) +} + +func (r *PullRequestReviewRequest) isComfortFadePreview() (bool, error) { + var isCF *bool + for _, comment := range r.Comments { + if comment == nil { + continue + } + hasPos := comment.Position != nil + hasComfortFade := (comment.StartSide != nil) || (comment.Side != nil) || + (comment.StartLine != nil) || (comment.Line != nil) + + switch { + case hasPos && hasComfortFade: + return false, ErrMixedCommentStyles + case hasPos && isCF != nil && *isCF: + return false, ErrMixedCommentStyles + case hasComfortFade && isCF != nil && !*isCF: + return false, ErrMixedCommentStyles + } + isCF = &hasComfortFade + } + if isCF != nil { + return *isCF, nil + } + return false, nil +} + +// PullRequestReviewDismissalRequest represents a request to dismiss a review. +type PullRequestReviewDismissalRequest struct { + Message *string `json:"message,omitempty"` +} + +func (r PullRequestReviewDismissalRequest) String() string { + return Stringify(r) +} + +// ListReviews lists all reviews on the specified pull request. +// +// GitHub API docs: https://docs.github.com/rest/pulls/reviews#list-reviews-for-a-pull-request +// +//meta:operation GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews +func (s *PullRequestsService) ListReviews(ctx context.Context, owner, repo string, number int, opts *ListOptions) ([]*PullRequestReview, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var reviews []*PullRequestReview + resp, err := s.client.Do(ctx, req, &reviews) + if err != nil { + return nil, resp, err + } + + return reviews, resp, nil +} + +// GetReview fetches the specified pull request review. +// +// GitHub API docs: https://docs.github.com/rest/pulls/reviews#get-a-review-for-a-pull-request +// +//meta:operation GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id} +func (s *PullRequestsService) GetReview(ctx context.Context, owner, repo string, number int, reviewID int64) (*PullRequestReview, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + review := new(PullRequestReview) + resp, err := s.client.Do(ctx, req, review) + if err != nil { + return nil, resp, err + } + + return review, resp, nil +} + +// DeletePendingReview deletes the specified pull request pending review. +// +// GitHub API docs: https://docs.github.com/rest/pulls/reviews#delete-a-pending-review-for-a-pull-request +// +//meta:operation DELETE /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id} +func (s *PullRequestsService) DeletePendingReview(ctx context.Context, owner, repo string, number int, reviewID int64) (*PullRequestReview, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, nil, err + } + + review := new(PullRequestReview) + resp, err := s.client.Do(ctx, req, review) + if err != nil { + return nil, resp, err + } + + return review, resp, nil +} + +// ListReviewComments lists all the comments for the specified review. +// +// GitHub API docs: https://docs.github.com/rest/pulls/reviews#list-comments-for-a-pull-request-review +// +//meta:operation GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments +func (s *PullRequestsService) ListReviewComments(ctx context.Context, owner, repo string, number int, reviewID int64, opts *ListOptions) ([]*PullRequestComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/comments", owner, repo, number, reviewID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var comments []*PullRequestComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// CreateReview creates a new review on the specified pull request. +// +// In order to use multi-line comments, you must use the "comfort fade" preview. +// This replaces the use of the "Position" field in comments with 4 new fields: +// +// [Start]Side, and [Start]Line. +// +// These new fields must be used for ALL comments (including single-line), +// with the following restrictions (empirically observed, so subject to change). +// +// For single-line "comfort fade" comments, you must use: +// +// Path: &path, // as before +// Body: &body, // as before +// Side: &"RIGHT" (or "LEFT") +// Line: &123, // NOT THE SAME AS POSITION, this is an actual line number. +// +// If StartSide or StartLine is used with single-line comments, a 422 is returned. +// +// For multi-line "comfort fade" comments, you must use: +// +// Path: &path, // as before +// Body: &body, // as before +// StartSide: &"RIGHT" (or "LEFT") +// Side: &"RIGHT" (or "LEFT") +// StartLine: &120, +// Line: &125, +// +// Suggested edits are made by commenting on the lines to replace, and including the +// suggested edit in a block like this (it may be surrounded in non-suggestion markdown): +// +// ```suggestion +// Use this instead. +// It is waaaaaay better. +// ``` +// +// GitHub API docs: https://docs.github.com/rest/pulls/reviews#create-a-review-for-a-pull-request +// +//meta:operation POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews +func (s *PullRequestsService) CreateReview(ctx context.Context, owner, repo string, number int, review *PullRequestReviewRequest) (*PullRequestReview, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number) + + req, err := s.client.NewRequest("POST", u, review) + if err != nil { + return nil, nil, err + } + + // Detect which style of review comment is being used. + if isCF, err := review.isComfortFadePreview(); err != nil { + return nil, nil, err + } else if isCF { + // If the review comments are using the comfort fade preview fields, + // then pass the comfort fade header. + req.Header.Set("Accept", mediaTypeMultiLineCommentsPreview) + } + + r := new(PullRequestReview) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// UpdateReview updates the review summary on the specified pull request. +// +// GitHub API docs: https://docs.github.com/rest/pulls/reviews#update-a-review-for-a-pull-request +// +//meta:operation PUT /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id} +func (s *PullRequestsService) UpdateReview(ctx context.Context, owner, repo string, number int, reviewID int64, body string) (*PullRequestReview, *Response, error) { + opts := &struct { + Body string `json:"body"` + }{Body: body} + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID) + + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, nil, err + } + + review := &PullRequestReview{} + resp, err := s.client.Do(ctx, req, review) + if err != nil { + return nil, resp, err + } + + return review, resp, nil +} + +// SubmitReview submits a specified review on the specified pull request. +// +// GitHub API docs: https://docs.github.com/rest/pulls/reviews#submit-a-review-for-a-pull-request +// +//meta:operation POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/events +func (s *PullRequestsService) SubmitReview(ctx context.Context, owner, repo string, number int, reviewID int64, review *PullRequestReviewRequest) (*PullRequestReview, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/events", owner, repo, number, reviewID) + + req, err := s.client.NewRequest("POST", u, review) + if err != nil { + return nil, nil, err + } + + r := new(PullRequestReview) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// DismissReview dismisses a specified review on the specified pull request. +// +// GitHub API docs: https://docs.github.com/rest/pulls/reviews#dismiss-a-review-for-a-pull-request +// +//meta:operation PUT /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/dismissals +func (s *PullRequestsService) DismissReview(ctx context.Context, owner, repo string, number int, reviewID int64, review *PullRequestReviewDismissalRequest) (*PullRequestReview, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/dismissals", owner, repo, number, reviewID) + + req, err := s.client.NewRequest("PUT", u, review) + if err != nil { + return nil, nil, err + } + + r := new(PullRequestReview) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/pulls_threads.go b/vendor/github.com/google/go-github/v68/github/pulls_threads.go new file mode 100644 index 0000000000..23e924d88f --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/pulls_threads.go @@ -0,0 +1,17 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +// PullRequestThread represents a thread of comments on a pull request. +type PullRequestThread struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Comments []*PullRequestComment `json:"comments,omitempty"` +} + +func (p PullRequestThread) String() string { + return Stringify(p) +} diff --git a/vendor/github.com/google/go-github/v68/github/rate_limit.go b/vendor/github.com/google/go-github/v68/github/rate_limit.go new file mode 100644 index 0000000000..5b01b573d8 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/rate_limit.go @@ -0,0 +1,125 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import "context" + +// RateLimitService provides access to rate limit functions in the GitHub API. +type RateLimitService service + +// Rate represents the rate limit for the current client. +type Rate struct { + // The number of requests per hour the client is currently limited to. + Limit int `json:"limit"` + + // The number of remaining requests the client can make this hour. + Remaining int `json:"remaining"` + + // The time at which the current rate limit will reset. + Reset Timestamp `json:"reset"` +} + +func (r Rate) String() string { + return Stringify(r) +} + +// RateLimits represents the rate limits for the current client. +type RateLimits struct { + // The rate limit for non-search API requests. Unauthenticated + // requests are limited to 60 per hour. Authenticated requests are + // limited to 5,000 per hour. + // + // GitHub API docs: https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting + Core *Rate `json:"core"` + + // The rate limit for search API requests. Unauthenticated requests + // are limited to 10 requests per minutes. Authenticated requests are + // limited to 30 per minute. + // + // GitHub API docs: https://docs.github.com/en/rest/search#rate-limit + Search *Rate `json:"search"` + + // GitHub API docs: https://docs.github.com/en/graphql/overview/resource-limitations#rate-limit + GraphQL *Rate `json:"graphql"` + + // GitHub API dos: https://docs.github.com/en/rest/rate-limit + IntegrationManifest *Rate `json:"integration_manifest"` + + SourceImport *Rate `json:"source_import"` + CodeScanningUpload *Rate `json:"code_scanning_upload"` + ActionsRunnerRegistration *Rate `json:"actions_runner_registration"` + SCIM *Rate `json:"scim"` + DependencySnapshots *Rate `json:"dependency_snapshots"` + CodeSearch *Rate `json:"code_search"` + AuditLog *Rate `json:"audit_log"` +} + +func (r RateLimits) String() string { + return Stringify(r) +} + +// Get returns the rate limits for the current client. +// +// GitHub API docs: https://docs.github.com/rest/rate-limit/rate-limit#get-rate-limit-status-for-the-authenticated-user +// +//meta:operation GET /rate_limit +func (s *RateLimitService) Get(ctx context.Context) (*RateLimits, *Response, error) { + req, err := s.client.NewRequest("GET", "rate_limit", nil) + if err != nil { + return nil, nil, err + } + + response := new(struct { + Resources *RateLimits `json:"resources"` + }) + + // This resource is not subject to rate limits. + ctx = context.WithValue(ctx, bypassRateLimitCheck, true) + resp, err := s.client.Do(ctx, req, response) + if err != nil { + return nil, resp, err + } + + if response.Resources != nil { + s.client.rateMu.Lock() + if response.Resources.Core != nil { + s.client.rateLimits[CoreCategory] = *response.Resources.Core + } + if response.Resources.Search != nil { + s.client.rateLimits[SearchCategory] = *response.Resources.Search + } + if response.Resources.GraphQL != nil { + s.client.rateLimits[GraphqlCategory] = *response.Resources.GraphQL + } + if response.Resources.IntegrationManifest != nil { + s.client.rateLimits[IntegrationManifestCategory] = *response.Resources.IntegrationManifest + } + if response.Resources.SourceImport != nil { + s.client.rateLimits[SourceImportCategory] = *response.Resources.SourceImport + } + if response.Resources.CodeScanningUpload != nil { + s.client.rateLimits[CodeScanningUploadCategory] = *response.Resources.CodeScanningUpload + } + if response.Resources.ActionsRunnerRegistration != nil { + s.client.rateLimits[ActionsRunnerRegistrationCategory] = *response.Resources.ActionsRunnerRegistration + } + if response.Resources.SCIM != nil { + s.client.rateLimits[ScimCategory] = *response.Resources.SCIM + } + if response.Resources.DependencySnapshots != nil { + s.client.rateLimits[DependencySnapshotsCategory] = *response.Resources.DependencySnapshots + } + if response.Resources.CodeSearch != nil { + s.client.rateLimits[CodeSearchCategory] = *response.Resources.CodeSearch + } + if response.Resources.AuditLog != nil { + s.client.rateLimits[AuditLogCategory] = *response.Resources.AuditLog + } + s.client.rateMu.Unlock() + } + + return response.Resources, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/reactions.go b/vendor/github.com/google/go-github/v68/github/reactions.go new file mode 100644 index 0000000000..9f9f72faee --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/reactions.go @@ -0,0 +1,570 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" +) + +// ReactionsService provides access to the reactions-related functions in the +// GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/reactions +type ReactionsService service + +// Reaction represents a GitHub reaction. +type Reaction struct { + // ID is the Reaction ID. + ID *int64 `json:"id,omitempty"` + User *User `json:"user,omitempty"` + NodeID *string `json:"node_id,omitempty"` + // Content is the type of reaction. + // Possible values are: + // "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". + Content *string `json:"content,omitempty"` +} + +// Reactions represents a summary of GitHub reactions. +type Reactions struct { + TotalCount *int `json:"total_count,omitempty"` + PlusOne *int `json:"+1,omitempty"` + MinusOne *int `json:"-1,omitempty"` + Laugh *int `json:"laugh,omitempty"` + Confused *int `json:"confused,omitempty"` + Heart *int `json:"heart,omitempty"` + Hooray *int `json:"hooray,omitempty"` + Rocket *int `json:"rocket,omitempty"` + Eyes *int `json:"eyes,omitempty"` + URL *string `json:"url,omitempty"` +} + +func (r Reaction) String() string { + return Stringify(r) +} + +// ListCommentReactionOptions specifies the optional parameters to the +// ReactionsService.ListCommentReactions method. +type ListCommentReactionOptions struct { + // Content restricts the returned comment reactions to only those with the given type. + // Omit this parameter to list all reactions to a commit comment. + // Possible values are: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". + Content string `url:"content,omitempty"` + + ListOptions +} + +// ListCommentReactions lists the reactions for a commit comment. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#list-reactions-for-a-commit-comment +// +//meta:operation GET /repos/{owner}/{repo}/comments/{comment_id}/reactions +func (s *ReactionsService) ListCommentReactions(ctx context.Context, owner, repo string, id int64, opts *ListCommentReactionOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateCommentReaction creates a reaction for a commit comment. +// Note that if you have already created a reaction of type content, the +// previously created reaction will be returned with Status: 200 OK. +// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#create-reaction-for-a-commit-comment +// +//meta:operation POST /repos/{owner}/{repo}/comments/{comment_id}/reactions +func (s *ReactionsService) CreateCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id) + + body := &Reaction{Content: Ptr(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeleteCommentReaction deletes the reaction for a commit comment. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#delete-a-commit-comment-reaction +// +//meta:operation DELETE /repos/{owner}/{repo}/comments/{comment_id}/reactions/{reaction_id} +func (s *ReactionsService) DeleteCommentReaction(ctx context.Context, owner, repo string, commentID, reactionID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions/%v", owner, repo, commentID, reactionID) + + return s.deleteReaction(ctx, u) +} + +// DeleteCommentReactionByID deletes the reaction for a commit comment by repository ID. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#delete-a-commit-comment-reaction +// +//meta:operation DELETE /repos/{owner}/{repo}/comments/{comment_id}/reactions/{reaction_id} +func (s *ReactionsService) DeleteCommentReactionByID(ctx context.Context, repoID, commentID, reactionID int64) (*Response, error) { + u := fmt.Sprintf("repositories/%v/comments/%v/reactions/%v", repoID, commentID, reactionID) + + return s.deleteReaction(ctx, u) +} + +// ListIssueReactions lists the reactions for an issue. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#list-reactions-for-an-issue +// +//meta:operation GET /repos/{owner}/{repo}/issues/{issue_number}/reactions +func (s *ReactionsService) ListIssueReactions(ctx context.Context, owner, repo string, number int, opts *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateIssueReaction creates a reaction for an issue. +// Note that if you have already created a reaction of type content, the +// previously created reaction will be returned with Status: 200 OK. +// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#create-reaction-for-an-issue +// +//meta:operation POST /repos/{owner}/{repo}/issues/{issue_number}/reactions +func (s *ReactionsService) CreateIssueReaction(ctx context.Context, owner, repo string, number int, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number) + + body := &Reaction{Content: Ptr(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeleteIssueReaction deletes the reaction to an issue. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#delete-an-issue-reaction +// +//meta:operation DELETE /repos/{owner}/{repo}/issues/{issue_number}/reactions/{reaction_id} +func (s *ReactionsService) DeleteIssueReaction(ctx context.Context, owner, repo string, issueNumber int, reactionID int64) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/issues/%v/reactions/%v", owner, repo, issueNumber, reactionID) + + return s.deleteReaction(ctx, url) +} + +// DeleteIssueReactionByID deletes the reaction to an issue by repository ID. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#delete-an-issue-reaction +// +//meta:operation DELETE /repos/{owner}/{repo}/issues/{issue_number}/reactions/{reaction_id} +func (s *ReactionsService) DeleteIssueReactionByID(ctx context.Context, repoID, issueNumber int, reactionID int64) (*Response, error) { + url := fmt.Sprintf("repositories/%v/issues/%v/reactions/%v", repoID, issueNumber, reactionID) + + return s.deleteReaction(ctx, url) +} + +// ListIssueCommentReactions lists the reactions for an issue comment. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#list-reactions-for-an-issue-comment +// +//meta:operation GET /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions +func (s *ReactionsService) ListIssueCommentReactions(ctx context.Context, owner, repo string, id int64, opts *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateIssueCommentReaction creates a reaction for an issue comment. +// Note that if you have already created a reaction of type content, the +// previously created reaction will be returned with Status: 200 OK. +// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#create-reaction-for-an-issue-comment +// +//meta:operation POST /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions +func (s *ReactionsService) CreateIssueCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id) + + body := &Reaction{Content: Ptr(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeleteIssueCommentReaction deletes the reaction to an issue comment. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#delete-an-issue-comment-reaction +// +//meta:operation DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions/{reaction_id} +func (s *ReactionsService) DeleteIssueCommentReaction(ctx context.Context, owner, repo string, commentID, reactionID int64) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions/%v", owner, repo, commentID, reactionID) + + return s.deleteReaction(ctx, url) +} + +// DeleteIssueCommentReactionByID deletes the reaction to an issue comment by repository ID. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#delete-an-issue-comment-reaction +// +//meta:operation DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions/{reaction_id} +func (s *ReactionsService) DeleteIssueCommentReactionByID(ctx context.Context, repoID, commentID, reactionID int64) (*Response, error) { + url := fmt.Sprintf("repositories/%v/issues/comments/%v/reactions/%v", repoID, commentID, reactionID) + + return s.deleteReaction(ctx, url) +} + +// ListPullRequestCommentReactions lists the reactions for a pull request review comment. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#list-reactions-for-a-pull-request-review-comment +// +//meta:operation GET /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions +func (s *ReactionsService) ListPullRequestCommentReactions(ctx context.Context, owner, repo string, id int64, opts *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreatePullRequestCommentReaction creates a reaction for a pull request review comment. +// Note that if you have already created a reaction of type content, the +// previously created reaction will be returned with Status: 200 OK. +// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#create-reaction-for-a-pull-request-review-comment +// +//meta:operation POST /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions +func (s *ReactionsService) CreatePullRequestCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id) + + body := &Reaction{Content: Ptr(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeletePullRequestCommentReaction deletes the reaction to a pull request review comment. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#delete-a-pull-request-comment-reaction +// +//meta:operation DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions/{reaction_id} +func (s *ReactionsService) DeletePullRequestCommentReaction(ctx context.Context, owner, repo string, commentID, reactionID int64) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions/%v", owner, repo, commentID, reactionID) + + return s.deleteReaction(ctx, url) +} + +// DeletePullRequestCommentReactionByID deletes the reaction to a pull request review comment by repository ID. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#delete-a-pull-request-comment-reaction +// +//meta:operation DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions/{reaction_id} +func (s *ReactionsService) DeletePullRequestCommentReactionByID(ctx context.Context, repoID, commentID, reactionID int64) (*Response, error) { + url := fmt.Sprintf("repositories/%v/pulls/comments/%v/reactions/%v", repoID, commentID, reactionID) + + return s.deleteReaction(ctx, url) +} + +// ListTeamDiscussionReactions lists the reactions for a team discussion. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#list-reactions-for-a-team-discussion-legacy +// +//meta:operation GET /teams/{team_id}/discussions/{discussion_number}/reactions +func (s *ReactionsService) ListTeamDiscussionReactions(ctx context.Context, teamID int64, discussionNumber int, opts *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("teams/%v/discussions/%v/reactions", teamID, discussionNumber) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateTeamDiscussionReaction creates a reaction for a team discussion. +// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#create-reaction-for-a-team-discussion-legacy +// +//meta:operation POST /teams/{team_id}/discussions/{discussion_number}/reactions +func (s *ReactionsService) CreateTeamDiscussionReaction(ctx context.Context, teamID int64, discussionNumber int, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("teams/%v/discussions/%v/reactions", teamID, discussionNumber) + + body := &Reaction{Content: Ptr(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeleteTeamDiscussionReaction deletes the reaction to a team discussion. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#delete-team-discussion-reaction +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions/{reaction_id} +func (s *ReactionsService) DeleteTeamDiscussionReaction(ctx context.Context, org, teamSlug string, discussionNumber int, reactionID int64) (*Response, error) { + url := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/reactions/%v", org, teamSlug, discussionNumber, reactionID) + + return s.deleteReaction(ctx, url) +} + +// DeleteTeamDiscussionReactionByOrgIDAndTeamID deletes the reaction to a team discussion by organization ID and team ID. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#create-reaction-for-a-team-discussion +// +//meta:operation POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions +func (s *ReactionsService) DeleteTeamDiscussionReactionByOrgIDAndTeamID(ctx context.Context, orgID, teamID, discussionNumber int, reactionID int64) (*Response, error) { + url := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/reactions/%v", orgID, teamID, discussionNumber, reactionID) + + return s.deleteReaction(ctx, url) +} + +// ListTeamDiscussionCommentReactions lists the reactions for a team discussion comment. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#list-reactions-for-a-team-discussion-comment-legacy +// +//meta:operation GET /teams/{team_id}/discussions/{discussion_number}/comments/{comment_number}/reactions +func (s *ReactionsService) ListTeamDiscussionCommentReactions(ctx context.Context, teamID int64, discussionNumber, commentNumber int, opts *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v/reactions", teamID, discussionNumber, commentNumber) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + return m, resp, nil +} + +// CreateTeamDiscussionCommentReaction creates a reaction for a team discussion comment. +// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#create-reaction-for-a-team-discussion-comment-legacy +// +//meta:operation POST /teams/{team_id}/discussions/{discussion_number}/comments/{comment_number}/reactions +func (s *ReactionsService) CreateTeamDiscussionCommentReaction(ctx context.Context, teamID int64, discussionNumber, commentNumber int, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v/reactions", teamID, discussionNumber, commentNumber) + + body := &Reaction{Content: Ptr(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeleteTeamDiscussionCommentReaction deletes the reaction to a team discussion comment. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#delete-team-discussion-comment-reaction +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions/{reaction_id} +func (s *ReactionsService) DeleteTeamDiscussionCommentReaction(ctx context.Context, org, teamSlug string, discussionNumber, commentNumber int, reactionID int64) (*Response, error) { + url := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments/%v/reactions/%v", org, teamSlug, discussionNumber, commentNumber, reactionID) + + return s.deleteReaction(ctx, url) +} + +// DeleteTeamDiscussionCommentReactionByOrgIDAndTeamID deletes the reaction to a team discussion comment by organization ID and team ID. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#create-reaction-for-a-team-discussion-comment +// +//meta:operation POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions +func (s *ReactionsService) DeleteTeamDiscussionCommentReactionByOrgIDAndTeamID(ctx context.Context, orgID, teamID, discussionNumber, commentNumber int, reactionID int64) (*Response, error) { + url := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments/%v/reactions/%v", orgID, teamID, discussionNumber, commentNumber, reactionID) + + return s.deleteReaction(ctx, url) +} + +func (s *ReactionsService) deleteReaction(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest(http.MethodDelete, url, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + return s.client.Do(ctx, req, nil) +} + +// CreateReleaseReaction creates a reaction to a release. +// Note that a response with a Status: 200 OK means that you already +// added the reaction type to this release. +// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#create-reaction-for-a-release +// +//meta:operation POST /repos/{owner}/{repo}/releases/{release_id}/reactions +func (s *ReactionsService) CreateReleaseReaction(ctx context.Context, owner, repo string, releaseID int64, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/releases/%v/reactions", owner, repo, releaseID) + + body := &Reaction{Content: Ptr(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos.go b/vendor/github.com/google/go-github/v68/github/repos.go new file mode 100644 index 0000000000..9faed401f8 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos.go @@ -0,0 +1,2428 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "net/http" + "net/url" + "strings" +) + +const githubBranchNotProtected string = "Branch not protected" + +var ErrBranchNotProtected = errors.New("branch is not protected") + +// RepositoriesService handles communication with the repository related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/repos/ +type RepositoriesService service + +// Repository represents a GitHub repository. +type Repository struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Owner *User `json:"owner,omitempty"` + Name *string `json:"name,omitempty"` + FullName *string `json:"full_name,omitempty"` + Description *string `json:"description,omitempty"` + Homepage *string `json:"homepage,omitempty"` + CodeOfConduct *CodeOfConduct `json:"code_of_conduct,omitempty"` + DefaultBranch *string `json:"default_branch,omitempty"` + MasterBranch *string `json:"master_branch,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + PushedAt *Timestamp `json:"pushed_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CloneURL *string `json:"clone_url,omitempty"` + GitURL *string `json:"git_url,omitempty"` + MirrorURL *string `json:"mirror_url,omitempty"` + SSHURL *string `json:"ssh_url,omitempty"` + SVNURL *string `json:"svn_url,omitempty"` + Language *string `json:"language,omitempty"` + Fork *bool `json:"fork,omitempty"` + ForksCount *int `json:"forks_count,omitempty"` + NetworkCount *int `json:"network_count,omitempty"` + OpenIssuesCount *int `json:"open_issues_count,omitempty"` + OpenIssues *int `json:"open_issues,omitempty"` // Deprecated: Replaced by OpenIssuesCount. For backward compatibility OpenIssues is still populated. + StargazersCount *int `json:"stargazers_count,omitempty"` + SubscribersCount *int `json:"subscribers_count,omitempty"` + WatchersCount *int `json:"watchers_count,omitempty"` // Deprecated: Replaced by StargazersCount. For backward compatibility WatchersCount is still populated. + Watchers *int `json:"watchers,omitempty"` // Deprecated: Replaced by StargazersCount. For backward compatibility Watchers is still populated. + Size *int `json:"size,omitempty"` + AutoInit *bool `json:"auto_init,omitempty"` + Parent *Repository `json:"parent,omitempty"` + Source *Repository `json:"source,omitempty"` + TemplateRepository *Repository `json:"template_repository,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Permissions map[string]bool `json:"permissions,omitempty"` + AllowRebaseMerge *bool `json:"allow_rebase_merge,omitempty"` + AllowUpdateBranch *bool `json:"allow_update_branch,omitempty"` + AllowSquashMerge *bool `json:"allow_squash_merge,omitempty"` + AllowMergeCommit *bool `json:"allow_merge_commit,omitempty"` + AllowAutoMerge *bool `json:"allow_auto_merge,omitempty"` + AllowForking *bool `json:"allow_forking,omitempty"` + WebCommitSignoffRequired *bool `json:"web_commit_signoff_required,omitempty"` + DeleteBranchOnMerge *bool `json:"delete_branch_on_merge,omitempty"` + UseSquashPRTitleAsDefault *bool `json:"use_squash_pr_title_as_default,omitempty"` + SquashMergeCommitTitle *string `json:"squash_merge_commit_title,omitempty"` // Can be one of: "PR_TITLE", "COMMIT_OR_PR_TITLE" + SquashMergeCommitMessage *string `json:"squash_merge_commit_message,omitempty"` // Can be one of: "PR_BODY", "COMMIT_MESSAGES", "BLANK" + MergeCommitTitle *string `json:"merge_commit_title,omitempty"` // Can be one of: "PR_TITLE", "MERGE_MESSAGE" + MergeCommitMessage *string `json:"merge_commit_message,omitempty"` // Can be one of: "PR_BODY", "PR_TITLE", "BLANK" + Topics []string `json:"topics,omitempty"` + CustomProperties map[string]interface{} `json:"custom_properties,omitempty"` + Archived *bool `json:"archived,omitempty"` + Disabled *bool `json:"disabled,omitempty"` + + // Only provided when using RepositoriesService.Get while in preview + License *License `json:"license,omitempty"` + + // Additional mutable fields when creating and editing a repository + Private *bool `json:"private,omitempty"` + HasIssues *bool `json:"has_issues,omitempty"` + HasWiki *bool `json:"has_wiki,omitempty"` + HasPages *bool `json:"has_pages,omitempty"` + HasProjects *bool `json:"has_projects,omitempty"` + HasDownloads *bool `json:"has_downloads,omitempty"` + HasDiscussions *bool `json:"has_discussions,omitempty"` + IsTemplate *bool `json:"is_template,omitempty"` + LicenseTemplate *string `json:"license_template,omitempty"` + GitignoreTemplate *string `json:"gitignore_template,omitempty"` + + // Options for configuring Advanced Security and Secret Scanning + SecurityAndAnalysis *SecurityAndAnalysis `json:"security_and_analysis,omitempty"` + + // Creating an organization repository. Required for non-owners. + TeamID *int64 `json:"team_id,omitempty"` + + // API URLs + URL *string `json:"url,omitempty"` + ArchiveURL *string `json:"archive_url,omitempty"` + AssigneesURL *string `json:"assignees_url,omitempty"` + BlobsURL *string `json:"blobs_url,omitempty"` + BranchesURL *string `json:"branches_url,omitempty"` + CollaboratorsURL *string `json:"collaborators_url,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + CommitsURL *string `json:"commits_url,omitempty"` + CompareURL *string `json:"compare_url,omitempty"` + ContentsURL *string `json:"contents_url,omitempty"` + ContributorsURL *string `json:"contributors_url,omitempty"` + DeploymentsURL *string `json:"deployments_url,omitempty"` + DownloadsURL *string `json:"downloads_url,omitempty"` + EventsURL *string `json:"events_url,omitempty"` + ForksURL *string `json:"forks_url,omitempty"` + GitCommitsURL *string `json:"git_commits_url,omitempty"` + GitRefsURL *string `json:"git_refs_url,omitempty"` + GitTagsURL *string `json:"git_tags_url,omitempty"` + HooksURL *string `json:"hooks_url,omitempty"` + IssueCommentURL *string `json:"issue_comment_url,omitempty"` + IssueEventsURL *string `json:"issue_events_url,omitempty"` + IssuesURL *string `json:"issues_url,omitempty"` + KeysURL *string `json:"keys_url,omitempty"` + LabelsURL *string `json:"labels_url,omitempty"` + LanguagesURL *string `json:"languages_url,omitempty"` + MergesURL *string `json:"merges_url,omitempty"` + MilestonesURL *string `json:"milestones_url,omitempty"` + NotificationsURL *string `json:"notifications_url,omitempty"` + PullsURL *string `json:"pulls_url,omitempty"` + ReleasesURL *string `json:"releases_url,omitempty"` + StargazersURL *string `json:"stargazers_url,omitempty"` + StatusesURL *string `json:"statuses_url,omitempty"` + SubscribersURL *string `json:"subscribers_url,omitempty"` + SubscriptionURL *string `json:"subscription_url,omitempty"` + TagsURL *string `json:"tags_url,omitempty"` + TreesURL *string `json:"trees_url,omitempty"` + TeamsURL *string `json:"teams_url,omitempty"` + + // TextMatches is only populated from search results that request text matches + // See: search.go and https://docs.github.com/rest/search/#text-match-metadata + TextMatches []*TextMatch `json:"text_matches,omitempty"` + + // Visibility is only used for Create and Edit endpoints. The visibility field + // overrides the field parameter when both are used. + // Can be one of public, private or internal. + Visibility *string `json:"visibility,omitempty"` + + // RoleName is only returned by the API 'check team permissions for a repository'. + // See: teams.go (IsTeamRepoByID) https://docs.github.com/rest/teams/teams#check-team-permissions-for-a-repository + RoleName *string `json:"role_name,omitempty"` +} + +func (r Repository) String() string { + return Stringify(r) +} + +// BranchListOptions specifies the optional parameters to the +// RepositoriesService.ListBranches method. +type BranchListOptions struct { + // Setting to true returns only protected branches. + // When set to false, only unprotected branches are returned. + // Omitting this parameter returns all branches. + // Default: nil + Protected *bool `url:"protected,omitempty"` + + ListOptions +} + +// RepositoryListOptions specifies the optional parameters to the +// RepositoriesService.List method. +type RepositoryListOptions struct { + // See RepositoryListByAuthenticatedUserOptions.Visibility + Visibility string `url:"visibility,omitempty"` + + // See RepositoryListByAuthenticatedUserOptions.Affiliation + Affiliation string `url:"affiliation,omitempty"` + + // See RepositoryListByUserOptions.Type or RepositoryListByAuthenticatedUserOptions.Type + Type string `url:"type,omitempty"` + + // See RepositoryListByUserOptions.Sort or RepositoryListByAuthenticatedUserOptions.Sort + Sort string `url:"sort,omitempty"` + + // See RepositoryListByUserOptions.Direction or RepositoryListByAuthenticatedUserOptions.Direction + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// SecurityAndAnalysis specifies the optional advanced security features +// that are enabled on a given repository. +type SecurityAndAnalysis struct { + AdvancedSecurity *AdvancedSecurity `json:"advanced_security,omitempty"` + SecretScanning *SecretScanning `json:"secret_scanning,omitempty"` + SecretScanningPushProtection *SecretScanningPushProtection `json:"secret_scanning_push_protection,omitempty"` + DependabotSecurityUpdates *DependabotSecurityUpdates `json:"dependabot_security_updates,omitempty"` + SecretScanningValidityChecks *SecretScanningValidityChecks `json:"secret_scanning_validity_checks,omitempty"` +} + +func (s SecurityAndAnalysis) String() string { + return Stringify(s) +} + +// AdvancedSecurity specifies the state of advanced security on a repository. +// +// GitHub API docs: https://docs.github.com/github/getting-started-with-github/learning-about-github/about-github-advanced-security +type AdvancedSecurity struct { + Status *string `json:"status,omitempty"` +} + +func (a AdvancedSecurity) String() string { + return Stringify(a) +} + +// SecretScanning specifies the state of secret scanning on a repository. +// +// GitHub API docs: https://docs.github.com/code-security/secret-security/about-secret-scanning +type SecretScanning struct { + Status *string `json:"status,omitempty"` +} + +func (s SecretScanning) String() string { + return Stringify(s) +} + +// SecretScanningPushProtection specifies the state of secret scanning push protection on a repository. +// +// GitHub API docs: https://docs.github.com/code-security/secret-scanning/about-secret-scanning#about-secret-scanning-for-partner-patterns +type SecretScanningPushProtection struct { + Status *string `json:"status,omitempty"` +} + +func (s SecretScanningPushProtection) String() string { + return Stringify(s) +} + +// DependabotSecurityUpdates specifies the state of Dependabot security updates on a repository. +// +// GitHub API docs: https://docs.github.com/code-security/dependabot/dependabot-security-updates/about-dependabot-security-updates +type DependabotSecurityUpdates struct { + Status *string `json:"status,omitempty"` +} + +func (d DependabotSecurityUpdates) String() string { + return Stringify(d) +} + +// SecretScanningValidityChecks represents the state of secret scanning validity checks on a repository. +// +// GitHub API docs: https://docs.github.com/en/enterprise-cloud@latest/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-security-and-analysis-settings-for-your-repository#allowing-validity-checks-for-partner-patterns-in-a-repository +type SecretScanningValidityChecks struct { + Status *string `json:"status,omitempty"` +} + +// List calls either RepositoriesService.ListByUser or RepositoriesService.ListByAuthenticatedUser +// depending on whether user is empty. +// +// Deprecated: Use RepositoriesService.ListByUser or RepositoriesService.ListByAuthenticatedUser instead. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-repositories-for-a-user +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-repositories-for-the-authenticated-user +// +//meta:operation GET /user/repos +//meta:operation GET /users/{username}/repos +func (s *RepositoriesService) List(ctx context.Context, user string, opts *RepositoryListOptions) ([]*Repository, *Response, error) { + if opts == nil { + opts = &RepositoryListOptions{} + } + if user != "" { + return s.ListByUser(ctx, user, &RepositoryListByUserOptions{ + Type: opts.Type, + Sort: opts.Sort, + Direction: opts.Direction, + ListOptions: opts.ListOptions, + }) + } + return s.ListByAuthenticatedUser(ctx, &RepositoryListByAuthenticatedUserOptions{ + Visibility: opts.Visibility, + Affiliation: opts.Affiliation, + Type: opts.Type, + Sort: opts.Sort, + Direction: opts.Direction, + ListOptions: opts.ListOptions, + }) +} + +// RepositoryListByUserOptions specifies the optional parameters to the +// RepositoriesService.ListByUser method. +type RepositoryListByUserOptions struct { + // Limit results to repositories of the specified type. + // Default: owner + // Can be one of: all, owner, member + Type string `url:"type,omitempty"` + + // The property to sort the results by. + // Default: full_name + // Can be one of: created, updated, pushed, full_name + Sort string `url:"sort,omitempty"` + + // The order to sort by. + // Default: asc when using full_name, otherwise desc. + // Can be one of: asc, desc + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// ListByUser lists public repositories for the specified user. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-repositories-for-a-user +// +//meta:operation GET /users/{username}/repos +func (s *RepositoriesService) ListByUser(ctx context.Context, user string, opts *RepositoryListByUserOptions) ([]*Repository, *Response, error) { + u := fmt.Sprintf("users/%v/repos", user) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// RepositoryListByAuthenticatedUserOptions specifies the optional parameters to the +// RepositoriesService.ListByAuthenticatedUser method. +type RepositoryListByAuthenticatedUserOptions struct { + // Limit results to repositories with the specified visibility. + // Default: all + // Can be one of: all, public, private + Visibility string `url:"visibility,omitempty"` + + // List repos of given affiliation[s]. + // Comma-separated list of values. Can include: + // * owner: Repositories that are owned by the authenticated user. + // * collaborator: Repositories that the user has been added to as a + // collaborator. + // * organization_member: Repositories that the user has access to through + // being a member of an organization. This includes every repository on + // every team that the user is on. + // Default: owner,collaborator,organization_member + Affiliation string `url:"affiliation,omitempty"` + + // Limit results to repositories of the specified type. Will cause a 422 error if + // used in the same request as visibility or affiliation. + // Default: all + // Can be one of: all, owner, public, private, member + Type string `url:"type,omitempty"` + + // The property to sort the results by. + // Default: full_name + // Can be one of: created, updated, pushed, full_name + Sort string `url:"sort,omitempty"` + + // Direction in which to sort repositories. Can be one of asc or desc. + // Default: when using full_name: asc; otherwise desc + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// ListByAuthenticatedUser lists repositories for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-repositories-for-the-authenticated-user +// +//meta:operation GET /user/repos +func (s *RepositoriesService) ListByAuthenticatedUser(ctx context.Context, opts *RepositoryListByAuthenticatedUserOptions) ([]*Repository, *Response, error) { + u := "user/repos" + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// RepositoryListByOrgOptions specifies the optional parameters to the +// RepositoriesService.ListByOrg method. +type RepositoryListByOrgOptions struct { + // Type of repositories to list. Possible values are: all, public, private, + // forks, sources, member. Default is "all". + Type string `url:"type,omitempty"` + + // How to sort the repository list. Can be one of created, updated, pushed, + // full_name. Default is "created". + Sort string `url:"sort,omitempty"` + + // Direction in which to sort repositories. Can be one of asc or desc. + // Default when using full_name: asc; otherwise desc. + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// ListByOrg lists the repositories for an organization. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-organization-repositories +// +//meta:operation GET /orgs/{org}/repos +func (s *RepositoriesService) ListByOrg(ctx context.Context, org string, opts *RepositoryListByOrgOptions) ([]*Repository, *Response, error) { + u := fmt.Sprintf("orgs/%v/repos", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeTopicsPreview, mediaTypeRepositoryVisibilityPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// RepositoryListAllOptions specifies the optional parameters to the +// RepositoriesService.ListAll method. +type RepositoryListAllOptions struct { + // ID of the last repository seen + Since int64 `url:"since,omitempty"` +} + +// ListAll lists all GitHub repositories in the order that they were created. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-public-repositories +// +//meta:operation GET /repositories +func (s *RepositoriesService) ListAll(ctx context.Context, opts *RepositoryListAllOptions) ([]*Repository, *Response, error) { + u, err := addOptions("repositories", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// createRepoRequest is a subset of Repository and is used internally +// by Create to pass only the known fields for the endpoint. +// +// See https://github.com/google/go-github/issues/1014 for more +// information. +type createRepoRequest struct { + // Name is required when creating a repo. + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + Homepage *string `json:"homepage,omitempty"` + + Private *bool `json:"private,omitempty"` + Visibility *string `json:"visibility,omitempty"` + HasIssues *bool `json:"has_issues,omitempty"` + HasProjects *bool `json:"has_projects,omitempty"` + HasWiki *bool `json:"has_wiki,omitempty"` + HasDiscussions *bool `json:"has_discussions,omitempty"` + IsTemplate *bool `json:"is_template,omitempty"` + + // Creating an organization repository. Required for non-owners. + TeamID *int64 `json:"team_id,omitempty"` + + AutoInit *bool `json:"auto_init,omitempty"` + GitignoreTemplate *string `json:"gitignore_template,omitempty"` + LicenseTemplate *string `json:"license_template,omitempty"` + AllowSquashMerge *bool `json:"allow_squash_merge,omitempty"` + AllowMergeCommit *bool `json:"allow_merge_commit,omitempty"` + AllowRebaseMerge *bool `json:"allow_rebase_merge,omitempty"` + AllowUpdateBranch *bool `json:"allow_update_branch,omitempty"` + AllowAutoMerge *bool `json:"allow_auto_merge,omitempty"` + AllowForking *bool `json:"allow_forking,omitempty"` + DeleteBranchOnMerge *bool `json:"delete_branch_on_merge,omitempty"` + UseSquashPRTitleAsDefault *bool `json:"use_squash_pr_title_as_default,omitempty"` + SquashMergeCommitTitle *string `json:"squash_merge_commit_title,omitempty"` + SquashMergeCommitMessage *string `json:"squash_merge_commit_message,omitempty"` + MergeCommitTitle *string `json:"merge_commit_title,omitempty"` + MergeCommitMessage *string `json:"merge_commit_message,omitempty"` +} + +// Create a new repository. If an organization is specified, the new +// repository will be created under that org. If the empty string is +// specified, it will be created for the authenticated user. +// +// Note that only a subset of the repo fields are used and repo must +// not be nil. +// +// Also note that this method will return the response without actually +// waiting for GitHub to finish creating the repository and letting the +// changes propagate throughout its servers. You may set up a loop with +// exponential back-off to verify repository's creation. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#create-a-repository-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/rest/repos/repos#create-an-organization-repository +// +//meta:operation POST /orgs/{org}/repos +//meta:operation POST /user/repos +func (s *RepositoriesService) Create(ctx context.Context, org string, repo *Repository) (*Repository, *Response, error) { + var u string + if org != "" { + u = fmt.Sprintf("orgs/%v/repos", org) + } else { + u = "user/repos" + } + + repoReq := &createRepoRequest{ + Name: repo.Name, + Description: repo.Description, + Homepage: repo.Homepage, + Private: repo.Private, + Visibility: repo.Visibility, + HasIssues: repo.HasIssues, + HasProjects: repo.HasProjects, + HasWiki: repo.HasWiki, + HasDiscussions: repo.HasDiscussions, + IsTemplate: repo.IsTemplate, + TeamID: repo.TeamID, + AutoInit: repo.AutoInit, + GitignoreTemplate: repo.GitignoreTemplate, + LicenseTemplate: repo.LicenseTemplate, + AllowSquashMerge: repo.AllowSquashMerge, + AllowMergeCommit: repo.AllowMergeCommit, + AllowRebaseMerge: repo.AllowRebaseMerge, + AllowUpdateBranch: repo.AllowUpdateBranch, + AllowAutoMerge: repo.AllowAutoMerge, + AllowForking: repo.AllowForking, + DeleteBranchOnMerge: repo.DeleteBranchOnMerge, + UseSquashPRTitleAsDefault: repo.UseSquashPRTitleAsDefault, + SquashMergeCommitTitle: repo.SquashMergeCommitTitle, + SquashMergeCommitMessage: repo.SquashMergeCommitMessage, + MergeCommitTitle: repo.MergeCommitTitle, + MergeCommitMessage: repo.MergeCommitMessage, + } + + req, err := s.client.NewRequest("POST", u, repoReq) + if err != nil { + return nil, nil, err + } + + acceptHeaders := []string{mediaTypeRepositoryTemplatePreview, mediaTypeRepositoryVisibilityPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// TemplateRepoRequest represents a request to create a repository from a template. +type TemplateRepoRequest struct { + // Name is required when creating a repo. + Name *string `json:"name,omitempty"` + Owner *string `json:"owner,omitempty"` + Description *string `json:"description,omitempty"` + + IncludeAllBranches *bool `json:"include_all_branches,omitempty"` + Private *bool `json:"private,omitempty"` +} + +// CreateFromTemplate generates a repository from a template. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#create-a-repository-using-a-template +// +//meta:operation POST /repos/{template_owner}/{template_repo}/generate +func (s *RepositoriesService) CreateFromTemplate(ctx context.Context, templateOwner, templateRepo string, templateRepoReq *TemplateRepoRequest) (*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/generate", templateOwner, templateRepo) + + req, err := s.client.NewRequest("POST", u, templateRepoReq) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeRepositoryTemplatePreview) + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// Get fetches a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#get-a-repository +// +//meta:operation GET /repos/{owner}/{repo} +func (s *RepositoriesService) Get(ctx context.Context, owner, repo string) (*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when the license support fully launches + // https://docs.github.com/rest/licenses/#get-a-repositorys-license + acceptHeaders := []string{ + mediaTypeCodesOfConductPreview, + mediaTypeTopicsPreview, + mediaTypeRepositoryTemplatePreview, + mediaTypeRepositoryVisibilityPreview, + } + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + repository := new(Repository) + resp, err := s.client.Do(ctx, req, repository) + if err != nil { + return nil, resp, err + } + + return repository, resp, nil +} + +// GetCodeOfConduct gets the contents of a repository's code of conduct. +// Note that https://docs.github.com/rest/codes-of-conduct#about-the-codes-of-conduct-api +// says to use the GET /repos/{owner}/{repo} endpoint. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#get-a-repository +// +//meta:operation GET /repos/{owner}/{repo} +func (s *RepositoriesService) GetCodeOfConduct(ctx context.Context, owner, repo string) (*CodeOfConduct, *Response, error) { + u := fmt.Sprintf("repos/%v/%v", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeCodesOfConductPreview) + + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r.GetCodeOfConduct(), resp, nil +} + +// GetByID fetches a repository. +// +// Note: GetByID uses the undocumented GitHub API endpoint "GET /repositories/{repository_id}". +// +//meta:operation GET /repositories/{repository_id} +func (s *RepositoriesService) GetByID(ctx context.Context, id int64) (*Repository, *Response, error) { + u := fmt.Sprintf("repositories/%d", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + repository := new(Repository) + resp, err := s.client.Do(ctx, req, repository) + if err != nil { + return nil, resp, err + } + + return repository, resp, nil +} + +// Edit updates a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#update-a-repository +// +//meta:operation PATCH /repos/{owner}/{repo} +func (s *RepositoriesService) Edit(ctx context.Context, owner, repo string, repository *Repository) (*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v", owner, repo) + req, err := s.client.NewRequest("PATCH", u, repository) + if err != nil { + return nil, nil, err + } + + acceptHeaders := []string{mediaTypeRepositoryTemplatePreview, mediaTypeRepositoryVisibilityPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// Delete a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#delete-a-repository +// +//meta:operation DELETE /repos/{owner}/{repo} +func (s *RepositoriesService) Delete(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v", owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Contributor represents a repository contributor. +type Contributor struct { + Login *string `json:"login,omitempty"` + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + AvatarURL *string `json:"avatar_url,omitempty"` + GravatarID *string `json:"gravatar_id,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + FollowersURL *string `json:"followers_url,omitempty"` + FollowingURL *string `json:"following_url,omitempty"` + GistsURL *string `json:"gists_url,omitempty"` + StarredURL *string `json:"starred_url,omitempty"` + SubscriptionsURL *string `json:"subscriptions_url,omitempty"` + OrganizationsURL *string `json:"organizations_url,omitempty"` + ReposURL *string `json:"repos_url,omitempty"` + EventsURL *string `json:"events_url,omitempty"` + ReceivedEventsURL *string `json:"received_events_url,omitempty"` + Type *string `json:"type,omitempty"` + SiteAdmin *bool `json:"site_admin,omitempty"` + Contributions *int `json:"contributions,omitempty"` + Name *string `json:"name,omitempty"` + Email *string `json:"email,omitempty"` +} + +// ListContributorsOptions specifies the optional parameters to the +// RepositoriesService.ListContributors method. +type ListContributorsOptions struct { + // Include anonymous contributors in results or not + Anon string `url:"anon,omitempty"` + + ListOptions +} + +// GetVulnerabilityAlerts checks if vulnerability alerts are enabled for a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#check-if-vulnerability-alerts-are-enabled-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/vulnerability-alerts +func (s *RepositoriesService) GetVulnerabilityAlerts(ctx context.Context, owner, repository string) (bool, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/vulnerability-alerts", owner, repository) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredVulnerabilityAlertsPreview) + + resp, err := s.client.Do(ctx, req, nil) + vulnerabilityAlertsEnabled, err := parseBoolResponse(err) + return vulnerabilityAlertsEnabled, resp, err +} + +// EnableVulnerabilityAlerts enables vulnerability alerts and the dependency graph for a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#enable-vulnerability-alerts +// +//meta:operation PUT /repos/{owner}/{repo}/vulnerability-alerts +func (s *RepositoriesService) EnableVulnerabilityAlerts(ctx context.Context, owner, repository string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/vulnerability-alerts", owner, repository) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredVulnerabilityAlertsPreview) + + return s.client.Do(ctx, req, nil) +} + +// DisableVulnerabilityAlerts disables vulnerability alerts and the dependency graph for a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#disable-vulnerability-alerts +// +//meta:operation DELETE /repos/{owner}/{repo}/vulnerability-alerts +func (s *RepositoriesService) DisableVulnerabilityAlerts(ctx context.Context, owner, repository string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/vulnerability-alerts", owner, repository) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredVulnerabilityAlertsPreview) + + return s.client.Do(ctx, req, nil) +} + +// GetAutomatedSecurityFixes checks if the automated security fixes for a repository are enabled. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#check-if-automated-security-fixes-are-enabled-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/automated-security-fixes +func (s *RepositoriesService) GetAutomatedSecurityFixes(ctx context.Context, owner, repository string) (*AutomatedSecurityFixes, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/automated-security-fixes", owner, repository) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + p := new(AutomatedSecurityFixes) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + return p, resp, nil +} + +// EnableAutomatedSecurityFixes enables the automated security fixes for a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#enable-automated-security-fixes +// +//meta:operation PUT /repos/{owner}/{repo}/automated-security-fixes +func (s *RepositoriesService) EnableAutomatedSecurityFixes(ctx context.Context, owner, repository string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/automated-security-fixes", owner, repository) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DisableAutomatedSecurityFixes disables vulnerability alerts and the dependency graph for a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#disable-automated-security-fixes +// +//meta:operation DELETE /repos/{owner}/{repo}/automated-security-fixes +func (s *RepositoriesService) DisableAutomatedSecurityFixes(ctx context.Context, owner, repository string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/automated-security-fixes", owner, repository) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListContributors lists contributors for a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-repository-contributors +// +//meta:operation GET /repos/{owner}/{repo}/contributors +func (s *RepositoriesService) ListContributors(ctx context.Context, owner string, repository string, opts *ListContributorsOptions) ([]*Contributor, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/contributors", owner, repository) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var contributor []*Contributor + resp, err := s.client.Do(ctx, req, &contributor) + if err != nil { + return nil, resp, err + } + + return contributor, resp, nil +} + +// ListLanguages lists languages for the specified repository. The returned map +// specifies the languages and the number of bytes of code written in that +// language. For example: +// +// { +// "C": 78769, +// "Python": 7769 +// } +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-repository-languages +// +//meta:operation GET /repos/{owner}/{repo}/languages +func (s *RepositoriesService) ListLanguages(ctx context.Context, owner string, repo string) (map[string]int, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/languages", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + languages := make(map[string]int) + resp, err := s.client.Do(ctx, req, &languages) + if err != nil { + return nil, resp, err + } + + return languages, resp, nil +} + +// ListTeams lists the teams for the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-repository-teams +// +//meta:operation GET /repos/{owner}/{repo}/teams +func (s *RepositoriesService) ListTeams(ctx context.Context, owner string, repo string, opts *ListOptions) ([]*Team, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/teams", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// RepositoryTag represents a repository tag. +type RepositoryTag struct { + Name *string `json:"name,omitempty"` + Commit *Commit `json:"commit,omitempty"` + ZipballURL *string `json:"zipball_url,omitempty"` + TarballURL *string `json:"tarball_url,omitempty"` +} + +// ListTags lists tags for the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-repository-tags +// +//meta:operation GET /repos/{owner}/{repo}/tags +func (s *RepositoriesService) ListTags(ctx context.Context, owner string, repo string, opts *ListOptions) ([]*RepositoryTag, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/tags", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var tags []*RepositoryTag + resp, err := s.client.Do(ctx, req, &tags) + if err != nil { + return nil, resp, err + } + + return tags, resp, nil +} + +// Branch represents a repository branch. +type Branch struct { + Name *string `json:"name,omitempty"` + Commit *RepositoryCommit `json:"commit,omitempty"` + Protected *bool `json:"protected,omitempty"` + + // Protection will always be included in APIs which return the + // 'Branch With Protection' schema such as 'Get a branch', but may + // not be included in APIs that return the `Short Branch` schema + // such as 'List branches'. In such cases, if branch protection is + // enabled, Protected will be `true` but this will be nil, and + // additional protection details can be obtained by calling GetBranch(). + Protection *Protection `json:"protection,omitempty"` +} + +// Protection represents a repository branch's protection. +type Protection struct { + RequiredStatusChecks *RequiredStatusChecks `json:"required_status_checks"` + RequiredPullRequestReviews *PullRequestReviewsEnforcement `json:"required_pull_request_reviews"` + EnforceAdmins *AdminEnforcement `json:"enforce_admins"` + Restrictions *BranchRestrictions `json:"restrictions"` + RequireLinearHistory *RequireLinearHistory `json:"required_linear_history"` + AllowForcePushes *AllowForcePushes `json:"allow_force_pushes"` + AllowDeletions *AllowDeletions `json:"allow_deletions"` + RequiredConversationResolution *RequiredConversationResolution `json:"required_conversation_resolution"` + BlockCreations *BlockCreations `json:"block_creations,omitempty"` + LockBranch *LockBranch `json:"lock_branch,omitempty"` + AllowForkSyncing *AllowForkSyncing `json:"allow_fork_syncing,omitempty"` + RequiredSignatures *SignaturesProtectedBranch `json:"required_signatures,omitempty"` + URL *string `json:"url,omitempty"` +} + +// BlockCreations represents whether users can push changes that create branches. If this is true, this +// setting blocks pushes that create new branches, unless the push is initiated by a user, team, or app +// which has the ability to push. +type BlockCreations struct { + Enabled *bool `json:"enabled,omitempty"` +} + +// LockBranch represents if the branch is marked as read-only. If this is true, users will not be able to push to the branch. +type LockBranch struct { + Enabled *bool `json:"enabled,omitempty"` +} + +// AllowForkSyncing represents whether users can pull changes from upstream when the branch is locked. +type AllowForkSyncing struct { + Enabled *bool `json:"enabled,omitempty"` +} + +// BranchProtectionRule represents the rule applied to a repositories branch. +type BranchProtectionRule struct { + ID *int64 `json:"id,omitempty"` + RepositoryID *int64 `json:"repository_id,omitempty"` + Name *string `json:"name,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + PullRequestReviewsEnforcementLevel *string `json:"pull_request_reviews_enforcement_level,omitempty"` + RequiredApprovingReviewCount *int `json:"required_approving_review_count,omitempty"` + DismissStaleReviewsOnPush *bool `json:"dismiss_stale_reviews_on_push,omitempty"` + AuthorizedDismissalActorsOnly *bool `json:"authorized_dismissal_actors_only,omitempty"` + IgnoreApprovalsFromContributors *bool `json:"ignore_approvals_from_contributors,omitempty"` + RequireCodeOwnerReview *bool `json:"require_code_owner_review,omitempty"` + RequiredStatusChecks []string `json:"required_status_checks,omitempty"` + RequiredStatusChecksEnforcementLevel *string `json:"required_status_checks_enforcement_level,omitempty"` + StrictRequiredStatusChecksPolicy *bool `json:"strict_required_status_checks_policy,omitempty"` + SignatureRequirementEnforcementLevel *string `json:"signature_requirement_enforcement_level,omitempty"` + LinearHistoryRequirementEnforcementLevel *string `json:"linear_history_requirement_enforcement_level,omitempty"` + AdminEnforced *bool `json:"admin_enforced,omitempty"` + AllowForcePushesEnforcementLevel *string `json:"allow_force_pushes_enforcement_level,omitempty"` + AllowDeletionsEnforcementLevel *string `json:"allow_deletions_enforcement_level,omitempty"` + MergeQueueEnforcementLevel *string `json:"merge_queue_enforcement_level,omitempty"` + RequiredDeploymentsEnforcementLevel *string `json:"required_deployments_enforcement_level,omitempty"` + RequiredConversationResolutionLevel *string `json:"required_conversation_resolution_level,omitempty"` + AuthorizedActorsOnly *bool `json:"authorized_actors_only,omitempty"` + AuthorizedActorNames []string `json:"authorized_actor_names,omitempty"` +} + +// ProtectionChanges represents the changes to the rule if the BranchProtection was edited. +type ProtectionChanges struct { + AdminEnforced *AdminEnforcedChanges `json:"admin_enforced,omitempty"` + AllowDeletionsEnforcementLevel *AllowDeletionsEnforcementLevelChanges `json:"allow_deletions_enforcement_level,omitempty"` + AuthorizedActorNames *AuthorizedActorNames `json:"authorized_actor_names,omitempty"` + AuthorizedActorsOnly *AuthorizedActorsOnly `json:"authorized_actors_only,omitempty"` + AuthorizedDismissalActorsOnly *AuthorizedDismissalActorsOnlyChanges `json:"authorized_dismissal_actors_only,omitempty"` + CreateProtected *CreateProtectedChanges `json:"create_protected,omitempty"` + DismissStaleReviewsOnPush *DismissStaleReviewsOnPushChanges `json:"dismiss_stale_reviews_on_push,omitempty"` + LinearHistoryRequirementEnforcementLevel *LinearHistoryRequirementEnforcementLevelChanges `json:"linear_history_requirement_enforcement_level,omitempty"` + PullRequestReviewsEnforcementLevel *PullRequestReviewsEnforcementLevelChanges `json:"pull_request_reviews_enforcement_level,omitempty"` + RequireCodeOwnerReview *RequireCodeOwnerReviewChanges `json:"require_code_owner_review,omitempty"` + RequiredConversationResolutionLevel *RequiredConversationResolutionLevelChanges `json:"required_conversation_resolution_level,omitempty"` + RequiredDeploymentsEnforcementLevel *RequiredDeploymentsEnforcementLevelChanges `json:"required_deployments_enforcement_level,omitempty"` + RequiredStatusChecks *RequiredStatusChecksChanges `json:"required_status_checks,omitempty"` + RequiredStatusChecksEnforcementLevel *RequiredStatusChecksEnforcementLevelChanges `json:"required_status_checks_enforcement_level,omitempty"` + SignatureRequirementEnforcementLevel *SignatureRequirementEnforcementLevelChanges `json:"signature_requirement_enforcement_level,omitempty"` +} + +// AdminEnforcedChanges represents the changes made to the AdminEnforced policy. +type AdminEnforcedChanges struct { + From *bool `json:"from,omitempty"` +} + +// AllowDeletionsEnforcementLevelChanges represents the changes made to the AllowDeletionsEnforcementLevel policy. +type AllowDeletionsEnforcementLevelChanges struct { + From *string `json:"from,omitempty"` +} + +// AuthorizedActorNames represents who are authorized to edit the branch protection rules. +type AuthorizedActorNames struct { + From []string `json:"from,omitempty"` +} + +// AuthorizedActorsOnly represents if the branch rule can be edited by authorized actors only. +type AuthorizedActorsOnly struct { + From *bool `json:"from,omitempty"` +} + +// AuthorizedDismissalActorsOnlyChanges represents the changes made to the AuthorizedDismissalActorsOnly policy. +type AuthorizedDismissalActorsOnlyChanges struct { + From *bool `json:"from,omitempty"` +} + +// CreateProtectedChanges represents the changes made to the CreateProtected policy. +type CreateProtectedChanges struct { + From *bool `json:"from,omitempty"` +} + +// DismissStaleReviewsOnPushChanges represents the changes made to the DismissStaleReviewsOnPushChanges policy. +type DismissStaleReviewsOnPushChanges struct { + From *bool `json:"from,omitempty"` +} + +// LinearHistoryRequirementEnforcementLevelChanges represents the changes made to the LinearHistoryRequirementEnforcementLevel policy. +type LinearHistoryRequirementEnforcementLevelChanges struct { + From *string `json:"from,omitempty"` +} + +// PullRequestReviewsEnforcementLevelChanges represents the changes made to the PullRequestReviewsEnforcementLevel policy. +type PullRequestReviewsEnforcementLevelChanges struct { + From *string `json:"from,omitempty"` +} + +// RequireCodeOwnerReviewChanges represents the changes made to the RequireCodeOwnerReview policy. +type RequireCodeOwnerReviewChanges struct { + From *bool `json:"from,omitempty"` +} + +// RequiredConversationResolutionLevelChanges represents the changes made to the RequiredConversationResolutionLevel policy. +type RequiredConversationResolutionLevelChanges struct { + From *string `json:"from,omitempty"` +} + +// RequiredDeploymentsEnforcementLevelChanges represents the changes made to the RequiredDeploymentsEnforcementLevel policy. +type RequiredDeploymentsEnforcementLevelChanges struct { + From *string `json:"from,omitempty"` +} + +// RequiredStatusChecksChanges represents the changes made to the RequiredStatusChecks policy. +type RequiredStatusChecksChanges struct { + From []string `json:"from,omitempty"` +} + +// RequiredStatusChecksEnforcementLevelChanges represents the changes made to the RequiredStatusChecksEnforcementLevel policy. +type RequiredStatusChecksEnforcementLevelChanges struct { + From *string `json:"from,omitempty"` +} + +// SignatureRequirementEnforcementLevelChanges represents the changes made to the SignatureRequirementEnforcementLevel policy. +type SignatureRequirementEnforcementLevelChanges struct { + From *string `json:"from,omitempty"` +} + +// ProtectionRequest represents a request to create/edit a branch's protection. +type ProtectionRequest struct { + RequiredStatusChecks *RequiredStatusChecks `json:"required_status_checks"` + RequiredPullRequestReviews *PullRequestReviewsEnforcementRequest `json:"required_pull_request_reviews"` + EnforceAdmins bool `json:"enforce_admins"` + Restrictions *BranchRestrictionsRequest `json:"restrictions"` + // Enforces a linear commit Git history, which prevents anyone from pushing merge commits to a branch. + RequireLinearHistory *bool `json:"required_linear_history,omitempty"` + // Permits force pushes to the protected branch by anyone with write access to the repository. + AllowForcePushes *bool `json:"allow_force_pushes,omitempty"` + // Allows deletion of the protected branch by anyone with write access to the repository. + AllowDeletions *bool `json:"allow_deletions,omitempty"` + // RequiredConversationResolution, if set to true, requires all comments + // on the pull request to be resolved before it can be merged to a protected branch. + RequiredConversationResolution *bool `json:"required_conversation_resolution,omitempty"` + // BlockCreations, if set to true, will cause the restrictions setting to also block pushes + // which create new branches, unless initiated by a user, team, app with the ability to push. + BlockCreations *bool `json:"block_creations,omitempty"` + // LockBranch, if set to true, will prevent users from pushing to the branch. + LockBranch *bool `json:"lock_branch,omitempty"` + // AllowForkSyncing, if set to true, will allow users to pull changes from upstream + // when the branch is locked. + AllowForkSyncing *bool `json:"allow_fork_syncing,omitempty"` +} + +// RequiredStatusChecks represents the protection status of a individual branch. +type RequiredStatusChecks struct { + // Require branches to be up to date before merging. (Required.) + Strict bool `json:"strict"` + // The list of status checks to require in order to merge into this + // branch. An empty slice is valid. (Deprecated. Note: only one of + // Contexts/Checks can be populated, but at least one must be populated). + Contexts *[]string `json:"contexts,omitempty"` + // The list of status checks to require in order to merge into this + // branch. An empty slice is valid. + Checks *[]*RequiredStatusCheck `json:"checks,omitempty"` + ContextsURL *string `json:"contexts_url,omitempty"` + URL *string `json:"url,omitempty"` +} + +// RequiredStatusChecksRequest represents a request to edit a protected branch's status checks. +type RequiredStatusChecksRequest struct { + Strict *bool `json:"strict,omitempty"` + // Deprecated. Note: if both Contexts and Checks are populated, + // the GitHub API will only use Checks. + Contexts []string `json:"contexts,omitempty"` + Checks []*RequiredStatusCheck `json:"checks,omitempty"` +} + +// RequiredStatusCheck represents a status check of a protected branch. +type RequiredStatusCheck struct { + // The name of the required check. + Context string `json:"context"` + // The ID of the GitHub App that must provide this check. + // Omit this field to automatically select the GitHub App + // that has recently provided this check, + // or any app if it was not set by a GitHub App. + // Pass -1 to explicitly allow any app to set the status. + AppID *int64 `json:"app_id,omitempty"` +} + +// PullRequestReviewsEnforcement represents the pull request reviews enforcement of a protected branch. +type PullRequestReviewsEnforcement struct { + // Allow specific users, teams, or apps to bypass pull request requirements. + BypassPullRequestAllowances *BypassPullRequestAllowances `json:"bypass_pull_request_allowances,omitempty"` + // Specifies which users, teams and apps can dismiss pull request reviews. + DismissalRestrictions *DismissalRestrictions `json:"dismissal_restrictions,omitempty"` + // Specifies if approved reviews are dismissed automatically, when a new commit is pushed. + DismissStaleReviews bool `json:"dismiss_stale_reviews"` + // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner. + RequireCodeOwnerReviews bool `json:"require_code_owner_reviews"` + // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged. + // Valid values are 1-6. + RequiredApprovingReviewCount int `json:"required_approving_review_count"` + // RequireLastPushApproval specifies whether the last pusher to a pull request branch can approve it. + RequireLastPushApproval bool `json:"require_last_push_approval"` +} + +// PullRequestReviewsEnforcementRequest represents request to set the pull request review +// enforcement of a protected branch. It is separate from PullRequestReviewsEnforcement above +// because the request structure is different from the response structure. +type PullRequestReviewsEnforcementRequest struct { + // Allow specific users, teams, or apps to bypass pull request requirements. + BypassPullRequestAllowancesRequest *BypassPullRequestAllowancesRequest `json:"bypass_pull_request_allowances,omitempty"` + // Specifies which users, teams and apps should be allowed to dismiss pull request reviews. + // User, team and app dismissal restrictions are only available for + // organization-owned repositories. Must be nil for personal repositories. + DismissalRestrictionsRequest *DismissalRestrictionsRequest `json:"dismissal_restrictions,omitempty"` + // Specifies if approved reviews can be dismissed automatically, when a new commit is pushed. (Required) + DismissStaleReviews bool `json:"dismiss_stale_reviews"` + // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner. + RequireCodeOwnerReviews bool `json:"require_code_owner_reviews"` + // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged. + // Valid values are 1-6. + RequiredApprovingReviewCount int `json:"required_approving_review_count"` + // RequireLastPushApproval specifies whether the last pusher to a pull request branch can approve it. + RequireLastPushApproval *bool `json:"require_last_push_approval,omitempty"` +} + +// PullRequestReviewsEnforcementUpdate represents request to patch the pull request review +// enforcement of a protected branch. It is separate from PullRequestReviewsEnforcementRequest above +// because the patch request does not require all fields to be initialized. +type PullRequestReviewsEnforcementUpdate struct { + // Allow specific users, teams, or apps to bypass pull request requirements. + BypassPullRequestAllowancesRequest *BypassPullRequestAllowancesRequest `json:"bypass_pull_request_allowances,omitempty"` + // Specifies which users, teams and apps can dismiss pull request reviews. Can be omitted. + DismissalRestrictionsRequest *DismissalRestrictionsRequest `json:"dismissal_restrictions,omitempty"` + // Specifies if approved reviews can be dismissed automatically, when a new commit is pushed. Can be omitted. + DismissStaleReviews *bool `json:"dismiss_stale_reviews,omitempty"` + // RequireCodeOwnerReviews specifies if merging pull requests is blocked until code owners have reviewed. + RequireCodeOwnerReviews *bool `json:"require_code_owner_reviews,omitempty"` + // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged. + // Valid values are 1 - 6 or 0 to not require reviewers. + RequiredApprovingReviewCount int `json:"required_approving_review_count"` + // RequireLastPushApproval specifies whether the last pusher to a pull request branch can approve it. + RequireLastPushApproval *bool `json:"require_last_push_approval,omitempty"` +} + +// RequireLinearHistory represents the configuration to enforce branches with no merge commit. +type RequireLinearHistory struct { + Enabled bool `json:"enabled"` +} + +// AllowDeletions represents the configuration to accept deletion of protected branches. +type AllowDeletions struct { + Enabled bool `json:"enabled"` +} + +// AllowForcePushes represents the configuration to accept forced pushes on protected branches. +type AllowForcePushes struct { + Enabled bool `json:"enabled"` +} + +// RequiredConversationResolution requires all comments on the pull request to be resolved before it can be +// merged to a protected branch when enabled. +type RequiredConversationResolution struct { + Enabled bool `json:"enabled"` +} + +// AdminEnforcement represents the configuration to enforce required status checks for repository administrators. +type AdminEnforcement struct { + URL *string `json:"url,omitempty"` + Enabled bool `json:"enabled"` +} + +// BranchRestrictions represents the restriction that only certain users or +// teams may push to a branch. +type BranchRestrictions struct { + // The list of user logins with push access. + Users []*User `json:"users"` + // The list of team slugs with push access. + Teams []*Team `json:"teams"` + // The list of app slugs with push access. + Apps []*App `json:"apps"` +} + +// BranchRestrictionsRequest represents the request to create/edit the +// restriction that only certain users or teams may push to a branch. It is +// separate from BranchRestrictions above because the request structure is +// different from the response structure. +type BranchRestrictionsRequest struct { + // The list of user logins with push access. (Required; use []string{} instead of nil for empty list.) + Users []string `json:"users"` + // The list of team slugs with push access. (Required; use []string{} instead of nil for empty list.) + Teams []string `json:"teams"` + // The list of app slugs with push access. + Apps []string `json:"apps"` +} + +// BypassPullRequestAllowances represents the people, teams, or apps who are allowed to bypass required pull requests. +type BypassPullRequestAllowances struct { + // The list of users allowed to bypass pull request requirements. + Users []*User `json:"users"` + // The list of teams allowed to bypass pull request requirements. + Teams []*Team `json:"teams"` + // The list of apps allowed to bypass pull request requirements. + Apps []*App `json:"apps"` +} + +// BypassPullRequestAllowancesRequest represents the people, teams, or apps who are +// allowed to bypass required pull requests. +// It is separate from BypassPullRequestAllowances above because the request structure is +// different from the response structure. +type BypassPullRequestAllowancesRequest struct { + // The list of user logins allowed to bypass pull request requirements. + Users []string `json:"users"` + // The list of team slugs allowed to bypass pull request requirements. + Teams []string `json:"teams"` + // The list of app slugs allowed to bypass pull request requirements. + Apps []string `json:"apps"` +} + +// DismissalRestrictions specifies which users and teams can dismiss pull request reviews. +type DismissalRestrictions struct { + // The list of users who can dismiss pull request reviews. + Users []*User `json:"users"` + // The list of teams which can dismiss pull request reviews. + Teams []*Team `json:"teams"` + // The list of apps which can dismiss pull request reviews. + Apps []*App `json:"apps"` +} + +// DismissalRestrictionsRequest represents the request to create/edit the +// restriction to allows only specific users, teams or apps to dismiss pull request reviews. It is +// separate from DismissalRestrictions above because the request structure is +// different from the response structure. +// Note: Both Users and Teams must be nil, or both must be non-nil. +type DismissalRestrictionsRequest struct { + // The list of user logins who can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.) + Users *[]string `json:"users,omitempty"` + // The list of team slugs which can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.) + Teams *[]string `json:"teams,omitempty"` + // The list of app slugs which can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.) + Apps *[]string `json:"apps,omitempty"` +} + +// SignaturesProtectedBranch represents the protection status of an individual branch. +type SignaturesProtectedBranch struct { + URL *string `json:"url,omitempty"` + // Commits pushed to matching branches must have verified signatures. + Enabled *bool `json:"enabled,omitempty"` +} + +// AutomatedSecurityFixes represents their status. +type AutomatedSecurityFixes struct { + Enabled *bool `json:"enabled"` + Paused *bool `json:"paused"` +} + +// ListBranches lists branches for the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/branches/branches#list-branches +// +//meta:operation GET /repos/{owner}/{repo}/branches +func (s *RepositoriesService) ListBranches(ctx context.Context, owner string, repo string, opts *BranchListOptions) ([]*Branch, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var branches []*Branch + resp, err := s.client.Do(ctx, req, &branches) + if err != nil { + return nil, resp, err + } + + return branches, resp, nil +} + +// GetBranch gets the specified branch for a repository. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branches#get-a-branch +// +//meta:operation GET /repos/{owner}/{repo}/branches/{branch} +func (s *RepositoriesService) GetBranch(ctx context.Context, owner, repo, branch string, maxRedirects int) (*Branch, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v", owner, repo, url.PathEscape(branch)) + + resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, maxRedirects) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + } + + b := new(Branch) + err = json.NewDecoder(resp.Body).Decode(b) + return b, newResponse(resp), err +} + +// renameBranchRequest represents a request to rename a branch. +type renameBranchRequest struct { + NewName string `json:"new_name"` +} + +// RenameBranch renames a branch in a repository. +// +// To rename a non-default branch: Users must have push access. GitHub Apps must have the `contents:write` repository permission. +// To rename the default branch: Users must have admin or owner permissions. GitHub Apps must have the `administration:write` repository permission. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branches#rename-a-branch +// +//meta:operation POST /repos/{owner}/{repo}/branches/{branch}/rename +func (s *RepositoriesService) RenameBranch(ctx context.Context, owner, repo, branch, newName string) (*Branch, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/rename", owner, repo, url.PathEscape(branch)) + r := &renameBranchRequest{NewName: newName} + req, err := s.client.NewRequest("POST", u, r) + if err != nil { + return nil, nil, err + } + + b := new(Branch) + resp, err := s.client.Do(ctx, req, b) + if err != nil { + return nil, resp, err + } + + return b, resp, nil +} + +// GetBranchProtection gets the protection of a given branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#get-branch-protection +// +//meta:operation GET /repos/{owner}/{repo}/branches/{branch}/protection +func (s *RepositoriesService) GetBranchProtection(ctx context.Context, owner, repo, branch string) (*Protection, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) + + p := new(Protection) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + if isBranchNotProtected(err) { + err = ErrBranchNotProtected + } + return nil, resp, err + } + + return p, resp, nil +} + +// GetRequiredStatusChecks gets the required status checks for a given protected branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#get-status-checks-protection +// +//meta:operation GET /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks +func (s *RepositoriesService) GetRequiredStatusChecks(ctx context.Context, owner, repo, branch string) (*RequiredStatusChecks, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + p := new(RequiredStatusChecks) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + if isBranchNotProtected(err) { + err = ErrBranchNotProtected + } + return nil, resp, err + } + + return p, resp, nil +} + +// ListRequiredStatusChecksContexts lists the required status checks contexts for a given protected branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#get-all-status-check-contexts +// +//meta:operation GET /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts +func (s *RepositoriesService) ListRequiredStatusChecksContexts(ctx context.Context, owner, repo, branch string) (contexts []string, resp *Response, err error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks/contexts", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + resp, err = s.client.Do(ctx, req, &contexts) + if err != nil { + if isBranchNotProtected(err) { + err = ErrBranchNotProtected + } + return nil, resp, err + } + + return contexts, resp, nil +} + +// UpdateBranchProtection updates the protection of a given branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#update-branch-protection +// +//meta:operation PUT /repos/{owner}/{repo}/branches/{branch}/protection +func (s *RepositoriesService) UpdateBranchProtection(ctx context.Context, owner, repo, branch string, preq *ProtectionRequest) (*Protection, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("PUT", u, preq) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) + + p := new(Protection) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// RemoveBranchProtection removes the protection of a given branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#delete-branch-protection +// +//meta:operation DELETE /repos/{owner}/{repo}/branches/{branch}/protection +func (s *RepositoriesService) RemoveBranchProtection(ctx context.Context, owner, repo, branch string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// GetSignaturesProtectedBranch gets required signatures of protected branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#get-commit-signature-protection +// +//meta:operation GET /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures +func (s *RepositoriesService) GetSignaturesProtectedBranch(ctx context.Context, owner, repo, branch string) (*SignaturesProtectedBranch, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeSignaturePreview) + + p := new(SignaturesProtectedBranch) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// RequireSignaturesOnProtectedBranch makes signed commits required on a protected branch. +// It requires admin access and branch protection to be enabled. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#create-commit-signature-protection +// +//meta:operation POST /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures +func (s *RepositoriesService) RequireSignaturesOnProtectedBranch(ctx context.Context, owner, repo, branch string) (*SignaturesProtectedBranch, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeSignaturePreview) + + r := new(SignaturesProtectedBranch) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// OptionalSignaturesOnProtectedBranch removes required signed commits on a given branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#delete-commit-signature-protection +// +//meta:operation DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures +func (s *RepositoriesService) OptionalSignaturesOnProtectedBranch(ctx context.Context, owner, repo, branch string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeSignaturePreview) + + return s.client.Do(ctx, req, nil) +} + +// UpdateRequiredStatusChecks updates the required status checks for a given protected branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#update-status-check-protection +// +//meta:operation PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks +func (s *RepositoriesService) UpdateRequiredStatusChecks(ctx context.Context, owner, repo, branch string, sreq *RequiredStatusChecksRequest) (*RequiredStatusChecks, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("PATCH", u, sreq) + if err != nil { + return nil, nil, err + } + + sc := new(RequiredStatusChecks) + resp, err := s.client.Do(ctx, req, sc) + if err != nil { + return nil, resp, err + } + + return sc, resp, nil +} + +// RemoveRequiredStatusChecks removes the required status checks for a given protected branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#remove-status-check-protection +// +//meta:operation DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks +func (s *RepositoriesService) RemoveRequiredStatusChecks(ctx context.Context, owner, repo, branch string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// License gets the contents of a repository's license if one is detected. +// +// GitHub API docs: https://docs.github.com/rest/licenses/licenses#get-the-license-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/license +func (s *RepositoriesService) License(ctx context.Context, owner, repo string) (*RepositoryLicense, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/license", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + r := &RepositoryLicense{} + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// GetPullRequestReviewEnforcement gets pull request review enforcement of a protected branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#get-pull-request-review-protection +// +//meta:operation GET /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews +func (s *RepositoriesService) GetPullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) + + r := new(PullRequestReviewsEnforcement) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// UpdatePullRequestReviewEnforcement patches pull request review enforcement of a protected branch. +// It requires admin access and branch protection to be enabled. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#update-pull-request-review-protection +// +//meta:operation PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews +func (s *RepositoriesService) UpdatePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string, patch *PullRequestReviewsEnforcementUpdate) (*PullRequestReviewsEnforcement, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("PATCH", u, patch) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) + + r := new(PullRequestReviewsEnforcement) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// DisableDismissalRestrictions disables dismissal restrictions of a protected branch. +// It requires admin access and branch protection to be enabled. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#update-pull-request-review-protection +// +//meta:operation PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews +func (s *RepositoriesService) DisableDismissalRestrictions(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, url.PathEscape(branch)) + + data := new(struct { + DismissalRestrictionsRequest `json:"dismissal_restrictions"` + }) + + req, err := s.client.NewRequest("PATCH", u, data) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) + + r := new(PullRequestReviewsEnforcement) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// RemovePullRequestReviewEnforcement removes pull request enforcement of a protected branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#delete-pull-request-review-protection +// +//meta:operation DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews +func (s *RepositoriesService) RemovePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// GetAdminEnforcement gets admin enforcement information of a protected branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#get-admin-branch-protection +// +//meta:operation GET /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins +func (s *RepositoriesService) GetAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + r := new(AdminEnforcement) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// AddAdminEnforcement adds admin enforcement to a protected branch. +// It requires admin access and branch protection to be enabled. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#set-admin-branch-protection +// +//meta:operation POST /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins +func (s *RepositoriesService) AddAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + r := new(AdminEnforcement) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// RemoveAdminEnforcement removes admin enforcement from a protected branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#delete-admin-branch-protection +// +//meta:operation DELETE /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins +func (s *RepositoriesService) RemoveAdminEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// repositoryTopics represents a collection of repository topics. +type repositoryTopics struct { + Names []string `json:"names"` +} + +// ListAllTopics lists topics for a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#get-all-repository-topics +// +//meta:operation GET /repos/{owner}/{repo}/topics +func (s *RepositoriesService) ListAllTopics(ctx context.Context, owner, repo string) ([]string, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/topics", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeTopicsPreview) + + topics := new(repositoryTopics) + resp, err := s.client.Do(ctx, req, topics) + if err != nil { + return nil, resp, err + } + + return topics.Names, resp, nil +} + +// ReplaceAllTopics replaces all repository topics. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#replace-all-repository-topics +// +//meta:operation PUT /repos/{owner}/{repo}/topics +func (s *RepositoriesService) ReplaceAllTopics(ctx context.Context, owner, repo string, topics []string) ([]string, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/topics", owner, repo) + t := &repositoryTopics{ + Names: topics, + } + if t.Names == nil { + t.Names = []string{} + } + req, err := s.client.NewRequest("PUT", u, t) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeTopicsPreview) + + t = new(repositoryTopics) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t.Names, resp, nil +} + +// ListApps lists the GitHub apps that have push access to a given protected branch. +// It requires the GitHub apps to have `write` access to the `content` permission. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// Deprecated: Please use ListAppRestrictions instead. +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#get-apps-with-access-to-the-protected-branch +// +//meta:operation GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps +func (s *RepositoriesService) ListApps(ctx context.Context, owner, repo, branch string) ([]*App, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var apps []*App + resp, err := s.client.Do(ctx, req, &apps) + if err != nil { + return nil, resp, err + } + + return apps, resp, nil +} + +// ListAppRestrictions lists the GitHub apps that have push access to a given protected branch. +// It requires the GitHub apps to have `write` access to the `content` permission. +// +// Note: This is a wrapper around ListApps so a naming convention with ListUserRestrictions and ListTeamRestrictions is preserved. +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#get-apps-with-access-to-the-protected-branch +// +//meta:operation GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps +func (s *RepositoriesService) ListAppRestrictions(ctx context.Context, owner, repo, branch string) ([]*App, *Response, error) { + return s.ListApps(ctx, owner, repo, branch) +} + +// ReplaceAppRestrictions replaces the apps that have push access to a given protected branch. +// It removes all apps that previously had push access and grants push access to the new list of apps. +// It requires the GitHub apps to have `write` access to the `content` permission. +// +// Note: The list of users, apps, and teams in total is limited to 100 items. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#set-app-access-restrictions +// +//meta:operation PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps +func (s *RepositoriesService) ReplaceAppRestrictions(ctx context.Context, owner, repo, branch string, apps []string) ([]*App, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("PUT", u, apps) + if err != nil { + return nil, nil, err + } + + var newApps []*App + resp, err := s.client.Do(ctx, req, &newApps) + if err != nil { + return nil, resp, err + } + + return newApps, resp, nil +} + +// AddAppRestrictions grants the specified apps push access to a given protected branch. +// It requires the GitHub apps to have `write` access to the `content` permission. +// +// Note: The list of users, apps, and teams in total is limited to 100 items. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#add-app-access-restrictions +// +//meta:operation POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps +func (s *RepositoriesService) AddAppRestrictions(ctx context.Context, owner, repo, branch string, apps []string) ([]*App, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("POST", u, apps) + if err != nil { + return nil, nil, err + } + + var newApps []*App + resp, err := s.client.Do(ctx, req, &newApps) + if err != nil { + return nil, resp, err + } + + return newApps, resp, nil +} + +// RemoveAppRestrictions removes the restrictions of an app from pushing to this branch. +// It requires the GitHub apps to have `write` access to the `content` permission. +// +// Note: The list of users, apps, and teams in total is limited to 100 items. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#remove-app-access-restrictions +// +//meta:operation DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps +func (s *RepositoriesService) RemoveAppRestrictions(ctx context.Context, owner, repo, branch string, apps []string) ([]*App, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("DELETE", u, apps) + if err != nil { + return nil, nil, err + } + + var newApps []*App + resp, err := s.client.Do(ctx, req, &newApps) + if err != nil { + return nil, resp, err + } + + return newApps, resp, nil +} + +// ListTeamRestrictions lists the GitHub teams that have push access to a given protected branch. +// It requires the GitHub teams to have `write` access to the `content` permission. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#get-teams-with-access-to-the-protected-branch +// +//meta:operation GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams +func (s *RepositoriesService) ListTeamRestrictions(ctx context.Context, owner, repo, branch string) ([]*Team, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/teams", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// ReplaceTeamRestrictions replaces the team that have push access to a given protected branch. +// This removes all teams that previously had push access and grants push access to the new list of teams. +// It requires the GitHub teams to have `write` access to the `content` permission. +// +// Note: The list of users, apps, and teams in total is limited to 100 items. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#set-team-access-restrictions +// +//meta:operation PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams +func (s *RepositoriesService) ReplaceTeamRestrictions(ctx context.Context, owner, repo, branch string, teams []string) ([]*Team, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/teams", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("PUT", u, teams) + if err != nil { + return nil, nil, err + } + + var newTeams []*Team + resp, err := s.client.Do(ctx, req, &newTeams) + if err != nil { + return nil, resp, err + } + + return newTeams, resp, nil +} + +// AddTeamRestrictions grants the specified teams push access to a given protected branch. +// It requires the GitHub teams to have `write` access to the `content` permission. +// +// Note: The list of users, apps, and teams in total is limited to 100 items. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#add-team-access-restrictions +// +//meta:operation POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams +func (s *RepositoriesService) AddTeamRestrictions(ctx context.Context, owner, repo, branch string, teams []string) ([]*Team, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/teams", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("POST", u, teams) + if err != nil { + return nil, nil, err + } + + var newTeams []*Team + resp, err := s.client.Do(ctx, req, &newTeams) + if err != nil { + return nil, resp, err + } + + return newTeams, resp, nil +} + +// RemoveTeamRestrictions removes the restrictions of a team from pushing to this branch. +// It requires the GitHub teams to have `write` access to the `content` permission. +// +// Note: The list of users, apps, and teams in total is limited to 100 items. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#remove-team-access-restrictions +// +//meta:operation DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams +func (s *RepositoriesService) RemoveTeamRestrictions(ctx context.Context, owner, repo, branch string, teams []string) ([]*Team, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/teams", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("DELETE", u, teams) + if err != nil { + return nil, nil, err + } + + var newTeams []*Team + resp, err := s.client.Do(ctx, req, &newTeams) + if err != nil { + return nil, resp, err + } + + return newTeams, resp, nil +} + +// ListUserRestrictions lists the GitHub users that have push access to a given protected branch. +// It requires the GitHub users to have `write` access to the `content` permission. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#get-users-with-access-to-the-protected-branch +// +//meta:operation GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users +func (s *RepositoriesService) ListUserRestrictions(ctx context.Context, owner, repo, branch string) ([]*User, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/users", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var users []*User + resp, err := s.client.Do(ctx, req, &users) + if err != nil { + return nil, resp, err + } + + return users, resp, nil +} + +// ReplaceUserRestrictions replaces the user that have push access to a given protected branch. +// It removes all users that previously had push access and grants push access to the new list of users. +// It requires the GitHub users to have `write` access to the `content` permission. +// +// Note: The list of users, apps, and teams in total is limited to 100 items. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#set-user-access-restrictions +// +//meta:operation PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users +func (s *RepositoriesService) ReplaceUserRestrictions(ctx context.Context, owner, repo, branch string, users []string) ([]*User, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/users", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("PUT", u, users) + if err != nil { + return nil, nil, err + } + + var newUsers []*User + resp, err := s.client.Do(ctx, req, &newUsers) + if err != nil { + return nil, resp, err + } + + return newUsers, resp, nil +} + +// AddUserRestrictions grants the specified users push access to a given protected branch. +// It requires the GitHub users to have `write` access to the `content` permission. +// +// Note: The list of users, apps, and teams in total is limited to 100 items. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#add-user-access-restrictions +// +//meta:operation POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users +func (s *RepositoriesService) AddUserRestrictions(ctx context.Context, owner, repo, branch string, users []string) ([]*User, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/users", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("POST", u, users) + if err != nil { + return nil, nil, err + } + + var newUsers []*User + resp, err := s.client.Do(ctx, req, &newUsers) + if err != nil { + return nil, resp, err + } + + return newUsers, resp, nil +} + +// RemoveUserRestrictions removes the restrictions of a user from pushing to this branch. +// It requires the GitHub users to have `write` access to the `content` permission. +// +// Note: The list of users, apps, and teams in total is limited to 100 items. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#remove-user-access-restrictions +// +//meta:operation DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users +func (s *RepositoriesService) RemoveUserRestrictions(ctx context.Context, owner, repo, branch string, users []string) ([]*User, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/users", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("DELETE", u, users) + if err != nil { + return nil, nil, err + } + + var newUsers []*User + resp, err := s.client.Do(ctx, req, &newUsers) + if err != nil { + return nil, resp, err + } + + return newUsers, resp, nil +} + +// TransferRequest represents a request to transfer a repository. +type TransferRequest struct { + NewOwner string `json:"new_owner"` + NewName *string `json:"new_name,omitempty"` + TeamID []int64 `json:"team_ids,omitempty"` +} + +// Transfer transfers a repository from one account or organization to another. +// +// This method might return an *AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it has now scheduled the transfer of the repository in a background task. +// A follow up request, after a delay of a second or so, should result +// in a successful request. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#transfer-a-repository +// +//meta:operation POST /repos/{owner}/{repo}/transfer +func (s *RepositoriesService) Transfer(ctx context.Context, owner, repo string, transfer TransferRequest) (*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/transfer", owner, repo) + + req, err := s.client.NewRequest("POST", u, &transfer) + if err != nil { + return nil, nil, err + } + + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// DispatchRequestOptions represents a request to trigger a repository_dispatch event. +type DispatchRequestOptions struct { + // EventType is a custom webhook event name. (Required.) + EventType string `json:"event_type"` + // ClientPayload is a custom JSON payload with extra information about the webhook event. + // Defaults to an empty JSON object. + ClientPayload *json.RawMessage `json:"client_payload,omitempty"` +} + +// Dispatch triggers a repository_dispatch event in a GitHub Actions workflow. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#create-a-repository-dispatch-event +// +//meta:operation POST /repos/{owner}/{repo}/dispatches +func (s *RepositoriesService) Dispatch(ctx context.Context, owner, repo string, opts DispatchRequestOptions) (*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/dispatches", owner, repo) + + req, err := s.client.NewRequest("POST", u, &opts) + if err != nil { + return nil, nil, err + } + + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// isBranchNotProtected determines whether a branch is not protected +// based on the error message returned by GitHub API. +func isBranchNotProtected(err error) bool { + errorResponse, ok := err.(*ErrorResponse) + return ok && errorResponse.Message == githubBranchNotProtected +} + +// EnablePrivateReporting enables private reporting of vulnerabilities for a +// repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#enable-private-vulnerability-reporting-for-a-repository +// +//meta:operation PUT /repos/{owner}/{repo}/private-vulnerability-reporting +func (s *RepositoriesService) EnablePrivateReporting(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/private-vulnerability-reporting", owner, repo) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// DisablePrivateReporting disables private reporting of vulnerabilities for a +// repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#disable-private-vulnerability-reporting-for-a-repository +// +//meta:operation DELETE /repos/{owner}/{repo}/private-vulnerability-reporting +func (s *RepositoriesService) DisablePrivateReporting(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/private-vulnerability-reporting", owner, repo) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// checkPrivateReporting represents whether private vulnerability reporting is enabled. +type checkPrivateReporting struct { + Enabled bool `json:"enabled,omitempty"` +} + +// IsPrivateReportingEnabled checks if private vulnerability reporting is enabled +// for the repository and returns a boolean indicating the status. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#check-if-private-vulnerability-reporting-is-enabled-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/private-vulnerability-reporting +func (s *RepositoriesService) IsPrivateReportingEnabled(ctx context.Context, owner, repo string) (bool, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/private-vulnerability-reporting", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + privateReporting := new(checkPrivateReporting) + resp, err := s.client.Do(ctx, req, privateReporting) + return privateReporting.Enabled, resp, err +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_actions_access.go b/vendor/github.com/google/go-github/v68/github/repos_actions_access.go new file mode 100644 index 0000000000..2da1f01cc2 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_actions_access.go @@ -0,0 +1,59 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// RepositoryActionsAccessLevel represents the repository actions access level. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#set-the-level-of-access-for-workflows-outside-of-the-repository +type RepositoryActionsAccessLevel struct { + // AccessLevel specifies the level of access that workflows outside of the repository have + // to actions and reusable workflows within the repository. + // Possible values are: "none", "organization" "enterprise". + AccessLevel *string `json:"access_level,omitempty"` +} + +// GetActionsAccessLevel gets the level of access that workflows outside of the repository have +// to actions and reusable workflows in the repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#get-the-level-of-access-for-workflows-outside-of-the-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/permissions/access +func (s *RepositoriesService) GetActionsAccessLevel(ctx context.Context, owner, repo string) (*RepositoryActionsAccessLevel, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/permissions/access", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + raal := new(RepositoryActionsAccessLevel) + resp, err := s.client.Do(ctx, req, raal) + if err != nil { + return nil, resp, err + } + + return raal, resp, nil +} + +// EditActionsAccessLevel sets the level of access that workflows outside of the repository have +// to actions and reusable workflows in the repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#set-the-level-of-access-for-workflows-outside-of-the-repository +// +//meta:operation PUT /repos/{owner}/{repo}/actions/permissions/access +func (s *RepositoriesService) EditActionsAccessLevel(ctx context.Context, owner, repo string, repositoryActionsAccessLevel RepositoryActionsAccessLevel) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/permissions/access", owner, repo) + req, err := s.client.NewRequest("PUT", u, repositoryActionsAccessLevel) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_actions_allowed.go b/vendor/github.com/google/go-github/v68/github/repos_actions_allowed.go new file mode 100644 index 0000000000..e9ebff1d32 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_actions_allowed.go @@ -0,0 +1,53 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetActionsAllowed gets the allowed actions and reusable workflows for a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#get-allowed-actions-and-reusable-workflows-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/permissions/selected-actions +func (s *RepositoriesService) GetActionsAllowed(ctx context.Context, org, repo string) (*ActionsAllowed, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/permissions/selected-actions", org, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + actionsAllowed := new(ActionsAllowed) + resp, err := s.client.Do(ctx, req, actionsAllowed) + if err != nil { + return nil, resp, err + } + + return actionsAllowed, resp, nil +} + +// EditActionsAllowed sets the allowed actions and reusable workflows for a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#set-allowed-actions-and-reusable-workflows-for-a-repository +// +//meta:operation PUT /repos/{owner}/{repo}/actions/permissions/selected-actions +func (s *RepositoriesService) EditActionsAllowed(ctx context.Context, org, repo string, actionsAllowed ActionsAllowed) (*ActionsAllowed, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/permissions/selected-actions", org, repo) + req, err := s.client.NewRequest("PUT", u, actionsAllowed) + if err != nil { + return nil, nil, err + } + + p := new(ActionsAllowed) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_actions_permissions.go b/vendor/github.com/google/go-github/v68/github/repos_actions_permissions.go new file mode 100644 index 0000000000..9abd32a783 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_actions_permissions.go @@ -0,0 +1,118 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ActionsPermissionsRepository represents a policy for repositories and allowed actions in a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions +type ActionsPermissionsRepository struct { + Enabled *bool `json:"enabled,omitempty"` + AllowedActions *string `json:"allowed_actions,omitempty"` + SelectedActionsURL *string `json:"selected_actions_url,omitempty"` +} + +func (a ActionsPermissionsRepository) String() string { + return Stringify(a) +} + +// DefaultWorkflowPermissionRepository represents the default permissions for GitHub Actions workflows for a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions +type DefaultWorkflowPermissionRepository struct { + DefaultWorkflowPermissions *string `json:"default_workflow_permissions,omitempty"` + CanApprovePullRequestReviews *bool `json:"can_approve_pull_request_reviews,omitempty"` +} + +// GetActionsPermissions gets the GitHub Actions permissions policy for repositories and allowed actions in a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#get-github-actions-permissions-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/permissions +func (s *RepositoriesService) GetActionsPermissions(ctx context.Context, owner, repo string) (*ActionsPermissionsRepository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/permissions", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + permissions := new(ActionsPermissionsRepository) + resp, err := s.client.Do(ctx, req, permissions) + if err != nil { + return nil, resp, err + } + + return permissions, resp, nil +} + +// EditActionsPermissions sets the permissions policy for repositories and allowed actions in a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#set-github-actions-permissions-for-a-repository +// +//meta:operation PUT /repos/{owner}/{repo}/actions/permissions +func (s *RepositoriesService) EditActionsPermissions(ctx context.Context, owner, repo string, actionsPermissionsRepository ActionsPermissionsRepository) (*ActionsPermissionsRepository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/permissions", owner, repo) + req, err := s.client.NewRequest("PUT", u, actionsPermissionsRepository) + if err != nil { + return nil, nil, err + } + + permissions := new(ActionsPermissionsRepository) + resp, err := s.client.Do(ctx, req, permissions) + if err != nil { + return nil, resp, err + } + + return permissions, resp, nil +} + +// GetDefaultWorkflowPermissions gets the GitHub Actions default workflow permissions in a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#get-default-workflow-permissions-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/permissions/workflow +func (s *RepositoriesService) GetDefaultWorkflowPermissions(ctx context.Context, owner, repo string) (*DefaultWorkflowPermissionRepository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/permissions/workflow", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + permissions := new(DefaultWorkflowPermissionRepository) + resp, err := s.client.Do(ctx, req, permissions) + if err != nil { + return nil, resp, err + } + + return permissions, resp, nil +} + +// EditDefaultWorkflowPermissions sets the GitHub Actions default workflow permissions in a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#set-default-workflow-permissions-for-a-repository +// +//meta:operation PUT /repos/{owner}/{repo}/actions/permissions/workflow +func (s *RepositoriesService) EditDefaultWorkflowPermissions(ctx context.Context, owner, repo string, permissions DefaultWorkflowPermissionRepository) (*DefaultWorkflowPermissionRepository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/permissions/workflow", owner, repo) + req, err := s.client.NewRequest("PUT", u, permissions) + if err != nil { + return nil, nil, err + } + + p := new(DefaultWorkflowPermissionRepository) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_attestations.go b/vendor/github.com/google/go-github/v68/github/repos_attestations.go new file mode 100644 index 0000000000..2e5425502c --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_attestations.go @@ -0,0 +1,39 @@ +// Copyright 2024 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListAttestations returns a collection of artifact attestations +// with a given subject digest that are associated with a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-attestations +// +//meta:operation GET /repos/{owner}/{repo}/attestations/{subject_digest} +func (s *RepositoriesService) ListAttestations(ctx context.Context, owner, repo, subjectDigest string, opts *ListOptions) (*AttestationsResponse, *Response, error) { + var u = fmt.Sprintf("repos/%v/%v/attestations/%v", owner, repo, subjectDigest) + + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var attestations *AttestationsResponse + resp, err := s.client.Do(ctx, req, &attestations) + if err != nil { + return nil, resp, err + } + + return attestations, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_autolinks.go b/vendor/github.com/google/go-github/v68/github/repos_autolinks.go new file mode 100644 index 0000000000..6c209b2d5e --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_autolinks.go @@ -0,0 +1,112 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// AutolinkOptions specifies parameters for RepositoriesService.AddAutolink method. +type AutolinkOptions struct { + KeyPrefix *string `json:"key_prefix,omitempty"` + URLTemplate *string `json:"url_template,omitempty"` + IsAlphanumeric *bool `json:"is_alphanumeric,omitempty"` +} + +// Autolink represents autolinks to external resources like JIRA issues and Zendesk tickets. +type Autolink struct { + ID *int64 `json:"id,omitempty"` + KeyPrefix *string `json:"key_prefix,omitempty"` + URLTemplate *string `json:"url_template,omitempty"` + IsAlphanumeric *bool `json:"is_alphanumeric,omitempty"` +} + +// ListAutolinks returns a list of autolinks configured for the given repository. +// Information about autolinks are only available to repository administrators. +// +// GitHub API docs: https://docs.github.com/rest/repos/autolinks#get-all-autolinks-of-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/autolinks +func (s *RepositoriesService) ListAutolinks(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Autolink, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/autolinks", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var autolinks []*Autolink + resp, err := s.client.Do(ctx, req, &autolinks) + if err != nil { + return nil, resp, err + } + + return autolinks, resp, nil +} + +// AddAutolink creates an autolink reference for a repository. +// Users with admin access to the repository can create an autolink. +// +// GitHub API docs: https://docs.github.com/rest/repos/autolinks#create-an-autolink-reference-for-a-repository +// +//meta:operation POST /repos/{owner}/{repo}/autolinks +func (s *RepositoriesService) AddAutolink(ctx context.Context, owner, repo string, opts *AutolinkOptions) (*Autolink, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/autolinks", owner, repo) + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + al := new(Autolink) + resp, err := s.client.Do(ctx, req, al) + if err != nil { + return nil, resp, err + } + return al, resp, nil +} + +// GetAutolink returns a single autolink reference by ID that was configured for the given repository. +// Information about autolinks are only available to repository administrators. +// +// GitHub API docs: https://docs.github.com/rest/repos/autolinks#get-an-autolink-reference-of-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/autolinks/{autolink_id} +func (s *RepositoriesService) GetAutolink(ctx context.Context, owner, repo string, id int64) (*Autolink, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/autolinks/%v", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var autolink *Autolink + resp, err := s.client.Do(ctx, req, &autolink) + if err != nil { + return nil, resp, err + } + + return autolink, resp, nil +} + +// DeleteAutolink deletes a single autolink reference by ID that was configured for the given repository. +// Information about autolinks are only available to repository administrators. +// +// GitHub API docs: https://docs.github.com/rest/repos/autolinks#delete-an-autolink-reference-from-a-repository +// +//meta:operation DELETE /repos/{owner}/{repo}/autolinks/{autolink_id} +func (s *RepositoriesService) DeleteAutolink(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/autolinks/%v", owner, repo, id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_codeowners.go b/vendor/github.com/google/go-github/v68/github/repos_codeowners.go new file mode 100644 index 0000000000..93eeae09b1 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_codeowners.go @@ -0,0 +1,61 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetCodeownersErrorsOptions specifies the optional parameters to the +// RepositoriesService.GetCodeownersErrors method. +type GetCodeownersErrorsOptions struct { + // A branch, tag or commit name used to determine which version of the CODEOWNERS file to use. + // Default: the repository's default branch (e.g. main). + Ref string `url:"ref,omitempty"` +} + +// CodeownersErrors represents a list of syntax errors detected in the CODEOWNERS file. +type CodeownersErrors struct { + Errors []*CodeownersError `json:"errors"` +} + +// CodeownersError represents a syntax error detected in the CODEOWNERS file. +type CodeownersError struct { + Line int `json:"line"` + Column int `json:"column"` + Kind string `json:"kind"` + Source string `json:"source"` + Suggestion *string `json:"suggestion,omitempty"` + Message string `json:"message"` + Path string `json:"path"` +} + +// GetCodeownersErrors lists any syntax errors that are detected in the CODEOWNERS file. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-codeowners-errors +// +//meta:operation GET /repos/{owner}/{repo}/codeowners/errors +func (s *RepositoriesService) GetCodeownersErrors(ctx context.Context, owner, repo string, opts *GetCodeownersErrorsOptions) (*CodeownersErrors, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/codeowners/errors", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + codeownersErrors := &CodeownersErrors{} + resp, err := s.client.Do(ctx, req, codeownersErrors) + if err != nil { + return nil, resp, err + } + + return codeownersErrors, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_collaborators.go b/vendor/github.com/google/go-github/v68/github/repos_collaborators.go new file mode 100644 index 0000000000..d6c985359a --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_collaborators.go @@ -0,0 +1,178 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListCollaboratorsOptions specifies the optional parameters to the +// RepositoriesService.ListCollaborators method. +type ListCollaboratorsOptions struct { + // Affiliation specifies how collaborators should be filtered by their affiliation. + // Possible values are: + // outside - All outside collaborators of an organization-owned repository + // direct - All collaborators with permissions to an organization-owned repository, + // regardless of organization membership status + // all - All collaborators the authenticated user can see + // + // Default value is "all". + Affiliation string `url:"affiliation,omitempty"` + + // Permission specifies how collaborators should be filtered by the permissions they have on the repository. + // Possible values are: + // "pull", "triage", "push", "maintain", "admin" + // + // If not specified, all collaborators will be returned. + Permission string `url:"permission,omitempty"` + + ListOptions +} + +// CollaboratorInvitation represents an invitation created when adding a collaborator. +// GitHub API docs: https://docs.github.com/rest/repos/collaborators/#response-when-a-new-invitation-is-created +type CollaboratorInvitation struct { + ID *int64 `json:"id,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Invitee *User `json:"invitee,omitempty"` + Inviter *User `json:"inviter,omitempty"` + Permissions *string `json:"permissions,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` +} + +// ListCollaborators lists the GitHub users that have access to the repository. +// +// GitHub API docs: https://docs.github.com/rest/collaborators/collaborators#list-repository-collaborators +// +//meta:operation GET /repos/{owner}/{repo}/collaborators +func (s *RepositoriesService) ListCollaborators(ctx context.Context, owner, repo string, opts *ListCollaboratorsOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/collaborators", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var users []*User + resp, err := s.client.Do(ctx, req, &users) + if err != nil { + return nil, resp, err + } + + return users, resp, nil +} + +// IsCollaborator checks whether the specified GitHub user has collaborator +// access to the given repo. +// Note: This will return false if the user is not a collaborator OR the user +// is not a GitHub user. +// +// GitHub API docs: https://docs.github.com/rest/collaborators/collaborators#check-if-a-user-is-a-repository-collaborator +// +//meta:operation GET /repos/{owner}/{repo}/collaborators/{username} +func (s *RepositoriesService) IsCollaborator(ctx context.Context, owner, repo, user string) (bool, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + isCollab, err := parseBoolResponse(err) + return isCollab, resp, err +} + +// RepositoryPermissionLevel represents the permission level an organization +// member has for a given repository. +type RepositoryPermissionLevel struct { + // Possible values: "admin", "write", "read", "none" + Permission *string `json:"permission,omitempty"` + + User *User `json:"user,omitempty"` + + RoleName *string `json:"role_name,omitempty"` +} + +// GetPermissionLevel retrieves the specific permission level a collaborator has for a given repository. +// +// GitHub API docs: https://docs.github.com/rest/collaborators/collaborators#get-repository-permissions-for-a-user +// +//meta:operation GET /repos/{owner}/{repo}/collaborators/{username}/permission +func (s *RepositoriesService) GetPermissionLevel(ctx context.Context, owner, repo, user string) (*RepositoryPermissionLevel, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/collaborators/%v/permission", owner, repo, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + rpl := new(RepositoryPermissionLevel) + resp, err := s.client.Do(ctx, req, rpl) + if err != nil { + return nil, resp, err + } + + return rpl, resp, nil +} + +// RepositoryAddCollaboratorOptions specifies the optional parameters to the +// RepositoriesService.AddCollaborator method. +type RepositoryAddCollaboratorOptions struct { + // Permission specifies the permission to grant the user on this repository. + // Possible values are: + // pull - team members can pull, but not push to or administer this repository + // push - team members can pull and push, but not administer this repository + // admin - team members can pull, push and administer this repository + // maintain - team members can manage the repository without access to sensitive or destructive actions. + // triage - team members can proactively manage issues and pull requests without write access. + // + // Default value is "push". This option is only valid for organization-owned repositories. + Permission string `json:"permission,omitempty"` +} + +// AddCollaborator sends an invitation to the specified GitHub user +// to become a collaborator to the given repo. +// +// GitHub API docs: https://docs.github.com/rest/collaborators/collaborators#add-a-repository-collaborator +// +//meta:operation PUT /repos/{owner}/{repo}/collaborators/{username} +func (s *RepositoriesService) AddCollaborator(ctx context.Context, owner, repo, user string, opts *RepositoryAddCollaboratorOptions) (*CollaboratorInvitation, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, nil, err + } + + acr := new(CollaboratorInvitation) + resp, err := s.client.Do(ctx, req, acr) + if err != nil { + return nil, resp, err + } + + return acr, resp, nil +} + +// RemoveCollaborator removes the specified GitHub user as collaborator from the given repo. +// Note: Does not return error if a valid user that is not a collaborator is removed. +// +// GitHub API docs: https://docs.github.com/rest/collaborators/collaborators#remove-a-repository-collaborator +// +//meta:operation DELETE /repos/{owner}/{repo}/collaborators/{username} +func (s *RepositoriesService) RemoveCollaborator(ctx context.Context, owner, repo, user string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_comments.go b/vendor/github.com/google/go-github/v68/github/repos_comments.go new file mode 100644 index 0000000000..766a614cc1 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_comments.go @@ -0,0 +1,173 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// RepositoryComment represents a comment for a commit, file, or line in a repository. +type RepositoryComment struct { + HTMLURL *string `json:"html_url,omitempty"` + URL *string `json:"url,omitempty"` + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + CommitID *string `json:"commit_id,omitempty"` + User *User `json:"user,omitempty"` + Reactions *Reactions `json:"reactions,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + + // User-mutable fields + Body *string `json:"body"` + // User-initialized fields + Path *string `json:"path,omitempty"` + Position *int `json:"position,omitempty"` +} + +func (r RepositoryComment) String() string { + return Stringify(r) +} + +// ListComments lists all the comments for the repository. +// +// GitHub API docs: https://docs.github.com/rest/commits/comments#list-commit-comments-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/comments +func (s *RepositoriesService) ListComments(ctx context.Context, owner, repo string, opts *ListOptions) ([]*RepositoryComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var comments []*RepositoryComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// ListCommitComments lists all the comments for a given commit SHA. +// +// GitHub API docs: https://docs.github.com/rest/commits/comments#list-commit-comments +// +//meta:operation GET /repos/{owner}/{repo}/commits/{commit_sha}/comments +func (s *RepositoriesService) ListCommitComments(ctx context.Context, owner, repo, sha string, opts *ListOptions) ([]*RepositoryComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/comments", owner, repo, sha) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var comments []*RepositoryComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// CreateComment creates a comment for the given commit. +// Note: GitHub allows for comments to be created for non-existing files and positions. +// +// GitHub API docs: https://docs.github.com/rest/commits/comments#create-a-commit-comment +// +//meta:operation POST /repos/{owner}/{repo}/commits/{commit_sha}/comments +func (s *RepositoriesService) CreateComment(ctx context.Context, owner, repo, sha string, comment *RepositoryComment) (*RepositoryComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/comments", owner, repo, sha) + req, err := s.client.NewRequest("POST", u, comment) + if err != nil { + return nil, nil, err + } + + c := new(RepositoryComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// GetComment gets a single comment from a repository. +// +// GitHub API docs: https://docs.github.com/rest/commits/comments#get-a-commit-comment +// +//meta:operation GET /repos/{owner}/{repo}/comments/{comment_id} +func (s *RepositoriesService) GetComment(ctx context.Context, owner, repo string, id int64) (*RepositoryComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + c := new(RepositoryComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// UpdateComment updates the body of a single comment. +// +// GitHub API docs: https://docs.github.com/rest/commits/comments#update-a-commit-comment +// +//meta:operation PATCH /repos/{owner}/{repo}/comments/{comment_id} +func (s *RepositoriesService) UpdateComment(ctx context.Context, owner, repo string, id int64, comment *RepositoryComment) (*RepositoryComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id) + req, err := s.client.NewRequest("PATCH", u, comment) + if err != nil { + return nil, nil, err + } + + c := new(RepositoryComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// DeleteComment deletes a single comment from a repository. +// +// GitHub API docs: https://docs.github.com/rest/commits/comments#delete-a-commit-comment +// +//meta:operation DELETE /repos/{owner}/{repo}/comments/{comment_id} +func (s *RepositoriesService) DeleteComment(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_commits.go b/vendor/github.com/google/go-github/v68/github/repos_commits.go new file mode 100644 index 0000000000..cca7430cb5 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_commits.go @@ -0,0 +1,325 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "context" + "fmt" + "net/url" + "time" +) + +// RepositoryCommit represents a commit in a repo. +// Note that it's wrapping a Commit, so author/committer information is in two places, +// but contain different details about them: in RepositoryCommit "github details", in Commit - "git details". +type RepositoryCommit struct { + NodeID *string `json:"node_id,omitempty"` + SHA *string `json:"sha,omitempty"` + Commit *Commit `json:"commit,omitempty"` + Author *User `json:"author,omitempty"` + Committer *User `json:"committer,omitempty"` + Parents []*Commit `json:"parents,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + URL *string `json:"url,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + + // Details about how many changes were made in this commit. Only filled in during GetCommit! + Stats *CommitStats `json:"stats,omitempty"` + // Details about which files, and how this commit touched. Only filled in during GetCommit! + Files []*CommitFile `json:"files,omitempty"` +} + +func (r RepositoryCommit) String() string { + return Stringify(r) +} + +// CommitStats represents the number of additions / deletions from a file in a given RepositoryCommit or GistCommit. +type CommitStats struct { + Additions *int `json:"additions,omitempty"` + Deletions *int `json:"deletions,omitempty"` + Total *int `json:"total,omitempty"` +} + +func (c CommitStats) String() string { + return Stringify(c) +} + +// CommitFile represents a file modified in a commit. +type CommitFile struct { + SHA *string `json:"sha,omitempty"` + Filename *string `json:"filename,omitempty"` + Additions *int `json:"additions,omitempty"` + Deletions *int `json:"deletions,omitempty"` + Changes *int `json:"changes,omitempty"` + Status *string `json:"status,omitempty"` + Patch *string `json:"patch,omitempty"` + BlobURL *string `json:"blob_url,omitempty"` + RawURL *string `json:"raw_url,omitempty"` + ContentsURL *string `json:"contents_url,omitempty"` + PreviousFilename *string `json:"previous_filename,omitempty"` +} + +func (c CommitFile) String() string { + return Stringify(c) +} + +// CommitsComparison is the result of comparing two commits. +// See CompareCommits() for details. +type CommitsComparison struct { + BaseCommit *RepositoryCommit `json:"base_commit,omitempty"` + MergeBaseCommit *RepositoryCommit `json:"merge_base_commit,omitempty"` + + // Head can be 'behind' or 'ahead' + Status *string `json:"status,omitempty"` + AheadBy *int `json:"ahead_by,omitempty"` + BehindBy *int `json:"behind_by,omitempty"` + TotalCommits *int `json:"total_commits,omitempty"` + + Commits []*RepositoryCommit `json:"commits,omitempty"` + + Files []*CommitFile `json:"files,omitempty"` + + HTMLURL *string `json:"html_url,omitempty"` + PermalinkURL *string `json:"permalink_url,omitempty"` + DiffURL *string `json:"diff_url,omitempty"` + PatchURL *string `json:"patch_url,omitempty"` + URL *string `json:"url,omitempty"` // API URL. +} + +func (c CommitsComparison) String() string { + return Stringify(c) +} + +// CommitsListOptions specifies the optional parameters to the +// RepositoriesService.ListCommits method. +type CommitsListOptions struct { + // SHA or branch to start listing Commits from. + SHA string `url:"sha,omitempty"` + + // Path that should be touched by the returned Commits. + Path string `url:"path,omitempty"` + + // Author of by which to filter Commits. + Author string `url:"author,omitempty"` + + // Since when should Commits be included in the response. + Since time.Time `url:"since,omitempty"` + + // Until when should Commits be included in the response. + Until time.Time `url:"until,omitempty"` + + ListOptions +} + +// BranchCommit is the result of listing branches with commit SHA. +type BranchCommit struct { + Name *string `json:"name,omitempty"` + Commit *Commit `json:"commit,omitempty"` + Protected *bool `json:"protected,omitempty"` +} + +// ListCommits lists the commits of a repository. +// +// GitHub API docs: https://docs.github.com/rest/commits/commits#list-commits +// +//meta:operation GET /repos/{owner}/{repo}/commits +func (s *RepositoriesService) ListCommits(ctx context.Context, owner, repo string, opts *CommitsListOptions) ([]*RepositoryCommit, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var commits []*RepositoryCommit + resp, err := s.client.Do(ctx, req, &commits) + if err != nil { + return nil, resp, err + } + + return commits, resp, nil +} + +// GetCommit fetches the specified commit, including all details about it. +// +// GitHub API docs: https://docs.github.com/rest/commits/commits#get-a-commit +// +//meta:operation GET /repos/{owner}/{repo}/commits/{ref} +func (s *RepositoriesService) GetCommit(ctx context.Context, owner, repo, sha string, opts *ListOptions) (*RepositoryCommit, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, sha) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + commit := new(RepositoryCommit) + resp, err := s.client.Do(ctx, req, commit) + if err != nil { + return nil, resp, err + } + + return commit, resp, nil +} + +// GetCommitRaw fetches the specified commit in raw (diff or patch) format. +// +// GitHub API docs: https://docs.github.com/rest/commits/commits#get-a-commit +// +//meta:operation GET /repos/{owner}/{repo}/commits/{ref} +func (s *RepositoriesService) GetCommitRaw(ctx context.Context, owner string, repo string, sha string, opts RawOptions) (string, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, sha) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return "", nil, err + } + + switch opts.Type { + case Diff: + req.Header.Set("Accept", mediaTypeV3Diff) + case Patch: + req.Header.Set("Accept", mediaTypeV3Patch) + default: + return "", nil, fmt.Errorf("unsupported raw type %d", opts.Type) + } + + var buf bytes.Buffer + resp, err := s.client.Do(ctx, req, &buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// GetCommitSHA1 gets the SHA-1 of a commit reference. If a last-known SHA1 is +// supplied and no new commits have occurred, a 304 Unmodified response is returned. +// +// GitHub API docs: https://docs.github.com/rest/commits/commits#get-a-commit +// +//meta:operation GET /repos/{owner}/{repo}/commits/{ref} +func (s *RepositoriesService) GetCommitSHA1(ctx context.Context, owner, repo, ref, lastSHA string) (string, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, refURLEscape(ref)) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return "", nil, err + } + if lastSHA != "" { + req.Header.Set("If-None-Match", `"`+lastSHA+`"`) + } + + req.Header.Set("Accept", mediaTypeV3SHA) + + var buf bytes.Buffer + resp, err := s.client.Do(ctx, req, &buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// CompareCommits compares a range of commits with each other. +// +// GitHub API docs: https://docs.github.com/rest/commits/commits#compare-two-commits +// +//meta:operation GET /repos/{owner}/{repo}/compare/{basehead} +func (s *RepositoriesService) CompareCommits(ctx context.Context, owner, repo string, base, head string, opts *ListOptions) (*CommitsComparison, *Response, error) { + escapedBase := url.QueryEscape(base) + escapedHead := url.QueryEscape(head) + + u := fmt.Sprintf("repos/%v/%v/compare/%v...%v", owner, repo, escapedBase, escapedHead) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + comp := new(CommitsComparison) + resp, err := s.client.Do(ctx, req, comp) + if err != nil { + return nil, resp, err + } + + return comp, resp, nil +} + +// CompareCommitsRaw compares a range of commits with each other in raw (diff or patch) format. +// +// Both "base" and "head" must be branch names in "repo". +// To compare branches across other repositories in the same network as "repo", +// use the format ":branch". +// +// GitHub API docs: https://docs.github.com/rest/commits/commits#compare-two-commits +// +//meta:operation GET /repos/{owner}/{repo}/compare/{basehead} +func (s *RepositoriesService) CompareCommitsRaw(ctx context.Context, owner, repo, base, head string, opts RawOptions) (string, *Response, error) { + escapedBase := url.QueryEscape(base) + escapedHead := url.QueryEscape(head) + + u := fmt.Sprintf("repos/%v/%v/compare/%v...%v", owner, repo, escapedBase, escapedHead) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return "", nil, err + } + + switch opts.Type { + case Diff: + req.Header.Set("Accept", mediaTypeV3Diff) + case Patch: + req.Header.Set("Accept", mediaTypeV3Patch) + default: + return "", nil, fmt.Errorf("unsupported raw type %d", opts.Type) + } + + var buf bytes.Buffer + resp, err := s.client.Do(ctx, req, &buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// ListBranchesHeadCommit gets all branches where the given commit SHA is the HEAD, +// or latest commit for the branch. +// +// GitHub API docs: https://docs.github.com/rest/commits/commits#list-branches-for-head-commit +// +//meta:operation GET /repos/{owner}/{repo}/commits/{commit_sha}/branches-where-head +func (s *RepositoriesService) ListBranchesHeadCommit(ctx context.Context, owner, repo, sha string) ([]*BranchCommit, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/branches-where-head", owner, repo, sha) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeListPullsOrBranchesForCommitPreview) + var branchCommits []*BranchCommit + resp, err := s.client.Do(ctx, req, &branchCommits) + if err != nil { + return nil, resp, err + } + + return branchCommits, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_community_health.go b/vendor/github.com/google/go-github/v68/github/repos_community_health.go new file mode 100644 index 0000000000..54d1b414ec --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_community_health.go @@ -0,0 +1,63 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Metric represents the different fields for one file in community health files. +type Metric struct { + Name *string `json:"name"` + Key *string `json:"key"` + SPDXID *string `json:"spdx_id"` + URL *string `json:"url"` + HTMLURL *string `json:"html_url"` + NodeID *string `json:"node_id"` +} + +// CommunityHealthFiles represents the different files in the community health metrics response. +type CommunityHealthFiles struct { + CodeOfConduct *Metric `json:"code_of_conduct"` + CodeOfConductFile *Metric `json:"code_of_conduct_file"` + Contributing *Metric `json:"contributing"` + IssueTemplate *Metric `json:"issue_template"` + PullRequestTemplate *Metric `json:"pull_request_template"` + License *Metric `json:"license"` + Readme *Metric `json:"readme"` +} + +// CommunityHealthMetrics represents a response containing the community metrics of a repository. +type CommunityHealthMetrics struct { + HealthPercentage *int `json:"health_percentage"` + Description *string `json:"description"` + Documentation *string `json:"documentation"` + Files *CommunityHealthFiles `json:"files"` + UpdatedAt *Timestamp `json:"updated_at"` + ContentReportsEnabled *bool `json:"content_reports_enabled"` +} + +// GetCommunityHealthMetrics retrieves all the community health metrics for a repository. +// +// GitHub API docs: https://docs.github.com/rest/metrics/community#get-community-profile-metrics +// +//meta:operation GET /repos/{owner}/{repo}/community/profile +func (s *RepositoriesService) GetCommunityHealthMetrics(ctx context.Context, owner, repo string) (*CommunityHealthMetrics, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/community/profile", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + metrics := &CommunityHealthMetrics{} + resp, err := s.client.Do(ctx, req, metrics) + if err != nil { + return nil, resp, err + } + + return metrics, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_contents.go b/vendor/github.com/google/go-github/v68/github/repos_contents.go new file mode 100644 index 0000000000..3a0c266b5e --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_contents.go @@ -0,0 +1,367 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Repository contents API methods. +// GitHub API docs: https://docs.github.com/rest/repos/contents/ + +package github + +import ( + "context" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "net/url" + "path" + "strings" +) + +var ErrPathForbidden = errors.New("path must not contain '..' due to auth vulnerability issue") + +// RepositoryContent represents a file or directory in a github repository. +type RepositoryContent struct { + Type *string `json:"type,omitempty"` + // Target is only set if the type is "symlink" and the target is not a normal file. + // If Target is set, Path will be the symlink path. + Target *string `json:"target,omitempty"` + Encoding *string `json:"encoding,omitempty"` + Size *int `json:"size,omitempty"` + Name *string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` + // Content contains the actual file content, which may be encoded. + // Callers should call GetContent which will decode the content if + // necessary. + Content *string `json:"content,omitempty"` + SHA *string `json:"sha,omitempty"` + URL *string `json:"url,omitempty"` + GitURL *string `json:"git_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + DownloadURL *string `json:"download_url,omitempty"` + SubmoduleGitURL *string `json:"submodule_git_url,omitempty"` +} + +// RepositoryContentResponse holds the parsed response from CreateFile, UpdateFile, and DeleteFile. +type RepositoryContentResponse struct { + Content *RepositoryContent `json:"content,omitempty"` + Commit `json:"commit,omitempty"` +} + +// RepositoryContentFileOptions specifies optional parameters for CreateFile, UpdateFile, and DeleteFile. +type RepositoryContentFileOptions struct { + Message *string `json:"message,omitempty"` + Content []byte `json:"content"` // unencoded + SHA *string `json:"sha,omitempty"` + Branch *string `json:"branch,omitempty"` + Author *CommitAuthor `json:"author,omitempty"` + Committer *CommitAuthor `json:"committer,omitempty"` +} + +// RepositoryContentGetOptions represents an optional ref parameter, which can be a SHA, +// branch, or tag. +type RepositoryContentGetOptions struct { + Ref string `url:"ref,omitempty"` +} + +// String converts RepositoryContent to a string. It's primarily for testing. +func (r RepositoryContent) String() string { + return Stringify(r) +} + +// GetContent returns the content of r, decoding it if necessary. +func (r *RepositoryContent) GetContent() (string, error) { + var encoding string + if r.Encoding != nil { + encoding = *r.Encoding + } + + switch encoding { + case "base64": + if r.Content == nil { + return "", errors.New("malformed response: base64 encoding of null content") + } + c, err := base64.StdEncoding.DecodeString(*r.Content) + return string(c), err + case "": + if r.Content == nil { + return "", nil + } + return *r.Content, nil + case "none": + return "", errors.New("unsupported content encoding: none, this may occur when file size > 1 MB, if that is the case consider using DownloadContents") + default: + return "", fmt.Errorf("unsupported content encoding: %v", encoding) + } +} + +// GetReadme gets the Readme file for the repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/contents#get-a-repository-readme +// +//meta:operation GET /repos/{owner}/{repo}/readme +func (s *RepositoriesService) GetReadme(ctx context.Context, owner, repo string, opts *RepositoryContentGetOptions) (*RepositoryContent, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/readme", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + readme := new(RepositoryContent) + resp, err := s.client.Do(ctx, req, readme) + if err != nil { + return nil, resp, err + } + + return readme, resp, nil +} + +// DownloadContents returns an io.ReadCloser that reads the contents of the +// specified file. This function will work with files of any size, as opposed +// to GetContents which is limited to 1 Mb files. It is the caller's +// responsibility to close the ReadCloser. +// +// It is possible for the download to result in a failed response when the +// returned error is nil. Callers should check the returned Response status +// code to verify the content is from a successful response. +// +// GitHub API docs: https://docs.github.com/rest/repos/contents#get-repository-content +// +//meta:operation GET /repos/{owner}/{repo}/contents/{path} +func (s *RepositoriesService) DownloadContents(ctx context.Context, owner, repo, filepath string, opts *RepositoryContentGetOptions) (io.ReadCloser, *Response, error) { + dir := path.Dir(filepath) + filename := path.Base(filepath) + _, dirContents, resp, err := s.GetContents(ctx, owner, repo, dir, opts) + if err != nil { + return nil, resp, err + } + + for _, contents := range dirContents { + if *contents.Name == filename { + if contents.DownloadURL == nil || *contents.DownloadURL == "" { + return nil, resp, fmt.Errorf("no download link found for %s", filepath) + } + + dlReq, err := http.NewRequestWithContext(ctx, http.MethodGet, *contents.DownloadURL, nil) + if err != nil { + return nil, resp, err + } + dlResp, err := s.client.client.Do(dlReq) + if err != nil { + return nil, &Response{Response: dlResp}, err + } + + return dlResp.Body, &Response{Response: dlResp}, nil + } + } + + return nil, resp, fmt.Errorf("no file named %s found in %s", filename, dir) +} + +// DownloadContentsWithMeta is identical to DownloadContents but additionally +// returns the RepositoryContent of the requested file. This additional data +// is useful for future operations involving the requested file. For merely +// reading the content of a file, DownloadContents is perfectly adequate. +// +// It is possible for the download to result in a failed response when the +// returned error is nil. Callers should check the returned Response status +// code to verify the content is from a successful response. +// +// GitHub API docs: https://docs.github.com/rest/repos/contents#get-repository-content +// +//meta:operation GET /repos/{owner}/{repo}/contents/{path} +func (s *RepositoriesService) DownloadContentsWithMeta(ctx context.Context, owner, repo, filepath string, opts *RepositoryContentGetOptions) (io.ReadCloser, *RepositoryContent, *Response, error) { + dir := path.Dir(filepath) + filename := path.Base(filepath) + _, dirContents, resp, err := s.GetContents(ctx, owner, repo, dir, opts) + if err != nil { + return nil, nil, resp, err + } + + for _, contents := range dirContents { + if *contents.Name == filename { + if contents.DownloadURL == nil || *contents.DownloadURL == "" { + return nil, contents, resp, fmt.Errorf("no download link found for %s", filepath) + } + + dlReq, err := http.NewRequestWithContext(ctx, http.MethodGet, *contents.DownloadURL, nil) + if err != nil { + return nil, contents, resp, err + } + dlResp, err := s.client.client.Do(dlReq) + if err != nil { + return nil, contents, &Response{Response: dlResp}, err + } + + return dlResp.Body, contents, &Response{Response: dlResp}, nil + } + } + + return nil, nil, resp, fmt.Errorf("no file named %s found in %s", filename, dir) +} + +// GetContents can return either the metadata and content of a single file +// (when path references a file) or the metadata of all the files and/or +// subdirectories of a directory (when path references a directory). To make it +// easy to distinguish between both result types and to mimic the API as much +// as possible, both result types will be returned but only one will contain a +// value and the other will be nil. +// +// Due to an auth vulnerability issue in the GitHub v3 API, ".." is not allowed +// to appear anywhere in the "path" or this method will return an error. +// +// GitHub API docs: https://docs.github.com/rest/repos/contents#get-repository-content +// +//meta:operation GET /repos/{owner}/{repo}/contents/{path} +func (s *RepositoriesService) GetContents(ctx context.Context, owner, repo, path string, opts *RepositoryContentGetOptions) (fileContent *RepositoryContent, directoryContent []*RepositoryContent, resp *Response, err error) { + if strings.Contains(path, "..") { + return nil, nil, nil, ErrPathForbidden + } + + escapedPath := (&url.URL{Path: strings.TrimSuffix(path, "/")}).String() + u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, escapedPath) + u, err = addOptions(u, opts) + if err != nil { + return nil, nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, nil, err + } + + var rawJSON json.RawMessage + resp, err = s.client.Do(ctx, req, &rawJSON) + if err != nil { + return nil, nil, resp, err + } + + fileUnmarshalError := json.Unmarshal(rawJSON, &fileContent) + if fileUnmarshalError == nil { + return fileContent, nil, resp, nil + } + + directoryUnmarshalError := json.Unmarshal(rawJSON, &directoryContent) + if directoryUnmarshalError == nil { + return nil, directoryContent, resp, nil + } + + return nil, nil, resp, fmt.Errorf("unmarshalling failed for both file and directory content: %s and %s", fileUnmarshalError, directoryUnmarshalError) +} + +// CreateFile creates a new file in a repository at the given path and returns +// the commit and file metadata. +// +// GitHub API docs: https://docs.github.com/rest/repos/contents#create-or-update-file-contents +// +//meta:operation PUT /repos/{owner}/{repo}/contents/{path} +func (s *RepositoriesService) CreateFile(ctx context.Context, owner, repo, path string, opts *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, nil, err + } + + createResponse := new(RepositoryContentResponse) + resp, err := s.client.Do(ctx, req, createResponse) + if err != nil { + return nil, resp, err + } + + return createResponse, resp, nil +} + +// UpdateFile updates a file in a repository at the given path and returns the +// commit and file metadata. Requires the blob SHA of the file being updated. +// +// GitHub API docs: https://docs.github.com/rest/repos/contents#create-or-update-file-contents +// +//meta:operation PUT /repos/{owner}/{repo}/contents/{path} +func (s *RepositoriesService) UpdateFile(ctx context.Context, owner, repo, path string, opts *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, nil, err + } + + updateResponse := new(RepositoryContentResponse) + resp, err := s.client.Do(ctx, req, updateResponse) + if err != nil { + return nil, resp, err + } + + return updateResponse, resp, nil +} + +// DeleteFile deletes a file from a repository and returns the commit. +// Requires the blob SHA of the file to be deleted. +// +// GitHub API docs: https://docs.github.com/rest/repos/contents#delete-a-file +// +//meta:operation DELETE /repos/{owner}/{repo}/contents/{path} +func (s *RepositoriesService) DeleteFile(ctx context.Context, owner, repo, path string, opts *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path) + req, err := s.client.NewRequest("DELETE", u, opts) + if err != nil { + return nil, nil, err + } + + deleteResponse := new(RepositoryContentResponse) + resp, err := s.client.Do(ctx, req, deleteResponse) + if err != nil { + return nil, resp, err + } + + return deleteResponse, resp, nil +} + +// ArchiveFormat is used to define the archive type when calling GetArchiveLink. +type ArchiveFormat string + +const ( + // Tarball specifies an archive in gzipped tar format. + Tarball ArchiveFormat = "tarball" + + // Zipball specifies an archive in zip format. + Zipball ArchiveFormat = "zipball" +) + +// GetArchiveLink returns an URL to download a tarball or zipball archive for a +// repository. The archiveFormat can be specified by either the github.Tarball +// or github.Zipball constant. +// +// GitHub API docs: https://docs.github.com/rest/repos/contents#download-a-repository-archive-tar +// GitHub API docs: https://docs.github.com/rest/repos/contents#download-a-repository-archive-zip +// +//meta:operation GET /repos/{owner}/{repo}/tarball/{ref} +//meta:operation GET /repos/{owner}/{repo}/zipball/{ref} +func (s *RepositoriesService) GetArchiveLink(ctx context.Context, owner, repo string, archiveformat ArchiveFormat, opts *RepositoryContentGetOptions, maxRedirects int) (*url.URL, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/%s", owner, repo, archiveformat) + if opts != nil && opts.Ref != "" { + u += fmt.Sprintf("/%s", opts.Ref) + } + resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, maxRedirects) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusFound { + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + } + + parsedURL, err := url.Parse(resp.Header.Get("Location")) + if err != nil { + return nil, newResponse(resp), err + } + + return parsedURL, newResponse(resp), nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_deployment_branch_policies.go b/vendor/github.com/google/go-github/v68/github/repos_deployment_branch_policies.go new file mode 100644 index 0000000000..77ac73e44e --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_deployment_branch_policies.go @@ -0,0 +1,135 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// DeploymentBranchPolicy represents a single deployment branch policy for an environment. +type DeploymentBranchPolicy struct { + Name *string `json:"name,omitempty"` + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Type *string `json:"type,omitempty"` +} + +// DeploymentBranchPolicyResponse represents the slightly different format of response that comes back when you list deployment branch policies. +type DeploymentBranchPolicyResponse struct { + TotalCount *int `json:"total_count,omitempty"` + BranchPolicies []*DeploymentBranchPolicy `json:"branch_policies,omitempty"` +} + +// DeploymentBranchPolicyRequest represents a deployment branch policy request. +type DeploymentBranchPolicyRequest struct { + Name *string `json:"name,omitempty"` + Type *string `json:"type,omitempty"` +} + +// ListDeploymentBranchPolicies lists the deployment branch policies for an environment. +// +// GitHub API docs: https://docs.github.com/rest/deployments/branch-policies#list-deployment-branch-policies +// +//meta:operation GET /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies +func (s *RepositoriesService) ListDeploymentBranchPolicies(ctx context.Context, owner, repo, environment string) (*DeploymentBranchPolicyResponse, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/environments/%v/deployment-branch-policies", owner, repo, environment) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var list *DeploymentBranchPolicyResponse + resp, err := s.client.Do(ctx, req, &list) + if err != nil { + return nil, resp, err + } + + return list, resp, nil +} + +// GetDeploymentBranchPolicy gets a deployment branch policy for an environment. +// +// GitHub API docs: https://docs.github.com/rest/deployments/branch-policies#get-a-deployment-branch-policy +// +//meta:operation GET /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id} +func (s *RepositoriesService) GetDeploymentBranchPolicy(ctx context.Context, owner, repo, environment string, branchPolicyID int64) (*DeploymentBranchPolicy, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/environments/%v/deployment-branch-policies/%v", owner, repo, environment, branchPolicyID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var policy *DeploymentBranchPolicy + resp, err := s.client.Do(ctx, req, &policy) + if err != nil { + return nil, resp, err + } + + return policy, resp, nil +} + +// CreateDeploymentBranchPolicy creates a deployment branch policy for an environment. +// +// GitHub API docs: https://docs.github.com/rest/deployments/branch-policies#create-a-deployment-branch-policy +// +//meta:operation POST /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies +func (s *RepositoriesService) CreateDeploymentBranchPolicy(ctx context.Context, owner, repo, environment string, request *DeploymentBranchPolicyRequest) (*DeploymentBranchPolicy, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/environments/%v/deployment-branch-policies", owner, repo, environment) + + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + var policy *DeploymentBranchPolicy + resp, err := s.client.Do(ctx, req, &policy) + if err != nil { + return nil, resp, err + } + + return policy, resp, nil +} + +// UpdateDeploymentBranchPolicy updates a deployment branch policy for an environment. +// +// GitHub API docs: https://docs.github.com/rest/deployments/branch-policies#update-a-deployment-branch-policy +// +//meta:operation PUT /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id} +func (s *RepositoriesService) UpdateDeploymentBranchPolicy(ctx context.Context, owner, repo, environment string, branchPolicyID int64, request *DeploymentBranchPolicyRequest) (*DeploymentBranchPolicy, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/environments/%v/deployment-branch-policies/%v", owner, repo, environment, branchPolicyID) + + req, err := s.client.NewRequest("PUT", u, request) + if err != nil { + return nil, nil, err + } + + var policy *DeploymentBranchPolicy + resp, err := s.client.Do(ctx, req, &policy) + if err != nil { + return nil, resp, err + } + + return policy, resp, nil +} + +// DeleteDeploymentBranchPolicy deletes a deployment branch policy for an environment. +// +// GitHub API docs: https://docs.github.com/rest/deployments/branch-policies#delete-a-deployment-branch-policy +// +//meta:operation DELETE /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id} +func (s *RepositoriesService) DeleteDeploymentBranchPolicy(ctx context.Context, owner, repo, environment string, branchPolicyID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/environments/%v/deployment-branch-policies/%v", owner, repo, environment, branchPolicyID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_deployment_protection_rules.go b/vendor/github.com/google/go-github/v68/github/repos_deployment_protection_rules.go new file mode 100644 index 0000000000..29d4903281 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_deployment_protection_rules.go @@ -0,0 +1,148 @@ +// Copyright 2024 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// CustomDeploymentProtectionRuleApp represents a single deployment protection rule app for an environment. +type CustomDeploymentProtectionRuleApp struct { + ID *int64 `json:"id,omitempty"` + Slug *string `json:"slug,omitempty"` + IntegrationURL *string `json:"integration_url,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +// CustomDeploymentProtectionRule represents a single deployment protection rule for an environment. +type CustomDeploymentProtectionRule struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + App *CustomDeploymentProtectionRuleApp `json:"app,omitempty"` +} + +// ListDeploymentProtectionRuleResponse represents the response that comes back when you list deployment protection rules. +type ListDeploymentProtectionRuleResponse struct { + TotalCount *int `json:"total_count,omitempty"` + ProtectionRules []*CustomDeploymentProtectionRule `json:"custom_deployment_protection_rules,omitempty"` +} + +// ListCustomDeploymentRuleIntegrationsResponse represents the slightly different response that comes back when you list custom deployment rule integrations. +type ListCustomDeploymentRuleIntegrationsResponse struct { + TotalCount *int `json:"total_count,omitempty"` + AvailableIntegrations []*CustomDeploymentProtectionRuleApp `json:"available_custom_deployment_protection_rule_integrations,omitempty"` +} + +// CustomDeploymentProtectionRuleRequest represents a deployment protection rule request. +type CustomDeploymentProtectionRuleRequest struct { + IntegrationID *int64 `json:"integration_id,omitempty"` +} + +// GetAllDeploymentProtectionRules gets all the deployment protection rules for an environment. +// +// GitHub API docs: https://docs.github.com/rest/deployments/protection-rules#get-all-deployment-protection-rules-for-an-environment +// +//meta:operation GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules +func (s *RepositoriesService) GetAllDeploymentProtectionRules(ctx context.Context, owner, repo, environment string) (*ListDeploymentProtectionRuleResponse, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/environments/%v/deployment_protection_rules", owner, repo, environment) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var list *ListDeploymentProtectionRuleResponse + resp, err := s.client.Do(ctx, req, &list) + if err != nil { + return nil, resp, err + } + + return list, resp, nil +} + +// CreateCustomDeploymentProtectionRule creates a custom deployment protection rule on an environment. +// +// GitHub API docs: https://docs.github.com/rest/deployments/protection-rules#create-a-custom-deployment-protection-rule-on-an-environment +// +//meta:operation POST /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules +func (s *RepositoriesService) CreateCustomDeploymentProtectionRule(ctx context.Context, owner, repo, environment string, request *CustomDeploymentProtectionRuleRequest) (*CustomDeploymentProtectionRule, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/environments/%v/deployment_protection_rules", owner, repo, environment) + + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + protectionRule := new(CustomDeploymentProtectionRule) + resp, err := s.client.Do(ctx, req, protectionRule) + if err != nil { + return nil, resp, err + } + + return protectionRule, resp, nil +} + +// ListCustomDeploymentRuleIntegrations lists the custom deployment rule integrations for an environment. +// +// GitHub API docs: https://docs.github.com/rest/deployments/protection-rules#list-custom-deployment-rule-integrations-available-for-an-environment +// +//meta:operation GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/apps +func (s *RepositoriesService) ListCustomDeploymentRuleIntegrations(ctx context.Context, owner, repo, environment string) (*ListCustomDeploymentRuleIntegrationsResponse, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/environments/%v/deployment_protection_rules/apps", owner, repo, environment) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var list *ListCustomDeploymentRuleIntegrationsResponse + resp, err := s.client.Do(ctx, req, &list) + if err != nil { + return nil, resp, err + } + + return list, resp, nil +} + +// GetCustomDeploymentProtectionRule gets a custom deployment protection rule for an environment. +// +// GitHub API docs: https://docs.github.com/rest/deployments/protection-rules#get-a-custom-deployment-protection-rule +// +//meta:operation GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/{protection_rule_id} +func (s *RepositoriesService) GetCustomDeploymentProtectionRule(ctx context.Context, owner, repo, environment string, protectionRuleID int64) (*CustomDeploymentProtectionRule, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/environments/%v/deployment_protection_rules/%v", owner, repo, environment, protectionRuleID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var protectionRule *CustomDeploymentProtectionRule + resp, err := s.client.Do(ctx, req, &protectionRule) + if err != nil { + return nil, resp, err + } + + return protectionRule, resp, nil +} + +// DisableCustomDeploymentProtectionRule disables a custom deployment protection rule for an environment. +// +// GitHub API docs: https://docs.github.com/rest/deployments/protection-rules#disable-a-custom-protection-rule-for-an-environment +// +//meta:operation DELETE /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/{protection_rule_id} +func (s *RepositoriesService) DisableCustomDeploymentProtectionRule(ctx context.Context, owner, repo, environment string, protectionRuleID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/environments/%v/deployment_protection_rules/%v", owner, repo, environment, protectionRuleID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_deployments.go b/vendor/github.com/google/go-github/v68/github/repos_deployments.go new file mode 100644 index 0000000000..6277ac2151 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_deployments.go @@ -0,0 +1,264 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" + "strings" +) + +// Deployment represents a deployment in a repo. +type Deployment struct { + URL *string `json:"url,omitempty"` + ID *int64 `json:"id,omitempty"` + SHA *string `json:"sha,omitempty"` + Ref *string `json:"ref,omitempty"` + Task *string `json:"task,omitempty"` + Payload json.RawMessage `json:"payload,omitempty"` + Environment *string `json:"environment,omitempty"` + Description *string `json:"description,omitempty"` + Creator *User `json:"creator,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + StatusesURL *string `json:"statuses_url,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +// DeploymentRequest represents a deployment request. +type DeploymentRequest struct { + Ref *string `json:"ref,omitempty"` + Task *string `json:"task,omitempty"` + AutoMerge *bool `json:"auto_merge,omitempty"` + RequiredContexts *[]string `json:"required_contexts,omitempty"` + Payload interface{} `json:"payload,omitempty"` + Environment *string `json:"environment,omitempty"` + Description *string `json:"description,omitempty"` + TransientEnvironment *bool `json:"transient_environment,omitempty"` + ProductionEnvironment *bool `json:"production_environment,omitempty"` +} + +// DeploymentsListOptions specifies the optional parameters to the +// RepositoriesService.ListDeployments method. +type DeploymentsListOptions struct { + // SHA of the Deployment. + SHA string `url:"sha,omitempty"` + + // List deployments for a given ref. + Ref string `url:"ref,omitempty"` + + // List deployments for a given task. + Task string `url:"task,omitempty"` + + // List deployments for a given environment. + Environment string `url:"environment,omitempty"` + + ListOptions +} + +// ListDeployments lists the deployments of a repository. +// +// GitHub API docs: https://docs.github.com/rest/deployments/deployments#list-deployments +// +//meta:operation GET /repos/{owner}/{repo}/deployments +func (s *RepositoriesService) ListDeployments(ctx context.Context, owner, repo string, opts *DeploymentsListOptions) ([]*Deployment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/deployments", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var deployments []*Deployment + resp, err := s.client.Do(ctx, req, &deployments) + if err != nil { + return nil, resp, err + } + + return deployments, resp, nil +} + +// GetDeployment returns a single deployment of a repository. +// +// GitHub API docs: https://docs.github.com/rest/deployments/deployments#get-a-deployment +// +//meta:operation GET /repos/{owner}/{repo}/deployments/{deployment_id} +func (s *RepositoriesService) GetDeployment(ctx context.Context, owner, repo string, deploymentID int64) (*Deployment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/deployments/%v", owner, repo, deploymentID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + deployment := new(Deployment) + resp, err := s.client.Do(ctx, req, deployment) + if err != nil { + return nil, resp, err + } + + return deployment, resp, nil +} + +// CreateDeployment creates a new deployment for a repository. +// +// GitHub API docs: https://docs.github.com/rest/deployments/deployments#create-a-deployment +// +//meta:operation POST /repos/{owner}/{repo}/deployments +func (s *RepositoriesService) CreateDeployment(ctx context.Context, owner, repo string, request *DeploymentRequest) (*Deployment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/deployments", owner, repo) + + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeExpandDeploymentStatusPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + d := new(Deployment) + resp, err := s.client.Do(ctx, req, d) + if err != nil { + return nil, resp, err + } + + return d, resp, nil +} + +// DeleteDeployment deletes an existing deployment for a repository. +// +// GitHub API docs: https://docs.github.com/rest/deployments/deployments#delete-a-deployment +// +//meta:operation DELETE /repos/{owner}/{repo}/deployments/{deployment_id} +func (s *RepositoriesService) DeleteDeployment(ctx context.Context, owner, repo string, deploymentID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/deployments/%v", owner, repo, deploymentID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// DeploymentStatus represents the status of a +// particular deployment. +type DeploymentStatus struct { + ID *int64 `json:"id,omitempty"` + // State is the deployment state. + // Possible values are: "pending", "success", "failure", "error", + // "inactive", "in_progress", "queued". + State *string `json:"state,omitempty"` + Creator *User `json:"creator,omitempty"` + Description *string `json:"description,omitempty"` + Environment *string `json:"environment,omitempty"` + NodeID *string `json:"node_id,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + TargetURL *string `json:"target_url,omitempty"` + DeploymentURL *string `json:"deployment_url,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` + EnvironmentURL *string `json:"environment_url,omitempty"` + LogURL *string `json:"log_url,omitempty"` + URL *string `json:"url,omitempty"` +} + +// DeploymentStatusRequest represents a deployment request. +type DeploymentStatusRequest struct { + State *string `json:"state,omitempty"` + LogURL *string `json:"log_url,omitempty"` + Description *string `json:"description,omitempty"` + Environment *string `json:"environment,omitempty"` + EnvironmentURL *string `json:"environment_url,omitempty"` + AutoInactive *bool `json:"auto_inactive,omitempty"` +} + +// ListDeploymentStatuses lists the statuses of a given deployment of a repository. +// +// GitHub API docs: https://docs.github.com/rest/deployments/statuses#list-deployment-statuses +// +//meta:operation GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses +func (s *RepositoriesService) ListDeploymentStatuses(ctx context.Context, owner, repo string, deployment int64, opts *ListOptions) ([]*DeploymentStatus, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses", owner, repo, deployment) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeExpandDeploymentStatusPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var statuses []*DeploymentStatus + resp, err := s.client.Do(ctx, req, &statuses) + if err != nil { + return nil, resp, err + } + + return statuses, resp, nil +} + +// GetDeploymentStatus returns a single deployment status of a repository. +// +// GitHub API docs: https://docs.github.com/rest/deployments/statuses#get-a-deployment-status +// +//meta:operation GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses/{status_id} +func (s *RepositoriesService) GetDeploymentStatus(ctx context.Context, owner, repo string, deploymentID, deploymentStatusID int64) (*DeploymentStatus, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses/%v", owner, repo, deploymentID, deploymentStatusID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeExpandDeploymentStatusPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + d := new(DeploymentStatus) + resp, err := s.client.Do(ctx, req, d) + if err != nil { + return nil, resp, err + } + + return d, resp, nil +} + +// CreateDeploymentStatus creates a new status for a deployment. +// +// GitHub API docs: https://docs.github.com/rest/deployments/statuses#create-a-deployment-status +// +//meta:operation POST /repos/{owner}/{repo}/deployments/{deployment_id}/statuses +func (s *RepositoriesService) CreateDeploymentStatus(ctx context.Context, owner, repo string, deployment int64, request *DeploymentStatusRequest) (*DeploymentStatus, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses", owner, repo, deployment) + + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeExpandDeploymentStatusPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + d := new(DeploymentStatus) + resp, err := s.client.Do(ctx, req, d) + if err != nil { + return nil, resp, err + } + + return d, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_environments.go b/vendor/github.com/google/go-github/v68/github/repos_environments.go new file mode 100644 index 0000000000..d3e34fa8f8 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_environments.go @@ -0,0 +1,252 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" + "net/http" +) + +// Environment represents a single environment in a repository. +type Environment struct { + Owner *string `json:"owner,omitempty"` + Repo *string `json:"repo,omitempty"` + EnvironmentName *string `json:"environment_name,omitempty"` + WaitTimer *int `json:"wait_timer,omitempty"` + Reviewers []*EnvReviewers `json:"reviewers,omitempty"` + DeploymentBranchPolicy *BranchPolicy `json:"deployment_branch_policy,omitempty"` + // Return/response only values + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Name *string `json:"name,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + CanAdminsBypass *bool `json:"can_admins_bypass,omitempty"` + ProtectionRules []*ProtectionRule `json:"protection_rules,omitempty"` +} + +// EnvReviewers represents a single environment reviewer entry. +type EnvReviewers struct { + Type *string `json:"type,omitempty"` + ID *int64 `json:"id,omitempty"` +} + +// BranchPolicy represents the options for whether a branch deployment policy is applied to this environment. +type BranchPolicy struct { + ProtectedBranches *bool `json:"protected_branches,omitempty"` + CustomBranchPolicies *bool `json:"custom_branch_policies,omitempty"` +} + +// EnvResponse represents the slightly different format of response that comes back when you list an environment. +type EnvResponse struct { + TotalCount *int `json:"total_count,omitempty"` + Environments []*Environment `json:"environments,omitempty"` +} + +// ProtectionRule represents a single protection rule applied to the environment. +type ProtectionRule struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + PreventSelfReview *bool `json:"prevent_self_review,omitempty"` + Type *string `json:"type,omitempty"` + WaitTimer *int `json:"wait_timer,omitempty"` + Reviewers []*RequiredReviewer `json:"reviewers,omitempty"` +} + +// RequiredReviewer represents a required reviewer. +type RequiredReviewer struct { + Type *string `json:"type,omitempty"` + Reviewer interface{} `json:"reviewer,omitempty"` +} + +// EnvironmentListOptions specifies the optional parameters to the +// RepositoriesService.ListEnvironments method. +type EnvironmentListOptions struct { + ListOptions +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +// This helps us handle the fact that RequiredReviewer can have either a User or Team type reviewer field. +func (r *RequiredReviewer) UnmarshalJSON(data []byte) error { + type aliasReviewer RequiredReviewer + var reviewer aliasReviewer + if err := json.Unmarshal(data, &reviewer); err != nil { + return err + } + + r.Type = reviewer.Type + + switch *reviewer.Type { + case "User": + reviewer.Reviewer = &User{} + if err := json.Unmarshal(data, &reviewer); err != nil { + return err + } + r.Reviewer = reviewer.Reviewer + case "Team": + reviewer.Reviewer = &Team{} + if err := json.Unmarshal(data, &reviewer); err != nil { + return err + } + r.Reviewer = reviewer.Reviewer + default: + r.Type = nil + r.Reviewer = nil + return fmt.Errorf("reviewer.Type is %T, not a string of 'User' or 'Team', unable to unmarshal", reviewer.Type) + } + + return nil +} + +// ListEnvironments lists all environments for a repository. +// +// GitHub API docs: https://docs.github.com/rest/deployments/environments#list-environments +// +//meta:operation GET /repos/{owner}/{repo}/environments +func (s *RepositoriesService) ListEnvironments(ctx context.Context, owner, repo string, opts *EnvironmentListOptions) (*EnvResponse, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/environments", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var list *EnvResponse + resp, err := s.client.Do(ctx, req, &list) + if err != nil { + return nil, resp, err + } + return list, resp, nil +} + +// GetEnvironment get a single environment for a repository. +// +// GitHub API docs: https://docs.github.com/rest/deployments/environments#get-an-environment +// +//meta:operation GET /repos/{owner}/{repo}/environments/{environment_name} +func (s *RepositoriesService) GetEnvironment(ctx context.Context, owner, repo, name string) (*Environment, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/environments/%s", owner, repo, name) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var env *Environment + resp, err := s.client.Do(ctx, req, &env) + if err != nil { + return nil, resp, err + } + return env, resp, nil +} + +// MarshalJSON implements the json.Marshaler interface. +// As the only way to clear a WaitTimer is to set it to 0, a missing WaitTimer object should default to 0, not null. +// As the default value for CanAdminsBypass is true, a nil value here marshals to true. +func (c *CreateUpdateEnvironment) MarshalJSON() ([]byte, error) { + type Alias CreateUpdateEnvironment + if c.WaitTimer == nil { + c.WaitTimer = Ptr(0) + } + if c.CanAdminsBypass == nil { + c.CanAdminsBypass = Ptr(true) + } + return json.Marshal(&struct { + *Alias + }{ + Alias: (*Alias)(c), + }) +} + +// CreateUpdateEnvironment represents the fields required for the create/update operation +// following the Create/Update release example. +// See https://github.com/google/go-github/issues/992 for more information. +// Removed omitempty here as the API expects null values for reviewers and deployment_branch_policy to clear them. +type CreateUpdateEnvironment struct { + WaitTimer *int `json:"wait_timer"` + Reviewers []*EnvReviewers `json:"reviewers"` + CanAdminsBypass *bool `json:"can_admins_bypass"` + DeploymentBranchPolicy *BranchPolicy `json:"deployment_branch_policy"` + PreventSelfReview *bool `json:"prevent_self_review,omitempty"` +} + +// createUpdateEnvironmentNoEnterprise represents the fields accepted for Pro/Teams private repos. +// Ref: https://docs.github.com/actions/deployment/targeting-different-environments/using-environments-for-deployment +// See https://github.com/google/go-github/issues/2602 for more information. +type createUpdateEnvironmentNoEnterprise struct { + DeploymentBranchPolicy *BranchPolicy `json:"deployment_branch_policy"` +} + +// CreateUpdateEnvironment create or update a new environment for a repository. +// +// GitHub API docs: https://docs.github.com/rest/deployments/environments#create-or-update-an-environment +// +//meta:operation PUT /repos/{owner}/{repo}/environments/{environment_name} +func (s *RepositoriesService) CreateUpdateEnvironment(ctx context.Context, owner, repo, name string, environment *CreateUpdateEnvironment) (*Environment, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/environments/%s", owner, repo, name) + + req, err := s.client.NewRequest("PUT", u, environment) + if err != nil { + return nil, nil, err + } + + e := new(Environment) + resp, err := s.client.Do(ctx, req, e) + if err != nil { + // The API returns 422 when the pricing plan doesn't support all the fields sent. + // This path will be executed for Pro/Teams private repos. + // For public repos, regardless of the pricing plan, all fields supported. + // For Free plan private repos the returned error code is 404. + // We are checking that the user didn't try to send a value for unsupported fields, + // and return an error if they did. + if resp != nil && resp.StatusCode == http.StatusUnprocessableEntity && environment != nil && len(environment.Reviewers) == 0 && environment.GetWaitTimer() == 0 { + return s.createNewEnvNoEnterprise(ctx, u, environment) + } + return nil, resp, err + } + return e, resp, nil +} + +// createNewEnvNoEnterprise is an internal function for cases where the original call returned 422. +// Currently only the `deployment_branch_policy` parameter is supported for Pro/Team private repos. +func (s *RepositoriesService) createNewEnvNoEnterprise(ctx context.Context, u string, environment *CreateUpdateEnvironment) (*Environment, *Response, error) { + req, err := s.client.NewRequest("PUT", u, &createUpdateEnvironmentNoEnterprise{ + DeploymentBranchPolicy: environment.DeploymentBranchPolicy, + }) + if err != nil { + return nil, nil, err + } + + e := new(Environment) + resp, err := s.client.Do(ctx, req, e) + if err != nil { + return nil, resp, err + } + return e, resp, nil +} + +// DeleteEnvironment delete an environment from a repository. +// +// GitHub API docs: https://docs.github.com/rest/deployments/environments#delete-an-environment +// +//meta:operation DELETE /repos/{owner}/{repo}/environments/{environment_name} +func (s *RepositoriesService) DeleteEnvironment(ctx context.Context, owner, repo, name string) (*Response, error) { + u := fmt.Sprintf("repos/%s/%s/environments/%s", owner, repo, name) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_forks.go b/vendor/github.com/google/go-github/v68/github/repos_forks.go new file mode 100644 index 0000000000..60fb49da5a --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_forks.go @@ -0,0 +1,97 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" +) + +// RepositoryListForksOptions specifies the optional parameters to the +// RepositoriesService.ListForks method. +type RepositoryListForksOptions struct { + // How to sort the forks list. Possible values are: newest, oldest, + // watchers. Default is "newest". + Sort string `url:"sort,omitempty"` + + ListOptions +} + +// ListForks lists the forks of the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/forks#list-forks +// +//meta:operation GET /repos/{owner}/{repo}/forks +func (s *RepositoriesService) ListForks(ctx context.Context, owner, repo string, opts *RepositoryListForksOptions) ([]*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/forks", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when topics API fully launches. + req.Header.Set("Accept", mediaTypeTopicsPreview) + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// RepositoryCreateForkOptions specifies the optional parameters to the +// RepositoriesService.CreateFork method. +type RepositoryCreateForkOptions struct { + // The organization to fork the repository into. + Organization string `json:"organization,omitempty"` + Name string `json:"name,omitempty"` + DefaultBranchOnly bool `json:"default_branch_only,omitempty"` +} + +// CreateFork creates a fork of the specified repository. +// +// This method might return an *AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it is now computing creating the fork in a background task. In this event, +// the Repository value will be returned, which includes the details about the pending fork. +// A follow up request, after a delay of a second or so, should result +// in a successful request. +// +// GitHub API docs: https://docs.github.com/rest/repos/forks#create-a-fork +// +//meta:operation POST /repos/{owner}/{repo}/forks +func (s *RepositoriesService) CreateFork(ctx context.Context, owner, repo string, opts *RepositoryCreateForkOptions) (*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/forks", owner, repo) + + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + fork := new(Repository) + resp, err := s.client.Do(ctx, req, fork) + if err != nil { + // Persist AcceptedError's metadata to the Repository object. + if aerr, ok := err.(*AcceptedError); ok { + if err := json.Unmarshal(aerr.Raw, fork); err != nil { + return fork, resp, err + } + + return fork, resp, err + } + return nil, resp, err + } + + return fork, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_hooks.go b/vendor/github.com/google/go-github/v68/github/repos_hooks.go new file mode 100644 index 0000000000..d221db21b6 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_hooks.go @@ -0,0 +1,271 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" + "net/url" + "strings" +) + +// WebHookPayload represents the data that is received from GitHub when a push +// event hook is triggered. The format of these payloads pre-date most of the +// GitHub v3 API, so there are lots of minor incompatibilities with the types +// defined in the rest of the API. Therefore, several types are duplicated +// here to account for these differences. +// +// GitHub API docs: https://help.github.com/articles/post-receive-hooks +// +// Deprecated: Please use PushEvent instead. +type WebHookPayload = PushEvent + +// WebHookCommit represents the commit variant we receive from GitHub in a +// WebHookPayload. +// +// Deprecated: Please use HeadCommit instead. +type WebHookCommit = HeadCommit + +// WebHookAuthor represents the author or committer of a commit, as specified +// in a WebHookCommit. The commit author may not correspond to a GitHub User. +// +// Deprecated: Please use CommitAuthor instead. +// NOTE Breaking API change: the `Username` field is now called `Login`. +type WebHookAuthor = CommitAuthor + +// Hook represents a GitHub (web and service) hook for a repository. +type Hook struct { + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + URL *string `json:"url,omitempty"` + ID *int64 `json:"id,omitempty"` + Type *string `json:"type,omitempty"` + Name *string `json:"name,omitempty"` + TestURL *string `json:"test_url,omitempty"` + PingURL *string `json:"ping_url,omitempty"` + LastResponse map[string]interface{} `json:"last_response,omitempty"` + + // Only the following fields are used when creating a hook. + // Config is required. + Config *HookConfig `json:"config,omitempty"` + Events []string `json:"events,omitempty"` + Active *bool `json:"active,omitempty"` +} + +func (h Hook) String() string { + return Stringify(h) +} + +// createHookRequest is a subset of Hook and is used internally +// by CreateHook to pass only the known fields for the endpoint. +// +// See https://github.com/google/go-github/issues/1015 for more +// information. +type createHookRequest struct { + // Config is required. + Name string `json:"name"` + Config *HookConfig `json:"config,omitempty"` + Events []string `json:"events,omitempty"` + Active *bool `json:"active,omitempty"` +} + +// CreateHook creates a Hook for the specified repository. +// Config is a required field. +// +// Note that only a subset of the hook fields are used and hook must +// not be nil. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#create-a-repository-webhook +// +//meta:operation POST /repos/{owner}/{repo}/hooks +func (s *RepositoriesService) CreateHook(ctx context.Context, owner, repo string, hook *Hook) (*Hook, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo) + + hookReq := &createHookRequest{ + Name: "web", + Events: hook.Events, + Active: hook.Active, + Config: hook.Config, + } + + req, err := s.client.NewRequest("POST", u, hookReq) + if err != nil { + return nil, nil, err + } + + h := new(Hook) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// ListHooks lists all Hooks for the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#list-repository-webhooks +// +//meta:operation GET /repos/{owner}/{repo}/hooks +func (s *RepositoriesService) ListHooks(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Hook, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var hooks []*Hook + resp, err := s.client.Do(ctx, req, &hooks) + if err != nil { + return nil, resp, err + } + + return hooks, resp, nil +} + +// GetHook returns a single specified Hook. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#get-a-repository-webhook +// +//meta:operation GET /repos/{owner}/{repo}/hooks/{hook_id} +func (s *RepositoriesService) GetHook(ctx context.Context, owner, repo string, id int64) (*Hook, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + h := new(Hook) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// EditHook updates a specified Hook. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#update-a-repository-webhook +// +//meta:operation PATCH /repos/{owner}/{repo}/hooks/{hook_id} +func (s *RepositoriesService) EditHook(ctx context.Context, owner, repo string, id int64, hook *Hook) (*Hook, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) + req, err := s.client.NewRequest("PATCH", u, hook) + if err != nil { + return nil, nil, err + } + h := new(Hook) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// DeleteHook deletes a specified Hook. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#delete-a-repository-webhook +// +//meta:operation DELETE /repos/{owner}/{repo}/hooks/{hook_id} +func (s *RepositoriesService) DeleteHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// PingHook triggers a 'ping' event to be sent to the Hook. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#ping-a-repository-webhook +// +//meta:operation POST /repos/{owner}/{repo}/hooks/{hook_id}/pings +func (s *RepositoriesService) PingHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d/pings", owner, repo, id) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// TestHook triggers a test Hook by github. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#test-the-push-repository-webhook +// +//meta:operation POST /repos/{owner}/{repo}/hooks/{hook_id}/tests +func (s *RepositoriesService) TestHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d/tests", owner, repo, id) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// Subscribe lets servers register to receive updates when a topic is updated. +// +// GitHub API docs: https://docs.github.com/webhooks/about-webhooks-for-repositories#pubsubhubbub +// +//meta:operation POST /hub +func (s *RepositoriesService) Subscribe(ctx context.Context, owner, repo, event, callback string, secret []byte) (*Response, error) { + req, err := s.createWebSubRequest("subscribe", owner, repo, event, callback, secret) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Unsubscribe lets servers unregister to no longer receive updates when a topic is updated. +// +// GitHub API docs: https://docs.github.com/webhooks/about-webhooks-for-repositories#pubsubhubbub +// +//meta:operation POST /hub +func (s *RepositoriesService) Unsubscribe(ctx context.Context, owner, repo, event, callback string, secret []byte) (*Response, error) { + req, err := s.createWebSubRequest("unsubscribe", owner, repo, event, callback, secret) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// createWebSubRequest returns a subscribe/unsubscribe request that implements +// the WebSub (formerly PubSubHubbub) protocol. +// +// See: https://www.w3.org/TR/websub/#subscriber-sends-subscription-request +func (s *RepositoriesService) createWebSubRequest(hubMode, owner, repo, event, callback string, secret []byte) (*http.Request, error) { + topic := fmt.Sprintf( + "https://github.com/%s/%s/events/%s", + owner, + repo, + event, + ) + form := url.Values{} + form.Add("hub.mode", hubMode) + form.Add("hub.topic", topic) + form.Add("hub.callback", callback) + if secret != nil { + form.Add("hub.secret", string(secret)) + } + body := strings.NewReader(form.Encode()) + + req, err := s.client.NewFormRequest("hub", body) + if err != nil { + return nil, err + } + + return req, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_hooks_configuration.go b/vendor/github.com/google/go-github/v68/github/repos_hooks_configuration.go new file mode 100644 index 0000000000..9560bd7a4b --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_hooks_configuration.go @@ -0,0 +1,68 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// HookConfig describes metadata about a webhook configuration. +type HookConfig struct { + // The media type used to serialize the payloads + // Possible values are `json` and `form`, the field is not specified the default is `form` + ContentType *string `json:"content_type,omitempty"` + // The possible values are 0 and 1. + // Setting it to 1 will allow skip certificate verification for the host, + // potentially exposing to MitM attacks: https://en.wikipedia.org/wiki/Man-in-the-middle_attack + InsecureSSL *string `json:"insecure_ssl,omitempty"` + URL *string `json:"url,omitempty"` + + // Secret is returned obfuscated by GitHub, but it can be set for outgoing requests. + Secret *string `json:"secret,omitempty"` +} + +// GetHookConfiguration returns the configuration for the specified repository webhook. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#get-a-webhook-configuration-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/hooks/{hook_id}/config +func (s *RepositoriesService) GetHookConfiguration(ctx context.Context, owner, repo string, id int64) (*HookConfig, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%v/config", owner, repo, id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + config := new(HookConfig) + resp, err := s.client.Do(ctx, req, config) + if err != nil { + return nil, resp, err + } + + return config, resp, nil +} + +// EditHookConfiguration updates the configuration for the specified repository webhook. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#update-a-webhook-configuration-for-a-repository +// +//meta:operation PATCH /repos/{owner}/{repo}/hooks/{hook_id}/config +func (s *RepositoriesService) EditHookConfiguration(ctx context.Context, owner, repo string, id int64, config *HookConfig) (*HookConfig, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%v/config", owner, repo, id) + req, err := s.client.NewRequest("PATCH", u, config) + if err != nil { + return nil, nil, err + } + + c := new(HookConfig) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_hooks_deliveries.go b/vendor/github.com/google/go-github/v68/github/repos_hooks_deliveries.go new file mode 100644 index 0000000000..c8029f626b --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_hooks_deliveries.go @@ -0,0 +1,142 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" +) + +// HookDelivery represents the data that is received from GitHub's Webhook Delivery API +// +// GitHub API docs: +// - https://docs.github.com/rest/webhooks/repo-deliveries#list-deliveries-for-a-repository-webhook +// - https://docs.github.com/rest/webhooks/repo-deliveries#get-a-delivery-for-a-repository-webhook +type HookDelivery struct { + ID *int64 `json:"id,omitempty"` + GUID *string `json:"guid,omitempty"` + DeliveredAt *Timestamp `json:"delivered_at,omitempty"` + Redelivery *bool `json:"redelivery,omitempty"` + Duration *float64 `json:"duration,omitempty"` + Status *string `json:"status,omitempty"` + StatusCode *int `json:"status_code,omitempty"` + Event *string `json:"event,omitempty"` + Action *string `json:"action,omitempty"` + InstallationID *int64 `json:"installation_id,omitempty"` + RepositoryID *int64 `json:"repository_id,omitempty"` + + // Request is populated by GetHookDelivery. + Request *HookRequest `json:"request,omitempty"` + // Response is populated by GetHookDelivery. + Response *HookResponse `json:"response,omitempty"` +} + +func (d HookDelivery) String() string { + return Stringify(d) +} + +// HookRequest is a part of HookDelivery that contains +// the HTTP headers and the JSON payload of the webhook request. +type HookRequest struct { + Headers map[string]string `json:"headers,omitempty"` + RawPayload *json.RawMessage `json:"payload,omitempty"` +} + +func (r HookRequest) String() string { + return Stringify(r) +} + +// HookResponse is a part of HookDelivery that contains +// the HTTP headers and the response body served by the webhook endpoint. +type HookResponse struct { + Headers map[string]string `json:"headers,omitempty"` + RawPayload *json.RawMessage `json:"payload,omitempty"` +} + +func (r HookResponse) String() string { + return Stringify(r) +} + +// ListHookDeliveries lists webhook deliveries for a webhook configured in a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#list-deliveries-for-a-repository-webhook +// +//meta:operation GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries +func (s *RepositoriesService) ListHookDeliveries(ctx context.Context, owner, repo string, id int64, opts *ListCursorOptions) ([]*HookDelivery, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%v/deliveries", owner, repo, id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + deliveries := []*HookDelivery{} + resp, err := s.client.Do(ctx, req, &deliveries) + if err != nil { + return nil, resp, err + } + + return deliveries, resp, nil +} + +// GetHookDelivery returns a delivery for a webhook configured in a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#get-a-delivery-for-a-repository-webhook +// +//meta:operation GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries/{delivery_id} +func (s *RepositoriesService) GetHookDelivery(ctx context.Context, owner, repo string, hookID, deliveryID int64) (*HookDelivery, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%v/deliveries/%v", owner, repo, hookID, deliveryID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + h := new(HookDelivery) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// RedeliverHookDelivery redelivers a delivery for a webhook configured in a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#redeliver-a-delivery-for-a-repository-webhook +// +//meta:operation POST /repos/{owner}/{repo}/hooks/{hook_id}/deliveries/{delivery_id}/attempts +func (s *RepositoriesService) RedeliverHookDelivery(ctx context.Context, owner, repo string, hookID, deliveryID int64) (*HookDelivery, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%v/deliveries/%v/attempts", owner, repo, hookID, deliveryID) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + h := new(HookDelivery) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// ParseRequestPayload parses the request payload. For recognized event types, +// a value of the corresponding struct type will be returned. +func (d *HookDelivery) ParseRequestPayload() (interface{}, error) { + eType, ok := messageToTypeName[d.GetEvent()] + if !ok { + return nil, fmt.Errorf("unsupported event type %q", d.GetEvent()) + } + + e := &Event{Type: &eType, RawPayload: d.Request.RawPayload} + return e.ParsePayload() +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_invitations.go b/vendor/github.com/google/go-github/v68/github/repos_invitations.go new file mode 100644 index 0000000000..98fe01d1c9 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_invitations.go @@ -0,0 +1,96 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// RepositoryInvitation represents an invitation to collaborate on a repo. +type RepositoryInvitation struct { + ID *int64 `json:"id,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Invitee *User `json:"invitee,omitempty"` + Inviter *User `json:"inviter,omitempty"` + + // Permissions represents the permissions that the associated user will have + // on the repository. Possible values are: "read", "write", "admin". + Permissions *string `json:"permissions,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + Expired *bool `json:"expired,omitempty"` +} + +// ListInvitations lists all currently-open repository invitations. +// +// GitHub API docs: https://docs.github.com/rest/collaborators/invitations#list-repository-invitations +// +//meta:operation GET /repos/{owner}/{repo}/invitations +func (s *RepositoriesService) ListInvitations(ctx context.Context, owner, repo string, opts *ListOptions) ([]*RepositoryInvitation, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/invitations", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + invites := []*RepositoryInvitation{} + resp, err := s.client.Do(ctx, req, &invites) + if err != nil { + return nil, resp, err + } + + return invites, resp, nil +} + +// DeleteInvitation deletes a repository invitation. +// +// GitHub API docs: https://docs.github.com/rest/collaborators/invitations#delete-a-repository-invitation +// +//meta:operation DELETE /repos/{owner}/{repo}/invitations/{invitation_id} +func (s *RepositoriesService) DeleteInvitation(ctx context.Context, owner, repo string, invitationID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/invitations/%v", owner, repo, invitationID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// UpdateInvitation updates the permissions associated with a repository +// invitation. +// +// permissions represents the permissions that the associated user will have +// on the repository. Possible values are: "read", "write", "admin". +// +// GitHub API docs: https://docs.github.com/rest/collaborators/invitations#update-a-repository-invitation +// +//meta:operation PATCH /repos/{owner}/{repo}/invitations/{invitation_id} +func (s *RepositoriesService) UpdateInvitation(ctx context.Context, owner, repo string, invitationID int64, permissions string) (*RepositoryInvitation, *Response, error) { + opts := &struct { + Permissions string `json:"permissions"` + }{Permissions: permissions} + u := fmt.Sprintf("repos/%v/%v/invitations/%v", owner, repo, invitationID) + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + invite := &RepositoryInvitation{} + resp, err := s.client.Do(ctx, req, invite) + if err != nil { + return nil, resp, err + } + + return invite, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_keys.go b/vendor/github.com/google/go-github/v68/github/repos_keys.go new file mode 100644 index 0000000000..cc86f8bbd0 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_keys.go @@ -0,0 +1,99 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// The Key type is defined in users_keys.go + +// ListKeys lists the deploy keys for a repository. +// +// GitHub API docs: https://docs.github.com/rest/deploy-keys/deploy-keys#list-deploy-keys +// +//meta:operation GET /repos/{owner}/{repo}/keys +func (s *RepositoriesService) ListKeys(ctx context.Context, owner string, repo string, opts *ListOptions) ([]*Key, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/keys", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var keys []*Key + resp, err := s.client.Do(ctx, req, &keys) + if err != nil { + return nil, resp, err + } + + return keys, resp, nil +} + +// GetKey fetches a single deploy key. +// +// GitHub API docs: https://docs.github.com/rest/deploy-keys/deploy-keys#get-a-deploy-key +// +//meta:operation GET /repos/{owner}/{repo}/keys/{key_id} +func (s *RepositoriesService) GetKey(ctx context.Context, owner string, repo string, id int64) (*Key, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + key := new(Key) + resp, err := s.client.Do(ctx, req, key) + if err != nil { + return nil, resp, err + } + + return key, resp, nil +} + +// CreateKey adds a deploy key for a repository. +// +// GitHub API docs: https://docs.github.com/rest/deploy-keys/deploy-keys#create-a-deploy-key +// +//meta:operation POST /repos/{owner}/{repo}/keys +func (s *RepositoriesService) CreateKey(ctx context.Context, owner string, repo string, key *Key) (*Key, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/keys", owner, repo) + + req, err := s.client.NewRequest("POST", u, key) + if err != nil { + return nil, nil, err + } + + k := new(Key) + resp, err := s.client.Do(ctx, req, k) + if err != nil { + return nil, resp, err + } + + return k, resp, nil +} + +// DeleteKey deletes a deploy key. +// +// GitHub API docs: https://docs.github.com/rest/deploy-keys/deploy-keys#delete-a-deploy-key +// +//meta:operation DELETE /repos/{owner}/{repo}/keys/{key_id} +func (s *RepositoriesService) DeleteKey(ctx context.Context, owner string, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_lfs.go b/vendor/github.com/google/go-github/v68/github/repos_lfs.go new file mode 100644 index 0000000000..f0153c0808 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_lfs.go @@ -0,0 +1,53 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// EnableLFS turns the LFS (Large File Storage) feature ON for the selected repo. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/repos/lfs#enable-git-lfs-for-a-repository +// +//meta:operation PUT /repos/{owner}/{repo}/lfs +func (s *RepositoriesService) EnableLFS(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/lfs", owner, repo) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// DisableLFS turns the LFS (Large File Storage) feature OFF for the selected repo. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/repos/lfs#disable-git-lfs-for-a-repository +// +//meta:operation DELETE /repos/{owner}/{repo}/lfs +func (s *RepositoriesService) DisableLFS(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/lfs", owner, repo) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_merging.go b/vendor/github.com/google/go-github/v68/github/repos_merging.go new file mode 100644 index 0000000000..b26e5da1af --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_merging.go @@ -0,0 +1,76 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// RepositoryMergeRequest represents a request to merge a branch in a +// repository. +type RepositoryMergeRequest struct { + Base *string `json:"base,omitempty"` + Head *string `json:"head,omitempty"` + CommitMessage *string `json:"commit_message,omitempty"` +} + +// RepoMergeUpstreamRequest represents a request to sync a branch of +// a forked repository to keep it up-to-date with the upstream repository. +type RepoMergeUpstreamRequest struct { + Branch *string `json:"branch,omitempty"` +} + +// RepoMergeUpstreamResult represents the result of syncing a branch of +// a forked repository with the upstream repository. +type RepoMergeUpstreamResult struct { + Message *string `json:"message,omitempty"` + MergeType *string `json:"merge_type,omitempty"` + BaseBranch *string `json:"base_branch,omitempty"` +} + +// Merge a branch in the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/branches/branches#merge-a-branch +// +//meta:operation POST /repos/{owner}/{repo}/merges +func (s *RepositoriesService) Merge(ctx context.Context, owner, repo string, request *RepositoryMergeRequest) (*RepositoryCommit, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/merges", owner, repo) + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + commit := new(RepositoryCommit) + resp, err := s.client.Do(ctx, req, commit) + if err != nil { + return nil, resp, err + } + + return commit, resp, nil +} + +// MergeUpstream syncs a branch of a forked repository to keep it up-to-date +// with the upstream repository. +// +// GitHub API docs: https://docs.github.com/rest/branches/branches#sync-a-fork-branch-with-the-upstream-repository +// +//meta:operation POST /repos/{owner}/{repo}/merge-upstream +func (s *RepositoriesService) MergeUpstream(ctx context.Context, owner, repo string, request *RepoMergeUpstreamRequest) (*RepoMergeUpstreamResult, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/merge-upstream", owner, repo) + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + result := new(RepoMergeUpstreamResult) + resp, err := s.client.Do(ctx, req, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_pages.go b/vendor/github.com/google/go-github/v68/github/repos_pages.go new file mode 100644 index 0000000000..6b9ba76e44 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_pages.go @@ -0,0 +1,324 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Pages represents a GitHub Pages site configuration. +type Pages struct { + URL *string `json:"url,omitempty"` + Status *string `json:"status,omitempty"` + CNAME *string `json:"cname,omitempty"` + Custom404 *bool `json:"custom_404,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + BuildType *string `json:"build_type,omitempty"` + Source *PagesSource `json:"source,omitempty"` + Public *bool `json:"public,omitempty"` + HTTPSCertificate *PagesHTTPSCertificate `json:"https_certificate,omitempty"` + HTTPSEnforced *bool `json:"https_enforced,omitempty"` +} + +// PagesSource represents a GitHub page's source. +type PagesSource struct { + Branch *string `json:"branch,omitempty"` + Path *string `json:"path,omitempty"` +} + +// PagesError represents a build error for a GitHub Pages site. +type PagesError struct { + Message *string `json:"message,omitempty"` +} + +// PagesBuild represents the build information for a GitHub Pages site. +type PagesBuild struct { + URL *string `json:"url,omitempty"` + Status *string `json:"status,omitempty"` + Error *PagesError `json:"error,omitempty"` + Pusher *User `json:"pusher,omitempty"` + Commit *string `json:"commit,omitempty"` + Duration *int `json:"duration,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +// PagesDomain represents a domain associated with a GitHub Pages site. +type PagesDomain struct { + Host *string `json:"host,omitempty"` + URI *string `json:"uri,omitempty"` + Nameservers *string `json:"nameservers,omitempty"` + DNSResolves *bool `json:"dns_resolves,omitempty"` + IsProxied *bool `json:"is_proxied,omitempty"` + IsCloudflareIP *bool `json:"is_cloudflare_ip,omitempty"` + IsFastlyIP *bool `json:"is_fastly_ip,omitempty"` + IsOldIPAddress *bool `json:"is_old_ip_address,omitempty"` + IsARecord *bool `json:"is_a_record,omitempty"` + HasCNAMERecord *bool `json:"has_cname_record,omitempty"` + HasMXRecordsPresent *bool `json:"has_mx_records_present,omitempty"` + IsValidDomain *bool `json:"is_valid_domain,omitempty"` + IsApexDomain *bool `json:"is_apex_domain,omitempty"` + ShouldBeARecord *bool `json:"should_be_a_record,omitempty"` + IsCNAMEToGithubUserDomain *bool `json:"is_cname_to_github_user_domain,omitempty"` + IsCNAMEToPagesDotGithubDotCom *bool `json:"is_cname_to_pages_dot_github_dot_com,omitempty"` + IsCNAMEToFastly *bool `json:"is_cname_to_fastly,omitempty"` + IsPointedToGithubPagesIP *bool `json:"is_pointed_to_github_pages_ip,omitempty"` + IsNonGithubPagesIPPresent *bool `json:"is_non_github_pages_ip_present,omitempty"` + IsPagesDomain *bool `json:"is_pages_domain,omitempty"` + IsServedByPages *bool `json:"is_served_by_pages,omitempty"` + IsValid *bool `json:"is_valid,omitempty"` + Reason *string `json:"reason,omitempty"` + RespondsToHTTPS *bool `json:"responds_to_https,omitempty"` + EnforcesHTTPS *bool `json:"enforces_https,omitempty"` + HTTPSError *string `json:"https_error,omitempty"` + IsHTTPSEligible *bool `json:"is_https_eligible,omitempty"` + CAAError *string `json:"caa_error,omitempty"` +} + +// PagesHealthCheckResponse represents the response given for the health check of a GitHub Pages site. +type PagesHealthCheckResponse struct { + Domain *PagesDomain `json:"domain,omitempty"` + AltDomain *PagesDomain `json:"alt_domain,omitempty"` +} + +// PagesHTTPSCertificate represents the HTTPS Certificate information for a GitHub Pages site. +type PagesHTTPSCertificate struct { + State *string `json:"state,omitempty"` + Description *string `json:"description,omitempty"` + Domains []string `json:"domains,omitempty"` + // GitHub's API doesn't return a standard Timestamp, rather it returns a YYYY-MM-DD string. + ExpiresAt *string `json:"expires_at,omitempty"` +} + +// createPagesRequest is a subset of Pages and is used internally +// by EnablePages to pass only the known fields for the endpoint. +type createPagesRequest struct { + BuildType *string `json:"build_type,omitempty"` + Source *PagesSource `json:"source,omitempty"` +} + +// EnablePages enables GitHub Pages for the named repo. +// +// GitHub API docs: https://docs.github.com/rest/pages/pages#create-a-github-pages-site +// +//meta:operation POST /repos/{owner}/{repo}/pages +func (s *RepositoriesService) EnablePages(ctx context.Context, owner, repo string, pages *Pages) (*Pages, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages", owner, repo) + + pagesReq := &createPagesRequest{ + BuildType: pages.BuildType, + Source: pages.Source, + } + + req, err := s.client.NewRequest("POST", u, pagesReq) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeEnablePagesAPIPreview) + + enable := new(Pages) + resp, err := s.client.Do(ctx, req, enable) + if err != nil { + return nil, resp, err + } + + return enable, resp, nil +} + +// PagesUpdate sets up parameters needed to update a GitHub Pages site. +type PagesUpdate struct { + // CNAME represents a custom domain for the repository. + // Leaving CNAME empty will remove the custom domain. + CNAME *string `json:"cname"` + // BuildType is optional and can either be "legacy" or "workflow". + // "workflow" - You are using a github workflow to build your pages. + // "legacy" - You are deploying from a branch. + BuildType *string `json:"build_type,omitempty"` + // Source must include the branch name, and may optionally specify the subdirectory "/docs". + // Possible values for Source.Branch are usually "gh-pages", "main", and "master", + // or any other existing branch name. + // Possible values for Source.Path are: "/", and "/docs". + Source *PagesSource `json:"source,omitempty"` + // Public configures access controls for the site. + // If "true", the site will be accessible to anyone on the internet. If "false", + // the site will be accessible to anyone with read access to the repository that + // published the site. + Public *bool `json:"public,omitempty"` + // HTTPSEnforced specifies whether HTTPS should be enforced for the repository. + HTTPSEnforced *bool `json:"https_enforced,omitempty"` +} + +// UpdatePages updates GitHub Pages for the named repo. +// +// GitHub API docs: https://docs.github.com/rest/pages/pages#update-information-about-a-github-pages-site +// +//meta:operation PUT /repos/{owner}/{repo}/pages +func (s *RepositoriesService) UpdatePages(ctx context.Context, owner, repo string, opts *PagesUpdate) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages", owner, repo) + + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// DisablePages disables GitHub Pages for the named repo. +// +// GitHub API docs: https://docs.github.com/rest/pages/pages#delete-a-github-pages-site +// +//meta:operation DELETE /repos/{owner}/{repo}/pages +func (s *RepositoriesService) DisablePages(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages", owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeEnablePagesAPIPreview) + + return s.client.Do(ctx, req, nil) +} + +// GetPagesInfo fetches information about a GitHub Pages site. +// +// GitHub API docs: https://docs.github.com/rest/pages/pages#get-a-github-pages-site +// +//meta:operation GET /repos/{owner}/{repo}/pages +func (s *RepositoriesService) GetPagesInfo(ctx context.Context, owner, repo string) (*Pages, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + site := new(Pages) + resp, err := s.client.Do(ctx, req, site) + if err != nil { + return nil, resp, err + } + + return site, resp, nil +} + +// ListPagesBuilds lists the builds for a GitHub Pages site. +// +// GitHub API docs: https://docs.github.com/rest/pages/pages#list-github-pages-builds +// +//meta:operation GET /repos/{owner}/{repo}/pages/builds +func (s *RepositoriesService) ListPagesBuilds(ctx context.Context, owner, repo string, opts *ListOptions) ([]*PagesBuild, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages/builds", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pages []*PagesBuild + resp, err := s.client.Do(ctx, req, &pages) + if err != nil { + return nil, resp, err + } + + return pages, resp, nil +} + +// GetLatestPagesBuild fetches the latest build information for a GitHub pages site. +// +// GitHub API docs: https://docs.github.com/rest/pages/pages#get-latest-pages-build +// +//meta:operation GET /repos/{owner}/{repo}/pages/builds/latest +func (s *RepositoriesService) GetLatestPagesBuild(ctx context.Context, owner, repo string) (*PagesBuild, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages/builds/latest", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + build := new(PagesBuild) + resp, err := s.client.Do(ctx, req, build) + if err != nil { + return nil, resp, err + } + + return build, resp, nil +} + +// GetPageBuild fetches the specific build information for a GitHub pages site. +// +// GitHub API docs: https://docs.github.com/rest/pages/pages#get-github-pages-build +// +//meta:operation GET /repos/{owner}/{repo}/pages/builds/{build_id} +func (s *RepositoriesService) GetPageBuild(ctx context.Context, owner, repo string, id int64) (*PagesBuild, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages/builds/%v", owner, repo, id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + build := new(PagesBuild) + resp, err := s.client.Do(ctx, req, build) + if err != nil { + return nil, resp, err + } + + return build, resp, nil +} + +// RequestPageBuild requests a build of a GitHub Pages site without needing to push new commit. +// +// GitHub API docs: https://docs.github.com/rest/pages/pages#request-a-github-pages-build +// +//meta:operation POST /repos/{owner}/{repo}/pages/builds +func (s *RepositoriesService) RequestPageBuild(ctx context.Context, owner, repo string) (*PagesBuild, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages/builds", owner, repo) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + build := new(PagesBuild) + resp, err := s.client.Do(ctx, req, build) + if err != nil { + return nil, resp, err + } + + return build, resp, nil +} + +// GetPageHealthCheck gets a DNS health check for the CNAME record configured for a repository's GitHub Pages. +// +// GitHub API docs: https://docs.github.com/rest/pages/pages#get-a-dns-health-check-for-github-pages +// +//meta:operation GET /repos/{owner}/{repo}/pages/health +func (s *RepositoriesService) GetPageHealthCheck(ctx context.Context, owner, repo string) (*PagesHealthCheckResponse, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages/health", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + healthCheckResponse := new(PagesHealthCheckResponse) + resp, err := s.client.Do(ctx, req, healthCheckResponse) + if err != nil { + return nil, resp, err + } + + return healthCheckResponse, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_prereceive_hooks.go b/vendor/github.com/google/go-github/v68/github/repos_prereceive_hooks.go new file mode 100644 index 0000000000..e97075d020 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_prereceive_hooks.go @@ -0,0 +1,118 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// PreReceiveHook represents a GitHub pre-receive hook for a repository. +type PreReceiveHook struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Enforcement *string `json:"enforcement,omitempty"` + ConfigURL *string `json:"configuration_url,omitempty"` +} + +func (p PreReceiveHook) String() string { + return Stringify(p) +} + +// ListPreReceiveHooks lists all pre-receive hooks for the specified repository. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/repo-pre-receive-hooks#list-pre-receive-hooks-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/pre-receive-hooks +func (s *RepositoriesService) ListPreReceiveHooks(ctx context.Context, owner, repo string, opts *ListOptions) ([]*PreReceiveHook, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypePreReceiveHooksPreview) + + var hooks []*PreReceiveHook + resp, err := s.client.Do(ctx, req, &hooks) + if err != nil { + return nil, resp, err + } + + return hooks, resp, nil +} + +// GetPreReceiveHook returns a single specified pre-receive hook. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/repo-pre-receive-hooks#get-a-pre-receive-hook-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/pre-receive-hooks/{pre_receive_hook_id} +func (s *RepositoriesService) GetPreReceiveHook(ctx context.Context, owner, repo string, id int64) (*PreReceiveHook, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks/%d", owner, repo, id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypePreReceiveHooksPreview) + + h := new(PreReceiveHook) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// UpdatePreReceiveHook updates a specified pre-receive hook. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/repo-pre-receive-hooks#update-pre-receive-hook-enforcement-for-a-repository +// +//meta:operation PATCH /repos/{owner}/{repo}/pre-receive-hooks/{pre_receive_hook_id} +func (s *RepositoriesService) UpdatePreReceiveHook(ctx context.Context, owner, repo string, id int64, hook *PreReceiveHook) (*PreReceiveHook, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks/%d", owner, repo, id) + req, err := s.client.NewRequest("PATCH", u, hook) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypePreReceiveHooksPreview) + + h := new(PreReceiveHook) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// DeletePreReceiveHook deletes a specified pre-receive hook. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/repo-pre-receive-hooks#remove-pre-receive-hook-enforcement-for-a-repository +// +//meta:operation DELETE /repos/{owner}/{repo}/pre-receive-hooks/{pre_receive_hook_id} +func (s *RepositoriesService) DeletePreReceiveHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks/%d", owner, repo, id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypePreReceiveHooksPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_properties.go b/vendor/github.com/google/go-github/v68/github/repos_properties.go new file mode 100644 index 0000000000..5b12bc8b30 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_properties.go @@ -0,0 +1,60 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetAllCustomPropertyValues gets all custom property values that are set for a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/custom-properties#get-all-custom-property-values-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/properties/values +func (s *RepositoriesService) GetAllCustomPropertyValues(ctx context.Context, org, repo string) ([]*CustomPropertyValue, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/properties/values", org, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var customPropertyValues []*CustomPropertyValue + resp, err := s.client.Do(ctx, req, &customPropertyValues) + if err != nil { + return nil, resp, err + } + + return customPropertyValues, resp, nil +} + +// CreateOrUpdateCustomProperties creates new or updates existing custom property values for a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/custom-properties#create-or-update-custom-property-values-for-a-repository +// +//meta:operation PATCH /repos/{owner}/{repo}/properties/values +func (s *RepositoriesService) CreateOrUpdateCustomProperties(ctx context.Context, org, repo string, customPropertyValues []*CustomPropertyValue) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/properties/values", org, repo) + + params := struct { + Properties []*CustomPropertyValue `json:"properties"` + }{ + Properties: customPropertyValues, + } + + req, err := s.client.NewRequest("PATCH", u, params) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_releases.go b/vendor/github.com/google/go-github/v68/github/repos_releases.go new file mode 100644 index 0000000000..6023f63271 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_releases.go @@ -0,0 +1,476 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "errors" + "fmt" + "io" + "mime" + "net/http" + "os" + "path/filepath" + "strings" +) + +// RepositoryRelease represents a GitHub release in a repository. +type RepositoryRelease struct { + TagName *string `json:"tag_name,omitempty"` + TargetCommitish *string `json:"target_commitish,omitempty"` + Name *string `json:"name,omitempty"` + Body *string `json:"body,omitempty"` + Draft *bool `json:"draft,omitempty"` + Prerelease *bool `json:"prerelease,omitempty"` + // MakeLatest can be one of: "true", "false", or "legacy". + MakeLatest *string `json:"make_latest,omitempty"` + DiscussionCategoryName *string `json:"discussion_category_name,omitempty"` + + // The following fields are not used in EditRelease: + GenerateReleaseNotes *bool `json:"generate_release_notes,omitempty"` + + // The following fields are not used in CreateRelease or EditRelease: + ID *int64 `json:"id,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + PublishedAt *Timestamp `json:"published_at,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + AssetsURL *string `json:"assets_url,omitempty"` + Assets []*ReleaseAsset `json:"assets,omitempty"` + UploadURL *string `json:"upload_url,omitempty"` + ZipballURL *string `json:"zipball_url,omitempty"` + TarballURL *string `json:"tarball_url,omitempty"` + Author *User `json:"author,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +func (r RepositoryRelease) String() string { + return Stringify(r) +} + +// RepositoryReleaseNotes represents a GitHub-generated release notes. +type RepositoryReleaseNotes struct { + Name string `json:"name"` + Body string `json:"body"` +} + +// GenerateNotesOptions represents the options to generate release notes. +type GenerateNotesOptions struct { + TagName string `json:"tag_name"` + PreviousTagName *string `json:"previous_tag_name,omitempty"` + TargetCommitish *string `json:"target_commitish,omitempty"` +} + +// ReleaseAsset represents a GitHub release asset in a repository. +type ReleaseAsset struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + Name *string `json:"name,omitempty"` + Label *string `json:"label,omitempty"` + State *string `json:"state,omitempty"` + ContentType *string `json:"content_type,omitempty"` + Size *int `json:"size,omitempty"` + DownloadCount *int `json:"download_count,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + BrowserDownloadURL *string `json:"browser_download_url,omitempty"` + Uploader *User `json:"uploader,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +func (r ReleaseAsset) String() string { + return Stringify(r) +} + +// ListReleases lists the releases for a repository. +// +// GitHub API docs: https://docs.github.com/rest/releases/releases#list-releases +// +//meta:operation GET /repos/{owner}/{repo}/releases +func (s *RepositoriesService) ListReleases(ctx context.Context, owner, repo string, opts *ListOptions) ([]*RepositoryRelease, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var releases []*RepositoryRelease + resp, err := s.client.Do(ctx, req, &releases) + if err != nil { + return nil, resp, err + } + return releases, resp, nil +} + +// GetRelease fetches a single release. +// +// GitHub API docs: https://docs.github.com/rest/releases/releases#get-a-release +// +//meta:operation GET /repos/{owner}/{repo}/releases/{release_id} +func (s *RepositoriesService) GetRelease(ctx context.Context, owner, repo string, id int64) (*RepositoryRelease, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id) + return s.getSingleRelease(ctx, u) +} + +// GetLatestRelease fetches the latest published release for the repository. +// +// GitHub API docs: https://docs.github.com/rest/releases/releases#get-the-latest-release +// +//meta:operation GET /repos/{owner}/{repo}/releases/latest +func (s *RepositoriesService) GetLatestRelease(ctx context.Context, owner, repo string) (*RepositoryRelease, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/latest", owner, repo) + return s.getSingleRelease(ctx, u) +} + +// GetReleaseByTag fetches a release with the specified tag. +// +// GitHub API docs: https://docs.github.com/rest/releases/releases#get-a-release-by-tag-name +// +//meta:operation GET /repos/{owner}/{repo}/releases/tags/{tag} +func (s *RepositoriesService) GetReleaseByTag(ctx context.Context, owner, repo, tag string) (*RepositoryRelease, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/tags/%s", owner, repo, tag) + return s.getSingleRelease(ctx, u) +} + +// GenerateReleaseNotes generates the release notes for the given tag. +// +// GitHub API docs: https://docs.github.com/rest/releases/releases#generate-release-notes-content-for-a-release +// +//meta:operation POST /repos/{owner}/{repo}/releases/generate-notes +func (s *RepositoriesService) GenerateReleaseNotes(ctx context.Context, owner, repo string, opts *GenerateNotesOptions) (*RepositoryReleaseNotes, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/generate-notes", owner, repo) + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + r := new(RepositoryReleaseNotes) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +func (s *RepositoriesService) getSingleRelease(ctx context.Context, url string) (*RepositoryRelease, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + release := new(RepositoryRelease) + resp, err := s.client.Do(ctx, req, release) + if err != nil { + return nil, resp, err + } + return release, resp, nil +} + +// repositoryReleaseRequest is a subset of RepositoryRelease and +// is used internally by CreateRelease and EditRelease to pass +// only the known fields for these endpoints. +// +// See https://github.com/google/go-github/issues/992 for more +// information. +type repositoryReleaseRequest struct { + TagName *string `json:"tag_name,omitempty"` + TargetCommitish *string `json:"target_commitish,omitempty"` + Name *string `json:"name,omitempty"` + Body *string `json:"body,omitempty"` + Draft *bool `json:"draft,omitempty"` + Prerelease *bool `json:"prerelease,omitempty"` + MakeLatest *string `json:"make_latest,omitempty"` + GenerateReleaseNotes *bool `json:"generate_release_notes,omitempty"` + DiscussionCategoryName *string `json:"discussion_category_name,omitempty"` +} + +// CreateRelease adds a new release for a repository. +// +// Note that only a subset of the release fields are used. +// See RepositoryRelease for more information. +// +// GitHub API docs: https://docs.github.com/rest/releases/releases#create-a-release +// +//meta:operation POST /repos/{owner}/{repo}/releases +func (s *RepositoriesService) CreateRelease(ctx context.Context, owner, repo string, release *RepositoryRelease) (*RepositoryRelease, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases", owner, repo) + + releaseReq := &repositoryReleaseRequest{ + TagName: release.TagName, + TargetCommitish: release.TargetCommitish, + Name: release.Name, + Body: release.Body, + Draft: release.Draft, + Prerelease: release.Prerelease, + MakeLatest: release.MakeLatest, + DiscussionCategoryName: release.DiscussionCategoryName, + GenerateReleaseNotes: release.GenerateReleaseNotes, + } + + req, err := s.client.NewRequest("POST", u, releaseReq) + if err != nil { + return nil, nil, err + } + + r := new(RepositoryRelease) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + return r, resp, nil +} + +// EditRelease edits a repository release. +// +// Note that only a subset of the release fields are used. +// See RepositoryRelease for more information. +// +// GitHub API docs: https://docs.github.com/rest/releases/releases#update-a-release +// +//meta:operation PATCH /repos/{owner}/{repo}/releases/{release_id} +func (s *RepositoriesService) EditRelease(ctx context.Context, owner, repo string, id int64, release *RepositoryRelease) (*RepositoryRelease, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id) + + releaseReq := &repositoryReleaseRequest{ + TagName: release.TagName, + TargetCommitish: release.TargetCommitish, + Name: release.Name, + Body: release.Body, + Draft: release.Draft, + Prerelease: release.Prerelease, + MakeLatest: release.MakeLatest, + DiscussionCategoryName: release.DiscussionCategoryName, + } + + req, err := s.client.NewRequest("PATCH", u, releaseReq) + if err != nil { + return nil, nil, err + } + + r := new(RepositoryRelease) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + return r, resp, nil +} + +// DeleteRelease delete a single release from a repository. +// +// GitHub API docs: https://docs.github.com/rest/releases/releases#delete-a-release +// +//meta:operation DELETE /repos/{owner}/{repo}/releases/{release_id} +func (s *RepositoriesService) DeleteRelease(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// ListReleaseAssets lists the release's assets. +// +// GitHub API docs: https://docs.github.com/rest/releases/assets#list-release-assets +// +//meta:operation GET /repos/{owner}/{repo}/releases/{release_id}/assets +func (s *RepositoriesService) ListReleaseAssets(ctx context.Context, owner, repo string, id int64, opts *ListOptions) ([]*ReleaseAsset, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/%d/assets", owner, repo, id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var assets []*ReleaseAsset + resp, err := s.client.Do(ctx, req, &assets) + if err != nil { + return nil, resp, err + } + return assets, resp, nil +} + +// GetReleaseAsset fetches a single release asset. +// +// GitHub API docs: https://docs.github.com/rest/releases/assets#get-a-release-asset +// +//meta:operation GET /repos/{owner}/{repo}/releases/assets/{asset_id} +func (s *RepositoriesService) GetReleaseAsset(ctx context.Context, owner, repo string, id int64) (*ReleaseAsset, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + asset := new(ReleaseAsset) + resp, err := s.client.Do(ctx, req, asset) + if err != nil { + return nil, resp, err + } + return asset, resp, nil +} + +// DownloadReleaseAsset downloads a release asset or returns a redirect URL. +// +// DownloadReleaseAsset returns an io.ReadCloser that reads the contents of the +// specified release asset. It is the caller's responsibility to close the ReadCloser. +// If a redirect is returned, the redirect URL will be returned as a string instead +// of the io.ReadCloser. Exactly one of rc and redirectURL will be zero. +// +// followRedirectsClient can be passed to download the asset from a redirected +// location. Specifying any http.Client is possible, but passing http.DefaultClient +// is recommended, except when the specified repository is private, in which case +// it's necessary to pass an http.Client that performs authenticated requests. +// If nil is passed the redirectURL will be returned instead. +// +// GitHub API docs: https://docs.github.com/rest/releases/assets#get-a-release-asset +// +//meta:operation GET /repos/{owner}/{repo}/releases/assets/{asset_id} +func (s *RepositoriesService) DownloadReleaseAsset(ctx context.Context, owner, repo string, id int64, followRedirectsClient *http.Client) (rc io.ReadCloser, redirectURL string, err error) { + u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, "", err + } + req.Header.Set("Accept", defaultMediaType) + + s.client.clientMu.Lock() + defer s.client.clientMu.Unlock() + + var loc string + saveRedirect := s.client.client.CheckRedirect + s.client.client.CheckRedirect = func(req *http.Request, via []*http.Request) error { + loc = req.URL.String() + return errors.New("disable redirect") + } + defer func() { s.client.client.CheckRedirect = saveRedirect }() + + req = withContext(ctx, req) + resp, err := s.client.client.Do(req) + if err != nil { + if !strings.Contains(err.Error(), "disable redirect") { + return nil, "", err + } + if followRedirectsClient != nil { + rc, err := s.downloadReleaseAssetFromURL(ctx, followRedirectsClient, loc) + return rc, "", err + } + return nil, loc, nil // Intentionally return no error with valid redirect URL. + } + + if err := CheckResponse(resp); err != nil { + _ = resp.Body.Close() + return nil, "", err + } + + return resp.Body, "", nil +} + +func (s *RepositoriesService) downloadReleaseAssetFromURL(ctx context.Context, followRedirectsClient *http.Client, url string) (rc io.ReadCloser, err error) { + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + req = withContext(ctx, req) + req.Header.Set("Accept", defaultMediaType) + resp, err := followRedirectsClient.Do(req) + if err != nil { + return nil, err + } + if err := CheckResponse(resp); err != nil { + _ = resp.Body.Close() + return nil, err + } + return resp.Body, nil +} + +// EditReleaseAsset edits a repository release asset. +// +// GitHub API docs: https://docs.github.com/rest/releases/assets#update-a-release-asset +// +//meta:operation PATCH /repos/{owner}/{repo}/releases/assets/{asset_id} +func (s *RepositoriesService) EditReleaseAsset(ctx context.Context, owner, repo string, id int64, release *ReleaseAsset) (*ReleaseAsset, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) + + req, err := s.client.NewRequest("PATCH", u, release) + if err != nil { + return nil, nil, err + } + + asset := new(ReleaseAsset) + resp, err := s.client.Do(ctx, req, asset) + if err != nil { + return nil, resp, err + } + return asset, resp, nil +} + +// DeleteReleaseAsset delete a single release asset from a repository. +// +// GitHub API docs: https://docs.github.com/rest/releases/assets#delete-a-release-asset +// +//meta:operation DELETE /repos/{owner}/{repo}/releases/assets/{asset_id} +func (s *RepositoriesService) DeleteReleaseAsset(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// UploadReleaseAsset creates an asset by uploading a file into a release repository. +// To upload assets that cannot be represented by an os.File, call NewUploadRequest directly. +// +// GitHub API docs: https://docs.github.com/rest/releases/assets#upload-a-release-asset +// +//meta:operation POST /repos/{owner}/{repo}/releases/{release_id}/assets +func (s *RepositoriesService) UploadReleaseAsset(ctx context.Context, owner, repo string, id int64, opts *UploadOptions, file *os.File) (*ReleaseAsset, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/%d/assets", owner, repo, id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + stat, err := file.Stat() + if err != nil { + return nil, nil, err + } + if stat.IsDir() { + return nil, nil, errors.New("the asset to upload can't be a directory") + } + + mediaType := mime.TypeByExtension(filepath.Ext(file.Name())) + if opts.MediaType != "" { + mediaType = opts.MediaType + } + + req, err := s.client.NewUploadRequest(u, file, stat.Size(), mediaType) + if err != nil { + return nil, nil, err + } + + asset := new(ReleaseAsset) + resp, err := s.client.Do(ctx, req, asset) + if err != nil { + return nil, resp, err + } + return asset, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_rules.go b/vendor/github.com/google/go-github/v68/github/repos_rules.go new file mode 100644 index 0000000000..b113553a24 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_rules.go @@ -0,0 +1,995 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" +) + +// BypassActor represents the bypass actors from a ruleset. +type BypassActor struct { + ActorID *int64 `json:"actor_id,omitempty"` + // Possible values for ActorType are: RepositoryRole, Team, Integration, OrganizationAdmin + ActorType *string `json:"actor_type,omitempty"` + // Possible values for BypassMode are: always, pull_request + BypassMode *string `json:"bypass_mode,omitempty"` +} + +// RulesetLink represents a single link object from GitHub ruleset request _links. +type RulesetLink struct { + HRef *string `json:"href,omitempty"` +} + +// RulesetLinks represents the "_links" object in a Ruleset. +type RulesetLinks struct { + Self *RulesetLink `json:"self,omitempty"` +} + +// RulesetRefConditionParameters represents the conditions object for ref_names. +type RulesetRefConditionParameters struct { + Include []string `json:"include"` + Exclude []string `json:"exclude"` +} + +// RulesetRepositoryNamesConditionParameters represents the conditions object for repository_names. +type RulesetRepositoryNamesConditionParameters struct { + Include []string `json:"include"` + Exclude []string `json:"exclude"` + Protected *bool `json:"protected,omitempty"` +} + +// RulesetRepositoryIDsConditionParameters represents the conditions object for repository_ids. +type RulesetRepositoryIDsConditionParameters struct { + RepositoryIDs []int64 `json:"repository_ids,omitempty"` +} + +// RulesetRepositoryPropertyTargetParameters represents a repository_property name and values to be used for targeting. +type RulesetRepositoryPropertyTargetParameters struct { + Name string `json:"name"` + Values []string `json:"property_values"` + Source *string `json:"source,omitempty"` +} + +// RulesetRepositoryPropertyConditionParameters represents the conditions object for repository_property. +type RulesetRepositoryPropertyConditionParameters struct { + Include []RulesetRepositoryPropertyTargetParameters `json:"include"` + Exclude []RulesetRepositoryPropertyTargetParameters `json:"exclude"` +} + +// RulesetConditions represents the conditions object in a ruleset. +// Set either RepositoryName or RepositoryID or RepositoryProperty, not more than one. +type RulesetConditions struct { + RefName *RulesetRefConditionParameters `json:"ref_name,omitempty"` + RepositoryName *RulesetRepositoryNamesConditionParameters `json:"repository_name,omitempty"` + RepositoryID *RulesetRepositoryIDsConditionParameters `json:"repository_id,omitempty"` + RepositoryProperty *RulesetRepositoryPropertyConditionParameters `json:"repository_property,omitempty"` +} + +// RulePatternParameters represents the rule pattern parameters. +type RulePatternParameters struct { + Name *string `json:"name,omitempty"` + // If Negate is true, the rule will fail if the pattern matches. + Negate *bool `json:"negate,omitempty"` + // Possible values for Operator are: starts_with, ends_with, contains, regex + Operator string `json:"operator"` + Pattern string `json:"pattern"` +} + +// RuleFileParameters represents a list of file paths. +type RuleFileParameters struct { + RestrictedFilePaths *[]string `json:"restricted_file_paths"` +} + +// RuleMaxFilePathLengthParameters represents the max_file_path_length rule parameters. +type RuleMaxFilePathLengthParameters struct { + MaxFilePathLength int `json:"max_file_path_length"` +} + +// RuleFileExtensionRestrictionParameters represents the file_extension_restriction rule parameters. +type RuleFileExtensionRestrictionParameters struct { + RestrictedFileExtensions []string `json:"restricted_file_extensions"` +} + +// RuleMaxFileSizeParameters represents the max_file_size rule parameters. +type RuleMaxFileSizeParameters struct { + MaxFileSize int64 `json:"max_file_size"` +} + +// UpdateAllowsFetchAndMergeRuleParameters represents the update rule parameters. +type UpdateAllowsFetchAndMergeRuleParameters struct { + UpdateAllowsFetchAndMerge bool `json:"update_allows_fetch_and_merge"` +} + +// RequiredDeploymentEnvironmentsRuleParameters represents the required_deployments rule parameters. +type RequiredDeploymentEnvironmentsRuleParameters struct { + RequiredDeploymentEnvironments []string `json:"required_deployment_environments"` +} + +// PullRequestRuleParameters represents the pull_request rule parameters. +type PullRequestRuleParameters struct { + DismissStaleReviewsOnPush bool `json:"dismiss_stale_reviews_on_push"` + RequireCodeOwnerReview bool `json:"require_code_owner_review"` + RequireLastPushApproval bool `json:"require_last_push_approval"` + RequiredApprovingReviewCount int `json:"required_approving_review_count"` + RequiredReviewThreadResolution bool `json:"required_review_thread_resolution"` +} + +// RuleRequiredStatusChecks represents the RequiredStatusChecks for the RequiredStatusChecksRuleParameters object. +type RuleRequiredStatusChecks struct { + Context string `json:"context"` + IntegrationID *int64 `json:"integration_id,omitempty"` +} + +// MergeQueueRuleParameters represents the merge_queue rule parameters. +type MergeQueueRuleParameters struct { + CheckResponseTimeoutMinutes int `json:"check_response_timeout_minutes"` + // Possible values for GroupingStrategy are: ALLGREEN, HEADGREEN + GroupingStrategy string `json:"grouping_strategy"` + MaxEntriesToBuild int `json:"max_entries_to_build"` + MaxEntriesToMerge int `json:"max_entries_to_merge"` + // Possible values for MergeMethod are: MERGE, SQUASH, REBASE + MergeMethod string `json:"merge_method"` + MinEntriesToMerge int `json:"min_entries_to_merge"` + MinEntriesToMergeWaitMinutes int `json:"min_entries_to_merge_wait_minutes"` +} + +// RequiredStatusChecksRuleParameters represents the required_status_checks rule parameters. +type RequiredStatusChecksRuleParameters struct { + DoNotEnforceOnCreate *bool `json:"do_not_enforce_on_create,omitempty"` + RequiredStatusChecks []RuleRequiredStatusChecks `json:"required_status_checks"` + StrictRequiredStatusChecksPolicy bool `json:"strict_required_status_checks_policy"` +} + +// RuleRequiredWorkflow represents the Workflow for the RequireWorkflowsRuleParameters object. +type RuleRequiredWorkflow struct { + Path string `json:"path"` + Ref *string `json:"ref,omitempty"` + RepositoryID *int64 `json:"repository_id,omitempty"` + Sha *string `json:"sha,omitempty"` +} + +// RequiredWorkflowsRuleParameters represents the workflows rule parameters. +type RequiredWorkflowsRuleParameters struct { + DoNotEnforceOnCreate bool `json:"do_not_enforce_on_create,omitempty"` + RequiredWorkflows []*RuleRequiredWorkflow `json:"workflows"` +} + +// RuleRequiredCodeScanningTool represents a single required code-scanning tool for the RequiredCodeScanningParameters object. +type RuleRequiredCodeScanningTool struct { + AlertsThreshold string `json:"alerts_threshold"` + SecurityAlertsThreshold string `json:"security_alerts_threshold"` + Tool string `json:"tool"` +} + +// RequiredCodeScanningRuleParameters represents the code_scanning rule parameters. +type RequiredCodeScanningRuleParameters struct { + RequiredCodeScanningTools []*RuleRequiredCodeScanningTool `json:"code_scanning_tools"` +} + +// RepositoryRule represents a GitHub Rule. +type RepositoryRule struct { + Type string `json:"type"` + Parameters *json.RawMessage `json:"parameters,omitempty"` + RulesetSourceType string `json:"ruleset_source_type"` + RulesetSource string `json:"ruleset_source"` + RulesetID int64 `json:"ruleset_id"` +} + +// RepositoryRulesetEditedChanges represents the changes made to a repository ruleset. +type RepositoryRulesetEditedChanges struct { + Name *RepositoryRulesetEditedSource `json:"name,omitempty"` + Enforcement *RepositoryRulesetEditedSource `json:"enforcement,omitempty"` + Conditions *RepositoryRulesetEditedConditions `json:"conditions,omitempty"` + Rules *RepositoryRulesetEditedRules `json:"rules,omitempty"` +} + +// RepositoryRulesetEditedSource represents a source change for the ruleset. +type RepositoryRulesetEditedSource struct { + From *string `json:"from,omitempty"` +} + +// RepositoryRulesetEditedSources represents multiple source changes for the ruleset. +type RepositoryRulesetEditedSources struct { + From []string `json:"from,omitempty"` +} + +// RepositoryRulesetEditedConditions holds changes to conditions in a ruleset. +type RepositoryRulesetEditedConditions struct { + Added []*RepositoryRulesetRefCondition `json:"added,omitempty"` + Deleted []*RepositoryRulesetRefCondition `json:"deleted,omitempty"` + Updated []*RepositoryRulesetEditedUpdatedConditions `json:"updated,omitempty"` +} + +// RepositoryRulesetEditedRules holds changes to rules in a ruleset. +type RepositoryRulesetEditedRules struct { + Added []*RepositoryRulesetRule `json:"added,omitempty"` + Deleted []*RepositoryRulesetRule `json:"deleted,omitempty"` + Updated []*RepositoryRulesetUpdatedRules `json:"updated,omitempty"` +} + +// RepositoryRulesetRefCondition represents a reference condition for the ruleset. +type RepositoryRulesetRefCondition struct { + RefName *RulesetRefConditionParameters `json:"ref_name,omitempty"` +} + +// RepositoryRulesetEditedUpdatedConditions holds updates to conditions in a ruleset. +type RepositoryRulesetEditedUpdatedConditions struct { + Condition *RepositoryRulesetRefCondition `json:"condition,omitempty"` + Changes *RepositoryRulesetUpdatedConditionsEdited `json:"changes,omitempty"` +} + +// RepositoryRulesetUpdatedConditionsEdited holds the edited updates to conditions in a ruleset. +type RepositoryRulesetUpdatedConditionsEdited struct { + ConditionType *RepositoryRulesetEditedSource `json:"condition_type,omitempty"` + Target *RepositoryRulesetEditedSource `json:"target,omitempty"` + Include *RepositoryRulesetEditedSources `json:"include,omitempty"` + Exclude *RepositoryRulesetEditedSources `json:"exclude,omitempty"` +} + +// RepositoryRulesetUpdatedRules holds updates to rules in a ruleset. +type RepositoryRulesetUpdatedRules struct { + Rule *RepositoryRulesetRule `json:"rule,omitempty"` + Changes *RepositoryRulesetEditedRuleChanges `json:"changes,omitempty"` +} + +// RepositoryRulesetEditedRuleChanges holds changes made to a rule in a ruleset. +type RepositoryRulesetEditedRuleChanges struct { + Configuration *RepositoryRulesetEditedSources `json:"configuration,omitempty"` + RuleType *RepositoryRulesetEditedSources `json:"rule_type,omitempty"` + Pattern *RepositoryRulesetEditedSources `json:"pattern,omitempty"` +} + +// RepositoryRuleset represents the structure of a ruleset associated with a GitHub repository. +type RepositoryRuleset struct { + ID int64 `json:"id"` + Name string `json:"name"` + // Possible values for target: "branch", "tag", "push" + Target *string `json:"target,omitempty"` + // Possible values for source type: "Repository", "Organization" + SourceType *string `json:"source_type,omitempty"` + Source string `json:"source"` + // Possible values for enforcement: "disabled", "active", "evaluate" + Enforcement string `json:"enforcement"` + BypassActors []*BypassActor `json:"bypass_actors,omitempty"` + // Possible values for current user can bypass: "always", "pull_requests_only", "never" + CurrentUserCanBypass *string `json:"current_user_can_bypass,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Links *RepositoryRulesetLink `json:"_links,omitempty"` + Conditions json.RawMessage `json:"conditions,omitempty"` + Rules []*RepositoryRulesetRule `json:"rules,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +// RepositoryRulesetRule represents individual rules which are present in a repository's ruleset. +type RepositoryRulesetRule struct { + Creation *RepositoryRulesetRuleType `json:"creation,omitempty"` + Update *RepositoryRulesetUpdateRule `json:"update,omitempty"` + Deletion *RepositoryRulesetRuleType `json:"deletion,omitempty"` + RequiredLinearHistory *RepositoryRulesetRuleType `json:"required_linear_history,omitempty"` + MergeQueue *RepositoryRulesetMergeQueueRule `json:"merge_queue,omitempty"` + RequiredDeployments *RepositoryRulesetRequiredDeploymentsRule `json:"required_deployments,omitempty"` + RequiredSignatures *RepositoryRulesetRuleType `json:"required_signatures,omitempty"` + PullRequest *RepositoryRulesetPullRequestRule `json:"pull_request,omitempty"` + RequiredStatusChecks *RepositoryRulesetRequiredStatusChecksRule `json:"required_status_checks,omitempty"` + NonFastForward *RepositoryRulesetRuleType `json:"non_fast_forward,omitempty"` + CommitMessagePattern *RepositoryRulesetPatternRule `json:"commit_message_pattern,omitempty"` + CommitAuthorEmailPattern *RepositoryRulesetPatternRule `json:"commit_author_email_pattern,omitempty"` + CommitterEmailPattern *RepositoryRulesetPatternRule `json:"committer_email_pattern,omitempty"` + BranchNamePattern *RepositoryRulesetPatternRule `json:"branch_name_pattern,omitempty"` + TagNamePattern *RepositoryRulesetPatternRule `json:"tag_name_pattern,omitempty"` + FilePathRestriction *RepositoryRulesetFilePathRestrictionRule `json:"file_path_restriction,omitempty"` + MaxFilePathLength *RepositoryRulesetMaxFilePathLengthRule `json:"max_file_path_length,omitempty"` + FileExtensionRestriction *RepositoryRulesetFileExtensionRestrictionRule `json:"file_extension_restriction,omitempty"` + MaxFileSize *RepositoryRulesetMaxFileSizeRule `json:"max_file_size,omitempty"` + Workflows *RepositoryRulesetWorkflowsRule `json:"workflows,omitempty"` + CodeScanning *RepositoryRulesetCodeScanningRule `json:"code_scanning,omitempty"` +} + +// RepositoryRulesetLink represents Links associated with a repository's rulesets. These links are used to provide more information about the ruleset. +type RepositoryRulesetLink struct { + Self *RulesetLink `json:"self,omitempty"` + HTML *RulesetLink `json:"html,omitempty"` +} + +// RepositoryRulesetRuleType represents the type of a ruleset rule. +type RepositoryRulesetRuleType struct { + Type string `json:"type"` +} + +// RepositoryRulesetUpdateRule defines an update rule for the repository. +type RepositoryRulesetUpdateRule struct { + // Type can be one of: "update". + Type string `json:"type"` + Parameters *UpdateAllowsFetchAndMergeRuleParameters `json:"parameters,omitempty"` +} + +// RepositoryRulesetMergeQueueRule defines a merge queue rule for the repository. +type RepositoryRulesetMergeQueueRule struct { + // Type can be one of: "merge_queue". + Type string `json:"type"` + Parameters *MergeQueueRuleParameters `json:"parameters,omitempty"` +} + +// RepositoryRulesetRequiredDeploymentsRule defines a rule for required deployments. +type RepositoryRulesetRequiredDeploymentsRule struct { + // Type can be one of: "required_deployments". + Type string `json:"type"` + Parameters *RequiredDeploymentEnvironmentsRuleParameters `json:"parameters,omitempty"` +} + +// RepositoryRulesetPullRequestRule defines a rule for pull requests. +type RepositoryRulesetPullRequestRule struct { + // Type can be one of: "pull_request". + + Type string `json:"type"` + Parameters *PullRequestRuleParameters `json:"parameters,omitempty"` +} + +// RepositoryRulesetRequiredStatusChecksRule defines a rule for required status checks. +type RepositoryRulesetRequiredStatusChecksRule struct { + // Type can be one of: "required_status_checks". + + Type string `json:"type"` + Parameters *RequiredStatusChecksRuleParameters `json:"parameters,omitempty"` +} + +// RepositoryRulesetPatternRule defines a pattern rule for the repository. +type RepositoryRulesetPatternRule struct { + Type string `json:"type"` + Parameters *RulePatternParameters `json:"parameters,omitempty"` +} + +// RepositoryRulesetFilePathRestrictionRule defines a file path restriction rule for the repository. +type RepositoryRulesetFilePathRestrictionRule struct { + // Type can be one of: "file_path_restriction". + Type string `json:"type"` + Parameters *RuleFileParameters `json:"parameters,omitempty"` +} + +// RepositoryRulesetMaxFilePathLengthRule defines a maximum file path length rule for the repository. +type RepositoryRulesetMaxFilePathLengthRule struct { + // Type can be one of: "max_file_path_length". + + Type string `json:"type"` + Parameters *RuleMaxFilePathLengthParameters `json:"parameters,omitempty"` +} + +// RepositoryRulesetFileExtensionRestrictionRule defines a file extension restriction rule for the repository. +type RepositoryRulesetFileExtensionRestrictionRule struct { + // Type can be one of: "file_extension_restriction". + Type string `json:"type"` + Parameters *RuleFileExtensionRestrictionParameters `json:"parameters,omitempty"` +} + +// RepositoryRulesetMaxFileSizeRule defines a maximum file size rule for the repository. +type RepositoryRulesetMaxFileSizeRule struct { + // Type can be one of: "max_file_size". + Type string `json:"type"` + Parameters *RuleMaxFileSizeParameters `json:"parameters,omitempty"` +} + +// RepositoryRulesetWorkflowsRule defines a workflow rule for the repository. +type RepositoryRulesetWorkflowsRule struct { + // Type can be one of: "workflows". + Type string `json:"type"` + Parameters *RequiredWorkflowsRuleParameters `json:"parameters,omitempty"` +} + +// RepositoryRulesetCodeScanningRule defines a code scanning rule for the repository. +type RepositoryRulesetCodeScanningRule struct { + // Type can be one of: "code_scanning". + Type string `json:"type"` + Parameters *RuleCodeScanningParameters `json:"parameters,omitempty"` +} + +// RuleCodeScanningParameters defines parameters for code scanning rules. +type RuleCodeScanningParameters struct { + CodeScanningTools []*CodeScanningTool `json:"code_scanning_tools,omitempty"` +} + +// CodeScanningTool defines a specific tool used for code scanning. +type CodeScanningTool struct { + AlertsThreshold string `json:"alerts_threshold"` + SecurityAlertsThreshold string `json:"security_alerts_threshold"` + Tool string `json:"tool"` +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +// This helps us handle the fact that RepositoryRule parameter field can be of numerous types. +func (r *RepositoryRule) UnmarshalJSON(data []byte) error { + type rule RepositoryRule + var repositoryRule rule + if err := json.Unmarshal(data, &repositoryRule); err != nil { + return err + } + + r.RulesetID = repositoryRule.RulesetID + r.RulesetSourceType = repositoryRule.RulesetSourceType + r.RulesetSource = repositoryRule.RulesetSource + r.Type = repositoryRule.Type + + switch repositoryRule.Type { + case "creation", "deletion", "non_fast_forward", "required_linear_history", "required_signatures": + r.Parameters = nil + case "update": + if repositoryRule.Parameters == nil { + r.Parameters = nil + return nil + } + params := UpdateAllowsFetchAndMergeRuleParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + case "merge_queue": + if repositoryRule.Parameters == nil { + r.Parameters = nil + return nil + } + params := MergeQueueRuleParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + case "required_deployments": + params := RequiredDeploymentEnvironmentsRuleParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + case "commit_message_pattern", "commit_author_email_pattern", "committer_email_pattern", "branch_name_pattern", "tag_name_pattern": + params := RulePatternParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + case "pull_request": + params := PullRequestRuleParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + case "required_status_checks": + params := RequiredStatusChecksRuleParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + case "workflows": + params := RequiredWorkflowsRuleParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + case "file_path_restriction": + params := RuleFileParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + case "code_scanning": + params := RequiredCodeScanningRuleParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + case "max_file_path_length": + params := RuleMaxFilePathLengthParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + case "file_extension_restriction": + params := RuleFileExtensionRestrictionParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + case "max_file_size": + params := RuleMaxFileSizeParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + default: + r.Type = "" + r.Parameters = nil + return fmt.Errorf("RepositoryRule.Type %q is not yet implemented, unable to unmarshal (%#v)", repositoryRule.Type, repositoryRule) + } + + return nil +} + +// NewMergeQueueRule creates a rule to only allow merges via a merge queue. +func NewMergeQueueRule(params *MergeQueueRuleParameters) (rule *RepositoryRule) { + if params != nil { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "merge_queue", + Parameters: &rawParams, + } + } + return &RepositoryRule{ + Type: "merge_queue", + } +} + +// NewCreationRule creates a rule to only allow users with bypass permission to create matching refs. +func NewCreationRule() (rule *RepositoryRule) { + return &RepositoryRule{ + Type: "creation", + } +} + +// NewUpdateRule creates a rule to only allow users with bypass permission to update matching refs. +func NewUpdateRule(params *UpdateAllowsFetchAndMergeRuleParameters) (rule *RepositoryRule) { + if params != nil { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "update", + Parameters: &rawParams, + } + } + return &RepositoryRule{ + Type: "update", + } +} + +// NewDeletionRule creates a rule to only allow users with bypass permissions to delete matching refs. +func NewDeletionRule() (rule *RepositoryRule) { + return &RepositoryRule{ + Type: "deletion", + } +} + +// NewRequiredLinearHistoryRule creates a rule to prevent merge commits from being pushed to matching branches. +func NewRequiredLinearHistoryRule() (rule *RepositoryRule) { + return &RepositoryRule{ + Type: "required_linear_history", + } +} + +// NewRequiredDeploymentsRule creates a rule to require environments to be successfully deployed before they can be merged into the matching branches. +func NewRequiredDeploymentsRule(params *RequiredDeploymentEnvironmentsRuleParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "required_deployments", + Parameters: &rawParams, + } +} + +// NewRequiredSignaturesRule creates a rule a to require commits pushed to matching branches to have verified signatures. +func NewRequiredSignaturesRule() (rule *RepositoryRule) { + return &RepositoryRule{ + Type: "required_signatures", + } +} + +// NewPullRequestRule creates a rule to require all commits be made to a non-target branch and submitted via a pull request before they can be merged. +func NewPullRequestRule(params *PullRequestRuleParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "pull_request", + Parameters: &rawParams, + } +} + +// NewRequiredStatusChecksRule creates a rule to require which status checks must pass before branches can be merged into a branch rule. +func NewRequiredStatusChecksRule(params *RequiredStatusChecksRuleParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "required_status_checks", + Parameters: &rawParams, + } +} + +// NewNonFastForwardRule creates a rule as part to prevent users with push access from force pushing to matching branches. +func NewNonFastForwardRule() (rule *RepositoryRule) { + return &RepositoryRule{ + Type: "non_fast_forward", + } +} + +// NewCommitMessagePatternRule creates a rule to restrict commit message patterns being pushed to matching branches. +func NewCommitMessagePatternRule(params *RulePatternParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "commit_message_pattern", + Parameters: &rawParams, + } +} + +// NewCommitAuthorEmailPatternRule creates a rule to restrict commits with author email patterns being merged into matching branches. +func NewCommitAuthorEmailPatternRule(params *RulePatternParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "commit_author_email_pattern", + Parameters: &rawParams, + } +} + +// NewCommitterEmailPatternRule creates a rule to restrict commits with committer email patterns being merged into matching branches. +func NewCommitterEmailPatternRule(params *RulePatternParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "committer_email_pattern", + Parameters: &rawParams, + } +} + +// NewBranchNamePatternRule creates a rule to restrict branch patterns from being merged into matching branches. +func NewBranchNamePatternRule(params *RulePatternParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "branch_name_pattern", + Parameters: &rawParams, + } +} + +// NewTagNamePatternRule creates a rule to restrict tag patterns contained in non-target branches from being merged into matching branches. +func NewTagNamePatternRule(params *RulePatternParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "tag_name_pattern", + Parameters: &rawParams, + } +} + +// NewRequiredWorkflowsRule creates a rule to require which status checks must pass before branches can be merged into a branch rule. +func NewRequiredWorkflowsRule(params *RequiredWorkflowsRuleParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "workflows", + Parameters: &rawParams, + } +} + +// NewRequiredCodeScanningRule creates a rule to require which tools must provide code scanning results before the reference is updated. +func NewRequiredCodeScanningRule(params *RequiredCodeScanningRuleParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "code_scanning", + Parameters: &rawParams, + } +} + +// NewFilePathRestrictionRule creates a rule to restrict file paths from being pushed to. +func NewFilePathRestrictionRule(params *RuleFileParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "file_path_restriction", + Parameters: &rawParams, + } +} + +// NewMaxFilePathLengthRule creates a rule to restrict file paths longer than the limit from being pushed. +func NewMaxFilePathLengthRule(params *RuleMaxFilePathLengthParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "max_file_path_length", + Parameters: &rawParams, + } +} + +// NewFileExtensionRestrictionRule creates a rule to restrict file extensions from being pushed to a commit. +func NewFileExtensionRestrictionRule(params *RuleFileExtensionRestrictionParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "file_extension_restriction", + Parameters: &rawParams, + } +} + +// NewMaxFileSizeRule creates a rule to restrict file sizes from being pushed to a commit. +func NewMaxFileSizeRule(params *RuleMaxFileSizeParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "max_file_size", + Parameters: &rawParams, + } +} + +// Ruleset represents a GitHub ruleset object. +type Ruleset struct { + ID *int64 `json:"id,omitempty"` + Name string `json:"name"` + // Possible values for Target are branch, tag, push + Target *string `json:"target,omitempty"` + // Possible values for SourceType are: Repository, Organization + SourceType *string `json:"source_type,omitempty"` + Source string `json:"source"` + // Possible values for Enforcement are: disabled, active, evaluate + Enforcement string `json:"enforcement"` + BypassActors []*BypassActor `json:"bypass_actors,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Links *RulesetLinks `json:"_links,omitempty"` + Conditions *RulesetConditions `json:"conditions,omitempty"` + Rules []*RepositoryRule `json:"rules,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` +} + +// rulesetNoOmitBypassActors represents a GitHub ruleset object. The struct does not omit bypassActors if the field is nil or an empty array is passed. +type rulesetNoOmitBypassActors struct { + ID *int64 `json:"id,omitempty"` + Name string `json:"name"` + // Possible values for Target are branch, tag + Target *string `json:"target,omitempty"` + // Possible values for SourceType are: Repository, Organization + SourceType *string `json:"source_type,omitempty"` + Source string `json:"source"` + // Possible values for Enforcement are: disabled, active, evaluate + Enforcement string `json:"enforcement"` + BypassActors []*BypassActor `json:"bypass_actors"` + NodeID *string `json:"node_id,omitempty"` + Links *RulesetLinks `json:"_links,omitempty"` + Conditions *RulesetConditions `json:"conditions,omitempty"` + Rules []*RepositoryRule `json:"rules,omitempty"` +} + +// GetRulesForBranch gets all the rules that apply to the specified branch. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#get-rules-for-a-branch +// +//meta:operation GET /repos/{owner}/{repo}/rules/branches/{branch} +func (s *RepositoriesService) GetRulesForBranch(ctx context.Context, owner, repo, branch string) ([]*RepositoryRule, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/rules/branches/%v", owner, repo, branch) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var rules []*RepositoryRule + resp, err := s.client.Do(ctx, req, &rules) + if err != nil { + return nil, resp, err + } + + return rules, resp, nil +} + +// GetAllRulesets gets all the rules that apply to the specified repository. +// If includesParents is true, rulesets configured at the organization level that apply to the repository will be returned. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#get-all-repository-rulesets +// +//meta:operation GET /repos/{owner}/{repo}/rulesets +func (s *RepositoriesService) GetAllRulesets(ctx context.Context, owner, repo string, includesParents bool) ([]*Ruleset, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/rulesets?includes_parents=%v", owner, repo, includesParents) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var ruleset []*Ruleset + resp, err := s.client.Do(ctx, req, &ruleset) + if err != nil { + return nil, resp, err + } + + return ruleset, resp, nil +} + +// CreateRuleset creates a ruleset for the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#create-a-repository-ruleset +// +//meta:operation POST /repos/{owner}/{repo}/rulesets +func (s *RepositoriesService) CreateRuleset(ctx context.Context, owner, repo string, rs *Ruleset) (*Ruleset, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/rulesets", owner, repo) + + req, err := s.client.NewRequest("POST", u, rs) + if err != nil { + return nil, nil, err + } + + var ruleset *Ruleset + resp, err := s.client.Do(ctx, req, &ruleset) + if err != nil { + return nil, resp, err + } + + return ruleset, resp, nil +} + +// GetRuleset gets a ruleset for the specified repository. +// If includesParents is true, rulesets configured at the organization level that apply to the repository will be returned. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#get-a-repository-ruleset +// +//meta:operation GET /repos/{owner}/{repo}/rulesets/{ruleset_id} +func (s *RepositoriesService) GetRuleset(ctx context.Context, owner, repo string, rulesetID int64, includesParents bool) (*Ruleset, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/rulesets/%v?includes_parents=%v", owner, repo, rulesetID, includesParents) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var ruleset *Ruleset + resp, err := s.client.Do(ctx, req, &ruleset) + if err != nil { + return nil, resp, err + } + + return ruleset, resp, nil +} + +// UpdateRuleset updates a ruleset for the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#update-a-repository-ruleset +// +//meta:operation PUT /repos/{owner}/{repo}/rulesets/{ruleset_id} +func (s *RepositoriesService) UpdateRuleset(ctx context.Context, owner, repo string, rulesetID int64, rs *Ruleset) (*Ruleset, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/rulesets/%v", owner, repo, rulesetID) + + req, err := s.client.NewRequest("PUT", u, rs) + if err != nil { + return nil, nil, err + } + + var ruleset *Ruleset + resp, err := s.client.Do(ctx, req, &ruleset) + if err != nil { + return nil, resp, err + } + + return ruleset, resp, nil +} + +// UpdateRulesetNoBypassActor updates a ruleset for the specified repository. +// +// This function is necessary as the UpdateRuleset function does not marshal ByPassActor if passed as nil or an empty array. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#update-a-repository-ruleset +// +//meta:operation PUT /repos/{owner}/{repo}/rulesets/{ruleset_id} +func (s *RepositoriesService) UpdateRulesetNoBypassActor(ctx context.Context, owner, repo string, rulesetID int64, rs *Ruleset) (*Ruleset, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/rulesets/%v", owner, repo, rulesetID) + + rsNoBypassActor := &rulesetNoOmitBypassActors{} + + if rs != nil { + rsNoBypassActor = &rulesetNoOmitBypassActors{ + ID: rs.ID, + Name: rs.Name, + Target: rs.Target, + SourceType: rs.SourceType, + Source: rs.Source, + Enforcement: rs.Enforcement, + BypassActors: rs.BypassActors, + NodeID: rs.NodeID, + Links: rs.Links, + Conditions: rs.Conditions, + Rules: rs.Rules, + } + } + + req, err := s.client.NewRequest("PUT", u, rsNoBypassActor) + if err != nil { + return nil, nil, err + } + + var ruleSet *Ruleset + resp, err := s.client.Do(ctx, req, &ruleSet) + if err != nil { + return nil, resp, err + } + + return ruleSet, resp, nil +} + +// DeleteRuleset deletes a ruleset for the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#delete-a-repository-ruleset +// +//meta:operation DELETE /repos/{owner}/{repo}/rulesets/{ruleset_id} +func (s *RepositoriesService) DeleteRuleset(ctx context.Context, owner, repo string, rulesetID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/rulesets/%v", owner, repo, rulesetID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_stats.go b/vendor/github.com/google/go-github/v68/github/repos_stats.go new file mode 100644 index 0000000000..a6ef9c0da4 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_stats.go @@ -0,0 +1,242 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// ContributorStats represents a contributor to a repository and their +// weekly contributions to a given repo. +type ContributorStats struct { + Author *Contributor `json:"author,omitempty"` + Total *int `json:"total,omitempty"` + Weeks []*WeeklyStats `json:"weeks,omitempty"` +} + +func (c ContributorStats) String() string { + return Stringify(c) +} + +// WeeklyStats represents the number of additions, deletions and commits +// a Contributor made in a given week. +type WeeklyStats struct { + Week *Timestamp `json:"w,omitempty"` + Additions *int `json:"a,omitempty"` + Deletions *int `json:"d,omitempty"` + Commits *int `json:"c,omitempty"` +} + +func (w WeeklyStats) String() string { + return Stringify(w) +} + +// ListContributorsStats gets a repo's contributor list with additions, +// deletions and commit counts. +// +// If this is the first time these statistics are requested for the given +// repository, this method will return an *AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it is now computing the requested statistics. A follow up request, after a +// delay of a second or so, should result in a successful request. +// +// GitHub API docs: https://docs.github.com/rest/metrics/statistics#get-all-contributor-commit-activity +// +//meta:operation GET /repos/{owner}/{repo}/stats/contributors +func (s *RepositoriesService) ListContributorsStats(ctx context.Context, owner, repo string) ([]*ContributorStats, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/stats/contributors", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var contributorStats []*ContributorStats + resp, err := s.client.Do(ctx, req, &contributorStats) + if err != nil { + return nil, resp, err + } + + return contributorStats, resp, nil +} + +// WeeklyCommitActivity represents the weekly commit activity for a repository. +// The days array is a group of commits per day, starting on Sunday. +type WeeklyCommitActivity struct { + Days []int `json:"days,omitempty"` + Total *int `json:"total,omitempty"` + Week *Timestamp `json:"week,omitempty"` +} + +func (w WeeklyCommitActivity) String() string { + return Stringify(w) +} + +// ListCommitActivity returns the last year of commit activity +// grouped by week. The days array is a group of commits per day, +// starting on Sunday. +// +// If this is the first time these statistics are requested for the given +// repository, this method will return an *AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it is now computing the requested statistics. A follow up request, after a +// delay of a second or so, should result in a successful request. +// +// GitHub API docs: https://docs.github.com/rest/metrics/statistics#get-the-last-year-of-commit-activity +// +//meta:operation GET /repos/{owner}/{repo}/stats/commit_activity +func (s *RepositoriesService) ListCommitActivity(ctx context.Context, owner, repo string) ([]*WeeklyCommitActivity, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/stats/commit_activity", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var weeklyCommitActivity []*WeeklyCommitActivity + resp, err := s.client.Do(ctx, req, &weeklyCommitActivity) + if err != nil { + return nil, resp, err + } + + return weeklyCommitActivity, resp, nil +} + +// ListCodeFrequency returns a weekly aggregate of the number of additions and +// deletions pushed to a repository. Returned WeeklyStats will contain +// additions and deletions, but not total commits. +// +// If this is the first time these statistics are requested for the given +// repository, this method will return an *AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it is now computing the requested statistics. A follow up request, after a +// delay of a second or so, should result in a successful request. +// +// GitHub API docs: https://docs.github.com/rest/metrics/statistics#get-the-weekly-commit-activity +// +//meta:operation GET /repos/{owner}/{repo}/stats/code_frequency +func (s *RepositoriesService) ListCodeFrequency(ctx context.Context, owner, repo string) ([]*WeeklyStats, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/stats/code_frequency", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var weeks [][]int + resp, err := s.client.Do(ctx, req, &weeks) + if err != nil { + return nil, resp, err + } + + // convert int slices into WeeklyStats + var stats []*WeeklyStats + for _, week := range weeks { + if len(week) != 3 { + continue + } + stat := &WeeklyStats{ + Week: &Timestamp{time.Unix(int64(week[0]), 0)}, + Additions: Ptr(week[1]), + Deletions: Ptr(week[2]), + } + stats = append(stats, stat) + } + + return stats, resp, nil +} + +// RepositoryParticipation is the number of commits by everyone +// who has contributed to the repository (including the owner) +// as well as the number of commits by the owner themself. +type RepositoryParticipation struct { + All []int `json:"all,omitempty"` + Owner []int `json:"owner,omitempty"` +} + +func (r RepositoryParticipation) String() string { + return Stringify(r) +} + +// ListParticipation returns the total commit counts for the 'owner' +// and total commit counts in 'all'. 'all' is everyone combined, +// including the 'owner' in the last 52 weeks. If you’d like to get +// the commit counts for non-owners, you can subtract 'all' from 'owner'. +// +// The array order is oldest week (index 0) to most recent week. +// +// If this is the first time these statistics are requested for the given +// repository, this method will return an *AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it is now computing the requested statistics. A follow up request, after a +// delay of a second or so, should result in a successful request. +// +// GitHub API docs: https://docs.github.com/rest/metrics/statistics#get-the-weekly-commit-count +// +//meta:operation GET /repos/{owner}/{repo}/stats/participation +func (s *RepositoriesService) ListParticipation(ctx context.Context, owner, repo string) (*RepositoryParticipation, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/stats/participation", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + participation := new(RepositoryParticipation) + resp, err := s.client.Do(ctx, req, participation) + if err != nil { + return nil, resp, err + } + + return participation, resp, nil +} + +// PunchCard represents the number of commits made during a given hour of a +// day of the week. +type PunchCard struct { + Day *int // Day of the week (0-6: =Sunday - Saturday). + Hour *int // Hour of day (0-23). + Commits *int // Number of commits. +} + +// ListPunchCard returns the number of commits per hour in each day. +// +// If this is the first time these statistics are requested for the given +// repository, this method will return an *AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it is now computing the requested statistics. A follow up request, after a +// delay of a second or so, should result in a successful request. +// +// GitHub API docs: https://docs.github.com/rest/metrics/statistics#get-the-hourly-commit-count-for-each-day +// +//meta:operation GET /repos/{owner}/{repo}/stats/punch_card +func (s *RepositoriesService) ListPunchCard(ctx context.Context, owner, repo string) ([]*PunchCard, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/stats/punch_card", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var results [][]int + resp, err := s.client.Do(ctx, req, &results) + if err != nil { + return nil, resp, err + } + + // convert int slices into Punchcards + var cards []*PunchCard + for _, result := range results { + if len(result) != 3 { + continue + } + card := &PunchCard{ + Day: Ptr(result[0]), + Hour: Ptr(result[1]), + Commits: Ptr(result[2]), + } + cards = append(cards, card) + } + + return cards, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_statuses.go b/vendor/github.com/google/go-github/v68/github/repos_statuses.go new file mode 100644 index 0000000000..e7b0304752 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_statuses.go @@ -0,0 +1,138 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// RepoStatus represents the status of a repository at a particular reference. +type RepoStatus struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + URL *string `json:"url,omitempty"` + + // State is the current state of the repository. Possible values are: + // pending, success, error, or failure. + State *string `json:"state,omitempty"` + + // TargetURL is the URL of the page representing this status. It will be + // linked from the GitHub UI to allow users to see the source of the status. + TargetURL *string `json:"target_url,omitempty"` + + // Description is a short high level summary of the status. + Description *string `json:"description,omitempty"` + + // A string label to differentiate this status from the statuses of other systems. + Context *string `json:"context,omitempty"` + + // AvatarURL is the URL of the avatar of this status. + AvatarURL *string `json:"avatar_url,omitempty"` + + Creator *User `json:"creator,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +func (r RepoStatus) String() string { + return Stringify(r) +} + +// ListStatuses lists the statuses of a repository at the specified +// reference. ref can be a SHA, a branch name, or a tag name. +// +// GitHub API docs: https://docs.github.com/rest/commits/statuses#list-commit-statuses-for-a-reference +// +//meta:operation GET /repos/{owner}/{repo}/commits/{ref}/statuses +func (s *RepositoriesService) ListStatuses(ctx context.Context, owner, repo, ref string, opts *ListOptions) ([]*RepoStatus, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/statuses", owner, repo, refURLEscape(ref)) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var statuses []*RepoStatus + resp, err := s.client.Do(ctx, req, &statuses) + if err != nil { + return nil, resp, err + } + + return statuses, resp, nil +} + +// CreateStatus creates a new status for a repository at the specified +// reference. Ref can be a SHA, a branch name, or a tag name. +// +// GitHub API docs: https://docs.github.com/rest/commits/statuses#create-a-commit-status +// +//meta:operation POST /repos/{owner}/{repo}/statuses/{sha} +func (s *RepositoriesService) CreateStatus(ctx context.Context, owner, repo, ref string, status *RepoStatus) (*RepoStatus, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/statuses/%v", owner, repo, refURLEscape(ref)) + req, err := s.client.NewRequest("POST", u, status) + if err != nil { + return nil, nil, err + } + + repoStatus := new(RepoStatus) + resp, err := s.client.Do(ctx, req, repoStatus) + if err != nil { + return nil, resp, err + } + + return repoStatus, resp, nil +} + +// CombinedStatus represents the combined status of a repository at a particular reference. +type CombinedStatus struct { + // State is the combined state of the repository. Possible values are: + // failure, pending, or success. + State *string `json:"state,omitempty"` + + Name *string `json:"name,omitempty"` + SHA *string `json:"sha,omitempty"` + TotalCount *int `json:"total_count,omitempty"` + Statuses []*RepoStatus `json:"statuses,omitempty"` + + CommitURL *string `json:"commit_url,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` +} + +func (s CombinedStatus) String() string { + return Stringify(s) +} + +// GetCombinedStatus returns the combined status of a repository at the specified +// reference. ref can be a SHA, a branch name, or a tag name. +// +// GitHub API docs: https://docs.github.com/rest/commits/statuses#get-the-combined-status-for-a-specific-reference +// +//meta:operation GET /repos/{owner}/{repo}/commits/{ref}/status +func (s *RepositoriesService) GetCombinedStatus(ctx context.Context, owner, repo, ref string, opts *ListOptions) (*CombinedStatus, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/status", owner, repo, refURLEscape(ref)) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + status := new(CombinedStatus) + resp, err := s.client.Do(ctx, req, status) + if err != nil { + return nil, resp, err + } + + return status, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_tags.go b/vendor/github.com/google/go-github/v68/github/repos_tags.go new file mode 100644 index 0000000000..b6dc36e2a3 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_tags.go @@ -0,0 +1,85 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// TagProtection represents a repository tag protection. +type TagProtection struct { + ID *int64 `json:"id"` + Pattern *string `json:"pattern"` +} + +// tagProtectionRequest represents a request to create tag protection. +type tagProtectionRequest struct { + // An optional glob pattern to match against when enforcing tag protection. + Pattern string `json:"pattern"` +} + +// Deprecated: ListTagProtection lists tag protection of the specified repository. +// Deprecation notice: This operation is deprecated and will be removed after August 30, 2024. Use the "Repository Rulesets" endpoint instead: https://docs.github.com/rest/repos/rules#get-all-repository-rulesets +// +// GitHub API docs: https://docs.github.com/rest/repos/tags#closing-down---list-tag-protection-states-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/tags/protection +func (s *RepositoriesService) ListTagProtection(ctx context.Context, owner, repo string) ([]*TagProtection, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/tags/protection", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var tagProtections []*TagProtection + resp, err := s.client.Do(ctx, req, &tagProtections) + if err != nil { + return nil, resp, err + } + + return tagProtections, resp, nil +} + +// Deprecated: CreateTagProtection creates the tag protection of the specified repository. +// Deprecation notice: This operation is deprecated and will be removed after August 30, 2024. Use the "Repository Rulesets" endpoint instead: https://docs.github.com/rest/repos/rules#create-a-repository-ruleset +// +// GitHub API docs: https://docs.github.com/rest/repos/tags#closing-down---create-a-tag-protection-state-for-a-repository +// +//meta:operation POST /repos/{owner}/{repo}/tags/protection +func (s *RepositoriesService) CreateTagProtection(ctx context.Context, owner, repo, pattern string) (*TagProtection, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/tags/protection", owner, repo) + r := &tagProtectionRequest{Pattern: pattern} + req, err := s.client.NewRequest("POST", u, r) + if err != nil { + return nil, nil, err + } + + tagProtection := new(TagProtection) + resp, err := s.client.Do(ctx, req, tagProtection) + if err != nil { + return nil, resp, err + } + + return tagProtection, resp, nil +} + +// Deprecated: DeleteTagProtection deletes a tag protection from the specified repository. +// Deprecation notice: This operation is deprecated and will be removed after August 30, 2024. Use the "Repository Rulesets" endpoint instead: https://docs.github.com/rest/repos/rules#delete-a-repository-ruleset +// +// GitHub API docs: https://docs.github.com/rest/repos/tags#closing-down---delete-a-tag-protection-state-for-a-repository +// +//meta:operation DELETE /repos/{owner}/{repo}/tags/protection/{tag_protection_id} +func (s *RepositoriesService) DeleteTagProtection(ctx context.Context, owner, repo string, tagProtectionID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/tags/protection/%v", owner, repo, tagProtectionID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_traffic.go b/vendor/github.com/google/go-github/v68/github/repos_traffic.go new file mode 100644 index 0000000000..ae2f1a86bd --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_traffic.go @@ -0,0 +1,149 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// TrafficReferrer represent information about traffic from a referrer . +type TrafficReferrer struct { + Referrer *string `json:"referrer,omitempty"` + Count *int `json:"count,omitempty"` + Uniques *int `json:"uniques,omitempty"` +} + +// TrafficPath represent information about the traffic on a path of the repo. +type TrafficPath struct { + Path *string `json:"path,omitempty"` + Title *string `json:"title,omitempty"` + Count *int `json:"count,omitempty"` + Uniques *int `json:"uniques,omitempty"` +} + +// TrafficData represent information about a specific timestamp in views or clones list. +type TrafficData struct { + Timestamp *Timestamp `json:"timestamp,omitempty"` + Count *int `json:"count,omitempty"` + Uniques *int `json:"uniques,omitempty"` +} + +// TrafficViews represent information about the number of views in the last 14 days. +type TrafficViews struct { + Views []*TrafficData `json:"views,omitempty"` + Count *int `json:"count,omitempty"` + Uniques *int `json:"uniques,omitempty"` +} + +// TrafficClones represent information about the number of clones in the last 14 days. +type TrafficClones struct { + Clones []*TrafficData `json:"clones,omitempty"` + Count *int `json:"count,omitempty"` + Uniques *int `json:"uniques,omitempty"` +} + +// TrafficBreakdownOptions specifies the parameters to methods that support breakdown per day or week. +// Can be one of: day, week. Default: day. +type TrafficBreakdownOptions struct { + Per string `url:"per,omitempty"` +} + +// ListTrafficReferrers list the top 10 referrers over the last 14 days. +// +// GitHub API docs: https://docs.github.com/rest/metrics/traffic#get-top-referral-sources +// +//meta:operation GET /repos/{owner}/{repo}/traffic/popular/referrers +func (s *RepositoriesService) ListTrafficReferrers(ctx context.Context, owner, repo string) ([]*TrafficReferrer, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/traffic/popular/referrers", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var trafficReferrers []*TrafficReferrer + resp, err := s.client.Do(ctx, req, &trafficReferrers) + if err != nil { + return nil, resp, err + } + + return trafficReferrers, resp, nil +} + +// ListTrafficPaths list the top 10 popular content over the last 14 days. +// +// GitHub API docs: https://docs.github.com/rest/metrics/traffic#get-top-referral-paths +// +//meta:operation GET /repos/{owner}/{repo}/traffic/popular/paths +func (s *RepositoriesService) ListTrafficPaths(ctx context.Context, owner, repo string) ([]*TrafficPath, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/traffic/popular/paths", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var paths []*TrafficPath + resp, err := s.client.Do(ctx, req, &paths) + if err != nil { + return nil, resp, err + } + + return paths, resp, nil +} + +// ListTrafficViews get total number of views for the last 14 days and breaks it down either per day or week. +// +// GitHub API docs: https://docs.github.com/rest/metrics/traffic#get-page-views +// +//meta:operation GET /repos/{owner}/{repo}/traffic/views +func (s *RepositoriesService) ListTrafficViews(ctx context.Context, owner, repo string, opts *TrafficBreakdownOptions) (*TrafficViews, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/traffic/views", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + trafficViews := new(TrafficViews) + resp, err := s.client.Do(ctx, req, &trafficViews) + if err != nil { + return nil, resp, err + } + + return trafficViews, resp, nil +} + +// ListTrafficClones get total number of clones for the last 14 days and breaks it down either per day or week for the last 14 days. +// +// GitHub API docs: https://docs.github.com/rest/metrics/traffic#get-repository-clones +// +//meta:operation GET /repos/{owner}/{repo}/traffic/clones +func (s *RepositoriesService) ListTrafficClones(ctx context.Context, owner, repo string, opts *TrafficBreakdownOptions) (*TrafficClones, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/traffic/clones", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + trafficClones := new(TrafficClones) + resp, err := s.client.Do(ctx, req, &trafficClones) + if err != nil { + return nil, resp, err + } + + return trafficClones, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/scim.go b/vendor/github.com/google/go-github/v68/github/scim.go new file mode 100644 index 0000000000..4b34c1663c --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/scim.go @@ -0,0 +1,219 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" +) + +// SCIMService provides access to SCIM related functions in the +// GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/scim +type SCIMService service + +// SCIMUserAttributes represents supported SCIM User attributes. +// +// GitHub API docs: https://docs.github.com/rest/scim#supported-scim-user-attributes +type SCIMUserAttributes struct { + UserName string `json:"userName"` // Configured by the admin. Could be an email, login, or username. (Required.) + Name SCIMUserName `json:"name"` // (Required.) + DisplayName *string `json:"displayName,omitempty"` // The name of the user, suitable for display to end-users. (Optional.) + Emails []*SCIMUserEmail `json:"emails"` // User emails. (Required.) + Schemas []string `json:"schemas,omitempty"` // (Optional.) + ExternalID *string `json:"externalId,omitempty"` // (Optional.) + Groups []string `json:"groups,omitempty"` // (Optional.) + Active *bool `json:"active,omitempty"` // (Optional.) + // Only populated as a result of calling ListSCIMProvisionedIdentitiesOptions or GetSCIMProvisioningInfoForUser: + ID *string `json:"id,omitempty"` + Meta *SCIMMeta `json:"meta,omitempty"` +} + +// SCIMUserName represents SCIM user information. +type SCIMUserName struct { + GivenName string `json:"givenName"` // The first name of the user. (Required.) + FamilyName string `json:"familyName"` // The family name of the user. (Required.) + Formatted *string `json:"formatted,omitempty"` // (Optional.) +} + +// SCIMUserEmail represents SCIM user email. +type SCIMUserEmail struct { + Value string `json:"value"` // (Required.) + Primary *bool `json:"primary,omitempty"` // (Optional.) + Type *string `json:"type,omitempty"` // (Optional.) +} + +// SCIMMeta represents metadata about the SCIM resource. +type SCIMMeta struct { + ResourceType *string `json:"resourceType,omitempty"` + Created *Timestamp `json:"created,omitempty"` + LastModified *Timestamp `json:"lastModified,omitempty"` + Location *string `json:"location,omitempty"` +} + +// SCIMProvisionedIdentities represents the result of calling ListSCIMProvisionedIdentities. +type SCIMProvisionedIdentities struct { + Schemas []string `json:"schemas,omitempty"` + TotalResults *int `json:"totalResults,omitempty"` + ItemsPerPage *int `json:"itemsPerPage,omitempty"` + StartIndex *int `json:"startIndex,omitempty"` + Resources []*SCIMUserAttributes `json:"Resources,omitempty"` +} + +// ListSCIMProvisionedIdentitiesOptions represents options for ListSCIMProvisionedIdentities. +// +// GitHub API docs: https://docs.github.com/rest/scim#list-scim-provisioned-identities--parameters +type ListSCIMProvisionedIdentitiesOptions struct { + StartIndex *int `url:"startIndex,omitempty"` // Used for pagination: the index of the first result to return. (Optional.) + Count *int `url:"count,omitempty"` // Used for pagination: the number of results to return. (Optional.) + // Filter results using the equals query parameter operator (eq). + // You can filter results that are equal to id, userName, emails, and external_id. + // For example, to search for an identity with the userName Octocat, you would use this query: ?filter=userName%20eq%20\"Octocat\". + // To filter results for the identity with the email octocat@github.com, you would use this query: ?filter=emails%20eq%20\"octocat@github.com\". + // (Optional.) + Filter *string `url:"filter,omitempty"` +} + +// ListSCIMProvisionedIdentities lists SCIM provisioned identities. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/scim/scim#list-scim-provisioned-identities +// +//meta:operation GET /scim/v2/organizations/{org}/Users +func (s *SCIMService) ListSCIMProvisionedIdentities(ctx context.Context, org string, opts *ListSCIMProvisionedIdentitiesOptions) (*SCIMProvisionedIdentities, *Response, error) { + u := fmt.Sprintf("scim/v2/organizations/%v/Users", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + identities := new(SCIMProvisionedIdentities) + resp, err := s.client.Do(ctx, req, identities) + if err != nil { + return nil, resp, err + } + + return identities, resp, nil +} + +// ProvisionAndInviteSCIMUser provisions organization membership for a user, and sends an activation email to the email address. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/scim/scim#provision-and-invite-a-scim-user +// +//meta:operation POST /scim/v2/organizations/{org}/Users +func (s *SCIMService) ProvisionAndInviteSCIMUser(ctx context.Context, org string, opts *SCIMUserAttributes) (*SCIMUserAttributes, *Response, error) { + u := fmt.Sprintf("scim/v2/organizations/%v/Users", org) + + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + user := new(SCIMUserAttributes) + resp, err := s.client.Do(ctx, req, user) + if err != nil { + return nil, resp, err + } + + return user, resp, nil +} + +// GetSCIMProvisioningInfoForUser returns SCIM provisioning information for a user. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/scim/scim#get-scim-provisioning-information-for-a-user +// +//meta:operation GET /scim/v2/organizations/{org}/Users/{scim_user_id} +func (s *SCIMService) GetSCIMProvisioningInfoForUser(ctx context.Context, org, scimUserID string) (*SCIMUserAttributes, *Response, error) { + u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + user := new(SCIMUserAttributes) + resp, err := s.client.Do(ctx, req, &user) + if err != nil { + return nil, resp, err + } + + return user, resp, nil +} + +// UpdateProvisionedOrgMembership updates a provisioned organization membership. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/scim/scim#update-a-provisioned-organization-membership +// +//meta:operation PUT /scim/v2/organizations/{org}/Users/{scim_user_id} +func (s *SCIMService) UpdateProvisionedOrgMembership(ctx context.Context, org, scimUserID string, opts *SCIMUserAttributes) (*Response, error) { + u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID) + u, err := addOptions(u, opts) + if err != nil { + return nil, err + } + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// UpdateAttributeForSCIMUserOptions represents options for UpdateAttributeForSCIMUser. +// +// GitHub API docs: https://docs.github.com/rest/scim#update-an-attribute-for-a-scim-user--parameters +type UpdateAttributeForSCIMUserOptions struct { + Schemas []string `json:"schemas,omitempty"` // (Optional.) + Operations UpdateAttributeForSCIMUserOperations `json:"operations"` // Set of operations to be performed. (Required.) +} + +// UpdateAttributeForSCIMUserOperations represents operations for UpdateAttributeForSCIMUser. +type UpdateAttributeForSCIMUserOperations struct { + Op string `json:"op"` // (Required.) + Path *string `json:"path,omitempty"` // (Optional.) + Value json.RawMessage `json:"value,omitempty"` // (Optional.) +} + +// UpdateAttributeForSCIMUser updates an attribute for an SCIM user. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/scim/scim#update-an-attribute-for-a-scim-user +// +//meta:operation PATCH /scim/v2/organizations/{org}/Users/{scim_user_id} +func (s *SCIMService) UpdateAttributeForSCIMUser(ctx context.Context, org, scimUserID string, opts *UpdateAttributeForSCIMUserOptions) (*Response, error) { + u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID) + u, err := addOptions(u, opts) + if err != nil { + return nil, err + } + + req, err := s.client.NewRequest("PATCH", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteSCIMUserFromOrg deletes SCIM user from an organization. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/scim/scim#delete-a-scim-user-from-an-organization +// +//meta:operation DELETE /scim/v2/organizations/{org}/Users/{scim_user_id} +func (s *SCIMService) DeleteSCIMUserFromOrg(ctx context.Context, org, scimUserID string) (*Response, error) { + u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/search.go b/vendor/github.com/google/go-github/v68/github/search.go new file mode 100644 index 0000000000..54bc6d5e1f --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/search.go @@ -0,0 +1,347 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "strconv" + "strings" + + qs "github.com/google/go-querystring/query" +) + +// SearchService provides access to the search related functions +// in the GitHub API. +// +// Each method takes a query string defining the search keywords and any search qualifiers. +// For example, when searching issues, the query "gopher is:issue language:go" will search +// for issues containing the word "gopher" in Go repositories. The method call +// +// opts := &github.SearchOptions{Sort: "created", Order: "asc"} +// cl.Search.Issues(ctx, "gopher is:issue language:go", opts) +// +// will search for such issues, sorting by creation date in ascending order +// (i.e., oldest first). +// +// If query includes multiple conditions, it MUST NOT include "+" as the condition separator. +// You have to use " " as the separator instead. +// For example, querying with "language:c++" and "leveldb", then query should be +// "language:c++ leveldb" but not "language:c+++leveldb". +// +// GitHub API docs: https://docs.github.com/rest/search/ +type SearchService service + +// SearchOptions specifies optional parameters to the SearchService methods. +type SearchOptions struct { + // How to sort the search results. Possible values are: + // - for repositories: stars, fork, updated + // - for commits: author-date, committer-date + // - for code: indexed + // - for issues: comments, created, updated + // - for users: followers, repositories, joined + // + // Default is to sort by best match. + Sort string `url:"sort,omitempty"` + + // Sort order if sort parameter is provided. Possible values are: asc, + // desc. Default is desc. + Order string `url:"order,omitempty"` + + // Whether to retrieve text match metadata with a query + TextMatch bool `url:"-"` + + ListOptions +} + +// Common search parameters. +type searchParameters struct { + Query string + RepositoryID *int64 // Sent if non-nil. +} + +// RepositoriesSearchResult represents the result of a repositories search. +type RepositoriesSearchResult struct { + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + Repositories []*Repository `json:"items,omitempty"` +} + +// Repositories searches repositories via various criteria. +// +// GitHub API docs: https://docs.github.com/rest/search/search#search-repositories +// +//meta:operation GET /search/repositories +func (s *SearchService) Repositories(ctx context.Context, query string, opts *SearchOptions) (*RepositoriesSearchResult, *Response, error) { + result := new(RepositoriesSearchResult) + resp, err := s.search(ctx, "repositories", &searchParameters{Query: query}, opts, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// TopicsSearchResult represents the result of a topics search. +type TopicsSearchResult struct { + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + Topics []*TopicResult `json:"items,omitempty"` +} + +type TopicResult struct { + Name *string `json:"name,omitempty"` + DisplayName *string `json:"display_name,omitempty"` + ShortDescription *string `json:"short_description,omitempty"` + Description *string `json:"description,omitempty"` + CreatedBy *string `json:"created_by,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *string `json:"updated_at,omitempty"` + Featured *bool `json:"featured,omitempty"` + Curated *bool `json:"curated,omitempty"` + Score *float64 `json:"score,omitempty"` +} + +// Topics finds topics via various criteria. Results are sorted by best match. +// Please see https://help.github.com/articles/searching-topics for more +// information about search qualifiers. +// +// GitHub API docs: https://docs.github.com/rest/search/search#search-topics +// +//meta:operation GET /search/topics +func (s *SearchService) Topics(ctx context.Context, query string, opts *SearchOptions) (*TopicsSearchResult, *Response, error) { + result := new(TopicsSearchResult) + resp, err := s.search(ctx, "topics", &searchParameters{Query: query}, opts, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// CommitsSearchResult represents the result of a commits search. +type CommitsSearchResult struct { + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + Commits []*CommitResult `json:"items,omitempty"` +} + +// CommitResult represents a commit object as returned in commit search endpoint response. +type CommitResult struct { + SHA *string `json:"sha,omitempty"` + Commit *Commit `json:"commit,omitempty"` + Author *User `json:"author,omitempty"` + Committer *User `json:"committer,omitempty"` + Parents []*Commit `json:"parents,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + URL *string `json:"url,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + + Repository *Repository `json:"repository,omitempty"` + Score *float64 `json:"score,omitempty"` +} + +// Commits searches commits via various criteria. +// +// GitHub API docs: https://docs.github.com/rest/search/search#search-commits +// +//meta:operation GET /search/commits +func (s *SearchService) Commits(ctx context.Context, query string, opts *SearchOptions) (*CommitsSearchResult, *Response, error) { + result := new(CommitsSearchResult) + resp, err := s.search(ctx, "commits", &searchParameters{Query: query}, opts, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// IssuesSearchResult represents the result of an issues search. +type IssuesSearchResult struct { + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + Issues []*Issue `json:"items,omitempty"` +} + +// Issues searches issues via various criteria. +// +// GitHub API docs: https://docs.github.com/rest/search/search#search-issues-and-pull-requests +// +//meta:operation GET /search/issues +func (s *SearchService) Issues(ctx context.Context, query string, opts *SearchOptions) (*IssuesSearchResult, *Response, error) { + result := new(IssuesSearchResult) + resp, err := s.search(ctx, "issues", &searchParameters{Query: query}, opts, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// UsersSearchResult represents the result of a users search. +type UsersSearchResult struct { + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + Users []*User `json:"items,omitempty"` +} + +// Users searches users via various criteria. +// +// GitHub API docs: https://docs.github.com/rest/search/search#search-users +// +//meta:operation GET /search/users +func (s *SearchService) Users(ctx context.Context, query string, opts *SearchOptions) (*UsersSearchResult, *Response, error) { + result := new(UsersSearchResult) + resp, err := s.search(ctx, "users", &searchParameters{Query: query}, opts, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// Match represents a single text match. +type Match struct { + Text *string `json:"text,omitempty"` + Indices []int `json:"indices,omitempty"` +} + +// TextMatch represents a text match for a SearchResult. +type TextMatch struct { + ObjectURL *string `json:"object_url,omitempty"` + ObjectType *string `json:"object_type,omitempty"` + Property *string `json:"property,omitempty"` + Fragment *string `json:"fragment,omitempty"` + Matches []*Match `json:"matches,omitempty"` +} + +func (tm TextMatch) String() string { + return Stringify(tm) +} + +// CodeSearchResult represents the result of a code search. +type CodeSearchResult struct { + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + CodeResults []*CodeResult `json:"items,omitempty"` +} + +// CodeResult represents a single search result. +type CodeResult struct { + Name *string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` + SHA *string `json:"sha,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + Repository *Repository `json:"repository,omitempty"` + TextMatches []*TextMatch `json:"text_matches,omitempty"` +} + +func (c CodeResult) String() string { + return Stringify(c) +} + +// Code searches code via various criteria. +// +// GitHub API docs: https://docs.github.com/rest/search/search#search-code +// +//meta:operation GET /search/code +func (s *SearchService) Code(ctx context.Context, query string, opts *SearchOptions) (*CodeSearchResult, *Response, error) { + result := new(CodeSearchResult) + resp, err := s.search(ctx, "code", &searchParameters{Query: query}, opts, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// LabelsSearchResult represents the result of a code search. +type LabelsSearchResult struct { + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + Labels []*LabelResult `json:"items,omitempty"` +} + +// LabelResult represents a single search result. +type LabelResult struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + Name *string `json:"name,omitempty"` + Color *string `json:"color,omitempty"` + Default *bool `json:"default,omitempty"` + Description *string `json:"description,omitempty"` + Score *float64 `json:"score,omitempty"` +} + +func (l LabelResult) String() string { + return Stringify(l) +} + +// Labels searches labels in the repository with ID repoID via various criteria. +// +// GitHub API docs: https://docs.github.com/rest/search/search#search-labels +// +//meta:operation GET /search/labels +func (s *SearchService) Labels(ctx context.Context, repoID int64, query string, opts *SearchOptions) (*LabelsSearchResult, *Response, error) { + result := new(LabelsSearchResult) + resp, err := s.search(ctx, "labels", &searchParameters{RepositoryID: &repoID, Query: query}, opts, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// Helper function that executes search queries against different +// GitHub search types (repositories, commits, code, issues, users, labels) +// +// If searchParameters.Query includes multiple condition, it MUST NOT include "+" as condition separator. +// For example, querying with "language:c++" and "leveldb", then searchParameters.Query should be "language:c++ leveldb" but not "language:c+++leveldb". +func (s *SearchService) search(ctx context.Context, searchType string, parameters *searchParameters, opts *SearchOptions, result interface{}) (*Response, error) { + params, err := qs.Values(opts) + if err != nil { + return nil, err + } + + if parameters.RepositoryID != nil { + params.Set("repository_id", strconv.FormatInt(*parameters.RepositoryID, 10)) + } + params.Set("q", parameters.Query) + u := fmt.Sprintf("search/%s?%s", searchType, params.Encode()) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, err + } + var acceptHeaders []string + switch { + case searchType == "commits": + // Accept header for search commits preview endpoint + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders = append(acceptHeaders, mediaTypeCommitSearchPreview) + case searchType == "topics": + // Accept header for search repositories based on topics preview endpoint + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders = append(acceptHeaders, mediaTypeTopicsPreview) + case searchType == "repositories": + // Accept header for search repositories based on topics preview endpoint + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders = append(acceptHeaders, mediaTypeTopicsPreview) + case searchType == "issues": + // Accept header for search issues based on reactions preview endpoint + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders = append(acceptHeaders, mediaTypeReactionsPreview) + } + // https://docs.github.com/rest/search#search-repositories + // Accept header defaults to "application/vnd.github.v3+json" + // We change it here to fetch back text-match metadata + if opts != nil && opts.TextMatch { + acceptHeaders = append(acceptHeaders, "application/vnd.github.v3.text-match+json") + } + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + return s.client.Do(ctx, req, result) +} diff --git a/vendor/github.com/google/go-github/v68/github/secret_scanning.go b/vendor/github.com/google/go-github/v68/github/secret_scanning.go new file mode 100644 index 0000000000..fc0fe0cd8c --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/secret_scanning.go @@ -0,0 +1,261 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// SecretScanningService handles communication with the secret scanning related +// methods of the GitHub API. +type SecretScanningService service + +// SecretScanningAlert represents a GitHub secret scanning alert. +type SecretScanningAlert struct { + Number *int `json:"number,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + LocationsURL *string `json:"locations_url,omitempty"` + State *string `json:"state,omitempty"` + Resolution *string `json:"resolution,omitempty"` + ResolvedAt *Timestamp `json:"resolved_at,omitempty"` + ResolvedBy *User `json:"resolved_by,omitempty"` + SecretType *string `json:"secret_type,omitempty"` + SecretTypeDisplayName *string `json:"secret_type_display_name,omitempty"` + Secret *string `json:"secret,omitempty"` + Repository *Repository `json:"repository,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + PushProtectionBypassed *bool `json:"push_protection_bypassed,omitempty"` + PushProtectionBypassedBy *User `json:"push_protection_bypassed_by,omitempty"` + PushProtectionBypassedAt *Timestamp `json:"push_protection_bypassed_at,omitempty"` + ResolutionComment *string `json:"resolution_comment,omitempty"` +} + +// SecretScanningAlertLocation represents the location for a secret scanning alert. +type SecretScanningAlertLocation struct { + Type *string `json:"type,omitempty"` + Details *SecretScanningAlertLocationDetails `json:"details,omitempty"` +} + +// SecretScanningAlertLocationDetails represents the location details for a secret scanning alert. +type SecretScanningAlertLocationDetails struct { + Path *string `json:"path,omitempty"` + Startline *int `json:"start_line,omitempty"` + EndLine *int `json:"end_line,omitempty"` + StartColumn *int `json:"start_column,omitempty"` + EndColumn *int `json:"end_column,omitempty"` + BlobSHA *string `json:"blob_sha,omitempty"` + BlobURL *string `json:"blob_url,omitempty"` + CommitSHA *string `json:"commit_sha,omitempty"` + CommitURL *string `json:"commit_url,omitempty"` + PullRequestCommentURL *string `json:"pull_request_comment_url,omitempty"` +} + +// SecretScanningAlertListOptions specifies optional parameters to the SecretScanningService.ListAlertsForEnterprise method. +type SecretScanningAlertListOptions struct { + // State of the secret scanning alerts to list. Set to open or resolved to only list secret scanning alerts in a specific state. + State string `url:"state,omitempty"` + + // A comma-separated list of secret types to return. By default all secret types are returned. + SecretType string `url:"secret_type,omitempty"` + + // A comma-separated list of resolutions. Only secret scanning alerts with one of these resolutions are listed. + // Valid resolutions are false_positive, wont_fix, revoked, pattern_edited, pattern_deleted or used_in_tests. + Resolution string `url:"resolution,omitempty"` + + ListCursorOptions + + // List options can vary on the Enterprise type. + // On Enterprise Cloud, Secret Scan alerts support requesting by page number + // along with providing a cursor for an "after" param. + // See: https://docs.github.com/enterprise-cloud@latest/rest/secret-scanning#list-secret-scanning-alerts-for-an-organization + // Whereas on Enterprise Server, pagination is by index. + // See: https://docs.github.com/enterprise-server@3.6/rest/secret-scanning#list-secret-scanning-alerts-for-an-organization + ListOptions +} + +// SecretScanningAlertUpdateOptions specifies optional parameters to the SecretScanningService.UpdateAlert method. +type SecretScanningAlertUpdateOptions struct { + // State is required and sets the state of the secret scanning alert. + // Can be either "open" or "resolved". + // You must provide resolution when you set the state to "resolved". + State string `json:"state"` + + // Required when the state is "resolved" and represents the reason for resolving the alert. + // Can be one of: "false_positive", "wont_fix", "revoked", or "used_in_tests". + Resolution *string `json:"resolution,omitempty"` + + // An optional comment when closing an alert. + ResolutionComment *string `json:"resolution_comment,omitempty"` +} + +// ListAlertsForEnterprise lists secret scanning alerts for eligible repositories in an enterprise, from newest to oldest. +// +// To use this endpoint, you must be a member of the enterprise, and you must use an access token with the repo scope or +// security_events scope. Alerts are only returned for organizations in the enterprise for which you are an organization owner or a security manager. +// +// GitHub API docs: https://docs.github.com/rest/secret-scanning/secret-scanning#list-secret-scanning-alerts-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/secret-scanning/alerts +func (s *SecretScanningService) ListAlertsForEnterprise(ctx context.Context, enterprise string, opts *SecretScanningAlertListOptions) ([]*SecretScanningAlert, *Response, error) { + u := fmt.Sprintf("enterprises/%v/secret-scanning/alerts", enterprise) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var alerts []*SecretScanningAlert + resp, err := s.client.Do(ctx, req, &alerts) + if err != nil { + return nil, resp, err + } + + return alerts, resp, nil +} + +// ListAlertsForOrg lists secret scanning alerts for eligible repositories in an organization, from newest to oldest. +// +// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with +// the repo scope or security_events scope. +// +// GitHub API docs: https://docs.github.com/rest/secret-scanning/secret-scanning#list-secret-scanning-alerts-for-an-organization +// +//meta:operation GET /orgs/{org}/secret-scanning/alerts +func (s *SecretScanningService) ListAlertsForOrg(ctx context.Context, org string, opts *SecretScanningAlertListOptions) ([]*SecretScanningAlert, *Response, error) { + u := fmt.Sprintf("orgs/%v/secret-scanning/alerts", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var alerts []*SecretScanningAlert + resp, err := s.client.Do(ctx, req, &alerts) + if err != nil { + return nil, resp, err + } + + return alerts, resp, nil +} + +// ListAlertsForRepo lists secret scanning alerts for a private repository, from newest to oldest. +// +// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with +// the repo scope or security_events scope. +// +// GitHub API docs: https://docs.github.com/rest/secret-scanning/secret-scanning#list-secret-scanning-alerts-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/secret-scanning/alerts +func (s *SecretScanningService) ListAlertsForRepo(ctx context.Context, owner, repo string, opts *SecretScanningAlertListOptions) ([]*SecretScanningAlert, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/secret-scanning/alerts", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var alerts []*SecretScanningAlert + resp, err := s.client.Do(ctx, req, &alerts) + if err != nil { + return nil, resp, err + } + + return alerts, resp, nil +} + +// GetAlert gets a single secret scanning alert detected in a private repository. +// +// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with +// the repo scope or security_events scope. +// +// GitHub API docs: https://docs.github.com/rest/secret-scanning/secret-scanning#get-a-secret-scanning-alert +// +//meta:operation GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number} +func (s *SecretScanningService) GetAlert(ctx context.Context, owner, repo string, number int64) (*SecretScanningAlert, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/secret-scanning/alerts/%v", owner, repo, number) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var alert *SecretScanningAlert + resp, err := s.client.Do(ctx, req, &alert) + if err != nil { + return nil, resp, err + } + + return alert, resp, nil +} + +// UpdateAlert updates the status of a secret scanning alert in a private repository. +// +// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with +// the repo scope or security_events scope. +// +// GitHub API docs: https://docs.github.com/rest/secret-scanning/secret-scanning#update-a-secret-scanning-alert +// +//meta:operation PATCH /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number} +func (s *SecretScanningService) UpdateAlert(ctx context.Context, owner, repo string, number int64, opts *SecretScanningAlertUpdateOptions) (*SecretScanningAlert, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/secret-scanning/alerts/%v", owner, repo, number) + + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + var alert *SecretScanningAlert + resp, err := s.client.Do(ctx, req, &alert) + if err != nil { + return nil, resp, err + } + + return alert, resp, nil +} + +// ListLocationsForAlert lists all locations for a given secret scanning alert for a private repository. +// +// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with +// the repo scope or security_events scope. +// +// GitHub API docs: https://docs.github.com/rest/secret-scanning/secret-scanning#list-locations-for-a-secret-scanning-alert +// +//meta:operation GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}/locations +func (s *SecretScanningService) ListLocationsForAlert(ctx context.Context, owner, repo string, number int64, opts *ListOptions) ([]*SecretScanningAlertLocation, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/secret-scanning/alerts/%v/locations", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var locations []*SecretScanningAlertLocation + resp, err := s.client.Do(ctx, req, &locations) + if err != nil { + return nil, resp, err + } + + return locations, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/security_advisories.go b/vendor/github.com/google/go-github/v68/github/security_advisories.go new file mode 100644 index 0000000000..b5a43f1aac --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/security_advisories.go @@ -0,0 +1,279 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" +) + +type SecurityAdvisoriesService service + +// SecurityAdvisorySubmission represents the Security Advisory Submission. +type SecurityAdvisorySubmission struct { + // Accepted represents whether a private vulnerability report was accepted by the repository's administrators. + Accepted *bool `json:"accepted,omitempty"` +} + +// RepoAdvisoryCredit represents the credit object for a repository Security Advisory. +type RepoAdvisoryCredit struct { + Login *string `json:"login,omitempty"` + Type *string `json:"type,omitempty"` +} + +// RepoAdvisoryCreditDetailed represents a credit given to a user for a repository Security Advisory. +type RepoAdvisoryCreditDetailed struct { + User *User `json:"user,omitempty"` + Type *string `json:"type,omitempty"` + State *string `json:"state,omitempty"` +} + +// ListRepositorySecurityAdvisoriesOptions specifies the optional parameters to list the repository security advisories. +type ListRepositorySecurityAdvisoriesOptions struct { + ListCursorOptions + + // Direction in which to sort advisories. Possible values are: asc, desc. + // Default is "asc". + Direction string `url:"direction,omitempty"` + + // Sort specifies how to sort advisories. Possible values are: created, updated, + // and published. Default value is "created". + Sort string `url:"sort,omitempty"` + + // State filters advisories based on their state. Possible values are: triage, draft, published, closed. + State string `url:"state,omitempty"` +} + +// ListGlobalSecurityAdvisoriesOptions specifies the optional parameters to list the global security advisories. +type ListGlobalSecurityAdvisoriesOptions struct { + ListCursorOptions + + // If specified, only advisories with this GHSA (GitHub Security Advisory) identifier will be returned. + GHSAID *string `url:"ghsa_id,omitempty"` + + // If specified, only advisories of this type will be returned. + // By default, a request with no other parameters defined will only return reviewed advisories that are not malware. + // Default: reviewed + // Can be one of: reviewed, malware, unreviewed + Type *string `url:"type,omitempty"` + + // If specified, only advisories with this CVE (Common Vulnerabilities and Exposures) identifier will be returned. + CVEID *string `url:"cve_id,omitempty"` + + // If specified, only advisories for these ecosystems will be returned. + // Can be one of: actions, composer, erlang, go, maven, npm, nuget, other, pip, pub, rubygems, rust + Ecosystem *string `url:"ecosystem,omitempty"` + + // If specified, only advisories with these severities will be returned. + // Can be one of: unknown, low, medium, high, critical + Severity *string `url:"severity,omitempty"` + + // If specified, only advisories with these Common Weakness Enumerations (CWEs) will be returned. + // Example: cwes=79,284,22 or cwes[]=79&cwes[]=284&cwes[]=22 + CWEs []string `url:"cwes,omitempty"` + + // Whether to only return advisories that have been withdrawn. + IsWithdrawn *bool `url:"is_withdrawn,omitempty"` + + // If specified, only return advisories that affect any of package or package@version. + // A maximum of 1000 packages can be specified. If the query parameter causes + // the URL to exceed the maximum URL length supported by your client, you must specify fewer packages. + // Example: affects=package1,package2@1.0.0,package3@^2.0.0 or affects[]=package1&affects[]=package2@1.0.0 + Affects *string `url:"affects,omitempty"` + + // If specified, only return advisories that were published on a date or date range. + Published *string `url:"published,omitempty"` + + // If specified, only return advisories that were updated on a date or date range. + Updated *string `url:"updated,omitempty"` + + // If specified, only show advisories that were updated or published on a date or date range. + Modified *string `url:"modified,omitempty"` +} + +// GlobalSecurityAdvisory represents the global security advisory object response. +type GlobalSecurityAdvisory struct { + SecurityAdvisory + ID *int64 `json:"id,omitempty"` + RepositoryAdvisoryURL *string `json:"repository_advisory_url,omitempty"` + Type *string `json:"type,omitempty"` + SourceCodeLocation *string `json:"source_code_location,omitempty"` + References []string `json:"references,omitempty"` + Vulnerabilities []*GlobalSecurityVulnerability `json:"vulnerabilities,omitempty"` + GithubReviewedAt *Timestamp `json:"github_reviewed_at,omitempty"` + NVDPublishedAt *Timestamp `json:"nvd_published_at,omitempty"` + Credits []*Credit `json:"credits,omitempty"` +} + +// GlobalSecurityVulnerability represents a vulnerability for a global security advisory. +type GlobalSecurityVulnerability struct { + Package *VulnerabilityPackage `json:"package,omitempty"` + FirstPatchedVersion *string `json:"first_patched_version,omitempty"` + VulnerableVersionRange *string `json:"vulnerable_version_range,omitempty"` + VulnerableFunctions []string `json:"vulnerable_functions,omitempty"` +} + +// Credit represents the credit object for a global security advisory. +type Credit struct { + User *User `json:"user,omitempty"` + Type *string `json:"type,omitempty"` +} + +// RequestCVE requests a Common Vulnerabilities and Exposures (CVE) for a repository security advisory. +// The ghsaID is the GitHub Security Advisory identifier of the advisory. +// +// GitHub API docs: https://docs.github.com/rest/security-advisories/repository-advisories#request-a-cve-for-a-repository-security-advisory +// +//meta:operation POST /repos/{owner}/{repo}/security-advisories/{ghsa_id}/cve +func (s *SecurityAdvisoriesService) RequestCVE(ctx context.Context, owner, repo, ghsaID string) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/security-advisories/%v/cve", owner, repo, ghsaID) + + req, err := s.client.NewRequest("POST", url, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + if _, ok := err.(*AcceptedError); ok { + return resp, nil + } + + return resp, err + } + + return resp, nil +} + +// CreateTemporaryPrivateFork creates a temporary private fork to collaborate on fixing a security vulnerability in your repository. +// The ghsaID is the GitHub Security Advisory identifier of the advisory. +// +// GitHub API docs: https://docs.github.com/rest/security-advisories/repository-advisories#create-a-temporary-private-fork +// +//meta:operation POST /repos/{owner}/{repo}/security-advisories/{ghsa_id}/forks +func (s *SecurityAdvisoriesService) CreateTemporaryPrivateFork(ctx context.Context, owner, repo, ghsaID string) (*Repository, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/security-advisories/%v/forks", owner, repo, ghsaID) + + req, err := s.client.NewRequest("POST", url, nil) + if err != nil { + return nil, nil, err + } + + fork := new(Repository) + resp, err := s.client.Do(ctx, req, fork) + if err != nil { + if aerr, ok := err.(*AcceptedError); ok { + if err := json.Unmarshal(aerr.Raw, fork); err != nil { + return fork, resp, err + } + + return fork, resp, err + } + return nil, resp, err + } + + return fork, resp, nil +} + +// ListRepositorySecurityAdvisoriesForOrg lists the repository security advisories for an organization. +// +// GitHub API docs: https://docs.github.com/rest/security-advisories/repository-advisories#list-repository-security-advisories-for-an-organization +// +//meta:operation GET /orgs/{org}/security-advisories +func (s *SecurityAdvisoriesService) ListRepositorySecurityAdvisoriesForOrg(ctx context.Context, org string, opt *ListRepositorySecurityAdvisoriesOptions) ([]*SecurityAdvisory, *Response, error) { + url := fmt.Sprintf("orgs/%v/security-advisories", org) + url, err := addOptions(url, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + var advisories []*SecurityAdvisory + resp, err := s.client.Do(ctx, req, &advisories) + if err != nil { + return nil, resp, err + } + + return advisories, resp, nil +} + +// ListRepositorySecurityAdvisories lists the security advisories in a repository. +// +// GitHub API docs: https://docs.github.com/rest/security-advisories/repository-advisories#list-repository-security-advisories +// +//meta:operation GET /repos/{owner}/{repo}/security-advisories +func (s *SecurityAdvisoriesService) ListRepositorySecurityAdvisories(ctx context.Context, owner, repo string, opt *ListRepositorySecurityAdvisoriesOptions) ([]*SecurityAdvisory, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/security-advisories", owner, repo) + url, err := addOptions(url, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + var advisories []*SecurityAdvisory + resp, err := s.client.Do(ctx, req, &advisories) + if err != nil { + return nil, resp, err + } + + return advisories, resp, nil +} + +// ListGlobalSecurityAdvisories lists all global security advisories. +// +// GitHub API docs: https://docs.github.com/rest/security-advisories/global-advisories#list-global-security-advisories +// +//meta:operation GET /advisories +func (s *SecurityAdvisoriesService) ListGlobalSecurityAdvisories(ctx context.Context, opts *ListGlobalSecurityAdvisoriesOptions) ([]*GlobalSecurityAdvisory, *Response, error) { + url := "advisories" + url, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + var advisories []*GlobalSecurityAdvisory + resp, err := s.client.Do(ctx, req, &advisories) + if err != nil { + return nil, resp, err + } + + return advisories, resp, nil +} + +// GetGlobalSecurityAdvisories gets a global security advisory using its GitHub Security Advisory (GHSA) identifier. +// +// GitHub API docs: https://docs.github.com/rest/security-advisories/global-advisories#get-a-global-security-advisory +// +//meta:operation GET /advisories/{ghsa_id} +func (s *SecurityAdvisoriesService) GetGlobalSecurityAdvisories(ctx context.Context, ghsaID string) (*GlobalSecurityAdvisory, *Response, error) { + url := fmt.Sprintf("advisories/%s", ghsaID) + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + var advisory *GlobalSecurityAdvisory + resp, err := s.client.Do(ctx, req, &advisory) + if err != nil { + return nil, resp, err + } + + return advisory, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/strings.go b/vendor/github.com/google/go-github/v68/github/strings.go new file mode 100644 index 0000000000..f5e61aa326 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/strings.go @@ -0,0 +1,94 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "fmt" + "reflect" +) + +var timestampType = reflect.TypeOf(Timestamp{}) + +// Stringify attempts to create a reasonable string representation of types in +// the GitHub library. It does things like resolve pointers to their values +// and omits struct fields with nil values. +func Stringify(message interface{}) string { + var buf bytes.Buffer + v := reflect.ValueOf(message) + stringifyValue(&buf, v) + return buf.String() +} + +// stringifyValue was heavily inspired by the goprotobuf library. + +func stringifyValue(w *bytes.Buffer, val reflect.Value) { + if val.Kind() == reflect.Ptr && val.IsNil() { + w.WriteString("") + return + } + + v := reflect.Indirect(val) + + switch v.Kind() { + case reflect.String: + fmt.Fprintf(w, `"%s"`, v) + case reflect.Slice: + w.WriteByte('[') + for i := 0; i < v.Len(); i++ { + if i > 0 { + w.WriteByte(' ') + } + + stringifyValue(w, v.Index(i)) + } + + w.WriteByte(']') + return + case reflect.Struct: + if v.Type().Name() != "" { + w.WriteString(v.Type().String()) + } + + // special handling of Timestamp values + if v.Type() == timestampType { + fmt.Fprintf(w, "{%s}", v.Interface()) + return + } + + w.WriteByte('{') + + var sep bool + for i := 0; i < v.NumField(); i++ { + fv := v.Field(i) + if fv.Kind() == reflect.Ptr && fv.IsNil() { + continue + } + if fv.Kind() == reflect.Slice && fv.IsNil() { + continue + } + if fv.Kind() == reflect.Map && fv.IsNil() { + continue + } + + if sep { + w.WriteString(", ") + } else { + sep = true + } + + w.WriteString(v.Type().Field(i).Name) + w.WriteByte(':') + stringifyValue(w, fv) + } + + w.WriteByte('}') + default: + if v.CanInterface() { + fmt.Fprint(w, v.Interface()) + } + } +} diff --git a/vendor/github.com/google/go-github/v68/github/teams.go b/vendor/github.com/google/go-github/v68/github/teams.go new file mode 100644 index 0000000000..579e5b828b --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/teams.go @@ -0,0 +1,1100 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" +) + +// TeamsService provides access to the team-related functions +// in the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/teams/ +type TeamsService service + +// Team represents a team within a GitHub organization. Teams are used to +// manage access to an organization's repositories. +type Team struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + URL *string `json:"url,omitempty"` + Slug *string `json:"slug,omitempty"` + + // Permission specifies the default permission for repositories owned by the team. + Permission *string `json:"permission,omitempty"` + + // Privacy identifies the level of privacy this team should have. + // Possible values are: + // secret - only visible to organization owners and members of this team + // closed - visible to all members of this organization + // Default is "secret". + Privacy *string `json:"privacy,omitempty"` + + MembersCount *int `json:"members_count,omitempty"` + ReposCount *int `json:"repos_count,omitempty"` + Organization *Organization `json:"organization,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + MembersURL *string `json:"members_url,omitempty"` + RepositoriesURL *string `json:"repositories_url,omitempty"` + Parent *Team `json:"parent,omitempty"` + + // LDAPDN is only available in GitHub Enterprise and when the team + // membership is synchronized with LDAP. + LDAPDN *string `json:"ldap_dn,omitempty"` + + // Permissions identifies the permissions that a team has on a given + // repository. This is only populated when calling Repositories.ListTeams. + Permissions map[string]bool `json:"permissions,omitempty"` + + // Assignment identifies how a team was assigned to an organization role. Its + // possible values are: "direct", "indirect", "mixed". This is only populated when + // calling the ListTeamsAssignedToOrgRole method. + Assignment *string `json:"assignment,omitempty"` +} + +func (t Team) String() string { + return Stringify(t) +} + +// Invitation represents a team member's invitation status. +type Invitation struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Login *string `json:"login,omitempty"` + Email *string `json:"email,omitempty"` + // Role can be one of the values - 'direct_member', 'admin', 'billing_manager', 'hiring_manager', or 'reinstate'. + Role *string `json:"role,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + Inviter *User `json:"inviter,omitempty"` + TeamCount *int `json:"team_count,omitempty"` + InvitationTeamURL *string `json:"invitation_team_url,omitempty"` + FailedAt *Timestamp `json:"failed_at,omitempty"` + FailedReason *string `json:"failed_reason,omitempty"` +} + +func (i Invitation) String() string { + return Stringify(i) +} + +// ListTeams lists all of the teams for an organization. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#list-teams +// +//meta:operation GET /orgs/{org}/teams +func (s *TeamsService) ListTeams(ctx context.Context, org string, opts *ListOptions) ([]*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// GetTeamByID fetches a team, given a specified organization ID, by ID. +// +// Deprecated: Use GetTeamBySlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#get-a-team-by-name +// +//meta:operation GET /orgs/{org}/teams/{team_slug} +func (s *TeamsService) GetTeamByID(ctx context.Context, orgID, teamID int64) (*Team, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v", orgID, teamID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + t := new(Team) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// GetTeamBySlug fetches a team, given a specified organization name, by slug. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#get-a-team-by-name +// +//meta:operation GET /orgs/{org}/teams/{team_slug} +func (s *TeamsService) GetTeamBySlug(ctx context.Context, org, slug string) (*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v", org, slug) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + t := new(Team) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// NewTeam represents a team to be created or modified. +type NewTeam struct { + Name string `json:"name"` // Name of the team. (Required.) + Description *string `json:"description,omitempty"` + Maintainers []string `json:"maintainers,omitempty"` + RepoNames []string `json:"repo_names,omitempty"` + ParentTeamID *int64 `json:"parent_team_id,omitempty"` + + // NotificationSetting can be one of: "notifications_enabled", "notifications_disabled". + NotificationSetting *string `json:"notification_setting,omitempty"` + + // Deprecated: Permission is deprecated when creating or editing a team in an org + // using the new GitHub permission model. It no longer identifies the + // permission a team has on its repos, but only specifies the default + // permission a repo is initially added with. Avoid confusion by + // specifying a permission value when calling AddTeamRepo. + Permission *string `json:"permission,omitempty"` + + // Privacy identifies the level of privacy this team should have. + // Possible values are: + // secret - only visible to organization owners and members of this team + // closed - visible to all members of this organization + // Default is "secret". + Privacy *string `json:"privacy,omitempty"` + + // LDAPDN may be used in GitHub Enterprise when the team membership + // is synchronized with LDAP. + LDAPDN *string `json:"ldap_dn,omitempty"` +} + +func (s NewTeam) String() string { + return Stringify(s) +} + +// CreateTeam creates a new team within an organization. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#create-a-team +// +//meta:operation POST /orgs/{org}/teams +func (s *TeamsService) CreateTeam(ctx context.Context, org string, team NewTeam) (*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams", org) + req, err := s.client.NewRequest("POST", u, team) + if err != nil { + return nil, nil, err + } + + t := new(Team) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// newTeamNoParent is the same as NewTeam but ensures that the +// "parent_team_id" field will be null. It is for internal use +// only and should not be exported. +type newTeamNoParent struct { + Name string `json:"name"` + Description *string `json:"description,omitempty"` + Maintainers []string `json:"maintainers,omitempty"` + RepoNames []string `json:"repo_names,omitempty"` + ParentTeamID *int64 `json:"parent_team_id"` // This will be "null" + NotificationSetting *string `json:"notification_setting,omitempty"` + Privacy *string `json:"privacy,omitempty"` + LDAPDN *string `json:"ldap_dn,omitempty"` +} + +// copyNewTeamWithoutParent is used to set the "parent_team_id" +// field to "null" after copying the other fields from a NewTeam. +// It is for internal use only and should not be exported. +func copyNewTeamWithoutParent(team *NewTeam) *newTeamNoParent { + return &newTeamNoParent{ + Name: team.Name, + Description: team.Description, + Maintainers: team.Maintainers, + RepoNames: team.RepoNames, + NotificationSetting: team.NotificationSetting, + Privacy: team.Privacy, + LDAPDN: team.LDAPDN, + } +} + +// EditTeamByID edits a team, given an organization ID, selected by ID. +// +// Deprecated: Use EditTeamBySlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#update-a-team +// +//meta:operation PATCH /orgs/{org}/teams/{team_slug} +func (s *TeamsService) EditTeamByID(ctx context.Context, orgID, teamID int64, team NewTeam, removeParent bool) (*Team, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v", orgID, teamID) + + var req *http.Request + var err error + if removeParent { + teamRemoveParent := copyNewTeamWithoutParent(&team) + req, err = s.client.NewRequest("PATCH", u, teamRemoveParent) + } else { + req, err = s.client.NewRequest("PATCH", u, team) + } + if err != nil { + return nil, nil, err + } + + t := new(Team) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// EditTeamBySlug edits a team, given an organization name, by slug. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#update-a-team +// +//meta:operation PATCH /orgs/{org}/teams/{team_slug} +func (s *TeamsService) EditTeamBySlug(ctx context.Context, org, slug string, team NewTeam, removeParent bool) (*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v", org, slug) + + var req *http.Request + var err error + if removeParent { + teamRemoveParent := copyNewTeamWithoutParent(&team) + req, err = s.client.NewRequest("PATCH", u, teamRemoveParent) + } else { + req, err = s.client.NewRequest("PATCH", u, team) + } + if err != nil { + return nil, nil, err + } + + t := new(Team) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// DeleteTeamByID deletes a team referenced by ID. +// +// Deprecated: Use DeleteTeamBySlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#delete-a-team +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug} +func (s *TeamsService) DeleteTeamByID(ctx context.Context, orgID, teamID int64) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v", orgID, teamID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteTeamBySlug deletes a team reference by slug. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#delete-a-team +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug} +func (s *TeamsService) DeleteTeamBySlug(ctx context.Context, org, slug string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v", org, slug) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListChildTeamsByParentID lists child teams for a parent team given parent ID. +// +// Deprecated: Use ListChildTeamsByParentSlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#list-child-teams +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/teams +func (s *TeamsService) ListChildTeamsByParentID(ctx context.Context, orgID, teamID int64, opts *ListOptions) ([]*Team, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/teams", orgID, teamID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// ListChildTeamsByParentSlug lists child teams for a parent team given parent slug. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#list-child-teams +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/teams +func (s *TeamsService) ListChildTeamsByParentSlug(ctx context.Context, org, slug string, opts *ListOptions) ([]*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/teams", org, slug) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// ListTeamReposByID lists the repositories given a team ID that the specified team has access to. +// +// Deprecated: Use ListTeamReposBySlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#list-team-repositories +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/repos +func (s *TeamsService) ListTeamReposByID(ctx context.Context, orgID, teamID int64, opts *ListOptions) ([]*Repository, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/repos", orgID, teamID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when topics API fully launches. + req.Header.Set("Accept", mediaTypeTopicsPreview) + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// ListTeamReposBySlug lists the repositories given a team slug that the specified team has access to. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#list-team-repositories +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/repos +func (s *TeamsService) ListTeamReposBySlug(ctx context.Context, org, slug string, opts *ListOptions) ([]*Repository, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/repos", org, slug) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when topics API fully launches. + req.Header.Set("Accept", mediaTypeTopicsPreview) + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// IsTeamRepoByID checks if a team, given its ID, manages the specified repository. If the +// repository is managed by team, a Repository is returned which includes the +// permissions team has for that repo. +// +// Deprecated: Use IsTeamRepoBySlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#check-team-permissions-for-a-repository +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo} +func (s *TeamsService) IsTeamRepoByID(ctx context.Context, orgID, teamID int64, owner, repo string) (*Repository, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/repos/%v/%v", orgID, teamID, owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeOrgPermissionRepo) + + repository := new(Repository) + resp, err := s.client.Do(ctx, req, repository) + if err != nil { + return nil, resp, err + } + + return repository, resp, nil +} + +// IsTeamRepoBySlug checks if a team, given its slug, manages the specified repository. If the +// repository is managed by team, a Repository is returned which includes the +// permissions team has for that repo. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#check-team-permissions-for-a-repository +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo} +func (s *TeamsService) IsTeamRepoBySlug(ctx context.Context, org, slug, owner, repo string) (*Repository, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/repos/%v/%v", org, slug, owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeOrgPermissionRepo) + + repository := new(Repository) + resp, err := s.client.Do(ctx, req, repository) + if err != nil { + return nil, resp, err + } + + return repository, resp, nil +} + +// TeamAddTeamRepoOptions specifies the optional parameters to the +// TeamsService.AddTeamRepoByID and TeamsService.AddTeamRepoBySlug methods. +type TeamAddTeamRepoOptions struct { + // Permission specifies the permission to grant the team on this repository. + // Possible values are: + // pull - team members can pull, but not push to or administer this repository + // push - team members can pull and push, but not administer this repository + // admin - team members can pull, push and administer this repository + // maintain - team members can manage the repository without access to sensitive or destructive actions. + // triage - team members can proactively manage issues and pull requests without write access. + // + // If not specified, the team's permission attribute will be used. + Permission string `json:"permission,omitempty"` +} + +// AddTeamRepoByID adds a repository to be managed by the specified team given the team ID. +// The specified repository must be owned by the organization to which the team +// belongs, or a direct fork of a repository owned by the organization. +// +// Deprecated: Use AddTeamRepoBySlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#add-or-update-team-repository-permissions +// +//meta:operation PUT /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo} +func (s *TeamsService) AddTeamRepoByID(ctx context.Context, orgID, teamID int64, owner, repo string, opts *TeamAddTeamRepoOptions) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/repos/%v/%v", orgID, teamID, owner, repo) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddTeamRepoBySlug adds a repository to be managed by the specified team given the team slug. +// The specified repository must be owned by the organization to which the team +// belongs, or a direct fork of a repository owned by the organization. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#add-or-update-team-repository-permissions +// +//meta:operation PUT /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo} +func (s *TeamsService) AddTeamRepoBySlug(ctx context.Context, org, slug, owner, repo string, opts *TeamAddTeamRepoOptions) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/repos/%v/%v", org, slug, owner, repo) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveTeamRepoByID removes a repository from being managed by the specified +// team given the team ID. Note that this does not delete the repository, it +// just removes it from the team. +// +// Deprecated: Use RemoveTeamRepoBySlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#remove-a-repository-from-a-team +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo} +func (s *TeamsService) RemoveTeamRepoByID(ctx context.Context, orgID, teamID int64, owner, repo string) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/repos/%v/%v", orgID, teamID, owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveTeamRepoBySlug removes a repository from being managed by the specified +// team given the team slug. Note that this does not delete the repository, it +// just removes it from the team. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#remove-a-repository-from-a-team +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo} +func (s *TeamsService) RemoveTeamRepoBySlug(ctx context.Context, org, slug, owner, repo string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/repos/%v/%v", org, slug, owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListUserTeams lists a user's teams +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#list-teams-for-the-authenticated-user +// +//meta:operation GET /user/teams +func (s *TeamsService) ListUserTeams(ctx context.Context, opts *ListOptions) ([]*Team, *Response, error) { + u := "user/teams" + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// ListTeamProjectsByID lists the organization projects for a team given the team ID. +// +// Deprecated: Use ListTeamProjectsBySlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#list-team-projects +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/projects +func (s *TeamsService) ListTeamProjectsByID(ctx context.Context, orgID, teamID int64) ([]*ProjectV2, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/projects", orgID, teamID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + var projects []*ProjectV2 + resp, err := s.client.Do(ctx, req, &projects) + if err != nil { + return nil, resp, err + } + + return projects, resp, nil +} + +// ListTeamProjectsBySlug lists the organization projects for a team given the team slug. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#list-team-projects +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/projects +func (s *TeamsService) ListTeamProjectsBySlug(ctx context.Context, org, slug string) ([]*ProjectV2, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/projects", org, slug) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + var projects []*ProjectV2 + resp, err := s.client.Do(ctx, req, &projects) + if err != nil { + return nil, resp, err + } + + return projects, resp, nil +} + +// ReviewTeamProjectsByID checks whether a team, given its ID, has read, write, or admin +// permissions for an organization project. +// +// Deprecated: Use ReviewTeamProjectsBySlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#check-team-permissions-for-a-project +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/projects/{project_id} +func (s *TeamsService) ReviewTeamProjectsByID(ctx context.Context, orgID, teamID, projectID int64) (*ProjectV2, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/projects/%v", orgID, teamID, projectID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + projects := &ProjectV2{} + resp, err := s.client.Do(ctx, req, &projects) + if err != nil { + return nil, resp, err + } + + return projects, resp, nil +} + +// ReviewTeamProjectsBySlug checks whether a team, given its slug, has read, write, or admin +// permissions for an organization project. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#check-team-permissions-for-a-project +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/projects/{project_id} +func (s *TeamsService) ReviewTeamProjectsBySlug(ctx context.Context, org, slug string, projectID int64) (*ProjectV2, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/projects/%v", org, slug, projectID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + projects := &ProjectV2{} + resp, err := s.client.Do(ctx, req, &projects) + if err != nil { + return nil, resp, err + } + + return projects, resp, nil +} + +// TeamProjectOptions specifies the optional parameters to the +// TeamsService.AddTeamProject method. +type TeamProjectOptions struct { + // Permission specifies the permission to grant to the team for this project. + // Possible values are: + // "read" - team members can read, but not write to or administer this project. + // "write" - team members can read and write, but not administer this project. + // "admin" - team members can read, write and administer this project. + // + Permission *string `json:"permission,omitempty"` +} + +// AddTeamProjectByID adds an organization project to a team given the team ID. +// To add a project to a team or update the team's permission on a project, the +// authenticated user must have admin permissions for the project. +// +// Deprecated: Use AddTeamProjectBySlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#add-or-update-team-project-permissions +// +//meta:operation PUT /orgs/{org}/teams/{team_slug}/projects/{project_id} +func (s *TeamsService) AddTeamProjectByID(ctx context.Context, orgID, teamID, projectID int64, opts *TeamProjectOptions) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/projects/%v", orgID, teamID, projectID) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + return s.client.Do(ctx, req, nil) +} + +// AddTeamProjectBySlug adds an organization project to a team given the team slug. +// To add a project to a team or update the team's permission on a project, the +// authenticated user must have admin permissions for the project. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#add-or-update-team-project-permissions +// +//meta:operation PUT /orgs/{org}/teams/{team_slug}/projects/{project_id} +func (s *TeamsService) AddTeamProjectBySlug(ctx context.Context, org, slug string, projectID int64, opts *TeamProjectOptions) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/projects/%v", org, slug, projectID) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + return s.client.Do(ctx, req, nil) +} + +// RemoveTeamProjectByID removes an organization project from a team given team ID. +// An organization owner or a team maintainer can remove any project from the team. +// To remove a project from a team as an organization member, the authenticated user +// must have "read" access to both the team and project, or "admin" access to the team +// or project. +// Note: This endpoint removes the project from the team, but does not delete it. +// +// Deprecated: Use RemoveTeamProjectBySlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#remove-a-project-from-a-team +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/projects/{project_id} +func (s *TeamsService) RemoveTeamProjectByID(ctx context.Context, orgID, teamID, projectID int64) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/projects/%v", orgID, teamID, projectID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + return s.client.Do(ctx, req, nil) +} + +// RemoveTeamProjectBySlug removes an organization project from a team given team slug. +// An organization owner or a team maintainer can remove any project from the team. +// To remove a project from a team as an organization member, the authenticated user +// must have "read" access to both the team and project, or "admin" access to the team +// or project. +// Note: This endpoint removes the project from the team, but does not delete it. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#remove-a-project-from-a-team +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/projects/{project_id} +func (s *TeamsService) RemoveTeamProjectBySlug(ctx context.Context, org, slug string, projectID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/projects/%v", org, slug, projectID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + return s.client.Do(ctx, req, nil) +} + +// ListIDPGroupsOptions specifies the optional parameters to the ListIDPGroupsInOrganization method. +type ListIDPGroupsOptions struct { + // Filters the results to return only those that begin with the value specified by this parameter. + Query string `url:"q,omitempty"` + + ListCursorOptions +} + +// IDPGroupList represents a list of external identity provider (IDP) groups. +type IDPGroupList struct { + Groups []*IDPGroup `json:"groups"` +} + +// IDPGroup represents an external identity provider (IDP) group. +type IDPGroup struct { + GroupID *string `json:"group_id,omitempty"` + GroupName *string `json:"group_name,omitempty"` + GroupDescription *string `json:"group_description,omitempty"` +} + +// ListIDPGroupsInOrganization lists IDP groups available in an organization. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/team-sync#list-idp-groups-for-an-organization +// +//meta:operation GET /orgs/{org}/team-sync/groups +func (s *TeamsService) ListIDPGroupsInOrganization(ctx context.Context, org string, opts *ListIDPGroupsOptions) (*IDPGroupList, *Response, error) { + u := fmt.Sprintf("orgs/%v/team-sync/groups", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + groups := new(IDPGroupList) + resp, err := s.client.Do(ctx, req, groups) + if err != nil { + return nil, resp, err + } + + return groups, resp, nil +} + +// ListIDPGroupsForTeamByID lists IDP groups connected to a team on GitHub +// given organization and team IDs. +// +// Deprecated: Use ListIDPGroupsForTeamBySlug instead. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/team-sync#list-idp-groups-for-a-team +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/team-sync/group-mappings +func (s *TeamsService) ListIDPGroupsForTeamByID(ctx context.Context, orgID, teamID int64) (*IDPGroupList, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/team-sync/group-mappings", orgID, teamID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + groups := new(IDPGroupList) + resp, err := s.client.Do(ctx, req, groups) + if err != nil { + return nil, resp, err + } + + return groups, resp, nil +} + +// ListIDPGroupsForTeamBySlug lists IDP groups connected to a team on GitHub +// given organization name and team slug. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/team-sync#list-idp-groups-for-a-team +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/team-sync/group-mappings +func (s *TeamsService) ListIDPGroupsForTeamBySlug(ctx context.Context, org, slug string) (*IDPGroupList, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/team-sync/group-mappings", org, slug) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + groups := new(IDPGroupList) + resp, err := s.client.Do(ctx, req, groups) + if err != nil { + return nil, resp, err + } + + return groups, resp, nil +} + +// CreateOrUpdateIDPGroupConnectionsByID creates, updates, or removes a connection +// between a team and an IDP group given organization and team IDs. +// +// Deprecated: Use CreateOrUpdateIDPGroupConnectionsBySlug instead. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/team-sync#create-or-update-idp-group-connections +// +//meta:operation PATCH /orgs/{org}/teams/{team_slug}/team-sync/group-mappings +func (s *TeamsService) CreateOrUpdateIDPGroupConnectionsByID(ctx context.Context, orgID, teamID int64, opts IDPGroupList) (*IDPGroupList, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/team-sync/group-mappings", orgID, teamID) + + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + groups := new(IDPGroupList) + resp, err := s.client.Do(ctx, req, groups) + if err != nil { + return nil, resp, err + } + + return groups, resp, nil +} + +// CreateOrUpdateIDPGroupConnectionsBySlug creates, updates, or removes a connection +// between a team and an IDP group given organization name and team slug. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/team-sync#create-or-update-idp-group-connections +// +//meta:operation PATCH /orgs/{org}/teams/{team_slug}/team-sync/group-mappings +func (s *TeamsService) CreateOrUpdateIDPGroupConnectionsBySlug(ctx context.Context, org, slug string, opts IDPGroupList) (*IDPGroupList, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/team-sync/group-mappings", org, slug) + + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + groups := new(IDPGroupList) + resp, err := s.client.Do(ctx, req, groups) + if err != nil { + return nil, resp, err + } + + return groups, resp, nil +} + +// ExternalGroupMember represents a member of an external group. +type ExternalGroupMember struct { + MemberID *int64 `json:"member_id,omitempty"` + MemberLogin *string `json:"member_login,omitempty"` + MemberName *string `json:"member_name,omitempty"` + MemberEmail *string `json:"member_email,omitempty"` +} + +// ExternalGroupTeam represents a team connected to an external group. +type ExternalGroupTeam struct { + TeamID *int64 `json:"team_id,omitempty"` + TeamName *string `json:"team_name,omitempty"` +} + +// ExternalGroup represents an external group. +type ExternalGroup struct { + GroupID *int64 `json:"group_id,omitempty"` + GroupName *string `json:"group_name,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Teams []*ExternalGroupTeam `json:"teams,omitempty"` + Members []*ExternalGroupMember `json:"members,omitempty"` +} + +// ExternalGroupList represents a list of external groups. +type ExternalGroupList struct { + Groups []*ExternalGroup `json:"groups"` +} + +// GetExternalGroup fetches an external group. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/external-groups#get-an-external-group +// +//meta:operation GET /orgs/{org}/external-group/{group_id} +func (s *TeamsService) GetExternalGroup(ctx context.Context, org string, groupID int64) (*ExternalGroup, *Response, error) { + u := fmt.Sprintf("orgs/%v/external-group/%v", org, groupID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + externalGroup := new(ExternalGroup) + resp, err := s.client.Do(ctx, req, externalGroup) + if err != nil { + return nil, resp, err + } + + return externalGroup, resp, nil +} + +// ListExternalGroupsOptions specifies the optional parameters to the +// TeamsService.ListExternalGroups method. +type ListExternalGroupsOptions struct { + DisplayName *string `url:"display_name,omitempty"` + + ListOptions +} + +// ListExternalGroups lists external groups in an organization on GitHub. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/external-groups#list-external-groups-in-an-organization +// +//meta:operation GET /orgs/{org}/external-groups +func (s *TeamsService) ListExternalGroups(ctx context.Context, org string, opts *ListExternalGroupsOptions) (*ExternalGroupList, *Response, error) { + u := fmt.Sprintf("orgs/%v/external-groups", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + externalGroups := new(ExternalGroupList) + resp, err := s.client.Do(ctx, req, externalGroups) + if err != nil { + return nil, resp, err + } + + return externalGroups, resp, nil +} + +// ListExternalGroupsForTeamBySlug lists external groups connected to a team on GitHub. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/external-groups#list-a-connection-between-an-external-group-and-a-team +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/external-groups +func (s *TeamsService) ListExternalGroupsForTeamBySlug(ctx context.Context, org, slug string) (*ExternalGroupList, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/external-groups", org, slug) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + externalGroups := new(ExternalGroupList) + resp, err := s.client.Do(ctx, req, externalGroups) + if err != nil { + return nil, resp, err + } + + return externalGroups, resp, nil +} + +// UpdateConnectedExternalGroup updates the connection between an external group and a team. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/external-groups#update-the-connection-between-an-external-group-and-a-team +// +//meta:operation PATCH /orgs/{org}/teams/{team_slug}/external-groups +func (s *TeamsService) UpdateConnectedExternalGroup(ctx context.Context, org, slug string, eg *ExternalGroup) (*ExternalGroup, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/external-groups", org, slug) + + req, err := s.client.NewRequest("PATCH", u, eg) + if err != nil { + return nil, nil, err + } + + externalGroup := new(ExternalGroup) + resp, err := s.client.Do(ctx, req, externalGroup) + if err != nil { + return nil, resp, err + } + + return externalGroup, resp, nil +} + +// RemoveConnectedExternalGroup removes the connection between an external group and a team. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/external-groups#remove-the-connection-between-an-external-group-and-a-team +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/external-groups +func (s *TeamsService) RemoveConnectedExternalGroup(ctx context.Context, org, slug string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/external-groups", org, slug) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/teams_discussion_comments.go b/vendor/github.com/google/go-github/v68/github/teams_discussion_comments.go new file mode 100644 index 0000000000..eba6fdf46a --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/teams_discussion_comments.go @@ -0,0 +1,262 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// DiscussionComment represents a GitHub discussion in a team. +type DiscussionComment struct { + Author *User `json:"author,omitempty"` + Body *string `json:"body,omitempty"` + BodyHTML *string `json:"body_html,omitempty"` + BodyVersion *string `json:"body_version,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + LastEditedAt *Timestamp `json:"last_edited_at,omitempty"` + DiscussionURL *string `json:"discussion_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Number *int `json:"number,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + URL *string `json:"url,omitempty"` + Reactions *Reactions `json:"reactions,omitempty"` +} + +func (c DiscussionComment) String() string { + return Stringify(c) +} + +// DiscussionCommentListOptions specifies optional parameters to the +// TeamServices.ListComments method. +type DiscussionCommentListOptions struct { + // Sorts the discussion comments by the date they were created. + // Accepted values are asc and desc. Default is desc. + Direction string `url:"direction,omitempty"` + ListOptions +} + +// ListCommentsByID lists all comments on a team discussion by team ID. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussion-comments#list-discussion-comments +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments +func (s *TeamsService) ListCommentsByID(ctx context.Context, orgID, teamID int64, discussionNumber int, options *DiscussionCommentListOptions) ([]*DiscussionComment, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments", orgID, teamID, discussionNumber) + u, err := addOptions(u, options) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var comments []*DiscussionComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// ListCommentsBySlug lists all comments on a team discussion by team slug. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussion-comments#list-discussion-comments +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments +func (s *TeamsService) ListCommentsBySlug(ctx context.Context, org, slug string, discussionNumber int, options *DiscussionCommentListOptions) ([]*DiscussionComment, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments", org, slug, discussionNumber) + u, err := addOptions(u, options) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var comments []*DiscussionComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// GetCommentByID gets a specific comment on a team discussion by team ID. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussion-comments#get-a-discussion-comment +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number} +func (s *TeamsService) GetCommentByID(ctx context.Context, orgID, teamID int64, discussionNumber, commentNumber int) (*DiscussionComment, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments/%v", orgID, teamID, discussionNumber, commentNumber) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + discussionComment := &DiscussionComment{} + resp, err := s.client.Do(ctx, req, discussionComment) + if err != nil { + return nil, resp, err + } + + return discussionComment, resp, nil +} + +// GetCommentBySlug gets a specific comment on a team discussion by team slug. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussion-comments#get-a-discussion-comment +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number} +func (s *TeamsService) GetCommentBySlug(ctx context.Context, org, slug string, discussionNumber, commentNumber int) (*DiscussionComment, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments/%v", org, slug, discussionNumber, commentNumber) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + discussionComment := &DiscussionComment{} + resp, err := s.client.Do(ctx, req, discussionComment) + if err != nil { + return nil, resp, err + } + + return discussionComment, resp, nil +} + +// CreateCommentByID creates a new comment on a team discussion by team ID. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussion-comments#create-a-discussion-comment +// +//meta:operation POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments +func (s *TeamsService) CreateCommentByID(ctx context.Context, orgID, teamID int64, discussionNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments", orgID, teamID, discussionNumber) + req, err := s.client.NewRequest("POST", u, comment) + if err != nil { + return nil, nil, err + } + + discussionComment := &DiscussionComment{} + resp, err := s.client.Do(ctx, req, discussionComment) + if err != nil { + return nil, resp, err + } + + return discussionComment, resp, nil +} + +// CreateCommentBySlug creates a new comment on a team discussion by team slug. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussion-comments#create-a-discussion-comment +// +//meta:operation POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments +func (s *TeamsService) CreateCommentBySlug(ctx context.Context, org, slug string, discsusionNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments", org, slug, discsusionNumber) + req, err := s.client.NewRequest("POST", u, comment) + if err != nil { + return nil, nil, err + } + + discussionComment := &DiscussionComment{} + resp, err := s.client.Do(ctx, req, discussionComment) + if err != nil { + return nil, resp, err + } + + return discussionComment, resp, nil +} + +// EditCommentByID edits the body text of a discussion comment by team ID. +// Authenticated user must grant write:discussion scope. +// User is allowed to edit body of a comment only. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussion-comments#update-a-discussion-comment +// +//meta:operation PATCH /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number} +func (s *TeamsService) EditCommentByID(ctx context.Context, orgID, teamID int64, discussionNumber, commentNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments/%v", orgID, teamID, discussionNumber, commentNumber) + req, err := s.client.NewRequest("PATCH", u, comment) + if err != nil { + return nil, nil, err + } + + discussionComment := &DiscussionComment{} + resp, err := s.client.Do(ctx, req, discussionComment) + if err != nil { + return nil, resp, err + } + + return discussionComment, resp, nil +} + +// EditCommentBySlug edits the body text of a discussion comment by team slug. +// Authenticated user must grant write:discussion scope. +// User is allowed to edit body of a comment only. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussion-comments#update-a-discussion-comment +// +//meta:operation PATCH /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number} +func (s *TeamsService) EditCommentBySlug(ctx context.Context, org, slug string, discussionNumber, commentNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments/%v", org, slug, discussionNumber, commentNumber) + req, err := s.client.NewRequest("PATCH", u, comment) + if err != nil { + return nil, nil, err + } + + discussionComment := &DiscussionComment{} + resp, err := s.client.Do(ctx, req, discussionComment) + if err != nil { + return nil, resp, err + } + + return discussionComment, resp, nil +} + +// DeleteCommentByID deletes a comment on a team discussion by team ID. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussion-comments#delete-a-discussion-comment +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number} +func (s *TeamsService) DeleteCommentByID(ctx context.Context, orgID, teamID int64, discussionNumber, commentNumber int) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments/%v", orgID, teamID, discussionNumber, commentNumber) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteCommentBySlug deletes a comment on a team discussion by team slug. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussion-comments#delete-a-discussion-comment +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number} +func (s *TeamsService) DeleteCommentBySlug(ctx context.Context, org, slug string, discussionNumber, commentNumber int) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments/%v", org, slug, discussionNumber, commentNumber) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/teams_discussions.go b/vendor/github.com/google/go-github/v68/github/teams_discussions.go new file mode 100644 index 0000000000..b056525f4e --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/teams_discussions.go @@ -0,0 +1,267 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// TeamDiscussion represents a GitHub discussion in a team. +type TeamDiscussion struct { + Author *User `json:"author,omitempty"` + Body *string `json:"body,omitempty"` + BodyHTML *string `json:"body_html,omitempty"` + BodyVersion *string `json:"body_version,omitempty"` + CommentsCount *int `json:"comments_count,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + LastEditedAt *Timestamp `json:"last_edited_at,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Number *int `json:"number,omitempty"` + Pinned *bool `json:"pinned,omitempty"` + Private *bool `json:"private,omitempty"` + TeamURL *string `json:"team_url,omitempty"` + Title *string `json:"title,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + URL *string `json:"url,omitempty"` + Reactions *Reactions `json:"reactions,omitempty"` +} + +func (d TeamDiscussion) String() string { + return Stringify(d) +} + +// DiscussionListOptions specifies optional parameters to the +// TeamServices.ListDiscussions method. +type DiscussionListOptions struct { + // Sorts the discussion by the date they were created. + // Accepted values are asc and desc. Default is desc. + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// ListDiscussionsByID lists all discussions on team's page given Organization and Team ID. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussions#list-discussions +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/discussions +func (s *TeamsService) ListDiscussionsByID(ctx context.Context, orgID, teamID int64, opts *DiscussionListOptions) ([]*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions", orgID, teamID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teamDiscussions []*TeamDiscussion + resp, err := s.client.Do(ctx, req, &teamDiscussions) + if err != nil { + return nil, resp, err + } + + return teamDiscussions, resp, nil +} + +// ListDiscussionsBySlug lists all discussions on team's page given Organization name and Team's slug. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussions#list-discussions +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/discussions +func (s *TeamsService) ListDiscussionsBySlug(ctx context.Context, org, slug string, opts *DiscussionListOptions) ([]*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions", org, slug) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teamDiscussions []*TeamDiscussion + resp, err := s.client.Do(ctx, req, &teamDiscussions) + if err != nil { + return nil, resp, err + } + + return teamDiscussions, resp, nil +} + +// GetDiscussionByID gets a specific discussion on a team's page given Organization and Team ID. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussions#get-a-discussion +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number} +func (s *TeamsService) GetDiscussionByID(ctx context.Context, orgID, teamID int64, discussionNumber int) (*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v", orgID, teamID, discussionNumber) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + teamDiscussion := &TeamDiscussion{} + resp, err := s.client.Do(ctx, req, teamDiscussion) + if err != nil { + return nil, resp, err + } + + return teamDiscussion, resp, nil +} + +// GetDiscussionBySlug gets a specific discussion on a team's page given Organization name and Team's slug. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussions#get-a-discussion +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number} +func (s *TeamsService) GetDiscussionBySlug(ctx context.Context, org, slug string, discussionNumber int) (*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v", org, slug, discussionNumber) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + teamDiscussion := &TeamDiscussion{} + resp, err := s.client.Do(ctx, req, teamDiscussion) + if err != nil { + return nil, resp, err + } + + return teamDiscussion, resp, nil +} + +// CreateDiscussionByID creates a new discussion post on a team's page given Organization and Team ID. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussions#create-a-discussion +// +//meta:operation POST /orgs/{org}/teams/{team_slug}/discussions +func (s *TeamsService) CreateDiscussionByID(ctx context.Context, orgID, teamID int64, discussion TeamDiscussion) (*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions", orgID, teamID) + req, err := s.client.NewRequest("POST", u, discussion) + if err != nil { + return nil, nil, err + } + + teamDiscussion := &TeamDiscussion{} + resp, err := s.client.Do(ctx, req, teamDiscussion) + if err != nil { + return nil, resp, err + } + + return teamDiscussion, resp, nil +} + +// CreateDiscussionBySlug creates a new discussion post on a team's page given Organization name and Team's slug. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussions#create-a-discussion +// +//meta:operation POST /orgs/{org}/teams/{team_slug}/discussions +func (s *TeamsService) CreateDiscussionBySlug(ctx context.Context, org, slug string, discussion TeamDiscussion) (*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions", org, slug) + req, err := s.client.NewRequest("POST", u, discussion) + if err != nil { + return nil, nil, err + } + + teamDiscussion := &TeamDiscussion{} + resp, err := s.client.Do(ctx, req, teamDiscussion) + if err != nil { + return nil, resp, err + } + + return teamDiscussion, resp, nil +} + +// EditDiscussionByID edits the title and body text of a discussion post given Organization and Team ID. +// Authenticated user must grant write:discussion scope. +// User is allowed to change Title and Body of a discussion only. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussions#update-a-discussion +// +//meta:operation PATCH /orgs/{org}/teams/{team_slug}/discussions/{discussion_number} +func (s *TeamsService) EditDiscussionByID(ctx context.Context, orgID, teamID int64, discussionNumber int, discussion TeamDiscussion) (*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v", orgID, teamID, discussionNumber) + req, err := s.client.NewRequest("PATCH", u, discussion) + if err != nil { + return nil, nil, err + } + + teamDiscussion := &TeamDiscussion{} + resp, err := s.client.Do(ctx, req, teamDiscussion) + if err != nil { + return nil, resp, err + } + + return teamDiscussion, resp, nil +} + +// EditDiscussionBySlug edits the title and body text of a discussion post given Organization name and Team's slug. +// Authenticated user must grant write:discussion scope. +// User is allowed to change Title and Body of a discussion only. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussions#update-a-discussion +// +//meta:operation PATCH /orgs/{org}/teams/{team_slug}/discussions/{discussion_number} +func (s *TeamsService) EditDiscussionBySlug(ctx context.Context, org, slug string, discussionNumber int, discussion TeamDiscussion) (*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v", org, slug, discussionNumber) + req, err := s.client.NewRequest("PATCH", u, discussion) + if err != nil { + return nil, nil, err + } + + teamDiscussion := &TeamDiscussion{} + resp, err := s.client.Do(ctx, req, teamDiscussion) + if err != nil { + return nil, resp, err + } + + return teamDiscussion, resp, nil +} + +// DeleteDiscussionByID deletes a discussion from team's page given Organization and Team ID. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussions#delete-a-discussion +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number} +func (s *TeamsService) DeleteDiscussionByID(ctx context.Context, orgID, teamID int64, discussionNumber int) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v", orgID, teamID, discussionNumber) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteDiscussionBySlug deletes a discussion from team's page given Organization name and Team's slug. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussions#delete-a-discussion +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number} +func (s *TeamsService) DeleteDiscussionBySlug(ctx context.Context, org, slug string, discussionNumber int) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v", org, slug, discussionNumber) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/teams_members.go b/vendor/github.com/google/go-github/v68/github/teams_members.go new file mode 100644 index 0000000000..059d993a3e --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/teams_members.go @@ -0,0 +1,263 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// TeamListTeamMembersOptions specifies the optional parameters to the +// TeamsService.ListTeamMembers method. +type TeamListTeamMembersOptions struct { + // Role filters members returned by their role in the team. Possible + // values are "all", "member", "maintainer". Default is "all". + Role string `url:"role,omitempty"` + + ListOptions +} + +// ListTeamMembersByID lists all of the users who are members of a team, given a specified +// organization ID, by team ID. +// +// GitHub API docs: https://docs.github.com/rest/teams/members#list-team-members +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/members +func (s *TeamsService) ListTeamMembersByID(ctx context.Context, orgID, teamID int64, opts *TeamListTeamMembersOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/members", orgID, teamID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var members []*User + resp, err := s.client.Do(ctx, req, &members) + if err != nil { + return nil, resp, err + } + + return members, resp, nil +} + +// ListTeamMembersBySlug lists all of the users who are members of a team, given a specified +// organization name, by team slug. +// +// GitHub API docs: https://docs.github.com/rest/teams/members#list-team-members +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/members +func (s *TeamsService) ListTeamMembersBySlug(ctx context.Context, org, slug string, opts *TeamListTeamMembersOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/members", org, slug) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var members []*User + resp, err := s.client.Do(ctx, req, &members) + if err != nil { + return nil, resp, err + } + + return members, resp, nil +} + +// GetTeamMembershipByID returns the membership status for a user in a team, given a specified +// organization ID, by team ID. +// +// GitHub API docs: https://docs.github.com/rest/teams/members#list-team-members +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/members +func (s *TeamsService) GetTeamMembershipByID(ctx context.Context, orgID, teamID int64, user string) (*Membership, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/memberships/%v", orgID, teamID, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + t := new(Membership) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// GetTeamMembershipBySlug returns the membership status for a user in a team, given a specified +// organization name, by team slug. +// +// GitHub API docs: https://docs.github.com/rest/teams/members#get-team-membership-for-a-user +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/memberships/{username} +func (s *TeamsService) GetTeamMembershipBySlug(ctx context.Context, org, slug, user string) (*Membership, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/memberships/%v", org, slug, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + t := new(Membership) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// TeamAddTeamMembershipOptions specifies the optional +// parameters to the TeamsService.AddTeamMembership method. +type TeamAddTeamMembershipOptions struct { + // Role specifies the role the user should have in the team. Possible + // values are: + // member - a normal member of the team + // maintainer - a team maintainer. Able to add/remove other team + // members, promote other team members to team + // maintainer, and edit the team’s name and description + // + // Default value is "member". + Role string `json:"role,omitempty"` +} + +// AddTeamMembershipByID adds or invites a user to a team, given a specified +// organization ID, by team ID. +// +// GitHub API docs: https://docs.github.com/rest/teams/members#add-or-update-team-membership-for-a-user +// +//meta:operation PUT /orgs/{org}/teams/{team_slug}/memberships/{username} +func (s *TeamsService) AddTeamMembershipByID(ctx context.Context, orgID, teamID int64, user string, opts *TeamAddTeamMembershipOptions) (*Membership, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/memberships/%v", orgID, teamID, user) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, nil, err + } + + t := new(Membership) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// AddTeamMembershipBySlug adds or invites a user to a team, given a specified +// organization name, by team slug. +// +// GitHub API docs: https://docs.github.com/rest/teams/members#add-or-update-team-membership-for-a-user +// +//meta:operation PUT /orgs/{org}/teams/{team_slug}/memberships/{username} +func (s *TeamsService) AddTeamMembershipBySlug(ctx context.Context, org, slug, user string, opts *TeamAddTeamMembershipOptions) (*Membership, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/memberships/%v", org, slug, user) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, nil, err + } + + t := new(Membership) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// RemoveTeamMembershipByID removes a user from a team, given a specified +// organization ID, by team ID. +// +// GitHub API docs: https://docs.github.com/rest/teams/members#remove-team-membership-for-a-user +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/memberships/{username} +func (s *TeamsService) RemoveTeamMembershipByID(ctx context.Context, orgID, teamID int64, user string) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/memberships/%v", orgID, teamID, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveTeamMembershipBySlug removes a user from a team, given a specified +// organization name, by team slug. +// +// GitHub API docs: https://docs.github.com/rest/teams/members#remove-team-membership-for-a-user +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/memberships/{username} +func (s *TeamsService) RemoveTeamMembershipBySlug(ctx context.Context, org, slug, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/memberships/%v", org, slug, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListPendingTeamInvitationsByID gets pending invitation list of a team, given a specified +// organization ID, by team ID. +// +// GitHub API docs: https://docs.github.com/rest/teams/members#list-pending-team-invitations +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/invitations +func (s *TeamsService) ListPendingTeamInvitationsByID(ctx context.Context, orgID, teamID int64, opts *ListOptions) ([]*Invitation, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/invitations", orgID, teamID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pendingInvitations []*Invitation + resp, err := s.client.Do(ctx, req, &pendingInvitations) + if err != nil { + return nil, resp, err + } + + return pendingInvitations, resp, nil +} + +// ListPendingTeamInvitationsBySlug get pending invitation list of a team, given a specified +// organization name, by team slug. +// +// GitHub API docs: https://docs.github.com/rest/teams/members#list-pending-team-invitations +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/invitations +func (s *TeamsService) ListPendingTeamInvitationsBySlug(ctx context.Context, org, slug string, opts *ListOptions) ([]*Invitation, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/invitations", org, slug) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pendingInvitations []*Invitation + resp, err := s.client.Do(ctx, req, &pendingInvitations) + if err != nil { + return nil, resp, err + } + + return pendingInvitations, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/timestamp.go b/vendor/github.com/google/go-github/v68/github/timestamp.go new file mode 100644 index 0000000000..dc1045cf74 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/timestamp.go @@ -0,0 +1,52 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "strconv" + "time" +) + +// Timestamp represents a time that can be unmarshalled from a JSON string +// formatted as either an RFC3339 or Unix timestamp. This is necessary for some +// fields since the GitHub API is inconsistent in how it represents times. All +// exported methods of time.Time can be called on Timestamp. +type Timestamp struct { + time.Time +} + +func (t Timestamp) String() string { + return t.Time.String() +} + +// GetTime returns std time.Time. +func (t *Timestamp) GetTime() *time.Time { + if t == nil { + return nil + } + return &t.Time +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +// Time is expected in RFC3339 or Unix format. +func (t *Timestamp) UnmarshalJSON(data []byte) (err error) { + str := string(data) + i, err := strconv.ParseInt(str, 10, 64) + if err == nil { + t.Time = time.Unix(i, 0) + if t.Time.Year() > 3000 { + t.Time = time.Unix(0, i*1e6) + } + } else { + t.Time, err = time.Parse(`"`+time.RFC3339+`"`, str) + } + return +} + +// Equal reports whether t and u are equal based on time.Equal. +func (t Timestamp) Equal(u Timestamp) bool { + return t.Time.Equal(u.Time) +} diff --git a/vendor/github.com/google/go-github/v68/github/users.go b/vendor/github.com/google/go-github/v68/github/users.go new file mode 100644 index 0000000000..60f1e06a69 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/users.go @@ -0,0 +1,302 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// UsersService handles communication with the user related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/users/ +type UsersService service + +// User represents a GitHub user. +type User struct { + Login *string `json:"login,omitempty"` + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + AvatarURL *string `json:"avatar_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + GravatarID *string `json:"gravatar_id,omitempty"` + Name *string `json:"name,omitempty"` + Company *string `json:"company,omitempty"` + Blog *string `json:"blog,omitempty"` + Location *string `json:"location,omitempty"` + Email *string `json:"email,omitempty"` + Hireable *bool `json:"hireable,omitempty"` + Bio *string `json:"bio,omitempty"` + TwitterUsername *string `json:"twitter_username,omitempty"` + PublicRepos *int `json:"public_repos,omitempty"` + PublicGists *int `json:"public_gists,omitempty"` + Followers *int `json:"followers,omitempty"` + Following *int `json:"following,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + SuspendedAt *Timestamp `json:"suspended_at,omitempty"` + Type *string `json:"type,omitempty"` + SiteAdmin *bool `json:"site_admin,omitempty"` + TotalPrivateRepos *int64 `json:"total_private_repos,omitempty"` + OwnedPrivateRepos *int64 `json:"owned_private_repos,omitempty"` + PrivateGists *int `json:"private_gists,omitempty"` + DiskUsage *int `json:"disk_usage,omitempty"` + Collaborators *int `json:"collaborators,omitempty"` + TwoFactorAuthentication *bool `json:"two_factor_authentication,omitempty"` + Plan *Plan `json:"plan,omitempty"` + LdapDn *string `json:"ldap_dn,omitempty"` + + // API URLs + URL *string `json:"url,omitempty"` + EventsURL *string `json:"events_url,omitempty"` + FollowingURL *string `json:"following_url,omitempty"` + FollowersURL *string `json:"followers_url,omitempty"` + GistsURL *string `json:"gists_url,omitempty"` + OrganizationsURL *string `json:"organizations_url,omitempty"` + ReceivedEventsURL *string `json:"received_events_url,omitempty"` + ReposURL *string `json:"repos_url,omitempty"` + StarredURL *string `json:"starred_url,omitempty"` + SubscriptionsURL *string `json:"subscriptions_url,omitempty"` + + // TextMatches is only populated from search results that request text matches + // See: search.go and https://docs.github.com/rest/search/#text-match-metadata + TextMatches []*TextMatch `json:"text_matches,omitempty"` + + // Permissions and RoleName identify the permissions and role that a user has on a given + // repository. These are only populated when calling Repositories.ListCollaborators. + Permissions map[string]bool `json:"permissions,omitempty"` + RoleName *string `json:"role_name,omitempty"` + + // Assignment identifies how a user was assigned to an organization role. Its + // possible values are: "direct", "indirect", "mixed". This is only populated when + // calling the ListUsersAssignedToOrgRole method. + Assignment *string `json:"assignment,omitempty"` + // InheritedFrom identifies the team that a user inherited their organization role + // from. This is only populated when calling the ListUsersAssignedToOrgRole method. + InheritedFrom *Team `json:"inherited_from,omitempty"` +} + +func (u User) String() string { + return Stringify(u) +} + +// Get fetches a user. Passing the empty string will fetch the authenticated +// user. +// +// GitHub API docs: https://docs.github.com/rest/users/users#get-a-user +// GitHub API docs: https://docs.github.com/rest/users/users#get-the-authenticated-user +// +//meta:operation GET /user +//meta:operation GET /users/{username} +func (s *UsersService) Get(ctx context.Context, user string) (*User, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v", user) + } else { + u = "user" + } + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + uResp := new(User) + resp, err := s.client.Do(ctx, req, uResp) + if err != nil { + return nil, resp, err + } + + return uResp, resp, nil +} + +// GetByID fetches a user. +// +// GitHub API docs: https://docs.github.com/rest/users/users#get-a-user-using-their-id +// +//meta:operation GET /user/{account_id} +func (s *UsersService) GetByID(ctx context.Context, id int64) (*User, *Response, error) { + u := fmt.Sprintf("user/%d", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + user := new(User) + resp, err := s.client.Do(ctx, req, user) + if err != nil { + return nil, resp, err + } + + return user, resp, nil +} + +// Edit the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/users/users#update-the-authenticated-user +// +//meta:operation PATCH /user +func (s *UsersService) Edit(ctx context.Context, user *User) (*User, *Response, error) { + u := "user" + req, err := s.client.NewRequest("PATCH", u, user) + if err != nil { + return nil, nil, err + } + + uResp := new(User) + resp, err := s.client.Do(ctx, req, uResp) + if err != nil { + return nil, resp, err + } + + return uResp, resp, nil +} + +// HovercardOptions specifies optional parameters to the UsersService.GetHovercard +// method. +type HovercardOptions struct { + // SubjectType specifies the additional information to be received about the hovercard. + // Possible values are: organization, repository, issue, pull_request. (Required when using subject_id.) + SubjectType string `url:"subject_type"` + + // SubjectID specifies the ID for the SubjectType. (Required when using subject_type.) + SubjectID string `url:"subject_id"` +} + +// Hovercard represents hovercard information about a user. +type Hovercard struct { + Contexts []*UserContext `json:"contexts,omitempty"` +} + +// UserContext represents the contextual information about user. +type UserContext struct { + Message *string `json:"message,omitempty"` + Octicon *string `json:"octicon,omitempty"` +} + +// GetHovercard fetches contextual information about user. It requires authentication +// via Basic Auth or via OAuth with the repo scope. +// +// GitHub API docs: https://docs.github.com/rest/users/users#get-contextual-information-for-a-user +// +//meta:operation GET /users/{username}/hovercard +func (s *UsersService) GetHovercard(ctx context.Context, user string, opts *HovercardOptions) (*Hovercard, *Response, error) { + u := fmt.Sprintf("users/%v/hovercard", user) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + hc := new(Hovercard) + resp, err := s.client.Do(ctx, req, hc) + if err != nil { + return nil, resp, err + } + + return hc, resp, nil +} + +// UserListOptions specifies optional parameters to the UsersService.ListAll +// method. +type UserListOptions struct { + // ID of the last user seen + Since int64 `url:"since,omitempty"` + + // Note: Pagination is powered exclusively by the Since parameter, + // ListOptions.Page has no effect. + // ListOptions.PerPage controls an undocumented GitHub API parameter. + ListOptions +} + +// ListAll lists all GitHub users. +// +// To paginate through all users, populate 'Since' with the ID of the last user. +// +// GitHub API docs: https://docs.github.com/rest/users/users#list-users +// +//meta:operation GET /users +func (s *UsersService) ListAll(ctx context.Context, opts *UserListOptions) ([]*User, *Response, error) { + u, err := addOptions("users", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var users []*User + resp, err := s.client.Do(ctx, req, &users) + if err != nil { + return nil, resp, err + } + + return users, resp, nil +} + +// ListInvitations lists all currently-open repository invitations for the +// authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/collaborators/invitations#list-repository-invitations-for-the-authenticated-user +// +//meta:operation GET /user/repository_invitations +func (s *UsersService) ListInvitations(ctx context.Context, opts *ListOptions) ([]*RepositoryInvitation, *Response, error) { + u, err := addOptions("user/repository_invitations", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + invites := []*RepositoryInvitation{} + resp, err := s.client.Do(ctx, req, &invites) + if err != nil { + return nil, resp, err + } + + return invites, resp, nil +} + +// AcceptInvitation accepts the currently-open repository invitation for the +// authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/collaborators/invitations#accept-a-repository-invitation +// +//meta:operation PATCH /user/repository_invitations/{invitation_id} +func (s *UsersService) AcceptInvitation(ctx context.Context, invitationID int64) (*Response, error) { + u := fmt.Sprintf("user/repository_invitations/%v", invitationID) + req, err := s.client.NewRequest("PATCH", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeclineInvitation declines the currently-open repository invitation for the +// authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/collaborators/invitations#decline-a-repository-invitation +// +//meta:operation DELETE /user/repository_invitations/{invitation_id} +func (s *UsersService) DeclineInvitation(ctx context.Context, invitationID int64) (*Response, error) { + u := fmt.Sprintf("user/repository_invitations/%v", invitationID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/users_administration.go b/vendor/github.com/google/go-github/v68/github/users_administration.go new file mode 100644 index 0000000000..c0aa3b6493 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/users_administration.go @@ -0,0 +1,80 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// PromoteSiteAdmin promotes a user to a site administrator of a GitHub Enterprise instance. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/users#promote-a-user-to-be-a-site-administrator +// +//meta:operation PUT /users/{username}/site_admin +func (s *UsersService) PromoteSiteAdmin(ctx context.Context, user string) (*Response, error) { + u := fmt.Sprintf("users/%v/site_admin", user) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DemoteSiteAdmin demotes a user from site administrator of a GitHub Enterprise instance. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/users#demote-a-site-administrator +// +//meta:operation DELETE /users/{username}/site_admin +func (s *UsersService) DemoteSiteAdmin(ctx context.Context, user string) (*Response, error) { + u := fmt.Sprintf("users/%v/site_admin", user) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// UserSuspendOptions represents the reason a user is being suspended. +type UserSuspendOptions struct { + Reason *string `json:"reason,omitempty"` +} + +// Suspend a user on a GitHub Enterprise instance. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/users#suspend-a-user +// +//meta:operation PUT /users/{username}/suspended +func (s *UsersService) Suspend(ctx context.Context, user string, opts *UserSuspendOptions) (*Response, error) { + u := fmt.Sprintf("users/%v/suspended", user) + + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Unsuspend a user on a GitHub Enterprise instance. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/users#unsuspend-a-user +// +//meta:operation DELETE /users/{username}/suspended +func (s *UsersService) Unsuspend(ctx context.Context, user string) (*Response, error) { + u := fmt.Sprintf("users/%v/suspended", user) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/users_attestations.go b/vendor/github.com/google/go-github/v68/github/users_attestations.go new file mode 100644 index 0000000000..18f60298d8 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/users_attestations.go @@ -0,0 +1,40 @@ +// Copyright 2024 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListAttestations returns a collection of artifact attestations +// with a given subject digest that are associated with repositories +// owned by a user. +// +// GitHub API docs: https://docs.github.com/rest/users/attestations#list-attestations +// +//meta:operation GET /users/{username}/attestations/{subject_digest} +func (s *UsersService) ListAttestations(ctx context.Context, user, subjectDigest string, opts *ListOptions) (*AttestationsResponse, *Response, error) { + var u = fmt.Sprintf("users/%v/attestations/%v", user, subjectDigest) + + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var attestations *AttestationsResponse + res, err := s.client.Do(ctx, req, &attestations) + if err != nil { + return nil, res, err + } + + return attestations, res, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/users_blocking.go b/vendor/github.com/google/go-github/v68/github/users_blocking.go new file mode 100644 index 0000000000..3f2af38f6c --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/users_blocking.go @@ -0,0 +1,99 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListBlockedUsers lists all the blocked users by the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/users/blocking#list-users-blocked-by-the-authenticated-user +// +//meta:operation GET /user/blocks +func (s *UsersService) ListBlockedUsers(ctx context.Context, opts *ListOptions) ([]*User, *Response, error) { + u := "user/blocks" + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + var blockedUsers []*User + resp, err := s.client.Do(ctx, req, &blockedUsers) + if err != nil { + return nil, resp, err + } + + return blockedUsers, resp, nil +} + +// IsBlocked reports whether specified user is blocked by the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/users/blocking#check-if-a-user-is-blocked-by-the-authenticated-user +// +//meta:operation GET /user/blocks/{username} +func (s *UsersService) IsBlocked(ctx context.Context, user string) (bool, *Response, error) { + u := fmt.Sprintf("user/blocks/%v", user) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + resp, err := s.client.Do(ctx, req, nil) + isBlocked, err := parseBoolResponse(err) + return isBlocked, resp, err +} + +// BlockUser blocks specified user for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/users/blocking#block-a-user +// +//meta:operation PUT /user/blocks/{username} +func (s *UsersService) BlockUser(ctx context.Context, user string) (*Response, error) { + u := fmt.Sprintf("user/blocks/%v", user) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + return s.client.Do(ctx, req, nil) +} + +// UnblockUser unblocks specified user for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/users/blocking#unblock-a-user +// +//meta:operation DELETE /user/blocks/{username} +func (s *UsersService) UnblockUser(ctx context.Context, user string) (*Response, error) { + u := fmt.Sprintf("user/blocks/%v", user) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/users_emails.go b/vendor/github.com/google/go-github/v68/github/users_emails.go new file mode 100644 index 0000000000..3d0e1bfaaf --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/users_emails.go @@ -0,0 +1,105 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import "context" + +// UserEmail represents user's email address. +type UserEmail struct { + Email *string `json:"email,omitempty"` + Primary *bool `json:"primary,omitempty"` + Verified *bool `json:"verified,omitempty"` + Visibility *string `json:"visibility,omitempty"` +} + +// ListEmails lists all email addresses for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/users/emails#list-email-addresses-for-the-authenticated-user +// +//meta:operation GET /user/emails +func (s *UsersService) ListEmails(ctx context.Context, opts *ListOptions) ([]*UserEmail, *Response, error) { + u := "user/emails" + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var emails []*UserEmail + resp, err := s.client.Do(ctx, req, &emails) + if err != nil { + return nil, resp, err + } + + return emails, resp, nil +} + +// AddEmails adds email addresses of the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/users/emails#add-an-email-address-for-the-authenticated-user +// +//meta:operation POST /user/emails +func (s *UsersService) AddEmails(ctx context.Context, emails []string) ([]*UserEmail, *Response, error) { + u := "user/emails" + req, err := s.client.NewRequest("POST", u, emails) + if err != nil { + return nil, nil, err + } + + var e []*UserEmail + resp, err := s.client.Do(ctx, req, &e) + if err != nil { + return nil, resp, err + } + + return e, resp, nil +} + +// DeleteEmails deletes email addresses from authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/users/emails#delete-an-email-address-for-the-authenticated-user +// +//meta:operation DELETE /user/emails +func (s *UsersService) DeleteEmails(ctx context.Context, emails []string) (*Response, error) { + u := "user/emails" + req, err := s.client.NewRequest("DELETE", u, emails) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// SetEmailVisibility sets the visibility for the primary email address of the authenticated user. +// `visibility` can be "private" or "public". +// +// GitHub API docs: https://docs.github.com/rest/users/emails#set-primary-email-visibility-for-the-authenticated-user +// +//meta:operation PATCH /user/email/visibility +func (s *UsersService) SetEmailVisibility(ctx context.Context, visibility string) ([]*UserEmail, *Response, error) { + u := "user/email/visibility" + + updateVisibilityReq := &UserEmail{ + Visibility: &visibility, + } + + req, err := s.client.NewRequest("PATCH", u, updateVisibilityReq) + if err != nil { + return nil, nil, err + } + + var e []*UserEmail + resp, err := s.client.Do(ctx, req, &e) + if err != nil { + return nil, resp, err + } + + return e, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/users_followers.go b/vendor/github.com/google/go-github/v68/github/users_followers.go new file mode 100644 index 0000000000..ec6f531eaa --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/users_followers.go @@ -0,0 +1,135 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListFollowers lists the followers for a user. Passing the empty string will +// fetch followers for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/users/followers#list-followers-of-a-user +// GitHub API docs: https://docs.github.com/rest/users/followers#list-followers-of-the-authenticated-user +// +//meta:operation GET /user/followers +//meta:operation GET /users/{username}/followers +func (s *UsersService) ListFollowers(ctx context.Context, user string, opts *ListOptions) ([]*User, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/followers", user) + } else { + u = "user/followers" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var users []*User + resp, err := s.client.Do(ctx, req, &users) + if err != nil { + return nil, resp, err + } + + return users, resp, nil +} + +// ListFollowing lists the people that a user is following. Passing the empty +// string will list people the authenticated user is following. +// +// GitHub API docs: https://docs.github.com/rest/users/followers#list-the-people-a-user-follows +// GitHub API docs: https://docs.github.com/rest/users/followers#list-the-people-the-authenticated-user-follows +// +//meta:operation GET /user/following +//meta:operation GET /users/{username}/following +func (s *UsersService) ListFollowing(ctx context.Context, user string, opts *ListOptions) ([]*User, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/following", user) + } else { + u = "user/following" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var users []*User + resp, err := s.client.Do(ctx, req, &users) + if err != nil { + return nil, resp, err + } + + return users, resp, nil +} + +// IsFollowing checks if "user" is following "target". Passing the empty +// string for "user" will check if the authenticated user is following "target". +// +// GitHub API docs: https://docs.github.com/rest/users/followers#check-if-a-person-is-followed-by-the-authenticated-user +// GitHub API docs: https://docs.github.com/rest/users/followers#check-if-a-user-follows-another-user +// +//meta:operation GET /user/following/{username} +//meta:operation GET /users/{username}/following/{target_user} +func (s *UsersService) IsFollowing(ctx context.Context, user, target string) (bool, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/following/%v", user, target) + } else { + u = fmt.Sprintf("user/following/%v", target) + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + following, err := parseBoolResponse(err) + return following, resp, err +} + +// Follow will cause the authenticated user to follow the specified user. +// +// GitHub API docs: https://docs.github.com/rest/users/followers#follow-a-user +// +//meta:operation PUT /user/following/{username} +func (s *UsersService) Follow(ctx context.Context, user string) (*Response, error) { + u := fmt.Sprintf("user/following/%v", user) + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Unfollow will cause the authenticated user to unfollow the specified user. +// +// GitHub API docs: https://docs.github.com/rest/users/followers#unfollow-a-user +// +//meta:operation DELETE /user/following/{username} +func (s *UsersService) Unfollow(ctx context.Context, user string) (*Response, error) { + u := fmt.Sprintf("user/following/%v", user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/users_gpg_keys.go b/vendor/github.com/google/go-github/v68/github/users_gpg_keys.go new file mode 100644 index 0000000000..2f296a1ef6 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/users_gpg_keys.go @@ -0,0 +1,138 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GPGKey represents a GitHub user's public GPG key used to verify GPG signed commits and tags. +// +// https://developer.github.com/changes/2016-04-04-git-signing-api-preview/ +type GPGKey struct { + ID *int64 `json:"id,omitempty"` + PrimaryKeyID *int64 `json:"primary_key_id,omitempty"` + KeyID *string `json:"key_id,omitempty"` + RawKey *string `json:"raw_key,omitempty"` + PublicKey *string `json:"public_key,omitempty"` + Emails []*GPGEmail `json:"emails,omitempty"` + Subkeys []*GPGKey `json:"subkeys,omitempty"` + CanSign *bool `json:"can_sign,omitempty"` + CanEncryptComms *bool `json:"can_encrypt_comms,omitempty"` + CanEncryptStorage *bool `json:"can_encrypt_storage,omitempty"` + CanCertify *bool `json:"can_certify,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + ExpiresAt *Timestamp `json:"expires_at,omitempty"` +} + +// String stringifies a GPGKey. +func (k GPGKey) String() string { + return Stringify(k) +} + +// GPGEmail represents an email address associated to a GPG key. +type GPGEmail struct { + Email *string `json:"email,omitempty"` + Verified *bool `json:"verified,omitempty"` +} + +// ListGPGKeys lists the public GPG keys for a user. Passing the empty +// string will fetch keys for the authenticated user. It requires authentication +// via Basic Auth or via OAuth with at least read:gpg_key scope. +// +// GitHub API docs: https://docs.github.com/rest/users/gpg-keys#list-gpg-keys-for-a-user +// GitHub API docs: https://docs.github.com/rest/users/gpg-keys#list-gpg-keys-for-the-authenticated-user +// +//meta:operation GET /user/gpg_keys +//meta:operation GET /users/{username}/gpg_keys +func (s *UsersService) ListGPGKeys(ctx context.Context, user string, opts *ListOptions) ([]*GPGKey, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/gpg_keys", user) + } else { + u = "user/gpg_keys" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var keys []*GPGKey + resp, err := s.client.Do(ctx, req, &keys) + if err != nil { + return nil, resp, err + } + + return keys, resp, nil +} + +// GetGPGKey gets extended details for a single GPG key. It requires authentication +// via Basic Auth or via OAuth with at least read:gpg_key scope. +// +// GitHub API docs: https://docs.github.com/rest/users/gpg-keys#get-a-gpg-key-for-the-authenticated-user +// +//meta:operation GET /user/gpg_keys/{gpg_key_id} +func (s *UsersService) GetGPGKey(ctx context.Context, id int64) (*GPGKey, *Response, error) { + u := fmt.Sprintf("user/gpg_keys/%v", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + key := &GPGKey{} + resp, err := s.client.Do(ctx, req, key) + if err != nil { + return nil, resp, err + } + + return key, resp, nil +} + +// CreateGPGKey creates a GPG key. It requires authentication via Basic Auth +// or OAuth with at least write:gpg_key scope. +// +// GitHub API docs: https://docs.github.com/rest/users/gpg-keys#create-a-gpg-key-for-the-authenticated-user +// +//meta:operation POST /user/gpg_keys +func (s *UsersService) CreateGPGKey(ctx context.Context, armoredPublicKey string) (*GPGKey, *Response, error) { + gpgKey := &struct { + ArmoredPublicKey string `json:"armored_public_key"` + }{ArmoredPublicKey: armoredPublicKey} + req, err := s.client.NewRequest("POST", "user/gpg_keys", gpgKey) + if err != nil { + return nil, nil, err + } + + key := &GPGKey{} + resp, err := s.client.Do(ctx, req, key) + if err != nil { + return nil, resp, err + } + + return key, resp, nil +} + +// DeleteGPGKey deletes a GPG key. It requires authentication via Basic Auth or +// via OAuth with at least admin:gpg_key scope. +// +// GitHub API docs: https://docs.github.com/rest/users/gpg-keys#delete-a-gpg-key-for-the-authenticated-user +// +//meta:operation DELETE /user/gpg_keys/{gpg_key_id} +func (s *UsersService) DeleteGPGKey(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("user/gpg_keys/%v", id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/users_keys.go b/vendor/github.com/google/go-github/v68/github/users_keys.go new file mode 100644 index 0000000000..4d42986ed2 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/users_keys.go @@ -0,0 +1,122 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Key represents a public SSH key used to authenticate a user or deploy script. +type Key struct { + ID *int64 `json:"id,omitempty"` + Key *string `json:"key,omitempty"` + URL *string `json:"url,omitempty"` + Title *string `json:"title,omitempty"` + ReadOnly *bool `json:"read_only,omitempty"` + Verified *bool `json:"verified,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + AddedBy *string `json:"added_by,omitempty"` + LastUsed *Timestamp `json:"last_used,omitempty"` +} + +func (k Key) String() string { + return Stringify(k) +} + +// ListKeys lists the verified public keys for a user. Passing the empty +// string will fetch keys for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/users/keys#list-public-keys-for-a-user +// GitHub API docs: https://docs.github.com/rest/users/keys#list-public-ssh-keys-for-the-authenticated-user +// +//meta:operation GET /user/keys +//meta:operation GET /users/{username}/keys +func (s *UsersService) ListKeys(ctx context.Context, user string, opts *ListOptions) ([]*Key, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/keys", user) + } else { + u = "user/keys" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var keys []*Key + resp, err := s.client.Do(ctx, req, &keys) + if err != nil { + return nil, resp, err + } + + return keys, resp, nil +} + +// GetKey fetches a single public key. +// +// GitHub API docs: https://docs.github.com/rest/users/keys#get-a-public-ssh-key-for-the-authenticated-user +// +//meta:operation GET /user/keys/{key_id} +func (s *UsersService) GetKey(ctx context.Context, id int64) (*Key, *Response, error) { + u := fmt.Sprintf("user/keys/%v", id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + key := new(Key) + resp, err := s.client.Do(ctx, req, key) + if err != nil { + return nil, resp, err + } + + return key, resp, nil +} + +// CreateKey adds a public key for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/users/keys#create-a-public-ssh-key-for-the-authenticated-user +// +//meta:operation POST /user/keys +func (s *UsersService) CreateKey(ctx context.Context, key *Key) (*Key, *Response, error) { + u := "user/keys" + + req, err := s.client.NewRequest("POST", u, key) + if err != nil { + return nil, nil, err + } + + k := new(Key) + resp, err := s.client.Do(ctx, req, k) + if err != nil { + return nil, resp, err + } + + return k, resp, nil +} + +// DeleteKey deletes a public key. +// +// GitHub API docs: https://docs.github.com/rest/users/keys#delete-a-public-ssh-key-for-the-authenticated-user +// +//meta:operation DELETE /user/keys/{key_id} +func (s *UsersService) DeleteKey(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("user/keys/%v", id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/users_packages.go b/vendor/github.com/google/go-github/v68/github/users_packages.go new file mode 100644 index 0000000000..3ccf68a169 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/users_packages.go @@ -0,0 +1,235 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListPackages lists the packages for a user. Passing the empty string for "user" will +// list packages for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#list-packages-for-a-user +// GitHub API docs: https://docs.github.com/rest/packages/packages#list-packages-for-the-authenticated-users-namespace +// +//meta:operation GET /user/packages +//meta:operation GET /users/{username}/packages +func (s *UsersService) ListPackages(ctx context.Context, user string, opts *PackageListOptions) ([]*Package, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages", user) + } else { + u = "user/packages" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var packages []*Package + resp, err := s.client.Do(ctx, req, &packages) + if err != nil { + return nil, resp, err + } + + return packages, resp, nil +} + +// GetPackage gets a package by name for a user. Passing the empty string for "user" will +// get the package for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#get-a-package-for-a-user +// GitHub API docs: https://docs.github.com/rest/packages/packages#get-a-package-for-the-authenticated-user +// +//meta:operation GET /user/packages/{package_type}/{package_name} +//meta:operation GET /users/{username}/packages/{package_type}/{package_name} +func (s *UsersService) GetPackage(ctx context.Context, user, packageType, packageName string) (*Package, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages/%v/%v", user, packageType, packageName) + } else { + u = fmt.Sprintf("user/packages/%v/%v", packageType, packageName) + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pack *Package + resp, err := s.client.Do(ctx, req, &pack) + if err != nil { + return nil, resp, err + } + + return pack, resp, nil +} + +// DeletePackage deletes a package from a user. Passing the empty string for "user" will +// delete the package for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#delete-a-package-for-a-user +// GitHub API docs: https://docs.github.com/rest/packages/packages#delete-a-package-for-the-authenticated-user +// +//meta:operation DELETE /user/packages/{package_type}/{package_name} +//meta:operation DELETE /users/{username}/packages/{package_type}/{package_name} +func (s *UsersService) DeletePackage(ctx context.Context, user, packageType, packageName string) (*Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages/%v/%v", user, packageType, packageName) + } else { + u = fmt.Sprintf("user/packages/%v/%v", packageType, packageName) + } + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RestorePackage restores a package to a user. Passing the empty string for "user" will +// restore the package for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#restore-a-package-for-a-user +// GitHub API docs: https://docs.github.com/rest/packages/packages#restore-a-package-for-the-authenticated-user +// +//meta:operation POST /user/packages/{package_type}/{package_name}/restore +//meta:operation POST /users/{username}/packages/{package_type}/{package_name}/restore +func (s *UsersService) RestorePackage(ctx context.Context, user, packageType, packageName string) (*Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages/%v/%v/restore", user, packageType, packageName) + } else { + u = fmt.Sprintf("user/packages/%v/%v/restore", packageType, packageName) + } + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// PackageGetAllVersions gets all versions of a package for a user. Passing the empty string for "user" will +// get versions for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#list-package-versions-for-a-package-owned-by-a-user +// GitHub API docs: https://docs.github.com/rest/packages/packages#list-package-versions-for-a-package-owned-by-the-authenticated-user +// +//meta:operation GET /user/packages/{package_type}/{package_name}/versions +//meta:operation GET /users/{username}/packages/{package_type}/{package_name}/versions +func (s *UsersService) PackageGetAllVersions(ctx context.Context, user, packageType, packageName string, opts *PackageListOptions) ([]*PackageVersion, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages/%v/%v/versions", user, packageType, packageName) + } else { + u = fmt.Sprintf("user/packages/%v/%v/versions", packageType, packageName) + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var versions []*PackageVersion + resp, err := s.client.Do(ctx, req, &versions) + if err != nil { + return nil, resp, err + } + + return versions, resp, nil +} + +// PackageGetVersion gets a specific version of a package for a user. Passing the empty string for "user" will +// get the version for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#get-a-package-version-for-a-user +// GitHub API docs: https://docs.github.com/rest/packages/packages#get-a-package-version-for-the-authenticated-user +// +//meta:operation GET /user/packages/{package_type}/{package_name}/versions/{package_version_id} +//meta:operation GET /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id} +func (s *UsersService) PackageGetVersion(ctx context.Context, user, packageType, packageName string, packageVersionID int64) (*PackageVersion, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages/%v/%v/versions/%v", user, packageType, packageName, packageVersionID) + } else { + u = fmt.Sprintf("user/packages/%v/%v/versions/%v", packageType, packageName, packageVersionID) + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var version *PackageVersion + resp, err := s.client.Do(ctx, req, &version) + if err != nil { + return nil, resp, err + } + + return version, resp, nil +} + +// PackageDeleteVersion deletes a package version for a user. Passing the empty string for "user" will +// delete the version for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#delete-a-package-version-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/rest/packages/packages#delete-package-version-for-a-user +// +//meta:operation DELETE /user/packages/{package_type}/{package_name}/versions/{package_version_id} +//meta:operation DELETE /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id} +func (s *UsersService) PackageDeleteVersion(ctx context.Context, user, packageType, packageName string, packageVersionID int64) (*Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages/%v/%v/versions/%v", user, packageType, packageName, packageVersionID) + } else { + u = fmt.Sprintf("user/packages/%v/%v/versions/%v", packageType, packageName, packageVersionID) + } + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// PackageRestoreVersion restores a package version to a user. Passing the empty string for "user" will +// restore the version for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#restore-a-package-version-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/rest/packages/packages#restore-package-version-for-a-user +// +//meta:operation POST /user/packages/{package_type}/{package_name}/versions/{package_version_id}/restore +//meta:operation POST /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}/restore +func (s *UsersService) PackageRestoreVersion(ctx context.Context, user, packageType, packageName string, packageVersionID int64) (*Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages/%v/%v/versions/%v/restore", user, packageType, packageName, packageVersionID) + } else { + u = fmt.Sprintf("user/packages/%v/%v/versions/%v/restore", packageType, packageName, packageVersionID) + } + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/users_ssh_signing_keys.go b/vendor/github.com/google/go-github/v68/github/users_ssh_signing_keys.go new file mode 100644 index 0000000000..fcc930be62 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/users_ssh_signing_keys.go @@ -0,0 +1,117 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// SSHSigningKey represents a public SSH key used to sign git commits. +type SSHSigningKey struct { + ID *int64 `json:"id,omitempty"` + Key *string `json:"key,omitempty"` + Title *string `json:"title,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` +} + +func (k SSHSigningKey) String() string { + return Stringify(k) +} + +// ListSSHSigningKeys lists the SSH signing keys for a user. Passing an empty +// username string will fetch SSH signing keys for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/users/ssh-signing-keys#list-ssh-signing-keys-for-a-user +// GitHub API docs: https://docs.github.com/rest/users/ssh-signing-keys#list-ssh-signing-keys-for-the-authenticated-user +// +//meta:operation GET /user/ssh_signing_keys +//meta:operation GET /users/{username}/ssh_signing_keys +func (s *UsersService) ListSSHSigningKeys(ctx context.Context, user string, opts *ListOptions) ([]*SSHSigningKey, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/ssh_signing_keys", user) + } else { + u = "user/ssh_signing_keys" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var keys []*SSHSigningKey + resp, err := s.client.Do(ctx, req, &keys) + if err != nil { + return nil, resp, err + } + + return keys, resp, nil +} + +// GetSSHSigningKey fetches a single SSH signing key for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/users/ssh-signing-keys#get-an-ssh-signing-key-for-the-authenticated-user +// +//meta:operation GET /user/ssh_signing_keys/{ssh_signing_key_id} +func (s *UsersService) GetSSHSigningKey(ctx context.Context, id int64) (*SSHSigningKey, *Response, error) { + u := fmt.Sprintf("user/ssh_signing_keys/%v", id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + key := new(SSHSigningKey) + resp, err := s.client.Do(ctx, req, key) + if err != nil { + return nil, resp, err + } + + return key, resp, nil +} + +// CreateSSHSigningKey adds a SSH signing key for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/users/ssh-signing-keys#create-a-ssh-signing-key-for-the-authenticated-user +// +//meta:operation POST /user/ssh_signing_keys +func (s *UsersService) CreateSSHSigningKey(ctx context.Context, key *Key) (*SSHSigningKey, *Response, error) { + u := "user/ssh_signing_keys" + + req, err := s.client.NewRequest("POST", u, key) + if err != nil { + return nil, nil, err + } + + k := new(SSHSigningKey) + resp, err := s.client.Do(ctx, req, k) + if err != nil { + return nil, resp, err + } + + return k, resp, nil +} + +// DeleteSSHSigningKey deletes a SSH signing key for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/users/ssh-signing-keys#delete-an-ssh-signing-key-for-the-authenticated-user +// +//meta:operation DELETE /user/ssh_signing_keys/{ssh_signing_key_id} +func (s *UsersService) DeleteSSHSigningKey(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("user/ssh_signing_keys/%v", id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/with_appengine.go b/vendor/github.com/google/go-github/v68/github/with_appengine.go new file mode 100644 index 0000000000..9bb95b8c89 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/with_appengine.go @@ -0,0 +1,20 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build appengine + +// This file provides glue for making github work on App Engine. + +package github + +import ( + "context" + "net/http" +) + +func withContext(ctx context.Context, req *http.Request) *http.Request { + // No-op because App Engine adds context to a request differently. + return req +} diff --git a/vendor/github.com/google/go-github/v68/github/without_appengine.go b/vendor/github.com/google/go-github/v68/github/without_appengine.go new file mode 100644 index 0000000000..bfdb18ecbb --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/without_appengine.go @@ -0,0 +1,19 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !appengine + +// This file provides glue for making github work without App Engine. + +package github + +import ( + "context" + "net/http" +) + +func withContext(ctx context.Context, req *http.Request) *http.Request { + return req.WithContext(ctx) +} diff --git a/vendor/github.com/google/go-querystring/LICENSE b/vendor/github.com/google/go-querystring/LICENSE new file mode 100644 index 0000000000..ae121a1e46 --- /dev/null +++ b/vendor/github.com/google/go-querystring/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013 Google. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/google/go-querystring/query/encode.go b/vendor/github.com/google/go-querystring/query/encode.go new file mode 100644 index 0000000000..91198f819a --- /dev/null +++ b/vendor/github.com/google/go-querystring/query/encode.go @@ -0,0 +1,357 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package query implements encoding of structs into URL query parameters. +// +// As a simple example: +// +// type Options struct { +// Query string `url:"q"` +// ShowAll bool `url:"all"` +// Page int `url:"page"` +// } +// +// opt := Options{ "foo", true, 2 } +// v, _ := query.Values(opt) +// fmt.Print(v.Encode()) // will output: "q=foo&all=true&page=2" +// +// The exact mapping between Go values and url.Values is described in the +// documentation for the Values() function. +package query + +import ( + "bytes" + "fmt" + "net/url" + "reflect" + "strconv" + "strings" + "time" +) + +var timeType = reflect.TypeOf(time.Time{}) + +var encoderType = reflect.TypeOf(new(Encoder)).Elem() + +// Encoder is an interface implemented by any type that wishes to encode +// itself into URL values in a non-standard way. +type Encoder interface { + EncodeValues(key string, v *url.Values) error +} + +// Values returns the url.Values encoding of v. +// +// Values expects to be passed a struct, and traverses it recursively using the +// following encoding rules. +// +// Each exported struct field is encoded as a URL parameter unless +// +// - the field's tag is "-", or +// - the field is empty and its tag specifies the "omitempty" option +// +// The empty values are false, 0, any nil pointer or interface value, any array +// slice, map, or string of length zero, and any type (such as time.Time) that +// returns true for IsZero(). +// +// The URL parameter name defaults to the struct field name but can be +// specified in the struct field's tag value. The "url" key in the struct +// field's tag value is the key name, followed by an optional comma and +// options. For example: +// +// // Field is ignored by this package. +// Field int `url:"-"` +// +// // Field appears as URL parameter "myName". +// Field int `url:"myName"` +// +// // Field appears as URL parameter "myName" and the field is omitted if +// // its value is empty +// Field int `url:"myName,omitempty"` +// +// // Field appears as URL parameter "Field" (the default), but the field +// // is skipped if empty. Note the leading comma. +// Field int `url:",omitempty"` +// +// For encoding individual field values, the following type-dependent rules +// apply: +// +// Boolean values default to encoding as the strings "true" or "false". +// Including the "int" option signals that the field should be encoded as the +// strings "1" or "0". +// +// time.Time values default to encoding as RFC3339 timestamps. Including the +// "unix" option signals that the field should be encoded as a Unix time (see +// time.Unix()). The "unixmilli" and "unixnano" options will encode the number +// of milliseconds and nanoseconds, respectively, since January 1, 1970 (see +// time.UnixNano()). Including the "layout" struct tag (separate from the +// "url" tag) will use the value of the "layout" tag as a layout passed to +// time.Format. For example: +// +// // Encode a time.Time as YYYY-MM-DD +// Field time.Time `layout:"2006-01-02"` +// +// Slice and Array values default to encoding as multiple URL values of the +// same name. Including the "comma" option signals that the field should be +// encoded as a single comma-delimited value. Including the "space" option +// similarly encodes the value as a single space-delimited string. Including +// the "semicolon" option will encode the value as a semicolon-delimited string. +// Including the "brackets" option signals that the multiple URL values should +// have "[]" appended to the value name. "numbered" will append a number to +// the end of each incidence of the value name, example: +// name0=value0&name1=value1, etc. Including the "del" struct tag (separate +// from the "url" tag) will use the value of the "del" tag as the delimiter. +// For example: +// +// // Encode a slice of bools as ints ("1" for true, "0" for false), +// // separated by exclamation points "!". +// Field []bool `url:",int" del:"!"` +// +// Anonymous struct fields are usually encoded as if their inner exported +// fields were fields in the outer struct, subject to the standard Go +// visibility rules. An anonymous struct field with a name given in its URL +// tag is treated as having that name, rather than being anonymous. +// +// Non-nil pointer values are encoded as the value pointed to. +// +// Nested structs are encoded including parent fields in value names for +// scoping. e.g: +// +// "user[name]=acme&user[addr][postcode]=1234&user[addr][city]=SFO" +// +// All other values are encoded using their default string representation. +// +// Multiple fields that encode to the same URL parameter name will be included +// as multiple URL values of the same name. +func Values(v interface{}) (url.Values, error) { + values := make(url.Values) + val := reflect.ValueOf(v) + for val.Kind() == reflect.Ptr { + if val.IsNil() { + return values, nil + } + val = val.Elem() + } + + if v == nil { + return values, nil + } + + if val.Kind() != reflect.Struct { + return nil, fmt.Errorf("query: Values() expects struct input. Got %v", val.Kind()) + } + + err := reflectValue(values, val, "") + return values, err +} + +// reflectValue populates the values parameter from the struct fields in val. +// Embedded structs are followed recursively (using the rules defined in the +// Values function documentation) breadth-first. +func reflectValue(values url.Values, val reflect.Value, scope string) error { + var embedded []reflect.Value + + typ := val.Type() + for i := 0; i < typ.NumField(); i++ { + sf := typ.Field(i) + if sf.PkgPath != "" && !sf.Anonymous { // unexported + continue + } + + sv := val.Field(i) + tag := sf.Tag.Get("url") + if tag == "-" { + continue + } + name, opts := parseTag(tag) + + if name == "" { + if sf.Anonymous { + v := reflect.Indirect(sv) + if v.IsValid() && v.Kind() == reflect.Struct { + // save embedded struct for later processing + embedded = append(embedded, v) + continue + } + } + + name = sf.Name + } + + if scope != "" { + name = scope + "[" + name + "]" + } + + if opts.Contains("omitempty") && isEmptyValue(sv) { + continue + } + + if sv.Type().Implements(encoderType) { + // if sv is a nil pointer and the custom encoder is defined on a non-pointer + // method receiver, set sv to the zero value of the underlying type + if !reflect.Indirect(sv).IsValid() && sv.Type().Elem().Implements(encoderType) { + sv = reflect.New(sv.Type().Elem()) + } + + m := sv.Interface().(Encoder) + if err := m.EncodeValues(name, &values); err != nil { + return err + } + continue + } + + // recursively dereference pointers. break on nil pointers + for sv.Kind() == reflect.Ptr { + if sv.IsNil() { + break + } + sv = sv.Elem() + } + + if sv.Kind() == reflect.Slice || sv.Kind() == reflect.Array { + var del string + if opts.Contains("comma") { + del = "," + } else if opts.Contains("space") { + del = " " + } else if opts.Contains("semicolon") { + del = ";" + } else if opts.Contains("brackets") { + name = name + "[]" + } else { + del = sf.Tag.Get("del") + } + + if del != "" { + s := new(bytes.Buffer) + first := true + for i := 0; i < sv.Len(); i++ { + if first { + first = false + } else { + s.WriteString(del) + } + s.WriteString(valueString(sv.Index(i), opts, sf)) + } + values.Add(name, s.String()) + } else { + for i := 0; i < sv.Len(); i++ { + k := name + if opts.Contains("numbered") { + k = fmt.Sprintf("%s%d", name, i) + } + values.Add(k, valueString(sv.Index(i), opts, sf)) + } + } + continue + } + + if sv.Type() == timeType { + values.Add(name, valueString(sv, opts, sf)) + continue + } + + if sv.Kind() == reflect.Struct { + if err := reflectValue(values, sv, name); err != nil { + return err + } + continue + } + + values.Add(name, valueString(sv, opts, sf)) + } + + for _, f := range embedded { + if err := reflectValue(values, f, scope); err != nil { + return err + } + } + + return nil +} + +// valueString returns the string representation of a value. +func valueString(v reflect.Value, opts tagOptions, sf reflect.StructField) string { + for v.Kind() == reflect.Ptr { + if v.IsNil() { + return "" + } + v = v.Elem() + } + + if v.Kind() == reflect.Bool && opts.Contains("int") { + if v.Bool() { + return "1" + } + return "0" + } + + if v.Type() == timeType { + t := v.Interface().(time.Time) + if opts.Contains("unix") { + return strconv.FormatInt(t.Unix(), 10) + } + if opts.Contains("unixmilli") { + return strconv.FormatInt((t.UnixNano() / 1e6), 10) + } + if opts.Contains("unixnano") { + return strconv.FormatInt(t.UnixNano(), 10) + } + if layout := sf.Tag.Get("layout"); layout != "" { + return t.Format(layout) + } + return t.Format(time.RFC3339) + } + + return fmt.Sprint(v.Interface()) +} + +// isEmptyValue checks if a value should be considered empty for the purposes +// of omitting fields with the "omitempty" option. +func isEmptyValue(v reflect.Value) bool { + switch v.Kind() { + case reflect.Array, reflect.Map, reflect.Slice, reflect.String: + return v.Len() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Interface, reflect.Ptr: + return v.IsNil() + } + + type zeroable interface { + IsZero() bool + } + + if z, ok := v.Interface().(zeroable); ok { + return z.IsZero() + } + + return false +} + +// tagOptions is the string following a comma in a struct field's "url" tag, or +// the empty string. It does not include the leading comma. +type tagOptions []string + +// parseTag splits a struct field's url tag into its name and comma-separated +// options. +func parseTag(tag string) (string, tagOptions) { + s := strings.Split(tag, ",") + return s[0], s[1:] +} + +// Contains checks whether the tagOptions contains the specified option. +func (o tagOptions) Contains(option string) bool { + for _, s := range o { + if s == option { + return true + } + } + return false +} diff --git a/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go b/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go index f1c495dd60..a21ed4ec1f 100644 --- a/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go +++ b/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go @@ -38,7 +38,7 @@ type EncoderOption func(*encoderOption) // WithCreatedLines is an EncoderOption that configures the OpenMetrics encoder // to include _created lines (See -// https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#counter-1). +// https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#counter-1). // Created timestamps can improve the accuracy of series reset detection, but // come with a bandwidth cost. // @@ -102,7 +102,7 @@ func WithUnit() EncoderOption { // // - According to the OM specs, the `# UNIT` line is optional, but if populated, // the unit has to be present in the metric name as its suffix: -// (see https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#unit). +// (see https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#unit). // However, in order to accommodate any potential scenario where such a change in the // metric name is not desirable, the users are here given the choice of either explicitly // opt in, in case they wish for the unit to be included in the output AND in the metric name diff --git a/vendor/github.com/prometheus/common/model/metric.go b/vendor/github.com/prometheus/common/model/metric.go index 0daca836af..5766107cf9 100644 --- a/vendor/github.com/prometheus/common/model/metric.go +++ b/vendor/github.com/prometheus/common/model/metric.go @@ -28,13 +28,13 @@ import ( var ( // NameValidationScheme determines the method of name validation to be used by - // all calls to IsValidMetricName() and LabelName IsValid(). Setting UTF-8 mode - // in isolation from other components that don't support UTF-8 may result in - // bugs or other undefined behavior. This value is intended to be set by - // UTF-8-aware binaries as part of their startup. To avoid need for locking, - // this value should be set once, ideally in an init(), before multiple - // goroutines are started. - NameValidationScheme = LegacyValidation + // all calls to IsValidMetricName() and LabelName IsValid(). Setting UTF-8 + // mode in isolation from other components that don't support UTF-8 may result + // in bugs or other undefined behavior. This value can be set to + // LegacyValidation during startup if a binary is not UTF-8-aware binaries. To + // avoid need for locking, this value should be set once, ideally in an + // init(), before multiple goroutines are started. + NameValidationScheme = UTF8Validation // NameEscapingScheme defines the default way that names will be escaped when // presented to systems that do not support UTF-8 names. If the Content-Type diff --git a/vendor/github.com/spf13/afero/.editorconfig b/vendor/github.com/spf13/afero/.editorconfig new file mode 100644 index 0000000000..4492e9f9fe --- /dev/null +++ b/vendor/github.com/spf13/afero/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.go] +indent_style = tab diff --git a/vendor/github.com/spf13/afero/.golangci.yaml b/vendor/github.com/spf13/afero/.golangci.yaml new file mode 100644 index 0000000000..806289a250 --- /dev/null +++ b/vendor/github.com/spf13/afero/.golangci.yaml @@ -0,0 +1,18 @@ +linters-settings: + gci: + sections: + - standard + - default + - prefix(github.com/spf13/afero) + +linters: + disable-all: true + enable: + - gci + - gofmt + - gofumpt + - staticcheck + +issues: + exclude-dirs: + - gcsfs/internal/stiface diff --git a/vendor/github.com/spf13/afero/README.md b/vendor/github.com/spf13/afero/README.md index 3bafbfdfca..619af574f3 100644 --- a/vendor/github.com/spf13/afero/README.md +++ b/vendor/github.com/spf13/afero/README.md @@ -12,7 +12,7 @@ types and methods. Afero has an exceptionally clean interface and simple design without needless constructors or initialization methods. Afero is also a library providing a base set of interoperable backend -filesystems that make it easy to work with afero while retaining all the power +filesystems that make it easy to work with, while retaining all the power and benefit of the os and ioutil packages. Afero provides significant improvements over using the os package alone, most diff --git a/vendor/github.com/spf13/afero/iofs.go b/vendor/github.com/spf13/afero/iofs.go index 938b9316e6..b13155ca4a 100644 --- a/vendor/github.com/spf13/afero/iofs.go +++ b/vendor/github.com/spf13/afero/iofs.go @@ -255,7 +255,6 @@ func (f fromIOFSFile) Readdir(count int) ([]os.FileInfo, error) { ret := make([]os.FileInfo, len(entries)) for i := range entries { ret[i], err = entries[i].Info() - if err != nil { return nil, err } diff --git a/vendor/github.com/spf13/afero/memmap.go b/vendor/github.com/spf13/afero/memmap.go index d6c744e8d5..ed92f5649d 100644 --- a/vendor/github.com/spf13/afero/memmap.go +++ b/vendor/github.com/spf13/afero/memmap.go @@ -16,11 +16,9 @@ package afero import ( "fmt" "io" - "log" "os" "path/filepath" - "sort" "strings" "sync" diff --git a/vendor/github.com/spf13/pflag/.editorconfig b/vendor/github.com/spf13/pflag/.editorconfig new file mode 100644 index 0000000000..4492e9f9fe --- /dev/null +++ b/vendor/github.com/spf13/pflag/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.go] +indent_style = tab diff --git a/vendor/github.com/spf13/pflag/.golangci.yaml b/vendor/github.com/spf13/pflag/.golangci.yaml new file mode 100644 index 0000000000..b274f24845 --- /dev/null +++ b/vendor/github.com/spf13/pflag/.golangci.yaml @@ -0,0 +1,4 @@ +linters: + disable-all: true + enable: + - nolintlint diff --git a/vendor/github.com/vishvananda/netlink/addr_linux.go b/vendor/github.com/vishvananda/netlink/addr_linux.go index 9b49baf976..01c2306cb2 100644 --- a/vendor/github.com/vishvananda/netlink/addr_linux.go +++ b/vendor/github.com/vishvananda/netlink/addr_linux.go @@ -18,6 +18,7 @@ import ( // // If `addr` is an IPv4 address and the broadcast address is not given, it // will be automatically computed based on the IP mask if /30 or larger. +// If `net.IPv4zero` is given as the broadcast address, broadcast is disabled. func AddrAdd(link Link, addr *Addr) error { return pkgHandle.AddrAdd(link, addr) } @@ -28,6 +29,7 @@ func AddrAdd(link Link, addr *Addr) error { // // If `addr` is an IPv4 address and the broadcast address is not given, it // will be automatically computed based on the IP mask if /30 or larger. +// If `net.IPv4zero` is given as the broadcast address, broadcast is disabled. func (h *Handle) AddrAdd(link Link, addr *Addr) error { req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) return h.addrHandle(link, addr, req) @@ -39,6 +41,7 @@ func (h *Handle) AddrAdd(link Link, addr *Addr) error { // // If `addr` is an IPv4 address and the broadcast address is not given, it // will be automatically computed based on the IP mask if /30 or larger. +// If `net.IPv4zero` is given as the broadcast address, broadcast is disabled. func AddrReplace(link Link, addr *Addr) error { return pkgHandle.AddrReplace(link, addr) } @@ -49,6 +52,7 @@ func AddrReplace(link Link, addr *Addr) error { // // If `addr` is an IPv4 address and the broadcast address is not given, it // will be automatically computed based on the IP mask if /30 or larger. +// If `net.IPv4zero` is given as the broadcast address, broadcast is disabled. func (h *Handle) AddrReplace(link Link, addr *Addr) error { req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_REPLACE|unix.NLM_F_ACK) return h.addrHandle(link, addr, req) @@ -57,18 +61,13 @@ func (h *Handle) AddrReplace(link Link, addr *Addr) error { // AddrDel will delete an IP address from a link device. // // Equivalent to: `ip addr del $addr dev $link` -// -// If `addr` is an IPv4 address and the broadcast address is not given, it -// will be automatically computed based on the IP mask if /30 or larger. func AddrDel(link Link, addr *Addr) error { return pkgHandle.AddrDel(link, addr) } // AddrDel will delete an IP address from a link device. -// Equivalent to: `ip addr del $addr dev $link` // -// If `addr` is an IPv4 address and the broadcast address is not given, it -// will be automatically computed based on the IP mask if /30 or larger. +// Equivalent to: `ip addr del $addr dev $link` func (h *Handle) AddrDel(link Link, addr *Addr) error { req := h.newNetlinkRequest(unix.RTM_DELADDR, unix.NLM_F_ACK) return h.addrHandle(link, addr, req) @@ -142,6 +141,10 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error addr.Broadcast = calcBroadcast } + if net.IPv4zero.Equal(addr.Broadcast) { + addr.Broadcast = nil + } + if addr.Broadcast != nil { req.AddData(nl.NewRtAttr(unix.IFA_BROADCAST, addr.Broadcast)) } diff --git a/vendor/github.com/vishvananda/netlink/conntrack_linux.go b/vendor/github.com/vishvananda/netlink/conntrack_linux.go index 69c5eca034..c566b2a4a6 100644 --- a/vendor/github.com/vishvananda/netlink/conntrack_linux.go +++ b/vendor/github.com/vishvananda/netlink/conntrack_linux.go @@ -159,13 +159,18 @@ func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFami // ConntrackDeleteFilters deletes entries on the specified table matching any of the specified filters using the netlink handle passed // conntrack -D [table] parameters Delete conntrack or expectation func (h *Handle) ConntrackDeleteFilters(table ConntrackTableType, family InetFamily, filters ...CustomConntrackFilter) (uint, error) { + var errMsgs []string res, err := h.dumpConntrackTable(table, family) if err != nil { - return 0, err + if !errors.Is(err, ErrDumpInterrupted) { + return 0, err + } + // This allows us to at least do a best effort to try to clean the + // entries matching the filter. + errMsgs = append(errMsgs, err.Error()) } var matched uint - var errMsgs []string for _, dataRaw := range res { flow := parseRawData(dataRaw) for _, filter := range filters { diff --git a/vendor/github.com/vishvananda/netlink/filter.go b/vendor/github.com/vishvananda/netlink/filter.go index 84e1ca7a49..a722e0a27b 100644 --- a/vendor/github.com/vishvananda/netlink/filter.go +++ b/vendor/github.com/vishvananda/netlink/filter.go @@ -231,6 +231,35 @@ func NewCsumAction() *CsumAction { } } +type VlanAct int8 + +type VlanAction struct { + ActionAttrs + Action VlanAct + VlanID uint16 +} + +const ( + TCA_VLAN_ACT_POP VlanAct = 1 + TCA_VLAN_ACT_PUSH VlanAct = 2 +) + +func (action *VlanAction) Type() string { + return "vlan" +} + +func (action *VlanAction) Attrs() *ActionAttrs { + return &action.ActionAttrs +} + +func NewVlanAction() *VlanAction { + return &VlanAction{ + ActionAttrs: ActionAttrs{ + Action: TC_ACT_PIPE, + }, + } +} + type MirredAct uint8 func (a MirredAct) String() string { diff --git a/vendor/github.com/vishvananda/netlink/filter_linux.go b/vendor/github.com/vishvananda/netlink/filter_linux.go index 19306612ee..404e50d524 100644 --- a/vendor/github.com/vishvananda/netlink/filter_linux.go +++ b/vendor/github.com/vishvananda/netlink/filter_linux.go @@ -65,6 +65,9 @@ type Flower struct { EncSrcIPMask net.IPMask EncDestPort uint16 EncKeyId uint32 + SrcMac net.HardwareAddr + DestMac net.HardwareAddr + VlanId uint16 SkipHw bool SkipSw bool IPProto *nl.IPProto @@ -135,6 +138,15 @@ func (filter *Flower) encode(parent *nl.RtAttr) error { if filter.EncKeyId != 0 { parent.AddRtAttr(nl.TCA_FLOWER_KEY_ENC_KEY_ID, htonl(filter.EncKeyId)) } + if filter.SrcMac != nil { + parent.AddRtAttr(nl.TCA_FLOWER_KEY_ETH_SRC, filter.SrcMac) + } + if filter.DestMac != nil { + parent.AddRtAttr(nl.TCA_FLOWER_KEY_ETH_DST, filter.DestMac) + } + if filter.VlanId != 0 { + parent.AddRtAttr(nl.TCA_FLOWER_KEY_VLAN_ID, nl.Uint16Attr(filter.VlanId)) + } if filter.IPProto != nil { ipproto := *filter.IPProto parent.AddRtAttr(nl.TCA_FLOWER_KEY_IP_PROTO, ipproto.Serialize()) @@ -201,6 +213,13 @@ func (filter *Flower) decode(data []syscall.NetlinkRouteAttr) error { filter.EncDestPort = ntohs(datum.Value) case nl.TCA_FLOWER_KEY_ENC_KEY_ID: filter.EncKeyId = ntohl(datum.Value) + case nl.TCA_FLOWER_KEY_ETH_SRC: + filter.SrcMac = datum.Value + case nl.TCA_FLOWER_KEY_ETH_DST: + filter.DestMac = datum.Value + case nl.TCA_FLOWER_KEY_VLAN_ID: + filter.VlanId = native.Uint16(datum.Value[0:2]) + filter.EthType = unix.ETH_P_8021Q case nl.TCA_FLOWER_KEY_IP_PROTO: val := new(nl.IPProto) *val = nl.IPProto(datum.Value[0]) @@ -622,6 +641,22 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error { } toTcGen(action.Attrs(), &mirred.TcGen) aopts.AddRtAttr(nl.TCA_MIRRED_PARMS, mirred.Serialize()) + case *VlanAction: + table := attr.AddRtAttr(tabIndex, nil) + tabIndex++ + table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("vlan")) + aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) + vlan := nl.TcVlan{ + Action: int32(action.Action), + } + toTcGen(action.Attrs(), &vlan.TcGen) + aopts.AddRtAttr(nl.TCA_VLAN_PARMS, vlan.Serialize()) + if action.Action == TCA_VLAN_ACT_PUSH && action.VlanID == 0 { + return fmt.Errorf("vlan id is required for push action") + } + if action.VlanID != 0 { + aopts.AddRtAttr(nl.TCA_VLAN_PUSH_VLAN_ID, nl.Uint16Attr(action.VlanID)) + } case *TunnelKeyAction: table := attr.AddRtAttr(tabIndex, nil) tabIndex++ @@ -792,6 +827,8 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) { action = &CsumAction{} case "gact": action = &GenericAction{} + case "vlan": + action = &VlanAction{} case "tunnel_key": action = &TunnelKeyAction{} case "skbedit": @@ -822,7 +859,17 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) { tcTs := nl.DeserializeTcf(adatum.Value) actionTimestamp = toTimeStamp(tcTs) } - + case "vlan": + switch adatum.Attr.Type { + case nl.TCA_VLAN_PARMS: + vlan := *nl.DeserializeTcVlan(adatum.Value) + action.(*VlanAction).ActionAttrs = ActionAttrs{} + toAttrs(&vlan.TcGen, action.Attrs()) + action.(*VlanAction).Action = VlanAct(vlan.Action) + case nl.TCA_VLAN_PUSH_VLAN_ID: + vlanId := native.Uint16(adatum.Value[0:2]) + action.(*VlanAction).VlanID = vlanId + } case "tunnel_key": switch adatum.Attr.Type { case nl.TCA_TUNNEL_KEY_PARMS: diff --git a/vendor/github.com/vishvananda/netlink/link_linux.go b/vendor/github.com/vishvananda/netlink/link_linux.go index 52491c5804..88bbc6db5c 100644 --- a/vendor/github.com/vishvananda/netlink/link_linux.go +++ b/vendor/github.com/vishvananda/netlink/link_linux.go @@ -3041,7 +3041,6 @@ func parseMacvlanData(link Link, data []syscall.NetlinkRouteAttr) { } } -// copied from pkg/net_linux.go func linkFlags(rawFlags uint32) net.Flags { var f net.Flags if rawFlags&unix.IFF_UP != 0 { @@ -3059,6 +3058,9 @@ func linkFlags(rawFlags uint32) net.Flags { if rawFlags&unix.IFF_MULTICAST != 0 { f |= net.FlagMulticast } + if rawFlags&unix.IFF_RUNNING != 0 { + f |= net.FlagRunning + } return f } diff --git a/vendor/github.com/vishvananda/netlink/nl/tc_linux.go b/vendor/github.com/vishvananda/netlink/nl/tc_linux.go index 0720729a90..b8f500792b 100644 --- a/vendor/github.com/vishvananda/netlink/nl/tc_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/tc_linux.go @@ -115,6 +115,7 @@ const ( SizeofTcConnmark = SizeofTcGen + 0x04 SizeofTcCsum = SizeofTcGen + 0x04 SizeofTcMirred = SizeofTcGen + 0x08 + SizeofTcVlan = SizeofTcGen + 0x04 SizeofTcTunnelKey = SizeofTcGen + 0x04 SizeofTcSkbEdit = SizeofTcGen SizeofTcPolice = 2*SizeofTcRateSpec + 0x20 @@ -816,6 +817,41 @@ func (x *TcMirred) Serialize() []byte { return (*(*[SizeofTcMirred]byte)(unsafe.Pointer(x)))[:] } +const ( + TCA_VLAN_UNSPEC = iota + TCA_VLAN_TM + TCA_VLAN_PARMS + TCA_VLAN_PUSH_VLAN_ID + TCA_VLAN_PUSH_VLAN_PROTOCOL + TCA_VLAN_PAD + TCA_VLAN_PUSH_VLAN_PRIORITY + TCA_VLAN_PUSH_ETH_DST + TCA_VLAN_PUSH_ETH_SRC + TCA_VLAN_MAX +) + +//struct tc_vlan { +// tc_gen; +// int v_action; +//}; + +type TcVlan struct { + TcGen + Action int32 +} + +func (msg *TcVlan) Len() int { + return SizeofTcVlan +} + +func DeserializeTcVlan(b []byte) *TcVlan { + return (*TcVlan)(unsafe.Pointer(&b[0:SizeofTcVlan][0])) +} + +func (x *TcVlan) Serialize() []byte { + return (*(*[SizeofTcVlan]byte)(unsafe.Pointer(x)))[:] +} + const ( TCA_TUNNEL_KEY_UNSPEC = iota TCA_TUNNEL_KEY_TM @@ -1239,8 +1275,8 @@ const ( ) // /* TCA_PEDIT_KEY_EX_HDR_TYPE_NETWROK is a special case for legacy users. It -// * means no specific header type - offset is relative to the network layer -// */ +// - means no specific header type - offset is relative to the network layer +// */ type PeditHeaderType uint16 const ( diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/common.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/common.go index 214acaf581..5d6e6156b7 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/common.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/common.go @@ -18,13 +18,6 @@ const ( WriteErrorKey = attribute.Key("http.write_error") // if an error occurred while writing a reply, the string of the error (io.EOF is not recorded) ) -// Server HTTP metrics. -const ( - serverRequestSize = "http.server.request.size" // Incoming request bytes total - serverResponseSize = "http.server.response.size" // Incoming response bytes total - serverDuration = "http.server.duration" // Incoming end to end duration, milliseconds -) - // Client HTTP metrics. const ( clientRequestSize = "http.client.request.size" // Outgoing request bytes total diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/config.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/config.go index f0a9bb9efe..a01bfafbe0 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/config.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/config.go @@ -8,6 +8,8 @@ import ( "net/http" "net/http/httptrace" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/propagation" @@ -33,8 +35,9 @@ type config struct { SpanNameFormatter func(string, *http.Request) string ClientTrace func(context.Context) *httptrace.ClientTrace - TracerProvider trace.TracerProvider - MeterProvider metric.MeterProvider + TracerProvider trace.TracerProvider + MeterProvider metric.MeterProvider + MetricAttributesFn func(*http.Request) []attribute.KeyValue } // Option interface used for setting optional config properties. @@ -194,3 +197,11 @@ func WithServerName(server string) Option { c.ServerName = server }) } + +// WithMetricAttributesFn returns an Option to set a function that maps an HTTP request to a slice of attribute.KeyValue. +// These attributes will be included in metrics for every request. +func WithMetricAttributesFn(metricAttributesFn func(r *http.Request) []attribute.KeyValue) Option { + return optionFunc(func(c *config) { + c.MetricAttributesFn = metricAttributesFn + }) +} diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go index d01bdccf40..33580a35b7 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go @@ -9,11 +9,9 @@ import ( "github.com/felixge/httpsnoop" + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv" - "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil" "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/trace" ) @@ -24,7 +22,6 @@ type middleware struct { server string tracer trace.Tracer - meter metric.Meter propagators propagation.TextMapPropagator spanStartOptions []trace.SpanStartOption readEvent bool @@ -34,10 +31,7 @@ type middleware struct { publicEndpoint bool publicEndpointFn func(*http.Request) bool - traceSemconv semconv.HTTPServer - requestBytesCounter metric.Int64Counter - responseBytesCounter metric.Int64Counter - serverLatencyMeasure metric.Float64Histogram + semconv semconv.HTTPServer } func defaultHandlerFormatter(operation string, _ *http.Request) string { @@ -56,8 +50,6 @@ func NewHandler(handler http.Handler, operation string, opts ...Option) http.Han func NewMiddleware(operation string, opts ...Option) func(http.Handler) http.Handler { h := middleware{ operation: operation, - - traceSemconv: semconv.NewHTTPServer(), } defaultOpts := []Option{ @@ -67,7 +59,6 @@ func NewMiddleware(operation string, opts ...Option) func(http.Handler) http.Han c := newConfig(append(defaultOpts, opts...)...) h.configure(c) - h.createMeasures() return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -78,7 +69,6 @@ func NewMiddleware(operation string, opts ...Option) func(http.Handler) http.Han func (h *middleware) configure(c *config) { h.tracer = c.Tracer - h.meter = c.Meter h.propagators = c.Propagators h.spanStartOptions = c.SpanStartOptions h.readEvent = c.ReadEvent @@ -88,6 +78,7 @@ func (h *middleware) configure(c *config) { h.publicEndpoint = c.PublicEndpoint h.publicEndpointFn = c.PublicEndpointFn h.server = c.ServerName + h.semconv = semconv.NewHTTPServer(c.Meter) } func handleErr(err error) { @@ -96,30 +87,6 @@ func handleErr(err error) { } } -func (h *middleware) createMeasures() { - var err error - h.requestBytesCounter, err = h.meter.Int64Counter( - serverRequestSize, - metric.WithUnit("By"), - metric.WithDescription("Measures the size of HTTP request messages."), - ) - handleErr(err) - - h.responseBytesCounter, err = h.meter.Int64Counter( - serverResponseSize, - metric.WithUnit("By"), - metric.WithDescription("Measures the size of HTTP response messages."), - ) - handleErr(err) - - h.serverLatencyMeasure, err = h.meter.Float64Histogram( - serverDuration, - metric.WithUnit("ms"), - metric.WithDescription("Measures the duration of inbound HTTP requests."), - ) - handleErr(err) -} - // serveHTTP sets up tracing and calls the given next http.Handler with the span // context injected into the request context. func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http.Handler) { @@ -134,7 +101,7 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http ctx := h.propagators.Extract(r.Context(), propagation.HeaderCarrier(r.Header)) opts := []trace.SpanStartOption{ - trace.WithAttributes(h.traceSemconv.RequestTraceAttrs(h.server, r)...), + trace.WithAttributes(h.semconv.RequestTraceAttrs(h.server, r)...), } opts = append(opts, h.spanStartOptions...) @@ -166,14 +133,12 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http } } - var bw bodyWrapper // if request body is nil or NoBody, we don't want to mutate the body as it // will affect the identity of it in an unforeseeable way because we assert // ReadCloser fulfills a certain interface and it is indeed nil or NoBody. + bw := request.NewBodyWrapper(r.Body, readRecordFunc) if r.Body != nil && r.Body != http.NoBody { - bw.ReadCloser = r.Body - bw.record = readRecordFunc - r.Body = &bw + r.Body = bw } writeRecordFunc := func(int64) {} @@ -183,13 +148,7 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http } } - rww := &respWriterWrapper{ - ResponseWriter: w, - record: writeRecordFunc, - ctx: ctx, - props: h.propagators, - statusCode: http.StatusOK, // default status code in case the Handler doesn't write anything - } + rww := request.NewRespWriterWrapper(w, writeRecordFunc) // Wrap w to use our ResponseWriter methods while also exposing // other interfaces that w may implement (http.CloseNotifier, @@ -217,35 +176,35 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http next.ServeHTTP(w, r.WithContext(ctx)) - span.SetStatus(semconv.ServerStatus(rww.statusCode)) - span.SetAttributes(h.traceSemconv.ResponseTraceAttrs(semconv.ResponseTelemetry{ - StatusCode: rww.statusCode, - ReadBytes: bw.read.Load(), - ReadError: bw.err, - WriteBytes: rww.written, - WriteError: rww.err, + statusCode := rww.StatusCode() + bytesWritten := rww.BytesWritten() + span.SetStatus(h.semconv.Status(statusCode)) + span.SetAttributes(h.semconv.ResponseTraceAttrs(semconv.ResponseTelemetry{ + StatusCode: statusCode, + ReadBytes: bw.BytesRead(), + ReadError: bw.Error(), + WriteBytes: bytesWritten, + WriteError: rww.Error(), })...) - // Add metrics - attributes := append(labeler.Get(), semconvutil.HTTPServerRequestMetrics(h.server, r)...) - if rww.statusCode > 0 { - attributes = append(attributes, semconv.HTTPStatusCode(rww.statusCode)) - } - o := metric.WithAttributeSet(attribute.NewSet(attributes...)) - addOpts := []metric.AddOption{o} // Allocate vararg slice once. - h.requestBytesCounter.Add(ctx, bw.read.Load(), addOpts...) - h.responseBytesCounter.Add(ctx, rww.written, addOpts...) - // Use floating point division here for higher precision (instead of Millisecond method). elapsedTime := float64(time.Since(requestStartTime)) / float64(time.Millisecond) - h.serverLatencyMeasure.Record(ctx, elapsedTime, o) + h.semconv.RecordMetrics(ctx, semconv.MetricData{ + ServerName: h.server, + Req: r, + StatusCode: statusCode, + AdditionalAttributes: labeler.Get(), + RequestSize: bw.BytesRead(), + ResponseSize: bytesWritten, + ElapsedTime: elapsedTime, + }) } // WithRouteTag annotates spans and metrics with the provided route name // with HTTP route attribute. func WithRouteTag(route string, h http.Handler) http.Handler { - attr := semconv.NewHTTPServer().Route(route) + attr := semconv.NewHTTPServer(nil).Route(route) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { span := trace.SpanFromContext(r.Context()) span.SetAttributes(attr) diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/body_wrapper.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/body_wrapper.go new file mode 100644 index 0000000000..a945f55661 --- /dev/null +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/body_wrapper.go @@ -0,0 +1,75 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package request // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request" + +import ( + "io" + "sync" +) + +var _ io.ReadCloser = &BodyWrapper{} + +// BodyWrapper wraps a http.Request.Body (an io.ReadCloser) to track the number +// of bytes read and the last error. +type BodyWrapper struct { + io.ReadCloser + OnRead func(n int64) // must not be nil + + mu sync.Mutex + read int64 + err error +} + +// NewBodyWrapper creates a new BodyWrapper. +// +// The onRead attribute is a callback that will be called every time the data +// is read, with the number of bytes being read. +func NewBodyWrapper(body io.ReadCloser, onRead func(int64)) *BodyWrapper { + return &BodyWrapper{ + ReadCloser: body, + OnRead: onRead, + } +} + +// Read reads the data from the io.ReadCloser, and stores the number of bytes +// read and the error. +func (w *BodyWrapper) Read(b []byte) (int, error) { + n, err := w.ReadCloser.Read(b) + n1 := int64(n) + + w.updateReadData(n1, err) + w.OnRead(n1) + return n, err +} + +func (w *BodyWrapper) updateReadData(n int64, err error) { + w.mu.Lock() + defer w.mu.Unlock() + + w.read += n + if err != nil { + w.err = err + } +} + +// Closes closes the io.ReadCloser. +func (w *BodyWrapper) Close() error { + return w.ReadCloser.Close() +} + +// BytesRead returns the number of bytes read up to this point. +func (w *BodyWrapper) BytesRead() int64 { + w.mu.Lock() + defer w.mu.Unlock() + + return w.read +} + +// Error returns the last error. +func (w *BodyWrapper) Error() error { + w.mu.Lock() + defer w.mu.Unlock() + + return w.err +} diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/resp_writer_wrapper.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/resp_writer_wrapper.go new file mode 100644 index 0000000000..aea171fb26 --- /dev/null +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/resp_writer_wrapper.go @@ -0,0 +1,112 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package request // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request" + +import ( + "net/http" + "sync" +) + +var _ http.ResponseWriter = &RespWriterWrapper{} + +// RespWriterWrapper wraps a http.ResponseWriter in order to track the number of +// bytes written, the last error, and to catch the first written statusCode. +// TODO: The wrapped http.ResponseWriter doesn't implement any of the optional +// types (http.Hijacker, http.Pusher, http.CloseNotifier, etc) +// that may be useful when using it in real life situations. +type RespWriterWrapper struct { + http.ResponseWriter + OnWrite func(n int64) // must not be nil + + mu sync.RWMutex + written int64 + statusCode int + err error + wroteHeader bool +} + +// NewRespWriterWrapper creates a new RespWriterWrapper. +// +// The onWrite attribute is a callback that will be called every time the data +// is written, with the number of bytes that were written. +func NewRespWriterWrapper(w http.ResponseWriter, onWrite func(int64)) *RespWriterWrapper { + return &RespWriterWrapper{ + ResponseWriter: w, + OnWrite: onWrite, + statusCode: http.StatusOK, // default status code in case the Handler doesn't write anything + } +} + +// Write writes the bytes array into the [ResponseWriter], and tracks the +// number of bytes written and last error. +func (w *RespWriterWrapper) Write(p []byte) (int, error) { + w.mu.Lock() + defer w.mu.Unlock() + + w.writeHeader(http.StatusOK) + + n, err := w.ResponseWriter.Write(p) + n1 := int64(n) + w.OnWrite(n1) + w.written += n1 + w.err = err + return n, err +} + +// WriteHeader persists initial statusCode for span attribution. +// All calls to WriteHeader will be propagated to the underlying ResponseWriter +// and will persist the statusCode from the first call. +// Blocking consecutive calls to WriteHeader alters expected behavior and will +// remove warning logs from net/http where developers will notice incorrect handler implementations. +func (w *RespWriterWrapper) WriteHeader(statusCode int) { + w.mu.Lock() + defer w.mu.Unlock() + + w.writeHeader(statusCode) +} + +// writeHeader persists the status code for span attribution, and propagates +// the call to the underlying ResponseWriter. +// It does not acquire a lock, and therefore assumes that is being handled by a +// parent method. +func (w *RespWriterWrapper) writeHeader(statusCode int) { + if !w.wroteHeader { + w.wroteHeader = true + w.statusCode = statusCode + } + w.ResponseWriter.WriteHeader(statusCode) +} + +// Flush implements [http.Flusher]. +func (w *RespWriterWrapper) Flush() { + w.WriteHeader(http.StatusOK) + + if f, ok := w.ResponseWriter.(http.Flusher); ok { + f.Flush() + } +} + +// BytesWritten returns the number of bytes written. +func (w *RespWriterWrapper) BytesWritten() int64 { + w.mu.RLock() + defer w.mu.RUnlock() + + return w.written +} + +// BytesWritten returns the HTTP status code that was sent. +func (w *RespWriterWrapper) StatusCode() int { + w.mu.RLock() + defer w.mu.RUnlock() + + return w.statusCode +} + +// Error returns the last error. +func (w *RespWriterWrapper) Error() error { + w.mu.RLock() + defer w.mu.RUnlock() + + return w.err +} diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/env.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/env.go index 3ec0ad00c8..9cae4cab86 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/env.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/env.go @@ -4,6 +4,7 @@ package semconv // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv" import ( + "context" "fmt" "net/http" "os" @@ -11,6 +12,7 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" + "go.opentelemetry.io/otel/metric" ) type ResponseTelemetry struct { @@ -23,6 +25,11 @@ type ResponseTelemetry struct { type HTTPServer struct { duplicate bool + + // Old metrics + requestBytesCounter metric.Int64Counter + responseBytesCounter metric.Int64Counter + serverLatencyMeasure metric.Float64Histogram } // RequestTraceAttrs returns trace attributes for an HTTP request received by a @@ -63,15 +70,10 @@ func (s HTTPServer) Route(route string) attribute.KeyValue { return oldHTTPServer{}.Route(route) } -func NewHTTPServer() HTTPServer { - env := strings.ToLower(os.Getenv("OTEL_HTTP_CLIENT_COMPATIBILITY_MODE")) - return HTTPServer{duplicate: env == "http/dup"} -} - -// ServerStatus returns a span status code and message for an HTTP status code +// Status returns a span status code and message for an HTTP status code // value returned by a server. Status codes in the 400-499 range are not // returned as errors. -func ServerStatus(code int) (codes.Code, string) { +func (s HTTPServer) Status(code int) (codes.Code, string) { if code < 100 || code >= 600 { return codes.Error, fmt.Sprintf("Invalid HTTP status code %d", code) } @@ -80,3 +82,84 @@ func ServerStatus(code int) (codes.Code, string) { } return codes.Unset, "" } + +type MetricData struct { + ServerName string + Req *http.Request + StatusCode int + AdditionalAttributes []attribute.KeyValue + + RequestSize int64 + ResponseSize int64 + ElapsedTime float64 +} + +func (s HTTPServer) RecordMetrics(ctx context.Context, md MetricData) { + if s.requestBytesCounter == nil || s.responseBytesCounter == nil || s.serverLatencyMeasure == nil { + // This will happen if an HTTPServer{} is used insted of NewHTTPServer. + return + } + + attributes := oldHTTPServer{}.MetricAttributes(md.ServerName, md.Req, md.StatusCode, md.AdditionalAttributes) + o := metric.WithAttributeSet(attribute.NewSet(attributes...)) + addOpts := []metric.AddOption{o} // Allocate vararg slice once. + s.requestBytesCounter.Add(ctx, md.RequestSize, addOpts...) + s.responseBytesCounter.Add(ctx, md.ResponseSize, addOpts...) + s.serverLatencyMeasure.Record(ctx, md.ElapsedTime, o) + + // TODO: Duplicate Metrics +} + +func NewHTTPServer(meter metric.Meter) HTTPServer { + env := strings.ToLower(os.Getenv("OTEL_SEMCONV_STABILITY_OPT_IN")) + duplicate := env == "http/dup" + server := HTTPServer{ + duplicate: duplicate, + } + server.requestBytesCounter, server.responseBytesCounter, server.serverLatencyMeasure = oldHTTPServer{}.createMeasures(meter) + return server +} + +type HTTPClient struct { + duplicate bool +} + +func NewHTTPClient() HTTPClient { + env := strings.ToLower(os.Getenv("OTEL_SEMCONV_STABILITY_OPT_IN")) + return HTTPClient{duplicate: env == "http/dup"} +} + +// RequestTraceAttrs returns attributes for an HTTP request made by a client. +func (c HTTPClient) RequestTraceAttrs(req *http.Request) []attribute.KeyValue { + if c.duplicate { + return append(oldHTTPClient{}.RequestTraceAttrs(req), newHTTPClient{}.RequestTraceAttrs(req)...) + } + return oldHTTPClient{}.RequestTraceAttrs(req) +} + +// ResponseTraceAttrs returns metric attributes for an HTTP request made by a client. +func (c HTTPClient) ResponseTraceAttrs(resp *http.Response) []attribute.KeyValue { + if c.duplicate { + return append(oldHTTPClient{}.ResponseTraceAttrs(resp), newHTTPClient{}.ResponseTraceAttrs(resp)...) + } + + return oldHTTPClient{}.ResponseTraceAttrs(resp) +} + +func (c HTTPClient) Status(code int) (codes.Code, string) { + if code < 100 || code >= 600 { + return codes.Error, fmt.Sprintf("Invalid HTTP status code %d", code) + } + if code >= 400 { + return codes.Error, "" + } + return codes.Unset, "" +} + +func (c HTTPClient) ErrorType(err error) attribute.KeyValue { + if c.duplicate { + return newHTTPClient{}.ErrorType(err) + } + + return attribute.KeyValue{} +} diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/v1.24.0.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/httpconv.go similarity index 57% rename from vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/v1.24.0.go rename to vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/httpconv.go index 0c5d4c4608..745b8c67bc 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/v1.24.0.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/httpconv.go @@ -4,11 +4,14 @@ package semconv // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv" import ( + "fmt" "net/http" + "reflect" + "strconv" "strings" "go.opentelemetry.io/otel/attribute" - semconvNew "go.opentelemetry.io/otel/semconv/v1.24.0" + semconvNew "go.opentelemetry.io/otel/semconv/v1.26.0" ) type newHTTPServer struct{} @@ -195,3 +198,151 @@ func (n newHTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.Ke func (n newHTTPServer) Route(route string) attribute.KeyValue { return semconvNew.HTTPRoute(route) } + +type newHTTPClient struct{} + +// RequestTraceAttrs returns trace attributes for an HTTP request made by a client. +func (n newHTTPClient) RequestTraceAttrs(req *http.Request) []attribute.KeyValue { + /* + below attributes are returned: + - http.request.method + - http.request.method.original + - url.full + - server.address + - server.port + - network.protocol.name + - network.protocol.version + */ + numOfAttributes := 3 // URL, server address, proto, and method. + + var urlHost string + if req.URL != nil { + urlHost = req.URL.Host + } + var requestHost string + var requestPort int + for _, hostport := range []string{urlHost, req.Header.Get("Host")} { + requestHost, requestPort = splitHostPort(hostport) + if requestHost != "" || requestPort > 0 { + break + } + } + + eligiblePort := requiredHTTPPort(req.URL != nil && req.URL.Scheme == "https", requestPort) + if eligiblePort > 0 { + numOfAttributes++ + } + useragent := req.UserAgent() + if useragent != "" { + numOfAttributes++ + } + + protoName, protoVersion := netProtocol(req.Proto) + if protoName != "" && protoName != "http" { + numOfAttributes++ + } + if protoVersion != "" { + numOfAttributes++ + } + + method, originalMethod := n.method(req.Method) + if originalMethod != (attribute.KeyValue{}) { + numOfAttributes++ + } + + attrs := make([]attribute.KeyValue, 0, numOfAttributes) + + attrs = append(attrs, method) + if originalMethod != (attribute.KeyValue{}) { + attrs = append(attrs, originalMethod) + } + + var u string + if req.URL != nil { + // Remove any username/password info that may be in the URL. + userinfo := req.URL.User + req.URL.User = nil + u = req.URL.String() + // Restore any username/password info that was removed. + req.URL.User = userinfo + } + attrs = append(attrs, semconvNew.URLFull(u)) + + attrs = append(attrs, semconvNew.ServerAddress(requestHost)) + if eligiblePort > 0 { + attrs = append(attrs, semconvNew.ServerPort(eligiblePort)) + } + + if protoName != "" && protoName != "http" { + attrs = append(attrs, semconvNew.NetworkProtocolName(protoName)) + } + if protoVersion != "" { + attrs = append(attrs, semconvNew.NetworkProtocolVersion(protoVersion)) + } + + return attrs +} + +// ResponseTraceAttrs returns trace attributes for an HTTP response made by a client. +func (n newHTTPClient) ResponseTraceAttrs(resp *http.Response) []attribute.KeyValue { + /* + below attributes are returned: + - http.response.status_code + - error.type + */ + var count int + if resp.StatusCode > 0 { + count++ + } + + if isErrorStatusCode(resp.StatusCode) { + count++ + } + + attrs := make([]attribute.KeyValue, 0, count) + if resp.StatusCode > 0 { + attrs = append(attrs, semconvNew.HTTPResponseStatusCode(resp.StatusCode)) + } + + if isErrorStatusCode(resp.StatusCode) { + errorType := strconv.Itoa(resp.StatusCode) + attrs = append(attrs, semconvNew.ErrorTypeKey.String(errorType)) + } + return attrs +} + +func (n newHTTPClient) ErrorType(err error) attribute.KeyValue { + t := reflect.TypeOf(err) + var value string + if t.PkgPath() == "" && t.Name() == "" { + // Likely a builtin type. + value = t.String() + } else { + value = fmt.Sprintf("%s.%s", t.PkgPath(), t.Name()) + } + + if value == "" { + return semconvNew.ErrorTypeOther + } + + return semconvNew.ErrorTypeKey.String(value) +} + +func (n newHTTPClient) method(method string) (attribute.KeyValue, attribute.KeyValue) { + if method == "" { + return semconvNew.HTTPRequestMethodGet, attribute.KeyValue{} + } + if attr, ok := methodLookup[method]; ok { + return attr, attribute.KeyValue{} + } + + orig := semconvNew.HTTPRequestMethodOriginal(method) + if attr, ok := methodLookup[strings.ToUpper(method)]; ok { + return attr, orig + } + return semconvNew.HTTPRequestMethodGet, orig +} + +func isErrorStatusCode(code int) bool { + return code >= 400 || code < 100 +} diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/util.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/util.go index e7f293761b..e6e14924f5 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/util.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/util.go @@ -9,8 +9,9 @@ import ( "strconv" "strings" + "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" - semconvNew "go.opentelemetry.io/otel/semconv/v1.24.0" + semconvNew "go.opentelemetry.io/otel/semconv/v1.26.0" ) // splitHostPort splits a network address hostport of the form "host", @@ -49,7 +50,7 @@ func splitHostPort(hostport string) (host string, port int) { if err != nil { return } - return host, int(p) + return host, int(p) // nolint: gosec // Byte size checked 16 above. } func requiredHTTPPort(https bool, port int) int { // nolint:revive @@ -89,3 +90,9 @@ var methodLookup = map[string]attribute.KeyValue{ http.MethodPut: semconvNew.HTTPRequestMethodPut, http.MethodTrace: semconvNew.HTTPRequestMethodTrace, } + +func handleErr(err error) { + if err != nil { + otel.Handle(err) + } +} diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/v1.20.0.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/v1.20.0.go index c3e838aaa5..c999b05e67 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/v1.20.0.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/v1.20.0.go @@ -7,9 +7,13 @@ import ( "errors" "io" "net/http" + "slices" + "strings" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil" "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/metric/noop" semconv "go.opentelemetry.io/otel/semconv/v1.20.0" ) @@ -72,3 +76,117 @@ func (o oldHTTPServer) Route(route string) attribute.KeyValue { func HTTPStatusCode(status int) attribute.KeyValue { return semconv.HTTPStatusCode(status) } + +// Server HTTP metrics. +const ( + serverRequestSize = "http.server.request.size" // Incoming request bytes total + serverResponseSize = "http.server.response.size" // Incoming response bytes total + serverDuration = "http.server.duration" // Incoming end to end duration, milliseconds +) + +func (h oldHTTPServer) createMeasures(meter metric.Meter) (metric.Int64Counter, metric.Int64Counter, metric.Float64Histogram) { + if meter == nil { + return noop.Int64Counter{}, noop.Int64Counter{}, noop.Float64Histogram{} + } + var err error + requestBytesCounter, err := meter.Int64Counter( + serverRequestSize, + metric.WithUnit("By"), + metric.WithDescription("Measures the size of HTTP request messages."), + ) + handleErr(err) + + responseBytesCounter, err := meter.Int64Counter( + serverResponseSize, + metric.WithUnit("By"), + metric.WithDescription("Measures the size of HTTP response messages."), + ) + handleErr(err) + + serverLatencyMeasure, err := meter.Float64Histogram( + serverDuration, + metric.WithUnit("ms"), + metric.WithDescription("Measures the duration of inbound HTTP requests."), + ) + handleErr(err) + + return requestBytesCounter, responseBytesCounter, serverLatencyMeasure +} + +func (o oldHTTPServer) MetricAttributes(server string, req *http.Request, statusCode int, additionalAttributes []attribute.KeyValue) []attribute.KeyValue { + n := len(additionalAttributes) + 3 + var host string + var p int + if server == "" { + host, p = splitHostPort(req.Host) + } else { + // Prioritize the primary server name. + host, p = splitHostPort(server) + if p < 0 { + _, p = splitHostPort(req.Host) + } + } + hostPort := requiredHTTPPort(req.TLS != nil, p) + if hostPort > 0 { + n++ + } + protoName, protoVersion := netProtocol(req.Proto) + if protoName != "" { + n++ + } + if protoVersion != "" { + n++ + } + + if statusCode > 0 { + n++ + } + + attributes := slices.Grow(additionalAttributes, n) + attributes = append(attributes, + o.methodMetric(req.Method), + o.scheme(req.TLS != nil), + semconv.NetHostName(host)) + + if hostPort > 0 { + attributes = append(attributes, semconv.NetHostPort(hostPort)) + } + if protoName != "" { + attributes = append(attributes, semconv.NetProtocolName(protoName)) + } + if protoVersion != "" { + attributes = append(attributes, semconv.NetProtocolVersion(protoVersion)) + } + + if statusCode > 0 { + attributes = append(attributes, semconv.HTTPStatusCode(statusCode)) + } + return attributes +} + +func (o oldHTTPServer) methodMetric(method string) attribute.KeyValue { + method = strings.ToUpper(method) + switch method { + case http.MethodConnect, http.MethodDelete, http.MethodGet, http.MethodHead, http.MethodOptions, http.MethodPatch, http.MethodPost, http.MethodPut, http.MethodTrace: + default: + method = "_OTHER" + } + return semconv.HTTPMethod(method) +} + +func (o oldHTTPServer) scheme(https bool) attribute.KeyValue { // nolint:revive + if https { + return semconv.HTTPSchemeHTTPS + } + return semconv.HTTPSchemeHTTP +} + +type oldHTTPClient struct{} + +func (o oldHTTPClient) RequestTraceAttrs(req *http.Request) []attribute.KeyValue { + return semconvutil.HTTPClientRequest(req) +} + +func (o oldHTTPClient) ResponseTraceAttrs(resp *http.Response) []attribute.KeyValue { + return semconvutil.HTTPClientResponse(resp) +} diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/netconv.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/netconv.go index a9a9226b39..b80a1db61f 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/netconv.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/netconv.go @@ -195,7 +195,7 @@ func splitHostPort(hostport string) (host string, port int) { if err != nil { return } - return host, int(p) + return host, int(p) // nolint: gosec // Bitsize checked to be 16 above. } func netProtocol(proto string) (name string, version string) { diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/transport.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/transport.go index 0d3cb2e4aa..b4119d3438 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/transport.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/transport.go @@ -11,13 +11,15 @@ import ( "sync/atomic" "time" + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request" + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/propagation" - semconv "go.opentelemetry.io/otel/semconv/v1.20.0" + "go.opentelemetry.io/otel/trace" ) @@ -26,14 +28,16 @@ import ( type Transport struct { rt http.RoundTripper - tracer trace.Tracer - meter metric.Meter - propagators propagation.TextMapPropagator - spanStartOptions []trace.SpanStartOption - filters []Filter - spanNameFormatter func(string, *http.Request) string - clientTrace func(context.Context) *httptrace.ClientTrace + tracer trace.Tracer + meter metric.Meter + propagators propagation.TextMapPropagator + spanStartOptions []trace.SpanStartOption + filters []Filter + spanNameFormatter func(string, *http.Request) string + clientTrace func(context.Context) *httptrace.ClientTrace + metricAttributesFn func(*http.Request) []attribute.KeyValue + semconv semconv.HTTPClient requestBytesCounter metric.Int64Counter responseBytesCounter metric.Int64Counter latencyMeasure metric.Float64Histogram @@ -53,7 +57,8 @@ func NewTransport(base http.RoundTripper, opts ...Option) *Transport { } t := Transport{ - rt: base, + rt: base, + semconv: semconv.NewHTTPClient(), } defaultOpts := []Option{ @@ -76,6 +81,7 @@ func (t *Transport) applyConfig(c *config) { t.filters = c.Filters t.spanNameFormatter = c.SpanNameFormatter t.clientTrace = c.ClientTrace + t.metricAttributesFn = c.MetricAttributesFn } func (t *Transport) createMeasures() { @@ -143,45 +149,49 @@ func (t *Transport) RoundTrip(r *http.Request) (*http.Response, error) { r = r.Clone(ctx) // According to RoundTripper spec, we shouldn't modify the origin request. - // use a body wrapper to determine the request size - var bw bodyWrapper // if request body is nil or NoBody, we don't want to mutate the body as it // will affect the identity of it in an unforeseeable way because we assert // ReadCloser fulfills a certain interface and it is indeed nil or NoBody. + bw := request.NewBodyWrapper(r.Body, func(int64) {}) if r.Body != nil && r.Body != http.NoBody { - bw.ReadCloser = r.Body - // noop to prevent nil panic. not using this record fun yet. - bw.record = func(int64) {} - r.Body = &bw + r.Body = bw } - span.SetAttributes(semconvutil.HTTPClientRequest(r)...) + span.SetAttributes(t.semconv.RequestTraceAttrs(r)...) t.propagators.Inject(ctx, propagation.HeaderCarrier(r.Header)) res, err := t.rt.RoundTrip(r) if err != nil { - span.RecordError(err) + // set error type attribute if the error is part of the predefined + // error types. + // otherwise, record it as an exception + if errType := t.semconv.ErrorType(err); errType.Valid() { + span.SetAttributes(errType) + } else { + span.RecordError(err) + } + span.SetStatus(codes.Error, err.Error()) span.End() return res, err } // metrics - metricAttrs := append(labeler.Get(), semconvutil.HTTPClientRequestMetrics(r)...) + metricAttrs := append(append(labeler.Get(), semconvutil.HTTPClientRequestMetrics(r)...), t.metricAttributesFromRequest(r)...) if res.StatusCode > 0 { metricAttrs = append(metricAttrs, semconv.HTTPStatusCode(res.StatusCode)) } o := metric.WithAttributeSet(attribute.NewSet(metricAttrs...)) - addOpts := []metric.AddOption{o} // Allocate vararg slice once. - t.requestBytesCounter.Add(ctx, bw.read.Load(), addOpts...) + + t.requestBytesCounter.Add(ctx, bw.BytesRead(), o) // For handling response bytes we leverage a callback when the client reads the http response readRecordFunc := func(n int64) { - t.responseBytesCounter.Add(ctx, n, addOpts...) + t.responseBytesCounter.Add(ctx, n, o) } // traces - span.SetAttributes(semconvutil.HTTPClientResponse(res)...) - span.SetStatus(semconvutil.HTTPClientStatus(res.StatusCode)) + span.SetAttributes(t.semconv.ResponseTraceAttrs(res)...) + span.SetStatus(t.semconv.Status(res.StatusCode)) res.Body = newWrappedBody(span, readRecordFunc, res.Body) @@ -193,6 +203,14 @@ func (t *Transport) RoundTrip(r *http.Request) (*http.Response, error) { return res, err } +func (t *Transport) metricAttributesFromRequest(r *http.Request) []attribute.KeyValue { + var attributeForRequest []attribute.KeyValue + if t.metricAttributesFn != nil { + attributeForRequest = t.metricAttributesFn(r) + } + return attributeForRequest +} + // newWrappedBody returns a new and appropriately scoped *wrappedBody as an // io.ReadCloser. If the passed body implements io.Writer, the returned value // will implement io.ReadWriteCloser. diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go index b0957f28ce..502c1bdafc 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go @@ -5,7 +5,7 @@ package otelhttp // import "go.opentelemetry.io/contrib/instrumentation/net/http // Version is the current release version of the otelhttp instrumentation. func Version() string { - return "0.53.0" + return "0.54.0" // This string is updated by the pre_release.sh script during release } diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/wrap.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/wrap.go deleted file mode 100644 index 948f8406c0..0000000000 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/wrap.go +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package otelhttp // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" - -import ( - "context" - "io" - "net/http" - "sync/atomic" - - "go.opentelemetry.io/otel/propagation" -) - -var _ io.ReadCloser = &bodyWrapper{} - -// bodyWrapper wraps a http.Request.Body (an io.ReadCloser) to track the number -// of bytes read and the last error. -type bodyWrapper struct { - io.ReadCloser - record func(n int64) // must not be nil - - read atomic.Int64 - err error -} - -func (w *bodyWrapper) Read(b []byte) (int, error) { - n, err := w.ReadCloser.Read(b) - n1 := int64(n) - w.read.Add(n1) - w.err = err - w.record(n1) - return n, err -} - -func (w *bodyWrapper) Close() error { - return w.ReadCloser.Close() -} - -var _ http.ResponseWriter = &respWriterWrapper{} - -// respWriterWrapper wraps a http.ResponseWriter in order to track the number of -// bytes written, the last error, and to catch the first written statusCode. -// TODO: The wrapped http.ResponseWriter doesn't implement any of the optional -// types (http.Hijacker, http.Pusher, http.CloseNotifier, http.Flusher, etc) -// that may be useful when using it in real life situations. -type respWriterWrapper struct { - http.ResponseWriter - record func(n int64) // must not be nil - - // used to inject the header - ctx context.Context - - props propagation.TextMapPropagator - - written int64 - statusCode int - err error - wroteHeader bool -} - -func (w *respWriterWrapper) Header() http.Header { - return w.ResponseWriter.Header() -} - -func (w *respWriterWrapper) Write(p []byte) (int, error) { - if !w.wroteHeader { - w.WriteHeader(http.StatusOK) - } - n, err := w.ResponseWriter.Write(p) - n1 := int64(n) - w.record(n1) - w.written += n1 - w.err = err - return n, err -} - -// WriteHeader persists initial statusCode for span attribution. -// All calls to WriteHeader will be propagated to the underlying ResponseWriter -// and will persist the statusCode from the first call. -// Blocking consecutive calls to WriteHeader alters expected behavior and will -// remove warning logs from net/http where developers will notice incorrect handler implementations. -func (w *respWriterWrapper) WriteHeader(statusCode int) { - if !w.wroteHeader { - w.wroteHeader = true - w.statusCode = statusCode - } - w.ResponseWriter.WriteHeader(statusCode) -} - -func (w *respWriterWrapper) Flush() { - if !w.wroteHeader { - w.WriteHeader(http.StatusOK) - } - - if f, ok := w.ResponseWriter.(http.Flusher); ok { - f.Flush() - } -} diff --git a/vendor/go.opentelemetry.io/otel/CHANGELOG.md b/vendor/go.opentelemetry.io/otel/CHANGELOG.md index a30988f25d..599d59cd13 100644 --- a/vendor/go.opentelemetry.io/otel/CHANGELOG.md +++ b/vendor/go.opentelemetry.io/otel/CHANGELOG.md @@ -8,6 +8,21 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased] + + + +## [1.34.0/0.56.0/0.10.0] 2025-01-17 + +### Changed + +- Remove the notices from `Logger` to make the whole Logs API user-facing in `go.opentelemetry.io/otel/log`. (#6167) + +### Fixed + +- Relax minimum Go version to 1.22.0 in various modules. (#6073) +- The `Type` name logged for the `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc` client is corrected from `otlphttpgrpc` to `otlptracegrpc`. (#6143) +- The `Type` name logged for the `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlphttpgrpc` client is corrected from `otlphttphttp` to `otlptracehttp`. (#6143) + ## [1.33.0/0.55.0/0.9.0/0.0.12] 2024-12-12 ### Added @@ -37,9 +52,6 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Fix attribute value truncation in `go.opentelemetry.io/otel/sdk/trace`. (#5997) - Fix attribute value truncation in `go.opentelemetry.io/otel/sdk/log`. (#6032) - - - ## [1.32.0/0.54.0/0.8.0/0.0.11] 2024-11-08 ### Added @@ -3185,7 +3197,8 @@ It contains api and sdk for trace and meter. - CircleCI build CI manifest files. - CODEOWNERS file to track owners of this project. -[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.33.0...HEAD +[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.34.0...HEAD +[1.34.0/0.56.0/0.10.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.34.0 [1.33.0/0.55.0/0.9.0/0.0.12]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.33.0 [1.32.0/0.54.0/0.8.0/0.0.11]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.32.0 [1.31.0/0.53.0/0.7.0/0.0.10]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.31.0 diff --git a/vendor/go.opentelemetry.io/otel/README.md b/vendor/go.opentelemetry.io/otel/README.md index efec278905..d9a1920762 100644 --- a/vendor/go.opentelemetry.io/otel/README.md +++ b/vendor/go.opentelemetry.io/otel/README.md @@ -1,6 +1,6 @@ # OpenTelemetry-Go -[![CI](https://github.com/open-telemetry/opentelemetry-go/workflows/ci/badge.svg)](https://github.com/open-telemetry/opentelemetry-go/actions?query=workflow%3Aci+branch%3Amain) +[![ci](https://github.com/open-telemetry/opentelemetry-go/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/open-telemetry/opentelemetry-go/actions/workflows/ci.yml) [![codecov.io](https://codecov.io/gh/open-telemetry/opentelemetry-go/coverage.svg?branch=main)](https://app.codecov.io/gh/open-telemetry/opentelemetry-go?branch=main) [![PkgGoDev](https://pkg.go.dev/badge/go.opentelemetry.io/otel)](https://pkg.go.dev/go.opentelemetry.io/otel) [![Go Report Card](https://goreportcard.com/badge/go.opentelemetry.io/otel)](https://goreportcard.com/report/go.opentelemetry.io/otel) diff --git a/vendor/go.opentelemetry.io/otel/RELEASING.md b/vendor/go.opentelemetry.io/otel/RELEASING.md index ffa9b61258..4ebef4f9dd 100644 --- a/vendor/go.opentelemetry.io/otel/RELEASING.md +++ b/vendor/go.opentelemetry.io/otel/RELEASING.md @@ -130,6 +130,6 @@ Importantly, bump any package versions referenced to be the latest one you just Bump the dependencies in the following Go services: -- [`accountingservice`](https://github.com/open-telemetry/opentelemetry-demo/tree/main/src/accountingservice) -- [`checkoutservice`](https://github.com/open-telemetry/opentelemetry-demo/tree/main/src/checkoutservice) -- [`productcatalogservice`](https://github.com/open-telemetry/opentelemetry-demo/tree/main/src/productcatalogservice) +- [`accounting`](https://github.com/open-telemetry/opentelemetry-demo/tree/main/src/accounting) +- [`checkoutservice`](https://github.com/open-telemetry/opentelemetry-demo/tree/main/src/checkout) +- [`productcatalogservice`](https://github.com/open-telemetry/opentelemetry-demo/tree/main/src/product-catalog) diff --git a/vendor/go.opentelemetry.io/otel/metric/noop/README.md b/vendor/go.opentelemetry.io/otel/metric/noop/README.md new file mode 100644 index 0000000000..bb89694356 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/metric/noop/README.md @@ -0,0 +1,3 @@ +# Metric Noop + +[![PkgGoDev](https://pkg.go.dev/badge/go.opentelemetry.io/otel/metric/noop)](https://pkg.go.dev/go.opentelemetry.io/otel/metric/noop) diff --git a/vendor/go.opentelemetry.io/otel/metric/noop/noop.go b/vendor/go.opentelemetry.io/otel/metric/noop/noop.go new file mode 100644 index 0000000000..ca6fcbdc09 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/metric/noop/noop.go @@ -0,0 +1,281 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Package noop provides an implementation of the OpenTelemetry metric API that +// produces no telemetry and minimizes used computation resources. +// +// Using this package to implement the OpenTelemetry metric API will +// effectively disable OpenTelemetry. +// +// This implementation can be embedded in other implementations of the +// OpenTelemetry metric API. Doing so will mean the implementation defaults to +// no operation for methods it does not implement. +package noop // import "go.opentelemetry.io/otel/metric/noop" + +import ( + "context" + + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/metric/embedded" +) + +var ( + // Compile-time check this implements the OpenTelemetry API. + + _ metric.MeterProvider = MeterProvider{} + _ metric.Meter = Meter{} + _ metric.Observer = Observer{} + _ metric.Registration = Registration{} + _ metric.Int64Counter = Int64Counter{} + _ metric.Float64Counter = Float64Counter{} + _ metric.Int64UpDownCounter = Int64UpDownCounter{} + _ metric.Float64UpDownCounter = Float64UpDownCounter{} + _ metric.Int64Histogram = Int64Histogram{} + _ metric.Float64Histogram = Float64Histogram{} + _ metric.Int64Gauge = Int64Gauge{} + _ metric.Float64Gauge = Float64Gauge{} + _ metric.Int64ObservableCounter = Int64ObservableCounter{} + _ metric.Float64ObservableCounter = Float64ObservableCounter{} + _ metric.Int64ObservableGauge = Int64ObservableGauge{} + _ metric.Float64ObservableGauge = Float64ObservableGauge{} + _ metric.Int64ObservableUpDownCounter = Int64ObservableUpDownCounter{} + _ metric.Float64ObservableUpDownCounter = Float64ObservableUpDownCounter{} + _ metric.Int64Observer = Int64Observer{} + _ metric.Float64Observer = Float64Observer{} +) + +// MeterProvider is an OpenTelemetry No-Op MeterProvider. +type MeterProvider struct{ embedded.MeterProvider } + +// NewMeterProvider returns a MeterProvider that does not record any telemetry. +func NewMeterProvider() MeterProvider { + return MeterProvider{} +} + +// Meter returns an OpenTelemetry Meter that does not record any telemetry. +func (MeterProvider) Meter(string, ...metric.MeterOption) metric.Meter { + return Meter{} +} + +// Meter is an OpenTelemetry No-Op Meter. +type Meter struct{ embedded.Meter } + +// Int64Counter returns a Counter used to record int64 measurements that +// produces no telemetry. +func (Meter) Int64Counter(string, ...metric.Int64CounterOption) (metric.Int64Counter, error) { + return Int64Counter{}, nil +} + +// Int64UpDownCounter returns an UpDownCounter used to record int64 +// measurements that produces no telemetry. +func (Meter) Int64UpDownCounter(string, ...metric.Int64UpDownCounterOption) (metric.Int64UpDownCounter, error) { + return Int64UpDownCounter{}, nil +} + +// Int64Histogram returns a Histogram used to record int64 measurements that +// produces no telemetry. +func (Meter) Int64Histogram(string, ...metric.Int64HistogramOption) (metric.Int64Histogram, error) { + return Int64Histogram{}, nil +} + +// Int64Gauge returns a Gauge used to record int64 measurements that +// produces no telemetry. +func (Meter) Int64Gauge(string, ...metric.Int64GaugeOption) (metric.Int64Gauge, error) { + return Int64Gauge{}, nil +} + +// Int64ObservableCounter returns an ObservableCounter used to record int64 +// measurements that produces no telemetry. +func (Meter) Int64ObservableCounter(string, ...metric.Int64ObservableCounterOption) (metric.Int64ObservableCounter, error) { + return Int64ObservableCounter{}, nil +} + +// Int64ObservableUpDownCounter returns an ObservableUpDownCounter used to +// record int64 measurements that produces no telemetry. +func (Meter) Int64ObservableUpDownCounter(string, ...metric.Int64ObservableUpDownCounterOption) (metric.Int64ObservableUpDownCounter, error) { + return Int64ObservableUpDownCounter{}, nil +} + +// Int64ObservableGauge returns an ObservableGauge used to record int64 +// measurements that produces no telemetry. +func (Meter) Int64ObservableGauge(string, ...metric.Int64ObservableGaugeOption) (metric.Int64ObservableGauge, error) { + return Int64ObservableGauge{}, nil +} + +// Float64Counter returns a Counter used to record int64 measurements that +// produces no telemetry. +func (Meter) Float64Counter(string, ...metric.Float64CounterOption) (metric.Float64Counter, error) { + return Float64Counter{}, nil +} + +// Float64UpDownCounter returns an UpDownCounter used to record int64 +// measurements that produces no telemetry. +func (Meter) Float64UpDownCounter(string, ...metric.Float64UpDownCounterOption) (metric.Float64UpDownCounter, error) { + return Float64UpDownCounter{}, nil +} + +// Float64Histogram returns a Histogram used to record int64 measurements that +// produces no telemetry. +func (Meter) Float64Histogram(string, ...metric.Float64HistogramOption) (metric.Float64Histogram, error) { + return Float64Histogram{}, nil +} + +// Float64Gauge returns a Gauge used to record float64 measurements that +// produces no telemetry. +func (Meter) Float64Gauge(string, ...metric.Float64GaugeOption) (metric.Float64Gauge, error) { + return Float64Gauge{}, nil +} + +// Float64ObservableCounter returns an ObservableCounter used to record int64 +// measurements that produces no telemetry. +func (Meter) Float64ObservableCounter(string, ...metric.Float64ObservableCounterOption) (metric.Float64ObservableCounter, error) { + return Float64ObservableCounter{}, nil +} + +// Float64ObservableUpDownCounter returns an ObservableUpDownCounter used to +// record int64 measurements that produces no telemetry. +func (Meter) Float64ObservableUpDownCounter(string, ...metric.Float64ObservableUpDownCounterOption) (metric.Float64ObservableUpDownCounter, error) { + return Float64ObservableUpDownCounter{}, nil +} + +// Float64ObservableGauge returns an ObservableGauge used to record int64 +// measurements that produces no telemetry. +func (Meter) Float64ObservableGauge(string, ...metric.Float64ObservableGaugeOption) (metric.Float64ObservableGauge, error) { + return Float64ObservableGauge{}, nil +} + +// RegisterCallback performs no operation. +func (Meter) RegisterCallback(metric.Callback, ...metric.Observable) (metric.Registration, error) { + return Registration{}, nil +} + +// Observer acts as a recorder of measurements for multiple instruments in a +// Callback, it performing no operation. +type Observer struct{ embedded.Observer } + +// ObserveFloat64 performs no operation. +func (Observer) ObserveFloat64(metric.Float64Observable, float64, ...metric.ObserveOption) { +} + +// ObserveInt64 performs no operation. +func (Observer) ObserveInt64(metric.Int64Observable, int64, ...metric.ObserveOption) { +} + +// Registration is the registration of a Callback with a No-Op Meter. +type Registration struct{ embedded.Registration } + +// Unregister unregisters the Callback the Registration represents with the +// No-Op Meter. This will always return nil because the No-Op Meter performs no +// operation, including hold any record of registrations. +func (Registration) Unregister() error { return nil } + +// Int64Counter is an OpenTelemetry Counter used to record int64 measurements. +// It produces no telemetry. +type Int64Counter struct{ embedded.Int64Counter } + +// Add performs no operation. +func (Int64Counter) Add(context.Context, int64, ...metric.AddOption) {} + +// Float64Counter is an OpenTelemetry Counter used to record float64 +// measurements. It produces no telemetry. +type Float64Counter struct{ embedded.Float64Counter } + +// Add performs no operation. +func (Float64Counter) Add(context.Context, float64, ...metric.AddOption) {} + +// Int64UpDownCounter is an OpenTelemetry UpDownCounter used to record int64 +// measurements. It produces no telemetry. +type Int64UpDownCounter struct{ embedded.Int64UpDownCounter } + +// Add performs no operation. +func (Int64UpDownCounter) Add(context.Context, int64, ...metric.AddOption) {} + +// Float64UpDownCounter is an OpenTelemetry UpDownCounter used to record +// float64 measurements. It produces no telemetry. +type Float64UpDownCounter struct{ embedded.Float64UpDownCounter } + +// Add performs no operation. +func (Float64UpDownCounter) Add(context.Context, float64, ...metric.AddOption) {} + +// Int64Histogram is an OpenTelemetry Histogram used to record int64 +// measurements. It produces no telemetry. +type Int64Histogram struct{ embedded.Int64Histogram } + +// Record performs no operation. +func (Int64Histogram) Record(context.Context, int64, ...metric.RecordOption) {} + +// Float64Histogram is an OpenTelemetry Histogram used to record float64 +// measurements. It produces no telemetry. +type Float64Histogram struct{ embedded.Float64Histogram } + +// Record performs no operation. +func (Float64Histogram) Record(context.Context, float64, ...metric.RecordOption) {} + +// Int64Gauge is an OpenTelemetry Gauge used to record instantaneous int64 +// measurements. It produces no telemetry. +type Int64Gauge struct{ embedded.Int64Gauge } + +// Record performs no operation. +func (Int64Gauge) Record(context.Context, int64, ...metric.RecordOption) {} + +// Float64Gauge is an OpenTelemetry Gauge used to record instantaneous float64 +// measurements. It produces no telemetry. +type Float64Gauge struct{ embedded.Float64Gauge } + +// Record performs no operation. +func (Float64Gauge) Record(context.Context, float64, ...metric.RecordOption) {} + +// Int64ObservableCounter is an OpenTelemetry ObservableCounter used to record +// int64 measurements. It produces no telemetry. +type Int64ObservableCounter struct { + metric.Int64Observable + embedded.Int64ObservableCounter +} + +// Float64ObservableCounter is an OpenTelemetry ObservableCounter used to record +// float64 measurements. It produces no telemetry. +type Float64ObservableCounter struct { + metric.Float64Observable + embedded.Float64ObservableCounter +} + +// Int64ObservableGauge is an OpenTelemetry ObservableGauge used to record +// int64 measurements. It produces no telemetry. +type Int64ObservableGauge struct { + metric.Int64Observable + embedded.Int64ObservableGauge +} + +// Float64ObservableGauge is an OpenTelemetry ObservableGauge used to record +// float64 measurements. It produces no telemetry. +type Float64ObservableGauge struct { + metric.Float64Observable + embedded.Float64ObservableGauge +} + +// Int64ObservableUpDownCounter is an OpenTelemetry ObservableUpDownCounter +// used to record int64 measurements. It produces no telemetry. +type Int64ObservableUpDownCounter struct { + metric.Int64Observable + embedded.Int64ObservableUpDownCounter +} + +// Float64ObservableUpDownCounter is an OpenTelemetry ObservableUpDownCounter +// used to record float64 measurements. It produces no telemetry. +type Float64ObservableUpDownCounter struct { + metric.Float64Observable + embedded.Float64ObservableUpDownCounter +} + +// Int64Observer is a recorder of int64 measurements that performs no operation. +type Int64Observer struct{ embedded.Int64Observer } + +// Observe performs no operation. +func (Int64Observer) Observe(int64, ...metric.ObserveOption) {} + +// Float64Observer is a recorder of float64 measurements that performs no +// operation. +type Float64Observer struct{ embedded.Float64Observer } + +// Observe performs no operation. +func (Float64Observer) Observe(float64, ...metric.ObserveOption) {} diff --git a/vendor/go.opentelemetry.io/otel/renovate.json b/vendor/go.opentelemetry.io/otel/renovate.json index 0a29a2f13d..4f80c898a1 100644 --- a/vendor/go.opentelemetry.io/otel/renovate.json +++ b/vendor/go.opentelemetry.io/otel/renovate.json @@ -14,12 +14,6 @@ "matchDepTypes": ["indirect"], "enabled": true }, - { - "matchFileNames": ["internal/tools/**"], - "matchManagers": ["gomod"], - "matchDepTypes": ["indirect"], - "enabled": false - }, { "matchPackageNames": ["google.golang.org/genproto/googleapis/**"], "groupName": "googleapis" diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/README.md b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/README.md deleted file mode 100644 index 0b6cbe960c..0000000000 --- a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Semconv v1.24.0 - -[![PkgGoDev](https://pkg.go.dev/badge/go.opentelemetry.io/otel/semconv/v1.24.0)](https://pkg.go.dev/go.opentelemetry.io/otel/semconv/v1.24.0) diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/attribute_group.go b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/attribute_group.go deleted file mode 100644 index 6e688345cb..0000000000 --- a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/attribute_group.go +++ /dev/null @@ -1,4387 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -// Code generated from semantic convention specification. DO NOT EDIT. - -package semconv // import "go.opentelemetry.io/otel/semconv/v1.24.0" - -import "go.opentelemetry.io/otel/attribute" - -// Describes FaaS attributes. -const ( - // FaaSInvokedNameKey is the attribute Key conforming to the - // "faas.invoked_name" semantic conventions. It represents the name of the - // invoked function. - // - // Type: string - // RequirementLevel: Required - // Stability: experimental - // Examples: 'my-function' - // Note: SHOULD be equal to the `faas.name` resource attribute of the - // invoked function. - FaaSInvokedNameKey = attribute.Key("faas.invoked_name") - - // FaaSInvokedProviderKey is the attribute Key conforming to the - // "faas.invoked_provider" semantic conventions. It represents the cloud - // provider of the invoked function. - // - // Type: Enum - // RequirementLevel: Required - // Stability: experimental - // Note: SHOULD be equal to the `cloud.provider` resource attribute of the - // invoked function. - FaaSInvokedProviderKey = attribute.Key("faas.invoked_provider") - - // FaaSInvokedRegionKey is the attribute Key conforming to the - // "faas.invoked_region" semantic conventions. It represents the cloud - // region of the invoked function. - // - // Type: string - // RequirementLevel: ConditionallyRequired (For some cloud providers, like - // AWS or GCP, the region in which a function is hosted is essential to - // uniquely identify the function and also part of its endpoint. Since it's - // part of the endpoint being called, the region is always known to - // clients. In these cases, `faas.invoked_region` MUST be set accordingly. - // If the region is unknown to the client or not required for identifying - // the invoked function, setting `faas.invoked_region` is optional.) - // Stability: experimental - // Examples: 'eu-central-1' - // Note: SHOULD be equal to the `cloud.region` resource attribute of the - // invoked function. - FaaSInvokedRegionKey = attribute.Key("faas.invoked_region") - - // FaaSTriggerKey is the attribute Key conforming to the "faas.trigger" - // semantic conventions. It represents the type of the trigger which caused - // this function invocation. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - FaaSTriggerKey = attribute.Key("faas.trigger") -) - -var ( - // Alibaba Cloud - FaaSInvokedProviderAlibabaCloud = FaaSInvokedProviderKey.String("alibaba_cloud") - // Amazon Web Services - FaaSInvokedProviderAWS = FaaSInvokedProviderKey.String("aws") - // Microsoft Azure - FaaSInvokedProviderAzure = FaaSInvokedProviderKey.String("azure") - // Google Cloud Platform - FaaSInvokedProviderGCP = FaaSInvokedProviderKey.String("gcp") - // Tencent Cloud - FaaSInvokedProviderTencentCloud = FaaSInvokedProviderKey.String("tencent_cloud") -) - -var ( - // A response to some data source operation such as a database or filesystem read/write - FaaSTriggerDatasource = FaaSTriggerKey.String("datasource") - // To provide an answer to an inbound HTTP request - FaaSTriggerHTTP = FaaSTriggerKey.String("http") - // A function is set to be executed when messages are sent to a messaging system - FaaSTriggerPubsub = FaaSTriggerKey.String("pubsub") - // A function is scheduled to be executed regularly - FaaSTriggerTimer = FaaSTriggerKey.String("timer") - // If none of the others apply - FaaSTriggerOther = FaaSTriggerKey.String("other") -) - -// FaaSInvokedName returns an attribute KeyValue conforming to the -// "faas.invoked_name" semantic conventions. It represents the name of the -// invoked function. -func FaaSInvokedName(val string) attribute.KeyValue { - return FaaSInvokedNameKey.String(val) -} - -// FaaSInvokedRegion returns an attribute KeyValue conforming to the -// "faas.invoked_region" semantic conventions. It represents the cloud region -// of the invoked function. -func FaaSInvokedRegion(val string) attribute.KeyValue { - return FaaSInvokedRegionKey.String(val) -} - -// Attributes for Events represented using Log Records. -const ( - // EventNameKey is the attribute Key conforming to the "event.name" - // semantic conventions. It represents the identifies the class / type of - // event. - // - // Type: string - // RequirementLevel: Required - // Stability: experimental - // Examples: 'browser.mouse.click', 'device.app.lifecycle' - // Note: Event names are subject to the same rules as [attribute - // names](https://github.com/open-telemetry/opentelemetry-specification/tree/v1.26.0/specification/common/attribute-naming.md). - // Notably, event names are namespaced to avoid collisions and provide a - // clean separation of semantics for events in separate domains like - // browser, mobile, and kubernetes. - EventNameKey = attribute.Key("event.name") -) - -// EventName returns an attribute KeyValue conforming to the "event.name" -// semantic conventions. It represents the identifies the class / type of -// event. -func EventName(val string) attribute.KeyValue { - return EventNameKey.String(val) -} - -// The attributes described in this section are rather generic. They may be -// used in any Log Record they apply to. -const ( - // LogRecordUIDKey is the attribute Key conforming to the "log.record.uid" - // semantic conventions. It represents a unique identifier for the Log - // Record. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '01ARZ3NDEKTSV4RRFFQ69G5FAV' - // Note: If an id is provided, other log records with the same id will be - // considered duplicates and can be removed safely. This means, that two - // distinguishable log records MUST have different values. - // The id MAY be an [Universally Unique Lexicographically Sortable - // Identifier (ULID)](https://github.com/ulid/spec), but other identifiers - // (e.g. UUID) may be used as needed. - LogRecordUIDKey = attribute.Key("log.record.uid") -) - -// LogRecordUID returns an attribute KeyValue conforming to the -// "log.record.uid" semantic conventions. It represents a unique identifier for -// the Log Record. -func LogRecordUID(val string) attribute.KeyValue { - return LogRecordUIDKey.String(val) -} - -// Describes Log attributes -const ( - // LogIostreamKey is the attribute Key conforming to the "log.iostream" - // semantic conventions. It represents the stream associated with the log. - // See below for a list of well-known values. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - LogIostreamKey = attribute.Key("log.iostream") -) - -var ( - // Logs from stdout stream - LogIostreamStdout = LogIostreamKey.String("stdout") - // Events from stderr stream - LogIostreamStderr = LogIostreamKey.String("stderr") -) - -// A file to which log was emitted. -const ( - // LogFileNameKey is the attribute Key conforming to the "log.file.name" - // semantic conventions. It represents the basename of the file. - // - // Type: string - // RequirementLevel: Recommended - // Stability: experimental - // Examples: 'audit.log' - LogFileNameKey = attribute.Key("log.file.name") - - // LogFileNameResolvedKey is the attribute Key conforming to the - // "log.file.name_resolved" semantic conventions. It represents the - // basename of the file, with symlinks resolved. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'uuid.log' - LogFileNameResolvedKey = attribute.Key("log.file.name_resolved") - - // LogFilePathKey is the attribute Key conforming to the "log.file.path" - // semantic conventions. It represents the full path to the file. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '/var/log/mysql/audit.log' - LogFilePathKey = attribute.Key("log.file.path") - - // LogFilePathResolvedKey is the attribute Key conforming to the - // "log.file.path_resolved" semantic conventions. It represents the full - // path to the file, with symlinks resolved. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '/var/lib/docker/uuid.log' - LogFilePathResolvedKey = attribute.Key("log.file.path_resolved") -) - -// LogFileName returns an attribute KeyValue conforming to the -// "log.file.name" semantic conventions. It represents the basename of the -// file. -func LogFileName(val string) attribute.KeyValue { - return LogFileNameKey.String(val) -} - -// LogFileNameResolved returns an attribute KeyValue conforming to the -// "log.file.name_resolved" semantic conventions. It represents the basename of -// the file, with symlinks resolved. -func LogFileNameResolved(val string) attribute.KeyValue { - return LogFileNameResolvedKey.String(val) -} - -// LogFilePath returns an attribute KeyValue conforming to the -// "log.file.path" semantic conventions. It represents the full path to the -// file. -func LogFilePath(val string) attribute.KeyValue { - return LogFilePathKey.String(val) -} - -// LogFilePathResolved returns an attribute KeyValue conforming to the -// "log.file.path_resolved" semantic conventions. It represents the full path -// to the file, with symlinks resolved. -func LogFilePathResolved(val string) attribute.KeyValue { - return LogFilePathResolvedKey.String(val) -} - -// Describes Database attributes -const ( - // PoolNameKey is the attribute Key conforming to the "pool.name" semantic - // conventions. It represents the name of the connection pool; unique - // within the instrumented application. In case the connection pool - // implementation doesn't provide a name, then the - // [db.connection_string](/docs/database/database-spans.md#connection-level-attributes) - // should be used - // - // Type: string - // RequirementLevel: Required - // Stability: experimental - // Examples: 'myDataSource' - PoolNameKey = attribute.Key("pool.name") - - // StateKey is the attribute Key conforming to the "state" semantic - // conventions. It represents the state of a connection in the pool - // - // Type: Enum - // RequirementLevel: Required - // Stability: experimental - // Examples: 'idle' - StateKey = attribute.Key("state") -) - -var ( - // idle - StateIdle = StateKey.String("idle") - // used - StateUsed = StateKey.String("used") -) - -// PoolName returns an attribute KeyValue conforming to the "pool.name" -// semantic conventions. It represents the name of the connection pool; unique -// within the instrumented application. In case the connection pool -// implementation doesn't provide a name, then the -// [db.connection_string](/docs/database/database-spans.md#connection-level-attributes) -// should be used -func PoolName(val string) attribute.KeyValue { - return PoolNameKey.String(val) -} - -// ASP.NET Core attributes -const ( - // AspnetcoreDiagnosticsHandlerTypeKey is the attribute Key conforming to - // the "aspnetcore.diagnostics.handler.type" semantic conventions. It - // represents the full type name of the - // [`IExceptionHandler`](https://learn.microsoft.com/dotnet/api/microsoft.aspnetcore.diagnostics.iexceptionhandler) - // implementation that handled the exception. - // - // Type: string - // RequirementLevel: ConditionallyRequired (if and only if the exception - // was handled by this handler.) - // Stability: experimental - // Examples: 'Contoso.MyHandler' - AspnetcoreDiagnosticsHandlerTypeKey = attribute.Key("aspnetcore.diagnostics.handler.type") - - // AspnetcoreRateLimitingPolicyKey is the attribute Key conforming to the - // "aspnetcore.rate_limiting.policy" semantic conventions. It represents - // the rate limiting policy name. - // - // Type: string - // RequirementLevel: ConditionallyRequired (if the matched endpoint for the - // request had a rate-limiting policy.) - // Stability: experimental - // Examples: 'fixed', 'sliding', 'token' - AspnetcoreRateLimitingPolicyKey = attribute.Key("aspnetcore.rate_limiting.policy") - - // AspnetcoreRateLimitingResultKey is the attribute Key conforming to the - // "aspnetcore.rate_limiting.result" semantic conventions. It represents - // the rate-limiting result, shows whether the lease was acquired or - // contains a rejection reason - // - // Type: Enum - // RequirementLevel: Required - // Stability: experimental - // Examples: 'acquired', 'request_canceled' - AspnetcoreRateLimitingResultKey = attribute.Key("aspnetcore.rate_limiting.result") - - // AspnetcoreRequestIsUnhandledKey is the attribute Key conforming to the - // "aspnetcore.request.is_unhandled" semantic conventions. It represents - // the flag indicating if request was handled by the application pipeline. - // - // Type: boolean - // RequirementLevel: ConditionallyRequired (if and only if the request was - // not handled.) - // Stability: experimental - // Examples: True - AspnetcoreRequestIsUnhandledKey = attribute.Key("aspnetcore.request.is_unhandled") - - // AspnetcoreRoutingIsFallbackKey is the attribute Key conforming to the - // "aspnetcore.routing.is_fallback" semantic conventions. It represents a - // value that indicates whether the matched route is a fallback route. - // - // Type: boolean - // RequirementLevel: ConditionallyRequired (If and only if a route was - // successfully matched.) - // Stability: experimental - // Examples: True - AspnetcoreRoutingIsFallbackKey = attribute.Key("aspnetcore.routing.is_fallback") -) - -var ( - // Lease was acquired - AspnetcoreRateLimitingResultAcquired = AspnetcoreRateLimitingResultKey.String("acquired") - // Lease request was rejected by the endpoint limiter - AspnetcoreRateLimitingResultEndpointLimiter = AspnetcoreRateLimitingResultKey.String("endpoint_limiter") - // Lease request was rejected by the global limiter - AspnetcoreRateLimitingResultGlobalLimiter = AspnetcoreRateLimitingResultKey.String("global_limiter") - // Lease request was canceled - AspnetcoreRateLimitingResultRequestCanceled = AspnetcoreRateLimitingResultKey.String("request_canceled") -) - -// AspnetcoreDiagnosticsHandlerType returns an attribute KeyValue conforming -// to the "aspnetcore.diagnostics.handler.type" semantic conventions. It -// represents the full type name of the -// [`IExceptionHandler`](https://learn.microsoft.com/dotnet/api/microsoft.aspnetcore.diagnostics.iexceptionhandler) -// implementation that handled the exception. -func AspnetcoreDiagnosticsHandlerType(val string) attribute.KeyValue { - return AspnetcoreDiagnosticsHandlerTypeKey.String(val) -} - -// AspnetcoreRateLimitingPolicy returns an attribute KeyValue conforming to -// the "aspnetcore.rate_limiting.policy" semantic conventions. It represents -// the rate limiting policy name. -func AspnetcoreRateLimitingPolicy(val string) attribute.KeyValue { - return AspnetcoreRateLimitingPolicyKey.String(val) -} - -// AspnetcoreRequestIsUnhandled returns an attribute KeyValue conforming to -// the "aspnetcore.request.is_unhandled" semantic conventions. It represents -// the flag indicating if request was handled by the application pipeline. -func AspnetcoreRequestIsUnhandled(val bool) attribute.KeyValue { - return AspnetcoreRequestIsUnhandledKey.Bool(val) -} - -// AspnetcoreRoutingIsFallback returns an attribute KeyValue conforming to -// the "aspnetcore.routing.is_fallback" semantic conventions. It represents a -// value that indicates whether the matched route is a fallback route. -func AspnetcoreRoutingIsFallback(val bool) attribute.KeyValue { - return AspnetcoreRoutingIsFallbackKey.Bool(val) -} - -// SignalR attributes -const ( - // SignalrConnectionStatusKey is the attribute Key conforming to the - // "signalr.connection.status" semantic conventions. It represents the - // signalR HTTP connection closure status. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'app_shutdown', 'timeout' - SignalrConnectionStatusKey = attribute.Key("signalr.connection.status") - - // SignalrTransportKey is the attribute Key conforming to the - // "signalr.transport" semantic conventions. It represents the [SignalR - // transport - // type](https://github.com/dotnet/aspnetcore/blob/main/src/SignalR/docs/specs/TransportProtocols.md) - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'web_sockets', 'long_polling' - SignalrTransportKey = attribute.Key("signalr.transport") -) - -var ( - // The connection was closed normally - SignalrConnectionStatusNormalClosure = SignalrConnectionStatusKey.String("normal_closure") - // The connection was closed due to a timeout - SignalrConnectionStatusTimeout = SignalrConnectionStatusKey.String("timeout") - // The connection was closed because the app is shutting down - SignalrConnectionStatusAppShutdown = SignalrConnectionStatusKey.String("app_shutdown") -) - -var ( - // ServerSentEvents protocol - SignalrTransportServerSentEvents = SignalrTransportKey.String("server_sent_events") - // LongPolling protocol - SignalrTransportLongPolling = SignalrTransportKey.String("long_polling") - // WebSockets protocol - SignalrTransportWebSockets = SignalrTransportKey.String("web_sockets") -) - -// Describes JVM buffer metric attributes. -const ( - // JvmBufferPoolNameKey is the attribute Key conforming to the - // "jvm.buffer.pool.name" semantic conventions. It represents the name of - // the buffer pool. - // - // Type: string - // RequirementLevel: Recommended - // Stability: experimental - // Examples: 'mapped', 'direct' - // Note: Pool names are generally obtained via - // [BufferPoolMXBean#getName()](https://docs.oracle.com/en/java/javase/11/docs/api/java.management/java/lang/management/BufferPoolMXBean.html#getName()). - JvmBufferPoolNameKey = attribute.Key("jvm.buffer.pool.name") -) - -// JvmBufferPoolName returns an attribute KeyValue conforming to the -// "jvm.buffer.pool.name" semantic conventions. It represents the name of the -// buffer pool. -func JvmBufferPoolName(val string) attribute.KeyValue { - return JvmBufferPoolNameKey.String(val) -} - -// Describes JVM memory metric attributes. -const ( - // JvmMemoryPoolNameKey is the attribute Key conforming to the - // "jvm.memory.pool.name" semantic conventions. It represents the name of - // the memory pool. - // - // Type: string - // RequirementLevel: Recommended - // Stability: stable - // Examples: 'G1 Old Gen', 'G1 Eden space', 'G1 Survivor Space' - // Note: Pool names are generally obtained via - // [MemoryPoolMXBean#getName()](https://docs.oracle.com/en/java/javase/11/docs/api/java.management/java/lang/management/MemoryPoolMXBean.html#getName()). - JvmMemoryPoolNameKey = attribute.Key("jvm.memory.pool.name") - - // JvmMemoryTypeKey is the attribute Key conforming to the - // "jvm.memory.type" semantic conventions. It represents the type of - // memory. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: stable - // Examples: 'heap', 'non_heap' - JvmMemoryTypeKey = attribute.Key("jvm.memory.type") -) - -var ( - // Heap memory - JvmMemoryTypeHeap = JvmMemoryTypeKey.String("heap") - // Non-heap memory - JvmMemoryTypeNonHeap = JvmMemoryTypeKey.String("non_heap") -) - -// JvmMemoryPoolName returns an attribute KeyValue conforming to the -// "jvm.memory.pool.name" semantic conventions. It represents the name of the -// memory pool. -func JvmMemoryPoolName(val string) attribute.KeyValue { - return JvmMemoryPoolNameKey.String(val) -} - -// Describes System metric attributes -const ( - // SystemDeviceKey is the attribute Key conforming to the "system.device" - // semantic conventions. It represents the device identifier - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '(identifier)' - SystemDeviceKey = attribute.Key("system.device") -) - -// SystemDevice returns an attribute KeyValue conforming to the -// "system.device" semantic conventions. It represents the device identifier -func SystemDevice(val string) attribute.KeyValue { - return SystemDeviceKey.String(val) -} - -// Describes System CPU metric attributes -const ( - // SystemCPULogicalNumberKey is the attribute Key conforming to the - // "system.cpu.logical_number" semantic conventions. It represents the - // logical CPU number [0..n-1] - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 1 - SystemCPULogicalNumberKey = attribute.Key("system.cpu.logical_number") - - // SystemCPUStateKey is the attribute Key conforming to the - // "system.cpu.state" semantic conventions. It represents the state of the - // CPU - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'idle', 'interrupt' - SystemCPUStateKey = attribute.Key("system.cpu.state") -) - -var ( - // user - SystemCPUStateUser = SystemCPUStateKey.String("user") - // system - SystemCPUStateSystem = SystemCPUStateKey.String("system") - // nice - SystemCPUStateNice = SystemCPUStateKey.String("nice") - // idle - SystemCPUStateIdle = SystemCPUStateKey.String("idle") - // iowait - SystemCPUStateIowait = SystemCPUStateKey.String("iowait") - // interrupt - SystemCPUStateInterrupt = SystemCPUStateKey.String("interrupt") - // steal - SystemCPUStateSteal = SystemCPUStateKey.String("steal") -) - -// SystemCPULogicalNumber returns an attribute KeyValue conforming to the -// "system.cpu.logical_number" semantic conventions. It represents the logical -// CPU number [0..n-1] -func SystemCPULogicalNumber(val int) attribute.KeyValue { - return SystemCPULogicalNumberKey.Int(val) -} - -// Describes System Memory metric attributes -const ( - // SystemMemoryStateKey is the attribute Key conforming to the - // "system.memory.state" semantic conventions. It represents the memory - // state - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'free', 'cached' - SystemMemoryStateKey = attribute.Key("system.memory.state") -) - -var ( - // used - SystemMemoryStateUsed = SystemMemoryStateKey.String("used") - // free - SystemMemoryStateFree = SystemMemoryStateKey.String("free") - // shared - SystemMemoryStateShared = SystemMemoryStateKey.String("shared") - // buffers - SystemMemoryStateBuffers = SystemMemoryStateKey.String("buffers") - // cached - SystemMemoryStateCached = SystemMemoryStateKey.String("cached") -) - -// Describes System Memory Paging metric attributes -const ( - // SystemPagingDirectionKey is the attribute Key conforming to the - // "system.paging.direction" semantic conventions. It represents the paging - // access direction - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'in' - SystemPagingDirectionKey = attribute.Key("system.paging.direction") - - // SystemPagingStateKey is the attribute Key conforming to the - // "system.paging.state" semantic conventions. It represents the memory - // paging state - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'free' - SystemPagingStateKey = attribute.Key("system.paging.state") - - // SystemPagingTypeKey is the attribute Key conforming to the - // "system.paging.type" semantic conventions. It represents the memory - // paging type - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'minor' - SystemPagingTypeKey = attribute.Key("system.paging.type") -) - -var ( - // in - SystemPagingDirectionIn = SystemPagingDirectionKey.String("in") - // out - SystemPagingDirectionOut = SystemPagingDirectionKey.String("out") -) - -var ( - // used - SystemPagingStateUsed = SystemPagingStateKey.String("used") - // free - SystemPagingStateFree = SystemPagingStateKey.String("free") -) - -var ( - // major - SystemPagingTypeMajor = SystemPagingTypeKey.String("major") - // minor - SystemPagingTypeMinor = SystemPagingTypeKey.String("minor") -) - -// Describes Filesystem metric attributes -const ( - // SystemFilesystemModeKey is the attribute Key conforming to the - // "system.filesystem.mode" semantic conventions. It represents the - // filesystem mode - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'rw, ro' - SystemFilesystemModeKey = attribute.Key("system.filesystem.mode") - - // SystemFilesystemMountpointKey is the attribute Key conforming to the - // "system.filesystem.mountpoint" semantic conventions. It represents the - // filesystem mount path - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '/mnt/data' - SystemFilesystemMountpointKey = attribute.Key("system.filesystem.mountpoint") - - // SystemFilesystemStateKey is the attribute Key conforming to the - // "system.filesystem.state" semantic conventions. It represents the - // filesystem state - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'used' - SystemFilesystemStateKey = attribute.Key("system.filesystem.state") - - // SystemFilesystemTypeKey is the attribute Key conforming to the - // "system.filesystem.type" semantic conventions. It represents the - // filesystem type - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'ext4' - SystemFilesystemTypeKey = attribute.Key("system.filesystem.type") -) - -var ( - // used - SystemFilesystemStateUsed = SystemFilesystemStateKey.String("used") - // free - SystemFilesystemStateFree = SystemFilesystemStateKey.String("free") - // reserved - SystemFilesystemStateReserved = SystemFilesystemStateKey.String("reserved") -) - -var ( - // fat32 - SystemFilesystemTypeFat32 = SystemFilesystemTypeKey.String("fat32") - // exfat - SystemFilesystemTypeExfat = SystemFilesystemTypeKey.String("exfat") - // ntfs - SystemFilesystemTypeNtfs = SystemFilesystemTypeKey.String("ntfs") - // refs - SystemFilesystemTypeRefs = SystemFilesystemTypeKey.String("refs") - // hfsplus - SystemFilesystemTypeHfsplus = SystemFilesystemTypeKey.String("hfsplus") - // ext4 - SystemFilesystemTypeExt4 = SystemFilesystemTypeKey.String("ext4") -) - -// SystemFilesystemMode returns an attribute KeyValue conforming to the -// "system.filesystem.mode" semantic conventions. It represents the filesystem -// mode -func SystemFilesystemMode(val string) attribute.KeyValue { - return SystemFilesystemModeKey.String(val) -} - -// SystemFilesystemMountpoint returns an attribute KeyValue conforming to -// the "system.filesystem.mountpoint" semantic conventions. It represents the -// filesystem mount path -func SystemFilesystemMountpoint(val string) attribute.KeyValue { - return SystemFilesystemMountpointKey.String(val) -} - -// Describes Network metric attributes -const ( - // SystemNetworkStateKey is the attribute Key conforming to the - // "system.network.state" semantic conventions. It represents a stateless - // protocol MUST NOT set this attribute - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'close_wait' - SystemNetworkStateKey = attribute.Key("system.network.state") -) - -var ( - // close - SystemNetworkStateClose = SystemNetworkStateKey.String("close") - // close_wait - SystemNetworkStateCloseWait = SystemNetworkStateKey.String("close_wait") - // closing - SystemNetworkStateClosing = SystemNetworkStateKey.String("closing") - // delete - SystemNetworkStateDelete = SystemNetworkStateKey.String("delete") - // established - SystemNetworkStateEstablished = SystemNetworkStateKey.String("established") - // fin_wait_1 - SystemNetworkStateFinWait1 = SystemNetworkStateKey.String("fin_wait_1") - // fin_wait_2 - SystemNetworkStateFinWait2 = SystemNetworkStateKey.String("fin_wait_2") - // last_ack - SystemNetworkStateLastAck = SystemNetworkStateKey.String("last_ack") - // listen - SystemNetworkStateListen = SystemNetworkStateKey.String("listen") - // syn_recv - SystemNetworkStateSynRecv = SystemNetworkStateKey.String("syn_recv") - // syn_sent - SystemNetworkStateSynSent = SystemNetworkStateKey.String("syn_sent") - // time_wait - SystemNetworkStateTimeWait = SystemNetworkStateKey.String("time_wait") -) - -// Describes System Process metric attributes -const ( - // SystemProcessesStatusKey is the attribute Key conforming to the - // "system.processes.status" semantic conventions. It represents the - // process state, e.g., [Linux Process State - // Codes](https://man7.org/linux/man-pages/man1/ps.1.html#PROCESS_STATE_CODES) - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'running' - SystemProcessesStatusKey = attribute.Key("system.processes.status") -) - -var ( - // running - SystemProcessesStatusRunning = SystemProcessesStatusKey.String("running") - // sleeping - SystemProcessesStatusSleeping = SystemProcessesStatusKey.String("sleeping") - // stopped - SystemProcessesStatusStopped = SystemProcessesStatusKey.String("stopped") - // defunct - SystemProcessesStatusDefunct = SystemProcessesStatusKey.String("defunct") -) - -// These attributes may be used to describe the client in a connection-based -// network interaction where there is one side that initiates the connection -// (the client is the side that initiates the connection). This covers all TCP -// network interactions since TCP is connection-based and one side initiates -// the connection (an exception is made for peer-to-peer communication over TCP -// where the "user-facing" surface of the protocol / API doesn't expose a clear -// notion of client and server). This also covers UDP network interactions -// where one side initiates the interaction, e.g. QUIC (HTTP/3) and DNS. -const ( - // ClientAddressKey is the attribute Key conforming to the "client.address" - // semantic conventions. It represents the client address - domain name if - // available without reverse DNS lookup; otherwise, IP address or Unix - // domain socket name. - // - // Type: string - // RequirementLevel: Optional - // Stability: stable - // Examples: 'client.example.com', '10.1.2.80', '/tmp/my.sock' - // Note: When observed from the server side, and when communicating through - // an intermediary, `client.address` SHOULD represent the client address - // behind any intermediaries, for example proxies, if it's available. - ClientAddressKey = attribute.Key("client.address") - - // ClientPortKey is the attribute Key conforming to the "client.port" - // semantic conventions. It represents the client port number. - // - // Type: int - // RequirementLevel: Optional - // Stability: stable - // Examples: 65123 - // Note: When observed from the server side, and when communicating through - // an intermediary, `client.port` SHOULD represent the client port behind - // any intermediaries, for example proxies, if it's available. - ClientPortKey = attribute.Key("client.port") -) - -// ClientAddress returns an attribute KeyValue conforming to the -// "client.address" semantic conventions. It represents the client address - -// domain name if available without reverse DNS lookup; otherwise, IP address -// or Unix domain socket name. -func ClientAddress(val string) attribute.KeyValue { - return ClientAddressKey.String(val) -} - -// ClientPort returns an attribute KeyValue conforming to the "client.port" -// semantic conventions. It represents the client port number. -func ClientPort(val int) attribute.KeyValue { - return ClientPortKey.Int(val) -} - -// The attributes used to describe telemetry in the context of databases. -const ( - // DBCassandraConsistencyLevelKey is the attribute Key conforming to the - // "db.cassandra.consistency_level" semantic conventions. It represents the - // consistency level of the query. Based on consistency values from - // [CQL](https://docs.datastax.com/en/cassandra-oss/3.0/cassandra/dml/dmlConfigConsistency.html). - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - DBCassandraConsistencyLevelKey = attribute.Key("db.cassandra.consistency_level") - - // DBCassandraCoordinatorDCKey is the attribute Key conforming to the - // "db.cassandra.coordinator.dc" semantic conventions. It represents the - // data center of the coordinating node for a query. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'us-west-2' - DBCassandraCoordinatorDCKey = attribute.Key("db.cassandra.coordinator.dc") - - // DBCassandraCoordinatorIDKey is the attribute Key conforming to the - // "db.cassandra.coordinator.id" semantic conventions. It represents the ID - // of the coordinating node for a query. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'be13faa2-8574-4d71-926d-27f16cf8a7af' - DBCassandraCoordinatorIDKey = attribute.Key("db.cassandra.coordinator.id") - - // DBCassandraIdempotenceKey is the attribute Key conforming to the - // "db.cassandra.idempotence" semantic conventions. It represents the - // whether or not the query is idempotent. - // - // Type: boolean - // RequirementLevel: Optional - // Stability: experimental - DBCassandraIdempotenceKey = attribute.Key("db.cassandra.idempotence") - - // DBCassandraPageSizeKey is the attribute Key conforming to the - // "db.cassandra.page_size" semantic conventions. It represents the fetch - // size used for paging, i.e. how many rows will be returned at once. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 5000 - DBCassandraPageSizeKey = attribute.Key("db.cassandra.page_size") - - // DBCassandraSpeculativeExecutionCountKey is the attribute Key conforming - // to the "db.cassandra.speculative_execution_count" semantic conventions. - // It represents the number of times a query was speculatively executed. - // Not set or `0` if the query was not executed speculatively. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 0, 2 - DBCassandraSpeculativeExecutionCountKey = attribute.Key("db.cassandra.speculative_execution_count") - - // DBCassandraTableKey is the attribute Key conforming to the - // "db.cassandra.table" semantic conventions. It represents the name of the - // primary Cassandra table that the operation is acting upon, including the - // keyspace name (if applicable). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'mytable' - // Note: This mirrors the db.sql.table attribute but references cassandra - // rather than sql. It is not recommended to attempt any client-side - // parsing of `db.statement` just to get this property, but it should be - // set if it is provided by the library being instrumented. If the - // operation is acting upon an anonymous table, or more than one table, - // this value MUST NOT be set. - DBCassandraTableKey = attribute.Key("db.cassandra.table") - - // DBConnectionStringKey is the attribute Key conforming to the - // "db.connection_string" semantic conventions. It represents the - // connection string used to connect to the database. It is recommended to - // remove embedded credentials. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'Server=(localdb)\\v11.0;Integrated Security=true;' - DBConnectionStringKey = attribute.Key("db.connection_string") - - // DBCosmosDBClientIDKey is the attribute Key conforming to the - // "db.cosmosdb.client_id" semantic conventions. It represents the unique - // Cosmos client instance id. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '3ba4827d-4422-483f-b59f-85b74211c11d' - DBCosmosDBClientIDKey = attribute.Key("db.cosmosdb.client_id") - - // DBCosmosDBConnectionModeKey is the attribute Key conforming to the - // "db.cosmosdb.connection_mode" semantic conventions. It represents the - // cosmos client connection mode. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - DBCosmosDBConnectionModeKey = attribute.Key("db.cosmosdb.connection_mode") - - // DBCosmosDBContainerKey is the attribute Key conforming to the - // "db.cosmosdb.container" semantic conventions. It represents the cosmos - // DB container name. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'anystring' - DBCosmosDBContainerKey = attribute.Key("db.cosmosdb.container") - - // DBCosmosDBOperationTypeKey is the attribute Key conforming to the - // "db.cosmosdb.operation_type" semantic conventions. It represents the - // cosmosDB Operation Type. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - DBCosmosDBOperationTypeKey = attribute.Key("db.cosmosdb.operation_type") - - // DBCosmosDBRequestChargeKey is the attribute Key conforming to the - // "db.cosmosdb.request_charge" semantic conventions. It represents the rU - // consumed for that operation - // - // Type: double - // RequirementLevel: Optional - // Stability: experimental - // Examples: 46.18, 1.0 - DBCosmosDBRequestChargeKey = attribute.Key("db.cosmosdb.request_charge") - - // DBCosmosDBRequestContentLengthKey is the attribute Key conforming to the - // "db.cosmosdb.request_content_length" semantic conventions. It represents - // the request payload size in bytes - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - DBCosmosDBRequestContentLengthKey = attribute.Key("db.cosmosdb.request_content_length") - - // DBCosmosDBStatusCodeKey is the attribute Key conforming to the - // "db.cosmosdb.status_code" semantic conventions. It represents the cosmos - // DB status code. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 200, 201 - DBCosmosDBStatusCodeKey = attribute.Key("db.cosmosdb.status_code") - - // DBCosmosDBSubStatusCodeKey is the attribute Key conforming to the - // "db.cosmosdb.sub_status_code" semantic conventions. It represents the - // cosmos DB sub status code. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 1000, 1002 - DBCosmosDBSubStatusCodeKey = attribute.Key("db.cosmosdb.sub_status_code") - - // DBElasticsearchClusterNameKey is the attribute Key conforming to the - // "db.elasticsearch.cluster.name" semantic conventions. It represents the - // represents the identifier of an Elasticsearch cluster. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'e9106fc68e3044f0b1475b04bf4ffd5f' - DBElasticsearchClusterNameKey = attribute.Key("db.elasticsearch.cluster.name") - - // DBElasticsearchNodeNameKey is the attribute Key conforming to the - // "db.elasticsearch.node.name" semantic conventions. It represents the - // represents the human-readable identifier of the node/instance to which a - // request was routed. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'instance-0000000001' - DBElasticsearchNodeNameKey = attribute.Key("db.elasticsearch.node.name") - - // DBInstanceIDKey is the attribute Key conforming to the "db.instance.id" - // semantic conventions. It represents an identifier (address, unique name, - // or any other identifier) of the database instance that is executing - // queries or mutations on the current connection. This is useful in cases - // where the database is running in a clustered environment and the - // instrumentation is able to record the node executing the query. The - // client may obtain this value in databases like MySQL using queries like - // `select @@hostname`. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'mysql-e26b99z.example.com' - DBInstanceIDKey = attribute.Key("db.instance.id") - - // DBJDBCDriverClassnameKey is the attribute Key conforming to the - // "db.jdbc.driver_classname" semantic conventions. It represents the - // fully-qualified class name of the [Java Database Connectivity - // (JDBC)](https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/) - // driver used to connect. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'org.postgresql.Driver', - // 'com.microsoft.sqlserver.jdbc.SQLServerDriver' - DBJDBCDriverClassnameKey = attribute.Key("db.jdbc.driver_classname") - - // DBMongoDBCollectionKey is the attribute Key conforming to the - // "db.mongodb.collection" semantic conventions. It represents the MongoDB - // collection being accessed within the database stated in `db.name`. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'customers', 'products' - DBMongoDBCollectionKey = attribute.Key("db.mongodb.collection") - - // DBMSSQLInstanceNameKey is the attribute Key conforming to the - // "db.mssql.instance_name" semantic conventions. It represents the - // Microsoft SQL Server [instance - // name](https://docs.microsoft.com/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver15) - // connecting to. This name is used to determine the port of a named - // instance. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'MSSQLSERVER' - // Note: If setting a `db.mssql.instance_name`, `server.port` is no longer - // required (but still recommended if non-standard). - DBMSSQLInstanceNameKey = attribute.Key("db.mssql.instance_name") - - // DBNameKey is the attribute Key conforming to the "db.name" semantic - // conventions. It represents the this attribute is used to report the name - // of the database being accessed. For commands that switch the database, - // this should be set to the target database (even if the command fails). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'customers', 'main' - // Note: In some SQL databases, the database name to be used is called - // "schema name". In case there are multiple layers that could be - // considered for database name (e.g. Oracle instance name and schema - // name), the database name to be used is the more specific layer (e.g. - // Oracle schema name). - DBNameKey = attribute.Key("db.name") - - // DBOperationKey is the attribute Key conforming to the "db.operation" - // semantic conventions. It represents the name of the operation being - // executed, e.g. the [MongoDB command - // name](https://docs.mongodb.com/manual/reference/command/#database-operations) - // such as `findAndModify`, or the SQL keyword. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'findAndModify', 'HMSET', 'SELECT' - // Note: When setting this to an SQL keyword, it is not recommended to - // attempt any client-side parsing of `db.statement` just to get this - // property, but it should be set if the operation name is provided by the - // library being instrumented. If the SQL statement has an ambiguous - // operation, or performs more than one operation, this value may be - // omitted. - DBOperationKey = attribute.Key("db.operation") - - // DBRedisDBIndexKey is the attribute Key conforming to the - // "db.redis.database_index" semantic conventions. It represents the index - // of the database being accessed as used in the [`SELECT` - // command](https://redis.io/commands/select), provided as an integer. To - // be used instead of the generic `db.name` attribute. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 0, 1, 15 - DBRedisDBIndexKey = attribute.Key("db.redis.database_index") - - // DBSQLTableKey is the attribute Key conforming to the "db.sql.table" - // semantic conventions. It represents the name of the primary table that - // the operation is acting upon, including the database name (if - // applicable). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'public.users', 'customers' - // Note: It is not recommended to attempt any client-side parsing of - // `db.statement` just to get this property, but it should be set if it is - // provided by the library being instrumented. If the operation is acting - // upon an anonymous table, or more than one table, this value MUST NOT be - // set. - DBSQLTableKey = attribute.Key("db.sql.table") - - // DBStatementKey is the attribute Key conforming to the "db.statement" - // semantic conventions. It represents the database statement being - // executed. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'SELECT * FROM wuser_table', 'SET mykey "WuValue"' - DBStatementKey = attribute.Key("db.statement") - - // DBSystemKey is the attribute Key conforming to the "db.system" semantic - // conventions. It represents an identifier for the database management - // system (DBMS) product being used. See below for a list of well-known - // identifiers. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - DBSystemKey = attribute.Key("db.system") - - // DBUserKey is the attribute Key conforming to the "db.user" semantic - // conventions. It represents the username for accessing the database. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'readonly_user', 'reporting_user' - DBUserKey = attribute.Key("db.user") -) - -var ( - // all - DBCassandraConsistencyLevelAll = DBCassandraConsistencyLevelKey.String("all") - // each_quorum - DBCassandraConsistencyLevelEachQuorum = DBCassandraConsistencyLevelKey.String("each_quorum") - // quorum - DBCassandraConsistencyLevelQuorum = DBCassandraConsistencyLevelKey.String("quorum") - // local_quorum - DBCassandraConsistencyLevelLocalQuorum = DBCassandraConsistencyLevelKey.String("local_quorum") - // one - DBCassandraConsistencyLevelOne = DBCassandraConsistencyLevelKey.String("one") - // two - DBCassandraConsistencyLevelTwo = DBCassandraConsistencyLevelKey.String("two") - // three - DBCassandraConsistencyLevelThree = DBCassandraConsistencyLevelKey.String("three") - // local_one - DBCassandraConsistencyLevelLocalOne = DBCassandraConsistencyLevelKey.String("local_one") - // any - DBCassandraConsistencyLevelAny = DBCassandraConsistencyLevelKey.String("any") - // serial - DBCassandraConsistencyLevelSerial = DBCassandraConsistencyLevelKey.String("serial") - // local_serial - DBCassandraConsistencyLevelLocalSerial = DBCassandraConsistencyLevelKey.String("local_serial") -) - -var ( - // Gateway (HTTP) connections mode - DBCosmosDBConnectionModeGateway = DBCosmosDBConnectionModeKey.String("gateway") - // Direct connection - DBCosmosDBConnectionModeDirect = DBCosmosDBConnectionModeKey.String("direct") -) - -var ( - // invalid - DBCosmosDBOperationTypeInvalid = DBCosmosDBOperationTypeKey.String("Invalid") - // create - DBCosmosDBOperationTypeCreate = DBCosmosDBOperationTypeKey.String("Create") - // patch - DBCosmosDBOperationTypePatch = DBCosmosDBOperationTypeKey.String("Patch") - // read - DBCosmosDBOperationTypeRead = DBCosmosDBOperationTypeKey.String("Read") - // read_feed - DBCosmosDBOperationTypeReadFeed = DBCosmosDBOperationTypeKey.String("ReadFeed") - // delete - DBCosmosDBOperationTypeDelete = DBCosmosDBOperationTypeKey.String("Delete") - // replace - DBCosmosDBOperationTypeReplace = DBCosmosDBOperationTypeKey.String("Replace") - // execute - DBCosmosDBOperationTypeExecute = DBCosmosDBOperationTypeKey.String("Execute") - // query - DBCosmosDBOperationTypeQuery = DBCosmosDBOperationTypeKey.String("Query") - // head - DBCosmosDBOperationTypeHead = DBCosmosDBOperationTypeKey.String("Head") - // head_feed - DBCosmosDBOperationTypeHeadFeed = DBCosmosDBOperationTypeKey.String("HeadFeed") - // upsert - DBCosmosDBOperationTypeUpsert = DBCosmosDBOperationTypeKey.String("Upsert") - // batch - DBCosmosDBOperationTypeBatch = DBCosmosDBOperationTypeKey.String("Batch") - // query_plan - DBCosmosDBOperationTypeQueryPlan = DBCosmosDBOperationTypeKey.String("QueryPlan") - // execute_javascript - DBCosmosDBOperationTypeExecuteJavascript = DBCosmosDBOperationTypeKey.String("ExecuteJavaScript") -) - -var ( - // Some other SQL database. Fallback only. See notes - DBSystemOtherSQL = DBSystemKey.String("other_sql") - // Microsoft SQL Server - DBSystemMSSQL = DBSystemKey.String("mssql") - // Microsoft SQL Server Compact - DBSystemMssqlcompact = DBSystemKey.String("mssqlcompact") - // MySQL - DBSystemMySQL = DBSystemKey.String("mysql") - // Oracle Database - DBSystemOracle = DBSystemKey.String("oracle") - // IBM DB2 - DBSystemDB2 = DBSystemKey.String("db2") - // PostgreSQL - DBSystemPostgreSQL = DBSystemKey.String("postgresql") - // Amazon Redshift - DBSystemRedshift = DBSystemKey.String("redshift") - // Apache Hive - DBSystemHive = DBSystemKey.String("hive") - // Cloudscape - DBSystemCloudscape = DBSystemKey.String("cloudscape") - // HyperSQL DataBase - DBSystemHSQLDB = DBSystemKey.String("hsqldb") - // Progress Database - DBSystemProgress = DBSystemKey.String("progress") - // SAP MaxDB - DBSystemMaxDB = DBSystemKey.String("maxdb") - // SAP HANA - DBSystemHanaDB = DBSystemKey.String("hanadb") - // Ingres - DBSystemIngres = DBSystemKey.String("ingres") - // FirstSQL - DBSystemFirstSQL = DBSystemKey.String("firstsql") - // EnterpriseDB - DBSystemEDB = DBSystemKey.String("edb") - // InterSystems Caché - DBSystemCache = DBSystemKey.String("cache") - // Adabas (Adaptable Database System) - DBSystemAdabas = DBSystemKey.String("adabas") - // Firebird - DBSystemFirebird = DBSystemKey.String("firebird") - // Apache Derby - DBSystemDerby = DBSystemKey.String("derby") - // FileMaker - DBSystemFilemaker = DBSystemKey.String("filemaker") - // Informix - DBSystemInformix = DBSystemKey.String("informix") - // InstantDB - DBSystemInstantDB = DBSystemKey.String("instantdb") - // InterBase - DBSystemInterbase = DBSystemKey.String("interbase") - // MariaDB - DBSystemMariaDB = DBSystemKey.String("mariadb") - // Netezza - DBSystemNetezza = DBSystemKey.String("netezza") - // Pervasive PSQL - DBSystemPervasive = DBSystemKey.String("pervasive") - // PointBase - DBSystemPointbase = DBSystemKey.String("pointbase") - // SQLite - DBSystemSqlite = DBSystemKey.String("sqlite") - // Sybase - DBSystemSybase = DBSystemKey.String("sybase") - // Teradata - DBSystemTeradata = DBSystemKey.String("teradata") - // Vertica - DBSystemVertica = DBSystemKey.String("vertica") - // H2 - DBSystemH2 = DBSystemKey.String("h2") - // ColdFusion IMQ - DBSystemColdfusion = DBSystemKey.String("coldfusion") - // Apache Cassandra - DBSystemCassandra = DBSystemKey.String("cassandra") - // Apache HBase - DBSystemHBase = DBSystemKey.String("hbase") - // MongoDB - DBSystemMongoDB = DBSystemKey.String("mongodb") - // Redis - DBSystemRedis = DBSystemKey.String("redis") - // Couchbase - DBSystemCouchbase = DBSystemKey.String("couchbase") - // CouchDB - DBSystemCouchDB = DBSystemKey.String("couchdb") - // Microsoft Azure Cosmos DB - DBSystemCosmosDB = DBSystemKey.String("cosmosdb") - // Amazon DynamoDB - DBSystemDynamoDB = DBSystemKey.String("dynamodb") - // Neo4j - DBSystemNeo4j = DBSystemKey.String("neo4j") - // Apache Geode - DBSystemGeode = DBSystemKey.String("geode") - // Elasticsearch - DBSystemElasticsearch = DBSystemKey.String("elasticsearch") - // Memcached - DBSystemMemcached = DBSystemKey.String("memcached") - // CockroachDB - DBSystemCockroachdb = DBSystemKey.String("cockroachdb") - // OpenSearch - DBSystemOpensearch = DBSystemKey.String("opensearch") - // ClickHouse - DBSystemClickhouse = DBSystemKey.String("clickhouse") - // Cloud Spanner - DBSystemSpanner = DBSystemKey.String("spanner") - // Trino - DBSystemTrino = DBSystemKey.String("trino") -) - -// DBCassandraCoordinatorDC returns an attribute KeyValue conforming to the -// "db.cassandra.coordinator.dc" semantic conventions. It represents the data -// center of the coordinating node for a query. -func DBCassandraCoordinatorDC(val string) attribute.KeyValue { - return DBCassandraCoordinatorDCKey.String(val) -} - -// DBCassandraCoordinatorID returns an attribute KeyValue conforming to the -// "db.cassandra.coordinator.id" semantic conventions. It represents the ID of -// the coordinating node for a query. -func DBCassandraCoordinatorID(val string) attribute.KeyValue { - return DBCassandraCoordinatorIDKey.String(val) -} - -// DBCassandraIdempotence returns an attribute KeyValue conforming to the -// "db.cassandra.idempotence" semantic conventions. It represents the whether -// or not the query is idempotent. -func DBCassandraIdempotence(val bool) attribute.KeyValue { - return DBCassandraIdempotenceKey.Bool(val) -} - -// DBCassandraPageSize returns an attribute KeyValue conforming to the -// "db.cassandra.page_size" semantic conventions. It represents the fetch size -// used for paging, i.e. how many rows will be returned at once. -func DBCassandraPageSize(val int) attribute.KeyValue { - return DBCassandraPageSizeKey.Int(val) -} - -// DBCassandraSpeculativeExecutionCount returns an attribute KeyValue -// conforming to the "db.cassandra.speculative_execution_count" semantic -// conventions. It represents the number of times a query was speculatively -// executed. Not set or `0` if the query was not executed speculatively. -func DBCassandraSpeculativeExecutionCount(val int) attribute.KeyValue { - return DBCassandraSpeculativeExecutionCountKey.Int(val) -} - -// DBCassandraTable returns an attribute KeyValue conforming to the -// "db.cassandra.table" semantic conventions. It represents the name of the -// primary Cassandra table that the operation is acting upon, including the -// keyspace name (if applicable). -func DBCassandraTable(val string) attribute.KeyValue { - return DBCassandraTableKey.String(val) -} - -// DBConnectionString returns an attribute KeyValue conforming to the -// "db.connection_string" semantic conventions. It represents the connection -// string used to connect to the database. It is recommended to remove embedded -// credentials. -func DBConnectionString(val string) attribute.KeyValue { - return DBConnectionStringKey.String(val) -} - -// DBCosmosDBClientID returns an attribute KeyValue conforming to the -// "db.cosmosdb.client_id" semantic conventions. It represents the unique -// Cosmos client instance id. -func DBCosmosDBClientID(val string) attribute.KeyValue { - return DBCosmosDBClientIDKey.String(val) -} - -// DBCosmosDBContainer returns an attribute KeyValue conforming to the -// "db.cosmosdb.container" semantic conventions. It represents the cosmos DB -// container name. -func DBCosmosDBContainer(val string) attribute.KeyValue { - return DBCosmosDBContainerKey.String(val) -} - -// DBCosmosDBRequestCharge returns an attribute KeyValue conforming to the -// "db.cosmosdb.request_charge" semantic conventions. It represents the rU -// consumed for that operation -func DBCosmosDBRequestCharge(val float64) attribute.KeyValue { - return DBCosmosDBRequestChargeKey.Float64(val) -} - -// DBCosmosDBRequestContentLength returns an attribute KeyValue conforming -// to the "db.cosmosdb.request_content_length" semantic conventions. It -// represents the request payload size in bytes -func DBCosmosDBRequestContentLength(val int) attribute.KeyValue { - return DBCosmosDBRequestContentLengthKey.Int(val) -} - -// DBCosmosDBStatusCode returns an attribute KeyValue conforming to the -// "db.cosmosdb.status_code" semantic conventions. It represents the cosmos DB -// status code. -func DBCosmosDBStatusCode(val int) attribute.KeyValue { - return DBCosmosDBStatusCodeKey.Int(val) -} - -// DBCosmosDBSubStatusCode returns an attribute KeyValue conforming to the -// "db.cosmosdb.sub_status_code" semantic conventions. It represents the cosmos -// DB sub status code. -func DBCosmosDBSubStatusCode(val int) attribute.KeyValue { - return DBCosmosDBSubStatusCodeKey.Int(val) -} - -// DBElasticsearchClusterName returns an attribute KeyValue conforming to -// the "db.elasticsearch.cluster.name" semantic conventions. It represents the -// represents the identifier of an Elasticsearch cluster. -func DBElasticsearchClusterName(val string) attribute.KeyValue { - return DBElasticsearchClusterNameKey.String(val) -} - -// DBElasticsearchNodeName returns an attribute KeyValue conforming to the -// "db.elasticsearch.node.name" semantic conventions. It represents the -// represents the human-readable identifier of the node/instance to which a -// request was routed. -func DBElasticsearchNodeName(val string) attribute.KeyValue { - return DBElasticsearchNodeNameKey.String(val) -} - -// DBInstanceID returns an attribute KeyValue conforming to the -// "db.instance.id" semantic conventions. It represents an identifier (address, -// unique name, or any other identifier) of the database instance that is -// executing queries or mutations on the current connection. This is useful in -// cases where the database is running in a clustered environment and the -// instrumentation is able to record the node executing the query. The client -// may obtain this value in databases like MySQL using queries like `select -// @@hostname`. -func DBInstanceID(val string) attribute.KeyValue { - return DBInstanceIDKey.String(val) -} - -// DBJDBCDriverClassname returns an attribute KeyValue conforming to the -// "db.jdbc.driver_classname" semantic conventions. It represents the -// fully-qualified class name of the [Java Database Connectivity -// (JDBC)](https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/) driver -// used to connect. -func DBJDBCDriverClassname(val string) attribute.KeyValue { - return DBJDBCDriverClassnameKey.String(val) -} - -// DBMongoDBCollection returns an attribute KeyValue conforming to the -// "db.mongodb.collection" semantic conventions. It represents the MongoDB -// collection being accessed within the database stated in `db.name`. -func DBMongoDBCollection(val string) attribute.KeyValue { - return DBMongoDBCollectionKey.String(val) -} - -// DBMSSQLInstanceName returns an attribute KeyValue conforming to the -// "db.mssql.instance_name" semantic conventions. It represents the Microsoft -// SQL Server [instance -// name](https://docs.microsoft.com/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver15) -// connecting to. This name is used to determine the port of a named instance. -func DBMSSQLInstanceName(val string) attribute.KeyValue { - return DBMSSQLInstanceNameKey.String(val) -} - -// DBName returns an attribute KeyValue conforming to the "db.name" semantic -// conventions. It represents the this attribute is used to report the name of -// the database being accessed. For commands that switch the database, this -// should be set to the target database (even if the command fails). -func DBName(val string) attribute.KeyValue { - return DBNameKey.String(val) -} - -// DBOperation returns an attribute KeyValue conforming to the -// "db.operation" semantic conventions. It represents the name of the operation -// being executed, e.g. the [MongoDB command -// name](https://docs.mongodb.com/manual/reference/command/#database-operations) -// such as `findAndModify`, or the SQL keyword. -func DBOperation(val string) attribute.KeyValue { - return DBOperationKey.String(val) -} - -// DBRedisDBIndex returns an attribute KeyValue conforming to the -// "db.redis.database_index" semantic conventions. It represents the index of -// the database being accessed as used in the [`SELECT` -// command](https://redis.io/commands/select), provided as an integer. To be -// used instead of the generic `db.name` attribute. -func DBRedisDBIndex(val int) attribute.KeyValue { - return DBRedisDBIndexKey.Int(val) -} - -// DBSQLTable returns an attribute KeyValue conforming to the "db.sql.table" -// semantic conventions. It represents the name of the primary table that the -// operation is acting upon, including the database name (if applicable). -func DBSQLTable(val string) attribute.KeyValue { - return DBSQLTableKey.String(val) -} - -// DBStatement returns an attribute KeyValue conforming to the -// "db.statement" semantic conventions. It represents the database statement -// being executed. -func DBStatement(val string) attribute.KeyValue { - return DBStatementKey.String(val) -} - -// DBUser returns an attribute KeyValue conforming to the "db.user" semantic -// conventions. It represents the username for accessing the database. -func DBUser(val string) attribute.KeyValue { - return DBUserKey.String(val) -} - -// Describes deprecated HTTP attributes. -const ( - // HTTPFlavorKey is the attribute Key conforming to the "http.flavor" - // semantic conventions. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: deprecated - // Deprecated: use `network.protocol.name` instead. - HTTPFlavorKey = attribute.Key("http.flavor") - - // HTTPMethodKey is the attribute Key conforming to the "http.method" - // semantic conventions. - // - // Type: string - // RequirementLevel: Optional - // Stability: deprecated - // Examples: 'GET', 'POST', 'HEAD' - // Deprecated: use `http.request.method` instead. - HTTPMethodKey = attribute.Key("http.method") - - // HTTPRequestContentLengthKey is the attribute Key conforming to the - // "http.request_content_length" semantic conventions. - // - // Type: int - // RequirementLevel: Optional - // Stability: deprecated - // Examples: 3495 - // Deprecated: use `http.request.header.content-length` instead. - HTTPRequestContentLengthKey = attribute.Key("http.request_content_length") - - // HTTPResponseContentLengthKey is the attribute Key conforming to the - // "http.response_content_length" semantic conventions. - // - // Type: int - // RequirementLevel: Optional - // Stability: deprecated - // Examples: 3495 - // Deprecated: use `http.response.header.content-length` instead. - HTTPResponseContentLengthKey = attribute.Key("http.response_content_length") - - // HTTPSchemeKey is the attribute Key conforming to the "http.scheme" - // semantic conventions. - // - // Type: string - // RequirementLevel: Optional - // Stability: deprecated - // Examples: 'http', 'https' - // Deprecated: use `url.scheme` instead. - HTTPSchemeKey = attribute.Key("http.scheme") - - // HTTPStatusCodeKey is the attribute Key conforming to the - // "http.status_code" semantic conventions. - // - // Type: int - // RequirementLevel: Optional - // Stability: deprecated - // Examples: 200 - // Deprecated: use `http.response.status_code` instead. - HTTPStatusCodeKey = attribute.Key("http.status_code") - - // HTTPTargetKey is the attribute Key conforming to the "http.target" - // semantic conventions. - // - // Type: string - // RequirementLevel: Optional - // Stability: deprecated - // Examples: '/search?q=OpenTelemetry#SemConv' - // Deprecated: use `url.path` and `url.query` instead. - HTTPTargetKey = attribute.Key("http.target") - - // HTTPURLKey is the attribute Key conforming to the "http.url" semantic - // conventions. - // - // Type: string - // RequirementLevel: Optional - // Stability: deprecated - // Examples: 'https://www.foo.bar/search?q=OpenTelemetry#SemConv' - // Deprecated: use `url.full` instead. - HTTPURLKey = attribute.Key("http.url") - - // HTTPUserAgentKey is the attribute Key conforming to the - // "http.user_agent" semantic conventions. - // - // Type: string - // RequirementLevel: Optional - // Stability: deprecated - // Examples: 'CERN-LineMode/2.15 libwww/2.17b3', 'Mozilla/5.0 (iPhone; CPU - // iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) - // Version/14.1.2 Mobile/15E148 Safari/604.1' - // Deprecated: use `user_agent.original` instead. - HTTPUserAgentKey = attribute.Key("http.user_agent") -) - -var ( - // HTTP/1.0 - // - // Deprecated: use `network.protocol.name` instead. - HTTPFlavorHTTP10 = HTTPFlavorKey.String("1.0") - // HTTP/1.1 - // - // Deprecated: use `network.protocol.name` instead. - HTTPFlavorHTTP11 = HTTPFlavorKey.String("1.1") - // HTTP/2 - // - // Deprecated: use `network.protocol.name` instead. - HTTPFlavorHTTP20 = HTTPFlavorKey.String("2.0") - // HTTP/3 - // - // Deprecated: use `network.protocol.name` instead. - HTTPFlavorHTTP30 = HTTPFlavorKey.String("3.0") - // SPDY protocol - // - // Deprecated: use `network.protocol.name` instead. - HTTPFlavorSPDY = HTTPFlavorKey.String("SPDY") - // QUIC protocol - // - // Deprecated: use `network.protocol.name` instead. - HTTPFlavorQUIC = HTTPFlavorKey.String("QUIC") -) - -// HTTPMethod returns an attribute KeyValue conforming to the "http.method" -// semantic conventions. -// -// Deprecated: use `http.request.method` instead. -func HTTPMethod(val string) attribute.KeyValue { - return HTTPMethodKey.String(val) -} - -// HTTPRequestContentLength returns an attribute KeyValue conforming to the -// "http.request_content_length" semantic conventions. -// -// Deprecated: use `http.request.header.content-length` instead. -func HTTPRequestContentLength(val int) attribute.KeyValue { - return HTTPRequestContentLengthKey.Int(val) -} - -// HTTPResponseContentLength returns an attribute KeyValue conforming to the -// "http.response_content_length" semantic conventions. -// -// Deprecated: use `http.response.header.content-length` instead. -func HTTPResponseContentLength(val int) attribute.KeyValue { - return HTTPResponseContentLengthKey.Int(val) -} - -// HTTPScheme returns an attribute KeyValue conforming to the "http.scheme" -// semantic conventions. -// -// Deprecated: use `url.scheme` instead. -func HTTPScheme(val string) attribute.KeyValue { - return HTTPSchemeKey.String(val) -} - -// HTTPStatusCode returns an attribute KeyValue conforming to the -// "http.status_code" semantic conventions. -// -// Deprecated: use `http.response.status_code` instead. -func HTTPStatusCode(val int) attribute.KeyValue { - return HTTPStatusCodeKey.Int(val) -} - -// HTTPTarget returns an attribute KeyValue conforming to the "http.target" -// semantic conventions. -// -// Deprecated: use `url.path` and `url.query` instead. -func HTTPTarget(val string) attribute.KeyValue { - return HTTPTargetKey.String(val) -} - -// HTTPURL returns an attribute KeyValue conforming to the "http.url" -// semantic conventions. -// -// Deprecated: use `url.full` instead. -func HTTPURL(val string) attribute.KeyValue { - return HTTPURLKey.String(val) -} - -// HTTPUserAgent returns an attribute KeyValue conforming to the -// "http.user_agent" semantic conventions. -// -// Deprecated: use `user_agent.original` instead. -func HTTPUserAgent(val string) attribute.KeyValue { - return HTTPUserAgentKey.String(val) -} - -// These attributes may be used for any network related operation. -const ( - // NetHostNameKey is the attribute Key conforming to the "net.host.name" - // semantic conventions. - // - // Type: string - // RequirementLevel: Optional - // Stability: deprecated - // Examples: 'example.com' - // Deprecated: use `server.address`. - NetHostNameKey = attribute.Key("net.host.name") - - // NetHostPortKey is the attribute Key conforming to the "net.host.port" - // semantic conventions. - // - // Type: int - // RequirementLevel: Optional - // Stability: deprecated - // Examples: 8080 - // Deprecated: use `server.port`. - NetHostPortKey = attribute.Key("net.host.port") - - // NetPeerNameKey is the attribute Key conforming to the "net.peer.name" - // semantic conventions. - // - // Type: string - // RequirementLevel: Optional - // Stability: deprecated - // Examples: 'example.com' - // Deprecated: use `server.address` on client spans and `client.address` on - // server spans. - NetPeerNameKey = attribute.Key("net.peer.name") - - // NetPeerPortKey is the attribute Key conforming to the "net.peer.port" - // semantic conventions. - // - // Type: int - // RequirementLevel: Optional - // Stability: deprecated - // Examples: 8080 - // Deprecated: use `server.port` on client spans and `client.port` on - // server spans. - NetPeerPortKey = attribute.Key("net.peer.port") - - // NetProtocolNameKey is the attribute Key conforming to the - // "net.protocol.name" semantic conventions. - // - // Type: string - // RequirementLevel: Optional - // Stability: deprecated - // Examples: 'amqp', 'http', 'mqtt' - // Deprecated: use `network.protocol.name`. - NetProtocolNameKey = attribute.Key("net.protocol.name") - - // NetProtocolVersionKey is the attribute Key conforming to the - // "net.protocol.version" semantic conventions. - // - // Type: string - // RequirementLevel: Optional - // Stability: deprecated - // Examples: '3.1.1' - // Deprecated: use `network.protocol.version`. - NetProtocolVersionKey = attribute.Key("net.protocol.version") - - // NetSockFamilyKey is the attribute Key conforming to the - // "net.sock.family" semantic conventions. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: deprecated - // Deprecated: use `network.transport` and `network.type`. - NetSockFamilyKey = attribute.Key("net.sock.family") - - // NetSockHostAddrKey is the attribute Key conforming to the - // "net.sock.host.addr" semantic conventions. - // - // Type: string - // RequirementLevel: Optional - // Stability: deprecated - // Examples: '/var/my.sock' - // Deprecated: use `network.local.address`. - NetSockHostAddrKey = attribute.Key("net.sock.host.addr") - - // NetSockHostPortKey is the attribute Key conforming to the - // "net.sock.host.port" semantic conventions. - // - // Type: int - // RequirementLevel: Optional - // Stability: deprecated - // Examples: 8080 - // Deprecated: use `network.local.port`. - NetSockHostPortKey = attribute.Key("net.sock.host.port") - - // NetSockPeerAddrKey is the attribute Key conforming to the - // "net.sock.peer.addr" semantic conventions. - // - // Type: string - // RequirementLevel: Optional - // Stability: deprecated - // Examples: '192.168.0.1' - // Deprecated: use `network.peer.address`. - NetSockPeerAddrKey = attribute.Key("net.sock.peer.addr") - - // NetSockPeerNameKey is the attribute Key conforming to the - // "net.sock.peer.name" semantic conventions. - // - // Type: string - // RequirementLevel: Optional - // Stability: deprecated - // Examples: '/var/my.sock' - // Deprecated: no replacement at this time. - NetSockPeerNameKey = attribute.Key("net.sock.peer.name") - - // NetSockPeerPortKey is the attribute Key conforming to the - // "net.sock.peer.port" semantic conventions. - // - // Type: int - // RequirementLevel: Optional - // Stability: deprecated - // Examples: 65531 - // Deprecated: use `network.peer.port`. - NetSockPeerPortKey = attribute.Key("net.sock.peer.port") - - // NetTransportKey is the attribute Key conforming to the "net.transport" - // semantic conventions. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: deprecated - // Deprecated: use `network.transport`. - NetTransportKey = attribute.Key("net.transport") -) - -var ( - // IPv4 address - // - // Deprecated: use `network.transport` and `network.type`. - NetSockFamilyInet = NetSockFamilyKey.String("inet") - // IPv6 address - // - // Deprecated: use `network.transport` and `network.type`. - NetSockFamilyInet6 = NetSockFamilyKey.String("inet6") - // Unix domain socket path - // - // Deprecated: use `network.transport` and `network.type`. - NetSockFamilyUnix = NetSockFamilyKey.String("unix") -) - -var ( - // ip_tcp - // - // Deprecated: use `network.transport`. - NetTransportTCP = NetTransportKey.String("ip_tcp") - // ip_udp - // - // Deprecated: use `network.transport`. - NetTransportUDP = NetTransportKey.String("ip_udp") - // Named or anonymous pipe - // - // Deprecated: use `network.transport`. - NetTransportPipe = NetTransportKey.String("pipe") - // In-process communication - // - // Deprecated: use `network.transport`. - NetTransportInProc = NetTransportKey.String("inproc") - // Something else (non IP-based) - // - // Deprecated: use `network.transport`. - NetTransportOther = NetTransportKey.String("other") -) - -// NetHostName returns an attribute KeyValue conforming to the -// "net.host.name" semantic conventions. -// -// Deprecated: use `server.address`. -func NetHostName(val string) attribute.KeyValue { - return NetHostNameKey.String(val) -} - -// NetHostPort returns an attribute KeyValue conforming to the -// "net.host.port" semantic conventions. -// -// Deprecated: use `server.port`. -func NetHostPort(val int) attribute.KeyValue { - return NetHostPortKey.Int(val) -} - -// NetPeerName returns an attribute KeyValue conforming to the -// "net.peer.name" semantic conventions. -// -// Deprecated: use `server.address` on client spans and `client.address` on -// server spans. -func NetPeerName(val string) attribute.KeyValue { - return NetPeerNameKey.String(val) -} - -// NetPeerPort returns an attribute KeyValue conforming to the -// "net.peer.port" semantic conventions. -// -// Deprecated: use `server.port` on client spans and `client.port` on server -// spans. -func NetPeerPort(val int) attribute.KeyValue { - return NetPeerPortKey.Int(val) -} - -// NetProtocolName returns an attribute KeyValue conforming to the -// "net.protocol.name" semantic conventions. -// -// Deprecated: use `network.protocol.name`. -func NetProtocolName(val string) attribute.KeyValue { - return NetProtocolNameKey.String(val) -} - -// NetProtocolVersion returns an attribute KeyValue conforming to the -// "net.protocol.version" semantic conventions. -// -// Deprecated: use `network.protocol.version`. -func NetProtocolVersion(val string) attribute.KeyValue { - return NetProtocolVersionKey.String(val) -} - -// NetSockHostAddr returns an attribute KeyValue conforming to the -// "net.sock.host.addr" semantic conventions. -// -// Deprecated: use `network.local.address`. -func NetSockHostAddr(val string) attribute.KeyValue { - return NetSockHostAddrKey.String(val) -} - -// NetSockHostPort returns an attribute KeyValue conforming to the -// "net.sock.host.port" semantic conventions. -// -// Deprecated: use `network.local.port`. -func NetSockHostPort(val int) attribute.KeyValue { - return NetSockHostPortKey.Int(val) -} - -// NetSockPeerAddr returns an attribute KeyValue conforming to the -// "net.sock.peer.addr" semantic conventions. -// -// Deprecated: use `network.peer.address`. -func NetSockPeerAddr(val string) attribute.KeyValue { - return NetSockPeerAddrKey.String(val) -} - -// NetSockPeerName returns an attribute KeyValue conforming to the -// "net.sock.peer.name" semantic conventions. -// -// Deprecated: no replacement at this time. -func NetSockPeerName(val string) attribute.KeyValue { - return NetSockPeerNameKey.String(val) -} - -// NetSockPeerPort returns an attribute KeyValue conforming to the -// "net.sock.peer.port" semantic conventions. -// -// Deprecated: use `network.peer.port`. -func NetSockPeerPort(val int) attribute.KeyValue { - return NetSockPeerPortKey.Int(val) -} - -// These attributes may be used to describe the receiver of a network -// exchange/packet. These should be used when there is no client/server -// relationship between the two sides, or when that relationship is unknown. -// This covers low-level network interactions (e.g. packet tracing) where you -// don't know if there was a connection or which side initiated it. This also -// covers unidirectional UDP flows and peer-to-peer communication where the -// "user-facing" surface of the protocol / API doesn't expose a clear notion of -// client and server. -const ( - // DestinationAddressKey is the attribute Key conforming to the - // "destination.address" semantic conventions. It represents the - // destination address - domain name if available without reverse DNS - // lookup; otherwise, IP address or Unix domain socket name. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'destination.example.com', '10.1.2.80', '/tmp/my.sock' - // Note: When observed from the source side, and when communicating through - // an intermediary, `destination.address` SHOULD represent the destination - // address behind any intermediaries, for example proxies, if it's - // available. - DestinationAddressKey = attribute.Key("destination.address") - - // DestinationPortKey is the attribute Key conforming to the - // "destination.port" semantic conventions. It represents the destination - // port number - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 3389, 2888 - DestinationPortKey = attribute.Key("destination.port") -) - -// DestinationAddress returns an attribute KeyValue conforming to the -// "destination.address" semantic conventions. It represents the destination -// address - domain name if available without reverse DNS lookup; otherwise, IP -// address or Unix domain socket name. -func DestinationAddress(val string) attribute.KeyValue { - return DestinationAddressKey.String(val) -} - -// DestinationPort returns an attribute KeyValue conforming to the -// "destination.port" semantic conventions. It represents the destination port -// number -func DestinationPort(val int) attribute.KeyValue { - return DestinationPortKey.Int(val) -} - -// These attributes may be used for any disk related operation. -const ( - // DiskIoDirectionKey is the attribute Key conforming to the - // "disk.io.direction" semantic conventions. It represents the disk IO - // operation direction. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'read' - DiskIoDirectionKey = attribute.Key("disk.io.direction") -) - -var ( - // read - DiskIoDirectionRead = DiskIoDirectionKey.String("read") - // write - DiskIoDirectionWrite = DiskIoDirectionKey.String("write") -) - -// The shared attributes used to report an error. -const ( - // ErrorTypeKey is the attribute Key conforming to the "error.type" - // semantic conventions. It represents the describes a class of error the - // operation ended with. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: stable - // Examples: 'timeout', 'java.net.UnknownHostException', - // 'server_certificate_invalid', '500' - // Note: The `error.type` SHOULD be predictable and SHOULD have low - // cardinality. - // Instrumentations SHOULD document the list of errors they report. - // - // The cardinality of `error.type` within one instrumentation library - // SHOULD be low. - // Telemetry consumers that aggregate data from multiple instrumentation - // libraries and applications - // should be prepared for `error.type` to have high cardinality at query - // time when no - // additional filters are applied. - // - // If the operation has completed successfully, instrumentations SHOULD NOT - // set `error.type`. - // - // If a specific domain defines its own set of error identifiers (such as - // HTTP or gRPC status codes), - // it's RECOMMENDED to: - // - // * Use a domain-specific attribute - // * Set `error.type` to capture all errors, regardless of whether they are - // defined within the domain-specific set or not. - ErrorTypeKey = attribute.Key("error.type") -) - -var ( - // A fallback error value to be used when the instrumentation doesn't define a custom value - ErrorTypeOther = ErrorTypeKey.String("_OTHER") -) - -// The shared attributes used to report a single exception associated with a -// span or log. -const ( - // ExceptionEscapedKey is the attribute Key conforming to the - // "exception.escaped" semantic conventions. It represents the sHOULD be - // set to true if the exception event is recorded at a point where it is - // known that the exception is escaping the scope of the span. - // - // Type: boolean - // RequirementLevel: Optional - // Stability: experimental - // Note: An exception is considered to have escaped (or left) the scope of - // a span, - // if that span is ended while the exception is still logically "in - // flight". - // This may be actually "in flight" in some languages (e.g. if the - // exception - // is passed to a Context manager's `__exit__` method in Python) but will - // usually be caught at the point of recording the exception in most - // languages. - // - // It is usually not possible to determine at the point where an exception - // is thrown - // whether it will escape the scope of a span. - // However, it is trivial to know that an exception - // will escape, if one checks for an active exception just before ending - // the span, - // as done in the [example for recording span - // exceptions](#recording-an-exception). - // - // It follows that an exception may still escape the scope of the span - // even if the `exception.escaped` attribute was not set or set to false, - // since the event might have been recorded at a time where it was not - // clear whether the exception will escape. - ExceptionEscapedKey = attribute.Key("exception.escaped") - - // ExceptionMessageKey is the attribute Key conforming to the - // "exception.message" semantic conventions. It represents the exception - // message. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'Division by zero', "Can't convert 'int' object to str - // implicitly" - ExceptionMessageKey = attribute.Key("exception.message") - - // ExceptionStacktraceKey is the attribute Key conforming to the - // "exception.stacktrace" semantic conventions. It represents a stacktrace - // as a string in the natural representation for the language runtime. The - // representation is to be determined and documented by each language SIG. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'Exception in thread "main" java.lang.RuntimeException: Test - // exception\\n at ' - // 'com.example.GenerateTrace.methodB(GenerateTrace.java:13)\\n at ' - // 'com.example.GenerateTrace.methodA(GenerateTrace.java:9)\\n at ' - // 'com.example.GenerateTrace.main(GenerateTrace.java:5)' - ExceptionStacktraceKey = attribute.Key("exception.stacktrace") - - // ExceptionTypeKey is the attribute Key conforming to the "exception.type" - // semantic conventions. It represents the type of the exception (its - // fully-qualified class name, if applicable). The dynamic type of the - // exception should be preferred over the static type in languages that - // support it. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'java.net.ConnectException', 'OSError' - ExceptionTypeKey = attribute.Key("exception.type") -) - -// ExceptionEscaped returns an attribute KeyValue conforming to the -// "exception.escaped" semantic conventions. It represents the sHOULD be set to -// true if the exception event is recorded at a point where it is known that -// the exception is escaping the scope of the span. -func ExceptionEscaped(val bool) attribute.KeyValue { - return ExceptionEscapedKey.Bool(val) -} - -// ExceptionMessage returns an attribute KeyValue conforming to the -// "exception.message" semantic conventions. It represents the exception -// message. -func ExceptionMessage(val string) attribute.KeyValue { - return ExceptionMessageKey.String(val) -} - -// ExceptionStacktrace returns an attribute KeyValue conforming to the -// "exception.stacktrace" semantic conventions. It represents a stacktrace as a -// string in the natural representation for the language runtime. The -// representation is to be determined and documented by each language SIG. -func ExceptionStacktrace(val string) attribute.KeyValue { - return ExceptionStacktraceKey.String(val) -} - -// ExceptionType returns an attribute KeyValue conforming to the -// "exception.type" semantic conventions. It represents the type of the -// exception (its fully-qualified class name, if applicable). The dynamic type -// of the exception should be preferred over the static type in languages that -// support it. -func ExceptionType(val string) attribute.KeyValue { - return ExceptionTypeKey.String(val) -} - -// Semantic convention attributes in the HTTP namespace. -const ( - // HTTPRequestBodySizeKey is the attribute Key conforming to the - // "http.request.body.size" semantic conventions. It represents the size of - // the request payload body in bytes. This is the number of bytes - // transferred excluding headers and is often, but not always, present as - // the - // [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length) - // header. For requests using transport encoding, this should be the - // compressed size. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 3495 - HTTPRequestBodySizeKey = attribute.Key("http.request.body.size") - - // HTTPRequestMethodKey is the attribute Key conforming to the - // "http.request.method" semantic conventions. It represents the hTTP - // request method. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: stable - // Examples: 'GET', 'POST', 'HEAD' - // Note: HTTP request method value SHOULD be "known" to the - // instrumentation. - // By default, this convention defines "known" methods as the ones listed - // in [RFC9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-methods) - // and the PATCH method defined in - // [RFC5789](https://www.rfc-editor.org/rfc/rfc5789.html). - // - // If the HTTP request method is not known to instrumentation, it MUST set - // the `http.request.method` attribute to `_OTHER`. - // - // If the HTTP instrumentation could end up converting valid HTTP request - // methods to `_OTHER`, then it MUST provide a way to override - // the list of known HTTP methods. If this override is done via environment - // variable, then the environment variable MUST be named - // OTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS and support a comma-separated - // list of case-sensitive known HTTP methods - // (this list MUST be a full override of the default known method, it is - // not a list of known methods in addition to the defaults). - // - // HTTP method names are case-sensitive and `http.request.method` attribute - // value MUST match a known HTTP method name exactly. - // Instrumentations for specific web frameworks that consider HTTP methods - // to be case insensitive, SHOULD populate a canonical equivalent. - // Tracing instrumentations that do so, MUST also set - // `http.request.method_original` to the original value. - HTTPRequestMethodKey = attribute.Key("http.request.method") - - // HTTPRequestMethodOriginalKey is the attribute Key conforming to the - // "http.request.method_original" semantic conventions. It represents the - // original HTTP method sent by the client in the request line. - // - // Type: string - // RequirementLevel: Optional - // Stability: stable - // Examples: 'GeT', 'ACL', 'foo' - HTTPRequestMethodOriginalKey = attribute.Key("http.request.method_original") - - // HTTPRequestResendCountKey is the attribute Key conforming to the - // "http.request.resend_count" semantic conventions. It represents the - // ordinal number of request resending attempt (for any reason, including - // redirects). - // - // Type: int - // RequirementLevel: Optional - // Stability: stable - // Examples: 3 - // Note: The resend count SHOULD be updated each time an HTTP request gets - // resent by the client, regardless of what was the cause of the resending - // (e.g. redirection, authorization failure, 503 Server Unavailable, - // network issues, or any other). - HTTPRequestResendCountKey = attribute.Key("http.request.resend_count") - - // HTTPResponseBodySizeKey is the attribute Key conforming to the - // "http.response.body.size" semantic conventions. It represents the size - // of the response payload body in bytes. This is the number of bytes - // transferred excluding headers and is often, but not always, present as - // the - // [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length) - // header. For requests using transport encoding, this should be the - // compressed size. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 3495 - HTTPResponseBodySizeKey = attribute.Key("http.response.body.size") - - // HTTPResponseStatusCodeKey is the attribute Key conforming to the - // "http.response.status_code" semantic conventions. It represents the - // [HTTP response status - // code](https://tools.ietf.org/html/rfc7231#section-6). - // - // Type: int - // RequirementLevel: Optional - // Stability: stable - // Examples: 200 - HTTPResponseStatusCodeKey = attribute.Key("http.response.status_code") - - // HTTPRouteKey is the attribute Key conforming to the "http.route" - // semantic conventions. It represents the matched route, that is, the path - // template in the format used by the respective server framework. - // - // Type: string - // RequirementLevel: Optional - // Stability: stable - // Examples: '/users/:userID?', '{controller}/{action}/{id?}' - // Note: MUST NOT be populated when this is not supported by the HTTP - // server framework as the route attribute should have low-cardinality and - // the URI path can NOT substitute it. - // SHOULD include the [application - // root](/docs/http/http-spans.md#http-server-definitions) if there is one. - HTTPRouteKey = attribute.Key("http.route") -) - -var ( - // CONNECT method - HTTPRequestMethodConnect = HTTPRequestMethodKey.String("CONNECT") - // DELETE method - HTTPRequestMethodDelete = HTTPRequestMethodKey.String("DELETE") - // GET method - HTTPRequestMethodGet = HTTPRequestMethodKey.String("GET") - // HEAD method - HTTPRequestMethodHead = HTTPRequestMethodKey.String("HEAD") - // OPTIONS method - HTTPRequestMethodOptions = HTTPRequestMethodKey.String("OPTIONS") - // PATCH method - HTTPRequestMethodPatch = HTTPRequestMethodKey.String("PATCH") - // POST method - HTTPRequestMethodPost = HTTPRequestMethodKey.String("POST") - // PUT method - HTTPRequestMethodPut = HTTPRequestMethodKey.String("PUT") - // TRACE method - HTTPRequestMethodTrace = HTTPRequestMethodKey.String("TRACE") - // Any HTTP method that the instrumentation has no prior knowledge of - HTTPRequestMethodOther = HTTPRequestMethodKey.String("_OTHER") -) - -// HTTPRequestBodySize returns an attribute KeyValue conforming to the -// "http.request.body.size" semantic conventions. It represents the size of the -// request payload body in bytes. This is the number of bytes transferred -// excluding headers and is often, but not always, present as the -// [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length) -// header. For requests using transport encoding, this should be the compressed -// size. -func HTTPRequestBodySize(val int) attribute.KeyValue { - return HTTPRequestBodySizeKey.Int(val) -} - -// HTTPRequestMethodOriginal returns an attribute KeyValue conforming to the -// "http.request.method_original" semantic conventions. It represents the -// original HTTP method sent by the client in the request line. -func HTTPRequestMethodOriginal(val string) attribute.KeyValue { - return HTTPRequestMethodOriginalKey.String(val) -} - -// HTTPRequestResendCount returns an attribute KeyValue conforming to the -// "http.request.resend_count" semantic conventions. It represents the ordinal -// number of request resending attempt (for any reason, including redirects). -func HTTPRequestResendCount(val int) attribute.KeyValue { - return HTTPRequestResendCountKey.Int(val) -} - -// HTTPResponseBodySize returns an attribute KeyValue conforming to the -// "http.response.body.size" semantic conventions. It represents the size of -// the response payload body in bytes. This is the number of bytes transferred -// excluding headers and is often, but not always, present as the -// [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length) -// header. For requests using transport encoding, this should be the compressed -// size. -func HTTPResponseBodySize(val int) attribute.KeyValue { - return HTTPResponseBodySizeKey.Int(val) -} - -// HTTPResponseStatusCode returns an attribute KeyValue conforming to the -// "http.response.status_code" semantic conventions. It represents the [HTTP -// response status code](https://tools.ietf.org/html/rfc7231#section-6). -func HTTPResponseStatusCode(val int) attribute.KeyValue { - return HTTPResponseStatusCodeKey.Int(val) -} - -// HTTPRoute returns an attribute KeyValue conforming to the "http.route" -// semantic conventions. It represents the matched route, that is, the path -// template in the format used by the respective server framework. -func HTTPRoute(val string) attribute.KeyValue { - return HTTPRouteKey.String(val) -} - -// Attributes describing telemetry around messaging systems and messaging -// activities. -const ( - // MessagingBatchMessageCountKey is the attribute Key conforming to the - // "messaging.batch.message_count" semantic conventions. It represents the - // number of messages sent, received, or processed in the scope of the - // batching operation. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 0, 1, 2 - // Note: Instrumentations SHOULD NOT set `messaging.batch.message_count` on - // spans that operate with a single message. When a messaging client - // library supports both batch and single-message API for the same - // operation, instrumentations SHOULD use `messaging.batch.message_count` - // for batching APIs and SHOULD NOT use it for single-message APIs. - MessagingBatchMessageCountKey = attribute.Key("messaging.batch.message_count") - - // MessagingClientIDKey is the attribute Key conforming to the - // "messaging.client_id" semantic conventions. It represents a unique - // identifier for the client that consumes or produces a message. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'client-5', 'myhost@8742@s8083jm' - MessagingClientIDKey = attribute.Key("messaging.client_id") - - // MessagingDestinationAnonymousKey is the attribute Key conforming to the - // "messaging.destination.anonymous" semantic conventions. It represents a - // boolean that is true if the message destination is anonymous (could be - // unnamed or have auto-generated name). - // - // Type: boolean - // RequirementLevel: Optional - // Stability: experimental - MessagingDestinationAnonymousKey = attribute.Key("messaging.destination.anonymous") - - // MessagingDestinationNameKey is the attribute Key conforming to the - // "messaging.destination.name" semantic conventions. It represents the - // message destination name - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'MyQueue', 'MyTopic' - // Note: Destination name SHOULD uniquely identify a specific queue, topic - // or other entity within the broker. If - // the broker doesn't have such notion, the destination name SHOULD - // uniquely identify the broker. - MessagingDestinationNameKey = attribute.Key("messaging.destination.name") - - // MessagingDestinationTemplateKey is the attribute Key conforming to the - // "messaging.destination.template" semantic conventions. It represents the - // low cardinality representation of the messaging destination name - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '/customers/{customerID}' - // Note: Destination names could be constructed from templates. An example - // would be a destination name involving a user name or product id. - // Although the destination name in this case is of high cardinality, the - // underlying template is of low cardinality and can be effectively used - // for grouping and aggregation. - MessagingDestinationTemplateKey = attribute.Key("messaging.destination.template") - - // MessagingDestinationTemporaryKey is the attribute Key conforming to the - // "messaging.destination.temporary" semantic conventions. It represents a - // boolean that is true if the message destination is temporary and might - // not exist anymore after messages are processed. - // - // Type: boolean - // RequirementLevel: Optional - // Stability: experimental - MessagingDestinationTemporaryKey = attribute.Key("messaging.destination.temporary") - - // MessagingDestinationPublishAnonymousKey is the attribute Key conforming - // to the "messaging.destination_publish.anonymous" semantic conventions. - // It represents a boolean that is true if the publish message destination - // is anonymous (could be unnamed or have auto-generated name). - // - // Type: boolean - // RequirementLevel: Optional - // Stability: experimental - MessagingDestinationPublishAnonymousKey = attribute.Key("messaging.destination_publish.anonymous") - - // MessagingDestinationPublishNameKey is the attribute Key conforming to - // the "messaging.destination_publish.name" semantic conventions. It - // represents the name of the original destination the message was - // published to - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'MyQueue', 'MyTopic' - // Note: The name SHOULD uniquely identify a specific queue, topic, or - // other entity within the broker. If - // the broker doesn't have such notion, the original destination name - // SHOULD uniquely identify the broker. - MessagingDestinationPublishNameKey = attribute.Key("messaging.destination_publish.name") - - // MessagingGCPPubsubMessageOrderingKeyKey is the attribute Key conforming - // to the "messaging.gcp_pubsub.message.ordering_key" semantic conventions. - // It represents the ordering key for a given message. If the attribute is - // not present, the message does not have an ordering key. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'ordering_key' - MessagingGCPPubsubMessageOrderingKeyKey = attribute.Key("messaging.gcp_pubsub.message.ordering_key") - - // MessagingKafkaConsumerGroupKey is the attribute Key conforming to the - // "messaging.kafka.consumer.group" semantic conventions. It represents the - // name of the Kafka Consumer Group that is handling the message. Only - // applies to consumers, not producers. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'my-group' - MessagingKafkaConsumerGroupKey = attribute.Key("messaging.kafka.consumer.group") - - // MessagingKafkaDestinationPartitionKey is the attribute Key conforming to - // the "messaging.kafka.destination.partition" semantic conventions. It - // represents the partition the message is sent to. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 2 - MessagingKafkaDestinationPartitionKey = attribute.Key("messaging.kafka.destination.partition") - - // MessagingKafkaMessageKeyKey is the attribute Key conforming to the - // "messaging.kafka.message.key" semantic conventions. It represents the - // message keys in Kafka are used for grouping alike messages to ensure - // they're processed on the same partition. They differ from - // `messaging.message.id` in that they're not unique. If the key is `null`, - // the attribute MUST NOT be set. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'myKey' - // Note: If the key type is not string, it's string representation has to - // be supplied for the attribute. If the key has no unambiguous, canonical - // string form, don't include its value. - MessagingKafkaMessageKeyKey = attribute.Key("messaging.kafka.message.key") - - // MessagingKafkaMessageOffsetKey is the attribute Key conforming to the - // "messaging.kafka.message.offset" semantic conventions. It represents the - // offset of a record in the corresponding Kafka partition. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 42 - MessagingKafkaMessageOffsetKey = attribute.Key("messaging.kafka.message.offset") - - // MessagingKafkaMessageTombstoneKey is the attribute Key conforming to the - // "messaging.kafka.message.tombstone" semantic conventions. It represents - // a boolean that is true if the message is a tombstone. - // - // Type: boolean - // RequirementLevel: Optional - // Stability: experimental - MessagingKafkaMessageTombstoneKey = attribute.Key("messaging.kafka.message.tombstone") - - // MessagingMessageBodySizeKey is the attribute Key conforming to the - // "messaging.message.body.size" semantic conventions. It represents the - // size of the message body in bytes. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 1439 - // Note: This can refer to both the compressed or uncompressed body size. - // If both sizes are known, the uncompressed - // body size should be used. - MessagingMessageBodySizeKey = attribute.Key("messaging.message.body.size") - - // MessagingMessageConversationIDKey is the attribute Key conforming to the - // "messaging.message.conversation_id" semantic conventions. It represents - // the conversation ID identifying the conversation to which the message - // belongs, represented as a string. Sometimes called "Correlation ID". - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'MyConversationID' - MessagingMessageConversationIDKey = attribute.Key("messaging.message.conversation_id") - - // MessagingMessageEnvelopeSizeKey is the attribute Key conforming to the - // "messaging.message.envelope.size" semantic conventions. It represents - // the size of the message body and metadata in bytes. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 2738 - // Note: This can refer to both the compressed or uncompressed size. If - // both sizes are known, the uncompressed - // size should be used. - MessagingMessageEnvelopeSizeKey = attribute.Key("messaging.message.envelope.size") - - // MessagingMessageIDKey is the attribute Key conforming to the - // "messaging.message.id" semantic conventions. It represents a value used - // by the messaging system as an identifier for the message, represented as - // a string. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '452a7c7c7c7048c2f887f61572b18fc2' - MessagingMessageIDKey = attribute.Key("messaging.message.id") - - // MessagingOperationKey is the attribute Key conforming to the - // "messaging.operation" semantic conventions. It represents a string - // identifying the kind of messaging operation. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - // Note: If a custom value is used, it MUST be of low cardinality. - MessagingOperationKey = attribute.Key("messaging.operation") - - // MessagingRabbitmqDestinationRoutingKeyKey is the attribute Key - // conforming to the "messaging.rabbitmq.destination.routing_key" semantic - // conventions. It represents the rabbitMQ message routing key. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'myKey' - MessagingRabbitmqDestinationRoutingKeyKey = attribute.Key("messaging.rabbitmq.destination.routing_key") - - // MessagingRocketmqClientGroupKey is the attribute Key conforming to the - // "messaging.rocketmq.client_group" semantic conventions. It represents - // the name of the RocketMQ producer/consumer group that is handling the - // message. The client type is identified by the SpanKind. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'myConsumerGroup' - MessagingRocketmqClientGroupKey = attribute.Key("messaging.rocketmq.client_group") - - // MessagingRocketmqConsumptionModelKey is the attribute Key conforming to - // the "messaging.rocketmq.consumption_model" semantic conventions. It - // represents the model of message consumption. This only applies to - // consumer spans. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - MessagingRocketmqConsumptionModelKey = attribute.Key("messaging.rocketmq.consumption_model") - - // MessagingRocketmqMessageDelayTimeLevelKey is the attribute Key - // conforming to the "messaging.rocketmq.message.delay_time_level" semantic - // conventions. It represents the delay time level for delay message, which - // determines the message delay time. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 3 - MessagingRocketmqMessageDelayTimeLevelKey = attribute.Key("messaging.rocketmq.message.delay_time_level") - - // MessagingRocketmqMessageDeliveryTimestampKey is the attribute Key - // conforming to the "messaging.rocketmq.message.delivery_timestamp" - // semantic conventions. It represents the timestamp in milliseconds that - // the delay message is expected to be delivered to consumer. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 1665987217045 - MessagingRocketmqMessageDeliveryTimestampKey = attribute.Key("messaging.rocketmq.message.delivery_timestamp") - - // MessagingRocketmqMessageGroupKey is the attribute Key conforming to the - // "messaging.rocketmq.message.group" semantic conventions. It represents - // the it is essential for FIFO message. Messages that belong to the same - // message group are always processed one by one within the same consumer - // group. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'myMessageGroup' - MessagingRocketmqMessageGroupKey = attribute.Key("messaging.rocketmq.message.group") - - // MessagingRocketmqMessageKeysKey is the attribute Key conforming to the - // "messaging.rocketmq.message.keys" semantic conventions. It represents - // the key(s) of message, another way to mark message besides message id. - // - // Type: string[] - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'keyA', 'keyB' - MessagingRocketmqMessageKeysKey = attribute.Key("messaging.rocketmq.message.keys") - - // MessagingRocketmqMessageTagKey is the attribute Key conforming to the - // "messaging.rocketmq.message.tag" semantic conventions. It represents the - // secondary classifier of message besides topic. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'tagA' - MessagingRocketmqMessageTagKey = attribute.Key("messaging.rocketmq.message.tag") - - // MessagingRocketmqMessageTypeKey is the attribute Key conforming to the - // "messaging.rocketmq.message.type" semantic conventions. It represents - // the type of message. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - MessagingRocketmqMessageTypeKey = attribute.Key("messaging.rocketmq.message.type") - - // MessagingRocketmqNamespaceKey is the attribute Key conforming to the - // "messaging.rocketmq.namespace" semantic conventions. It represents the - // namespace of RocketMQ resources, resources in different namespaces are - // individual. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'myNamespace' - MessagingRocketmqNamespaceKey = attribute.Key("messaging.rocketmq.namespace") - - // MessagingSystemKey is the attribute Key conforming to the - // "messaging.system" semantic conventions. It represents an identifier for - // the messaging system being used. See below for a list of well-known - // identifiers. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - MessagingSystemKey = attribute.Key("messaging.system") -) - -var ( - // One or more messages are provided for publishing to an intermediary. If a single message is published, the context of the "Publish" span can be used as the creation context and no "Create" span needs to be created - MessagingOperationPublish = MessagingOperationKey.String("publish") - // A message is created. "Create" spans always refer to a single message and are used to provide a unique creation context for messages in batch publishing scenarios - MessagingOperationCreate = MessagingOperationKey.String("create") - // One or more messages are requested by a consumer. This operation refers to pull-based scenarios, where consumers explicitly call methods of messaging SDKs to receive messages - MessagingOperationReceive = MessagingOperationKey.String("receive") - // One or more messages are passed to a consumer. This operation refers to push-based scenarios, where consumer register callbacks which get called by messaging SDKs - MessagingOperationDeliver = MessagingOperationKey.String("deliver") -) - -var ( - // Clustering consumption model - MessagingRocketmqConsumptionModelClustering = MessagingRocketmqConsumptionModelKey.String("clustering") - // Broadcasting consumption model - MessagingRocketmqConsumptionModelBroadcasting = MessagingRocketmqConsumptionModelKey.String("broadcasting") -) - -var ( - // Normal message - MessagingRocketmqMessageTypeNormal = MessagingRocketmqMessageTypeKey.String("normal") - // FIFO message - MessagingRocketmqMessageTypeFifo = MessagingRocketmqMessageTypeKey.String("fifo") - // Delay message - MessagingRocketmqMessageTypeDelay = MessagingRocketmqMessageTypeKey.String("delay") - // Transaction message - MessagingRocketmqMessageTypeTransaction = MessagingRocketmqMessageTypeKey.String("transaction") -) - -var ( - // Apache ActiveMQ - MessagingSystemActivemq = MessagingSystemKey.String("activemq") - // Amazon Simple Queue Service (SQS) - MessagingSystemAWSSqs = MessagingSystemKey.String("aws_sqs") - // Azure Event Grid - MessagingSystemAzureEventgrid = MessagingSystemKey.String("azure_eventgrid") - // Azure Event Hubs - MessagingSystemAzureEventhubs = MessagingSystemKey.String("azure_eventhubs") - // Azure Service Bus - MessagingSystemAzureServicebus = MessagingSystemKey.String("azure_servicebus") - // Google Cloud Pub/Sub - MessagingSystemGCPPubsub = MessagingSystemKey.String("gcp_pubsub") - // Java Message Service - MessagingSystemJms = MessagingSystemKey.String("jms") - // Apache Kafka - MessagingSystemKafka = MessagingSystemKey.String("kafka") - // RabbitMQ - MessagingSystemRabbitmq = MessagingSystemKey.String("rabbitmq") - // Apache RocketMQ - MessagingSystemRocketmq = MessagingSystemKey.String("rocketmq") -) - -// MessagingBatchMessageCount returns an attribute KeyValue conforming to -// the "messaging.batch.message_count" semantic conventions. It represents the -// number of messages sent, received, or processed in the scope of the batching -// operation. -func MessagingBatchMessageCount(val int) attribute.KeyValue { - return MessagingBatchMessageCountKey.Int(val) -} - -// MessagingClientID returns an attribute KeyValue conforming to the -// "messaging.client_id" semantic conventions. It represents a unique -// identifier for the client that consumes or produces a message. -func MessagingClientID(val string) attribute.KeyValue { - return MessagingClientIDKey.String(val) -} - -// MessagingDestinationAnonymous returns an attribute KeyValue conforming to -// the "messaging.destination.anonymous" semantic conventions. It represents a -// boolean that is true if the message destination is anonymous (could be -// unnamed or have auto-generated name). -func MessagingDestinationAnonymous(val bool) attribute.KeyValue { - return MessagingDestinationAnonymousKey.Bool(val) -} - -// MessagingDestinationName returns an attribute KeyValue conforming to the -// "messaging.destination.name" semantic conventions. It represents the message -// destination name -func MessagingDestinationName(val string) attribute.KeyValue { - return MessagingDestinationNameKey.String(val) -} - -// MessagingDestinationTemplate returns an attribute KeyValue conforming to -// the "messaging.destination.template" semantic conventions. It represents the -// low cardinality representation of the messaging destination name -func MessagingDestinationTemplate(val string) attribute.KeyValue { - return MessagingDestinationTemplateKey.String(val) -} - -// MessagingDestinationTemporary returns an attribute KeyValue conforming to -// the "messaging.destination.temporary" semantic conventions. It represents a -// boolean that is true if the message destination is temporary and might not -// exist anymore after messages are processed. -func MessagingDestinationTemporary(val bool) attribute.KeyValue { - return MessagingDestinationTemporaryKey.Bool(val) -} - -// MessagingDestinationPublishAnonymous returns an attribute KeyValue -// conforming to the "messaging.destination_publish.anonymous" semantic -// conventions. It represents a boolean that is true if the publish message -// destination is anonymous (could be unnamed or have auto-generated name). -func MessagingDestinationPublishAnonymous(val bool) attribute.KeyValue { - return MessagingDestinationPublishAnonymousKey.Bool(val) -} - -// MessagingDestinationPublishName returns an attribute KeyValue conforming -// to the "messaging.destination_publish.name" semantic conventions. It -// represents the name of the original destination the message was published to -func MessagingDestinationPublishName(val string) attribute.KeyValue { - return MessagingDestinationPublishNameKey.String(val) -} - -// MessagingGCPPubsubMessageOrderingKey returns an attribute KeyValue -// conforming to the "messaging.gcp_pubsub.message.ordering_key" semantic -// conventions. It represents the ordering key for a given message. If the -// attribute is not present, the message does not have an ordering key. -func MessagingGCPPubsubMessageOrderingKey(val string) attribute.KeyValue { - return MessagingGCPPubsubMessageOrderingKeyKey.String(val) -} - -// MessagingKafkaConsumerGroup returns an attribute KeyValue conforming to -// the "messaging.kafka.consumer.group" semantic conventions. It represents the -// name of the Kafka Consumer Group that is handling the message. Only applies -// to consumers, not producers. -func MessagingKafkaConsumerGroup(val string) attribute.KeyValue { - return MessagingKafkaConsumerGroupKey.String(val) -} - -// MessagingKafkaDestinationPartition returns an attribute KeyValue -// conforming to the "messaging.kafka.destination.partition" semantic -// conventions. It represents the partition the message is sent to. -func MessagingKafkaDestinationPartition(val int) attribute.KeyValue { - return MessagingKafkaDestinationPartitionKey.Int(val) -} - -// MessagingKafkaMessageKey returns an attribute KeyValue conforming to the -// "messaging.kafka.message.key" semantic conventions. It represents the -// message keys in Kafka are used for grouping alike messages to ensure they're -// processed on the same partition. They differ from `messaging.message.id` in -// that they're not unique. If the key is `null`, the attribute MUST NOT be -// set. -func MessagingKafkaMessageKey(val string) attribute.KeyValue { - return MessagingKafkaMessageKeyKey.String(val) -} - -// MessagingKafkaMessageOffset returns an attribute KeyValue conforming to -// the "messaging.kafka.message.offset" semantic conventions. It represents the -// offset of a record in the corresponding Kafka partition. -func MessagingKafkaMessageOffset(val int) attribute.KeyValue { - return MessagingKafkaMessageOffsetKey.Int(val) -} - -// MessagingKafkaMessageTombstone returns an attribute KeyValue conforming -// to the "messaging.kafka.message.tombstone" semantic conventions. It -// represents a boolean that is true if the message is a tombstone. -func MessagingKafkaMessageTombstone(val bool) attribute.KeyValue { - return MessagingKafkaMessageTombstoneKey.Bool(val) -} - -// MessagingMessageBodySize returns an attribute KeyValue conforming to the -// "messaging.message.body.size" semantic conventions. It represents the size -// of the message body in bytes. -func MessagingMessageBodySize(val int) attribute.KeyValue { - return MessagingMessageBodySizeKey.Int(val) -} - -// MessagingMessageConversationID returns an attribute KeyValue conforming -// to the "messaging.message.conversation_id" semantic conventions. It -// represents the conversation ID identifying the conversation to which the -// message belongs, represented as a string. Sometimes called "Correlation ID". -func MessagingMessageConversationID(val string) attribute.KeyValue { - return MessagingMessageConversationIDKey.String(val) -} - -// MessagingMessageEnvelopeSize returns an attribute KeyValue conforming to -// the "messaging.message.envelope.size" semantic conventions. It represents -// the size of the message body and metadata in bytes. -func MessagingMessageEnvelopeSize(val int) attribute.KeyValue { - return MessagingMessageEnvelopeSizeKey.Int(val) -} - -// MessagingMessageID returns an attribute KeyValue conforming to the -// "messaging.message.id" semantic conventions. It represents a value used by -// the messaging system as an identifier for the message, represented as a -// string. -func MessagingMessageID(val string) attribute.KeyValue { - return MessagingMessageIDKey.String(val) -} - -// MessagingRabbitmqDestinationRoutingKey returns an attribute KeyValue -// conforming to the "messaging.rabbitmq.destination.routing_key" semantic -// conventions. It represents the rabbitMQ message routing key. -func MessagingRabbitmqDestinationRoutingKey(val string) attribute.KeyValue { - return MessagingRabbitmqDestinationRoutingKeyKey.String(val) -} - -// MessagingRocketmqClientGroup returns an attribute KeyValue conforming to -// the "messaging.rocketmq.client_group" semantic conventions. It represents -// the name of the RocketMQ producer/consumer group that is handling the -// message. The client type is identified by the SpanKind. -func MessagingRocketmqClientGroup(val string) attribute.KeyValue { - return MessagingRocketmqClientGroupKey.String(val) -} - -// MessagingRocketmqMessageDelayTimeLevel returns an attribute KeyValue -// conforming to the "messaging.rocketmq.message.delay_time_level" semantic -// conventions. It represents the delay time level for delay message, which -// determines the message delay time. -func MessagingRocketmqMessageDelayTimeLevel(val int) attribute.KeyValue { - return MessagingRocketmqMessageDelayTimeLevelKey.Int(val) -} - -// MessagingRocketmqMessageDeliveryTimestamp returns an attribute KeyValue -// conforming to the "messaging.rocketmq.message.delivery_timestamp" semantic -// conventions. It represents the timestamp in milliseconds that the delay -// message is expected to be delivered to consumer. -func MessagingRocketmqMessageDeliveryTimestamp(val int) attribute.KeyValue { - return MessagingRocketmqMessageDeliveryTimestampKey.Int(val) -} - -// MessagingRocketmqMessageGroup returns an attribute KeyValue conforming to -// the "messaging.rocketmq.message.group" semantic conventions. It represents -// the it is essential for FIFO message. Messages that belong to the same -// message group are always processed one by one within the same consumer -// group. -func MessagingRocketmqMessageGroup(val string) attribute.KeyValue { - return MessagingRocketmqMessageGroupKey.String(val) -} - -// MessagingRocketmqMessageKeys returns an attribute KeyValue conforming to -// the "messaging.rocketmq.message.keys" semantic conventions. It represents -// the key(s) of message, another way to mark message besides message id. -func MessagingRocketmqMessageKeys(val ...string) attribute.KeyValue { - return MessagingRocketmqMessageKeysKey.StringSlice(val) -} - -// MessagingRocketmqMessageTag returns an attribute KeyValue conforming to -// the "messaging.rocketmq.message.tag" semantic conventions. It represents the -// secondary classifier of message besides topic. -func MessagingRocketmqMessageTag(val string) attribute.KeyValue { - return MessagingRocketmqMessageTagKey.String(val) -} - -// MessagingRocketmqNamespace returns an attribute KeyValue conforming to -// the "messaging.rocketmq.namespace" semantic conventions. It represents the -// namespace of RocketMQ resources, resources in different namespaces are -// individual. -func MessagingRocketmqNamespace(val string) attribute.KeyValue { - return MessagingRocketmqNamespaceKey.String(val) -} - -// These attributes may be used for any network related operation. -const ( - // NetworkCarrierIccKey is the attribute Key conforming to the - // "network.carrier.icc" semantic conventions. It represents the ISO 3166-1 - // alpha-2 2-character country code associated with the mobile carrier - // network. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'DE' - NetworkCarrierIccKey = attribute.Key("network.carrier.icc") - - // NetworkCarrierMccKey is the attribute Key conforming to the - // "network.carrier.mcc" semantic conventions. It represents the mobile - // carrier country code. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '310' - NetworkCarrierMccKey = attribute.Key("network.carrier.mcc") - - // NetworkCarrierMncKey is the attribute Key conforming to the - // "network.carrier.mnc" semantic conventions. It represents the mobile - // carrier network code. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '001' - NetworkCarrierMncKey = attribute.Key("network.carrier.mnc") - - // NetworkCarrierNameKey is the attribute Key conforming to the - // "network.carrier.name" semantic conventions. It represents the name of - // the mobile carrier. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'sprint' - NetworkCarrierNameKey = attribute.Key("network.carrier.name") - - // NetworkConnectionSubtypeKey is the attribute Key conforming to the - // "network.connection.subtype" semantic conventions. It represents the - // this describes more details regarding the connection.type. It may be the - // type of cell technology connection, but it could be used for describing - // details about a wifi connection. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'LTE' - NetworkConnectionSubtypeKey = attribute.Key("network.connection.subtype") - - // NetworkConnectionTypeKey is the attribute Key conforming to the - // "network.connection.type" semantic conventions. It represents the - // internet connection type. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'wifi' - NetworkConnectionTypeKey = attribute.Key("network.connection.type") - - // NetworkIoDirectionKey is the attribute Key conforming to the - // "network.io.direction" semantic conventions. It represents the network - // IO operation direction. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'transmit' - NetworkIoDirectionKey = attribute.Key("network.io.direction") - - // NetworkLocalAddressKey is the attribute Key conforming to the - // "network.local.address" semantic conventions. It represents the local - // address of the network connection - IP address or Unix domain socket - // name. - // - // Type: string - // RequirementLevel: Optional - // Stability: stable - // Examples: '10.1.2.80', '/tmp/my.sock' - NetworkLocalAddressKey = attribute.Key("network.local.address") - - // NetworkLocalPortKey is the attribute Key conforming to the - // "network.local.port" semantic conventions. It represents the local port - // number of the network connection. - // - // Type: int - // RequirementLevel: Optional - // Stability: stable - // Examples: 65123 - NetworkLocalPortKey = attribute.Key("network.local.port") - - // NetworkPeerAddressKey is the attribute Key conforming to the - // "network.peer.address" semantic conventions. It represents the peer - // address of the network connection - IP address or Unix domain socket - // name. - // - // Type: string - // RequirementLevel: Optional - // Stability: stable - // Examples: '10.1.2.80', '/tmp/my.sock' - NetworkPeerAddressKey = attribute.Key("network.peer.address") - - // NetworkPeerPortKey is the attribute Key conforming to the - // "network.peer.port" semantic conventions. It represents the peer port - // number of the network connection. - // - // Type: int - // RequirementLevel: Optional - // Stability: stable - // Examples: 65123 - NetworkPeerPortKey = attribute.Key("network.peer.port") - - // NetworkProtocolNameKey is the attribute Key conforming to the - // "network.protocol.name" semantic conventions. It represents the [OSI - // application layer](https://osi-model.com/application-layer/) or non-OSI - // equivalent. - // - // Type: string - // RequirementLevel: Optional - // Stability: stable - // Examples: 'amqp', 'http', 'mqtt' - // Note: The value SHOULD be normalized to lowercase. - NetworkProtocolNameKey = attribute.Key("network.protocol.name") - - // NetworkProtocolVersionKey is the attribute Key conforming to the - // "network.protocol.version" semantic conventions. It represents the - // version of the protocol specified in `network.protocol.name`. - // - // Type: string - // RequirementLevel: Optional - // Stability: stable - // Examples: '3.1.1' - // Note: `network.protocol.version` refers to the version of the protocol - // used and might be different from the protocol client's version. If the - // HTTP client has a version of `0.27.2`, but sends HTTP version `1.1`, - // this attribute should be set to `1.1`. - NetworkProtocolVersionKey = attribute.Key("network.protocol.version") - - // NetworkTransportKey is the attribute Key conforming to the - // "network.transport" semantic conventions. It represents the [OSI - // transport layer](https://osi-model.com/transport-layer/) or - // [inter-process communication - // method](https://wikipedia.org/wiki/Inter-process_communication). - // - // Type: Enum - // RequirementLevel: Optional - // Stability: stable - // Examples: 'tcp', 'udp' - // Note: The value SHOULD be normalized to lowercase. - // - // Consider always setting the transport when setting a port number, since - // a port number is ambiguous without knowing the transport. For example - // different processes could be listening on TCP port 12345 and UDP port - // 12345. - NetworkTransportKey = attribute.Key("network.transport") - - // NetworkTypeKey is the attribute Key conforming to the "network.type" - // semantic conventions. It represents the [OSI network - // layer](https://osi-model.com/network-layer/) or non-OSI equivalent. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: stable - // Examples: 'ipv4', 'ipv6' - // Note: The value SHOULD be normalized to lowercase. - NetworkTypeKey = attribute.Key("network.type") -) - -var ( - // GPRS - NetworkConnectionSubtypeGprs = NetworkConnectionSubtypeKey.String("gprs") - // EDGE - NetworkConnectionSubtypeEdge = NetworkConnectionSubtypeKey.String("edge") - // UMTS - NetworkConnectionSubtypeUmts = NetworkConnectionSubtypeKey.String("umts") - // CDMA - NetworkConnectionSubtypeCdma = NetworkConnectionSubtypeKey.String("cdma") - // EVDO Rel. 0 - NetworkConnectionSubtypeEvdo0 = NetworkConnectionSubtypeKey.String("evdo_0") - // EVDO Rev. A - NetworkConnectionSubtypeEvdoA = NetworkConnectionSubtypeKey.String("evdo_a") - // CDMA2000 1XRTT - NetworkConnectionSubtypeCdma20001xrtt = NetworkConnectionSubtypeKey.String("cdma2000_1xrtt") - // HSDPA - NetworkConnectionSubtypeHsdpa = NetworkConnectionSubtypeKey.String("hsdpa") - // HSUPA - NetworkConnectionSubtypeHsupa = NetworkConnectionSubtypeKey.String("hsupa") - // HSPA - NetworkConnectionSubtypeHspa = NetworkConnectionSubtypeKey.String("hspa") - // IDEN - NetworkConnectionSubtypeIden = NetworkConnectionSubtypeKey.String("iden") - // EVDO Rev. B - NetworkConnectionSubtypeEvdoB = NetworkConnectionSubtypeKey.String("evdo_b") - // LTE - NetworkConnectionSubtypeLte = NetworkConnectionSubtypeKey.String("lte") - // EHRPD - NetworkConnectionSubtypeEhrpd = NetworkConnectionSubtypeKey.String("ehrpd") - // HSPAP - NetworkConnectionSubtypeHspap = NetworkConnectionSubtypeKey.String("hspap") - // GSM - NetworkConnectionSubtypeGsm = NetworkConnectionSubtypeKey.String("gsm") - // TD-SCDMA - NetworkConnectionSubtypeTdScdma = NetworkConnectionSubtypeKey.String("td_scdma") - // IWLAN - NetworkConnectionSubtypeIwlan = NetworkConnectionSubtypeKey.String("iwlan") - // 5G NR (New Radio) - NetworkConnectionSubtypeNr = NetworkConnectionSubtypeKey.String("nr") - // 5G NRNSA (New Radio Non-Standalone) - NetworkConnectionSubtypeNrnsa = NetworkConnectionSubtypeKey.String("nrnsa") - // LTE CA - NetworkConnectionSubtypeLteCa = NetworkConnectionSubtypeKey.String("lte_ca") -) - -var ( - // wifi - NetworkConnectionTypeWifi = NetworkConnectionTypeKey.String("wifi") - // wired - NetworkConnectionTypeWired = NetworkConnectionTypeKey.String("wired") - // cell - NetworkConnectionTypeCell = NetworkConnectionTypeKey.String("cell") - // unavailable - NetworkConnectionTypeUnavailable = NetworkConnectionTypeKey.String("unavailable") - // unknown - NetworkConnectionTypeUnknown = NetworkConnectionTypeKey.String("unknown") -) - -var ( - // transmit - NetworkIoDirectionTransmit = NetworkIoDirectionKey.String("transmit") - // receive - NetworkIoDirectionReceive = NetworkIoDirectionKey.String("receive") -) - -var ( - // TCP - NetworkTransportTCP = NetworkTransportKey.String("tcp") - // UDP - NetworkTransportUDP = NetworkTransportKey.String("udp") - // Named or anonymous pipe - NetworkTransportPipe = NetworkTransportKey.String("pipe") - // Unix domain socket - NetworkTransportUnix = NetworkTransportKey.String("unix") -) - -var ( - // IPv4 - NetworkTypeIpv4 = NetworkTypeKey.String("ipv4") - // IPv6 - NetworkTypeIpv6 = NetworkTypeKey.String("ipv6") -) - -// NetworkCarrierIcc returns an attribute KeyValue conforming to the -// "network.carrier.icc" semantic conventions. It represents the ISO 3166-1 -// alpha-2 2-character country code associated with the mobile carrier network. -func NetworkCarrierIcc(val string) attribute.KeyValue { - return NetworkCarrierIccKey.String(val) -} - -// NetworkCarrierMcc returns an attribute KeyValue conforming to the -// "network.carrier.mcc" semantic conventions. It represents the mobile carrier -// country code. -func NetworkCarrierMcc(val string) attribute.KeyValue { - return NetworkCarrierMccKey.String(val) -} - -// NetworkCarrierMnc returns an attribute KeyValue conforming to the -// "network.carrier.mnc" semantic conventions. It represents the mobile carrier -// network code. -func NetworkCarrierMnc(val string) attribute.KeyValue { - return NetworkCarrierMncKey.String(val) -} - -// NetworkCarrierName returns an attribute KeyValue conforming to the -// "network.carrier.name" semantic conventions. It represents the name of the -// mobile carrier. -func NetworkCarrierName(val string) attribute.KeyValue { - return NetworkCarrierNameKey.String(val) -} - -// NetworkLocalAddress returns an attribute KeyValue conforming to the -// "network.local.address" semantic conventions. It represents the local -// address of the network connection - IP address or Unix domain socket name. -func NetworkLocalAddress(val string) attribute.KeyValue { - return NetworkLocalAddressKey.String(val) -} - -// NetworkLocalPort returns an attribute KeyValue conforming to the -// "network.local.port" semantic conventions. It represents the local port -// number of the network connection. -func NetworkLocalPort(val int) attribute.KeyValue { - return NetworkLocalPortKey.Int(val) -} - -// NetworkPeerAddress returns an attribute KeyValue conforming to the -// "network.peer.address" semantic conventions. It represents the peer address -// of the network connection - IP address or Unix domain socket name. -func NetworkPeerAddress(val string) attribute.KeyValue { - return NetworkPeerAddressKey.String(val) -} - -// NetworkPeerPort returns an attribute KeyValue conforming to the -// "network.peer.port" semantic conventions. It represents the peer port number -// of the network connection. -func NetworkPeerPort(val int) attribute.KeyValue { - return NetworkPeerPortKey.Int(val) -} - -// NetworkProtocolName returns an attribute KeyValue conforming to the -// "network.protocol.name" semantic conventions. It represents the [OSI -// application layer](https://osi-model.com/application-layer/) or non-OSI -// equivalent. -func NetworkProtocolName(val string) attribute.KeyValue { - return NetworkProtocolNameKey.String(val) -} - -// NetworkProtocolVersion returns an attribute KeyValue conforming to the -// "network.protocol.version" semantic conventions. It represents the version -// of the protocol specified in `network.protocol.name`. -func NetworkProtocolVersion(val string) attribute.KeyValue { - return NetworkProtocolVersionKey.String(val) -} - -// Attributes for remote procedure calls. -const ( - // RPCConnectRPCErrorCodeKey is the attribute Key conforming to the - // "rpc.connect_rpc.error_code" semantic conventions. It represents the - // [error codes](https://connect.build/docs/protocol/#error-codes) of the - // Connect request. Error codes are always string values. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - RPCConnectRPCErrorCodeKey = attribute.Key("rpc.connect_rpc.error_code") - - // RPCGRPCStatusCodeKey is the attribute Key conforming to the - // "rpc.grpc.status_code" semantic conventions. It represents the [numeric - // status - // code](https://github.com/grpc/grpc/blob/v1.33.2/doc/statuscodes.md) of - // the gRPC request. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - RPCGRPCStatusCodeKey = attribute.Key("rpc.grpc.status_code") - - // RPCJsonrpcErrorCodeKey is the attribute Key conforming to the - // "rpc.jsonrpc.error_code" semantic conventions. It represents the - // `error.code` property of response if it is an error response. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: -32700, 100 - RPCJsonrpcErrorCodeKey = attribute.Key("rpc.jsonrpc.error_code") - - // RPCJsonrpcErrorMessageKey is the attribute Key conforming to the - // "rpc.jsonrpc.error_message" semantic conventions. It represents the - // `error.message` property of response if it is an error response. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'Parse error', 'User already exists' - RPCJsonrpcErrorMessageKey = attribute.Key("rpc.jsonrpc.error_message") - - // RPCJsonrpcRequestIDKey is the attribute Key conforming to the - // "rpc.jsonrpc.request_id" semantic conventions. It represents the `id` - // property of request or response. Since protocol allows id to be int, - // string, `null` or missing (for notifications), value is expected to be - // cast to string for simplicity. Use empty string in case of `null` value. - // Omit entirely if this is a notification. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '10', 'request-7', '' - RPCJsonrpcRequestIDKey = attribute.Key("rpc.jsonrpc.request_id") - - // RPCJsonrpcVersionKey is the attribute Key conforming to the - // "rpc.jsonrpc.version" semantic conventions. It represents the protocol - // version as in `jsonrpc` property of request/response. Since JSON-RPC 1.0 - // doesn't specify this, the value can be omitted. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '2.0', '1.0' - RPCJsonrpcVersionKey = attribute.Key("rpc.jsonrpc.version") - - // RPCMethodKey is the attribute Key conforming to the "rpc.method" - // semantic conventions. It represents the name of the (logical) method - // being called, must be equal to the $method part in the span name. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'exampleMethod' - // Note: This is the logical name of the method from the RPC interface - // perspective, which can be different from the name of any implementing - // method/function. The `code.function` attribute may be used to store the - // latter (e.g., method actually executing the call on the server side, RPC - // client stub method on the client side). - RPCMethodKey = attribute.Key("rpc.method") - - // RPCServiceKey is the attribute Key conforming to the "rpc.service" - // semantic conventions. It represents the full (logical) name of the - // service being called, including its package name, if applicable. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'myservice.EchoService' - // Note: This is the logical name of the service from the RPC interface - // perspective, which can be different from the name of any implementing - // class. The `code.namespace` attribute may be used to store the latter - // (despite the attribute name, it may include a class name; e.g., class - // with method actually executing the call on the server side, RPC client - // stub class on the client side). - RPCServiceKey = attribute.Key("rpc.service") - - // RPCSystemKey is the attribute Key conforming to the "rpc.system" - // semantic conventions. It represents a string identifying the remoting - // system. See below for a list of well-known identifiers. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - RPCSystemKey = attribute.Key("rpc.system") -) - -var ( - // cancelled - RPCConnectRPCErrorCodeCancelled = RPCConnectRPCErrorCodeKey.String("cancelled") - // unknown - RPCConnectRPCErrorCodeUnknown = RPCConnectRPCErrorCodeKey.String("unknown") - // invalid_argument - RPCConnectRPCErrorCodeInvalidArgument = RPCConnectRPCErrorCodeKey.String("invalid_argument") - // deadline_exceeded - RPCConnectRPCErrorCodeDeadlineExceeded = RPCConnectRPCErrorCodeKey.String("deadline_exceeded") - // not_found - RPCConnectRPCErrorCodeNotFound = RPCConnectRPCErrorCodeKey.String("not_found") - // already_exists - RPCConnectRPCErrorCodeAlreadyExists = RPCConnectRPCErrorCodeKey.String("already_exists") - // permission_denied - RPCConnectRPCErrorCodePermissionDenied = RPCConnectRPCErrorCodeKey.String("permission_denied") - // resource_exhausted - RPCConnectRPCErrorCodeResourceExhausted = RPCConnectRPCErrorCodeKey.String("resource_exhausted") - // failed_precondition - RPCConnectRPCErrorCodeFailedPrecondition = RPCConnectRPCErrorCodeKey.String("failed_precondition") - // aborted - RPCConnectRPCErrorCodeAborted = RPCConnectRPCErrorCodeKey.String("aborted") - // out_of_range - RPCConnectRPCErrorCodeOutOfRange = RPCConnectRPCErrorCodeKey.String("out_of_range") - // unimplemented - RPCConnectRPCErrorCodeUnimplemented = RPCConnectRPCErrorCodeKey.String("unimplemented") - // internal - RPCConnectRPCErrorCodeInternal = RPCConnectRPCErrorCodeKey.String("internal") - // unavailable - RPCConnectRPCErrorCodeUnavailable = RPCConnectRPCErrorCodeKey.String("unavailable") - // data_loss - RPCConnectRPCErrorCodeDataLoss = RPCConnectRPCErrorCodeKey.String("data_loss") - // unauthenticated - RPCConnectRPCErrorCodeUnauthenticated = RPCConnectRPCErrorCodeKey.String("unauthenticated") -) - -var ( - // OK - RPCGRPCStatusCodeOk = RPCGRPCStatusCodeKey.Int(0) - // CANCELLED - RPCGRPCStatusCodeCancelled = RPCGRPCStatusCodeKey.Int(1) - // UNKNOWN - RPCGRPCStatusCodeUnknown = RPCGRPCStatusCodeKey.Int(2) - // INVALID_ARGUMENT - RPCGRPCStatusCodeInvalidArgument = RPCGRPCStatusCodeKey.Int(3) - // DEADLINE_EXCEEDED - RPCGRPCStatusCodeDeadlineExceeded = RPCGRPCStatusCodeKey.Int(4) - // NOT_FOUND - RPCGRPCStatusCodeNotFound = RPCGRPCStatusCodeKey.Int(5) - // ALREADY_EXISTS - RPCGRPCStatusCodeAlreadyExists = RPCGRPCStatusCodeKey.Int(6) - // PERMISSION_DENIED - RPCGRPCStatusCodePermissionDenied = RPCGRPCStatusCodeKey.Int(7) - // RESOURCE_EXHAUSTED - RPCGRPCStatusCodeResourceExhausted = RPCGRPCStatusCodeKey.Int(8) - // FAILED_PRECONDITION - RPCGRPCStatusCodeFailedPrecondition = RPCGRPCStatusCodeKey.Int(9) - // ABORTED - RPCGRPCStatusCodeAborted = RPCGRPCStatusCodeKey.Int(10) - // OUT_OF_RANGE - RPCGRPCStatusCodeOutOfRange = RPCGRPCStatusCodeKey.Int(11) - // UNIMPLEMENTED - RPCGRPCStatusCodeUnimplemented = RPCGRPCStatusCodeKey.Int(12) - // INTERNAL - RPCGRPCStatusCodeInternal = RPCGRPCStatusCodeKey.Int(13) - // UNAVAILABLE - RPCGRPCStatusCodeUnavailable = RPCGRPCStatusCodeKey.Int(14) - // DATA_LOSS - RPCGRPCStatusCodeDataLoss = RPCGRPCStatusCodeKey.Int(15) - // UNAUTHENTICATED - RPCGRPCStatusCodeUnauthenticated = RPCGRPCStatusCodeKey.Int(16) -) - -var ( - // gRPC - RPCSystemGRPC = RPCSystemKey.String("grpc") - // Java RMI - RPCSystemJavaRmi = RPCSystemKey.String("java_rmi") - // .NET WCF - RPCSystemDotnetWcf = RPCSystemKey.String("dotnet_wcf") - // Apache Dubbo - RPCSystemApacheDubbo = RPCSystemKey.String("apache_dubbo") - // Connect RPC - RPCSystemConnectRPC = RPCSystemKey.String("connect_rpc") -) - -// RPCJsonrpcErrorCode returns an attribute KeyValue conforming to the -// "rpc.jsonrpc.error_code" semantic conventions. It represents the -// `error.code` property of response if it is an error response. -func RPCJsonrpcErrorCode(val int) attribute.KeyValue { - return RPCJsonrpcErrorCodeKey.Int(val) -} - -// RPCJsonrpcErrorMessage returns an attribute KeyValue conforming to the -// "rpc.jsonrpc.error_message" semantic conventions. It represents the -// `error.message` property of response if it is an error response. -func RPCJsonrpcErrorMessage(val string) attribute.KeyValue { - return RPCJsonrpcErrorMessageKey.String(val) -} - -// RPCJsonrpcRequestID returns an attribute KeyValue conforming to the -// "rpc.jsonrpc.request_id" semantic conventions. It represents the `id` -// property of request or response. Since protocol allows id to be int, string, -// `null` or missing (for notifications), value is expected to be cast to -// string for simplicity. Use empty string in case of `null` value. Omit -// entirely if this is a notification. -func RPCJsonrpcRequestID(val string) attribute.KeyValue { - return RPCJsonrpcRequestIDKey.String(val) -} - -// RPCJsonrpcVersion returns an attribute KeyValue conforming to the -// "rpc.jsonrpc.version" semantic conventions. It represents the protocol -// version as in `jsonrpc` property of request/response. Since JSON-RPC 1.0 -// doesn't specify this, the value can be omitted. -func RPCJsonrpcVersion(val string) attribute.KeyValue { - return RPCJsonrpcVersionKey.String(val) -} - -// RPCMethod returns an attribute KeyValue conforming to the "rpc.method" -// semantic conventions. It represents the name of the (logical) method being -// called, must be equal to the $method part in the span name. -func RPCMethod(val string) attribute.KeyValue { - return RPCMethodKey.String(val) -} - -// RPCService returns an attribute KeyValue conforming to the "rpc.service" -// semantic conventions. It represents the full (logical) name of the service -// being called, including its package name, if applicable. -func RPCService(val string) attribute.KeyValue { - return RPCServiceKey.String(val) -} - -// These attributes may be used to describe the server in a connection-based -// network interaction where there is one side that initiates the connection -// (the client is the side that initiates the connection). This covers all TCP -// network interactions since TCP is connection-based and one side initiates -// the connection (an exception is made for peer-to-peer communication over TCP -// where the "user-facing" surface of the protocol / API doesn't expose a clear -// notion of client and server). This also covers UDP network interactions -// where one side initiates the interaction, e.g. QUIC (HTTP/3) and DNS. -const ( - // ServerAddressKey is the attribute Key conforming to the "server.address" - // semantic conventions. It represents the server domain name if available - // without reverse DNS lookup; otherwise, IP address or Unix domain socket - // name. - // - // Type: string - // RequirementLevel: Optional - // Stability: stable - // Examples: 'example.com', '10.1.2.80', '/tmp/my.sock' - // Note: When observed from the client side, and when communicating through - // an intermediary, `server.address` SHOULD represent the server address - // behind any intermediaries, for example proxies, if it's available. - ServerAddressKey = attribute.Key("server.address") - - // ServerPortKey is the attribute Key conforming to the "server.port" - // semantic conventions. It represents the server port number. - // - // Type: int - // RequirementLevel: Optional - // Stability: stable - // Examples: 80, 8080, 443 - // Note: When observed from the client side, and when communicating through - // an intermediary, `server.port` SHOULD represent the server port behind - // any intermediaries, for example proxies, if it's available. - ServerPortKey = attribute.Key("server.port") -) - -// ServerAddress returns an attribute KeyValue conforming to the -// "server.address" semantic conventions. It represents the server domain name -// if available without reverse DNS lookup; otherwise, IP address or Unix -// domain socket name. -func ServerAddress(val string) attribute.KeyValue { - return ServerAddressKey.String(val) -} - -// ServerPort returns an attribute KeyValue conforming to the "server.port" -// semantic conventions. It represents the server port number. -func ServerPort(val int) attribute.KeyValue { - return ServerPortKey.Int(val) -} - -// These attributes may be used to describe the sender of a network -// exchange/packet. These should be used when there is no client/server -// relationship between the two sides, or when that relationship is unknown. -// This covers low-level network interactions (e.g. packet tracing) where you -// don't know if there was a connection or which side initiated it. This also -// covers unidirectional UDP flows and peer-to-peer communication where the -// "user-facing" surface of the protocol / API doesn't expose a clear notion of -// client and server. -const ( - // SourceAddressKey is the attribute Key conforming to the "source.address" - // semantic conventions. It represents the source address - domain name if - // available without reverse DNS lookup; otherwise, IP address or Unix - // domain socket name. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'source.example.com', '10.1.2.80', '/tmp/my.sock' - // Note: When observed from the destination side, and when communicating - // through an intermediary, `source.address` SHOULD represent the source - // address behind any intermediaries, for example proxies, if it's - // available. - SourceAddressKey = attribute.Key("source.address") - - // SourcePortKey is the attribute Key conforming to the "source.port" - // semantic conventions. It represents the source port number - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 3389, 2888 - SourcePortKey = attribute.Key("source.port") -) - -// SourceAddress returns an attribute KeyValue conforming to the -// "source.address" semantic conventions. It represents the source address - -// domain name if available without reverse DNS lookup; otherwise, IP address -// or Unix domain socket name. -func SourceAddress(val string) attribute.KeyValue { - return SourceAddressKey.String(val) -} - -// SourcePort returns an attribute KeyValue conforming to the "source.port" -// semantic conventions. It represents the source port number -func SourcePort(val int) attribute.KeyValue { - return SourcePortKey.Int(val) -} - -// Semantic convention attributes in the TLS namespace. -const ( - // TLSCipherKey is the attribute Key conforming to the "tls.cipher" - // semantic conventions. It represents the string indicating the - // [cipher](https://datatracker.ietf.org/doc/html/rfc5246#appendix-A.5) - // used during the current connection. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'TLS_RSA_WITH_3DES_EDE_CBC_SHA', - // 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256' - // Note: The values allowed for `tls.cipher` MUST be one of the - // `Descriptions` of the [registered TLS Cipher - // Suits](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#table-tls-parameters-4). - TLSCipherKey = attribute.Key("tls.cipher") - - // TLSClientCertificateKey is the attribute Key conforming to the - // "tls.client.certificate" semantic conventions. It represents the - // pEM-encoded stand-alone certificate offered by the client. This is - // usually mutually-exclusive of `client.certificate_chain` since this - // value also exists in that list. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'MII...' - TLSClientCertificateKey = attribute.Key("tls.client.certificate") - - // TLSClientCertificateChainKey is the attribute Key conforming to the - // "tls.client.certificate_chain" semantic conventions. It represents the - // array of PEM-encoded certificates that make up the certificate chain - // offered by the client. This is usually mutually-exclusive of - // `client.certificate` since that value should be the first certificate in - // the chain. - // - // Type: string[] - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'MII...', 'MI...' - TLSClientCertificateChainKey = attribute.Key("tls.client.certificate_chain") - - // TLSClientHashMd5Key is the attribute Key conforming to the - // "tls.client.hash.md5" semantic conventions. It represents the - // certificate fingerprint using the MD5 digest of DER-encoded version of - // certificate offered by the client. For consistency with other hash - // values, this value should be formatted as an uppercase hash. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC' - TLSClientHashMd5Key = attribute.Key("tls.client.hash.md5") - - // TLSClientHashSha1Key is the attribute Key conforming to the - // "tls.client.hash.sha1" semantic conventions. It represents the - // certificate fingerprint using the SHA1 digest of DER-encoded version of - // certificate offered by the client. For consistency with other hash - // values, this value should be formatted as an uppercase hash. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '9E393D93138888D288266C2D915214D1D1CCEB2A' - TLSClientHashSha1Key = attribute.Key("tls.client.hash.sha1") - - // TLSClientHashSha256Key is the attribute Key conforming to the - // "tls.client.hash.sha256" semantic conventions. It represents the - // certificate fingerprint using the SHA256 digest of DER-encoded version - // of certificate offered by the client. For consistency with other hash - // values, this value should be formatted as an uppercase hash. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: - // '0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0' - TLSClientHashSha256Key = attribute.Key("tls.client.hash.sha256") - - // TLSClientIssuerKey is the attribute Key conforming to the - // "tls.client.issuer" semantic conventions. It represents the - // distinguished name of - // [subject](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6) - // of the issuer of the x.509 certificate presented by the client. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'CN=Example Root CA, OU=Infrastructure Team, DC=example, - // DC=com' - TLSClientIssuerKey = attribute.Key("tls.client.issuer") - - // TLSClientJa3Key is the attribute Key conforming to the "tls.client.ja3" - // semantic conventions. It represents a hash that identifies clients based - // on how they perform an SSL/TLS handshake. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'd4e5b18d6b55c71272893221c96ba240' - TLSClientJa3Key = attribute.Key("tls.client.ja3") - - // TLSClientNotAfterKey is the attribute Key conforming to the - // "tls.client.not_after" semantic conventions. It represents the date/Time - // indicating when client certificate is no longer considered valid. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '2021-01-01T00:00:00.000Z' - TLSClientNotAfterKey = attribute.Key("tls.client.not_after") - - // TLSClientNotBeforeKey is the attribute Key conforming to the - // "tls.client.not_before" semantic conventions. It represents the - // date/Time indicating when client certificate is first considered valid. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '1970-01-01T00:00:00.000Z' - TLSClientNotBeforeKey = attribute.Key("tls.client.not_before") - - // TLSClientServerNameKey is the attribute Key conforming to the - // "tls.client.server_name" semantic conventions. It represents the also - // called an SNI, this tells the server which hostname to which the client - // is attempting to connect to. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'opentelemetry.io' - TLSClientServerNameKey = attribute.Key("tls.client.server_name") - - // TLSClientSubjectKey is the attribute Key conforming to the - // "tls.client.subject" semantic conventions. It represents the - // distinguished name of subject of the x.509 certificate presented by the - // client. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'CN=myclient, OU=Documentation Team, DC=example, DC=com' - TLSClientSubjectKey = attribute.Key("tls.client.subject") - - // TLSClientSupportedCiphersKey is the attribute Key conforming to the - // "tls.client.supported_ciphers" semantic conventions. It represents the - // array of ciphers offered by the client during the client hello. - // - // Type: string[] - // RequirementLevel: Optional - // Stability: experimental - // Examples: '"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", - // "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "..."' - TLSClientSupportedCiphersKey = attribute.Key("tls.client.supported_ciphers") - - // TLSCurveKey is the attribute Key conforming to the "tls.curve" semantic - // conventions. It represents the string indicating the curve used for the - // given cipher, when applicable - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'secp256r1' - TLSCurveKey = attribute.Key("tls.curve") - - // TLSEstablishedKey is the attribute Key conforming to the - // "tls.established" semantic conventions. It represents the boolean flag - // indicating if the TLS negotiation was successful and transitioned to an - // encrypted tunnel. - // - // Type: boolean - // RequirementLevel: Optional - // Stability: experimental - // Examples: True - TLSEstablishedKey = attribute.Key("tls.established") - - // TLSNextProtocolKey is the attribute Key conforming to the - // "tls.next_protocol" semantic conventions. It represents the string - // indicating the protocol being tunneled. Per the values in the [IANA - // registry](https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids), - // this string should be lower case. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'http/1.1' - TLSNextProtocolKey = attribute.Key("tls.next_protocol") - - // TLSProtocolNameKey is the attribute Key conforming to the - // "tls.protocol.name" semantic conventions. It represents the normalized - // lowercase protocol name parsed from original string of the negotiated - // [SSL/TLS protocol - // version](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_version.html#RETURN-VALUES) - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - TLSProtocolNameKey = attribute.Key("tls.protocol.name") - - // TLSProtocolVersionKey is the attribute Key conforming to the - // "tls.protocol.version" semantic conventions. It represents the numeric - // part of the version parsed from the original string of the negotiated - // [SSL/TLS protocol - // version](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_version.html#RETURN-VALUES) - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '1.2', '3' - TLSProtocolVersionKey = attribute.Key("tls.protocol.version") - - // TLSResumedKey is the attribute Key conforming to the "tls.resumed" - // semantic conventions. It represents the boolean flag indicating if this - // TLS connection was resumed from an existing TLS negotiation. - // - // Type: boolean - // RequirementLevel: Optional - // Stability: experimental - // Examples: True - TLSResumedKey = attribute.Key("tls.resumed") - - // TLSServerCertificateKey is the attribute Key conforming to the - // "tls.server.certificate" semantic conventions. It represents the - // pEM-encoded stand-alone certificate offered by the server. This is - // usually mutually-exclusive of `server.certificate_chain` since this - // value also exists in that list. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'MII...' - TLSServerCertificateKey = attribute.Key("tls.server.certificate") - - // TLSServerCertificateChainKey is the attribute Key conforming to the - // "tls.server.certificate_chain" semantic conventions. It represents the - // array of PEM-encoded certificates that make up the certificate chain - // offered by the server. This is usually mutually-exclusive of - // `server.certificate` since that value should be the first certificate in - // the chain. - // - // Type: string[] - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'MII...', 'MI...' - TLSServerCertificateChainKey = attribute.Key("tls.server.certificate_chain") - - // TLSServerHashMd5Key is the attribute Key conforming to the - // "tls.server.hash.md5" semantic conventions. It represents the - // certificate fingerprint using the MD5 digest of DER-encoded version of - // certificate offered by the server. For consistency with other hash - // values, this value should be formatted as an uppercase hash. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC' - TLSServerHashMd5Key = attribute.Key("tls.server.hash.md5") - - // TLSServerHashSha1Key is the attribute Key conforming to the - // "tls.server.hash.sha1" semantic conventions. It represents the - // certificate fingerprint using the SHA1 digest of DER-encoded version of - // certificate offered by the server. For consistency with other hash - // values, this value should be formatted as an uppercase hash. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '9E393D93138888D288266C2D915214D1D1CCEB2A' - TLSServerHashSha1Key = attribute.Key("tls.server.hash.sha1") - - // TLSServerHashSha256Key is the attribute Key conforming to the - // "tls.server.hash.sha256" semantic conventions. It represents the - // certificate fingerprint using the SHA256 digest of DER-encoded version - // of certificate offered by the server. For consistency with other hash - // values, this value should be formatted as an uppercase hash. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: - // '0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0' - TLSServerHashSha256Key = attribute.Key("tls.server.hash.sha256") - - // TLSServerIssuerKey is the attribute Key conforming to the - // "tls.server.issuer" semantic conventions. It represents the - // distinguished name of - // [subject](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6) - // of the issuer of the x.509 certificate presented by the client. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'CN=Example Root CA, OU=Infrastructure Team, DC=example, - // DC=com' - TLSServerIssuerKey = attribute.Key("tls.server.issuer") - - // TLSServerJa3sKey is the attribute Key conforming to the - // "tls.server.ja3s" semantic conventions. It represents a hash that - // identifies servers based on how they perform an SSL/TLS handshake. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'd4e5b18d6b55c71272893221c96ba240' - TLSServerJa3sKey = attribute.Key("tls.server.ja3s") - - // TLSServerNotAfterKey is the attribute Key conforming to the - // "tls.server.not_after" semantic conventions. It represents the date/Time - // indicating when server certificate is no longer considered valid. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '2021-01-01T00:00:00.000Z' - TLSServerNotAfterKey = attribute.Key("tls.server.not_after") - - // TLSServerNotBeforeKey is the attribute Key conforming to the - // "tls.server.not_before" semantic conventions. It represents the - // date/Time indicating when server certificate is first considered valid. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '1970-01-01T00:00:00.000Z' - TLSServerNotBeforeKey = attribute.Key("tls.server.not_before") - - // TLSServerSubjectKey is the attribute Key conforming to the - // "tls.server.subject" semantic conventions. It represents the - // distinguished name of subject of the x.509 certificate presented by the - // server. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'CN=myserver, OU=Documentation Team, DC=example, DC=com' - TLSServerSubjectKey = attribute.Key("tls.server.subject") -) - -var ( - // ssl - TLSProtocolNameSsl = TLSProtocolNameKey.String("ssl") - // tls - TLSProtocolNameTLS = TLSProtocolNameKey.String("tls") -) - -// TLSCipher returns an attribute KeyValue conforming to the "tls.cipher" -// semantic conventions. It represents the string indicating the -// [cipher](https://datatracker.ietf.org/doc/html/rfc5246#appendix-A.5) used -// during the current connection. -func TLSCipher(val string) attribute.KeyValue { - return TLSCipherKey.String(val) -} - -// TLSClientCertificate returns an attribute KeyValue conforming to the -// "tls.client.certificate" semantic conventions. It represents the pEM-encoded -// stand-alone certificate offered by the client. This is usually -// mutually-exclusive of `client.certificate_chain` since this value also -// exists in that list. -func TLSClientCertificate(val string) attribute.KeyValue { - return TLSClientCertificateKey.String(val) -} - -// TLSClientCertificateChain returns an attribute KeyValue conforming to the -// "tls.client.certificate_chain" semantic conventions. It represents the array -// of PEM-encoded certificates that make up the certificate chain offered by -// the client. This is usually mutually-exclusive of `client.certificate` since -// that value should be the first certificate in the chain. -func TLSClientCertificateChain(val ...string) attribute.KeyValue { - return TLSClientCertificateChainKey.StringSlice(val) -} - -// TLSClientHashMd5 returns an attribute KeyValue conforming to the -// "tls.client.hash.md5" semantic conventions. It represents the certificate -// fingerprint using the MD5 digest of DER-encoded version of certificate -// offered by the client. For consistency with other hash values, this value -// should be formatted as an uppercase hash. -func TLSClientHashMd5(val string) attribute.KeyValue { - return TLSClientHashMd5Key.String(val) -} - -// TLSClientHashSha1 returns an attribute KeyValue conforming to the -// "tls.client.hash.sha1" semantic conventions. It represents the certificate -// fingerprint using the SHA1 digest of DER-encoded version of certificate -// offered by the client. For consistency with other hash values, this value -// should be formatted as an uppercase hash. -func TLSClientHashSha1(val string) attribute.KeyValue { - return TLSClientHashSha1Key.String(val) -} - -// TLSClientHashSha256 returns an attribute KeyValue conforming to the -// "tls.client.hash.sha256" semantic conventions. It represents the certificate -// fingerprint using the SHA256 digest of DER-encoded version of certificate -// offered by the client. For consistency with other hash values, this value -// should be formatted as an uppercase hash. -func TLSClientHashSha256(val string) attribute.KeyValue { - return TLSClientHashSha256Key.String(val) -} - -// TLSClientIssuer returns an attribute KeyValue conforming to the -// "tls.client.issuer" semantic conventions. It represents the distinguished -// name of -// [subject](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6) of -// the issuer of the x.509 certificate presented by the client. -func TLSClientIssuer(val string) attribute.KeyValue { - return TLSClientIssuerKey.String(val) -} - -// TLSClientJa3 returns an attribute KeyValue conforming to the -// "tls.client.ja3" semantic conventions. It represents a hash that identifies -// clients based on how they perform an SSL/TLS handshake. -func TLSClientJa3(val string) attribute.KeyValue { - return TLSClientJa3Key.String(val) -} - -// TLSClientNotAfter returns an attribute KeyValue conforming to the -// "tls.client.not_after" semantic conventions. It represents the date/Time -// indicating when client certificate is no longer considered valid. -func TLSClientNotAfter(val string) attribute.KeyValue { - return TLSClientNotAfterKey.String(val) -} - -// TLSClientNotBefore returns an attribute KeyValue conforming to the -// "tls.client.not_before" semantic conventions. It represents the date/Time -// indicating when client certificate is first considered valid. -func TLSClientNotBefore(val string) attribute.KeyValue { - return TLSClientNotBeforeKey.String(val) -} - -// TLSClientServerName returns an attribute KeyValue conforming to the -// "tls.client.server_name" semantic conventions. It represents the also called -// an SNI, this tells the server which hostname to which the client is -// attempting to connect to. -func TLSClientServerName(val string) attribute.KeyValue { - return TLSClientServerNameKey.String(val) -} - -// TLSClientSubject returns an attribute KeyValue conforming to the -// "tls.client.subject" semantic conventions. It represents the distinguished -// name of subject of the x.509 certificate presented by the client. -func TLSClientSubject(val string) attribute.KeyValue { - return TLSClientSubjectKey.String(val) -} - -// TLSClientSupportedCiphers returns an attribute KeyValue conforming to the -// "tls.client.supported_ciphers" semantic conventions. It represents the array -// of ciphers offered by the client during the client hello. -func TLSClientSupportedCiphers(val ...string) attribute.KeyValue { - return TLSClientSupportedCiphersKey.StringSlice(val) -} - -// TLSCurve returns an attribute KeyValue conforming to the "tls.curve" -// semantic conventions. It represents the string indicating the curve used for -// the given cipher, when applicable -func TLSCurve(val string) attribute.KeyValue { - return TLSCurveKey.String(val) -} - -// TLSEstablished returns an attribute KeyValue conforming to the -// "tls.established" semantic conventions. It represents the boolean flag -// indicating if the TLS negotiation was successful and transitioned to an -// encrypted tunnel. -func TLSEstablished(val bool) attribute.KeyValue { - return TLSEstablishedKey.Bool(val) -} - -// TLSNextProtocol returns an attribute KeyValue conforming to the -// "tls.next_protocol" semantic conventions. It represents the string -// indicating the protocol being tunneled. Per the values in the [IANA -// registry](https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids), -// this string should be lower case. -func TLSNextProtocol(val string) attribute.KeyValue { - return TLSNextProtocolKey.String(val) -} - -// TLSProtocolVersion returns an attribute KeyValue conforming to the -// "tls.protocol.version" semantic conventions. It represents the numeric part -// of the version parsed from the original string of the negotiated [SSL/TLS -// protocol -// version](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_version.html#RETURN-VALUES) -func TLSProtocolVersion(val string) attribute.KeyValue { - return TLSProtocolVersionKey.String(val) -} - -// TLSResumed returns an attribute KeyValue conforming to the "tls.resumed" -// semantic conventions. It represents the boolean flag indicating if this TLS -// connection was resumed from an existing TLS negotiation. -func TLSResumed(val bool) attribute.KeyValue { - return TLSResumedKey.Bool(val) -} - -// TLSServerCertificate returns an attribute KeyValue conforming to the -// "tls.server.certificate" semantic conventions. It represents the pEM-encoded -// stand-alone certificate offered by the server. This is usually -// mutually-exclusive of `server.certificate_chain` since this value also -// exists in that list. -func TLSServerCertificate(val string) attribute.KeyValue { - return TLSServerCertificateKey.String(val) -} - -// TLSServerCertificateChain returns an attribute KeyValue conforming to the -// "tls.server.certificate_chain" semantic conventions. It represents the array -// of PEM-encoded certificates that make up the certificate chain offered by -// the server. This is usually mutually-exclusive of `server.certificate` since -// that value should be the first certificate in the chain. -func TLSServerCertificateChain(val ...string) attribute.KeyValue { - return TLSServerCertificateChainKey.StringSlice(val) -} - -// TLSServerHashMd5 returns an attribute KeyValue conforming to the -// "tls.server.hash.md5" semantic conventions. It represents the certificate -// fingerprint using the MD5 digest of DER-encoded version of certificate -// offered by the server. For consistency with other hash values, this value -// should be formatted as an uppercase hash. -func TLSServerHashMd5(val string) attribute.KeyValue { - return TLSServerHashMd5Key.String(val) -} - -// TLSServerHashSha1 returns an attribute KeyValue conforming to the -// "tls.server.hash.sha1" semantic conventions. It represents the certificate -// fingerprint using the SHA1 digest of DER-encoded version of certificate -// offered by the server. For consistency with other hash values, this value -// should be formatted as an uppercase hash. -func TLSServerHashSha1(val string) attribute.KeyValue { - return TLSServerHashSha1Key.String(val) -} - -// TLSServerHashSha256 returns an attribute KeyValue conforming to the -// "tls.server.hash.sha256" semantic conventions. It represents the certificate -// fingerprint using the SHA256 digest of DER-encoded version of certificate -// offered by the server. For consistency with other hash values, this value -// should be formatted as an uppercase hash. -func TLSServerHashSha256(val string) attribute.KeyValue { - return TLSServerHashSha256Key.String(val) -} - -// TLSServerIssuer returns an attribute KeyValue conforming to the -// "tls.server.issuer" semantic conventions. It represents the distinguished -// name of -// [subject](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6) of -// the issuer of the x.509 certificate presented by the client. -func TLSServerIssuer(val string) attribute.KeyValue { - return TLSServerIssuerKey.String(val) -} - -// TLSServerJa3s returns an attribute KeyValue conforming to the -// "tls.server.ja3s" semantic conventions. It represents a hash that identifies -// servers based on how they perform an SSL/TLS handshake. -func TLSServerJa3s(val string) attribute.KeyValue { - return TLSServerJa3sKey.String(val) -} - -// TLSServerNotAfter returns an attribute KeyValue conforming to the -// "tls.server.not_after" semantic conventions. It represents the date/Time -// indicating when server certificate is no longer considered valid. -func TLSServerNotAfter(val string) attribute.KeyValue { - return TLSServerNotAfterKey.String(val) -} - -// TLSServerNotBefore returns an attribute KeyValue conforming to the -// "tls.server.not_before" semantic conventions. It represents the date/Time -// indicating when server certificate is first considered valid. -func TLSServerNotBefore(val string) attribute.KeyValue { - return TLSServerNotBeforeKey.String(val) -} - -// TLSServerSubject returns an attribute KeyValue conforming to the -// "tls.server.subject" semantic conventions. It represents the distinguished -// name of subject of the x.509 certificate presented by the server. -func TLSServerSubject(val string) attribute.KeyValue { - return TLSServerSubjectKey.String(val) -} - -// Attributes describing URL. -const ( - // URLFragmentKey is the attribute Key conforming to the "url.fragment" - // semantic conventions. It represents the [URI - // fragment](https://www.rfc-editor.org/rfc/rfc3986#section-3.5) component - // - // Type: string - // RequirementLevel: Optional - // Stability: stable - // Examples: 'SemConv' - URLFragmentKey = attribute.Key("url.fragment") - - // URLFullKey is the attribute Key conforming to the "url.full" semantic - // conventions. It represents the absolute URL describing a network - // resource according to [RFC3986](https://www.rfc-editor.org/rfc/rfc3986) - // - // Type: string - // RequirementLevel: Optional - // Stability: stable - // Examples: 'https://www.foo.bar/search?q=OpenTelemetry#SemConv', - // '//localhost' - // Note: For network calls, URL usually has - // `scheme://host[:port][path][?query][#fragment]` format, where the - // fragment is not transmitted over HTTP, but if it is known, it SHOULD be - // included nevertheless. - // `url.full` MUST NOT contain credentials passed via URL in form of - // `https://username:password@www.example.com/`. In such case username and - // password SHOULD be redacted and attribute's value SHOULD be - // `https://REDACTED:REDACTED@www.example.com/`. - // `url.full` SHOULD capture the absolute URL when it is available (or can - // be reconstructed) and SHOULD NOT be validated or modified except for - // sanitizing purposes. - URLFullKey = attribute.Key("url.full") - - // URLPathKey is the attribute Key conforming to the "url.path" semantic - // conventions. It represents the [URI - // path](https://www.rfc-editor.org/rfc/rfc3986#section-3.3) component - // - // Type: string - // RequirementLevel: Optional - // Stability: stable - // Examples: '/search' - URLPathKey = attribute.Key("url.path") - - // URLQueryKey is the attribute Key conforming to the "url.query" semantic - // conventions. It represents the [URI - // query](https://www.rfc-editor.org/rfc/rfc3986#section-3.4) component - // - // Type: string - // RequirementLevel: Optional - // Stability: stable - // Examples: 'q=OpenTelemetry' - // Note: Sensitive content provided in query string SHOULD be scrubbed when - // instrumentations can identify it. - URLQueryKey = attribute.Key("url.query") - - // URLSchemeKey is the attribute Key conforming to the "url.scheme" - // semantic conventions. It represents the [URI - // scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component - // identifying the used protocol. - // - // Type: string - // RequirementLevel: Optional - // Stability: stable - // Examples: 'https', 'ftp', 'telnet' - URLSchemeKey = attribute.Key("url.scheme") -) - -// URLFragment returns an attribute KeyValue conforming to the -// "url.fragment" semantic conventions. It represents the [URI -// fragment](https://www.rfc-editor.org/rfc/rfc3986#section-3.5) component -func URLFragment(val string) attribute.KeyValue { - return URLFragmentKey.String(val) -} - -// URLFull returns an attribute KeyValue conforming to the "url.full" -// semantic conventions. It represents the absolute URL describing a network -// resource according to [RFC3986](https://www.rfc-editor.org/rfc/rfc3986) -func URLFull(val string) attribute.KeyValue { - return URLFullKey.String(val) -} - -// URLPath returns an attribute KeyValue conforming to the "url.path" -// semantic conventions. It represents the [URI -// path](https://www.rfc-editor.org/rfc/rfc3986#section-3.3) component -func URLPath(val string) attribute.KeyValue { - return URLPathKey.String(val) -} - -// URLQuery returns an attribute KeyValue conforming to the "url.query" -// semantic conventions. It represents the [URI -// query](https://www.rfc-editor.org/rfc/rfc3986#section-3.4) component -func URLQuery(val string) attribute.KeyValue { - return URLQueryKey.String(val) -} - -// URLScheme returns an attribute KeyValue conforming to the "url.scheme" -// semantic conventions. It represents the [URI -// scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component -// identifying the used protocol. -func URLScheme(val string) attribute.KeyValue { - return URLSchemeKey.String(val) -} - -// Describes user-agent attributes. -const ( - // UserAgentOriginalKey is the attribute Key conforming to the - // "user_agent.original" semantic conventions. It represents the value of - // the [HTTP - // User-Agent](https://www.rfc-editor.org/rfc/rfc9110.html#field.user-agent) - // header sent by the client. - // - // Type: string - // RequirementLevel: Optional - // Stability: stable - // Examples: 'CERN-LineMode/2.15 libwww/2.17b3', 'Mozilla/5.0 (iPhone; CPU - // iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) - // Version/14.1.2 Mobile/15E148 Safari/604.1' - UserAgentOriginalKey = attribute.Key("user_agent.original") -) - -// UserAgentOriginal returns an attribute KeyValue conforming to the -// "user_agent.original" semantic conventions. It represents the value of the -// [HTTP -// User-Agent](https://www.rfc-editor.org/rfc/rfc9110.html#field.user-agent) -// header sent by the client. -func UserAgentOriginal(val string) attribute.KeyValue { - return UserAgentOriginalKey.String(val) -} - -// Session is defined as the period of time encompassing all activities -// performed by the application and the actions executed by the end user. -// Consequently, a Session is represented as a collection of Logs, Events, and -// Spans emitted by the Client Application throughout the Session's duration. -// Each Session is assigned a unique identifier, which is included as an -// attribute in the Logs, Events, and Spans generated during the Session's -// lifecycle. -// When a session reaches end of life, typically due to user inactivity or -// session timeout, a new session identifier will be assigned. The previous -// session identifier may be provided by the instrumentation so that telemetry -// backends can link the two sessions. -const ( - // SessionIDKey is the attribute Key conforming to the "session.id" - // semantic conventions. It represents a unique id to identify a session. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '00112233-4455-6677-8899-aabbccddeeff' - SessionIDKey = attribute.Key("session.id") - - // SessionPreviousIDKey is the attribute Key conforming to the - // "session.previous_id" semantic conventions. It represents the previous - // `session.id` for this user, when known. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '00112233-4455-6677-8899-aabbccddeeff' - SessionPreviousIDKey = attribute.Key("session.previous_id") -) - -// SessionID returns an attribute KeyValue conforming to the "session.id" -// semantic conventions. It represents a unique id to identify a session. -func SessionID(val string) attribute.KeyValue { - return SessionIDKey.String(val) -} - -// SessionPreviousID returns an attribute KeyValue conforming to the -// "session.previous_id" semantic conventions. It represents the previous -// `session.id` for this user, when known. -func SessionPreviousID(val string) attribute.KeyValue { - return SessionPreviousIDKey.String(val) -} diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/doc.go b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/doc.go deleted file mode 100644 index d27e8a8f8b..0000000000 --- a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/doc.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -// Package semconv implements OpenTelemetry semantic conventions. -// -// OpenTelemetry semantic conventions are agreed standardized naming -// patterns for OpenTelemetry things. This package represents the v1.24.0 -// version of the OpenTelemetry semantic conventions. -package semconv // import "go.opentelemetry.io/otel/semconv/v1.24.0" diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/event.go b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/event.go deleted file mode 100644 index 6c019aafc3..0000000000 --- a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/event.go +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -// Code generated from semantic convention specification. DO NOT EDIT. - -package semconv // import "go.opentelemetry.io/otel/semconv/v1.24.0" - -import "go.opentelemetry.io/otel/attribute" - -// This event represents an occurrence of a lifecycle transition on the iOS -// platform. -const ( - // IosStateKey is the attribute Key conforming to the "ios.state" semantic - // conventions. It represents the this attribute represents the state the - // application has transitioned into at the occurrence of the event. - // - // Type: Enum - // RequirementLevel: Required - // Stability: experimental - // Note: The iOS lifecycle states are defined in the [UIApplicationDelegate - // documentation](https://developer.apple.com/documentation/uikit/uiapplicationdelegate#1656902), - // and from which the `OS terminology` column values are derived. - IosStateKey = attribute.Key("ios.state") -) - -var ( - // The app has become `active`. Associated with UIKit notification `applicationDidBecomeActive` - IosStateActive = IosStateKey.String("active") - // The app is now `inactive`. Associated with UIKit notification `applicationWillResignActive` - IosStateInactive = IosStateKey.String("inactive") - // The app is now in the background. This value is associated with UIKit notification `applicationDidEnterBackground` - IosStateBackground = IosStateKey.String("background") - // The app is now in the foreground. This value is associated with UIKit notification `applicationWillEnterForeground` - IosStateForeground = IosStateKey.String("foreground") - // The app is about to terminate. Associated with UIKit notification `applicationWillTerminate` - IosStateTerminate = IosStateKey.String("terminate") -) - -// This event represents an occurrence of a lifecycle transition on the Android -// platform. -const ( - // AndroidStateKey is the attribute Key conforming to the "android.state" - // semantic conventions. It represents the this attribute represents the - // state the application has transitioned into at the occurrence of the - // event. - // - // Type: Enum - // RequirementLevel: Required - // Stability: experimental - // Note: The Android lifecycle states are defined in [Activity lifecycle - // callbacks](https://developer.android.com/guide/components/activities/activity-lifecycle#lc), - // and from which the `OS identifiers` are derived. - AndroidStateKey = attribute.Key("android.state") -) - -var ( - // Any time before Activity.onResume() or, if the app has no Activity, Context.startService() has been called in the app for the first time - AndroidStateCreated = AndroidStateKey.String("created") - // Any time after Activity.onPause() or, if the app has no Activity, Context.stopService() has been called when the app was in the foreground state - AndroidStateBackground = AndroidStateKey.String("background") - // Any time after Activity.onResume() or, if the app has no Activity, Context.startService() has been called when the app was in either the created or background states - AndroidStateForeground = AndroidStateKey.String("foreground") -) - -// This semantic convention defines the attributes used to represent a feature -// flag evaluation as an event. -const ( - // FeatureFlagKeyKey is the attribute Key conforming to the - // "feature_flag.key" semantic conventions. It represents the unique - // identifier of the feature flag. - // - // Type: string - // RequirementLevel: Required - // Stability: experimental - // Examples: 'logo-color' - FeatureFlagKeyKey = attribute.Key("feature_flag.key") - - // FeatureFlagProviderNameKey is the attribute Key conforming to the - // "feature_flag.provider_name" semantic conventions. It represents the - // name of the service provider that performs the flag evaluation. - // - // Type: string - // RequirementLevel: Recommended - // Stability: experimental - // Examples: 'Flag Manager' - FeatureFlagProviderNameKey = attribute.Key("feature_flag.provider_name") - - // FeatureFlagVariantKey is the attribute Key conforming to the - // "feature_flag.variant" semantic conventions. It represents the sHOULD be - // a semantic identifier for a value. If one is unavailable, a stringified - // version of the value can be used. - // - // Type: string - // RequirementLevel: Recommended - // Stability: experimental - // Examples: 'red', 'true', 'on' - // Note: A semantic identifier, commonly referred to as a variant, provides - // a means - // for referring to a value without including the value itself. This can - // provide additional context for understanding the meaning behind a value. - // For example, the variant `red` maybe be used for the value `#c05543`. - // - // A stringified version of the value can be used in situations where a - // semantic identifier is unavailable. String representation of the value - // should be determined by the implementer. - FeatureFlagVariantKey = attribute.Key("feature_flag.variant") -) - -// FeatureFlagKey returns an attribute KeyValue conforming to the -// "feature_flag.key" semantic conventions. It represents the unique identifier -// of the feature flag. -func FeatureFlagKey(val string) attribute.KeyValue { - return FeatureFlagKeyKey.String(val) -} - -// FeatureFlagProviderName returns an attribute KeyValue conforming to the -// "feature_flag.provider_name" semantic conventions. It represents the name of -// the service provider that performs the flag evaluation. -func FeatureFlagProviderName(val string) attribute.KeyValue { - return FeatureFlagProviderNameKey.String(val) -} - -// FeatureFlagVariant returns an attribute KeyValue conforming to the -// "feature_flag.variant" semantic conventions. It represents the sHOULD be a -// semantic identifier for a value. If one is unavailable, a stringified -// version of the value can be used. -func FeatureFlagVariant(val string) attribute.KeyValue { - return FeatureFlagVariantKey.String(val) -} - -// RPC received/sent message. -const ( - // MessageCompressedSizeKey is the attribute Key conforming to the - // "message.compressed_size" semantic conventions. It represents the - // compressed size of the message in bytes. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - MessageCompressedSizeKey = attribute.Key("message.compressed_size") - - // MessageIDKey is the attribute Key conforming to the "message.id" - // semantic conventions. It represents the mUST be calculated as two - // different counters starting from `1` one for sent messages and one for - // received message. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Note: This way we guarantee that the values will be consistent between - // different implementations. - MessageIDKey = attribute.Key("message.id") - - // MessageTypeKey is the attribute Key conforming to the "message.type" - // semantic conventions. It represents the whether this is a received or - // sent message. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - MessageTypeKey = attribute.Key("message.type") - - // MessageUncompressedSizeKey is the attribute Key conforming to the - // "message.uncompressed_size" semantic conventions. It represents the - // uncompressed size of the message in bytes. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - MessageUncompressedSizeKey = attribute.Key("message.uncompressed_size") -) - -var ( - // sent - MessageTypeSent = MessageTypeKey.String("SENT") - // received - MessageTypeReceived = MessageTypeKey.String("RECEIVED") -) - -// MessageCompressedSize returns an attribute KeyValue conforming to the -// "message.compressed_size" semantic conventions. It represents the compressed -// size of the message in bytes. -func MessageCompressedSize(val int) attribute.KeyValue { - return MessageCompressedSizeKey.Int(val) -} - -// MessageID returns an attribute KeyValue conforming to the "message.id" -// semantic conventions. It represents the mUST be calculated as two different -// counters starting from `1` one for sent messages and one for received -// message. -func MessageID(val int) attribute.KeyValue { - return MessageIDKey.Int(val) -} - -// MessageUncompressedSize returns an attribute KeyValue conforming to the -// "message.uncompressed_size" semantic conventions. It represents the -// uncompressed size of the message in bytes. -func MessageUncompressedSize(val int) attribute.KeyValue { - return MessageUncompressedSizeKey.Int(val) -} diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/exception.go b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/exception.go deleted file mode 100644 index 7235bb51d9..0000000000 --- a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/exception.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package semconv // import "go.opentelemetry.io/otel/semconv/v1.24.0" - -const ( - // ExceptionEventName is the name of the Span event representing an exception. - ExceptionEventName = "exception" -) diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/metric.go b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/metric.go deleted file mode 100644 index a6b953f625..0000000000 --- a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/metric.go +++ /dev/null @@ -1,1071 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -// Code generated from semantic convention specification. DO NOT EDIT. - -package semconv // import "go.opentelemetry.io/otel/semconv/v1.24.0" - -const ( - - // DBClientConnectionsUsage is the metric conforming to the - // "db.client.connections.usage" semantic conventions. It represents the number - // of connections that are currently in state described by the `state` - // attribute. - // Instrument: updowncounter - // Unit: {connection} - // Stability: Experimental - DBClientConnectionsUsageName = "db.client.connections.usage" - DBClientConnectionsUsageUnit = "{connection}" - DBClientConnectionsUsageDescription = "The number of connections that are currently in state described by the `state` attribute" - - // DBClientConnectionsIdleMax is the metric conforming to the - // "db.client.connections.idle.max" semantic conventions. It represents the - // maximum number of idle open connections allowed. - // Instrument: updowncounter - // Unit: {connection} - // Stability: Experimental - DBClientConnectionsIdleMaxName = "db.client.connections.idle.max" - DBClientConnectionsIdleMaxUnit = "{connection}" - DBClientConnectionsIdleMaxDescription = "The maximum number of idle open connections allowed" - - // DBClientConnectionsIdleMin is the metric conforming to the - // "db.client.connections.idle.min" semantic conventions. It represents the - // minimum number of idle open connections allowed. - // Instrument: updowncounter - // Unit: {connection} - // Stability: Experimental - DBClientConnectionsIdleMinName = "db.client.connections.idle.min" - DBClientConnectionsIdleMinUnit = "{connection}" - DBClientConnectionsIdleMinDescription = "The minimum number of idle open connections allowed" - - // DBClientConnectionsMax is the metric conforming to the - // "db.client.connections.max" semantic conventions. It represents the maximum - // number of open connections allowed. - // Instrument: updowncounter - // Unit: {connection} - // Stability: Experimental - DBClientConnectionsMaxName = "db.client.connections.max" - DBClientConnectionsMaxUnit = "{connection}" - DBClientConnectionsMaxDescription = "The maximum number of open connections allowed" - - // DBClientConnectionsPendingRequests is the metric conforming to the - // "db.client.connections.pending_requests" semantic conventions. It represents - // the number of pending requests for an open connection, cumulative for the - // entire pool. - // Instrument: updowncounter - // Unit: {request} - // Stability: Experimental - DBClientConnectionsPendingRequestsName = "db.client.connections.pending_requests" - DBClientConnectionsPendingRequestsUnit = "{request}" - DBClientConnectionsPendingRequestsDescription = "The number of pending requests for an open connection, cumulative for the entire pool" - - // DBClientConnectionsTimeouts is the metric conforming to the - // "db.client.connections.timeouts" semantic conventions. It represents the - // number of connection timeouts that have occurred trying to obtain a - // connection from the pool. - // Instrument: counter - // Unit: {timeout} - // Stability: Experimental - DBClientConnectionsTimeoutsName = "db.client.connections.timeouts" - DBClientConnectionsTimeoutsUnit = "{timeout}" - DBClientConnectionsTimeoutsDescription = "The number of connection timeouts that have occurred trying to obtain a connection from the pool" - - // DBClientConnectionsCreateTime is the metric conforming to the - // "db.client.connections.create_time" semantic conventions. It represents the - // time it took to create a new connection. - // Instrument: histogram - // Unit: ms - // Stability: Experimental - DBClientConnectionsCreateTimeName = "db.client.connections.create_time" - DBClientConnectionsCreateTimeUnit = "ms" - DBClientConnectionsCreateTimeDescription = "The time it took to create a new connection" - - // DBClientConnectionsWaitTime is the metric conforming to the - // "db.client.connections.wait_time" semantic conventions. It represents the - // time it took to obtain an open connection from the pool. - // Instrument: histogram - // Unit: ms - // Stability: Experimental - DBClientConnectionsWaitTimeName = "db.client.connections.wait_time" - DBClientConnectionsWaitTimeUnit = "ms" - DBClientConnectionsWaitTimeDescription = "The time it took to obtain an open connection from the pool" - - // DBClientConnectionsUseTime is the metric conforming to the - // "db.client.connections.use_time" semantic conventions. It represents the - // time between borrowing a connection and returning it to the pool. - // Instrument: histogram - // Unit: ms - // Stability: Experimental - DBClientConnectionsUseTimeName = "db.client.connections.use_time" - DBClientConnectionsUseTimeUnit = "ms" - DBClientConnectionsUseTimeDescription = "The time between borrowing a connection and returning it to the pool" - - // AspnetcoreRoutingMatchAttempts is the metric conforming to the - // "aspnetcore.routing.match_attempts" semantic conventions. It represents the - // number of requests that were attempted to be matched to an endpoint. - // Instrument: counter - // Unit: {match_attempt} - // Stability: Experimental - AspnetcoreRoutingMatchAttemptsName = "aspnetcore.routing.match_attempts" - AspnetcoreRoutingMatchAttemptsUnit = "{match_attempt}" - AspnetcoreRoutingMatchAttemptsDescription = "Number of requests that were attempted to be matched to an endpoint." - - // AspnetcoreDiagnosticsExceptions is the metric conforming to the - // "aspnetcore.diagnostics.exceptions" semantic conventions. It represents the - // number of exceptions caught by exception handling middleware. - // Instrument: counter - // Unit: {exception} - // Stability: Experimental - AspnetcoreDiagnosticsExceptionsName = "aspnetcore.diagnostics.exceptions" - AspnetcoreDiagnosticsExceptionsUnit = "{exception}" - AspnetcoreDiagnosticsExceptionsDescription = "Number of exceptions caught by exception handling middleware." - - // AspnetcoreRateLimitingActiveRequestLeases is the metric conforming to the - // "aspnetcore.rate_limiting.active_request_leases" semantic conventions. It - // represents the number of requests that are currently active on the server - // that hold a rate limiting lease. - // Instrument: updowncounter - // Unit: {request} - // Stability: Experimental - AspnetcoreRateLimitingActiveRequestLeasesName = "aspnetcore.rate_limiting.active_request_leases" - AspnetcoreRateLimitingActiveRequestLeasesUnit = "{request}" - AspnetcoreRateLimitingActiveRequestLeasesDescription = "Number of requests that are currently active on the server that hold a rate limiting lease." - - // AspnetcoreRateLimitingRequestLeaseDuration is the metric conforming to the - // "aspnetcore.rate_limiting.request_lease.duration" semantic conventions. It - // represents the duration of rate limiting lease held by requests on the - // server. - // Instrument: histogram - // Unit: s - // Stability: Experimental - AspnetcoreRateLimitingRequestLeaseDurationName = "aspnetcore.rate_limiting.request_lease.duration" - AspnetcoreRateLimitingRequestLeaseDurationUnit = "s" - AspnetcoreRateLimitingRequestLeaseDurationDescription = "The duration of rate limiting lease held by requests on the server." - - // AspnetcoreRateLimitingRequestTimeInQueue is the metric conforming to the - // "aspnetcore.rate_limiting.request.time_in_queue" semantic conventions. It - // represents the time the request spent in a queue waiting to acquire a rate - // limiting lease. - // Instrument: histogram - // Unit: s - // Stability: Experimental - AspnetcoreRateLimitingRequestTimeInQueueName = "aspnetcore.rate_limiting.request.time_in_queue" - AspnetcoreRateLimitingRequestTimeInQueueUnit = "s" - AspnetcoreRateLimitingRequestTimeInQueueDescription = "The time the request spent in a queue waiting to acquire a rate limiting lease." - - // AspnetcoreRateLimitingQueuedRequests is the metric conforming to the - // "aspnetcore.rate_limiting.queued_requests" semantic conventions. It - // represents the number of requests that are currently queued, waiting to - // acquire a rate limiting lease. - // Instrument: updowncounter - // Unit: {request} - // Stability: Experimental - AspnetcoreRateLimitingQueuedRequestsName = "aspnetcore.rate_limiting.queued_requests" - AspnetcoreRateLimitingQueuedRequestsUnit = "{request}" - AspnetcoreRateLimitingQueuedRequestsDescription = "Number of requests that are currently queued, waiting to acquire a rate limiting lease." - - // AspnetcoreRateLimitingRequests is the metric conforming to the - // "aspnetcore.rate_limiting.requests" semantic conventions. It represents the - // number of requests that tried to acquire a rate limiting lease. - // Instrument: counter - // Unit: {request} - // Stability: Experimental - AspnetcoreRateLimitingRequestsName = "aspnetcore.rate_limiting.requests" - AspnetcoreRateLimitingRequestsUnit = "{request}" - AspnetcoreRateLimitingRequestsDescription = "Number of requests that tried to acquire a rate limiting lease." - - // DNSLookupDuration is the metric conforming to the "dns.lookup.duration" - // semantic conventions. It represents the measures the time taken to perform a - // DNS lookup. - // Instrument: histogram - // Unit: s - // Stability: Experimental - DNSLookupDurationName = "dns.lookup.duration" - DNSLookupDurationUnit = "s" - DNSLookupDurationDescription = "Measures the time taken to perform a DNS lookup." - - // HTTPClientOpenConnections is the metric conforming to the - // "http.client.open_connections" semantic conventions. It represents the - // number of outbound HTTP connections that are currently active or idle on the - // client. - // Instrument: updowncounter - // Unit: {connection} - // Stability: Experimental - HTTPClientOpenConnectionsName = "http.client.open_connections" - HTTPClientOpenConnectionsUnit = "{connection}" - HTTPClientOpenConnectionsDescription = "Number of outbound HTTP connections that are currently active or idle on the client." - - // HTTPClientConnectionDuration is the metric conforming to the - // "http.client.connection.duration" semantic conventions. It represents the - // duration of the successfully established outbound HTTP connections. - // Instrument: histogram - // Unit: s - // Stability: Experimental - HTTPClientConnectionDurationName = "http.client.connection.duration" - HTTPClientConnectionDurationUnit = "s" - HTTPClientConnectionDurationDescription = "The duration of the successfully established outbound HTTP connections." - - // HTTPClientActiveRequests is the metric conforming to the - // "http.client.active_requests" semantic conventions. It represents the number - // of active HTTP requests. - // Instrument: updowncounter - // Unit: {request} - // Stability: Experimental - HTTPClientActiveRequestsName = "http.client.active_requests" - HTTPClientActiveRequestsUnit = "{request}" - HTTPClientActiveRequestsDescription = "Number of active HTTP requests." - - // HTTPClientRequestTimeInQueue is the metric conforming to the - // "http.client.request.time_in_queue" semantic conventions. It represents the - // amount of time requests spent on a queue waiting for an available - // connection. - // Instrument: histogram - // Unit: s - // Stability: Experimental - HTTPClientRequestTimeInQueueName = "http.client.request.time_in_queue" - HTTPClientRequestTimeInQueueUnit = "s" - HTTPClientRequestTimeInQueueDescription = "The amount of time requests spent on a queue waiting for an available connection." - - // KestrelActiveConnections is the metric conforming to the - // "kestrel.active_connections" semantic conventions. It represents the number - // of connections that are currently active on the server. - // Instrument: updowncounter - // Unit: {connection} - // Stability: Experimental - KestrelActiveConnectionsName = "kestrel.active_connections" - KestrelActiveConnectionsUnit = "{connection}" - KestrelActiveConnectionsDescription = "Number of connections that are currently active on the server." - - // KestrelConnectionDuration is the metric conforming to the - // "kestrel.connection.duration" semantic conventions. It represents the - // duration of connections on the server. - // Instrument: histogram - // Unit: s - // Stability: Experimental - KestrelConnectionDurationName = "kestrel.connection.duration" - KestrelConnectionDurationUnit = "s" - KestrelConnectionDurationDescription = "The duration of connections on the server." - - // KestrelRejectedConnections is the metric conforming to the - // "kestrel.rejected_connections" semantic conventions. It represents the - // number of connections rejected by the server. - // Instrument: counter - // Unit: {connection} - // Stability: Experimental - KestrelRejectedConnectionsName = "kestrel.rejected_connections" - KestrelRejectedConnectionsUnit = "{connection}" - KestrelRejectedConnectionsDescription = "Number of connections rejected by the server." - - // KestrelQueuedConnections is the metric conforming to the - // "kestrel.queued_connections" semantic conventions. It represents the number - // of connections that are currently queued and are waiting to start. - // Instrument: updowncounter - // Unit: {connection} - // Stability: Experimental - KestrelQueuedConnectionsName = "kestrel.queued_connections" - KestrelQueuedConnectionsUnit = "{connection}" - KestrelQueuedConnectionsDescription = "Number of connections that are currently queued and are waiting to start." - - // KestrelQueuedRequests is the metric conforming to the - // "kestrel.queued_requests" semantic conventions. It represents the number of - // HTTP requests on multiplexed connections (HTTP/2 and HTTP/3) that are - // currently queued and are waiting to start. - // Instrument: updowncounter - // Unit: {request} - // Stability: Experimental - KestrelQueuedRequestsName = "kestrel.queued_requests" - KestrelQueuedRequestsUnit = "{request}" - KestrelQueuedRequestsDescription = "Number of HTTP requests on multiplexed connections (HTTP/2 and HTTP/3) that are currently queued and are waiting to start." - - // KestrelUpgradedConnections is the metric conforming to the - // "kestrel.upgraded_connections" semantic conventions. It represents the - // number of connections that are currently upgraded (WebSockets). . - // Instrument: updowncounter - // Unit: {connection} - // Stability: Experimental - KestrelUpgradedConnectionsName = "kestrel.upgraded_connections" - KestrelUpgradedConnectionsUnit = "{connection}" - KestrelUpgradedConnectionsDescription = "Number of connections that are currently upgraded (WebSockets). ." - - // KestrelTLSHandshakeDuration is the metric conforming to the - // "kestrel.tls_handshake.duration" semantic conventions. It represents the - // duration of TLS handshakes on the server. - // Instrument: histogram - // Unit: s - // Stability: Experimental - KestrelTLSHandshakeDurationName = "kestrel.tls_handshake.duration" - KestrelTLSHandshakeDurationUnit = "s" - KestrelTLSHandshakeDurationDescription = "The duration of TLS handshakes on the server." - - // KestrelActiveTLSHandshakes is the metric conforming to the - // "kestrel.active_tls_handshakes" semantic conventions. It represents the - // number of TLS handshakes that are currently in progress on the server. - // Instrument: updowncounter - // Unit: {handshake} - // Stability: Experimental - KestrelActiveTLSHandshakesName = "kestrel.active_tls_handshakes" - KestrelActiveTLSHandshakesUnit = "{handshake}" - KestrelActiveTLSHandshakesDescription = "Number of TLS handshakes that are currently in progress on the server." - - // SignalrServerConnectionDuration is the metric conforming to the - // "signalr.server.connection.duration" semantic conventions. It represents the - // duration of connections on the server. - // Instrument: histogram - // Unit: s - // Stability: Experimental - SignalrServerConnectionDurationName = "signalr.server.connection.duration" - SignalrServerConnectionDurationUnit = "s" - SignalrServerConnectionDurationDescription = "The duration of connections on the server." - - // SignalrServerActiveConnections is the metric conforming to the - // "signalr.server.active_connections" semantic conventions. It represents the - // number of connections that are currently active on the server. - // Instrument: updowncounter - // Unit: {connection} - // Stability: Experimental - SignalrServerActiveConnectionsName = "signalr.server.active_connections" - SignalrServerActiveConnectionsUnit = "{connection}" - SignalrServerActiveConnectionsDescription = "Number of connections that are currently active on the server." - - // FaaSInvokeDuration is the metric conforming to the "faas.invoke_duration" - // semantic conventions. It represents the measures the duration of the - // function's logic execution. - // Instrument: histogram - // Unit: s - // Stability: Experimental - FaaSInvokeDurationName = "faas.invoke_duration" - FaaSInvokeDurationUnit = "s" - FaaSInvokeDurationDescription = "Measures the duration of the function's logic execution" - - // FaaSInitDuration is the metric conforming to the "faas.init_duration" - // semantic conventions. It represents the measures the duration of the - // function's initialization, such as a cold start. - // Instrument: histogram - // Unit: s - // Stability: Experimental - FaaSInitDurationName = "faas.init_duration" - FaaSInitDurationUnit = "s" - FaaSInitDurationDescription = "Measures the duration of the function's initialization, such as a cold start" - - // FaaSColdstarts is the metric conforming to the "faas.coldstarts" semantic - // conventions. It represents the number of invocation cold starts. - // Instrument: counter - // Unit: {coldstart} - // Stability: Experimental - FaaSColdstartsName = "faas.coldstarts" - FaaSColdstartsUnit = "{coldstart}" - FaaSColdstartsDescription = "Number of invocation cold starts" - - // FaaSErrors is the metric conforming to the "faas.errors" semantic - // conventions. It represents the number of invocation errors. - // Instrument: counter - // Unit: {error} - // Stability: Experimental - FaaSErrorsName = "faas.errors" - FaaSErrorsUnit = "{error}" - FaaSErrorsDescription = "Number of invocation errors" - - // FaaSInvocations is the metric conforming to the "faas.invocations" semantic - // conventions. It represents the number of successful invocations. - // Instrument: counter - // Unit: {invocation} - // Stability: Experimental - FaaSInvocationsName = "faas.invocations" - FaaSInvocationsUnit = "{invocation}" - FaaSInvocationsDescription = "Number of successful invocations" - - // FaaSTimeouts is the metric conforming to the "faas.timeouts" semantic - // conventions. It represents the number of invocation timeouts. - // Instrument: counter - // Unit: {timeout} - // Stability: Experimental - FaaSTimeoutsName = "faas.timeouts" - FaaSTimeoutsUnit = "{timeout}" - FaaSTimeoutsDescription = "Number of invocation timeouts" - - // FaaSMemUsage is the metric conforming to the "faas.mem_usage" semantic - // conventions. It represents the distribution of max memory usage per - // invocation. - // Instrument: histogram - // Unit: By - // Stability: Experimental - FaaSMemUsageName = "faas.mem_usage" - FaaSMemUsageUnit = "By" - FaaSMemUsageDescription = "Distribution of max memory usage per invocation" - - // FaaSCPUUsage is the metric conforming to the "faas.cpu_usage" semantic - // conventions. It represents the distribution of CPU usage per invocation. - // Instrument: histogram - // Unit: s - // Stability: Experimental - FaaSCPUUsageName = "faas.cpu_usage" - FaaSCPUUsageUnit = "s" - FaaSCPUUsageDescription = "Distribution of CPU usage per invocation" - - // FaaSNetIo is the metric conforming to the "faas.net_io" semantic - // conventions. It represents the distribution of net I/O usage per invocation. - // Instrument: histogram - // Unit: By - // Stability: Experimental - FaaSNetIoName = "faas.net_io" - FaaSNetIoUnit = "By" - FaaSNetIoDescription = "Distribution of net I/O usage per invocation" - - // HTTPServerRequestDuration is the metric conforming to the - // "http.server.request.duration" semantic conventions. It represents the - // duration of HTTP server requests. - // Instrument: histogram - // Unit: s - // Stability: Stable - HTTPServerRequestDurationName = "http.server.request.duration" - HTTPServerRequestDurationUnit = "s" - HTTPServerRequestDurationDescription = "Duration of HTTP server requests." - - // HTTPServerActiveRequests is the metric conforming to the - // "http.server.active_requests" semantic conventions. It represents the number - // of active HTTP server requests. - // Instrument: updowncounter - // Unit: {request} - // Stability: Experimental - HTTPServerActiveRequestsName = "http.server.active_requests" - HTTPServerActiveRequestsUnit = "{request}" - HTTPServerActiveRequestsDescription = "Number of active HTTP server requests." - - // HTTPServerRequestBodySize is the metric conforming to the - // "http.server.request.body.size" semantic conventions. It represents the size - // of HTTP server request bodies. - // Instrument: histogram - // Unit: By - // Stability: Experimental - HTTPServerRequestBodySizeName = "http.server.request.body.size" - HTTPServerRequestBodySizeUnit = "By" - HTTPServerRequestBodySizeDescription = "Size of HTTP server request bodies." - - // HTTPServerResponseBodySize is the metric conforming to the - // "http.server.response.body.size" semantic conventions. It represents the - // size of HTTP server response bodies. - // Instrument: histogram - // Unit: By - // Stability: Experimental - HTTPServerResponseBodySizeName = "http.server.response.body.size" - HTTPServerResponseBodySizeUnit = "By" - HTTPServerResponseBodySizeDescription = "Size of HTTP server response bodies." - - // HTTPClientRequestDuration is the metric conforming to the - // "http.client.request.duration" semantic conventions. It represents the - // duration of HTTP client requests. - // Instrument: histogram - // Unit: s - // Stability: Stable - HTTPClientRequestDurationName = "http.client.request.duration" - HTTPClientRequestDurationUnit = "s" - HTTPClientRequestDurationDescription = "Duration of HTTP client requests." - - // HTTPClientRequestBodySize is the metric conforming to the - // "http.client.request.body.size" semantic conventions. It represents the size - // of HTTP client request bodies. - // Instrument: histogram - // Unit: By - // Stability: Experimental - HTTPClientRequestBodySizeName = "http.client.request.body.size" - HTTPClientRequestBodySizeUnit = "By" - HTTPClientRequestBodySizeDescription = "Size of HTTP client request bodies." - - // HTTPClientResponseBodySize is the metric conforming to the - // "http.client.response.body.size" semantic conventions. It represents the - // size of HTTP client response bodies. - // Instrument: histogram - // Unit: By - // Stability: Experimental - HTTPClientResponseBodySizeName = "http.client.response.body.size" - HTTPClientResponseBodySizeUnit = "By" - HTTPClientResponseBodySizeDescription = "Size of HTTP client response bodies." - - // JvmMemoryInit is the metric conforming to the "jvm.memory.init" semantic - // conventions. It represents the measure of initial memory requested. - // Instrument: updowncounter - // Unit: By - // Stability: Experimental - JvmMemoryInitName = "jvm.memory.init" - JvmMemoryInitUnit = "By" - JvmMemoryInitDescription = "Measure of initial memory requested." - - // JvmSystemCPUUtilization is the metric conforming to the - // "jvm.system.cpu.utilization" semantic conventions. It represents the recent - // CPU utilization for the whole system as reported by the JVM. - // Instrument: gauge - // Unit: 1 - // Stability: Experimental - JvmSystemCPUUtilizationName = "jvm.system.cpu.utilization" - JvmSystemCPUUtilizationUnit = "1" - JvmSystemCPUUtilizationDescription = "Recent CPU utilization for the whole system as reported by the JVM." - - // JvmSystemCPULoad1m is the metric conforming to the "jvm.system.cpu.load_1m" - // semantic conventions. It represents the average CPU load of the whole system - // for the last minute as reported by the JVM. - // Instrument: gauge - // Unit: {run_queue_item} - // Stability: Experimental - JvmSystemCPULoad1mName = "jvm.system.cpu.load_1m" - JvmSystemCPULoad1mUnit = "{run_queue_item}" - JvmSystemCPULoad1mDescription = "Average CPU load of the whole system for the last minute as reported by the JVM." - - // JvmBufferMemoryUsage is the metric conforming to the - // "jvm.buffer.memory.usage" semantic conventions. It represents the measure of - // memory used by buffers. - // Instrument: updowncounter - // Unit: By - // Stability: Experimental - JvmBufferMemoryUsageName = "jvm.buffer.memory.usage" - JvmBufferMemoryUsageUnit = "By" - JvmBufferMemoryUsageDescription = "Measure of memory used by buffers." - - // JvmBufferMemoryLimit is the metric conforming to the - // "jvm.buffer.memory.limit" semantic conventions. It represents the measure of - // total memory capacity of buffers. - // Instrument: updowncounter - // Unit: By - // Stability: Experimental - JvmBufferMemoryLimitName = "jvm.buffer.memory.limit" - JvmBufferMemoryLimitUnit = "By" - JvmBufferMemoryLimitDescription = "Measure of total memory capacity of buffers." - - // JvmBufferCount is the metric conforming to the "jvm.buffer.count" semantic - // conventions. It represents the number of buffers in the pool. - // Instrument: updowncounter - // Unit: {buffer} - // Stability: Experimental - JvmBufferCountName = "jvm.buffer.count" - JvmBufferCountUnit = "{buffer}" - JvmBufferCountDescription = "Number of buffers in the pool." - - // JvmMemoryUsed is the metric conforming to the "jvm.memory.used" semantic - // conventions. It represents the measure of memory used. - // Instrument: updowncounter - // Unit: By - // Stability: Stable - JvmMemoryUsedName = "jvm.memory.used" - JvmMemoryUsedUnit = "By" - JvmMemoryUsedDescription = "Measure of memory used." - - // JvmMemoryCommitted is the metric conforming to the "jvm.memory.committed" - // semantic conventions. It represents the measure of memory committed. - // Instrument: updowncounter - // Unit: By - // Stability: Stable - JvmMemoryCommittedName = "jvm.memory.committed" - JvmMemoryCommittedUnit = "By" - JvmMemoryCommittedDescription = "Measure of memory committed." - - // JvmMemoryLimit is the metric conforming to the "jvm.memory.limit" semantic - // conventions. It represents the measure of max obtainable memory. - // Instrument: updowncounter - // Unit: By - // Stability: Stable - JvmMemoryLimitName = "jvm.memory.limit" - JvmMemoryLimitUnit = "By" - JvmMemoryLimitDescription = "Measure of max obtainable memory." - - // JvmMemoryUsedAfterLastGc is the metric conforming to the - // "jvm.memory.used_after_last_gc" semantic conventions. It represents the - // measure of memory used, as measured after the most recent garbage collection - // event on this pool. - // Instrument: updowncounter - // Unit: By - // Stability: Stable - JvmMemoryUsedAfterLastGcName = "jvm.memory.used_after_last_gc" - JvmMemoryUsedAfterLastGcUnit = "By" - JvmMemoryUsedAfterLastGcDescription = "Measure of memory used, as measured after the most recent garbage collection event on this pool." - - // JvmGcDuration is the metric conforming to the "jvm.gc.duration" semantic - // conventions. It represents the duration of JVM garbage collection actions. - // Instrument: histogram - // Unit: s - // Stability: Stable - JvmGcDurationName = "jvm.gc.duration" - JvmGcDurationUnit = "s" - JvmGcDurationDescription = "Duration of JVM garbage collection actions." - - // JvmThreadCount is the metric conforming to the "jvm.thread.count" semantic - // conventions. It represents the number of executing platform threads. - // Instrument: updowncounter - // Unit: {thread} - // Stability: Stable - JvmThreadCountName = "jvm.thread.count" - JvmThreadCountUnit = "{thread}" - JvmThreadCountDescription = "Number of executing platform threads." - - // JvmClassLoaded is the metric conforming to the "jvm.class.loaded" semantic - // conventions. It represents the number of classes loaded since JVM start. - // Instrument: counter - // Unit: {class} - // Stability: Stable - JvmClassLoadedName = "jvm.class.loaded" - JvmClassLoadedUnit = "{class}" - JvmClassLoadedDescription = "Number of classes loaded since JVM start." - - // JvmClassUnloaded is the metric conforming to the "jvm.class.unloaded" - // semantic conventions. It represents the number of classes unloaded since JVM - // start. - // Instrument: counter - // Unit: {class} - // Stability: Stable - JvmClassUnloadedName = "jvm.class.unloaded" - JvmClassUnloadedUnit = "{class}" - JvmClassUnloadedDescription = "Number of classes unloaded since JVM start." - - // JvmClassCount is the metric conforming to the "jvm.class.count" semantic - // conventions. It represents the number of classes currently loaded. - // Instrument: updowncounter - // Unit: {class} - // Stability: Stable - JvmClassCountName = "jvm.class.count" - JvmClassCountUnit = "{class}" - JvmClassCountDescription = "Number of classes currently loaded." - - // JvmCPUCount is the metric conforming to the "jvm.cpu.count" semantic - // conventions. It represents the number of processors available to the Java - // virtual machine. - // Instrument: updowncounter - // Unit: {cpu} - // Stability: Stable - JvmCPUCountName = "jvm.cpu.count" - JvmCPUCountUnit = "{cpu}" - JvmCPUCountDescription = "Number of processors available to the Java virtual machine." - - // JvmCPUTime is the metric conforming to the "jvm.cpu.time" semantic - // conventions. It represents the cPU time used by the process as reported by - // the JVM. - // Instrument: counter - // Unit: s - // Stability: Stable - JvmCPUTimeName = "jvm.cpu.time" - JvmCPUTimeUnit = "s" - JvmCPUTimeDescription = "CPU time used by the process as reported by the JVM." - - // JvmCPURecentUtilization is the metric conforming to the - // "jvm.cpu.recent_utilization" semantic conventions. It represents the recent - // CPU utilization for the process as reported by the JVM. - // Instrument: gauge - // Unit: 1 - // Stability: Stable - JvmCPURecentUtilizationName = "jvm.cpu.recent_utilization" - JvmCPURecentUtilizationUnit = "1" - JvmCPURecentUtilizationDescription = "Recent CPU utilization for the process as reported by the JVM." - - // MessagingPublishDuration is the metric conforming to the - // "messaging.publish.duration" semantic conventions. It represents the - // measures the duration of publish operation. - // Instrument: histogram - // Unit: s - // Stability: Experimental - MessagingPublishDurationName = "messaging.publish.duration" - MessagingPublishDurationUnit = "s" - MessagingPublishDurationDescription = "Measures the duration of publish operation." - - // MessagingReceiveDuration is the metric conforming to the - // "messaging.receive.duration" semantic conventions. It represents the - // measures the duration of receive operation. - // Instrument: histogram - // Unit: s - // Stability: Experimental - MessagingReceiveDurationName = "messaging.receive.duration" - MessagingReceiveDurationUnit = "s" - MessagingReceiveDurationDescription = "Measures the duration of receive operation." - - // MessagingDeliverDuration is the metric conforming to the - // "messaging.deliver.duration" semantic conventions. It represents the - // measures the duration of deliver operation. - // Instrument: histogram - // Unit: s - // Stability: Experimental - MessagingDeliverDurationName = "messaging.deliver.duration" - MessagingDeliverDurationUnit = "s" - MessagingDeliverDurationDescription = "Measures the duration of deliver operation." - - // MessagingPublishMessages is the metric conforming to the - // "messaging.publish.messages" semantic conventions. It represents the - // measures the number of published messages. - // Instrument: counter - // Unit: {message} - // Stability: Experimental - MessagingPublishMessagesName = "messaging.publish.messages" - MessagingPublishMessagesUnit = "{message}" - MessagingPublishMessagesDescription = "Measures the number of published messages." - - // MessagingReceiveMessages is the metric conforming to the - // "messaging.receive.messages" semantic conventions. It represents the - // measures the number of received messages. - // Instrument: counter - // Unit: {message} - // Stability: Experimental - MessagingReceiveMessagesName = "messaging.receive.messages" - MessagingReceiveMessagesUnit = "{message}" - MessagingReceiveMessagesDescription = "Measures the number of received messages." - - // MessagingDeliverMessages is the metric conforming to the - // "messaging.deliver.messages" semantic conventions. It represents the - // measures the number of delivered messages. - // Instrument: counter - // Unit: {message} - // Stability: Experimental - MessagingDeliverMessagesName = "messaging.deliver.messages" - MessagingDeliverMessagesUnit = "{message}" - MessagingDeliverMessagesDescription = "Measures the number of delivered messages." - - // RPCServerDuration is the metric conforming to the "rpc.server.duration" - // semantic conventions. It represents the measures the duration of inbound - // RPC. - // Instrument: histogram - // Unit: ms - // Stability: Experimental - RPCServerDurationName = "rpc.server.duration" - RPCServerDurationUnit = "ms" - RPCServerDurationDescription = "Measures the duration of inbound RPC." - - // RPCServerRequestSize is the metric conforming to the - // "rpc.server.request.size" semantic conventions. It represents the measures - // the size of RPC request messages (uncompressed). - // Instrument: histogram - // Unit: By - // Stability: Experimental - RPCServerRequestSizeName = "rpc.server.request.size" - RPCServerRequestSizeUnit = "By" - RPCServerRequestSizeDescription = "Measures the size of RPC request messages (uncompressed)." - - // RPCServerResponseSize is the metric conforming to the - // "rpc.server.response.size" semantic conventions. It represents the measures - // the size of RPC response messages (uncompressed). - // Instrument: histogram - // Unit: By - // Stability: Experimental - RPCServerResponseSizeName = "rpc.server.response.size" - RPCServerResponseSizeUnit = "By" - RPCServerResponseSizeDescription = "Measures the size of RPC response messages (uncompressed)." - - // RPCServerRequestsPerRPC is the metric conforming to the - // "rpc.server.requests_per_rpc" semantic conventions. It represents the - // measures the number of messages received per RPC. - // Instrument: histogram - // Unit: {count} - // Stability: Experimental - RPCServerRequestsPerRPCName = "rpc.server.requests_per_rpc" - RPCServerRequestsPerRPCUnit = "{count}" - RPCServerRequestsPerRPCDescription = "Measures the number of messages received per RPC." - - // RPCServerResponsesPerRPC is the metric conforming to the - // "rpc.server.responses_per_rpc" semantic conventions. It represents the - // measures the number of messages sent per RPC. - // Instrument: histogram - // Unit: {count} - // Stability: Experimental - RPCServerResponsesPerRPCName = "rpc.server.responses_per_rpc" - RPCServerResponsesPerRPCUnit = "{count}" - RPCServerResponsesPerRPCDescription = "Measures the number of messages sent per RPC." - - // RPCClientDuration is the metric conforming to the "rpc.client.duration" - // semantic conventions. It represents the measures the duration of outbound - // RPC. - // Instrument: histogram - // Unit: ms - // Stability: Experimental - RPCClientDurationName = "rpc.client.duration" - RPCClientDurationUnit = "ms" - RPCClientDurationDescription = "Measures the duration of outbound RPC." - - // RPCClientRequestSize is the metric conforming to the - // "rpc.client.request.size" semantic conventions. It represents the measures - // the size of RPC request messages (uncompressed). - // Instrument: histogram - // Unit: By - // Stability: Experimental - RPCClientRequestSizeName = "rpc.client.request.size" - RPCClientRequestSizeUnit = "By" - RPCClientRequestSizeDescription = "Measures the size of RPC request messages (uncompressed)." - - // RPCClientResponseSize is the metric conforming to the - // "rpc.client.response.size" semantic conventions. It represents the measures - // the size of RPC response messages (uncompressed). - // Instrument: histogram - // Unit: By - // Stability: Experimental - RPCClientResponseSizeName = "rpc.client.response.size" - RPCClientResponseSizeUnit = "By" - RPCClientResponseSizeDescription = "Measures the size of RPC response messages (uncompressed)." - - // RPCClientRequestsPerRPC is the metric conforming to the - // "rpc.client.requests_per_rpc" semantic conventions. It represents the - // measures the number of messages received per RPC. - // Instrument: histogram - // Unit: {count} - // Stability: Experimental - RPCClientRequestsPerRPCName = "rpc.client.requests_per_rpc" - RPCClientRequestsPerRPCUnit = "{count}" - RPCClientRequestsPerRPCDescription = "Measures the number of messages received per RPC." - - // RPCClientResponsesPerRPC is the metric conforming to the - // "rpc.client.responses_per_rpc" semantic conventions. It represents the - // measures the number of messages sent per RPC. - // Instrument: histogram - // Unit: {count} - // Stability: Experimental - RPCClientResponsesPerRPCName = "rpc.client.responses_per_rpc" - RPCClientResponsesPerRPCUnit = "{count}" - RPCClientResponsesPerRPCDescription = "Measures the number of messages sent per RPC." - - // SystemCPUTime is the metric conforming to the "system.cpu.time" semantic - // conventions. It represents the seconds each logical CPU spent on each mode. - // Instrument: counter - // Unit: s - // Stability: Experimental - SystemCPUTimeName = "system.cpu.time" - SystemCPUTimeUnit = "s" - SystemCPUTimeDescription = "Seconds each logical CPU spent on each mode" - - // SystemCPUUtilization is the metric conforming to the - // "system.cpu.utilization" semantic conventions. It represents the difference - // in system.cpu.time since the last measurement, divided by the elapsed time - // and number of logical CPUs. - // Instrument: gauge - // Unit: 1 - // Stability: Experimental - SystemCPUUtilizationName = "system.cpu.utilization" - SystemCPUUtilizationUnit = "1" - SystemCPUUtilizationDescription = "Difference in system.cpu.time since the last measurement, divided by the elapsed time and number of logical CPUs" - - // SystemCPUFrequency is the metric conforming to the "system.cpu.frequency" - // semantic conventions. It represents the reports the current frequency of the - // CPU in Hz. - // Instrument: gauge - // Unit: {Hz} - // Stability: Experimental - SystemCPUFrequencyName = "system.cpu.frequency" - SystemCPUFrequencyUnit = "{Hz}" - SystemCPUFrequencyDescription = "Reports the current frequency of the CPU in Hz" - - // SystemCPUPhysicalCount is the metric conforming to the - // "system.cpu.physical.count" semantic conventions. It represents the reports - // the number of actual physical processor cores on the hardware. - // Instrument: updowncounter - // Unit: {cpu} - // Stability: Experimental - SystemCPUPhysicalCountName = "system.cpu.physical.count" - SystemCPUPhysicalCountUnit = "{cpu}" - SystemCPUPhysicalCountDescription = "Reports the number of actual physical processor cores on the hardware" - - // SystemCPULogicalCount is the metric conforming to the - // "system.cpu.logical.count" semantic conventions. It represents the reports - // the number of logical (virtual) processor cores created by the operating - // system to manage multitasking. - // Instrument: updowncounter - // Unit: {cpu} - // Stability: Experimental - SystemCPULogicalCountName = "system.cpu.logical.count" - SystemCPULogicalCountUnit = "{cpu}" - SystemCPULogicalCountDescription = "Reports the number of logical (virtual) processor cores created by the operating system to manage multitasking" - - // SystemMemoryUsage is the metric conforming to the "system.memory.usage" - // semantic conventions. It represents the reports memory in use by state. - // Instrument: updowncounter - // Unit: By - // Stability: Experimental - SystemMemoryUsageName = "system.memory.usage" - SystemMemoryUsageUnit = "By" - SystemMemoryUsageDescription = "Reports memory in use by state." - - // SystemMemoryLimit is the metric conforming to the "system.memory.limit" - // semantic conventions. It represents the total memory available in the - // system. - // Instrument: updowncounter - // Unit: By - // Stability: Experimental - SystemMemoryLimitName = "system.memory.limit" - SystemMemoryLimitUnit = "By" - SystemMemoryLimitDescription = "Total memory available in the system." - - // SystemMemoryUtilization is the metric conforming to the - // "system.memory.utilization" semantic conventions. - // Instrument: gauge - // Unit: 1 - // Stability: Experimental - // NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository. - SystemMemoryUtilizationName = "system.memory.utilization" - SystemMemoryUtilizationUnit = "1" - - // SystemPagingUsage is the metric conforming to the "system.paging.usage" - // semantic conventions. It represents the unix swap or windows pagefile usage. - // Instrument: updowncounter - // Unit: By - // Stability: Experimental - SystemPagingUsageName = "system.paging.usage" - SystemPagingUsageUnit = "By" - SystemPagingUsageDescription = "Unix swap or windows pagefile usage" - - // SystemPagingUtilization is the metric conforming to the - // "system.paging.utilization" semantic conventions. - // Instrument: gauge - // Unit: 1 - // Stability: Experimental - // NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository. - SystemPagingUtilizationName = "system.paging.utilization" - SystemPagingUtilizationUnit = "1" - - // SystemPagingFaults is the metric conforming to the "system.paging.faults" - // semantic conventions. - // Instrument: counter - // Unit: {fault} - // Stability: Experimental - // NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository. - SystemPagingFaultsName = "system.paging.faults" - SystemPagingFaultsUnit = "{fault}" - - // SystemPagingOperations is the metric conforming to the - // "system.paging.operations" semantic conventions. - // Instrument: counter - // Unit: {operation} - // Stability: Experimental - // NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository. - SystemPagingOperationsName = "system.paging.operations" - SystemPagingOperationsUnit = "{operation}" - - // SystemDiskIo is the metric conforming to the "system.disk.io" semantic - // conventions. - // Instrument: counter - // Unit: By - // Stability: Experimental - // NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository. - SystemDiskIoName = "system.disk.io" - SystemDiskIoUnit = "By" - - // SystemDiskOperations is the metric conforming to the - // "system.disk.operations" semantic conventions. - // Instrument: counter - // Unit: {operation} - // Stability: Experimental - // NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository. - SystemDiskOperationsName = "system.disk.operations" - SystemDiskOperationsUnit = "{operation}" - - // SystemDiskIoTime is the metric conforming to the "system.disk.io_time" - // semantic conventions. It represents the time disk spent activated. - // Instrument: counter - // Unit: s - // Stability: Experimental - SystemDiskIoTimeName = "system.disk.io_time" - SystemDiskIoTimeUnit = "s" - SystemDiskIoTimeDescription = "Time disk spent activated" - - // SystemDiskOperationTime is the metric conforming to the - // "system.disk.operation_time" semantic conventions. It represents the sum of - // the time each operation took to complete. - // Instrument: counter - // Unit: s - // Stability: Experimental - SystemDiskOperationTimeName = "system.disk.operation_time" - SystemDiskOperationTimeUnit = "s" - SystemDiskOperationTimeDescription = "Sum of the time each operation took to complete" - - // SystemDiskMerged is the metric conforming to the "system.disk.merged" - // semantic conventions. - // Instrument: counter - // Unit: {operation} - // Stability: Experimental - // NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository. - SystemDiskMergedName = "system.disk.merged" - SystemDiskMergedUnit = "{operation}" - - // SystemFilesystemUsage is the metric conforming to the - // "system.filesystem.usage" semantic conventions. - // Instrument: updowncounter - // Unit: By - // Stability: Experimental - // NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository. - SystemFilesystemUsageName = "system.filesystem.usage" - SystemFilesystemUsageUnit = "By" - - // SystemFilesystemUtilization is the metric conforming to the - // "system.filesystem.utilization" semantic conventions. - // Instrument: gauge - // Unit: 1 - // Stability: Experimental - // NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository. - SystemFilesystemUtilizationName = "system.filesystem.utilization" - SystemFilesystemUtilizationUnit = "1" - - // SystemNetworkDropped is the metric conforming to the - // "system.network.dropped" semantic conventions. It represents the count of - // packets that are dropped or discarded even though there was no error. - // Instrument: counter - // Unit: {packet} - // Stability: Experimental - SystemNetworkDroppedName = "system.network.dropped" - SystemNetworkDroppedUnit = "{packet}" - SystemNetworkDroppedDescription = "Count of packets that are dropped or discarded even though there was no error" - - // SystemNetworkPackets is the metric conforming to the - // "system.network.packets" semantic conventions. - // Instrument: counter - // Unit: {packet} - // Stability: Experimental - // NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository. - SystemNetworkPacketsName = "system.network.packets" - SystemNetworkPacketsUnit = "{packet}" - - // SystemNetworkErrors is the metric conforming to the "system.network.errors" - // semantic conventions. It represents the count of network errors detected. - // Instrument: counter - // Unit: {error} - // Stability: Experimental - SystemNetworkErrorsName = "system.network.errors" - SystemNetworkErrorsUnit = "{error}" - SystemNetworkErrorsDescription = "Count of network errors detected" - - // SystemNetworkIo is the metric conforming to the "system.network.io" semantic - // conventions. - // Instrument: counter - // Unit: By - // Stability: Experimental - // NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository. - SystemNetworkIoName = "system.network.io" - SystemNetworkIoUnit = "By" - - // SystemNetworkConnections is the metric conforming to the - // "system.network.connections" semantic conventions. - // Instrument: updowncounter - // Unit: {connection} - // Stability: Experimental - // NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository. - SystemNetworkConnectionsName = "system.network.connections" - SystemNetworkConnectionsUnit = "{connection}" - - // SystemProcessesCount is the metric conforming to the - // "system.processes.count" semantic conventions. It represents the total - // number of processes in each state. - // Instrument: updowncounter - // Unit: {process} - // Stability: Experimental - SystemProcessesCountName = "system.processes.count" - SystemProcessesCountUnit = "{process}" - SystemProcessesCountDescription = "Total number of processes in each state" - - // SystemProcessesCreated is the metric conforming to the - // "system.processes.created" semantic conventions. It represents the total - // number of processes created over uptime of the host. - // Instrument: counter - // Unit: {process} - // Stability: Experimental - SystemProcessesCreatedName = "system.processes.created" - SystemProcessesCreatedUnit = "{process}" - SystemProcessesCreatedDescription = "Total number of processes created over uptime of the host" - - // SystemLinuxMemoryAvailable is the metric conforming to the - // "system.linux.memory.available" semantic conventions. It represents an - // estimate of how much memory is available for starting new applications, - // without causing swapping. - // Instrument: updowncounter - // Unit: By - // Stability: Experimental - SystemLinuxMemoryAvailableName = "system.linux.memory.available" - SystemLinuxMemoryAvailableUnit = "By" - SystemLinuxMemoryAvailableDescription = "An estimate of how much memory is available for starting new applications, without causing swapping" -) diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/resource.go b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/resource.go deleted file mode 100644 index d66bbe9c23..0000000000 --- a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/resource.go +++ /dev/null @@ -1,2545 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -// Code generated from semantic convention specification. DO NOT EDIT. - -package semconv // import "go.opentelemetry.io/otel/semconv/v1.24.0" - -import "go.opentelemetry.io/otel/attribute" - -// A cloud environment (e.g. GCP, Azure, AWS). -const ( - // CloudAccountIDKey is the attribute Key conforming to the - // "cloud.account.id" semantic conventions. It represents the cloud account - // ID the resource is assigned to. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '111111111111', 'opentelemetry' - CloudAccountIDKey = attribute.Key("cloud.account.id") - - // CloudAvailabilityZoneKey is the attribute Key conforming to the - // "cloud.availability_zone" semantic conventions. It represents the cloud - // regions often have multiple, isolated locations known as zones to - // increase availability. Availability zone represents the zone where the - // resource is running. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'us-east-1c' - // Note: Availability zones are called "zones" on Alibaba Cloud and Google - // Cloud. - CloudAvailabilityZoneKey = attribute.Key("cloud.availability_zone") - - // CloudPlatformKey is the attribute Key conforming to the "cloud.platform" - // semantic conventions. It represents the cloud platform in use. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - // Note: The prefix of the service SHOULD match the one specified in - // `cloud.provider`. - CloudPlatformKey = attribute.Key("cloud.platform") - - // CloudProviderKey is the attribute Key conforming to the "cloud.provider" - // semantic conventions. It represents the name of the cloud provider. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - CloudProviderKey = attribute.Key("cloud.provider") - - // CloudRegionKey is the attribute Key conforming to the "cloud.region" - // semantic conventions. It represents the geographical region the resource - // is running. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'us-central1', 'us-east-1' - // Note: Refer to your provider's docs to see the available regions, for - // example [Alibaba Cloud - // regions](https://www.alibabacloud.com/help/doc-detail/40654.htm), [AWS - // regions](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/), - // [Azure - // regions](https://azure.microsoft.com/global-infrastructure/geographies/), - // [Google Cloud regions](https://cloud.google.com/about/locations), or - // [Tencent Cloud - // regions](https://www.tencentcloud.com/document/product/213/6091). - CloudRegionKey = attribute.Key("cloud.region") - - // CloudResourceIDKey is the attribute Key conforming to the - // "cloud.resource_id" semantic conventions. It represents the cloud - // provider-specific native identifier of the monitored cloud resource - // (e.g. an - // [ARN](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) - // on AWS, a [fully qualified resource - // ID](https://learn.microsoft.com/rest/api/resources/resources/get-by-id) - // on Azure, a [full resource - // name](https://cloud.google.com/apis/design/resource_names#full_resource_name) - // on GCP) - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'arn:aws:lambda:REGION:ACCOUNT_ID:function:my-function', - // '//run.googleapis.com/projects/PROJECT_ID/locations/LOCATION_ID/services/SERVICE_ID', - // '/subscriptions//resourceGroups//providers/Microsoft.Web/sites//functions/' - // Note: On some cloud providers, it may not be possible to determine the - // full ID at startup, - // so it may be necessary to set `cloud.resource_id` as a span attribute - // instead. - // - // The exact value to use for `cloud.resource_id` depends on the cloud - // provider. - // The following well-known definitions MUST be used if you set this - // attribute and they apply: - // - // * **AWS Lambda:** The function - // [ARN](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html). - // Take care not to use the "invoked ARN" directly but replace any - // [alias - // suffix](https://docs.aws.amazon.com/lambda/latest/dg/configuration-aliases.html) - // with the resolved function version, as the same runtime instance may - // be invokable with - // multiple different aliases. - // * **GCP:** The [URI of the - // resource](https://cloud.google.com/iam/docs/full-resource-names) - // * **Azure:** The [Fully Qualified Resource - // ID](https://docs.microsoft.com/rest/api/resources/resources/get-by-id) - // of the invoked function, - // *not* the function app, having the form - // `/subscriptions//resourceGroups//providers/Microsoft.Web/sites//functions/`. - // This means that a span attribute MUST be used, as an Azure function - // app can host multiple functions that would usually share - // a TracerProvider. - CloudResourceIDKey = attribute.Key("cloud.resource_id") -) - -var ( - // Alibaba Cloud Elastic Compute Service - CloudPlatformAlibabaCloudECS = CloudPlatformKey.String("alibaba_cloud_ecs") - // Alibaba Cloud Function Compute - CloudPlatformAlibabaCloudFc = CloudPlatformKey.String("alibaba_cloud_fc") - // Red Hat OpenShift on Alibaba Cloud - CloudPlatformAlibabaCloudOpenshift = CloudPlatformKey.String("alibaba_cloud_openshift") - // AWS Elastic Compute Cloud - CloudPlatformAWSEC2 = CloudPlatformKey.String("aws_ec2") - // AWS Elastic Container Service - CloudPlatformAWSECS = CloudPlatformKey.String("aws_ecs") - // AWS Elastic Kubernetes Service - CloudPlatformAWSEKS = CloudPlatformKey.String("aws_eks") - // AWS Lambda - CloudPlatformAWSLambda = CloudPlatformKey.String("aws_lambda") - // AWS Elastic Beanstalk - CloudPlatformAWSElasticBeanstalk = CloudPlatformKey.String("aws_elastic_beanstalk") - // AWS App Runner - CloudPlatformAWSAppRunner = CloudPlatformKey.String("aws_app_runner") - // Red Hat OpenShift on AWS (ROSA) - CloudPlatformAWSOpenshift = CloudPlatformKey.String("aws_openshift") - // Azure Virtual Machines - CloudPlatformAzureVM = CloudPlatformKey.String("azure_vm") - // Azure Container Instances - CloudPlatformAzureContainerInstances = CloudPlatformKey.String("azure_container_instances") - // Azure Kubernetes Service - CloudPlatformAzureAKS = CloudPlatformKey.String("azure_aks") - // Azure Functions - CloudPlatformAzureFunctions = CloudPlatformKey.String("azure_functions") - // Azure App Service - CloudPlatformAzureAppService = CloudPlatformKey.String("azure_app_service") - // Azure Red Hat OpenShift - CloudPlatformAzureOpenshift = CloudPlatformKey.String("azure_openshift") - // Google Bare Metal Solution (BMS) - CloudPlatformGCPBareMetalSolution = CloudPlatformKey.String("gcp_bare_metal_solution") - // Google Cloud Compute Engine (GCE) - CloudPlatformGCPComputeEngine = CloudPlatformKey.String("gcp_compute_engine") - // Google Cloud Run - CloudPlatformGCPCloudRun = CloudPlatformKey.String("gcp_cloud_run") - // Google Cloud Kubernetes Engine (GKE) - CloudPlatformGCPKubernetesEngine = CloudPlatformKey.String("gcp_kubernetes_engine") - // Google Cloud Functions (GCF) - CloudPlatformGCPCloudFunctions = CloudPlatformKey.String("gcp_cloud_functions") - // Google Cloud App Engine (GAE) - CloudPlatformGCPAppEngine = CloudPlatformKey.String("gcp_app_engine") - // Red Hat OpenShift on Google Cloud - CloudPlatformGCPOpenshift = CloudPlatformKey.String("gcp_openshift") - // Red Hat OpenShift on IBM Cloud - CloudPlatformIbmCloudOpenshift = CloudPlatformKey.String("ibm_cloud_openshift") - // Tencent Cloud Cloud Virtual Machine (CVM) - CloudPlatformTencentCloudCvm = CloudPlatformKey.String("tencent_cloud_cvm") - // Tencent Cloud Elastic Kubernetes Service (EKS) - CloudPlatformTencentCloudEKS = CloudPlatformKey.String("tencent_cloud_eks") - // Tencent Cloud Serverless Cloud Function (SCF) - CloudPlatformTencentCloudScf = CloudPlatformKey.String("tencent_cloud_scf") -) - -var ( - // Alibaba Cloud - CloudProviderAlibabaCloud = CloudProviderKey.String("alibaba_cloud") - // Amazon Web Services - CloudProviderAWS = CloudProviderKey.String("aws") - // Microsoft Azure - CloudProviderAzure = CloudProviderKey.String("azure") - // Google Cloud Platform - CloudProviderGCP = CloudProviderKey.String("gcp") - // Heroku Platform as a Service - CloudProviderHeroku = CloudProviderKey.String("heroku") - // IBM Cloud - CloudProviderIbmCloud = CloudProviderKey.String("ibm_cloud") - // Tencent Cloud - CloudProviderTencentCloud = CloudProviderKey.String("tencent_cloud") -) - -// CloudAccountID returns an attribute KeyValue conforming to the -// "cloud.account.id" semantic conventions. It represents the cloud account ID -// the resource is assigned to. -func CloudAccountID(val string) attribute.KeyValue { - return CloudAccountIDKey.String(val) -} - -// CloudAvailabilityZone returns an attribute KeyValue conforming to the -// "cloud.availability_zone" semantic conventions. It represents the cloud -// regions often have multiple, isolated locations known as zones to increase -// availability. Availability zone represents the zone where the resource is -// running. -func CloudAvailabilityZone(val string) attribute.KeyValue { - return CloudAvailabilityZoneKey.String(val) -} - -// CloudRegion returns an attribute KeyValue conforming to the -// "cloud.region" semantic conventions. It represents the geographical region -// the resource is running. -func CloudRegion(val string) attribute.KeyValue { - return CloudRegionKey.String(val) -} - -// CloudResourceID returns an attribute KeyValue conforming to the -// "cloud.resource_id" semantic conventions. It represents the cloud -// provider-specific native identifier of the monitored cloud resource (e.g. an -// [ARN](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) -// on AWS, a [fully qualified resource -// ID](https://learn.microsoft.com/rest/api/resources/resources/get-by-id) on -// Azure, a [full resource -// name](https://cloud.google.com/apis/design/resource_names#full_resource_name) -// on GCP) -func CloudResourceID(val string) attribute.KeyValue { - return CloudResourceIDKey.String(val) -} - -// A container instance. -const ( - // ContainerCommandKey is the attribute Key conforming to the - // "container.command" semantic conventions. It represents the command used - // to run the container (i.e. the command name). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'otelcontribcol' - // Note: If using embedded credentials or sensitive data, it is recommended - // to remove them to prevent potential leakage. - ContainerCommandKey = attribute.Key("container.command") - - // ContainerCommandArgsKey is the attribute Key conforming to the - // "container.command_args" semantic conventions. It represents the all the - // command arguments (including the command/executable itself) run by the - // container. [2] - // - // Type: string[] - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'otelcontribcol, --config, config.yaml' - ContainerCommandArgsKey = attribute.Key("container.command_args") - - // ContainerCommandLineKey is the attribute Key conforming to the - // "container.command_line" semantic conventions. It represents the full - // command run by the container as a single string representing the full - // command. [2] - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'otelcontribcol --config config.yaml' - ContainerCommandLineKey = attribute.Key("container.command_line") - - // ContainerIDKey is the attribute Key conforming to the "container.id" - // semantic conventions. It represents the container ID. Usually a UUID, as - // for example used to [identify Docker - // containers](https://docs.docker.com/engine/reference/run/#container-identification). - // The UUID might be abbreviated. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'a3bf90e006b2' - ContainerIDKey = attribute.Key("container.id") - - // ContainerImageIDKey is the attribute Key conforming to the - // "container.image.id" semantic conventions. It represents the runtime - // specific image identifier. Usually a hash algorithm followed by a UUID. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: - // 'sha256:19c92d0a00d1b66d897bceaa7319bee0dd38a10a851c60bcec9474aa3f01e50f' - // Note: Docker defines a sha256 of the image id; `container.image.id` - // corresponds to the `Image` field from the Docker container inspect - // [API](https://docs.docker.com/engine/api/v1.43/#tag/Container/operation/ContainerInspect) - // endpoint. - // K8S defines a link to the container registry repository with digest - // `"imageID": "registry.azurecr.io - // /namespace/service/dockerfile@sha256:bdeabd40c3a8a492eaf9e8e44d0ebbb84bac7ee25ac0cf8a7159d25f62555625"`. - // The ID is assinged by the container runtime and can vary in different - // environments. Consider using `oci.manifest.digest` if it is important to - // identify the same image in different environments/runtimes. - ContainerImageIDKey = attribute.Key("container.image.id") - - // ContainerImageNameKey is the attribute Key conforming to the - // "container.image.name" semantic conventions. It represents the name of - // the image the container was built on. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'gcr.io/opentelemetry/operator' - ContainerImageNameKey = attribute.Key("container.image.name") - - // ContainerImageRepoDigestsKey is the attribute Key conforming to the - // "container.image.repo_digests" semantic conventions. It represents the - // repo digests of the container image as provided by the container - // runtime. - // - // Type: string[] - // RequirementLevel: Optional - // Stability: experimental - // Examples: - // 'example@sha256:afcc7f1ac1b49db317a7196c902e61c6c3c4607d63599ee1a82d702d249a0ccb', - // 'internal.registry.example.com:5000/example@sha256:b69959407d21e8a062e0416bf13405bb2b71ed7a84dde4158ebafacfa06f5578' - // Note: - // [Docker](https://docs.docker.com/engine/api/v1.43/#tag/Image/operation/ImageInspect) - // and - // [CRI](https://github.com/kubernetes/cri-api/blob/c75ef5b473bbe2d0a4fc92f82235efd665ea8e9f/pkg/apis/runtime/v1/api.proto#L1237-L1238) - // report those under the `RepoDigests` field. - ContainerImageRepoDigestsKey = attribute.Key("container.image.repo_digests") - - // ContainerImageTagsKey is the attribute Key conforming to the - // "container.image.tags" semantic conventions. It represents the container - // image tags. An example can be found in [Docker Image - // Inspect](https://docs.docker.com/engine/api/v1.43/#tag/Image/operation/ImageInspect). - // Should be only the `` section of the full name for example from - // `registry.example.com/my-org/my-image:`. - // - // Type: string[] - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'v1.27.1', '3.5.7-0' - ContainerImageTagsKey = attribute.Key("container.image.tags") - - // ContainerNameKey is the attribute Key conforming to the "container.name" - // semantic conventions. It represents the container name used by container - // runtime. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'opentelemetry-autoconf' - ContainerNameKey = attribute.Key("container.name") - - // ContainerRuntimeKey is the attribute Key conforming to the - // "container.runtime" semantic conventions. It represents the container - // runtime managing this container. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'docker', 'containerd', 'rkt' - ContainerRuntimeKey = attribute.Key("container.runtime") -) - -// ContainerCommand returns an attribute KeyValue conforming to the -// "container.command" semantic conventions. It represents the command used to -// run the container (i.e. the command name). -func ContainerCommand(val string) attribute.KeyValue { - return ContainerCommandKey.String(val) -} - -// ContainerCommandArgs returns an attribute KeyValue conforming to the -// "container.command_args" semantic conventions. It represents the all the -// command arguments (including the command/executable itself) run by the -// container. [2] -func ContainerCommandArgs(val ...string) attribute.KeyValue { - return ContainerCommandArgsKey.StringSlice(val) -} - -// ContainerCommandLine returns an attribute KeyValue conforming to the -// "container.command_line" semantic conventions. It represents the full -// command run by the container as a single string representing the full -// command. [2] -func ContainerCommandLine(val string) attribute.KeyValue { - return ContainerCommandLineKey.String(val) -} - -// ContainerID returns an attribute KeyValue conforming to the -// "container.id" semantic conventions. It represents the container ID. Usually -// a UUID, as for example used to [identify Docker -// containers](https://docs.docker.com/engine/reference/run/#container-identification). -// The UUID might be abbreviated. -func ContainerID(val string) attribute.KeyValue { - return ContainerIDKey.String(val) -} - -// ContainerImageID returns an attribute KeyValue conforming to the -// "container.image.id" semantic conventions. It represents the runtime -// specific image identifier. Usually a hash algorithm followed by a UUID. -func ContainerImageID(val string) attribute.KeyValue { - return ContainerImageIDKey.String(val) -} - -// ContainerImageName returns an attribute KeyValue conforming to the -// "container.image.name" semantic conventions. It represents the name of the -// image the container was built on. -func ContainerImageName(val string) attribute.KeyValue { - return ContainerImageNameKey.String(val) -} - -// ContainerImageRepoDigests returns an attribute KeyValue conforming to the -// "container.image.repo_digests" semantic conventions. It represents the repo -// digests of the container image as provided by the container runtime. -func ContainerImageRepoDigests(val ...string) attribute.KeyValue { - return ContainerImageRepoDigestsKey.StringSlice(val) -} - -// ContainerImageTags returns an attribute KeyValue conforming to the -// "container.image.tags" semantic conventions. It represents the container -// image tags. An example can be found in [Docker Image -// Inspect](https://docs.docker.com/engine/api/v1.43/#tag/Image/operation/ImageInspect). -// Should be only the `` section of the full name for example from -// `registry.example.com/my-org/my-image:`. -func ContainerImageTags(val ...string) attribute.KeyValue { - return ContainerImageTagsKey.StringSlice(val) -} - -// ContainerName returns an attribute KeyValue conforming to the -// "container.name" semantic conventions. It represents the container name used -// by container runtime. -func ContainerName(val string) attribute.KeyValue { - return ContainerNameKey.String(val) -} - -// ContainerRuntime returns an attribute KeyValue conforming to the -// "container.runtime" semantic conventions. It represents the container -// runtime managing this container. -func ContainerRuntime(val string) attribute.KeyValue { - return ContainerRuntimeKey.String(val) -} - -// Describes device attributes. -const ( - // DeviceIDKey is the attribute Key conforming to the "device.id" semantic - // conventions. It represents a unique identifier representing the device - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '2ab2916d-a51f-4ac8-80ee-45ac31a28092' - // Note: The device identifier MUST only be defined using the values - // outlined below. This value is not an advertising identifier and MUST NOT - // be used as such. On iOS (Swift or Objective-C), this value MUST be equal - // to the [vendor - // identifier](https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor). - // On Android (Java or Kotlin), this value MUST be equal to the Firebase - // Installation ID or a globally unique UUID which is persisted across - // sessions in your application. More information can be found - // [here](https://developer.android.com/training/articles/user-data-ids) on - // best practices and exact implementation details. Caution should be taken - // when storing personal data or anything which can identify a user. GDPR - // and data protection laws may apply, ensure you do your own due - // diligence. - DeviceIDKey = attribute.Key("device.id") - - // DeviceManufacturerKey is the attribute Key conforming to the - // "device.manufacturer" semantic conventions. It represents the name of - // the device manufacturer - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'Apple', 'Samsung' - // Note: The Android OS provides this field via - // [Build](https://developer.android.com/reference/android/os/Build#MANUFACTURER). - // iOS apps SHOULD hardcode the value `Apple`. - DeviceManufacturerKey = attribute.Key("device.manufacturer") - - // DeviceModelIdentifierKey is the attribute Key conforming to the - // "device.model.identifier" semantic conventions. It represents the model - // identifier for the device - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'iPhone3,4', 'SM-G920F' - // Note: It's recommended this value represents a machine-readable version - // of the model identifier rather than the market or consumer-friendly name - // of the device. - DeviceModelIdentifierKey = attribute.Key("device.model.identifier") - - // DeviceModelNameKey is the attribute Key conforming to the - // "device.model.name" semantic conventions. It represents the marketing - // name for the device model - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'iPhone 6s Plus', 'Samsung Galaxy S6' - // Note: It's recommended this value represents a human-readable version of - // the device model rather than a machine-readable alternative. - DeviceModelNameKey = attribute.Key("device.model.name") -) - -// DeviceID returns an attribute KeyValue conforming to the "device.id" -// semantic conventions. It represents a unique identifier representing the -// device -func DeviceID(val string) attribute.KeyValue { - return DeviceIDKey.String(val) -} - -// DeviceManufacturer returns an attribute KeyValue conforming to the -// "device.manufacturer" semantic conventions. It represents the name of the -// device manufacturer -func DeviceManufacturer(val string) attribute.KeyValue { - return DeviceManufacturerKey.String(val) -} - -// DeviceModelIdentifier returns an attribute KeyValue conforming to the -// "device.model.identifier" semantic conventions. It represents the model -// identifier for the device -func DeviceModelIdentifier(val string) attribute.KeyValue { - return DeviceModelIdentifierKey.String(val) -} - -// DeviceModelName returns an attribute KeyValue conforming to the -// "device.model.name" semantic conventions. It represents the marketing name -// for the device model -func DeviceModelName(val string) attribute.KeyValue { - return DeviceModelNameKey.String(val) -} - -// A host is defined as a computing instance. For example, physical servers, -// virtual machines, switches or disk array. -const ( - // HostArchKey is the attribute Key conforming to the "host.arch" semantic - // conventions. It represents the CPU architecture the host system is - // running on. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - HostArchKey = attribute.Key("host.arch") - - // HostCPUCacheL2SizeKey is the attribute Key conforming to the - // "host.cpu.cache.l2.size" semantic conventions. It represents the amount - // of level 2 memory cache available to the processor (in Bytes). - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 12288000 - HostCPUCacheL2SizeKey = attribute.Key("host.cpu.cache.l2.size") - - // HostCPUFamilyKey is the attribute Key conforming to the - // "host.cpu.family" semantic conventions. It represents the family or - // generation of the CPU. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '6', 'PA-RISC 1.1e' - HostCPUFamilyKey = attribute.Key("host.cpu.family") - - // HostCPUModelIDKey is the attribute Key conforming to the - // "host.cpu.model.id" semantic conventions. It represents the model - // identifier. It provides more granular information about the CPU, - // distinguishing it from other CPUs within the same family. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '6', '9000/778/B180L' - HostCPUModelIDKey = attribute.Key("host.cpu.model.id") - - // HostCPUModelNameKey is the attribute Key conforming to the - // "host.cpu.model.name" semantic conventions. It represents the model - // designation of the processor. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '11th Gen Intel(R) Core(TM) i7-1185G7 @ 3.00GHz' - HostCPUModelNameKey = attribute.Key("host.cpu.model.name") - - // HostCPUSteppingKey is the attribute Key conforming to the - // "host.cpu.stepping" semantic conventions. It represents the stepping or - // core revisions. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 1 - HostCPUSteppingKey = attribute.Key("host.cpu.stepping") - - // HostCPUVendorIDKey is the attribute Key conforming to the - // "host.cpu.vendor.id" semantic conventions. It represents the processor - // manufacturer identifier. A maximum 12-character string. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'GenuineIntel' - // Note: [CPUID](https://wiki.osdev.org/CPUID) command returns the vendor - // ID string in EBX, EDX and ECX registers. Writing these to memory in this - // order results in a 12-character string. - HostCPUVendorIDKey = attribute.Key("host.cpu.vendor.id") - - // HostIDKey is the attribute Key conforming to the "host.id" semantic - // conventions. It represents the unique host ID. For Cloud, this must be - // the instance_id assigned by the cloud provider. For non-containerized - // systems, this should be the `machine-id`. See the table below for the - // sources to use to determine the `machine-id` based on operating system. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'fdbf79e8af94cb7f9e8df36789187052' - HostIDKey = attribute.Key("host.id") - - // HostImageIDKey is the attribute Key conforming to the "host.image.id" - // semantic conventions. It represents the vM image ID or host OS image ID. - // For Cloud, this value is from the provider. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'ami-07b06b442921831e5' - HostImageIDKey = attribute.Key("host.image.id") - - // HostImageNameKey is the attribute Key conforming to the - // "host.image.name" semantic conventions. It represents the name of the VM - // image or OS install the host was instantiated from. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'infra-ami-eks-worker-node-7d4ec78312', 'CentOS-8-x86_64-1905' - HostImageNameKey = attribute.Key("host.image.name") - - // HostImageVersionKey is the attribute Key conforming to the - // "host.image.version" semantic conventions. It represents the version - // string of the VM image or host OS as defined in [Version - // Attributes](/docs/resource/README.md#version-attributes). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '0.1' - HostImageVersionKey = attribute.Key("host.image.version") - - // HostIPKey is the attribute Key conforming to the "host.ip" semantic - // conventions. It represents the available IP addresses of the host, - // excluding loopback interfaces. - // - // Type: string[] - // RequirementLevel: Optional - // Stability: experimental - // Examples: '192.168.1.140', 'fe80::abc2:4a28:737a:609e' - // Note: IPv4 Addresses MUST be specified in dotted-quad notation. IPv6 - // addresses MUST be specified in the [RFC - // 5952](https://www.rfc-editor.org/rfc/rfc5952.html) format. - HostIPKey = attribute.Key("host.ip") - - // HostMacKey is the attribute Key conforming to the "host.mac" semantic - // conventions. It represents the available MAC addresses of the host, - // excluding loopback interfaces. - // - // Type: string[] - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'AC-DE-48-23-45-67', 'AC-DE-48-23-45-67-01-9F' - // Note: MAC Addresses MUST be represented in [IEEE RA hexadecimal - // form](https://standards.ieee.org/wp-content/uploads/import/documents/tutorials/eui.pdf): - // as hyphen-separated octets in uppercase hexadecimal form from most to - // least significant. - HostMacKey = attribute.Key("host.mac") - - // HostNameKey is the attribute Key conforming to the "host.name" semantic - // conventions. It represents the name of the host. On Unix systems, it may - // contain what the hostname command returns, or the fully qualified - // hostname, or another name specified by the user. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'opentelemetry-test' - HostNameKey = attribute.Key("host.name") - - // HostTypeKey is the attribute Key conforming to the "host.type" semantic - // conventions. It represents the type of host. For Cloud, this must be the - // machine type. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'n1-standard-1' - HostTypeKey = attribute.Key("host.type") -) - -var ( - // AMD64 - HostArchAMD64 = HostArchKey.String("amd64") - // ARM32 - HostArchARM32 = HostArchKey.String("arm32") - // ARM64 - HostArchARM64 = HostArchKey.String("arm64") - // Itanium - HostArchIA64 = HostArchKey.String("ia64") - // 32-bit PowerPC - HostArchPPC32 = HostArchKey.String("ppc32") - // 64-bit PowerPC - HostArchPPC64 = HostArchKey.String("ppc64") - // IBM z/Architecture - HostArchS390x = HostArchKey.String("s390x") - // 32-bit x86 - HostArchX86 = HostArchKey.String("x86") -) - -// HostCPUCacheL2Size returns an attribute KeyValue conforming to the -// "host.cpu.cache.l2.size" semantic conventions. It represents the amount of -// level 2 memory cache available to the processor (in Bytes). -func HostCPUCacheL2Size(val int) attribute.KeyValue { - return HostCPUCacheL2SizeKey.Int(val) -} - -// HostCPUFamily returns an attribute KeyValue conforming to the -// "host.cpu.family" semantic conventions. It represents the family or -// generation of the CPU. -func HostCPUFamily(val string) attribute.KeyValue { - return HostCPUFamilyKey.String(val) -} - -// HostCPUModelID returns an attribute KeyValue conforming to the -// "host.cpu.model.id" semantic conventions. It represents the model -// identifier. It provides more granular information about the CPU, -// distinguishing it from other CPUs within the same family. -func HostCPUModelID(val string) attribute.KeyValue { - return HostCPUModelIDKey.String(val) -} - -// HostCPUModelName returns an attribute KeyValue conforming to the -// "host.cpu.model.name" semantic conventions. It represents the model -// designation of the processor. -func HostCPUModelName(val string) attribute.KeyValue { - return HostCPUModelNameKey.String(val) -} - -// HostCPUStepping returns an attribute KeyValue conforming to the -// "host.cpu.stepping" semantic conventions. It represents the stepping or core -// revisions. -func HostCPUStepping(val int) attribute.KeyValue { - return HostCPUSteppingKey.Int(val) -} - -// HostCPUVendorID returns an attribute KeyValue conforming to the -// "host.cpu.vendor.id" semantic conventions. It represents the processor -// manufacturer identifier. A maximum 12-character string. -func HostCPUVendorID(val string) attribute.KeyValue { - return HostCPUVendorIDKey.String(val) -} - -// HostID returns an attribute KeyValue conforming to the "host.id" semantic -// conventions. It represents the unique host ID. For Cloud, this must be the -// instance_id assigned by the cloud provider. For non-containerized systems, -// this should be the `machine-id`. See the table below for the sources to use -// to determine the `machine-id` based on operating system. -func HostID(val string) attribute.KeyValue { - return HostIDKey.String(val) -} - -// HostImageID returns an attribute KeyValue conforming to the -// "host.image.id" semantic conventions. It represents the vM image ID or host -// OS image ID. For Cloud, this value is from the provider. -func HostImageID(val string) attribute.KeyValue { - return HostImageIDKey.String(val) -} - -// HostImageName returns an attribute KeyValue conforming to the -// "host.image.name" semantic conventions. It represents the name of the VM -// image or OS install the host was instantiated from. -func HostImageName(val string) attribute.KeyValue { - return HostImageNameKey.String(val) -} - -// HostImageVersion returns an attribute KeyValue conforming to the -// "host.image.version" semantic conventions. It represents the version string -// of the VM image or host OS as defined in [Version -// Attributes](/docs/resource/README.md#version-attributes). -func HostImageVersion(val string) attribute.KeyValue { - return HostImageVersionKey.String(val) -} - -// HostIP returns an attribute KeyValue conforming to the "host.ip" semantic -// conventions. It represents the available IP addresses of the host, excluding -// loopback interfaces. -func HostIP(val ...string) attribute.KeyValue { - return HostIPKey.StringSlice(val) -} - -// HostMac returns an attribute KeyValue conforming to the "host.mac" -// semantic conventions. It represents the available MAC addresses of the host, -// excluding loopback interfaces. -func HostMac(val ...string) attribute.KeyValue { - return HostMacKey.StringSlice(val) -} - -// HostName returns an attribute KeyValue conforming to the "host.name" -// semantic conventions. It represents the name of the host. On Unix systems, -// it may contain what the hostname command returns, or the fully qualified -// hostname, or another name specified by the user. -func HostName(val string) attribute.KeyValue { - return HostNameKey.String(val) -} - -// HostType returns an attribute KeyValue conforming to the "host.type" -// semantic conventions. It represents the type of host. For Cloud, this must -// be the machine type. -func HostType(val string) attribute.KeyValue { - return HostTypeKey.String(val) -} - -// Kubernetes resource attributes. -const ( - // K8SClusterNameKey is the attribute Key conforming to the - // "k8s.cluster.name" semantic conventions. It represents the name of the - // cluster. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'opentelemetry-cluster' - K8SClusterNameKey = attribute.Key("k8s.cluster.name") - - // K8SClusterUIDKey is the attribute Key conforming to the - // "k8s.cluster.uid" semantic conventions. It represents a pseudo-ID for - // the cluster, set to the UID of the `kube-system` namespace. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '218fc5a9-a5f1-4b54-aa05-46717d0ab26d' - // Note: K8S doesn't have support for obtaining a cluster ID. If this is - // ever - // added, we will recommend collecting the `k8s.cluster.uid` through the - // official APIs. In the meantime, we are able to use the `uid` of the - // `kube-system` namespace as a proxy for cluster ID. Read on for the - // rationale. - // - // Every object created in a K8S cluster is assigned a distinct UID. The - // `kube-system` namespace is used by Kubernetes itself and will exist - // for the lifetime of the cluster. Using the `uid` of the `kube-system` - // namespace is a reasonable proxy for the K8S ClusterID as it will only - // change if the cluster is rebuilt. Furthermore, Kubernetes UIDs are - // UUIDs as standardized by - // [ISO/IEC 9834-8 and ITU-T - // X.667](https://www.itu.int/ITU-T/studygroups/com17/oid.html). - // Which states: - // - // > If generated according to one of the mechanisms defined in Rec. - // ITU-T X.667 | ISO/IEC 9834-8, a UUID is either guaranteed to be - // different from all other UUIDs generated before 3603 A.D., or is - // extremely likely to be different (depending on the mechanism chosen). - // - // Therefore, UIDs between clusters should be extremely unlikely to - // conflict. - K8SClusterUIDKey = attribute.Key("k8s.cluster.uid") - - // K8SContainerNameKey is the attribute Key conforming to the - // "k8s.container.name" semantic conventions. It represents the name of the - // Container from Pod specification, must be unique within a Pod. Container - // runtime usually uses different globally unique name (`container.name`). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'redis' - K8SContainerNameKey = attribute.Key("k8s.container.name") - - // K8SContainerRestartCountKey is the attribute Key conforming to the - // "k8s.container.restart_count" semantic conventions. It represents the - // number of times the container was restarted. This attribute can be used - // to identify a particular container (running or stopped) within a - // container spec. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 0, 2 - K8SContainerRestartCountKey = attribute.Key("k8s.container.restart_count") - - // K8SCronJobNameKey is the attribute Key conforming to the - // "k8s.cronjob.name" semantic conventions. It represents the name of the - // CronJob. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'opentelemetry' - K8SCronJobNameKey = attribute.Key("k8s.cronjob.name") - - // K8SCronJobUIDKey is the attribute Key conforming to the - // "k8s.cronjob.uid" semantic conventions. It represents the UID of the - // CronJob. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' - K8SCronJobUIDKey = attribute.Key("k8s.cronjob.uid") - - // K8SDaemonSetNameKey is the attribute Key conforming to the - // "k8s.daemonset.name" semantic conventions. It represents the name of the - // DaemonSet. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'opentelemetry' - K8SDaemonSetNameKey = attribute.Key("k8s.daemonset.name") - - // K8SDaemonSetUIDKey is the attribute Key conforming to the - // "k8s.daemonset.uid" semantic conventions. It represents the UID of the - // DaemonSet. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' - K8SDaemonSetUIDKey = attribute.Key("k8s.daemonset.uid") - - // K8SDeploymentNameKey is the attribute Key conforming to the - // "k8s.deployment.name" semantic conventions. It represents the name of - // the Deployment. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'opentelemetry' - K8SDeploymentNameKey = attribute.Key("k8s.deployment.name") - - // K8SDeploymentUIDKey is the attribute Key conforming to the - // "k8s.deployment.uid" semantic conventions. It represents the UID of the - // Deployment. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' - K8SDeploymentUIDKey = attribute.Key("k8s.deployment.uid") - - // K8SJobNameKey is the attribute Key conforming to the "k8s.job.name" - // semantic conventions. It represents the name of the Job. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'opentelemetry' - K8SJobNameKey = attribute.Key("k8s.job.name") - - // K8SJobUIDKey is the attribute Key conforming to the "k8s.job.uid" - // semantic conventions. It represents the UID of the Job. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' - K8SJobUIDKey = attribute.Key("k8s.job.uid") - - // K8SNamespaceNameKey is the attribute Key conforming to the - // "k8s.namespace.name" semantic conventions. It represents the name of the - // namespace that the pod is running in. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'default' - K8SNamespaceNameKey = attribute.Key("k8s.namespace.name") - - // K8SNodeNameKey is the attribute Key conforming to the "k8s.node.name" - // semantic conventions. It represents the name of the Node. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'node-1' - K8SNodeNameKey = attribute.Key("k8s.node.name") - - // K8SNodeUIDKey is the attribute Key conforming to the "k8s.node.uid" - // semantic conventions. It represents the UID of the Node. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '1eb3a0c6-0477-4080-a9cb-0cb7db65c6a2' - K8SNodeUIDKey = attribute.Key("k8s.node.uid") - - // K8SPodNameKey is the attribute Key conforming to the "k8s.pod.name" - // semantic conventions. It represents the name of the Pod. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'opentelemetry-pod-autoconf' - K8SPodNameKey = attribute.Key("k8s.pod.name") - - // K8SPodUIDKey is the attribute Key conforming to the "k8s.pod.uid" - // semantic conventions. It represents the UID of the Pod. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' - K8SPodUIDKey = attribute.Key("k8s.pod.uid") - - // K8SReplicaSetNameKey is the attribute Key conforming to the - // "k8s.replicaset.name" semantic conventions. It represents the name of - // the ReplicaSet. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'opentelemetry' - K8SReplicaSetNameKey = attribute.Key("k8s.replicaset.name") - - // K8SReplicaSetUIDKey is the attribute Key conforming to the - // "k8s.replicaset.uid" semantic conventions. It represents the UID of the - // ReplicaSet. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' - K8SReplicaSetUIDKey = attribute.Key("k8s.replicaset.uid") - - // K8SStatefulSetNameKey is the attribute Key conforming to the - // "k8s.statefulset.name" semantic conventions. It represents the name of - // the StatefulSet. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'opentelemetry' - K8SStatefulSetNameKey = attribute.Key("k8s.statefulset.name") - - // K8SStatefulSetUIDKey is the attribute Key conforming to the - // "k8s.statefulset.uid" semantic conventions. It represents the UID of the - // StatefulSet. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' - K8SStatefulSetUIDKey = attribute.Key("k8s.statefulset.uid") -) - -// K8SClusterName returns an attribute KeyValue conforming to the -// "k8s.cluster.name" semantic conventions. It represents the name of the -// cluster. -func K8SClusterName(val string) attribute.KeyValue { - return K8SClusterNameKey.String(val) -} - -// K8SClusterUID returns an attribute KeyValue conforming to the -// "k8s.cluster.uid" semantic conventions. It represents a pseudo-ID for the -// cluster, set to the UID of the `kube-system` namespace. -func K8SClusterUID(val string) attribute.KeyValue { - return K8SClusterUIDKey.String(val) -} - -// K8SContainerName returns an attribute KeyValue conforming to the -// "k8s.container.name" semantic conventions. It represents the name of the -// Container from Pod specification, must be unique within a Pod. Container -// runtime usually uses different globally unique name (`container.name`). -func K8SContainerName(val string) attribute.KeyValue { - return K8SContainerNameKey.String(val) -} - -// K8SContainerRestartCount returns an attribute KeyValue conforming to the -// "k8s.container.restart_count" semantic conventions. It represents the number -// of times the container was restarted. This attribute can be used to identify -// a particular container (running or stopped) within a container spec. -func K8SContainerRestartCount(val int) attribute.KeyValue { - return K8SContainerRestartCountKey.Int(val) -} - -// K8SCronJobName returns an attribute KeyValue conforming to the -// "k8s.cronjob.name" semantic conventions. It represents the name of the -// CronJob. -func K8SCronJobName(val string) attribute.KeyValue { - return K8SCronJobNameKey.String(val) -} - -// K8SCronJobUID returns an attribute KeyValue conforming to the -// "k8s.cronjob.uid" semantic conventions. It represents the UID of the -// CronJob. -func K8SCronJobUID(val string) attribute.KeyValue { - return K8SCronJobUIDKey.String(val) -} - -// K8SDaemonSetName returns an attribute KeyValue conforming to the -// "k8s.daemonset.name" semantic conventions. It represents the name of the -// DaemonSet. -func K8SDaemonSetName(val string) attribute.KeyValue { - return K8SDaemonSetNameKey.String(val) -} - -// K8SDaemonSetUID returns an attribute KeyValue conforming to the -// "k8s.daemonset.uid" semantic conventions. It represents the UID of the -// DaemonSet. -func K8SDaemonSetUID(val string) attribute.KeyValue { - return K8SDaemonSetUIDKey.String(val) -} - -// K8SDeploymentName returns an attribute KeyValue conforming to the -// "k8s.deployment.name" semantic conventions. It represents the name of the -// Deployment. -func K8SDeploymentName(val string) attribute.KeyValue { - return K8SDeploymentNameKey.String(val) -} - -// K8SDeploymentUID returns an attribute KeyValue conforming to the -// "k8s.deployment.uid" semantic conventions. It represents the UID of the -// Deployment. -func K8SDeploymentUID(val string) attribute.KeyValue { - return K8SDeploymentUIDKey.String(val) -} - -// K8SJobName returns an attribute KeyValue conforming to the "k8s.job.name" -// semantic conventions. It represents the name of the Job. -func K8SJobName(val string) attribute.KeyValue { - return K8SJobNameKey.String(val) -} - -// K8SJobUID returns an attribute KeyValue conforming to the "k8s.job.uid" -// semantic conventions. It represents the UID of the Job. -func K8SJobUID(val string) attribute.KeyValue { - return K8SJobUIDKey.String(val) -} - -// K8SNamespaceName returns an attribute KeyValue conforming to the -// "k8s.namespace.name" semantic conventions. It represents the name of the -// namespace that the pod is running in. -func K8SNamespaceName(val string) attribute.KeyValue { - return K8SNamespaceNameKey.String(val) -} - -// K8SNodeName returns an attribute KeyValue conforming to the -// "k8s.node.name" semantic conventions. It represents the name of the Node. -func K8SNodeName(val string) attribute.KeyValue { - return K8SNodeNameKey.String(val) -} - -// K8SNodeUID returns an attribute KeyValue conforming to the "k8s.node.uid" -// semantic conventions. It represents the UID of the Node. -func K8SNodeUID(val string) attribute.KeyValue { - return K8SNodeUIDKey.String(val) -} - -// K8SPodName returns an attribute KeyValue conforming to the "k8s.pod.name" -// semantic conventions. It represents the name of the Pod. -func K8SPodName(val string) attribute.KeyValue { - return K8SPodNameKey.String(val) -} - -// K8SPodUID returns an attribute KeyValue conforming to the "k8s.pod.uid" -// semantic conventions. It represents the UID of the Pod. -func K8SPodUID(val string) attribute.KeyValue { - return K8SPodUIDKey.String(val) -} - -// K8SReplicaSetName returns an attribute KeyValue conforming to the -// "k8s.replicaset.name" semantic conventions. It represents the name of the -// ReplicaSet. -func K8SReplicaSetName(val string) attribute.KeyValue { - return K8SReplicaSetNameKey.String(val) -} - -// K8SReplicaSetUID returns an attribute KeyValue conforming to the -// "k8s.replicaset.uid" semantic conventions. It represents the UID of the -// ReplicaSet. -func K8SReplicaSetUID(val string) attribute.KeyValue { - return K8SReplicaSetUIDKey.String(val) -} - -// K8SStatefulSetName returns an attribute KeyValue conforming to the -// "k8s.statefulset.name" semantic conventions. It represents the name of the -// StatefulSet. -func K8SStatefulSetName(val string) attribute.KeyValue { - return K8SStatefulSetNameKey.String(val) -} - -// K8SStatefulSetUID returns an attribute KeyValue conforming to the -// "k8s.statefulset.uid" semantic conventions. It represents the UID of the -// StatefulSet. -func K8SStatefulSetUID(val string) attribute.KeyValue { - return K8SStatefulSetUIDKey.String(val) -} - -// An OCI image manifest. -const ( - // OciManifestDigestKey is the attribute Key conforming to the - // "oci.manifest.digest" semantic conventions. It represents the digest of - // the OCI image manifest. For container images specifically is the digest - // by which the container image is known. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: - // 'sha256:e4ca62c0d62f3e886e684806dfe9d4e0cda60d54986898173c1083856cfda0f4' - // Note: Follows [OCI Image Manifest - // Specification](https://github.com/opencontainers/image-spec/blob/main/manifest.md), - // and specifically the [Digest - // property](https://github.com/opencontainers/image-spec/blob/main/descriptor.md#digests). - // An example can be found in [Example Image - // Manifest](https://docs.docker.com/registry/spec/manifest-v2-2/#example-image-manifest). - OciManifestDigestKey = attribute.Key("oci.manifest.digest") -) - -// OciManifestDigest returns an attribute KeyValue conforming to the -// "oci.manifest.digest" semantic conventions. It represents the digest of the -// OCI image manifest. For container images specifically is the digest by which -// the container image is known. -func OciManifestDigest(val string) attribute.KeyValue { - return OciManifestDigestKey.String(val) -} - -// The operating system (OS) on which the process represented by this resource -// is running. -const ( - // OSBuildIDKey is the attribute Key conforming to the "os.build_id" - // semantic conventions. It represents the unique identifier for a - // particular build or compilation of the operating system. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'TQ3C.230805.001.B2', '20E247', '22621' - OSBuildIDKey = attribute.Key("os.build_id") - - // OSDescriptionKey is the attribute Key conforming to the "os.description" - // semantic conventions. It represents the human readable (not intended to - // be parsed) OS version information, like e.g. reported by `ver` or - // `lsb_release -a` commands. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'Microsoft Windows [Version 10.0.18363.778]', 'Ubuntu 18.04.1 - // LTS' - OSDescriptionKey = attribute.Key("os.description") - - // OSNameKey is the attribute Key conforming to the "os.name" semantic - // conventions. It represents the human readable operating system name. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'iOS', 'Android', 'Ubuntu' - OSNameKey = attribute.Key("os.name") - - // OSTypeKey is the attribute Key conforming to the "os.type" semantic - // conventions. It represents the operating system type. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - OSTypeKey = attribute.Key("os.type") - - // OSVersionKey is the attribute Key conforming to the "os.version" - // semantic conventions. It represents the version string of the operating - // system as defined in [Version - // Attributes](/docs/resource/README.md#version-attributes). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '14.2.1', '18.04.1' - OSVersionKey = attribute.Key("os.version") -) - -var ( - // Microsoft Windows - OSTypeWindows = OSTypeKey.String("windows") - // Linux - OSTypeLinux = OSTypeKey.String("linux") - // Apple Darwin - OSTypeDarwin = OSTypeKey.String("darwin") - // FreeBSD - OSTypeFreeBSD = OSTypeKey.String("freebsd") - // NetBSD - OSTypeNetBSD = OSTypeKey.String("netbsd") - // OpenBSD - OSTypeOpenBSD = OSTypeKey.String("openbsd") - // DragonFly BSD - OSTypeDragonflyBSD = OSTypeKey.String("dragonflybsd") - // HP-UX (Hewlett Packard Unix) - OSTypeHPUX = OSTypeKey.String("hpux") - // AIX (Advanced Interactive eXecutive) - OSTypeAIX = OSTypeKey.String("aix") - // SunOS, Oracle Solaris - OSTypeSolaris = OSTypeKey.String("solaris") - // IBM z/OS - OSTypeZOS = OSTypeKey.String("z_os") -) - -// OSBuildID returns an attribute KeyValue conforming to the "os.build_id" -// semantic conventions. It represents the unique identifier for a particular -// build or compilation of the operating system. -func OSBuildID(val string) attribute.KeyValue { - return OSBuildIDKey.String(val) -} - -// OSDescription returns an attribute KeyValue conforming to the -// "os.description" semantic conventions. It represents the human readable (not -// intended to be parsed) OS version information, like e.g. reported by `ver` -// or `lsb_release -a` commands. -func OSDescription(val string) attribute.KeyValue { - return OSDescriptionKey.String(val) -} - -// OSName returns an attribute KeyValue conforming to the "os.name" semantic -// conventions. It represents the human readable operating system name. -func OSName(val string) attribute.KeyValue { - return OSNameKey.String(val) -} - -// OSVersion returns an attribute KeyValue conforming to the "os.version" -// semantic conventions. It represents the version string of the operating -// system as defined in [Version -// Attributes](/docs/resource/README.md#version-attributes). -func OSVersion(val string) attribute.KeyValue { - return OSVersionKey.String(val) -} - -// An operating system process. -const ( - // ProcessCommandKey is the attribute Key conforming to the - // "process.command" semantic conventions. It represents the command used - // to launch the process (i.e. the command name). On Linux based systems, - // can be set to the zeroth string in `proc/[pid]/cmdline`. On Windows, can - // be set to the first parameter extracted from `GetCommandLineW`. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'cmd/otelcol' - ProcessCommandKey = attribute.Key("process.command") - - // ProcessCommandArgsKey is the attribute Key conforming to the - // "process.command_args" semantic conventions. It represents the all the - // command arguments (including the command/executable itself) as received - // by the process. On Linux-based systems (and some other Unixoid systems - // supporting procfs), can be set according to the list of null-delimited - // strings extracted from `proc/[pid]/cmdline`. For libc-based executables, - // this would be the full argv vector passed to `main`. - // - // Type: string[] - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'cmd/otecol', '--config=config.yaml' - ProcessCommandArgsKey = attribute.Key("process.command_args") - - // ProcessCommandLineKey is the attribute Key conforming to the - // "process.command_line" semantic conventions. It represents the full - // command used to launch the process as a single string representing the - // full command. On Windows, can be set to the result of `GetCommandLineW`. - // Do not set this if you have to assemble it just for monitoring; use - // `process.command_args` instead. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'C:\\cmd\\otecol --config="my directory\\config.yaml"' - ProcessCommandLineKey = attribute.Key("process.command_line") - - // ProcessExecutableNameKey is the attribute Key conforming to the - // "process.executable.name" semantic conventions. It represents the name - // of the process executable. On Linux based systems, can be set to the - // `Name` in `proc/[pid]/status`. On Windows, can be set to the base name - // of `GetProcessImageFileNameW`. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'otelcol' - ProcessExecutableNameKey = attribute.Key("process.executable.name") - - // ProcessExecutablePathKey is the attribute Key conforming to the - // "process.executable.path" semantic conventions. It represents the full - // path to the process executable. On Linux based systems, can be set to - // the target of `proc/[pid]/exe`. On Windows, can be set to the result of - // `GetProcessImageFileNameW`. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '/usr/bin/cmd/otelcol' - ProcessExecutablePathKey = attribute.Key("process.executable.path") - - // ProcessOwnerKey is the attribute Key conforming to the "process.owner" - // semantic conventions. It represents the username of the user that owns - // the process. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'root' - ProcessOwnerKey = attribute.Key("process.owner") - - // ProcessParentPIDKey is the attribute Key conforming to the - // "process.parent_pid" semantic conventions. It represents the parent - // Process identifier (PPID). - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 111 - ProcessParentPIDKey = attribute.Key("process.parent_pid") - - // ProcessPIDKey is the attribute Key conforming to the "process.pid" - // semantic conventions. It represents the process identifier (PID). - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 1234 - ProcessPIDKey = attribute.Key("process.pid") - - // ProcessRuntimeDescriptionKey is the attribute Key conforming to the - // "process.runtime.description" semantic conventions. It represents an - // additional description about the runtime of the process, for example a - // specific vendor customization of the runtime environment. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'Eclipse OpenJ9 Eclipse OpenJ9 VM openj9-0.21.0' - ProcessRuntimeDescriptionKey = attribute.Key("process.runtime.description") - - // ProcessRuntimeNameKey is the attribute Key conforming to the - // "process.runtime.name" semantic conventions. It represents the name of - // the runtime of this process. For compiled native binaries, this SHOULD - // be the name of the compiler. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'OpenJDK Runtime Environment' - ProcessRuntimeNameKey = attribute.Key("process.runtime.name") - - // ProcessRuntimeVersionKey is the attribute Key conforming to the - // "process.runtime.version" semantic conventions. It represents the - // version of the runtime of this process, as returned by the runtime - // without modification. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '14.0.2' - ProcessRuntimeVersionKey = attribute.Key("process.runtime.version") -) - -// ProcessCommand returns an attribute KeyValue conforming to the -// "process.command" semantic conventions. It represents the command used to -// launch the process (i.e. the command name). On Linux based systems, can be -// set to the zeroth string in `proc/[pid]/cmdline`. On Windows, can be set to -// the first parameter extracted from `GetCommandLineW`. -func ProcessCommand(val string) attribute.KeyValue { - return ProcessCommandKey.String(val) -} - -// ProcessCommandArgs returns an attribute KeyValue conforming to the -// "process.command_args" semantic conventions. It represents the all the -// command arguments (including the command/executable itself) as received by -// the process. On Linux-based systems (and some other Unixoid systems -// supporting procfs), can be set according to the list of null-delimited -// strings extracted from `proc/[pid]/cmdline`. For libc-based executables, -// this would be the full argv vector passed to `main`. -func ProcessCommandArgs(val ...string) attribute.KeyValue { - return ProcessCommandArgsKey.StringSlice(val) -} - -// ProcessCommandLine returns an attribute KeyValue conforming to the -// "process.command_line" semantic conventions. It represents the full command -// used to launch the process as a single string representing the full command. -// On Windows, can be set to the result of `GetCommandLineW`. Do not set this -// if you have to assemble it just for monitoring; use `process.command_args` -// instead. -func ProcessCommandLine(val string) attribute.KeyValue { - return ProcessCommandLineKey.String(val) -} - -// ProcessExecutableName returns an attribute KeyValue conforming to the -// "process.executable.name" semantic conventions. It represents the name of -// the process executable. On Linux based systems, can be set to the `Name` in -// `proc/[pid]/status`. On Windows, can be set to the base name of -// `GetProcessImageFileNameW`. -func ProcessExecutableName(val string) attribute.KeyValue { - return ProcessExecutableNameKey.String(val) -} - -// ProcessExecutablePath returns an attribute KeyValue conforming to the -// "process.executable.path" semantic conventions. It represents the full path -// to the process executable. On Linux based systems, can be set to the target -// of `proc/[pid]/exe`. On Windows, can be set to the result of -// `GetProcessImageFileNameW`. -func ProcessExecutablePath(val string) attribute.KeyValue { - return ProcessExecutablePathKey.String(val) -} - -// ProcessOwner returns an attribute KeyValue conforming to the -// "process.owner" semantic conventions. It represents the username of the user -// that owns the process. -func ProcessOwner(val string) attribute.KeyValue { - return ProcessOwnerKey.String(val) -} - -// ProcessParentPID returns an attribute KeyValue conforming to the -// "process.parent_pid" semantic conventions. It represents the parent Process -// identifier (PPID). -func ProcessParentPID(val int) attribute.KeyValue { - return ProcessParentPIDKey.Int(val) -} - -// ProcessPID returns an attribute KeyValue conforming to the "process.pid" -// semantic conventions. It represents the process identifier (PID). -func ProcessPID(val int) attribute.KeyValue { - return ProcessPIDKey.Int(val) -} - -// ProcessRuntimeDescription returns an attribute KeyValue conforming to the -// "process.runtime.description" semantic conventions. It represents an -// additional description about the runtime of the process, for example a -// specific vendor customization of the runtime environment. -func ProcessRuntimeDescription(val string) attribute.KeyValue { - return ProcessRuntimeDescriptionKey.String(val) -} - -// ProcessRuntimeName returns an attribute KeyValue conforming to the -// "process.runtime.name" semantic conventions. It represents the name of the -// runtime of this process. For compiled native binaries, this SHOULD be the -// name of the compiler. -func ProcessRuntimeName(val string) attribute.KeyValue { - return ProcessRuntimeNameKey.String(val) -} - -// ProcessRuntimeVersion returns an attribute KeyValue conforming to the -// "process.runtime.version" semantic conventions. It represents the version of -// the runtime of this process, as returned by the runtime without -// modification. -func ProcessRuntimeVersion(val string) attribute.KeyValue { - return ProcessRuntimeVersionKey.String(val) -} - -// The Android platform on which the Android application is running. -const ( - // AndroidOSAPILevelKey is the attribute Key conforming to the - // "android.os.api_level" semantic conventions. It represents the uniquely - // identifies the framework API revision offered by a version - // (`os.version`) of the android operating system. More information can be - // found - // [here](https://developer.android.com/guide/topics/manifest/uses-sdk-element#APILevels). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '33', '32' - AndroidOSAPILevelKey = attribute.Key("android.os.api_level") -) - -// AndroidOSAPILevel returns an attribute KeyValue conforming to the -// "android.os.api_level" semantic conventions. It represents the uniquely -// identifies the framework API revision offered by a version (`os.version`) of -// the android operating system. More information can be found -// [here](https://developer.android.com/guide/topics/manifest/uses-sdk-element#APILevels). -func AndroidOSAPILevel(val string) attribute.KeyValue { - return AndroidOSAPILevelKey.String(val) -} - -// The web browser in which the application represented by the resource is -// running. The `browser.*` attributes MUST be used only for resources that -// represent applications running in a web browser (regardless of whether -// running on a mobile or desktop device). -const ( - // BrowserBrandsKey is the attribute Key conforming to the "browser.brands" - // semantic conventions. It represents the array of brand name and version - // separated by a space - // - // Type: string[] - // RequirementLevel: Optional - // Stability: experimental - // Examples: ' Not A;Brand 99', 'Chromium 99', 'Chrome 99' - // Note: This value is intended to be taken from the [UA client hints - // API](https://wicg.github.io/ua-client-hints/#interface) - // (`navigator.userAgentData.brands`). - BrowserBrandsKey = attribute.Key("browser.brands") - - // BrowserLanguageKey is the attribute Key conforming to the - // "browser.language" semantic conventions. It represents the preferred - // language of the user using the browser - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'en', 'en-US', 'fr', 'fr-FR' - // Note: This value is intended to be taken from the Navigator API - // `navigator.language`. - BrowserLanguageKey = attribute.Key("browser.language") - - // BrowserMobileKey is the attribute Key conforming to the "browser.mobile" - // semantic conventions. It represents a boolean that is true if the - // browser is running on a mobile device - // - // Type: boolean - // RequirementLevel: Optional - // Stability: experimental - // Note: This value is intended to be taken from the [UA client hints - // API](https://wicg.github.io/ua-client-hints/#interface) - // (`navigator.userAgentData.mobile`). If unavailable, this attribute - // SHOULD be left unset. - BrowserMobileKey = attribute.Key("browser.mobile") - - // BrowserPlatformKey is the attribute Key conforming to the - // "browser.platform" semantic conventions. It represents the platform on - // which the browser is running - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'Windows', 'macOS', 'Android' - // Note: This value is intended to be taken from the [UA client hints - // API](https://wicg.github.io/ua-client-hints/#interface) - // (`navigator.userAgentData.platform`). If unavailable, the legacy - // `navigator.platform` API SHOULD NOT be used instead and this attribute - // SHOULD be left unset in order for the values to be consistent. - // The list of possible values is defined in the [W3C User-Agent Client - // Hints - // specification](https://wicg.github.io/ua-client-hints/#sec-ch-ua-platform). - // Note that some (but not all) of these values can overlap with values in - // the [`os.type` and `os.name` attributes](./os.md). However, for - // consistency, the values in the `browser.platform` attribute should - // capture the exact value that the user agent provides. - BrowserPlatformKey = attribute.Key("browser.platform") -) - -// BrowserBrands returns an attribute KeyValue conforming to the -// "browser.brands" semantic conventions. It represents the array of brand name -// and version separated by a space -func BrowserBrands(val ...string) attribute.KeyValue { - return BrowserBrandsKey.StringSlice(val) -} - -// BrowserLanguage returns an attribute KeyValue conforming to the -// "browser.language" semantic conventions. It represents the preferred -// language of the user using the browser -func BrowserLanguage(val string) attribute.KeyValue { - return BrowserLanguageKey.String(val) -} - -// BrowserMobile returns an attribute KeyValue conforming to the -// "browser.mobile" semantic conventions. It represents a boolean that is true -// if the browser is running on a mobile device -func BrowserMobile(val bool) attribute.KeyValue { - return BrowserMobileKey.Bool(val) -} - -// BrowserPlatform returns an attribute KeyValue conforming to the -// "browser.platform" semantic conventions. It represents the platform on which -// the browser is running -func BrowserPlatform(val string) attribute.KeyValue { - return BrowserPlatformKey.String(val) -} - -// Resources used by AWS Elastic Container Service (ECS). -const ( - // AWSECSClusterARNKey is the attribute Key conforming to the - // "aws.ecs.cluster.arn" semantic conventions. It represents the ARN of an - // [ECS - // cluster](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/clusters.html). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'arn:aws:ecs:us-west-2:123456789123:cluster/my-cluster' - AWSECSClusterARNKey = attribute.Key("aws.ecs.cluster.arn") - - // AWSECSContainerARNKey is the attribute Key conforming to the - // "aws.ecs.container.arn" semantic conventions. It represents the Amazon - // Resource Name (ARN) of an [ECS container - // instance](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_instances.html). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: - // 'arn:aws:ecs:us-west-1:123456789123:container/32624152-9086-4f0e-acae-1a75b14fe4d9' - AWSECSContainerARNKey = attribute.Key("aws.ecs.container.arn") - - // AWSECSLaunchtypeKey is the attribute Key conforming to the - // "aws.ecs.launchtype" semantic conventions. It represents the [launch - // type](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_types.html) - // for an ECS task. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - AWSECSLaunchtypeKey = attribute.Key("aws.ecs.launchtype") - - // AWSECSTaskARNKey is the attribute Key conforming to the - // "aws.ecs.task.arn" semantic conventions. It represents the ARN of an - // [ECS task - // definition](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definitions.html). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: - // 'arn:aws:ecs:us-west-1:123456789123:task/10838bed-421f-43ef-870a-f43feacbbb5b' - AWSECSTaskARNKey = attribute.Key("aws.ecs.task.arn") - - // AWSECSTaskFamilyKey is the attribute Key conforming to the - // "aws.ecs.task.family" semantic conventions. It represents the task - // definition family this task definition is a member of. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'opentelemetry-family' - AWSECSTaskFamilyKey = attribute.Key("aws.ecs.task.family") - - // AWSECSTaskRevisionKey is the attribute Key conforming to the - // "aws.ecs.task.revision" semantic conventions. It represents the revision - // for this task definition. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '8', '26' - AWSECSTaskRevisionKey = attribute.Key("aws.ecs.task.revision") -) - -var ( - // ec2 - AWSECSLaunchtypeEC2 = AWSECSLaunchtypeKey.String("ec2") - // fargate - AWSECSLaunchtypeFargate = AWSECSLaunchtypeKey.String("fargate") -) - -// AWSECSClusterARN returns an attribute KeyValue conforming to the -// "aws.ecs.cluster.arn" semantic conventions. It represents the ARN of an [ECS -// cluster](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/clusters.html). -func AWSECSClusterARN(val string) attribute.KeyValue { - return AWSECSClusterARNKey.String(val) -} - -// AWSECSContainerARN returns an attribute KeyValue conforming to the -// "aws.ecs.container.arn" semantic conventions. It represents the Amazon -// Resource Name (ARN) of an [ECS container -// instance](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_instances.html). -func AWSECSContainerARN(val string) attribute.KeyValue { - return AWSECSContainerARNKey.String(val) -} - -// AWSECSTaskARN returns an attribute KeyValue conforming to the -// "aws.ecs.task.arn" semantic conventions. It represents the ARN of an [ECS -// task -// definition](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definitions.html). -func AWSECSTaskARN(val string) attribute.KeyValue { - return AWSECSTaskARNKey.String(val) -} - -// AWSECSTaskFamily returns an attribute KeyValue conforming to the -// "aws.ecs.task.family" semantic conventions. It represents the task -// definition family this task definition is a member of. -func AWSECSTaskFamily(val string) attribute.KeyValue { - return AWSECSTaskFamilyKey.String(val) -} - -// AWSECSTaskRevision returns an attribute KeyValue conforming to the -// "aws.ecs.task.revision" semantic conventions. It represents the revision for -// this task definition. -func AWSECSTaskRevision(val string) attribute.KeyValue { - return AWSECSTaskRevisionKey.String(val) -} - -// Resources used by AWS Elastic Kubernetes Service (EKS). -const ( - // AWSEKSClusterARNKey is the attribute Key conforming to the - // "aws.eks.cluster.arn" semantic conventions. It represents the ARN of an - // EKS cluster. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'arn:aws:ecs:us-west-2:123456789123:cluster/my-cluster' - AWSEKSClusterARNKey = attribute.Key("aws.eks.cluster.arn") -) - -// AWSEKSClusterARN returns an attribute KeyValue conforming to the -// "aws.eks.cluster.arn" semantic conventions. It represents the ARN of an EKS -// cluster. -func AWSEKSClusterARN(val string) attribute.KeyValue { - return AWSEKSClusterARNKey.String(val) -} - -// Resources specific to Amazon Web Services. -const ( - // AWSLogGroupARNsKey is the attribute Key conforming to the - // "aws.log.group.arns" semantic conventions. It represents the Amazon - // Resource Name(s) (ARN) of the AWS log group(s). - // - // Type: string[] - // RequirementLevel: Optional - // Stability: experimental - // Examples: - // 'arn:aws:logs:us-west-1:123456789012:log-group:/aws/my/group:*' - // Note: See the [log group ARN format - // documentation](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/iam-access-control-overview-cwl.html#CWL_ARN_Format). - AWSLogGroupARNsKey = attribute.Key("aws.log.group.arns") - - // AWSLogGroupNamesKey is the attribute Key conforming to the - // "aws.log.group.names" semantic conventions. It represents the name(s) of - // the AWS log group(s) an application is writing to. - // - // Type: string[] - // RequirementLevel: Optional - // Stability: experimental - // Examples: '/aws/lambda/my-function', 'opentelemetry-service' - // Note: Multiple log groups must be supported for cases like - // multi-container applications, where a single application has sidecar - // containers, and each write to their own log group. - AWSLogGroupNamesKey = attribute.Key("aws.log.group.names") - - // AWSLogStreamARNsKey is the attribute Key conforming to the - // "aws.log.stream.arns" semantic conventions. It represents the ARN(s) of - // the AWS log stream(s). - // - // Type: string[] - // RequirementLevel: Optional - // Stability: experimental - // Examples: - // 'arn:aws:logs:us-west-1:123456789012:log-group:/aws/my/group:log-stream:logs/main/10838bed-421f-43ef-870a-f43feacbbb5b' - // Note: See the [log stream ARN format - // documentation](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/iam-access-control-overview-cwl.html#CWL_ARN_Format). - // One log group can contain several log streams, so these ARNs necessarily - // identify both a log group and a log stream. - AWSLogStreamARNsKey = attribute.Key("aws.log.stream.arns") - - // AWSLogStreamNamesKey is the attribute Key conforming to the - // "aws.log.stream.names" semantic conventions. It represents the name(s) - // of the AWS log stream(s) an application is writing to. - // - // Type: string[] - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'logs/main/10838bed-421f-43ef-870a-f43feacbbb5b' - AWSLogStreamNamesKey = attribute.Key("aws.log.stream.names") -) - -// AWSLogGroupARNs returns an attribute KeyValue conforming to the -// "aws.log.group.arns" semantic conventions. It represents the Amazon Resource -// Name(s) (ARN) of the AWS log group(s). -func AWSLogGroupARNs(val ...string) attribute.KeyValue { - return AWSLogGroupARNsKey.StringSlice(val) -} - -// AWSLogGroupNames returns an attribute KeyValue conforming to the -// "aws.log.group.names" semantic conventions. It represents the name(s) of the -// AWS log group(s) an application is writing to. -func AWSLogGroupNames(val ...string) attribute.KeyValue { - return AWSLogGroupNamesKey.StringSlice(val) -} - -// AWSLogStreamARNs returns an attribute KeyValue conforming to the -// "aws.log.stream.arns" semantic conventions. It represents the ARN(s) of the -// AWS log stream(s). -func AWSLogStreamARNs(val ...string) attribute.KeyValue { - return AWSLogStreamARNsKey.StringSlice(val) -} - -// AWSLogStreamNames returns an attribute KeyValue conforming to the -// "aws.log.stream.names" semantic conventions. It represents the name(s) of -// the AWS log stream(s) an application is writing to. -func AWSLogStreamNames(val ...string) attribute.KeyValue { - return AWSLogStreamNamesKey.StringSlice(val) -} - -// Resource used by Google Cloud Run. -const ( - // GCPCloudRunJobExecutionKey is the attribute Key conforming to the - // "gcp.cloud_run.job.execution" semantic conventions. It represents the - // name of the Cloud Run - // [execution](https://cloud.google.com/run/docs/managing/job-executions) - // being run for the Job, as set by the - // [`CLOUD_RUN_EXECUTION`](https://cloud.google.com/run/docs/container-contract#jobs-env-vars) - // environment variable. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'job-name-xxxx', 'sample-job-mdw84' - GCPCloudRunJobExecutionKey = attribute.Key("gcp.cloud_run.job.execution") - - // GCPCloudRunJobTaskIndexKey is the attribute Key conforming to the - // "gcp.cloud_run.job.task_index" semantic conventions. It represents the - // index for a task within an execution as provided by the - // [`CLOUD_RUN_TASK_INDEX`](https://cloud.google.com/run/docs/container-contract#jobs-env-vars) - // environment variable. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 0, 1 - GCPCloudRunJobTaskIndexKey = attribute.Key("gcp.cloud_run.job.task_index") -) - -// GCPCloudRunJobExecution returns an attribute KeyValue conforming to the -// "gcp.cloud_run.job.execution" semantic conventions. It represents the name -// of the Cloud Run -// [execution](https://cloud.google.com/run/docs/managing/job-executions) being -// run for the Job, as set by the -// [`CLOUD_RUN_EXECUTION`](https://cloud.google.com/run/docs/container-contract#jobs-env-vars) -// environment variable. -func GCPCloudRunJobExecution(val string) attribute.KeyValue { - return GCPCloudRunJobExecutionKey.String(val) -} - -// GCPCloudRunJobTaskIndex returns an attribute KeyValue conforming to the -// "gcp.cloud_run.job.task_index" semantic conventions. It represents the index -// for a task within an execution as provided by the -// [`CLOUD_RUN_TASK_INDEX`](https://cloud.google.com/run/docs/container-contract#jobs-env-vars) -// environment variable. -func GCPCloudRunJobTaskIndex(val int) attribute.KeyValue { - return GCPCloudRunJobTaskIndexKey.Int(val) -} - -// Resources used by Google Compute Engine (GCE). -const ( - // GCPGceInstanceHostnameKey is the attribute Key conforming to the - // "gcp.gce.instance.hostname" semantic conventions. It represents the - // hostname of a GCE instance. This is the full value of the default or - // [custom - // hostname](https://cloud.google.com/compute/docs/instances/custom-hostname-vm). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'my-host1234.example.com', - // 'sample-vm.us-west1-b.c.my-project.internal' - GCPGceInstanceHostnameKey = attribute.Key("gcp.gce.instance.hostname") - - // GCPGceInstanceNameKey is the attribute Key conforming to the - // "gcp.gce.instance.name" semantic conventions. It represents the instance - // name of a GCE instance. This is the value provided by `host.name`, the - // visible name of the instance in the Cloud Console UI, and the prefix for - // the default hostname of the instance as defined by the [default internal - // DNS - // name](https://cloud.google.com/compute/docs/internal-dns#instance-fully-qualified-domain-names). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'instance-1', 'my-vm-name' - GCPGceInstanceNameKey = attribute.Key("gcp.gce.instance.name") -) - -// GCPGceInstanceHostname returns an attribute KeyValue conforming to the -// "gcp.gce.instance.hostname" semantic conventions. It represents the hostname -// of a GCE instance. This is the full value of the default or [custom -// hostname](https://cloud.google.com/compute/docs/instances/custom-hostname-vm). -func GCPGceInstanceHostname(val string) attribute.KeyValue { - return GCPGceInstanceHostnameKey.String(val) -} - -// GCPGceInstanceName returns an attribute KeyValue conforming to the -// "gcp.gce.instance.name" semantic conventions. It represents the instance -// name of a GCE instance. This is the value provided by `host.name`, the -// visible name of the instance in the Cloud Console UI, and the prefix for the -// default hostname of the instance as defined by the [default internal DNS -// name](https://cloud.google.com/compute/docs/internal-dns#instance-fully-qualified-domain-names). -func GCPGceInstanceName(val string) attribute.KeyValue { - return GCPGceInstanceNameKey.String(val) -} - -// Heroku dyno metadata -const ( - // HerokuAppIDKey is the attribute Key conforming to the "heroku.app.id" - // semantic conventions. It represents the unique identifier for the - // application - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '2daa2797-e42b-4624-9322-ec3f968df4da' - HerokuAppIDKey = attribute.Key("heroku.app.id") - - // HerokuReleaseCommitKey is the attribute Key conforming to the - // "heroku.release.commit" semantic conventions. It represents the commit - // hash for the current release - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'e6134959463efd8966b20e75b913cafe3f5ec' - HerokuReleaseCommitKey = attribute.Key("heroku.release.commit") - - // HerokuReleaseCreationTimestampKey is the attribute Key conforming to the - // "heroku.release.creation_timestamp" semantic conventions. It represents - // the time and date the release was created - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '2022-10-23T18:00:42Z' - HerokuReleaseCreationTimestampKey = attribute.Key("heroku.release.creation_timestamp") -) - -// HerokuAppID returns an attribute KeyValue conforming to the -// "heroku.app.id" semantic conventions. It represents the unique identifier -// for the application -func HerokuAppID(val string) attribute.KeyValue { - return HerokuAppIDKey.String(val) -} - -// HerokuReleaseCommit returns an attribute KeyValue conforming to the -// "heroku.release.commit" semantic conventions. It represents the commit hash -// for the current release -func HerokuReleaseCommit(val string) attribute.KeyValue { - return HerokuReleaseCommitKey.String(val) -} - -// HerokuReleaseCreationTimestamp returns an attribute KeyValue conforming -// to the "heroku.release.creation_timestamp" semantic conventions. It -// represents the time and date the release was created -func HerokuReleaseCreationTimestamp(val string) attribute.KeyValue { - return HerokuReleaseCreationTimestampKey.String(val) -} - -// The software deployment. -const ( - // DeploymentEnvironmentKey is the attribute Key conforming to the - // "deployment.environment" semantic conventions. It represents the name of - // the [deployment - // environment](https://wikipedia.org/wiki/Deployment_environment) (aka - // deployment tier). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'staging', 'production' - // Note: `deployment.environment` does not affect the uniqueness - // constraints defined through - // the `service.namespace`, `service.name` and `service.instance.id` - // resource attributes. - // This implies that resources carrying the following attribute - // combinations MUST be - // considered to be identifying the same service: - // - // * `service.name=frontend`, `deployment.environment=production` - // * `service.name=frontend`, `deployment.environment=staging`. - DeploymentEnvironmentKey = attribute.Key("deployment.environment") -) - -// DeploymentEnvironment returns an attribute KeyValue conforming to the -// "deployment.environment" semantic conventions. It represents the name of the -// [deployment environment](https://wikipedia.org/wiki/Deployment_environment) -// (aka deployment tier). -func DeploymentEnvironment(val string) attribute.KeyValue { - return DeploymentEnvironmentKey.String(val) -} - -// A serverless instance. -const ( - // FaaSInstanceKey is the attribute Key conforming to the "faas.instance" - // semantic conventions. It represents the execution environment ID as a - // string, that will be potentially reused for other invocations to the - // same function/function version. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '2021/06/28/[$LATEST]2f399eb14537447da05ab2a2e39309de' - // Note: * **AWS Lambda:** Use the (full) log stream name. - FaaSInstanceKey = attribute.Key("faas.instance") - - // FaaSMaxMemoryKey is the attribute Key conforming to the - // "faas.max_memory" semantic conventions. It represents the amount of - // memory available to the serverless function converted to Bytes. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 134217728 - // Note: It's recommended to set this attribute since e.g. too little - // memory can easily stop a Java AWS Lambda function from working - // correctly. On AWS Lambda, the environment variable - // `AWS_LAMBDA_FUNCTION_MEMORY_SIZE` provides this information (which must - // be multiplied by 1,048,576). - FaaSMaxMemoryKey = attribute.Key("faas.max_memory") - - // FaaSNameKey is the attribute Key conforming to the "faas.name" semantic - // conventions. It represents the name of the single function that this - // runtime instance executes. - // - // Type: string - // RequirementLevel: Required - // Stability: experimental - // Examples: 'my-function', 'myazurefunctionapp/some-function-name' - // Note: This is the name of the function as configured/deployed on the - // FaaS - // platform and is usually different from the name of the callback - // function (which may be stored in the - // [`code.namespace`/`code.function`](/docs/general/attributes.md#source-code-attributes) - // span attributes). - // - // For some cloud providers, the above definition is ambiguous. The - // following - // definition of function name MUST be used for this attribute - // (and consequently the span name) for the listed cloud - // providers/products: - // - // * **Azure:** The full name `/`, i.e., function app name - // followed by a forward slash followed by the function name (this form - // can also be seen in the resource JSON for the function). - // This means that a span attribute MUST be used, as an Azure function - // app can host multiple functions that would usually share - // a TracerProvider (see also the `cloud.resource_id` attribute). - FaaSNameKey = attribute.Key("faas.name") - - // FaaSVersionKey is the attribute Key conforming to the "faas.version" - // semantic conventions. It represents the immutable version of the - // function being executed. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '26', 'pinkfroid-00002' - // Note: Depending on the cloud provider and platform, use: - // - // * **AWS Lambda:** The [function - // version](https://docs.aws.amazon.com/lambda/latest/dg/configuration-versions.html) - // (an integer represented as a decimal string). - // * **Google Cloud Run (Services):** The - // [revision](https://cloud.google.com/run/docs/managing/revisions) - // (i.e., the function name plus the revision suffix). - // * **Google Cloud Functions:** The value of the - // [`K_REVISION` environment - // variable](https://cloud.google.com/functions/docs/env-var#runtime_environment_variables_set_automatically). - // * **Azure Functions:** Not applicable. Do not set this attribute. - FaaSVersionKey = attribute.Key("faas.version") -) - -// FaaSInstance returns an attribute KeyValue conforming to the -// "faas.instance" semantic conventions. It represents the execution -// environment ID as a string, that will be potentially reused for other -// invocations to the same function/function version. -func FaaSInstance(val string) attribute.KeyValue { - return FaaSInstanceKey.String(val) -} - -// FaaSMaxMemory returns an attribute KeyValue conforming to the -// "faas.max_memory" semantic conventions. It represents the amount of memory -// available to the serverless function converted to Bytes. -func FaaSMaxMemory(val int) attribute.KeyValue { - return FaaSMaxMemoryKey.Int(val) -} - -// FaaSName returns an attribute KeyValue conforming to the "faas.name" -// semantic conventions. It represents the name of the single function that -// this runtime instance executes. -func FaaSName(val string) attribute.KeyValue { - return FaaSNameKey.String(val) -} - -// FaaSVersion returns an attribute KeyValue conforming to the -// "faas.version" semantic conventions. It represents the immutable version of -// the function being executed. -func FaaSVersion(val string) attribute.KeyValue { - return FaaSVersionKey.String(val) -} - -// A service instance. -const ( - // ServiceNameKey is the attribute Key conforming to the "service.name" - // semantic conventions. It represents the logical name of the service. - // - // Type: string - // RequirementLevel: Required - // Stability: experimental - // Examples: 'shoppingcart' - // Note: MUST be the same for all instances of horizontally scaled - // services. If the value was not specified, SDKs MUST fallback to - // `unknown_service:` concatenated with - // [`process.executable.name`](process.md#process), e.g. - // `unknown_service:bash`. If `process.executable.name` is not available, - // the value MUST be set to `unknown_service`. - ServiceNameKey = attribute.Key("service.name") - - // ServiceVersionKey is the attribute Key conforming to the - // "service.version" semantic conventions. It represents the version string - // of the service API or implementation. The format is not defined by these - // conventions. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '2.0.0', 'a01dbef8a' - ServiceVersionKey = attribute.Key("service.version") -) - -// ServiceName returns an attribute KeyValue conforming to the -// "service.name" semantic conventions. It represents the logical name of the -// service. -func ServiceName(val string) attribute.KeyValue { - return ServiceNameKey.String(val) -} - -// ServiceVersion returns an attribute KeyValue conforming to the -// "service.version" semantic conventions. It represents the version string of -// the service API or implementation. The format is not defined by these -// conventions. -func ServiceVersion(val string) attribute.KeyValue { - return ServiceVersionKey.String(val) -} - -// A service instance. -const ( - // ServiceInstanceIDKey is the attribute Key conforming to the - // "service.instance.id" semantic conventions. It represents the string ID - // of the service instance. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'my-k8s-pod-deployment-1', - // '627cc493-f310-47de-96bd-71410b7dec09' - // Note: MUST be unique for each instance of the same - // `service.namespace,service.name` pair (in other words - // `service.namespace,service.name,service.instance.id` triplet MUST be - // globally unique). The ID helps to distinguish instances of the same - // service that exist at the same time (e.g. instances of a horizontally - // scaled service). It is preferable for the ID to be persistent and stay - // the same for the lifetime of the service instance, however it is - // acceptable that the ID is ephemeral and changes during important - // lifetime events for the service (e.g. service restarts). If the service - // has no inherent unique ID that can be used as the value of this - // attribute it is recommended to generate a random Version 1 or Version 4 - // RFC 4122 UUID (services aiming for reproducible UUIDs may also use - // Version 5, see RFC 4122 for more recommendations). - ServiceInstanceIDKey = attribute.Key("service.instance.id") - - // ServiceNamespaceKey is the attribute Key conforming to the - // "service.namespace" semantic conventions. It represents a namespace for - // `service.name`. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'Shop' - // Note: A string value having a meaning that helps to distinguish a group - // of services, for example the team name that owns a group of services. - // `service.name` is expected to be unique within the same namespace. If - // `service.namespace` is not specified in the Resource then `service.name` - // is expected to be unique for all services that have no explicit - // namespace defined (so the empty/unspecified namespace is simply one more - // valid namespace). Zero-length namespace string is assumed equal to - // unspecified namespace. - ServiceNamespaceKey = attribute.Key("service.namespace") -) - -// ServiceInstanceID returns an attribute KeyValue conforming to the -// "service.instance.id" semantic conventions. It represents the string ID of -// the service instance. -func ServiceInstanceID(val string) attribute.KeyValue { - return ServiceInstanceIDKey.String(val) -} - -// ServiceNamespace returns an attribute KeyValue conforming to the -// "service.namespace" semantic conventions. It represents a namespace for -// `service.name`. -func ServiceNamespace(val string) attribute.KeyValue { - return ServiceNamespaceKey.String(val) -} - -// The telemetry SDK used to capture data recorded by the instrumentation -// libraries. -const ( - // TelemetrySDKLanguageKey is the attribute Key conforming to the - // "telemetry.sdk.language" semantic conventions. It represents the - // language of the telemetry SDK. - // - // Type: Enum - // RequirementLevel: Required - // Stability: experimental - TelemetrySDKLanguageKey = attribute.Key("telemetry.sdk.language") - - // TelemetrySDKNameKey is the attribute Key conforming to the - // "telemetry.sdk.name" semantic conventions. It represents the name of the - // telemetry SDK as defined above. - // - // Type: string - // RequirementLevel: Required - // Stability: experimental - // Examples: 'opentelemetry' - // Note: The OpenTelemetry SDK MUST set the `telemetry.sdk.name` attribute - // to `opentelemetry`. - // If another SDK, like a fork or a vendor-provided implementation, is - // used, this SDK MUST set the - // `telemetry.sdk.name` attribute to the fully-qualified class or module - // name of this SDK's main entry point - // or another suitable identifier depending on the language. - // The identifier `opentelemetry` is reserved and MUST NOT be used in this - // case. - // All custom identifiers SHOULD be stable across different versions of an - // implementation. - TelemetrySDKNameKey = attribute.Key("telemetry.sdk.name") - - // TelemetrySDKVersionKey is the attribute Key conforming to the - // "telemetry.sdk.version" semantic conventions. It represents the version - // string of the telemetry SDK. - // - // Type: string - // RequirementLevel: Required - // Stability: experimental - // Examples: '1.2.3' - TelemetrySDKVersionKey = attribute.Key("telemetry.sdk.version") -) - -var ( - // cpp - TelemetrySDKLanguageCPP = TelemetrySDKLanguageKey.String("cpp") - // dotnet - TelemetrySDKLanguageDotnet = TelemetrySDKLanguageKey.String("dotnet") - // erlang - TelemetrySDKLanguageErlang = TelemetrySDKLanguageKey.String("erlang") - // go - TelemetrySDKLanguageGo = TelemetrySDKLanguageKey.String("go") - // java - TelemetrySDKLanguageJava = TelemetrySDKLanguageKey.String("java") - // nodejs - TelemetrySDKLanguageNodejs = TelemetrySDKLanguageKey.String("nodejs") - // php - TelemetrySDKLanguagePHP = TelemetrySDKLanguageKey.String("php") - // python - TelemetrySDKLanguagePython = TelemetrySDKLanguageKey.String("python") - // ruby - TelemetrySDKLanguageRuby = TelemetrySDKLanguageKey.String("ruby") - // rust - TelemetrySDKLanguageRust = TelemetrySDKLanguageKey.String("rust") - // swift - TelemetrySDKLanguageSwift = TelemetrySDKLanguageKey.String("swift") - // webjs - TelemetrySDKLanguageWebjs = TelemetrySDKLanguageKey.String("webjs") -) - -// TelemetrySDKName returns an attribute KeyValue conforming to the -// "telemetry.sdk.name" semantic conventions. It represents the name of the -// telemetry SDK as defined above. -func TelemetrySDKName(val string) attribute.KeyValue { - return TelemetrySDKNameKey.String(val) -} - -// TelemetrySDKVersion returns an attribute KeyValue conforming to the -// "telemetry.sdk.version" semantic conventions. It represents the version -// string of the telemetry SDK. -func TelemetrySDKVersion(val string) attribute.KeyValue { - return TelemetrySDKVersionKey.String(val) -} - -// The telemetry SDK used to capture data recorded by the instrumentation -// libraries. -const ( - // TelemetryDistroNameKey is the attribute Key conforming to the - // "telemetry.distro.name" semantic conventions. It represents the name of - // the auto instrumentation agent or distribution, if used. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'parts-unlimited-java' - // Note: Official auto instrumentation agents and distributions SHOULD set - // the `telemetry.distro.name` attribute to - // a string starting with `opentelemetry-`, e.g. - // `opentelemetry-java-instrumentation`. - TelemetryDistroNameKey = attribute.Key("telemetry.distro.name") - - // TelemetryDistroVersionKey is the attribute Key conforming to the - // "telemetry.distro.version" semantic conventions. It represents the - // version string of the auto instrumentation agent or distribution, if - // used. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '1.2.3' - TelemetryDistroVersionKey = attribute.Key("telemetry.distro.version") -) - -// TelemetryDistroName returns an attribute KeyValue conforming to the -// "telemetry.distro.name" semantic conventions. It represents the name of the -// auto instrumentation agent or distribution, if used. -func TelemetryDistroName(val string) attribute.KeyValue { - return TelemetryDistroNameKey.String(val) -} - -// TelemetryDistroVersion returns an attribute KeyValue conforming to the -// "telemetry.distro.version" semantic conventions. It represents the version -// string of the auto instrumentation agent or distribution, if used. -func TelemetryDistroVersion(val string) attribute.KeyValue { - return TelemetryDistroVersionKey.String(val) -} - -// Resource describing the packaged software running the application code. Web -// engines are typically executed using process.runtime. -const ( - // WebEngineDescriptionKey is the attribute Key conforming to the - // "webengine.description" semantic conventions. It represents the - // additional description of the web engine (e.g. detailed version and - // edition information). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'WildFly Full 21.0.0.Final (WildFly Core 13.0.1.Final) - - // 2.2.2.Final' - WebEngineDescriptionKey = attribute.Key("webengine.description") - - // WebEngineNameKey is the attribute Key conforming to the "webengine.name" - // semantic conventions. It represents the name of the web engine. - // - // Type: string - // RequirementLevel: Required - // Stability: experimental - // Examples: 'WildFly' - WebEngineNameKey = attribute.Key("webengine.name") - - // WebEngineVersionKey is the attribute Key conforming to the - // "webengine.version" semantic conventions. It represents the version of - // the web engine. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '21.0.0' - WebEngineVersionKey = attribute.Key("webengine.version") -) - -// WebEngineDescription returns an attribute KeyValue conforming to the -// "webengine.description" semantic conventions. It represents the additional -// description of the web engine (e.g. detailed version and edition -// information). -func WebEngineDescription(val string) attribute.KeyValue { - return WebEngineDescriptionKey.String(val) -} - -// WebEngineName returns an attribute KeyValue conforming to the -// "webengine.name" semantic conventions. It represents the name of the web -// engine. -func WebEngineName(val string) attribute.KeyValue { - return WebEngineNameKey.String(val) -} - -// WebEngineVersion returns an attribute KeyValue conforming to the -// "webengine.version" semantic conventions. It represents the version of the -// web engine. -func WebEngineVersion(val string) attribute.KeyValue { - return WebEngineVersionKey.String(val) -} - -// Attributes used by non-OTLP exporters to represent OpenTelemetry Scope's -// concepts. -const ( - // OTelScopeNameKey is the attribute Key conforming to the - // "otel.scope.name" semantic conventions. It represents the name of the - // instrumentation scope - (`InstrumentationScope.Name` in OTLP). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'io.opentelemetry.contrib.mongodb' - OTelScopeNameKey = attribute.Key("otel.scope.name") - - // OTelScopeVersionKey is the attribute Key conforming to the - // "otel.scope.version" semantic conventions. It represents the version of - // the instrumentation scope - (`InstrumentationScope.Version` in OTLP). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '1.0.0' - OTelScopeVersionKey = attribute.Key("otel.scope.version") -) - -// OTelScopeName returns an attribute KeyValue conforming to the -// "otel.scope.name" semantic conventions. It represents the name of the -// instrumentation scope - (`InstrumentationScope.Name` in OTLP). -func OTelScopeName(val string) attribute.KeyValue { - return OTelScopeNameKey.String(val) -} - -// OTelScopeVersion returns an attribute KeyValue conforming to the -// "otel.scope.version" semantic conventions. It represents the version of the -// instrumentation scope - (`InstrumentationScope.Version` in OTLP). -func OTelScopeVersion(val string) attribute.KeyValue { - return OTelScopeVersionKey.String(val) -} - -// Span attributes used by non-OTLP exporters to represent OpenTelemetry -// Scope's concepts. -const ( - // OTelLibraryNameKey is the attribute Key conforming to the - // "otel.library.name" semantic conventions. - // - // Type: string - // RequirementLevel: Optional - // Stability: deprecated - // Examples: 'io.opentelemetry.contrib.mongodb' - // Deprecated: use the `otel.scope.name` attribute. - OTelLibraryNameKey = attribute.Key("otel.library.name") - - // OTelLibraryVersionKey is the attribute Key conforming to the - // "otel.library.version" semantic conventions. - // - // Type: string - // RequirementLevel: Optional - // Stability: deprecated - // Examples: '1.0.0' - // Deprecated: use the `otel.scope.version` attribute. - OTelLibraryVersionKey = attribute.Key("otel.library.version") -) - -// OTelLibraryName returns an attribute KeyValue conforming to the -// "otel.library.name" semantic conventions. -// -// Deprecated: use the `otel.scope.name` attribute. -func OTelLibraryName(val string) attribute.KeyValue { - return OTelLibraryNameKey.String(val) -} - -// OTelLibraryVersion returns an attribute KeyValue conforming to the -// "otel.library.version" semantic conventions. -// -// Deprecated: use the `otel.scope.version` attribute. -func OTelLibraryVersion(val string) attribute.KeyValue { - return OTelLibraryVersionKey.String(val) -} diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/schema.go b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/schema.go deleted file mode 100644 index fe80b1731d..0000000000 --- a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/schema.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package semconv // import "go.opentelemetry.io/otel/semconv/v1.24.0" - -// SchemaURL is the schema URL that matches the version of the semantic conventions -// that this package defines. Semconv packages starting from v1.4.0 must declare -// non-empty schema URL in the form https://opentelemetry.io/schemas/ -const SchemaURL = "https://opentelemetry.io/schemas/1.24.0" diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/trace.go b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/trace.go deleted file mode 100644 index c1718234e5..0000000000 --- a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/trace.go +++ /dev/null @@ -1,1323 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -// Code generated from semantic convention specification. DO NOT EDIT. - -package semconv // import "go.opentelemetry.io/otel/semconv/v1.24.0" - -import "go.opentelemetry.io/otel/attribute" - -// Operations that access some remote service. -const ( - // PeerServiceKey is the attribute Key conforming to the "peer.service" - // semantic conventions. It represents the - // [`service.name`](/docs/resource/README.md#service) of the remote - // service. SHOULD be equal to the actual `service.name` resource attribute - // of the remote service if any. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'AuthTokenCache' - PeerServiceKey = attribute.Key("peer.service") -) - -// PeerService returns an attribute KeyValue conforming to the -// "peer.service" semantic conventions. It represents the -// [`service.name`](/docs/resource/README.md#service) of the remote service. -// SHOULD be equal to the actual `service.name` resource attribute of the -// remote service if any. -func PeerService(val string) attribute.KeyValue { - return PeerServiceKey.String(val) -} - -// These attributes may be used for any operation with an authenticated and/or -// authorized enduser. -const ( - // EnduserIDKey is the attribute Key conforming to the "enduser.id" - // semantic conventions. It represents the username or client_id extracted - // from the access token or - // [Authorization](https://tools.ietf.org/html/rfc7235#section-4.2) header - // in the inbound request from outside the system. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'username' - EnduserIDKey = attribute.Key("enduser.id") - - // EnduserRoleKey is the attribute Key conforming to the "enduser.role" - // semantic conventions. It represents the actual/assumed role the client - // is making the request under extracted from token or application security - // context. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'admin' - EnduserRoleKey = attribute.Key("enduser.role") - - // EnduserScopeKey is the attribute Key conforming to the "enduser.scope" - // semantic conventions. It represents the scopes or granted authorities - // the client currently possesses extracted from token or application - // security context. The value would come from the scope associated with an - // [OAuth 2.0 Access - // Token](https://tools.ietf.org/html/rfc6749#section-3.3) or an attribute - // value in a [SAML 2.0 - // Assertion](http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0.html). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'read:message, write:files' - EnduserScopeKey = attribute.Key("enduser.scope") -) - -// EnduserID returns an attribute KeyValue conforming to the "enduser.id" -// semantic conventions. It represents the username or client_id extracted from -// the access token or -// [Authorization](https://tools.ietf.org/html/rfc7235#section-4.2) header in -// the inbound request from outside the system. -func EnduserID(val string) attribute.KeyValue { - return EnduserIDKey.String(val) -} - -// EnduserRole returns an attribute KeyValue conforming to the -// "enduser.role" semantic conventions. It represents the actual/assumed role -// the client is making the request under extracted from token or application -// security context. -func EnduserRole(val string) attribute.KeyValue { - return EnduserRoleKey.String(val) -} - -// EnduserScope returns an attribute KeyValue conforming to the -// "enduser.scope" semantic conventions. It represents the scopes or granted -// authorities the client currently possesses extracted from token or -// application security context. The value would come from the scope associated -// with an [OAuth 2.0 Access -// Token](https://tools.ietf.org/html/rfc6749#section-3.3) or an attribute -// value in a [SAML 2.0 -// Assertion](http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0.html). -func EnduserScope(val string) attribute.KeyValue { - return EnduserScopeKey.String(val) -} - -// These attributes allow to report this unit of code and therefore to provide -// more context about the span. -const ( - // CodeColumnKey is the attribute Key conforming to the "code.column" - // semantic conventions. It represents the column number in `code.filepath` - // best representing the operation. It SHOULD point within the code unit - // named in `code.function`. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 16 - CodeColumnKey = attribute.Key("code.column") - - // CodeFilepathKey is the attribute Key conforming to the "code.filepath" - // semantic conventions. It represents the source code file name that - // identifies the code unit as uniquely as possible (preferably an absolute - // file path). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '/usr/local/MyApplication/content_root/app/index.php' - CodeFilepathKey = attribute.Key("code.filepath") - - // CodeFunctionKey is the attribute Key conforming to the "code.function" - // semantic conventions. It represents the method or function name, or - // equivalent (usually rightmost part of the code unit's name). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'serveRequest' - CodeFunctionKey = attribute.Key("code.function") - - // CodeLineNumberKey is the attribute Key conforming to the "code.lineno" - // semantic conventions. It represents the line number in `code.filepath` - // best representing the operation. It SHOULD point within the code unit - // named in `code.function`. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 42 - CodeLineNumberKey = attribute.Key("code.lineno") - - // CodeNamespaceKey is the attribute Key conforming to the "code.namespace" - // semantic conventions. It represents the "namespace" within which - // `code.function` is defined. Usually the qualified class or module name, - // such that `code.namespace` + some separator + `code.function` form a - // unique identifier for the code unit. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'com.example.MyHTTPService' - CodeNamespaceKey = attribute.Key("code.namespace") - - // CodeStacktraceKey is the attribute Key conforming to the - // "code.stacktrace" semantic conventions. It represents a stacktrace as a - // string in the natural representation for the language runtime. The - // representation is to be determined and documented by each language SIG. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'at - // com.example.GenerateTrace.methodB(GenerateTrace.java:13)\\n at ' - // 'com.example.GenerateTrace.methodA(GenerateTrace.java:9)\\n at ' - // 'com.example.GenerateTrace.main(GenerateTrace.java:5)' - CodeStacktraceKey = attribute.Key("code.stacktrace") -) - -// CodeColumn returns an attribute KeyValue conforming to the "code.column" -// semantic conventions. It represents the column number in `code.filepath` -// best representing the operation. It SHOULD point within the code unit named -// in `code.function`. -func CodeColumn(val int) attribute.KeyValue { - return CodeColumnKey.Int(val) -} - -// CodeFilepath returns an attribute KeyValue conforming to the -// "code.filepath" semantic conventions. It represents the source code file -// name that identifies the code unit as uniquely as possible (preferably an -// absolute file path). -func CodeFilepath(val string) attribute.KeyValue { - return CodeFilepathKey.String(val) -} - -// CodeFunction returns an attribute KeyValue conforming to the -// "code.function" semantic conventions. It represents the method or function -// name, or equivalent (usually rightmost part of the code unit's name). -func CodeFunction(val string) attribute.KeyValue { - return CodeFunctionKey.String(val) -} - -// CodeLineNumber returns an attribute KeyValue conforming to the "code.lineno" -// semantic conventions. It represents the line number in `code.filepath` best -// representing the operation. It SHOULD point within the code unit named in -// `code.function`. -func CodeLineNumber(val int) attribute.KeyValue { - return CodeLineNumberKey.Int(val) -} - -// CodeNamespace returns an attribute KeyValue conforming to the -// "code.namespace" semantic conventions. It represents the "namespace" within -// which `code.function` is defined. Usually the qualified class or module -// name, such that `code.namespace` + some separator + `code.function` form a -// unique identifier for the code unit. -func CodeNamespace(val string) attribute.KeyValue { - return CodeNamespaceKey.String(val) -} - -// CodeStacktrace returns an attribute KeyValue conforming to the -// "code.stacktrace" semantic conventions. It represents a stacktrace as a -// string in the natural representation for the language runtime. The -// representation is to be determined and documented by each language SIG. -func CodeStacktrace(val string) attribute.KeyValue { - return CodeStacktraceKey.String(val) -} - -// These attributes may be used for any operation to store information about a -// thread that started a span. -const ( - // ThreadIDKey is the attribute Key conforming to the "thread.id" semantic - // conventions. It represents the current "managed" thread ID (as opposed - // to OS thread ID). - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 42 - ThreadIDKey = attribute.Key("thread.id") - - // ThreadNameKey is the attribute Key conforming to the "thread.name" - // semantic conventions. It represents the current thread name. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'main' - ThreadNameKey = attribute.Key("thread.name") -) - -// ThreadID returns an attribute KeyValue conforming to the "thread.id" -// semantic conventions. It represents the current "managed" thread ID (as -// opposed to OS thread ID). -func ThreadID(val int) attribute.KeyValue { - return ThreadIDKey.Int(val) -} - -// ThreadName returns an attribute KeyValue conforming to the "thread.name" -// semantic conventions. It represents the current thread name. -func ThreadName(val string) attribute.KeyValue { - return ThreadNameKey.String(val) -} - -// Span attributes used by AWS Lambda (in addition to general `faas` -// attributes). -const ( - // AWSLambdaInvokedARNKey is the attribute Key conforming to the - // "aws.lambda.invoked_arn" semantic conventions. It represents the full - // invoked ARN as provided on the `Context` passed to the function - // (`Lambda-Runtime-Invoked-Function-ARN` header on the - // `/runtime/invocation/next` applicable). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'arn:aws:lambda:us-east-1:123456:function:myfunction:myalias' - // Note: This may be different from `cloud.resource_id` if an alias is - // involved. - AWSLambdaInvokedARNKey = attribute.Key("aws.lambda.invoked_arn") -) - -// AWSLambdaInvokedARN returns an attribute KeyValue conforming to the -// "aws.lambda.invoked_arn" semantic conventions. It represents the full -// invoked ARN as provided on the `Context` passed to the function -// (`Lambda-Runtime-Invoked-Function-ARN` header on the -// `/runtime/invocation/next` applicable). -func AWSLambdaInvokedARN(val string) attribute.KeyValue { - return AWSLambdaInvokedARNKey.String(val) -} - -// Attributes for CloudEvents. CloudEvents is a specification on how to define -// event data in a standard way. These attributes can be attached to spans when -// performing operations with CloudEvents, regardless of the protocol being -// used. -const ( - // CloudeventsEventIDKey is the attribute Key conforming to the - // "cloudevents.event_id" semantic conventions. It represents the - // [event_id](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#id) - // uniquely identifies the event. - // - // Type: string - // RequirementLevel: Required - // Stability: experimental - // Examples: '123e4567-e89b-12d3-a456-426614174000', '0001' - CloudeventsEventIDKey = attribute.Key("cloudevents.event_id") - - // CloudeventsEventSourceKey is the attribute Key conforming to the - // "cloudevents.event_source" semantic conventions. It represents the - // [source](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#source-1) - // identifies the context in which an event happened. - // - // Type: string - // RequirementLevel: Required - // Stability: experimental - // Examples: 'https://github.com/cloudevents', - // '/cloudevents/spec/pull/123', 'my-service' - CloudeventsEventSourceKey = attribute.Key("cloudevents.event_source") - - // CloudeventsEventSpecVersionKey is the attribute Key conforming to the - // "cloudevents.event_spec_version" semantic conventions. It represents the - // [version of the CloudEvents - // specification](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#specversion) - // which the event uses. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '1.0' - CloudeventsEventSpecVersionKey = attribute.Key("cloudevents.event_spec_version") - - // CloudeventsEventSubjectKey is the attribute Key conforming to the - // "cloudevents.event_subject" semantic conventions. It represents the - // [subject](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#subject) - // of the event in the context of the event producer (identified by - // source). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'mynewfile.jpg' - CloudeventsEventSubjectKey = attribute.Key("cloudevents.event_subject") - - // CloudeventsEventTypeKey is the attribute Key conforming to the - // "cloudevents.event_type" semantic conventions. It represents the - // [event_type](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#type) - // contains a value describing the type of event related to the originating - // occurrence. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'com.github.pull_request.opened', - // 'com.example.object.deleted.v2' - CloudeventsEventTypeKey = attribute.Key("cloudevents.event_type") -) - -// CloudeventsEventID returns an attribute KeyValue conforming to the -// "cloudevents.event_id" semantic conventions. It represents the -// [event_id](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#id) -// uniquely identifies the event. -func CloudeventsEventID(val string) attribute.KeyValue { - return CloudeventsEventIDKey.String(val) -} - -// CloudeventsEventSource returns an attribute KeyValue conforming to the -// "cloudevents.event_source" semantic conventions. It represents the -// [source](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#source-1) -// identifies the context in which an event happened. -func CloudeventsEventSource(val string) attribute.KeyValue { - return CloudeventsEventSourceKey.String(val) -} - -// CloudeventsEventSpecVersion returns an attribute KeyValue conforming to -// the "cloudevents.event_spec_version" semantic conventions. It represents the -// [version of the CloudEvents -// specification](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#specversion) -// which the event uses. -func CloudeventsEventSpecVersion(val string) attribute.KeyValue { - return CloudeventsEventSpecVersionKey.String(val) -} - -// CloudeventsEventSubject returns an attribute KeyValue conforming to the -// "cloudevents.event_subject" semantic conventions. It represents the -// [subject](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#subject) -// of the event in the context of the event producer (identified by source). -func CloudeventsEventSubject(val string) attribute.KeyValue { - return CloudeventsEventSubjectKey.String(val) -} - -// CloudeventsEventType returns an attribute KeyValue conforming to the -// "cloudevents.event_type" semantic conventions. It represents the -// [event_type](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#type) -// contains a value describing the type of event related to the originating -// occurrence. -func CloudeventsEventType(val string) attribute.KeyValue { - return CloudeventsEventTypeKey.String(val) -} - -// Semantic conventions for the OpenTracing Shim -const ( - // OpentracingRefTypeKey is the attribute Key conforming to the - // "opentracing.ref_type" semantic conventions. It represents the - // parent-child Reference type - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - // Note: The causal relationship between a child Span and a parent Span. - OpentracingRefTypeKey = attribute.Key("opentracing.ref_type") -) - -var ( - // The parent Span depends on the child Span in some capacity - OpentracingRefTypeChildOf = OpentracingRefTypeKey.String("child_of") - // The parent Span doesn't depend in any way on the result of the child Span - OpentracingRefTypeFollowsFrom = OpentracingRefTypeKey.String("follows_from") -) - -// Span attributes used by non-OTLP exporters to represent OpenTelemetry Span's -// concepts. -const ( - // OTelStatusCodeKey is the attribute Key conforming to the - // "otel.status_code" semantic conventions. It represents the name of the - // code, either "OK" or "ERROR". MUST NOT be set if the status code is - // UNSET. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - OTelStatusCodeKey = attribute.Key("otel.status_code") - - // OTelStatusDescriptionKey is the attribute Key conforming to the - // "otel.status_description" semantic conventions. It represents the - // description of the Status if it has a value, otherwise not set. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'resource not found' - OTelStatusDescriptionKey = attribute.Key("otel.status_description") -) - -var ( - // The operation has been validated by an Application developer or Operator to have completed successfully - OTelStatusCodeOk = OTelStatusCodeKey.String("OK") - // The operation contains an error - OTelStatusCodeError = OTelStatusCodeKey.String("ERROR") -) - -// OTelStatusDescription returns an attribute KeyValue conforming to the -// "otel.status_description" semantic conventions. It represents the -// description of the Status if it has a value, otherwise not set. -func OTelStatusDescription(val string) attribute.KeyValue { - return OTelStatusDescriptionKey.String(val) -} - -// This semantic convention describes an instance of a function that runs -// without provisioning or managing of servers (also known as serverless -// functions or Function as a Service (FaaS)) with spans. -const ( - // FaaSInvocationIDKey is the attribute Key conforming to the - // "faas.invocation_id" semantic conventions. It represents the invocation - // ID of the current function invocation. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'af9d5aa4-a685-4c5f-a22b-444f80b3cc28' - FaaSInvocationIDKey = attribute.Key("faas.invocation_id") -) - -// FaaSInvocationID returns an attribute KeyValue conforming to the -// "faas.invocation_id" semantic conventions. It represents the invocation ID -// of the current function invocation. -func FaaSInvocationID(val string) attribute.KeyValue { - return FaaSInvocationIDKey.String(val) -} - -// Semantic Convention for FaaS triggered as a response to some data source -// operation such as a database or filesystem read/write. -const ( - // FaaSDocumentCollectionKey is the attribute Key conforming to the - // "faas.document.collection" semantic conventions. It represents the name - // of the source on which the triggering operation was performed. For - // example, in Cloud Storage or S3 corresponds to the bucket name, and in - // Cosmos DB to the database name. - // - // Type: string - // RequirementLevel: Required - // Stability: experimental - // Examples: 'myBucketName', 'myDBName' - FaaSDocumentCollectionKey = attribute.Key("faas.document.collection") - - // FaaSDocumentNameKey is the attribute Key conforming to the - // "faas.document.name" semantic conventions. It represents the document - // name/table subjected to the operation. For example, in Cloud Storage or - // S3 is the name of the file, and in Cosmos DB the table name. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'myFile.txt', 'myTableName' - FaaSDocumentNameKey = attribute.Key("faas.document.name") - - // FaaSDocumentOperationKey is the attribute Key conforming to the - // "faas.document.operation" semantic conventions. It represents the - // describes the type of the operation that was performed on the data. - // - // Type: Enum - // RequirementLevel: Required - // Stability: experimental - FaaSDocumentOperationKey = attribute.Key("faas.document.operation") - - // FaaSDocumentTimeKey is the attribute Key conforming to the - // "faas.document.time" semantic conventions. It represents a string - // containing the time when the data was accessed in the [ISO - // 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format - // expressed in [UTC](https://www.w3.org/TR/NOTE-datetime). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '2020-01-23T13:47:06Z' - FaaSDocumentTimeKey = attribute.Key("faas.document.time") -) - -var ( - // When a new object is created - FaaSDocumentOperationInsert = FaaSDocumentOperationKey.String("insert") - // When an object is modified - FaaSDocumentOperationEdit = FaaSDocumentOperationKey.String("edit") - // When an object is deleted - FaaSDocumentOperationDelete = FaaSDocumentOperationKey.String("delete") -) - -// FaaSDocumentCollection returns an attribute KeyValue conforming to the -// "faas.document.collection" semantic conventions. It represents the name of -// the source on which the triggering operation was performed. For example, in -// Cloud Storage or S3 corresponds to the bucket name, and in Cosmos DB to the -// database name. -func FaaSDocumentCollection(val string) attribute.KeyValue { - return FaaSDocumentCollectionKey.String(val) -} - -// FaaSDocumentName returns an attribute KeyValue conforming to the -// "faas.document.name" semantic conventions. It represents the document -// name/table subjected to the operation. For example, in Cloud Storage or S3 -// is the name of the file, and in Cosmos DB the table name. -func FaaSDocumentName(val string) attribute.KeyValue { - return FaaSDocumentNameKey.String(val) -} - -// FaaSDocumentTime returns an attribute KeyValue conforming to the -// "faas.document.time" semantic conventions. It represents a string containing -// the time when the data was accessed in the [ISO -// 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format -// expressed in [UTC](https://www.w3.org/TR/NOTE-datetime). -func FaaSDocumentTime(val string) attribute.KeyValue { - return FaaSDocumentTimeKey.String(val) -} - -// Semantic Convention for FaaS scheduled to be executed regularly. -const ( - // FaaSCronKey is the attribute Key conforming to the "faas.cron" semantic - // conventions. It represents a string containing the schedule period as - // [Cron - // Expression](https://docs.oracle.com/cd/E12058_01/doc/doc.1014/e12030/cron_expressions.htm). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '0/5 * * * ? *' - FaaSCronKey = attribute.Key("faas.cron") - - // FaaSTimeKey is the attribute Key conforming to the "faas.time" semantic - // conventions. It represents a string containing the function invocation - // time in the [ISO - // 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format - // expressed in [UTC](https://www.w3.org/TR/NOTE-datetime). - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '2020-01-23T13:47:06Z' - FaaSTimeKey = attribute.Key("faas.time") -) - -// FaaSCron returns an attribute KeyValue conforming to the "faas.cron" -// semantic conventions. It represents a string containing the schedule period -// as [Cron -// Expression](https://docs.oracle.com/cd/E12058_01/doc/doc.1014/e12030/cron_expressions.htm). -func FaaSCron(val string) attribute.KeyValue { - return FaaSCronKey.String(val) -} - -// FaaSTime returns an attribute KeyValue conforming to the "faas.time" -// semantic conventions. It represents a string containing the function -// invocation time in the [ISO -// 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format -// expressed in [UTC](https://www.w3.org/TR/NOTE-datetime). -func FaaSTime(val string) attribute.KeyValue { - return FaaSTimeKey.String(val) -} - -// Contains additional attributes for incoming FaaS spans. -const ( - // FaaSColdstartKey is the attribute Key conforming to the "faas.coldstart" - // semantic conventions. It represents a boolean that is true if the - // serverless function is executed for the first time (aka cold-start). - // - // Type: boolean - // RequirementLevel: Optional - // Stability: experimental - FaaSColdstartKey = attribute.Key("faas.coldstart") -) - -// FaaSColdstart returns an attribute KeyValue conforming to the -// "faas.coldstart" semantic conventions. It represents a boolean that is true -// if the serverless function is executed for the first time (aka cold-start). -func FaaSColdstart(val bool) attribute.KeyValue { - return FaaSColdstartKey.Bool(val) -} - -// The `aws` conventions apply to operations using the AWS SDK. They map -// request or response parameters in AWS SDK API calls to attributes on a Span. -// The conventions have been collected over time based on feedback from AWS -// users of tracing and will continue to evolve as new interesting conventions -// are found. -// Some descriptions are also provided for populating general OpenTelemetry -// semantic conventions based on these APIs. -const ( - // AWSRequestIDKey is the attribute Key conforming to the "aws.request_id" - // semantic conventions. It represents the AWS request ID as returned in - // the response headers `x-amz-request-id` or `x-amz-requestid`. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '79b9da39-b7ae-508a-a6bc-864b2829c622', 'C9ER4AJX75574TDJ' - AWSRequestIDKey = attribute.Key("aws.request_id") -) - -// AWSRequestID returns an attribute KeyValue conforming to the -// "aws.request_id" semantic conventions. It represents the AWS request ID as -// returned in the response headers `x-amz-request-id` or `x-amz-requestid`. -func AWSRequestID(val string) attribute.KeyValue { - return AWSRequestIDKey.String(val) -} - -// Attributes that exist for multiple DynamoDB request types. -const ( - // AWSDynamoDBAttributesToGetKey is the attribute Key conforming to the - // "aws.dynamodb.attributes_to_get" semantic conventions. It represents the - // value of the `AttributesToGet` request parameter. - // - // Type: string[] - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'lives', 'id' - AWSDynamoDBAttributesToGetKey = attribute.Key("aws.dynamodb.attributes_to_get") - - // AWSDynamoDBConsistentReadKey is the attribute Key conforming to the - // "aws.dynamodb.consistent_read" semantic conventions. It represents the - // value of the `ConsistentRead` request parameter. - // - // Type: boolean - // RequirementLevel: Optional - // Stability: experimental - AWSDynamoDBConsistentReadKey = attribute.Key("aws.dynamodb.consistent_read") - - // AWSDynamoDBConsumedCapacityKey is the attribute Key conforming to the - // "aws.dynamodb.consumed_capacity" semantic conventions. It represents the - // JSON-serialized value of each item in the `ConsumedCapacity` response - // field. - // - // Type: string[] - // RequirementLevel: Optional - // Stability: experimental - // Examples: '{ "CapacityUnits": number, "GlobalSecondaryIndexes": { - // "string" : { "CapacityUnits": number, "ReadCapacityUnits": number, - // "WriteCapacityUnits": number } }, "LocalSecondaryIndexes": { "string" : - // { "CapacityUnits": number, "ReadCapacityUnits": number, - // "WriteCapacityUnits": number } }, "ReadCapacityUnits": number, "Table": - // { "CapacityUnits": number, "ReadCapacityUnits": number, - // "WriteCapacityUnits": number }, "TableName": "string", - // "WriteCapacityUnits": number }' - AWSDynamoDBConsumedCapacityKey = attribute.Key("aws.dynamodb.consumed_capacity") - - // AWSDynamoDBIndexNameKey is the attribute Key conforming to the - // "aws.dynamodb.index_name" semantic conventions. It represents the value - // of the `IndexName` request parameter. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'name_to_group' - AWSDynamoDBIndexNameKey = attribute.Key("aws.dynamodb.index_name") - - // AWSDynamoDBItemCollectionMetricsKey is the attribute Key conforming to - // the "aws.dynamodb.item_collection_metrics" semantic conventions. It - // represents the JSON-serialized value of the `ItemCollectionMetrics` - // response field. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: '{ "string" : [ { "ItemCollectionKey": { "string" : { "B": - // blob, "BOOL": boolean, "BS": [ blob ], "L": [ "AttributeValue" ], "M": { - // "string" : "AttributeValue" }, "N": "string", "NS": [ "string" ], - // "NULL": boolean, "S": "string", "SS": [ "string" ] } }, - // "SizeEstimateRangeGB": [ number ] } ] }' - AWSDynamoDBItemCollectionMetricsKey = attribute.Key("aws.dynamodb.item_collection_metrics") - - // AWSDynamoDBLimitKey is the attribute Key conforming to the - // "aws.dynamodb.limit" semantic conventions. It represents the value of - // the `Limit` request parameter. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 10 - AWSDynamoDBLimitKey = attribute.Key("aws.dynamodb.limit") - - // AWSDynamoDBProjectionKey is the attribute Key conforming to the - // "aws.dynamodb.projection" semantic conventions. It represents the value - // of the `ProjectionExpression` request parameter. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'Title', 'Title, Price, Color', 'Title, Description, - // RelatedItems, ProductReviews' - AWSDynamoDBProjectionKey = attribute.Key("aws.dynamodb.projection") - - // AWSDynamoDBProvisionedReadCapacityKey is the attribute Key conforming to - // the "aws.dynamodb.provisioned_read_capacity" semantic conventions. It - // represents the value of the `ProvisionedThroughput.ReadCapacityUnits` - // request parameter. - // - // Type: double - // RequirementLevel: Optional - // Stability: experimental - // Examples: 1.0, 2.0 - AWSDynamoDBProvisionedReadCapacityKey = attribute.Key("aws.dynamodb.provisioned_read_capacity") - - // AWSDynamoDBProvisionedWriteCapacityKey is the attribute Key conforming - // to the "aws.dynamodb.provisioned_write_capacity" semantic conventions. - // It represents the value of the - // `ProvisionedThroughput.WriteCapacityUnits` request parameter. - // - // Type: double - // RequirementLevel: Optional - // Stability: experimental - // Examples: 1.0, 2.0 - AWSDynamoDBProvisionedWriteCapacityKey = attribute.Key("aws.dynamodb.provisioned_write_capacity") - - // AWSDynamoDBSelectKey is the attribute Key conforming to the - // "aws.dynamodb.select" semantic conventions. It represents the value of - // the `Select` request parameter. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'ALL_ATTRIBUTES', 'COUNT' - AWSDynamoDBSelectKey = attribute.Key("aws.dynamodb.select") - - // AWSDynamoDBTableNamesKey is the attribute Key conforming to the - // "aws.dynamodb.table_names" semantic conventions. It represents the keys - // in the `RequestItems` object field. - // - // Type: string[] - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'Users', 'Cats' - AWSDynamoDBTableNamesKey = attribute.Key("aws.dynamodb.table_names") -) - -// AWSDynamoDBAttributesToGet returns an attribute KeyValue conforming to -// the "aws.dynamodb.attributes_to_get" semantic conventions. It represents the -// value of the `AttributesToGet` request parameter. -func AWSDynamoDBAttributesToGet(val ...string) attribute.KeyValue { - return AWSDynamoDBAttributesToGetKey.StringSlice(val) -} - -// AWSDynamoDBConsistentRead returns an attribute KeyValue conforming to the -// "aws.dynamodb.consistent_read" semantic conventions. It represents the value -// of the `ConsistentRead` request parameter. -func AWSDynamoDBConsistentRead(val bool) attribute.KeyValue { - return AWSDynamoDBConsistentReadKey.Bool(val) -} - -// AWSDynamoDBConsumedCapacity returns an attribute KeyValue conforming to -// the "aws.dynamodb.consumed_capacity" semantic conventions. It represents the -// JSON-serialized value of each item in the `ConsumedCapacity` response field. -func AWSDynamoDBConsumedCapacity(val ...string) attribute.KeyValue { - return AWSDynamoDBConsumedCapacityKey.StringSlice(val) -} - -// AWSDynamoDBIndexName returns an attribute KeyValue conforming to the -// "aws.dynamodb.index_name" semantic conventions. It represents the value of -// the `IndexName` request parameter. -func AWSDynamoDBIndexName(val string) attribute.KeyValue { - return AWSDynamoDBIndexNameKey.String(val) -} - -// AWSDynamoDBItemCollectionMetrics returns an attribute KeyValue conforming -// to the "aws.dynamodb.item_collection_metrics" semantic conventions. It -// represents the JSON-serialized value of the `ItemCollectionMetrics` response -// field. -func AWSDynamoDBItemCollectionMetrics(val string) attribute.KeyValue { - return AWSDynamoDBItemCollectionMetricsKey.String(val) -} - -// AWSDynamoDBLimit returns an attribute KeyValue conforming to the -// "aws.dynamodb.limit" semantic conventions. It represents the value of the -// `Limit` request parameter. -func AWSDynamoDBLimit(val int) attribute.KeyValue { - return AWSDynamoDBLimitKey.Int(val) -} - -// AWSDynamoDBProjection returns an attribute KeyValue conforming to the -// "aws.dynamodb.projection" semantic conventions. It represents the value of -// the `ProjectionExpression` request parameter. -func AWSDynamoDBProjection(val string) attribute.KeyValue { - return AWSDynamoDBProjectionKey.String(val) -} - -// AWSDynamoDBProvisionedReadCapacity returns an attribute KeyValue -// conforming to the "aws.dynamodb.provisioned_read_capacity" semantic -// conventions. It represents the value of the -// `ProvisionedThroughput.ReadCapacityUnits` request parameter. -func AWSDynamoDBProvisionedReadCapacity(val float64) attribute.KeyValue { - return AWSDynamoDBProvisionedReadCapacityKey.Float64(val) -} - -// AWSDynamoDBProvisionedWriteCapacity returns an attribute KeyValue -// conforming to the "aws.dynamodb.provisioned_write_capacity" semantic -// conventions. It represents the value of the -// `ProvisionedThroughput.WriteCapacityUnits` request parameter. -func AWSDynamoDBProvisionedWriteCapacity(val float64) attribute.KeyValue { - return AWSDynamoDBProvisionedWriteCapacityKey.Float64(val) -} - -// AWSDynamoDBSelect returns an attribute KeyValue conforming to the -// "aws.dynamodb.select" semantic conventions. It represents the value of the -// `Select` request parameter. -func AWSDynamoDBSelect(val string) attribute.KeyValue { - return AWSDynamoDBSelectKey.String(val) -} - -// AWSDynamoDBTableNames returns an attribute KeyValue conforming to the -// "aws.dynamodb.table_names" semantic conventions. It represents the keys in -// the `RequestItems` object field. -func AWSDynamoDBTableNames(val ...string) attribute.KeyValue { - return AWSDynamoDBTableNamesKey.StringSlice(val) -} - -// DynamoDB.CreateTable -const ( - // AWSDynamoDBGlobalSecondaryIndexesKey is the attribute Key conforming to - // the "aws.dynamodb.global_secondary_indexes" semantic conventions. It - // represents the JSON-serialized value of each item of the - // `GlobalSecondaryIndexes` request field - // - // Type: string[] - // RequirementLevel: Optional - // Stability: experimental - // Examples: '{ "IndexName": "string", "KeySchema": [ { "AttributeName": - // "string", "KeyType": "string" } ], "Projection": { "NonKeyAttributes": [ - // "string" ], "ProjectionType": "string" }, "ProvisionedThroughput": { - // "ReadCapacityUnits": number, "WriteCapacityUnits": number } }' - AWSDynamoDBGlobalSecondaryIndexesKey = attribute.Key("aws.dynamodb.global_secondary_indexes") - - // AWSDynamoDBLocalSecondaryIndexesKey is the attribute Key conforming to - // the "aws.dynamodb.local_secondary_indexes" semantic conventions. It - // represents the JSON-serialized value of each item of the - // `LocalSecondaryIndexes` request field. - // - // Type: string[] - // RequirementLevel: Optional - // Stability: experimental - // Examples: '{ "IndexARN": "string", "IndexName": "string", - // "IndexSizeBytes": number, "ItemCount": number, "KeySchema": [ { - // "AttributeName": "string", "KeyType": "string" } ], "Projection": { - // "NonKeyAttributes": [ "string" ], "ProjectionType": "string" } }' - AWSDynamoDBLocalSecondaryIndexesKey = attribute.Key("aws.dynamodb.local_secondary_indexes") -) - -// AWSDynamoDBGlobalSecondaryIndexes returns an attribute KeyValue -// conforming to the "aws.dynamodb.global_secondary_indexes" semantic -// conventions. It represents the JSON-serialized value of each item of the -// `GlobalSecondaryIndexes` request field -func AWSDynamoDBGlobalSecondaryIndexes(val ...string) attribute.KeyValue { - return AWSDynamoDBGlobalSecondaryIndexesKey.StringSlice(val) -} - -// AWSDynamoDBLocalSecondaryIndexes returns an attribute KeyValue conforming -// to the "aws.dynamodb.local_secondary_indexes" semantic conventions. It -// represents the JSON-serialized value of each item of the -// `LocalSecondaryIndexes` request field. -func AWSDynamoDBLocalSecondaryIndexes(val ...string) attribute.KeyValue { - return AWSDynamoDBLocalSecondaryIndexesKey.StringSlice(val) -} - -// DynamoDB.ListTables -const ( - // AWSDynamoDBExclusiveStartTableKey is the attribute Key conforming to the - // "aws.dynamodb.exclusive_start_table" semantic conventions. It represents - // the value of the `ExclusiveStartTableName` request parameter. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'Users', 'CatsTable' - AWSDynamoDBExclusiveStartTableKey = attribute.Key("aws.dynamodb.exclusive_start_table") - - // AWSDynamoDBTableCountKey is the attribute Key conforming to the - // "aws.dynamodb.table_count" semantic conventions. It represents the the - // number of items in the `TableNames` response parameter. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 20 - AWSDynamoDBTableCountKey = attribute.Key("aws.dynamodb.table_count") -) - -// AWSDynamoDBExclusiveStartTable returns an attribute KeyValue conforming -// to the "aws.dynamodb.exclusive_start_table" semantic conventions. It -// represents the value of the `ExclusiveStartTableName` request parameter. -func AWSDynamoDBExclusiveStartTable(val string) attribute.KeyValue { - return AWSDynamoDBExclusiveStartTableKey.String(val) -} - -// AWSDynamoDBTableCount returns an attribute KeyValue conforming to the -// "aws.dynamodb.table_count" semantic conventions. It represents the the -// number of items in the `TableNames` response parameter. -func AWSDynamoDBTableCount(val int) attribute.KeyValue { - return AWSDynamoDBTableCountKey.Int(val) -} - -// DynamoDB.Query -const ( - // AWSDynamoDBScanForwardKey is the attribute Key conforming to the - // "aws.dynamodb.scan_forward" semantic conventions. It represents the - // value of the `ScanIndexForward` request parameter. - // - // Type: boolean - // RequirementLevel: Optional - // Stability: experimental - AWSDynamoDBScanForwardKey = attribute.Key("aws.dynamodb.scan_forward") -) - -// AWSDynamoDBScanForward returns an attribute KeyValue conforming to the -// "aws.dynamodb.scan_forward" semantic conventions. It represents the value of -// the `ScanIndexForward` request parameter. -func AWSDynamoDBScanForward(val bool) attribute.KeyValue { - return AWSDynamoDBScanForwardKey.Bool(val) -} - -// DynamoDB.Scan -const ( - // AWSDynamoDBCountKey is the attribute Key conforming to the - // "aws.dynamodb.count" semantic conventions. It represents the value of - // the `Count` response parameter. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 10 - AWSDynamoDBCountKey = attribute.Key("aws.dynamodb.count") - - // AWSDynamoDBScannedCountKey is the attribute Key conforming to the - // "aws.dynamodb.scanned_count" semantic conventions. It represents the - // value of the `ScannedCount` response parameter. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 50 - AWSDynamoDBScannedCountKey = attribute.Key("aws.dynamodb.scanned_count") - - // AWSDynamoDBSegmentKey is the attribute Key conforming to the - // "aws.dynamodb.segment" semantic conventions. It represents the value of - // the `Segment` request parameter. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 10 - AWSDynamoDBSegmentKey = attribute.Key("aws.dynamodb.segment") - - // AWSDynamoDBTotalSegmentsKey is the attribute Key conforming to the - // "aws.dynamodb.total_segments" semantic conventions. It represents the - // value of the `TotalSegments` request parameter. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 100 - AWSDynamoDBTotalSegmentsKey = attribute.Key("aws.dynamodb.total_segments") -) - -// AWSDynamoDBCount returns an attribute KeyValue conforming to the -// "aws.dynamodb.count" semantic conventions. It represents the value of the -// `Count` response parameter. -func AWSDynamoDBCount(val int) attribute.KeyValue { - return AWSDynamoDBCountKey.Int(val) -} - -// AWSDynamoDBScannedCount returns an attribute KeyValue conforming to the -// "aws.dynamodb.scanned_count" semantic conventions. It represents the value -// of the `ScannedCount` response parameter. -func AWSDynamoDBScannedCount(val int) attribute.KeyValue { - return AWSDynamoDBScannedCountKey.Int(val) -} - -// AWSDynamoDBSegment returns an attribute KeyValue conforming to the -// "aws.dynamodb.segment" semantic conventions. It represents the value of the -// `Segment` request parameter. -func AWSDynamoDBSegment(val int) attribute.KeyValue { - return AWSDynamoDBSegmentKey.Int(val) -} - -// AWSDynamoDBTotalSegments returns an attribute KeyValue conforming to the -// "aws.dynamodb.total_segments" semantic conventions. It represents the value -// of the `TotalSegments` request parameter. -func AWSDynamoDBTotalSegments(val int) attribute.KeyValue { - return AWSDynamoDBTotalSegmentsKey.Int(val) -} - -// DynamoDB.UpdateTable -const ( - // AWSDynamoDBAttributeDefinitionsKey is the attribute Key conforming to - // the "aws.dynamodb.attribute_definitions" semantic conventions. It - // represents the JSON-serialized value of each item in the - // `AttributeDefinitions` request field. - // - // Type: string[] - // RequirementLevel: Optional - // Stability: experimental - // Examples: '{ "AttributeName": "string", "AttributeType": "string" }' - AWSDynamoDBAttributeDefinitionsKey = attribute.Key("aws.dynamodb.attribute_definitions") - - // AWSDynamoDBGlobalSecondaryIndexUpdatesKey is the attribute Key - // conforming to the "aws.dynamodb.global_secondary_index_updates" semantic - // conventions. It represents the JSON-serialized value of each item in the - // the `GlobalSecondaryIndexUpdates` request field. - // - // Type: string[] - // RequirementLevel: Optional - // Stability: experimental - // Examples: '{ "Create": { "IndexName": "string", "KeySchema": [ { - // "AttributeName": "string", "KeyType": "string" } ], "Projection": { - // "NonKeyAttributes": [ "string" ], "ProjectionType": "string" }, - // "ProvisionedThroughput": { "ReadCapacityUnits": number, - // "WriteCapacityUnits": number } }' - AWSDynamoDBGlobalSecondaryIndexUpdatesKey = attribute.Key("aws.dynamodb.global_secondary_index_updates") -) - -// AWSDynamoDBAttributeDefinitions returns an attribute KeyValue conforming -// to the "aws.dynamodb.attribute_definitions" semantic conventions. It -// represents the JSON-serialized value of each item in the -// `AttributeDefinitions` request field. -func AWSDynamoDBAttributeDefinitions(val ...string) attribute.KeyValue { - return AWSDynamoDBAttributeDefinitionsKey.StringSlice(val) -} - -// AWSDynamoDBGlobalSecondaryIndexUpdates returns an attribute KeyValue -// conforming to the "aws.dynamodb.global_secondary_index_updates" semantic -// conventions. It represents the JSON-serialized value of each item in the the -// `GlobalSecondaryIndexUpdates` request field. -func AWSDynamoDBGlobalSecondaryIndexUpdates(val ...string) attribute.KeyValue { - return AWSDynamoDBGlobalSecondaryIndexUpdatesKey.StringSlice(val) -} - -// Attributes that exist for S3 request types. -const ( - // AWSS3BucketKey is the attribute Key conforming to the "aws.s3.bucket" - // semantic conventions. It represents the S3 bucket name the request - // refers to. Corresponds to the `--bucket` parameter of the [S3 - // API](https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html) - // operations. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'some-bucket-name' - // Note: The `bucket` attribute is applicable to all S3 operations that - // reference a bucket, i.e. that require the bucket name as a mandatory - // parameter. - // This applies to almost all S3 operations except `list-buckets`. - AWSS3BucketKey = attribute.Key("aws.s3.bucket") - - // AWSS3CopySourceKey is the attribute Key conforming to the - // "aws.s3.copy_source" semantic conventions. It represents the source - // object (in the form `bucket`/`key`) for the copy operation. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'someFile.yml' - // Note: The `copy_source` attribute applies to S3 copy operations and - // corresponds to the `--copy-source` parameter - // of the [copy-object operation within the S3 - // API](https://docs.aws.amazon.com/cli/latest/reference/s3api/copy-object.html). - // This applies in particular to the following operations: - // - // - - // [copy-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/copy-object.html) - // - - // [upload-part-copy](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html) - AWSS3CopySourceKey = attribute.Key("aws.s3.copy_source") - - // AWSS3DeleteKey is the attribute Key conforming to the "aws.s3.delete" - // semantic conventions. It represents the delete request container that - // specifies the objects to be deleted. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: - // 'Objects=[{Key=string,VersionID=string},{Key=string,VersionID=string}],Quiet=boolean' - // Note: The `delete` attribute is only applicable to the - // [delete-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/delete-object.html) - // operation. - // The `delete` attribute corresponds to the `--delete` parameter of the - // [delete-objects operation within the S3 - // API](https://docs.aws.amazon.com/cli/latest/reference/s3api/delete-objects.html). - AWSS3DeleteKey = attribute.Key("aws.s3.delete") - - // AWSS3KeyKey is the attribute Key conforming to the "aws.s3.key" semantic - // conventions. It represents the S3 object key the request refers to. - // Corresponds to the `--key` parameter of the [S3 - // API](https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html) - // operations. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'someFile.yml' - // Note: The `key` attribute is applicable to all object-related S3 - // operations, i.e. that require the object key as a mandatory parameter. - // This applies in particular to the following operations: - // - // - - // [copy-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/copy-object.html) - // - - // [delete-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/delete-object.html) - // - - // [get-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/get-object.html) - // - - // [head-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/head-object.html) - // - - // [put-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/put-object.html) - // - - // [restore-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/restore-object.html) - // - - // [select-object-content](https://docs.aws.amazon.com/cli/latest/reference/s3api/select-object-content.html) - // - - // [abort-multipart-upload](https://docs.aws.amazon.com/cli/latest/reference/s3api/abort-multipart-upload.html) - // - - // [complete-multipart-upload](https://docs.aws.amazon.com/cli/latest/reference/s3api/complete-multipart-upload.html) - // - - // [create-multipart-upload](https://docs.aws.amazon.com/cli/latest/reference/s3api/create-multipart-upload.html) - // - - // [list-parts](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-parts.html) - // - - // [upload-part](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html) - // - - // [upload-part-copy](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html) - AWSS3KeyKey = attribute.Key("aws.s3.key") - - // AWSS3PartNumberKey is the attribute Key conforming to the - // "aws.s3.part_number" semantic conventions. It represents the part number - // of the part being uploaded in a multipart-upload operation. This is a - // positive integer between 1 and 10,000. - // - // Type: int - // RequirementLevel: Optional - // Stability: experimental - // Examples: 3456 - // Note: The `part_number` attribute is only applicable to the - // [upload-part](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html) - // and - // [upload-part-copy](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html) - // operations. - // The `part_number` attribute corresponds to the `--part-number` parameter - // of the - // [upload-part operation within the S3 - // API](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html). - AWSS3PartNumberKey = attribute.Key("aws.s3.part_number") - - // AWSS3UploadIDKey is the attribute Key conforming to the - // "aws.s3.upload_id" semantic conventions. It represents the upload ID - // that identifies the multipart upload. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'dfRtDYWFbkRONycy.Yxwh66Yjlx.cph0gtNBtJ' - // Note: The `upload_id` attribute applies to S3 multipart-upload - // operations and corresponds to the `--upload-id` parameter - // of the [S3 - // API](https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html) - // multipart operations. - // This applies in particular to the following operations: - // - // - - // [abort-multipart-upload](https://docs.aws.amazon.com/cli/latest/reference/s3api/abort-multipart-upload.html) - // - - // [complete-multipart-upload](https://docs.aws.amazon.com/cli/latest/reference/s3api/complete-multipart-upload.html) - // - - // [list-parts](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-parts.html) - // - - // [upload-part](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html) - // - - // [upload-part-copy](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html) - AWSS3UploadIDKey = attribute.Key("aws.s3.upload_id") -) - -// AWSS3Bucket returns an attribute KeyValue conforming to the -// "aws.s3.bucket" semantic conventions. It represents the S3 bucket name the -// request refers to. Corresponds to the `--bucket` parameter of the [S3 -// API](https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html) -// operations. -func AWSS3Bucket(val string) attribute.KeyValue { - return AWSS3BucketKey.String(val) -} - -// AWSS3CopySource returns an attribute KeyValue conforming to the -// "aws.s3.copy_source" semantic conventions. It represents the source object -// (in the form `bucket`/`key`) for the copy operation. -func AWSS3CopySource(val string) attribute.KeyValue { - return AWSS3CopySourceKey.String(val) -} - -// AWSS3Delete returns an attribute KeyValue conforming to the -// "aws.s3.delete" semantic conventions. It represents the delete request -// container that specifies the objects to be deleted. -func AWSS3Delete(val string) attribute.KeyValue { - return AWSS3DeleteKey.String(val) -} - -// AWSS3Key returns an attribute KeyValue conforming to the "aws.s3.key" -// semantic conventions. It represents the S3 object key the request refers to. -// Corresponds to the `--key` parameter of the [S3 -// API](https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html) -// operations. -func AWSS3Key(val string) attribute.KeyValue { - return AWSS3KeyKey.String(val) -} - -// AWSS3PartNumber returns an attribute KeyValue conforming to the -// "aws.s3.part_number" semantic conventions. It represents the part number of -// the part being uploaded in a multipart-upload operation. This is a positive -// integer between 1 and 10,000. -func AWSS3PartNumber(val int) attribute.KeyValue { - return AWSS3PartNumberKey.Int(val) -} - -// AWSS3UploadID returns an attribute KeyValue conforming to the -// "aws.s3.upload_id" semantic conventions. It represents the upload ID that -// identifies the multipart upload. -func AWSS3UploadID(val string) attribute.KeyValue { - return AWSS3UploadIDKey.String(val) -} - -// Semantic conventions to apply when instrumenting the GraphQL implementation. -// They map GraphQL operations to attributes on a Span. -const ( - // GraphqlDocumentKey is the attribute Key conforming to the - // "graphql.document" semantic conventions. It represents the GraphQL - // document being executed. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'query findBookByID { bookByID(id: ?) { name } }' - // Note: The value may be sanitized to exclude sensitive information. - GraphqlDocumentKey = attribute.Key("graphql.document") - - // GraphqlOperationNameKey is the attribute Key conforming to the - // "graphql.operation.name" semantic conventions. It represents the name of - // the operation being executed. - // - // Type: string - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'findBookByID' - GraphqlOperationNameKey = attribute.Key("graphql.operation.name") - - // GraphqlOperationTypeKey is the attribute Key conforming to the - // "graphql.operation.type" semantic conventions. It represents the type of - // the operation being executed. - // - // Type: Enum - // RequirementLevel: Optional - // Stability: experimental - // Examples: 'query', 'mutation', 'subscription' - GraphqlOperationTypeKey = attribute.Key("graphql.operation.type") -) - -var ( - // GraphQL query - GraphqlOperationTypeQuery = GraphqlOperationTypeKey.String("query") - // GraphQL mutation - GraphqlOperationTypeMutation = GraphqlOperationTypeKey.String("mutation") - // GraphQL subscription - GraphqlOperationTypeSubscription = GraphqlOperationTypeKey.String("subscription") -) - -// GraphqlDocument returns an attribute KeyValue conforming to the -// "graphql.document" semantic conventions. It represents the GraphQL document -// being executed. -func GraphqlDocument(val string) attribute.KeyValue { - return GraphqlDocumentKey.String(val) -} - -// GraphqlOperationName returns an attribute KeyValue conforming to the -// "graphql.operation.name" semantic conventions. It represents the name of the -// operation being executed. -func GraphqlOperationName(val string) attribute.KeyValue { - return GraphqlOperationNameKey.String(val) -} diff --git a/vendor/go.opentelemetry.io/otel/version.go b/vendor/go.opentelemetry.io/otel/version.go index fb7d12673e..eb22002d82 100644 --- a/vendor/go.opentelemetry.io/otel/version.go +++ b/vendor/go.opentelemetry.io/otel/version.go @@ -5,5 +5,5 @@ package otel // import "go.opentelemetry.io/otel" // Version is the current release version of OpenTelemetry in use. func Version() string { - return "1.33.0" + return "1.34.0" } diff --git a/vendor/go.opentelemetry.io/otel/versions.yaml b/vendor/go.opentelemetry.io/otel/versions.yaml index 9f878cd1fe..ce4fe59b0e 100644 --- a/vendor/go.opentelemetry.io/otel/versions.yaml +++ b/vendor/go.opentelemetry.io/otel/versions.yaml @@ -3,7 +3,7 @@ module-sets: stable-v1: - version: v1.33.0 + version: v1.34.0 modules: - go.opentelemetry.io/otel - go.opentelemetry.io/otel/bridge/opencensus @@ -23,11 +23,11 @@ module-sets: - go.opentelemetry.io/otel/sdk/metric - go.opentelemetry.io/otel/trace experimental-metrics: - version: v0.55.0 + version: v0.56.0 modules: - go.opentelemetry.io/otel/exporters/prometheus experimental-logs: - version: v0.9.0 + version: v0.10.0 modules: - go.opentelemetry.io/otel/log - go.opentelemetry.io/otel/sdk/log diff --git a/vendor/golang.org/x/oauth2/oauth2.go b/vendor/golang.org/x/oauth2/oauth2.go index 09f6a49b80..74f052aa9f 100644 --- a/vendor/golang.org/x/oauth2/oauth2.go +++ b/vendor/golang.org/x/oauth2/oauth2.go @@ -56,7 +56,7 @@ type Config struct { // the OAuth flow, after the resource owner's URLs. RedirectURL string - // Scope specifies optional requested permissions. + // Scopes specifies optional requested permissions. Scopes []string // authStyleCache caches which auth style to use when Endpoint.AuthStyle is diff --git a/vendor/google.golang.org/grpc/version.go b/vendor/google.golang.org/grpc/version.go index 6cbe116f24..d2bba7f3d9 100644 --- a/vendor/google.golang.org/grpc/version.go +++ b/vendor/google.golang.org/grpc/version.go @@ -19,4 +19,4 @@ package grpc // Version is the current grpc version. -const Version = "1.69.2" +const Version = "1.69.4" diff --git a/vendor/google.golang.org/protobuf/encoding/protojson/decode.go b/vendor/google.golang.org/protobuf/encoding/protojson/decode.go index 8f9e592f87..cffdfda961 100644 --- a/vendor/google.golang.org/protobuf/encoding/protojson/decode.go +++ b/vendor/google.golang.org/protobuf/encoding/protojson/decode.go @@ -192,7 +192,7 @@ func (d decoder) unmarshalMessage(m protoreflect.Message, skipTypeURL bool) erro fd = fieldDescs.ByTextName(name) } } - if flags.ProtoLegacy { + if flags.ProtoLegacyWeak { if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() { fd = nil // reset since the weak reference is not linked in } diff --git a/vendor/google.golang.org/protobuf/encoding/prototext/decode.go b/vendor/google.golang.org/protobuf/encoding/prototext/decode.go index 24bc98ac42..d972a3d98e 100644 --- a/vendor/google.golang.org/protobuf/encoding/prototext/decode.go +++ b/vendor/google.golang.org/protobuf/encoding/prototext/decode.go @@ -185,7 +185,7 @@ func (d decoder) unmarshalMessage(m protoreflect.Message, checkDelims bool) erro } else if xtErr != nil && xtErr != protoregistry.NotFound { return d.newError(tok.Pos(), "unable to resolve [%s]: %v", tok.RawString(), xtErr) } - if flags.ProtoLegacy { + if flags.ProtoLegacyWeak { if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() { fd = nil // reset since the weak reference is not linked in } diff --git a/vendor/google.golang.org/protobuf/internal/flags/flags.go b/vendor/google.golang.org/protobuf/internal/flags/flags.go index 58372dd348..5cb3ee70f9 100644 --- a/vendor/google.golang.org/protobuf/internal/flags/flags.go +++ b/vendor/google.golang.org/protobuf/internal/flags/flags.go @@ -22,3 +22,8 @@ const ProtoLegacy = protoLegacy // extension fields at unmarshal time, but defers creating the message // structure until the extension is first accessed. const LazyUnmarshalExtensions = ProtoLegacy + +// ProtoLegacyWeak specifies whether to enable support for weak fields. +// This flag was split out of ProtoLegacy in preparation for removing +// support for weak fields (independent of the other protolegacy features). +const ProtoLegacyWeak = ProtoLegacy diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_map.go b/vendor/google.golang.org/protobuf/internal/impl/codec_map.go index fb35f0bae9..229c698013 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/codec_map.go +++ b/vendor/google.golang.org/protobuf/internal/impl/codec_map.go @@ -94,7 +94,7 @@ func sizeMap(mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalO return 0 } n := 0 - iter := mapRange(mapv) + iter := mapv.MapRange() for iter.Next() { key := mapi.conv.keyConv.PBValueOf(iter.Key()).MapKey() keySize := mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts) @@ -281,7 +281,7 @@ func appendMap(b []byte, mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, o if opts.Deterministic() { return appendMapDeterministic(b, mapv, mapi, f, opts) } - iter := mapRange(mapv) + iter := mapv.MapRange() for iter.Next() { var err error b = protowire.AppendVarint(b, f.wiretag) @@ -328,7 +328,7 @@ func isInitMap(mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo) error { if !mi.needsInitCheck { return nil } - iter := mapRange(mapv) + iter := mapv.MapRange() for iter.Next() { val := pointerOfValue(iter.Value()) if err := mi.checkInitializedPointer(val); err != nil { @@ -336,7 +336,7 @@ func isInitMap(mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo) error { } } } else { - iter := mapRange(mapv) + iter := mapv.MapRange() for iter.Next() { val := mapi.conv.valConv.PBValueOf(iter.Value()) if err := mapi.valFuncs.isInit(val); err != nil { @@ -356,7 +356,7 @@ func mergeMap(dst, src pointer, f *coderFieldInfo, opts mergeOptions) { if dstm.IsNil() { dstm.Set(reflect.MakeMap(f.ft)) } - iter := mapRange(srcm) + iter := srcm.MapRange() for iter.Next() { dstm.SetMapIndex(iter.Key(), iter.Value()) } @@ -371,7 +371,7 @@ func mergeMapOfBytes(dst, src pointer, f *coderFieldInfo, opts mergeOptions) { if dstm.IsNil() { dstm.Set(reflect.MakeMap(f.ft)) } - iter := mapRange(srcm) + iter := srcm.MapRange() for iter.Next() { dstm.SetMapIndex(iter.Key(), reflect.ValueOf(append(emptyBuf[:], iter.Value().Bytes()...))) } @@ -386,7 +386,7 @@ func mergeMapOfMessage(dst, src pointer, f *coderFieldInfo, opts mergeOptions) { if dstm.IsNil() { dstm.Set(reflect.MakeMap(f.ft)) } - iter := mapRange(srcm) + iter := srcm.MapRange() for iter.Next() { val := reflect.New(f.ft.Elem().Elem()) if f.mi != nil { diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_map_go111.go b/vendor/google.golang.org/protobuf/internal/impl/codec_map_go111.go deleted file mode 100644 index 4b15493f2f..0000000000 --- a/vendor/google.golang.org/protobuf/internal/impl/codec_map_go111.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.12 -// +build !go1.12 - -package impl - -import "reflect" - -type mapIter struct { - v reflect.Value - keys []reflect.Value -} - -// mapRange provides a less-efficient equivalent to -// the Go 1.12 reflect.Value.MapRange method. -func mapRange(v reflect.Value) *mapIter { - return &mapIter{v: v} -} - -func (i *mapIter) Next() bool { - if i.keys == nil { - i.keys = i.v.MapKeys() - } else { - i.keys = i.keys[1:] - } - return len(i.keys) > 0 -} - -func (i *mapIter) Key() reflect.Value { - return i.keys[0] -} - -func (i *mapIter) Value() reflect.Value { - return i.v.MapIndex(i.keys[0]) -} diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_map_go112.go b/vendor/google.golang.org/protobuf/internal/impl/codec_map_go112.go deleted file mode 100644 index 0b31b66eaf..0000000000 --- a/vendor/google.golang.org/protobuf/internal/impl/codec_map_go112.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.12 -// +build go1.12 - -package impl - -import "reflect" - -func mapRange(v reflect.Value) *reflect.MapIter { return v.MapRange() } diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_message.go b/vendor/google.golang.org/protobuf/internal/impl/codec_message.go index 2f7b363ec4..111d95833d 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/codec_message.go +++ b/vendor/google.golang.org/protobuf/internal/impl/codec_message.go @@ -118,12 +118,12 @@ func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) { }, } case isOneof: - fieldOffset = offsetOf(fs, mi.Exporter) + fieldOffset = offsetOf(fs) case fd.IsWeak(): fieldOffset = si.weakOffset funcs = makeWeakMessageFieldCoder(fd) default: - fieldOffset = offsetOf(fs, mi.Exporter) + fieldOffset = offsetOf(fs) childMessage, funcs = fieldCoder(fd, ft) } cf := &preallocFields[i] diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go b/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go index 88c16ae5b7..f81d7d0db9 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go +++ b/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go @@ -45,19 +45,19 @@ func (mi *MessageInfo) makeOpaqueCoderMethods(t reflect.Type, si opaqueStructInf var childMessage *MessageInfo switch { case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic(): - fieldOffset = offsetOf(fs, mi.Exporter) + fieldOffset = offsetOf(fs) case fd.IsWeak(): fieldOffset = si.weakOffset funcs = makeWeakMessageFieldCoder(fd) case fd.Message() != nil && !fd.IsMap(): - fieldOffset = offsetOf(fs, mi.Exporter) + fieldOffset = offsetOf(fs) if fd.IsList() { childMessage, funcs = makeOpaqueRepeatedMessageFieldCoder(fd, ft) } else { childMessage, funcs = makeOpaqueMessageFieldCoder(fd, ft) } default: - fieldOffset = offsetOf(fs, mi.Exporter) + fieldOffset = offsetOf(fs) childMessage, funcs = fieldCoder(fd, ft) } cf := &coderFieldInfo{ diff --git a/vendor/google.golang.org/protobuf/internal/impl/convert_map.go b/vendor/google.golang.org/protobuf/internal/impl/convert_map.go index 304244a651..e4580b3ac2 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/convert_map.go +++ b/vendor/google.golang.org/protobuf/internal/impl/convert_map.go @@ -101,7 +101,7 @@ func (ms *mapReflect) Mutable(k protoreflect.MapKey) protoreflect.Value { return v } func (ms *mapReflect) Range(f func(protoreflect.MapKey, protoreflect.Value) bool) { - iter := mapRange(ms.v) + iter := ms.v.MapRange() for iter.Next() { k := ms.keyConv.PBValueOf(iter.Key()).MapKey() v := ms.valConv.PBValueOf(iter.Value()) diff --git a/vendor/google.golang.org/protobuf/internal/impl/message.go b/vendor/google.golang.org/protobuf/internal/impl/message.go index fa10a0f5cc..d1f79b4224 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/message.go +++ b/vendor/google.golang.org/protobuf/internal/impl/message.go @@ -165,28 +165,28 @@ fieldLoop: switch f := t.Field(i); f.Name { case genid.SizeCache_goname, genid.SizeCacheA_goname: if f.Type == sizecacheType { - si.sizecacheOffset = offsetOf(f, mi.Exporter) + si.sizecacheOffset = offsetOf(f) si.sizecacheType = f.Type } case genid.WeakFields_goname, genid.WeakFieldsA_goname: if f.Type == weakFieldsType { - si.weakOffset = offsetOf(f, mi.Exporter) + si.weakOffset = offsetOf(f) si.weakType = f.Type } case genid.UnknownFields_goname, genid.UnknownFieldsA_goname: if f.Type == unknownFieldsAType || f.Type == unknownFieldsBType { - si.unknownOffset = offsetOf(f, mi.Exporter) + si.unknownOffset = offsetOf(f) si.unknownType = f.Type } case genid.ExtensionFields_goname, genid.ExtensionFieldsA_goname, genid.ExtensionFieldsB_goname: if f.Type == extensionFieldsType { - si.extensionOffset = offsetOf(f, mi.Exporter) + si.extensionOffset = offsetOf(f) si.extensionType = f.Type } case "lazyFields", "XXX_lazyUnmarshalInfo": - si.lazyOffset = offsetOf(f, mi.Exporter) + si.lazyOffset = offsetOf(f) case "XXX_presence": - si.presenceOffset = offsetOf(f, mi.Exporter) + si.presenceOffset = offsetOf(f) default: for _, s := range strings.Split(f.Tag.Get("protobuf"), ",") { if len(s) > 0 && strings.Trim(s, "0123456789") == "" { diff --git a/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go b/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go index d7ec53f074..d8dcd78863 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go +++ b/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go @@ -142,7 +142,7 @@ func (mi *MessageInfo) fieldInfoForMapOpaque(si opaqueStructInfo, fd protoreflec if ft.Kind() != reflect.Map { panic(fmt.Sprintf("invalid type: got %v, want map kind", ft)) } - fieldOffset := offsetOf(fs, mi.Exporter) + fieldOffset := offsetOf(fs) conv := NewConverter(ft, fd) return fieldInfo{ fieldDesc: fd, @@ -196,7 +196,7 @@ func (mi *MessageInfo) fieldInfoForScalarListOpaque(si opaqueStructInfo, fd prot panic(fmt.Sprintf("invalid type: got %v, want slice kind", ft)) } conv := NewConverter(reflect.PtrTo(ft), fd) - fieldOffset := offsetOf(fs, mi.Exporter) + fieldOffset := offsetOf(fs) index, _ := presenceIndex(mi.Desc, fd) return fieldInfo{ fieldDesc: fd, @@ -246,7 +246,7 @@ func (mi *MessageInfo) fieldInfoForMessageListOpaque(si opaqueStructInfo, fd pro panic(fmt.Sprintf("invalid type: got %v, want slice kind", ft)) } conv := NewConverter(ft, fd) - fieldOffset := offsetOf(fs, mi.Exporter) + fieldOffset := offsetOf(fs) index, _ := presenceIndex(mi.Desc, fd) fieldNumber := fd.Number() return fieldInfo{ @@ -339,7 +339,7 @@ func (mi *MessageInfo) fieldInfoForMessageListOpaqueNoPresence(si opaqueStructIn panic(fmt.Sprintf("invalid type: got %v, want slice kind", ft)) } conv := NewConverter(ft, fd) - fieldOffset := offsetOf(fs, mi.Exporter) + fieldOffset := offsetOf(fs) return fieldInfo{ fieldDesc: fd, has: func(p pointer) bool { @@ -411,7 +411,7 @@ func (mi *MessageInfo) fieldInfoForScalarOpaque(si opaqueStructInfo, fd protoref deref = true } conv := NewConverter(ft, fd) - fieldOffset := offsetOf(fs, mi.Exporter) + fieldOffset := offsetOf(fs) index, _ := presenceIndex(mi.Desc, fd) var getter func(p pointer) protoreflect.Value if !nullable { @@ -480,7 +480,7 @@ func (mi *MessageInfo) fieldInfoForScalarOpaque(si opaqueStructInfo, fd protoref func (mi *MessageInfo) fieldInfoForMessageOpaque(si opaqueStructInfo, fd protoreflect.FieldDescriptor, fs reflect.StructField) fieldInfo { ft := fs.Type conv := NewConverter(ft, fd) - fieldOffset := offsetOf(fs, mi.Exporter) + fieldOffset := offsetOf(fs) index, _ := presenceIndex(mi.Desc, fd) fieldNumber := fd.Number() elemType := fs.Type.Elem() diff --git a/vendor/google.golang.org/protobuf/internal/impl/message_reflect_field.go b/vendor/google.golang.org/protobuf/internal/impl/message_reflect_field.go index a740646205..3cd1fbc21f 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/message_reflect_field.go +++ b/vendor/google.golang.org/protobuf/internal/impl/message_reflect_field.go @@ -76,7 +76,7 @@ func fieldInfoForOneof(fd protoreflect.FieldDescriptor, fs reflect.StructField, isMessage := fd.Message() != nil // TODO: Implement unsafe fast path? - fieldOffset := offsetOf(fs, x) + fieldOffset := offsetOf(fs) return fieldInfo{ // NOTE: The logic below intentionally assumes that oneof fields are // well-formatted. That is, the oneof interface never contains a @@ -152,7 +152,7 @@ func fieldInfoForMap(fd protoreflect.FieldDescriptor, fs reflect.StructField, x conv := NewConverter(ft, fd) // TODO: Implement unsafe fast path? - fieldOffset := offsetOf(fs, x) + fieldOffset := offsetOf(fs) return fieldInfo{ fieldDesc: fd, has: func(p pointer) bool { @@ -205,7 +205,7 @@ func fieldInfoForList(fd protoreflect.FieldDescriptor, fs reflect.StructField, x conv := NewConverter(reflect.PtrTo(ft), fd) // TODO: Implement unsafe fast path? - fieldOffset := offsetOf(fs, x) + fieldOffset := offsetOf(fs) return fieldInfo{ fieldDesc: fd, has: func(p pointer) bool { @@ -269,7 +269,7 @@ func fieldInfoForScalar(fd protoreflect.FieldDescriptor, fs reflect.StructField, } } conv := NewConverter(ft, fd) - fieldOffset := offsetOf(fs, x) + fieldOffset := offsetOf(fs) // Generate specialized getter functions to avoid going through reflect.Value if nullable { @@ -333,7 +333,7 @@ func fieldInfoForScalar(fd protoreflect.FieldDescriptor, fs reflect.StructField, } func fieldInfoForWeakMessage(fd protoreflect.FieldDescriptor, weakOffset offset) fieldInfo { - if !flags.ProtoLegacy { + if !flags.ProtoLegacyWeak { panic("no support for proto1 weak fields") } @@ -410,7 +410,7 @@ func fieldInfoForMessage(fd protoreflect.FieldDescriptor, fs reflect.StructField conv := NewConverter(ft, fd) // TODO: Implement unsafe fast path? - fieldOffset := offsetOf(fs, x) + fieldOffset := offsetOf(fs) return fieldInfo{ fieldDesc: fd, has: func(p pointer) bool { @@ -419,7 +419,7 @@ func fieldInfoForMessage(fd protoreflect.FieldDescriptor, fs reflect.StructField } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if fs.Type.Kind() != reflect.Ptr { - return !isZero(rv) + return !rv.IsZero() } return !rv.IsNil() }, @@ -466,7 +466,7 @@ func makeOneofInfo(od protoreflect.OneofDescriptor, si structInfo, x exporter) * oi := &oneofInfo{oneofDesc: od} if od.IsSynthetic() { fs := si.fieldsByNumber[od.Fields().Get(0).Number()] - fieldOffset := offsetOf(fs, x) + fieldOffset := offsetOf(fs) oi.which = func(p pointer) protoreflect.FieldNumber { if p.IsNil() { return 0 @@ -479,7 +479,7 @@ func makeOneofInfo(od protoreflect.OneofDescriptor, si structInfo, x exporter) * } } else { fs := si.oneofsByName[od.Name()] - fieldOffset := offsetOf(fs, x) + fieldOffset := offsetOf(fs) oi.which = func(p pointer) protoreflect.FieldNumber { if p.IsNil() { return 0 @@ -497,41 +497,3 @@ func makeOneofInfo(od protoreflect.OneofDescriptor, si structInfo, x exporter) * } return oi } - -// isZero is identical to reflect.Value.IsZero. -// TODO: Remove this when Go1.13 is the minimally supported Go version. -func isZero(v reflect.Value) bool { - switch v.Kind() { - case reflect.Bool: - return !v.Bool() - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return v.Int() == 0 - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return v.Uint() == 0 - case reflect.Float32, reflect.Float64: - return math.Float64bits(v.Float()) == 0 - case reflect.Complex64, reflect.Complex128: - c := v.Complex() - return math.Float64bits(real(c)) == 0 && math.Float64bits(imag(c)) == 0 - case reflect.Array: - for i := 0; i < v.Len(); i++ { - if !isZero(v.Index(i)) { - return false - } - } - return true - case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer: - return v.IsNil() - case reflect.String: - return v.Len() == 0 - case reflect.Struct: - for i := 0; i < v.NumField(); i++ { - if !isZero(v.Field(i)) { - return false - } - } - return true - default: - panic(&reflect.ValueError{Method: "reflect.Value.IsZero", Kind: v.Kind()}) - } -} diff --git a/vendor/google.golang.org/protobuf/internal/impl/pointer_unsafe.go b/vendor/google.golang.org/protobuf/internal/impl/pointer_unsafe.go index 041ebde2de..6bed45e35c 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/pointer_unsafe.go +++ b/vendor/google.golang.org/protobuf/internal/impl/pointer_unsafe.go @@ -22,7 +22,7 @@ type Pointer unsafe.Pointer type offset uintptr // offsetOf returns a field offset for the struct field. -func offsetOf(f reflect.StructField, x exporter) offset { +func offsetOf(f reflect.StructField) offset { return offset(f.Offset) } diff --git a/vendor/google.golang.org/protobuf/internal/version/version.go b/vendor/google.golang.org/protobuf/internal/version/version.go index 386c823aa6..f5c06280fe 100644 --- a/vendor/google.golang.org/protobuf/internal/version/version.go +++ b/vendor/google.golang.org/protobuf/internal/version/version.go @@ -52,7 +52,7 @@ import ( const ( Major = 1 Minor = 36 - Patch = 2 + Patch = 3 PreRelease = "" ) diff --git a/vendor/google.golang.org/protobuf/proto/decode.go b/vendor/google.golang.org/protobuf/proto/decode.go index a3b5e142d2..e28d7acb37 100644 --- a/vendor/google.golang.org/protobuf/proto/decode.go +++ b/vendor/google.golang.org/protobuf/proto/decode.go @@ -172,7 +172,7 @@ func (o UnmarshalOptions) unmarshalMessageSlow(b []byte, m protoreflect.Message) var err error if fd == nil { err = errUnknown - } else if flags.ProtoLegacy { + } else if flags.ProtoLegacyWeak { if fd.IsWeak() && fd.Message().IsPlaceholder() { err = errUnknown // weak referent is not linked in } diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go index 6de31c2ebd..5eaf652176 100644 --- a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go +++ b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go @@ -149,7 +149,7 @@ func validateMessageDeclarations(file *filedesc.File, ms []filedesc.Message, mds return errors.New("message field %q under proto3 optional semantics must be within a single element oneof", f.FullName()) } } - if f.IsWeak() && !flags.ProtoLegacy { + if f.IsWeak() && !flags.ProtoLegacyWeak { return errors.New("message field %q is a weak field, which is a legacy proto1 feature that is no longer supported", f.FullName()) } if f.IsWeak() && (!f.HasPresence() || !isOptionalMessage(f) || f.ContainingOneof() != nil) { diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/editions.go b/vendor/google.golang.org/protobuf/reflect/protodesc/editions.go index bf0a0ccdee..f55b036959 100644 --- a/vendor/google.golang.org/protobuf/reflect/protodesc/editions.go +++ b/vendor/google.golang.org/protobuf/reflect/protodesc/editions.go @@ -125,16 +125,27 @@ func mergeEditionFeatures(parentDesc protoreflect.Descriptor, child *descriptorp parentFS.IsJSONCompliant = *jf == descriptorpb.FeatureSet_ALLOW } - if goFeatures, ok := proto.GetExtension(child, gofeaturespb.E_Go).(*gofeaturespb.GoFeatures); ok && goFeatures != nil { - if luje := goFeatures.LegacyUnmarshalJsonEnum; luje != nil { - parentFS.GenerateLegacyUnmarshalJSON = *luje - } - if sep := goFeatures.StripEnumPrefix; sep != nil { - parentFS.StripEnumPrefix = int(*sep) - } - if al := goFeatures.ApiLevel; al != nil { - parentFS.APILevel = int(*al) - } + // We must not use proto.GetExtension(child, gofeaturespb.E_Go) + // because that only works for messages we generated, but not for + // dynamicpb messages. See golang/protobuf#1669. + goFeatures := child.ProtoReflect().Get(gofeaturespb.E_Go.TypeDescriptor()) + if !goFeatures.IsValid() { + return parentFS + } + // gf.Interface() could be *dynamicpb.Message or *gofeaturespb.GoFeatures. + gf := goFeatures.Message() + fields := gf.Descriptor().Fields() + + if fd := fields.ByName("legacy_unmarshal_json_enum"); gf.Has(fd) { + parentFS.GenerateLegacyUnmarshalJSON = gf.Get(fd).Bool() + } + + if fd := fields.ByName("strip_enum_prefix"); gf.Has(fd) { + parentFS.StripEnumPrefix = int(gf.Get(fd).Enum()) + } + + if fd := fields.ByName("api_level"); gf.Has(fd) { + parentFS.APILevel = int(gf.Get(fd).Enum()) } return parentFS diff --git a/vendor/helm.sh/helm/v3/internal/version/version.go b/vendor/helm.sh/helm/v3/internal/version/version.go index 539659f5ed..4124100ae1 100644 --- a/vendor/helm.sh/helm/v3/internal/version/version.go +++ b/vendor/helm.sh/helm/v3/internal/version/version.go @@ -29,7 +29,7 @@ var ( // // Increment major number for new feature additions and behavioral changes. // Increment minor number for bug fixes and performance enhancements. - version = "v3.16" + version = "v3.17" // metadata is extra build time data metadata = "" diff --git a/vendor/helm.sh/helm/v3/pkg/action/dependency.go b/vendor/helm.sh/helm/v3/pkg/action/dependency.go index 3265f1f175..19305fee88 100644 --- a/vendor/helm.sh/helm/v3/pkg/action/dependency.go +++ b/vendor/helm.sh/helm/v3/pkg/action/dependency.go @@ -34,10 +34,17 @@ import ( // // It provides the implementation of 'helm dependency' and its respective subcommands. type Dependency struct { - Verify bool - Keyring string - SkipRefresh bool - ColumnWidth uint + Verify bool + Keyring string + SkipRefresh bool + ColumnWidth uint + Username string + Password string + CertFile string + KeyFile string + CaFile string + InsecureSkipTLSverify bool + PlainHTTP bool } // NewDependency creates a new Dependency object with the given configuration. diff --git a/vendor/helm.sh/helm/v3/pkg/action/get_metadata.go b/vendor/helm.sh/helm/v3/pkg/action/get_metadata.go index ec096ae165..f79788c3bb 100644 --- a/vendor/helm.sh/helm/v3/pkg/action/get_metadata.go +++ b/vendor/helm.sh/helm/v3/pkg/action/get_metadata.go @@ -16,7 +16,13 @@ limitations under the License. package action -import "time" +import ( + "sort" + "strings" + "time" + + "helm.sh/helm/v3/pkg/chart" +) // GetMetadata is the action for checking a given release's metadata. // @@ -28,14 +34,16 @@ type GetMetadata struct { } type Metadata struct { - Name string `json:"name" yaml:"name"` - Chart string `json:"chart" yaml:"chart"` - Version string `json:"version" yaml:"version"` - AppVersion string `json:"appVersion" yaml:"appVersion"` - Namespace string `json:"namespace" yaml:"namespace"` - Revision int `json:"revision" yaml:"revision"` - Status string `json:"status" yaml:"status"` - DeployedAt string `json:"deployedAt" yaml:"deployedAt"` + Name string `json:"name" yaml:"name"` + Chart string `json:"chart" yaml:"chart"` + Version string `json:"version" yaml:"version"` + AppVersion string `json:"appVersion" yaml:"appVersion"` + Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"` + Dependencies []*chart.Dependency `json:"dependencies,omitempty" yaml:"dependencies,omitempty"` + Namespace string `json:"namespace" yaml:"namespace"` + Revision int `json:"revision" yaml:"revision"` + Status string `json:"status" yaml:"status"` + DeployedAt string `json:"deployedAt" yaml:"deployedAt"` } // NewGetMetadata creates a new GetMetadata object with the given configuration. @@ -57,13 +65,26 @@ func (g *GetMetadata) Run(name string) (*Metadata, error) { } return &Metadata{ - Name: rel.Name, - Chart: rel.Chart.Metadata.Name, - Version: rel.Chart.Metadata.Version, - AppVersion: rel.Chart.Metadata.AppVersion, - Namespace: rel.Namespace, - Revision: rel.Version, - Status: rel.Info.Status.String(), - DeployedAt: rel.Info.LastDeployed.Format(time.RFC3339), + Name: rel.Name, + Chart: rel.Chart.Metadata.Name, + Version: rel.Chart.Metadata.Version, + AppVersion: rel.Chart.Metadata.AppVersion, + Dependencies: rel.Chart.Metadata.Dependencies, + Annotations: rel.Chart.Metadata.Annotations, + Namespace: rel.Namespace, + Revision: rel.Version, + Status: rel.Info.Status.String(), + DeployedAt: rel.Info.LastDeployed.Format(time.RFC3339), }, nil } + +// FormattedDepNames formats metadata.dependencies names into a comma-separated list. +func (m *Metadata) FormattedDepNames() string { + depsNames := make([]string, 0, len(m.Dependencies)) + for _, dep := range m.Dependencies { + depsNames = append(depsNames, dep.Name) + } + sort.StringSlice(depsNames).Sort() + + return strings.Join(depsNames, ",") +} diff --git a/vendor/helm.sh/helm/v3/pkg/action/hooks.go b/vendor/helm.sh/helm/v3/pkg/action/hooks.go index 4bffb6ae0a..e1cbab5e12 100644 --- a/vendor/helm.sh/helm/v3/pkg/action/hooks.go +++ b/vendor/helm.sh/helm/v3/pkg/action/hooks.go @@ -44,7 +44,7 @@ func (cfg *Configuration) execHook(rl *release.Release, hook release.HookEvent, for _, h := range executingHooks { // Set default delete policy to before-hook-creation - if h.DeletePolicies == nil || len(h.DeletePolicies) == 0 { + if len(h.DeletePolicies) == 0 { // TODO(jlegrone): Only apply before-hook-creation delete policy to run to completion // resources. For all other resource types update in place if a // resource with the same name already exists and is owned by the diff --git a/vendor/helm.sh/helm/v3/pkg/action/install.go b/vendor/helm.sh/helm/v3/pkg/action/install.go index 7ca40c88aa..ae732f4fd7 100644 --- a/vendor/helm.sh/helm/v3/pkg/action/install.go +++ b/vendor/helm.sh/helm/v3/pkg/action/install.go @@ -770,6 +770,7 @@ func (c *ChartPathOptions) LocateChart(name string, settings *cli.EnvSettings) ( getter.WithTLSClientConfig(c.CertFile, c.KeyFile, c.CaFile), getter.WithInsecureSkipVerifyTLS(c.InsecureSkipTLSverify), getter.WithPlainHTTP(c.PlainHTTP), + getter.WithBasicAuth(c.Username, c.Password), }, RepositoryConfig: settings.RepositoryConfig, RepositoryCache: settings.RepositoryCache, diff --git a/vendor/helm.sh/helm/v3/pkg/action/package.go b/vendor/helm.sh/helm/v3/pkg/action/package.go index 013b32f550..2357e3882a 100644 --- a/vendor/helm.sh/helm/v3/pkg/action/package.go +++ b/vendor/helm.sh/helm/v3/pkg/action/package.go @@ -44,8 +44,15 @@ type Package struct { Destination string DependencyUpdate bool - RepositoryConfig string - RepositoryCache string + RepositoryConfig string + RepositoryCache string + PlainHTTP bool + Username string + Password string + CertFile string + KeyFile string + CaFile string + InsecureSkipTLSverify bool } // NewPackage creates a new Package object with the given configuration. diff --git a/vendor/helm.sh/helm/v3/pkg/action/push.go b/vendor/helm.sh/helm/v3/pkg/action/push.go index 68d2ba42dc..70e5c15823 100644 --- a/vendor/helm.sh/helm/v3/pkg/action/push.go +++ b/vendor/helm.sh/helm/v3/pkg/action/push.go @@ -73,7 +73,7 @@ func WithPlainHTTP(plainHTTP bool) PushOpt { } } -// WithOptWriter sets the registryOut field on the push configuration object. +// WithPushOptWriter sets the registryOut field on the push configuration object. func WithPushOptWriter(out io.Writer) PushOpt { return func(p *Push) { p.out = out diff --git a/vendor/helm.sh/helm/v3/pkg/chart/dependency.go b/vendor/helm.sh/helm/v3/pkg/chart/dependency.go index 4ef5eeb320..eda0f5a89d 100644 --- a/vendor/helm.sh/helm/v3/pkg/chart/dependency.go +++ b/vendor/helm.sh/helm/v3/pkg/chart/dependency.go @@ -25,28 +25,28 @@ type Dependency struct { // Name is the name of the dependency. // // This must mach the name in the dependency's Chart.yaml. - Name string `json:"name"` + Name string `json:"name" yaml:"name"` // Version is the version (range) of this chart. // // A lock file will always produce a single version, while a dependency // may contain a semantic version range. - Version string `json:"version,omitempty"` + Version string `json:"version,omitempty" yaml:"version,omitempty"` // The URL to the repository. // // Appending `index.yaml` to this string should result in a URL that can be // used to fetch the repository index. - Repository string `json:"repository"` + Repository string `json:"repository" yaml:"repository"` // A yaml path that resolves to a boolean, used for enabling/disabling charts (e.g. subchart1.enabled ) - Condition string `json:"condition,omitempty"` + Condition string `json:"condition,omitempty" yaml:"condition,omitempty"` // Tags can be used to group charts for enabling/disabling together - Tags []string `json:"tags,omitempty"` + Tags []string `json:"tags,omitempty" yaml:"tags,omitempty"` // Enabled bool determines if chart should be loaded - Enabled bool `json:"enabled,omitempty"` + Enabled bool `json:"enabled,omitempty" yaml:"enabled,omitempty"` // ImportValues holds the mapping of source values to parent key to be imported. Each item can be a // string or pair of child/parent sublist items. - ImportValues []interface{} `json:"import-values,omitempty"` + ImportValues []interface{} `json:"import-values,omitempty" yaml:"import-values,omitempty"` // Alias usable alias to be used for the chart - Alias string `json:"alias,omitempty"` + Alias string `json:"alias,omitempty" yaml:"alias,omitempty"` } // Validate checks for common problems with the dependency datastructure in diff --git a/vendor/helm.sh/helm/v3/pkg/chart/loader/load.go b/vendor/helm.sh/helm/v3/pkg/chart/loader/load.go index f59c35a5e4..a68a05aa9a 100644 --- a/vendor/helm.sh/helm/v3/pkg/chart/loader/load.go +++ b/vendor/helm.sh/helm/v3/pkg/chart/loader/load.go @@ -174,7 +174,7 @@ func LoadFiles(files []*BufferedFile) (*chart.Chart, error) { case filepath.Ext(n) == ".tgz": file := files[0] if file.Name != n { - return c, errors.Errorf("error unpacking tar in %s: expected %s, got %s", c.Name(), n, file.Name) + return c, errors.Errorf("error unpacking subchart tar in %s: expected %s, got %s", c.Name(), n, file.Name) } // Untar the chart and add to c.Dependencies sc, err = LoadArchive(bytes.NewBuffer(file.Data)) @@ -194,7 +194,7 @@ func LoadFiles(files []*BufferedFile) (*chart.Chart, error) { } if err != nil { - return c, errors.Wrapf(err, "error unpacking %s in %s", n, c.Name()) + return c, errors.Wrapf(err, "error unpacking subchart %s in %s", n, c.Name()) } c.AddDependency(sc) } diff --git a/vendor/helm.sh/helm/v3/pkg/chartutil/create.go b/vendor/helm.sh/helm/v3/pkg/chartutil/create.go index e9769932f6..321d3d2c04 100644 --- a/vendor/helm.sh/helm/v3/pkg/chartutil/create.go +++ b/vendor/helm.sh/helm/v3/pkg/chartutil/create.go @@ -117,13 +117,13 @@ image: # Overrides the image tag whose default is the chart appVersion. tag: "" -# This is for the secretes for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ +# This is for the secrets for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ imagePullSecrets: [] # This is to override the chart name. nameOverride: "" fullnameOverride: "" -#This section builds out the service account more information can be found here: https://kubernetes.io/docs/concepts/security/service-accounts/ +# This section builds out the service account more information can be found here: https://kubernetes.io/docs/concepts/security/service-accounts/ serviceAccount: # Specifies whether a service account should be created create: true @@ -136,7 +136,7 @@ serviceAccount: name: "" # This is for setting Kubernetes Annotations to a Pod. -# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ podAnnotations: {} # This is for setting Kubernetes Labels to a Pod. # For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ @@ -199,7 +199,7 @@ readinessProbe: path: / port: http -#This section is for setting up autoscaling more information can be found here: https://kubernetes.io/docs/concepts/workloads/autoscaling/ +# This section is for setting up autoscaling more information can be found here: https://kubernetes.io/docs/concepts/workloads/autoscaling/ autoscaling: enabled: false minReplicas: 1 @@ -327,24 +327,34 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} serviceAccountName: {{ include ".serviceAccountName" . }} + {{- with .Values.podSecurityContext }} securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- toYaml . | nindent 8 }} + {{- end }} containers: - name: {{ .Chart.Name }} + {{- with .Values.securityContext }} securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} + {{- toYaml . | nindent 12 }} + {{- end }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} ports: - name: http containerPort: {{ .Values.service.port }} protocol: TCP + {{- with .Values.livenessProbe }} livenessProbe: - {{- toYaml .Values.livenessProbe | nindent 12 }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.readinessProbe }} readinessProbe: - {{- toYaml .Values.readinessProbe | nindent 12 }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.resources }} resources: - {{- toYaml .Values.resources | nindent 12 }} + {{- toYaml . | nindent 12 }} + {{- end }} {{- with .Values.volumeMounts }} volumeMounts: {{- toYaml . | nindent 12 }} @@ -620,6 +630,10 @@ func Create(name, dir string) (string, error) { return cdir, errors.Errorf("file %s already exists and is not a directory", cdir) } + // Note: If adding a new template below (i.e., to `helm create`) which is disabled by default (similar to hpa and + // ingress below); or making an existing template disabled by default, add the enabling condition in + // `TestHelmCreateChart_CheckDeprecatedWarnings` in `pkg/lint/lint_test.go` to make it run through deprecation checks + // with latest Kubernetes version. files := []struct { path string content []byte diff --git a/vendor/helm.sh/helm/v3/pkg/cli/environment.go b/vendor/helm.sh/helm/v3/pkg/cli/environment.go index 0f28c61fd9..6358063442 100644 --- a/vendor/helm.sh/helm/v3/pkg/cli/environment.go +++ b/vendor/helm.sh/helm/v3/pkg/cli/environment.go @@ -36,6 +36,7 @@ import ( "helm.sh/helm/v3/internal/version" "helm.sh/helm/v3/pkg/helmpath" + "helm.sh/helm/v3/pkg/kube" ) // defaultMaxHistory sets the maximum number of releases to 0: unlimited @@ -127,7 +128,7 @@ func New() *EnvSettings { config.Burst = env.BurstLimit config.QPS = env.QPS config.Wrap(func(rt http.RoundTripper) http.RoundTripper { - return &retryingRoundTripper{wrapped: rt} + return &kube.RetryingRoundTripper{Wrapped: rt} }) config.UserAgent = version.GetUserAgent() return config diff --git a/vendor/helm.sh/helm/v3/pkg/downloader/chart_downloader.go b/vendor/helm.sh/helm/v3/pkg/downloader/chart_downloader.go index a95894e00e..9e8e243b8c 100644 --- a/vendor/helm.sh/helm/v3/pkg/downloader/chart_downloader.go +++ b/vendor/helm.sh/helm/v3/pkg/downloader/chart_downloader.go @@ -23,7 +23,6 @@ import ( "path/filepath" "strings" - "github.com/Masterminds/semver/v3" "github.com/pkg/errors" "helm.sh/helm/v3/internal/fileutil" @@ -97,6 +96,8 @@ func (c *ChartDownloader) DownloadTo(ref, version, dest string) (string, *proven return "", nil, err } + c.Options = append(c.Options, getter.WithAcceptHeader("application/gzip,application/octet-stream")) + data, err := g.Get(u.String(), c.Options...) if err != nil { return "", nil, err @@ -141,39 +142,6 @@ func (c *ChartDownloader) DownloadTo(ref, version, dest string) (string, *proven return destfile, ver, nil } -func (c *ChartDownloader) getOciURI(ref, version string, u *url.URL) (*url.URL, error) { - var tag string - var err error - - // Evaluate whether an explicit version has been provided. Otherwise, determine version to use - _, errSemVer := semver.NewVersion(version) - if errSemVer == nil { - tag = version - } else { - // Retrieve list of repository tags - tags, err := c.RegistryClient.Tags(strings.TrimPrefix(ref, fmt.Sprintf("%s://", registry.OCIScheme))) - if err != nil { - return nil, err - } - if len(tags) == 0 { - return nil, errors.Errorf("Unable to locate any tags in provided repository: %s", ref) - } - - // Determine if version provided - // If empty, try to get the highest available tag - // If exact version, try to find it - // If semver constraint string, try to find a match - tag, err = registry.GetTagMatchingVersionOrConstraint(tags, version) - if err != nil { - return nil, err - } - } - - u.Path = fmt.Sprintf("%s:%s", u.Path, tag) - - return u, err -} - // ResolveChartVersion resolves a chart reference to a URL. // // It returns the URL and sets the ChartDownloader's Options that can fetch @@ -196,7 +164,7 @@ func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, er } if registry.IsOCI(u.String()) { - return c.getOciURI(ref, version, u) + return c.RegistryClient.ValidateReference(ref, version, u) } rf, err := loadRepoConfig(c.RepositoryConfig) diff --git a/vendor/helm.sh/helm/v3/pkg/engine/engine.go b/vendor/helm.sh/helm/v3/pkg/engine/engine.go index df3a600a39..d8ee313e1e 100644 --- a/vendor/helm.sh/helm/v3/pkg/engine/engine.go +++ b/vendor/helm.sh/helm/v3/pkg/engine/engine.go @@ -206,7 +206,7 @@ func (e Engine) initFunMap(t *template.Template) { log.Printf("[INFO] Missing required value: %s", warn) return "", nil } - return val, errors.Errorf(warnWrap(warn)) + return val, errors.New(warnWrap(warn)) } else if _, ok := val.(string); ok { if val == "" { if e.LintMode { @@ -214,7 +214,7 @@ func (e Engine) initFunMap(t *template.Template) { log.Printf("[INFO] Missing required value: %s", warn) return "", nil } - return val, errors.Errorf(warnWrap(warn)) + return val, errors.New(warnWrap(warn)) } } return val, nil diff --git a/vendor/helm.sh/helm/v3/pkg/engine/funcs.go b/vendor/helm.sh/helm/v3/pkg/engine/funcs.go index 8f05a3a1db..d03a818c28 100644 --- a/vendor/helm.sh/helm/v3/pkg/engine/funcs.go +++ b/vendor/helm.sh/helm/v3/pkg/engine/funcs.go @@ -25,6 +25,7 @@ import ( "github.com/BurntSushi/toml" "github.com/Masterminds/sprig/v3" "sigs.k8s.io/yaml" + goYaml "sigs.k8s.io/yaml/goyaml.v3" ) // funcMap returns a mapping of all of the functions that Engine has. @@ -48,7 +49,9 @@ func funcMap() template.FuncMap { // Add some extra functionality extra := template.FuncMap{ "toToml": toTOML, + "fromToml": fromTOML, "toYaml": toYAML, + "toYamlPretty": toYAMLPretty, "fromYaml": fromYAML, "fromYamlArray": fromYAMLArray, "toJson": toJSON, @@ -88,6 +91,19 @@ func toYAML(v interface{}) string { return strings.TrimSuffix(string(data), "\n") } +func toYAMLPretty(v interface{}) string { + var data bytes.Buffer + encoder := goYaml.NewEncoder(&data) + encoder.SetIndent(2) + err := encoder.Encode(v) + + if err != nil { + // Swallow errors inside of a template. + return "" + } + return strings.TrimSuffix(data.String(), "\n") +} + // fromYAML converts a YAML document into a map[string]interface{}. // // This is not a general-purpose YAML parser, and will not parse all valid @@ -132,6 +148,21 @@ func toTOML(v interface{}) string { return b.String() } +// fromTOML converts a TOML document into a map[string]interface{}. +// +// This is not a general-purpose TOML parser, and will not parse all valid +// TOML documents. Additionally, because its intended use is within templates +// it tolerates errors. It will insert the returned error message string into +// m["Error"] in the returned map. +func fromTOML(str string) map[string]interface{} { + m := make(map[string]interface{}) + + if err := toml.Unmarshal([]byte(str), &m); err != nil { + m["Error"] = err.Error() + } + return m +} + // toJSON takes an interface, marshals it to json, and returns a string. It will // always return a string, even on marshal error (empty string). // diff --git a/vendor/helm.sh/helm/v3/pkg/getter/getter.go b/vendor/helm.sh/helm/v3/pkg/getter/getter.go index 45ab4da7e4..1acb2093dc 100644 --- a/vendor/helm.sh/helm/v3/pkg/getter/getter.go +++ b/vendor/helm.sh/helm/v3/pkg/getter/getter.go @@ -38,6 +38,7 @@ type options struct { unTar bool insecureSkipVerifyTLS bool plainHTTP bool + acceptHeader string username string password string passCredentialsAll bool @@ -60,6 +61,13 @@ func WithURL(url string) Option { } } +// WithAcceptHeader sets the request's Accept header as some REST APIs serve multiple content types +func WithAcceptHeader(header string) Option { + return func(opts *options) { + opts.acceptHeader = header + } +} + // WithBasicAuth sets the request's Authorization header to use the provided credentials func WithBasicAuth(username, password string) Option { return func(opts *options) { diff --git a/vendor/helm.sh/helm/v3/pkg/getter/httpgetter.go b/vendor/helm.sh/helm/v3/pkg/getter/httpgetter.go index b53e558e35..df3dcd9109 100644 --- a/vendor/helm.sh/helm/v3/pkg/getter/httpgetter.go +++ b/vendor/helm.sh/helm/v3/pkg/getter/httpgetter.go @@ -53,6 +53,10 @@ func (g *HTTPGetter) get(href string) (*bytes.Buffer, error) { return nil, err } + if g.opts.acceptHeader != "" { + req.Header.Set("Accept", g.opts.acceptHeader) + } + req.Header.Set("User-Agent", version.GetUserAgent()) if g.opts.userAgent != "" { req.Header.Set("User-Agent", g.opts.userAgent) diff --git a/vendor/helm.sh/helm/v3/pkg/getter/ocigetter.go b/vendor/helm.sh/helm/v3/pkg/getter/ocigetter.go index 0547cdcbb6..5b0522395c 100644 --- a/vendor/helm.sh/helm/v3/pkg/getter/ocigetter.go +++ b/vendor/helm.sh/helm/v3/pkg/getter/ocigetter.go @@ -20,6 +20,7 @@ import ( "fmt" "net" "net/http" + "path" "strings" "sync" "time" @@ -58,6 +59,9 @@ func (g *OCIGetter) get(href string) (*bytes.Buffer, error) { ref := strings.TrimPrefix(href, fmt.Sprintf("%s://", registry.OCIScheme)) + if version := g.opts.version; version != "" && !strings.Contains(path.Base(ref), ":") { + ref = fmt.Sprintf("%s:%s", ref, version) + } var pullOpts []registry.PullOption requestingProv := strings.HasSuffix(ref, ".prov") if requestingProv { diff --git a/vendor/helm.sh/helm/v3/pkg/kube/client.go b/vendor/helm.sh/helm/v3/pkg/kube/client.go index d979fd22cd..5f16f2bfb6 100644 --- a/vendor/helm.sh/helm/v3/pkg/kube/client.go +++ b/vendor/helm.sh/helm/v3/pkg/kube/client.go @@ -55,6 +55,7 @@ import ( "k8s.io/client-go/rest" cachetools "k8s.io/client-go/tools/cache" watchtools "k8s.io/client-go/tools/watch" + "k8s.io/client-go/util/retry" cmdutil "k8s.io/kubectl/pkg/cmd/util" ) @@ -85,23 +86,22 @@ type Client struct { kubeClient *kubernetes.Clientset } -var addToScheme sync.Once +func init() { + // Add CRDs to the scheme. They are missing by default. + if err := apiextv1.AddToScheme(scheme.Scheme); err != nil { + // This should never happen. + panic(err) + } + if err := apiextv1beta1.AddToScheme(scheme.Scheme); err != nil { + panic(err) + } +} // New creates a new Client. func New(getter genericclioptions.RESTClientGetter) *Client { if getter == nil { getter = genericclioptions.NewConfigFlags(true) } - // Add CRDs to the scheme. They are missing by default. - addToScheme.Do(func() { - if err := apiextv1.AddToScheme(scheme.Scheme); err != nil { - // This should never happen. - panic(err) - } - if err := apiextv1beta1.AddToScheme(scheme.Scheme); err != nil { - panic(err) - } - }) return &Client{ Factory: cmdutil.NewFactory(getter), Log: nopLogger, @@ -435,7 +435,7 @@ func (c *Client) Update(original, target ResourceList, force bool) (*Result, err case err != nil: return res, err case len(updateErrors) != 0: - return res, errors.Errorf(strings.Join(updateErrors, " && ")) + return res, errors.New(strings.Join(updateErrors, " && ")) } for _, info := range original.Difference(target) { @@ -596,17 +596,25 @@ func batchPerform(infos ResourceList, fn func(*resource.Info) error, errs chan<- } func createResource(info *resource.Info) error { - obj, err := resource.NewHelper(info.Client, info.Mapping).WithFieldManager(getManagedFieldsManager()).Create(info.Namespace, true, info.Object) - if err != nil { - return err - } - return info.Refresh(obj, true) + return retry.RetryOnConflict( + retry.DefaultRetry, + func() error { + obj, err := resource.NewHelper(info.Client, info.Mapping).WithFieldManager(getManagedFieldsManager()).Create(info.Namespace, true, info.Object) + if err != nil { + return err + } + return info.Refresh(obj, true) + }) } func deleteResource(info *resource.Info, policy metav1.DeletionPropagation) error { - opts := &metav1.DeleteOptions{PropagationPolicy: &policy} - _, err := resource.NewHelper(info.Client, info.Mapping).WithFieldManager(getManagedFieldsManager()).DeleteWithOptions(info.Namespace, info.Name, opts) - return err + return retry.RetryOnConflict( + retry.DefaultRetry, + func() error { + opts := &metav1.DeleteOptions{PropagationPolicy: &policy} + _, err := resource.NewHelper(info.Client, info.Mapping).WithFieldManager(getManagedFieldsManager()).DeleteWithOptions(info.Namespace, info.Name, opts) + return err + }) } func createPatch(target *resource.Info, current runtime.Object) ([]byte, types.PatchType, error) { diff --git a/vendor/helm.sh/helm/v3/pkg/cli/roundtripper.go b/vendor/helm.sh/helm/v3/pkg/kube/roundtripper.go similarity index 87% rename from vendor/helm.sh/helm/v3/pkg/cli/roundtripper.go rename to vendor/helm.sh/helm/v3/pkg/kube/roundtripper.go index 9cd4eacba7..fdb1035291 100644 --- a/vendor/helm.sh/helm/v3/pkg/cli/roundtripper.go +++ b/vendor/helm.sh/helm/v3/pkg/kube/roundtripper.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cli +package kube import ( "bytes" @@ -24,19 +24,19 @@ import ( "strings" ) -type retryingRoundTripper struct { - wrapped http.RoundTripper +type RetryingRoundTripper struct { + Wrapped http.RoundTripper } -func (rt *retryingRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { +func (rt *RetryingRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { return rt.roundTrip(req, 1, nil) } -func (rt *retryingRoundTripper) roundTrip(req *http.Request, retry int, prevResp *http.Response) (*http.Response, error) { +func (rt *RetryingRoundTripper) roundTrip(req *http.Request, retry int, prevResp *http.Response) (*http.Response, error) { if retry < 0 { return prevResp, nil } - resp, rtErr := rt.wrapped.RoundTrip(req) + resp, rtErr := rt.Wrapped.RoundTrip(req) if rtErr != nil { return resp, rtErr } diff --git a/vendor/helm.sh/helm/v3/pkg/kube/wait.go b/vendor/helm.sh/helm/v3/pkg/kube/wait.go index 36110d0de3..bdafc82556 100644 --- a/vendor/helm.sh/helm/v3/pkg/kube/wait.go +++ b/vendor/helm.sh/helm/v3/pkg/kube/wait.go @@ -153,7 +153,7 @@ func SelectorsForObject(object runtime.Object) (selector labels.Selector, err er case *batchv1.Job: selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) case *corev1.Service: - if t.Spec.Selector == nil || len(t.Spec.Selector) == 0 { + if len(t.Spec.Selector) == 0 { return nil, fmt.Errorf("invalid service '%s': Service is defined without a selector", t.Name) } selector = labels.SelectorFromSet(t.Spec.Selector) diff --git a/vendor/helm.sh/helm/v3/pkg/pusher/ocipusher.go b/vendor/helm.sh/helm/v3/pkg/pusher/ocipusher.go index b37a0c6053..33296aaddc 100644 --- a/vendor/helm.sh/helm/v3/pkg/pusher/ocipusher.go +++ b/vendor/helm.sh/helm/v3/pkg/pusher/ocipusher.go @@ -90,8 +90,9 @@ func (pusher *OCIPusher) push(chartRef, href string) error { path.Join(strings.TrimPrefix(href, fmt.Sprintf("%s://", registry.OCIScheme)), meta.Metadata.Name), meta.Metadata.Version) - chartCreationTime := ctime.Created(stat) - pushOpts = append(pushOpts, registry.PushOptCreationTime(chartCreationTime.Format(time.RFC3339))) + // The time the chart was "created" is semantically the time the chart archive file was last written(modified) + chartArchiveFileCreatedTime := ctime.Modified(stat) + pushOpts = append(pushOpts, registry.PushOptCreationTime(chartArchiveFileCreatedTime.Format(time.RFC3339))) _, err = client.Push(chartBytes, ref, pushOpts...) return err diff --git a/vendor/helm.sh/helm/v3/pkg/registry/client.go b/vendor/helm.sh/helm/v3/pkg/registry/client.go index 42f736816d..fc26ca11a7 100644 --- a/vendor/helm.sh/helm/v3/pkg/registry/client.go +++ b/vendor/helm.sh/helm/v3/pkg/registry/client.go @@ -18,10 +18,12 @@ package registry // import "helm.sh/helm/v3/pkg/registry" import ( "context" + "encoding/base64" "encoding/json" "fmt" "io" "net/http" + "net/url" "sort" "strings" @@ -50,15 +52,24 @@ an underscore (_) in chart version tags when pushing to a registry and back to a plus (+) when pulling from a registry.` type ( + // RemoteClient shadows the ORAS remote.Client interface + // (hiding the ORAS type from Helm client visibility) + // https://pkg.go.dev/oras.land/oras-go/pkg/registry/remote#Client + RemoteClient interface { + Do(req *http.Request) (*http.Response, error) + } + // Client works with OCI-compliant registries Client struct { debug bool enableCache bool // path to repository config file e.g. ~/.docker/config.json credentialsFile string + username string + password string out io.Writer authorizer auth.Client - registryAuthorizer *registryauth.Client + registryAuthorizer RemoteClient resolver func(ref registry.Reference) (remotes.Resolver, error) httpClient *http.Client plainHTTP bool @@ -105,6 +116,19 @@ func NewClient(options ...ClientOption) (*Client, error) { if client.plainHTTP { opts = append(opts, auth.WithResolverPlainHTTP()) } + + // if username and password are set, use them for authentication + // by adding the basic auth Authorization header to the resolver + if client.username != "" && client.password != "" { + concat := client.username + ":" + client.password + encodedAuth := base64.StdEncoding.EncodeToString([]byte(concat)) + opts = append(opts, auth.WithResolverHeaders( + http.Header{ + "Authorization": []string{"Basic " + encodedAuth}, + }, + )) + } + resolver, err := client.authorizer.ResolverWithOpts(opts...) if err != nil { return nil, err @@ -125,6 +149,13 @@ func NewClient(options ...ClientOption) (*Client, error) { }, Cache: cache, Credential: func(_ context.Context, reg string) (registryauth.Credential, error) { + if client.username != "" && client.password != "" { + return registryauth.Credential{ + Username: client.username, + Password: client.password, + }, nil + } + dockerClient, ok := client.authorizer.(*dockerauth.Client) if !ok { return registryauth.EmptyCredential, errors.New("unable to obtain docker client") @@ -168,6 +199,14 @@ func ClientOptEnableCache(enableCache bool) ClientOption { } } +// ClientOptBasicAuth returns a function that sets the username and password setting on client options set +func ClientOptBasicAuth(username, password string) ClientOption { + return func(client *Client) { + client.username = username + client.password = password + } +} + // ClientOptWriter returns a function that sets the writer setting on client options set func ClientOptWriter(out io.Writer) ClientOption { return func(client *Client) { @@ -175,6 +214,26 @@ func ClientOptWriter(out io.Writer) ClientOption { } } +// ClientOptAuthorizer returns a function that sets the authorizer setting on a client options set. This +// can be used to override the default authorization mechanism. +// +// Depending on the use-case you may need to set both ClientOptAuthorizer and ClientOptRegistryAuthorizer. +func ClientOptAuthorizer(authorizer auth.Client) ClientOption { + return func(client *Client) { + client.authorizer = authorizer + } +} + +// ClientOptRegistryAuthorizer returns a function that sets the registry authorizer setting on a client options set. This +// can be used to override the default authorization mechanism. +// +// Depending on the use-case you may need to set both ClientOptAuthorizer and ClientOptRegistryAuthorizer. +func ClientOptRegistryAuthorizer(registryAuthorizer RemoteClient) ClientOption { + return func(client *Client) { + client.registryAuthorizer = registryAuthorizer + } +} + // ClientOptCredentialsFile returns a function that sets the credentialsFile setting on a client options set func ClientOptCredentialsFile(credentialsFile string) ClientOption { return func(client *Client) { @@ -319,7 +378,7 @@ type ( // Pull downloads a chart from a registry func (c *Client) Pull(ref string, options ...PullOption) (*PullResult, error) { - parsedRef, err := parseReference(ref) + parsedRef, err := newReference(ref) if err != nil { return nil, err } @@ -351,7 +410,7 @@ func (c *Client) Pull(ref string, options ...PullOption) (*PullResult, error) { } var descriptors, layers []ocispec.Descriptor - remotesResolver, err := c.resolver(parsedRef) + remotesResolver, err := c.resolver(parsedRef.orasReference) if err != nil { return nil, err } @@ -535,7 +594,7 @@ type ( // Push uploads a chart to a registry. func (c *Client) Push(data []byte, ref string, options ...PushOption) (*PushResult, error) { - parsedRef, err := parseReference(ref) + parsedRef, err := newReference(ref) if err != nil { return nil, err } @@ -594,12 +653,12 @@ func (c *Client) Push(data []byte, ref string, options ...PushOption) (*PushResu return nil, err } - remotesResolver, err := c.resolver(parsedRef) + remotesResolver, err := c.resolver(parsedRef.orasReference) if err != nil { return nil, err } registryStore := content.Registry{Resolver: remotesResolver} - _, err = oras.Copy(ctx(c.out, c.debug), memoryStore, parsedRef.String(), registryStore, "", + _, err = oras.Copy(ctx(c.out, c.debug), memoryStore, parsedRef.orasReference.String(), registryStore, "", oras.WithNameValidation(nil)) if err != nil { return nil, err @@ -630,7 +689,7 @@ func (c *Client) Push(data []byte, ref string, options ...PushOption) (*PushResu } fmt.Fprintf(c.out, "Pushed: %s\n", result.Ref) fmt.Fprintf(c.out, "Digest: %s\n", result.Manifest.Digest) - if strings.Contains(parsedRef.Reference, "_") { + if strings.Contains(parsedRef.orasReference.Reference, "_") { fmt.Fprintf(c.out, "%s contains an underscore.\n", result.Ref) fmt.Fprint(c.out, registryUnderscoreMessage+"\n") } @@ -701,3 +760,89 @@ func (c *Client) Tags(ref string) ([]string, error) { return tags, nil } + +// Resolve a reference to a descriptor. +func (c *Client) Resolve(ref string) (*ocispec.Descriptor, error) { + ctx := context.Background() + parsedRef, err := newReference(ref) + if err != nil { + return nil, err + } + if parsedRef.Registry == "" { + return nil, nil + } + + remotesResolver, err := c.resolver(parsedRef.orasReference) + if err != nil { + return nil, err + } + + _, desc, err := remotesResolver.Resolve(ctx, ref) + return &desc, err +} + +// ValidateReference for path and version +func (c *Client) ValidateReference(ref, version string, u *url.URL) (*url.URL, error) { + var tag string + + registryReference, err := newReference(u.Path) + if err != nil { + return nil, err + } + + if version == "" { + // Use OCI URI tag as default + version = registryReference.Tag + } else { + if registryReference.Tag != "" && registryReference.Tag != version { + return nil, errors.Errorf("chart reference and version mismatch: %s is not %s", version, registryReference.Tag) + } + } + + if registryReference.Digest != "" { + if registryReference.Tag == "" { + // Install by digest only + return u, nil + } + + // Validate the tag if it was specified + path := registryReference.Registry + "/" + registryReference.Repository + ":" + registryReference.Tag + desc, err := c.Resolve(path) + if err != nil { + // The resource does not have to be tagged when digest is specified + return u, nil + } + if desc != nil && desc.Digest.String() != registryReference.Digest { + return nil, errors.Errorf("chart reference digest mismatch: %s is not %s", desc.Digest.String(), registryReference.Digest) + } + return u, nil + } + + // Evaluate whether an explicit version has been provided. Otherwise, determine version to use + _, errSemVer := semver.NewVersion(version) + if errSemVer == nil { + tag = version + } else { + // Retrieve list of repository tags + tags, err := c.Tags(strings.TrimPrefix(ref, fmt.Sprintf("%s://", OCIScheme))) + if err != nil { + return nil, err + } + if len(tags) == 0 { + return nil, errors.Errorf("Unable to locate any tags in provided repository: %s", ref) + } + + // Determine if version provided + // If empty, try to get the highest available tag + // If exact version, try to find it + // If semver constraint string, try to find a match + tag, err = GetTagMatchingVersionOrConstraint(tags, version) + if err != nil { + return nil, err + } + } + + u.Path = fmt.Sprintf("%s/%s:%s", registryReference.Registry, registryReference.Repository, tag) + + return u, err +} diff --git a/vendor/helm.sh/helm/v3/pkg/registry/reference.go b/vendor/helm.sh/helm/v3/pkg/registry/reference.go new file mode 100644 index 0000000000..9b99d73bf1 --- /dev/null +++ b/vendor/helm.sh/helm/v3/pkg/registry/reference.go @@ -0,0 +1,78 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package registry + +import ( + "strings" + + orasregistry "oras.land/oras-go/pkg/registry" +) + +type reference struct { + orasReference orasregistry.Reference + Registry string + Repository string + Tag string + Digest string +} + +// newReference will parse and validate the reference, and clean tags when +// applicable tags are only cleaned when plus (+) signs are present, and are +// converted to underscores (_) before pushing +// See https://github.com/helm/helm/issues/10166 +func newReference(raw string) (result reference, err error) { + // Remove oci:// prefix if it is there + raw = strings.TrimPrefix(raw, OCIScheme+"://") + + // The sole possible reference modification is replacing plus (+) signs + // present in tags with underscores (_). To do this properly, we first + // need to identify a tag, and then pass it on to the reference parser + // NOTE: Passing immediately to the reference parser will fail since (+) + // signs are an invalid tag character, and simply replacing all plus (+) + // occurrences could invalidate other portions of the URI + lastIndex := strings.LastIndex(raw, "@") + if lastIndex >= 0 { + result.Digest = raw[(lastIndex + 1):] + raw = raw[:lastIndex] + } + parts := strings.Split(raw, ":") + if len(parts) > 1 && !strings.Contains(parts[len(parts)-1], "/") { + tag := parts[len(parts)-1] + + if tag != "" { + // Replace any plus (+) signs with known underscore (_) conversion + newTag := strings.ReplaceAll(tag, "+", "_") + raw = strings.ReplaceAll(raw, tag, newTag) + } + } + + result.orasReference, err = orasregistry.ParseReference(raw) + if err != nil { + return result, err + } + result.Registry = result.orasReference.Registry + result.Repository = result.orasReference.Repository + result.Tag = result.orasReference.Reference + return result, nil +} + +func (r *reference) String() string { + if r.Tag == "" { + return r.orasReference.String() + "@" + r.Digest + } + return r.orasReference.String() +} diff --git a/vendor/helm.sh/helm/v3/pkg/registry/util.go b/vendor/helm.sh/helm/v3/pkg/registry/util.go index 727cdae033..bd9f151a8e 100644 --- a/vendor/helm.sh/helm/v3/pkg/registry/util.go +++ b/vendor/helm.sh/helm/v3/pkg/registry/util.go @@ -32,7 +32,6 @@ import ( "github.com/pkg/errors" "github.com/sirupsen/logrus" orascontext "oras.land/oras-go/pkg/context" - "oras.land/oras-go/pkg/registry" "helm.sh/helm/v3/internal/tlsutil" "helm.sh/helm/v3/pkg/chart" @@ -115,31 +114,6 @@ func ctx(out io.Writer, debug bool) context.Context { return ctx } -// parseReference will parse and validate the reference, and clean tags when -// applicable tags are only cleaned when plus (+) signs are present, and are -// converted to underscores (_) before pushing -// See https://github.com/helm/helm/issues/10166 -func parseReference(raw string) (registry.Reference, error) { - // The sole possible reference modification is replacing plus (+) signs - // present in tags with underscores (_). To do this properly, we first - // need to identify a tag, and then pass it on to the reference parser - // NOTE: Passing immediately to the reference parser will fail since (+) - // signs are an invalid tag character, and simply replacing all plus (+) - // occurrences could invalidate other portions of the URI - parts := strings.Split(raw, ":") - if len(parts) > 1 && !strings.Contains(parts[len(parts)-1], "/") { - tag := parts[len(parts)-1] - - if tag != "" { - // Replace any plus (+) signs with known underscore (_) conversion - newTag := strings.ReplaceAll(tag, "+", "_") - raw = strings.ReplaceAll(raw, tag, newTag) - } - } - - return registry.ParseReference(raw) -} - // NewRegistryClientWithTLS is a helper function to create a new registry client with TLS enabled. func NewRegistryClientWithTLS(out io.Writer, certFile, keyFile, caFile string, insecureSkipTLSverify bool, registryConfig string, debug bool) (*Client, error) { tlsConf, err := tlsutil.NewClientTLS(certFile, keyFile, caFile, insecureSkipTLSverify) @@ -208,7 +182,7 @@ func generateChartOCIAnnotations(meta *chart.Metadata, creationTime string) map[ chartOCIAnnotations = addToMap(chartOCIAnnotations, ocispec.AnnotationSource, meta.Sources[0]) } - if meta.Maintainers != nil && len(meta.Maintainers) > 0 { + if len(meta.Maintainers) > 0 { var maintainerSb strings.Builder for maintainerIdx, maintainer := range meta.Maintainers { diff --git a/vendor/helm.sh/helm/v3/pkg/release/mock.go b/vendor/helm.sh/helm/v3/pkg/release/mock.go index a28e1dc166..eb0b5157df 100644 --- a/vendor/helm.sh/helm/v3/pkg/release/mock.go +++ b/vendor/helm.sh/helm/v3/pkg/release/mock.go @@ -74,6 +74,24 @@ func Mock(opts *MockReleaseOptions) *Release { Name: "foo", Version: "0.1.0-beta.1", AppVersion: "1.0", + Annotations: map[string]string{ + "category": "web-apps", + "supported": "true", + }, + Dependencies: []*chart.Dependency{ + { + Name: "cool-plugin", + Version: "1.0.0", + Repository: "https://coolplugin.io/charts", + Condition: "coolPlugin.enabled", + Enabled: true, + }, + { + Name: "crds", + Version: "2.7.1", + Condition: "crds.enabled", + }, + }, }, Templates: []*chart.File{ {Name: "templates/foo.tpl", Data: []byte(MockManifest)}, diff --git a/vendor/helm.sh/helm/v3/pkg/storage/driver/cfgmaps.go b/vendor/helm.sh/helm/v3/pkg/storage/driver/cfgmaps.go index 5fd64ea59c..ce88c662b0 100644 --- a/vendor/helm.sh/helm/v3/pkg/storage/driver/cfgmaps.go +++ b/vendor/helm.sh/helm/v3/pkg/storage/driver/cfgmaps.go @@ -18,6 +18,7 @@ package driver // import "helm.sh/helm/v3/pkg/storage/driver" import ( "context" + "fmt" "strconv" "strings" "time" @@ -160,7 +161,7 @@ func (cfgmaps *ConfigMaps) Create(key string, rls *rspb.Release) error { lbs.init() lbs.fromMap(rls.Labels) - lbs.set("createdAt", strconv.Itoa(int(time.Now().Unix()))) + lbs.set("createdAt", fmt.Sprintf("%v", time.Now().Unix())) // create a new configmap to hold the release obj, err := newConfigMapsObject(key, rls, lbs) @@ -188,7 +189,7 @@ func (cfgmaps *ConfigMaps) Update(key string, rls *rspb.Release) error { lbs.init() lbs.fromMap(rls.Labels) - lbs.set("modifiedAt", strconv.Itoa(int(time.Now().Unix()))) + lbs.set("modifiedAt", fmt.Sprintf("%v", time.Now().Unix())) // create a new configmap object to hold the release obj, err := newConfigMapsObject(key, rls, lbs) diff --git a/vendor/helm.sh/helm/v3/pkg/storage/driver/secrets.go b/vendor/helm.sh/helm/v3/pkg/storage/driver/secrets.go index 9c2f805f24..95a7e90324 100644 --- a/vendor/helm.sh/helm/v3/pkg/storage/driver/secrets.go +++ b/vendor/helm.sh/helm/v3/pkg/storage/driver/secrets.go @@ -18,6 +18,7 @@ package driver // import "helm.sh/helm/v3/pkg/storage/driver" import ( "context" + "fmt" "strconv" "strings" "time" @@ -151,7 +152,7 @@ func (secrets *Secrets) Create(key string, rls *rspb.Release) error { lbs.init() lbs.fromMap(rls.Labels) - lbs.set("createdAt", strconv.Itoa(int(time.Now().Unix()))) + lbs.set("createdAt", fmt.Sprintf("%v", time.Now().Unix())) // create a new secret to hold the release obj, err := newSecretsObject(key, rls, lbs) @@ -177,7 +178,7 @@ func (secrets *Secrets) Update(key string, rls *rspb.Release) error { lbs.init() lbs.fromMap(rls.Labels) - lbs.set("modifiedAt", strconv.Itoa(int(time.Now().Unix()))) + lbs.set("modifiedAt", fmt.Sprintf("%v", time.Now().Unix())) // create a new secret object to hold the release obj, err := newSecretsObject(key, rls, lbs) diff --git a/vendor/helm.sh/helm/v3/pkg/time/ctime/ctime.go b/vendor/helm.sh/helm/v3/pkg/time/ctime/ctime.go index f2998d76d5..63a41c0bf4 100644 --- a/vendor/helm.sh/helm/v3/pkg/time/ctime/ctime.go +++ b/vendor/helm.sh/helm/v3/pkg/time/ctime/ctime.go @@ -21,5 +21,9 @@ import ( ) func Created(fi os.FileInfo) time.Time { - return created(fi) + return modified(fi) +} + +func Modified(fi os.FileInfo) time.Time { + return modified(fi) } diff --git a/vendor/helm.sh/helm/v3/pkg/time/ctime/ctime_linux.go b/vendor/helm.sh/helm/v3/pkg/time/ctime/ctime_linux.go index c3cea1d78f..d8a6ea1a17 100644 --- a/vendor/helm.sh/helm/v3/pkg/time/ctime/ctime_linux.go +++ b/vendor/helm.sh/helm/v3/pkg/time/ctime/ctime_linux.go @@ -23,8 +23,8 @@ import ( "time" ) -func created(fi os.FileInfo) time.Time { +func modified(fi os.FileInfo) time.Time { st := fi.Sys().(*syscall.Stat_t) //nolint - return time.Unix(int64(st.Ctim.Sec), int64(st.Ctim.Nsec)) + return time.Unix(int64(st.Mtim.Sec), int64(st.Mtim.Nsec)) } diff --git a/vendor/helm.sh/helm/v3/pkg/time/ctime/ctime_other.go b/vendor/helm.sh/helm/v3/pkg/time/ctime/ctime_other.go index f21ed73479..12afc6df2e 100644 --- a/vendor/helm.sh/helm/v3/pkg/time/ctime/ctime_other.go +++ b/vendor/helm.sh/helm/v3/pkg/time/ctime/ctime_other.go @@ -22,6 +22,6 @@ import ( "time" ) -func created(fi os.FileInfo) time.Time { +func modified(fi os.FileInfo) time.Time { return fi.ModTime() } diff --git a/vendor/k8s.io/api/resource/v1alpha3/generated.proto b/vendor/k8s.io/api/resource/v1alpha3/generated.proto index 13be7cbd8e..e802a01439 100644 --- a/vendor/k8s.io/api/resource/v1alpha3/generated.proto +++ b/vendor/k8s.io/api/resource/v1alpha3/generated.proto @@ -675,7 +675,7 @@ message ResourceClaimStatus { // which issued it knows that it must put the pod back into the queue, // waiting for the ResourceClaim to become usable again. // - // There can be at most 32 such reservations. This may get increased in + // There can be at most 256 such reservations. This may get increased in // the future, but not reduced. // // +optional diff --git a/vendor/k8s.io/api/resource/v1alpha3/types.go b/vendor/k8s.io/api/resource/v1alpha3/types.go index e3d7fd8945..fb4d7041db 100644 --- a/vendor/k8s.io/api/resource/v1alpha3/types.go +++ b/vendor/k8s.io/api/resource/v1alpha3/types.go @@ -687,7 +687,7 @@ type ResourceClaimStatus struct { // which issued it knows that it must put the pod back into the queue, // waiting for the ResourceClaim to become usable again. // - // There can be at most 32 such reservations. This may get increased in + // There can be at most 256 such reservations. This may get increased in // the future, but not reduced. // // +optional @@ -715,9 +715,9 @@ type ResourceClaimStatus struct { Devices []AllocatedDeviceStatus `json:"devices,omitempty" protobuf:"bytes,4,opt,name=devices"` } -// ReservedForMaxSize is the maximum number of entries in +// ResourceClaimReservedForMaxSize is the maximum number of entries in // claim.status.reservedFor. -const ResourceClaimReservedForMaxSize = 32 +const ResourceClaimReservedForMaxSize = 256 // ResourceClaimConsumerReference contains enough information to let you // locate the consumer of a ResourceClaim. The user must be a resource in the same diff --git a/vendor/k8s.io/api/resource/v1alpha3/types_swagger_doc_generated.go b/vendor/k8s.io/api/resource/v1alpha3/types_swagger_doc_generated.go index 1a71d64c10..b41609d118 100644 --- a/vendor/k8s.io/api/resource/v1alpha3/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/resource/v1alpha3/types_swagger_doc_generated.go @@ -291,7 +291,7 @@ func (ResourceClaimSpec) SwaggerDoc() map[string]string { var map_ResourceClaimStatus = map[string]string{ "": "ResourceClaimStatus tracks whether the resource has been allocated and what the result of that was.", "allocation": "Allocation is set once the claim has been allocated successfully.", - "reservedFor": "ReservedFor indicates which entities are currently allowed to use the claim. A Pod which references a ResourceClaim which is not reserved for that Pod will not be started. A claim that is in use or might be in use because it has been reserved must not get deallocated.\n\nIn a cluster with multiple scheduler instances, two pods might get scheduled concurrently by different schedulers. When they reference the same ResourceClaim which already has reached its maximum number of consumers, only one pod can be scheduled.\n\nBoth schedulers try to add their pod to the claim.status.reservedFor field, but only the update that reaches the API server first gets stored. The other one fails with an error and the scheduler which issued it knows that it must put the pod back into the queue, waiting for the ResourceClaim to become usable again.\n\nThere can be at most 32 such reservations. This may get increased in the future, but not reduced.", + "reservedFor": "ReservedFor indicates which entities are currently allowed to use the claim. A Pod which references a ResourceClaim which is not reserved for that Pod will not be started. A claim that is in use or might be in use because it has been reserved must not get deallocated.\n\nIn a cluster with multiple scheduler instances, two pods might get scheduled concurrently by different schedulers. When they reference the same ResourceClaim which already has reached its maximum number of consumers, only one pod can be scheduled.\n\nBoth schedulers try to add their pod to the claim.status.reservedFor field, but only the update that reaches the API server first gets stored. The other one fails with an error and the scheduler which issued it knows that it must put the pod back into the queue, waiting for the ResourceClaim to become usable again.\n\nThere can be at most 256 such reservations. This may get increased in the future, but not reduced.", "devices": "Devices contains the status of each device allocated for this claim, as reported by the driver. This can include driver-specific information. Entries are owned by their respective drivers.", } diff --git a/vendor/k8s.io/api/resource/v1beta1/generated.proto b/vendor/k8s.io/api/resource/v1beta1/generated.proto index 6d525d5b85..4ea13e0337 100644 --- a/vendor/k8s.io/api/resource/v1beta1/generated.proto +++ b/vendor/k8s.io/api/resource/v1beta1/generated.proto @@ -683,7 +683,7 @@ message ResourceClaimStatus { // which issued it knows that it must put the pod back into the queue, // waiting for the ResourceClaim to become usable again. // - // There can be at most 32 such reservations. This may get increased in + // There can be at most 256 such reservations. This may get increased in // the future, but not reduced. // // +optional diff --git a/vendor/k8s.io/api/resource/v1beta1/types.go b/vendor/k8s.io/api/resource/v1beta1/types.go index a7f1ee7b54..ca79c5a664 100644 --- a/vendor/k8s.io/api/resource/v1beta1/types.go +++ b/vendor/k8s.io/api/resource/v1beta1/types.go @@ -695,7 +695,7 @@ type ResourceClaimStatus struct { // which issued it knows that it must put the pod back into the queue, // waiting for the ResourceClaim to become usable again. // - // There can be at most 32 such reservations. This may get increased in + // There can be at most 256 such reservations. This may get increased in // the future, but not reduced. // // +optional @@ -723,9 +723,9 @@ type ResourceClaimStatus struct { Devices []AllocatedDeviceStatus `json:"devices,omitempty" protobuf:"bytes,4,opt,name=devices"` } -// ReservedForMaxSize is the maximum number of entries in +// ResourceClaimReservedForMaxSize is the maximum number of entries in // claim.status.reservedFor. -const ResourceClaimReservedForMaxSize = 32 +const ResourceClaimReservedForMaxSize = 256 // ResourceClaimConsumerReference contains enough information to let you // locate the consumer of a ResourceClaim. The user must be a resource in the same diff --git a/vendor/k8s.io/api/resource/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/api/resource/v1beta1/types_swagger_doc_generated.go index 1d0176cbca..4ecc35d08a 100644 --- a/vendor/k8s.io/api/resource/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/resource/v1beta1/types_swagger_doc_generated.go @@ -300,7 +300,7 @@ func (ResourceClaimSpec) SwaggerDoc() map[string]string { var map_ResourceClaimStatus = map[string]string{ "": "ResourceClaimStatus tracks whether the resource has been allocated and what the result of that was.", "allocation": "Allocation is set once the claim has been allocated successfully.", - "reservedFor": "ReservedFor indicates which entities are currently allowed to use the claim. A Pod which references a ResourceClaim which is not reserved for that Pod will not be started. A claim that is in use or might be in use because it has been reserved must not get deallocated.\n\nIn a cluster with multiple scheduler instances, two pods might get scheduled concurrently by different schedulers. When they reference the same ResourceClaim which already has reached its maximum number of consumers, only one pod can be scheduled.\n\nBoth schedulers try to add their pod to the claim.status.reservedFor field, but only the update that reaches the API server first gets stored. The other one fails with an error and the scheduler which issued it knows that it must put the pod back into the queue, waiting for the ResourceClaim to become usable again.\n\nThere can be at most 32 such reservations. This may get increased in the future, but not reduced.", + "reservedFor": "ReservedFor indicates which entities are currently allowed to use the claim. A Pod which references a ResourceClaim which is not reserved for that Pod will not be started. A claim that is in use or might be in use because it has been reserved must not get deallocated.\n\nIn a cluster with multiple scheduler instances, two pods might get scheduled concurrently by different schedulers. When they reference the same ResourceClaim which already has reached its maximum number of consumers, only one pod can be scheduled.\n\nBoth schedulers try to add their pod to the claim.status.reservedFor field, but only the update that reaches the API server first gets stored. The other one fails with an error and the scheduler which issued it knows that it must put the pod back into the queue, waiting for the ResourceClaim to become usable again.\n\nThere can be at most 256 such reservations. This may get increased in the future, but not reduced.", "devices": "Devices contains the status of each device allocated for this claim, as reported by the driver. This can include driver-specific information. Entries are owned by their respective drivers.", } diff --git a/vendor/k8s.io/client-go/util/retry/OWNERS b/vendor/k8s.io/client-go/util/retry/OWNERS new file mode 100644 index 0000000000..75736b5aac --- /dev/null +++ b/vendor/k8s.io/client-go/util/retry/OWNERS @@ -0,0 +1,4 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +reviewers: + - caesarxuchao diff --git a/vendor/k8s.io/client-go/util/retry/util.go b/vendor/k8s.io/client-go/util/retry/util.go new file mode 100644 index 0000000000..0c6e504a6d --- /dev/null +++ b/vendor/k8s.io/client-go/util/retry/util.go @@ -0,0 +1,105 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package retry + +import ( + "time" + + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/util/wait" +) + +// DefaultRetry is the recommended retry for a conflict where multiple clients +// are making changes to the same resource. +var DefaultRetry = wait.Backoff{ + Steps: 5, + Duration: 10 * time.Millisecond, + Factor: 1.0, + Jitter: 0.1, +} + +// DefaultBackoff is the recommended backoff for a conflict where a client +// may be attempting to make an unrelated modification to a resource under +// active management by one or more controllers. +var DefaultBackoff = wait.Backoff{ + Steps: 4, + Duration: 10 * time.Millisecond, + Factor: 5.0, + Jitter: 0.1, +} + +// OnError allows the caller to retry fn in case the error returned by fn is retriable +// according to the provided function. backoff defines the maximum retries and the wait +// interval between two retries. +func OnError(backoff wait.Backoff, retriable func(error) bool, fn func() error) error { + var lastErr error + err := wait.ExponentialBackoff(backoff, func() (bool, error) { + err := fn() + switch { + case err == nil: + return true, nil + case retriable(err): + lastErr = err + return false, nil + default: + return false, err + } + }) + if err == wait.ErrWaitTimeout { + err = lastErr + } + return err +} + +// RetryOnConflict is used to make an update to a resource when you have to worry about +// conflicts caused by other code making unrelated updates to the resource at the same +// time. fn should fetch the resource to be modified, make appropriate changes to it, try +// to update it, and return (unmodified) the error from the update function. On a +// successful update, RetryOnConflict will return nil. If the update function returns a +// "Conflict" error, RetryOnConflict will wait some amount of time as described by +// backoff, and then try again. On a non-"Conflict" error, or if it retries too many times +// and gives up, RetryOnConflict will return an error to the caller. +// +// err := retry.RetryOnConflict(retry.DefaultRetry, func() error { +// // Fetch the resource here; you need to refetch it on every try, since +// // if you got a conflict on the last update attempt then you need to get +// // the current version before making your own changes. +// pod, err := c.Pods("mynamespace").Get(name, metav1.GetOptions{}) +// if err != nil { +// return err +// } +// +// // Make whatever updates to the resource are needed +// pod.Status.Phase = v1.PodFailed +// +// // Try to update +// _, err = c.Pods("mynamespace").UpdateStatus(pod) +// // You have to return err itself here (not wrapped inside another error) +// // so that RetryOnConflict can identify it correctly. +// return err +// }) +// if err != nil { +// // May be conflict if max retries were hit, or may be something unrelated +// // like permissions or a network error +// return err +// } +// ... +// +// TODO: Make Backoff an interface? +func RetryOnConflict(backoff wait.Backoff, fn func() error) error { + return OnError(backoff, errors.IsConflict, fn) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 196dcaf4be..4303080860 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -11,8 +11,8 @@ github.com/AdaLogics/go-fuzz-headers ## explicit; go 1.16 github.com/Azure/go-ansiterm github.com/Azure/go-ansiterm/winterm -# github.com/BurntSushi/toml v1.3.2 -## explicit; go 1.16 +# github.com/BurntSushi/toml v1.4.0 +## explicit; go 1.18 github.com/BurntSushi/toml github.com/BurntSushi/toml/internal # github.com/MakeNowJust/heredoc v1.0.0 @@ -52,10 +52,10 @@ github.com/chai2010/gettext-go github.com/chai2010/gettext-go/mo github.com/chai2010/gettext-go/plural github.com/chai2010/gettext-go/po -# github.com/cilium/charts v0.0.0-20241218153829-9518b30a2027 +# github.com/cilium/charts v0.0.0-20250122005123-9aa3c2db578d ## explicit; go 1.17 github.com/cilium/charts -# github.com/cilium/cilium v1.17.0-pre.3.0.20250108154004-47bb433883b2 +# github.com/cilium/cilium v1.17.0-pre.3.0.20250129155153-a50d083bc18f ## explicit; go 1.23.0 github.com/cilium/cilium/api/v1/client github.com/cilium/cilium/api/v1/client/bgp @@ -151,7 +151,6 @@ github.com/cilium/cilium/pkg/health/defaults github.com/cilium/cilium/pkg/hive github.com/cilium/cilium/pkg/hive/health github.com/cilium/cilium/pkg/hive/health/types -github.com/cilium/cilium/pkg/hubble github.com/cilium/cilium/pkg/iana github.com/cilium/cilium/pkg/identity github.com/cilium/cilium/pkg/identity/identitymanager @@ -264,7 +263,7 @@ github.com/cilium/ebpf/internal/testutils/fdtrace github.com/cilium/ebpf/internal/tracefs github.com/cilium/ebpf/internal/unix github.com/cilium/ebpf/link -# github.com/cilium/hive v0.0.0-20241213121623-605c1412b9b3 +# github.com/cilium/hive v0.0.0-20250121145729-e67f66eb0375 ## explicit; go 1.21.3 github.com/cilium/hive github.com/cilium/hive/cell @@ -595,7 +594,7 @@ github.com/cncf/xds/go/xds/annotations/v3 github.com/cncf/xds/go/xds/core/v3 github.com/cncf/xds/go/xds/type/matcher/v3 github.com/cncf/xds/go/xds/type/v3 -# github.com/containerd/containerd v1.7.23 +# github.com/containerd/containerd v1.7.24 ## explicit; go 1.21 github.com/containerd/containerd/archive/compression github.com/containerd/containerd/content @@ -629,8 +628,8 @@ github.com/coreos/go-semver/semver # github.com/coreos/go-systemd/v22 v22.5.0 ## explicit; go 1.12 github.com/coreos/go-systemd/v22/journal -# github.com/cyphar/filepath-securejoin v0.3.4 -## explicit; go 1.21 +# github.com/cyphar/filepath-securejoin v0.3.6 +## explicit; go 1.18 github.com/cyphar/filepath-securejoin # github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc ## explicit @@ -656,7 +655,7 @@ github.com/docker/distribution/registry/client/auth/challenge github.com/docker/distribution/registry/client/transport github.com/docker/distribution/registry/storage/cache github.com/docker/distribution/registry/storage/cache/memory -# github.com/docker/docker v27.4.1+incompatible +# github.com/docker/docker v27.5.1+incompatible ## explicit github.com/docker/docker/api/types/filters github.com/docker/docker/api/types/registry @@ -785,7 +784,7 @@ github.com/golang/protobuf/ptypes github.com/golang/protobuf/ptypes/any github.com/golang/protobuf/ptypes/duration github.com/golang/protobuf/ptypes/timestamp -# github.com/google/btree v1.1.2 +# github.com/google/btree v1.1.3 ## explicit; go 1.18 github.com/google/btree # github.com/google/certificate-transparency-go v1.1.7 @@ -813,6 +812,12 @@ github.com/google/go-cmp/cmp/internal/diff github.com/google/go-cmp/cmp/internal/flags github.com/google/go-cmp/cmp/internal/function github.com/google/go-cmp/cmp/internal/value +# github.com/google/go-github/v68 v68.0.0 +## explicit; go 1.21 +github.com/google/go-github/v68/github +# github.com/google/go-querystring v1.1.0 +## explicit; go 1.10 +github.com/google/go-querystring/query # github.com/google/gofuzz v1.2.0 ## explicit; go 1.12 github.com/google/gofuzz @@ -1014,7 +1019,7 @@ github.com/prometheus/client_golang/prometheus/promhttp # github.com/prometheus/client_model v0.6.1 ## explicit; go 1.19 github.com/prometheus/client_model/go -# github.com/prometheus/common v0.61.0 +# github.com/prometheus/common v0.62.0 ## explicit; go 1.21 github.com/prometheus/common/expfmt github.com/prometheus/common/model @@ -1026,7 +1031,7 @@ github.com/prometheus/procfs/internal/util # github.com/rivo/uniseg v0.4.4 ## explicit; go 1.18 github.com/rivo/uniseg -# github.com/rubenv/sql-migrate v1.7.0 +# github.com/rubenv/sql-migrate v1.7.1 ## explicit; go 1.21 github.com/rubenv/sql-migrate github.com/rubenv/sql-migrate/sqlparse @@ -1055,8 +1060,8 @@ github.com/sourcegraph/conc github.com/sourcegraph/conc/internal/multierror github.com/sourcegraph/conc/iter github.com/sourcegraph/conc/panics -# github.com/spf13/afero v1.11.0 -## explicit; go 1.19 +# github.com/spf13/afero v1.12.0 +## explicit; go 1.21 github.com/spf13/afero github.com/spf13/afero/internal/common github.com/spf13/afero/mem @@ -1066,7 +1071,7 @@ github.com/spf13/cast # github.com/spf13/cobra v1.8.1 ## explicit; go 1.15 github.com/spf13/cobra -# github.com/spf13/pflag v1.0.6-0.20210604193023-d5e0c0615ace +# github.com/spf13/pflag v1.0.6-0.20250109003754-5ca813443bd2 ## explicit; go 1.12 github.com/spf13/pflag # github.com/spf13/viper v1.19.0 @@ -1084,7 +1089,7 @@ github.com/spf13/viper/internal/features # github.com/subosito/gotenv v1.6.0 ## explicit; go 1.18 github.com/subosito/gotenv -# github.com/vishvananda/netlink v1.3.1-0.20241227191253-26ee0e2abe2d +# github.com/vishvananda/netlink v1.3.1-0.20250121061148-364253875734 ## explicit; go 1.12 github.com/vishvananda/netlink github.com/vishvananda/netlink/nl @@ -1168,12 +1173,13 @@ go.mongodb.org/mongo-driver/x/bsonx/bsoncore ## explicit; go 1.22.0 go.opentelemetry.io/auto/sdk go.opentelemetry.io/auto/sdk/internal/telemetry -# go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 +# go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 ## explicit; go 1.21 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil -# go.opentelemetry.io/otel v1.33.0 +# go.opentelemetry.io/otel v1.34.0 ## explicit; go 1.22.0 go.opentelemetry.io/otel go.opentelemetry.io/otel/attribute @@ -1189,13 +1195,13 @@ go.opentelemetry.io/otel/semconv/v1.17.0 go.opentelemetry.io/otel/semconv/v1.17.0/httpconv go.opentelemetry.io/otel/semconv/v1.20.0 go.opentelemetry.io/otel/semconv/v1.21.0 -go.opentelemetry.io/otel/semconv/v1.24.0 go.opentelemetry.io/otel/semconv/v1.26.0 -# go.opentelemetry.io/otel/metric v1.33.0 +# go.opentelemetry.io/otel/metric v1.34.0 ## explicit; go 1.22.0 go.opentelemetry.io/otel/metric go.opentelemetry.io/otel/metric/embedded -# go.opentelemetry.io/otel/trace v1.33.0 +go.opentelemetry.io/otel/metric/noop +# go.opentelemetry.io/otel/trace v1.34.0 ## explicit; go 1.22.0 go.opentelemetry.io/otel/trace go.opentelemetry.io/otel/trace/embedded @@ -1269,7 +1275,7 @@ golang.org/x/net/internal/timeseries golang.org/x/net/proxy golang.org/x/net/trace golang.org/x/net/websocket -# golang.org/x/oauth2 v0.24.0 +# golang.org/x/oauth2 v0.25.0 ## explicit; go 1.18 golang.org/x/oauth2 golang.org/x/oauth2/internal @@ -1310,10 +1316,10 @@ golang.org/x/tools/txtar google.golang.org/genproto/googleapis/api google.golang.org/genproto/googleapis/api/annotations google.golang.org/genproto/googleapis/api/expr/v1alpha1 -# google.golang.org/genproto/googleapis/rpc v0.0.0-20250106144421-5f5ef82da422 +# google.golang.org/genproto/googleapis/rpc v0.0.0-20250122153221-138b5a5a4fd4 ## explicit; go 1.22 google.golang.org/genproto/googleapis/rpc/status -# google.golang.org/grpc v1.69.2 +# google.golang.org/grpc v1.69.4 ## explicit; go 1.22 google.golang.org/grpc google.golang.org/grpc/attributes @@ -1373,7 +1379,7 @@ google.golang.org/grpc/serviceconfig google.golang.org/grpc/stats google.golang.org/grpc/status google.golang.org/grpc/tap -# google.golang.org/protobuf v1.36.2 +# google.golang.org/protobuf v1.36.3 ## explicit; go 1.21 google.golang.org/protobuf/encoding/protodelim google.golang.org/protobuf/encoding/protojson @@ -1429,8 +1435,8 @@ gopkg.in/ini.v1 # gopkg.in/yaml.v3 v3.0.1 ## explicit gopkg.in/yaml.v3 -# helm.sh/helm/v3 v3.16.4 -## explicit; go 1.22.0 +# helm.sh/helm/v3 v3.17.0 +## explicit; go 1.23.0 helm.sh/helm/v3/internal/fileutil helm.sh/helm/v3/internal/resolver helm.sh/helm/v3/internal/sympath @@ -1471,7 +1477,7 @@ helm.sh/helm/v3/pkg/strvals helm.sh/helm/v3/pkg/time helm.sh/helm/v3/pkg/time/ctime helm.sh/helm/v3/pkg/uploader -# k8s.io/api v0.32.0 +# k8s.io/api v0.32.1 ## explicit; go 1.23.0 k8s.io/api/admission/v1 k8s.io/api/admission/v1beta1 @@ -1532,7 +1538,7 @@ k8s.io/api/storage/v1 k8s.io/api/storage/v1alpha1 k8s.io/api/storage/v1beta1 k8s.io/api/storagemigration/v1alpha1 -# k8s.io/apiextensions-apiserver v0.32.0 +# k8s.io/apiextensions-apiserver v0.32.1 ## explicit; go 1.23.0 k8s.io/apiextensions-apiserver/pkg/apis/apiextensions k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1 @@ -1548,7 +1554,7 @@ k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextension k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1/fake k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1 k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake -# k8s.io/apimachinery v0.32.0 +# k8s.io/apimachinery v0.32.1 ## explicit; go 1.23.0 k8s.io/apimachinery/pkg/api/equality k8s.io/apimachinery/pkg/api/errors @@ -1613,16 +1619,16 @@ k8s.io/apimachinery/pkg/watch k8s.io/apimachinery/third_party/forked/golang/json k8s.io/apimachinery/third_party/forked/golang/netutil k8s.io/apimachinery/third_party/forked/golang/reflect -# k8s.io/apiserver v0.32.0 +# k8s.io/apiserver v0.32.1 ## explicit; go 1.23.0 k8s.io/apiserver/pkg/endpoints/deprecation -# k8s.io/cli-runtime v0.32.0 +# k8s.io/cli-runtime v0.32.1 ## explicit; go 1.23.0 k8s.io/cli-runtime/pkg/genericclioptions k8s.io/cli-runtime/pkg/genericiooptions k8s.io/cli-runtime/pkg/printers k8s.io/cli-runtime/pkg/resource -# k8s.io/client-go v0.32.0 +# k8s.io/client-go v0.32.1 ## explicit; go 1.23.0 k8s.io/client-go/applyconfigurations k8s.io/client-go/applyconfigurations/admissionregistration/v1 @@ -1847,9 +1853,10 @@ k8s.io/client-go/util/flowcontrol k8s.io/client-go/util/homedir k8s.io/client-go/util/jsonpath k8s.io/client-go/util/keyutil +k8s.io/client-go/util/retry k8s.io/client-go/util/watchlist k8s.io/client-go/util/workqueue -# k8s.io/component-base v0.32.0 +# k8s.io/component-base v0.32.1 ## explicit; go 1.23.0 k8s.io/component-base/version # k8s.io/klog/v2 v2.130.1 @@ -1873,7 +1880,7 @@ k8s.io/kube-openapi/pkg/spec3 k8s.io/kube-openapi/pkg/util/proto k8s.io/kube-openapi/pkg/util/proto/validation k8s.io/kube-openapi/pkg/validation/spec -# k8s.io/kubectl v0.32.0 +# k8s.io/kubectl v0.32.1 ## explicit; go 1.23.0 k8s.io/kubectl/pkg/cmd/util k8s.io/kubectl/pkg/scheme @@ -1910,8 +1917,8 @@ oras.land/oras-go/pkg/registry/remote/auth oras.land/oras-go/pkg/registry/remote/internal/errutil oras.land/oras-go/pkg/registry/remote/internal/syncutil oras.land/oras-go/pkg/target -# sigs.k8s.io/controller-runtime v0.19.3 -## explicit; go 1.22.0 +# sigs.k8s.io/controller-runtime v0.20.1 +## explicit; go 1.23.0 sigs.k8s.io/controller-runtime/pkg/client/apiutil # sigs.k8s.io/gateway-api v1.2.1 ## explicit; go 1.22.0 @@ -2000,8 +2007,8 @@ sigs.k8s.io/kustomize/kyaml/yaml/internal/k8sgen/pkg/util/validation/field sigs.k8s.io/kustomize/kyaml/yaml/merge2 sigs.k8s.io/kustomize/kyaml/yaml/schema sigs.k8s.io/kustomize/kyaml/yaml/walk -# sigs.k8s.io/mcs-api v0.1.1-0.20241217092652-fede3192824f -## explicit; go 1.22.0 +# sigs.k8s.io/mcs-api v0.1.1-0.20250116162235-62ede9a032dc +## explicit; go 1.23.0 sigs.k8s.io/mcs-api/pkg/apis/v1alpha1 sigs.k8s.io/mcs-api/pkg/client/clientset/versioned sigs.k8s.io/mcs-api/pkg/client/clientset/versioned/fake diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/client/apiutil/restmapper.go b/vendor/sigs.k8s.io/controller-runtime/pkg/client/apiutil/restmapper.go index 927be22b4e..ad898617fa 100644 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/client/apiutil/restmapper.go +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/client/apiutil/restmapper.go @@ -28,6 +28,7 @@ import ( "k8s.io/client-go/discovery" "k8s.io/client-go/rest" "k8s.io/client-go/restmapper" + "k8s.io/utils/ptr" ) // NewDynamicRESTMapper returns a dynamic RESTMapper for cfg. The dynamic @@ -41,6 +42,7 @@ func NewDynamicRESTMapper(cfg *rest.Config, httpClient *http.Client) (meta.RESTM if err != nil { return nil, err } + return &mapper{ mapper: restmapper.NewDiscoveryRESTMapper([]*restmapper.APIGroupResources{}), client: client, @@ -53,11 +55,15 @@ func NewDynamicRESTMapper(cfg *rest.Config, httpClient *http.Client) (meta.RESTM // client for discovery information to do REST mappings. type mapper struct { mapper meta.RESTMapper - client discovery.DiscoveryInterface + client discovery.AggregatedDiscoveryInterface knownGroups map[string]*restmapper.APIGroupResources apiGroups map[string]*metav1.APIGroup + initialDiscoveryDone bool + // mutex to provide thread-safe mapper reloading. + // It protects all fields in the mapper as well as methods + // that have the `Locked` suffix. mu sync.RWMutex } @@ -159,28 +165,42 @@ func (m *mapper) addKnownGroupAndReload(groupName string, versions ...string) er versions = nil } + m.mu.Lock() + defer m.mu.Unlock() // If no specific versions are set by user, we will scan all available ones for the API group. // This operation requires 2 requests: /api and /apis, but only once. For all subsequent calls // this data will be taken from cache. - if len(versions) == 0 { - apiGroup, err := m.findAPIGroupByName(groupName) + // + // We always run this once, because if the server supports aggregated discovery, this will + // load everything with two api calls which we assume is overall cheaper. + if len(versions) == 0 || !m.initialDiscoveryDone { + apiGroup, didAggregatedDiscovery, err := m.findAPIGroupByNameAndMaybeAggregatedDiscoveryLocked(groupName) if err != nil { return err } - if apiGroup != nil { + if apiGroup != nil && len(versions) == 0 { for _, version := range apiGroup.Versions { versions = append(versions, version.Version) } } - } - m.mu.Lock() - defer m.mu.Unlock() - - // Create or fetch group resources from cache. - groupResources := &restmapper.APIGroupResources{ - Group: metav1.APIGroup{Name: groupName}, - VersionedResources: make(map[string][]metav1.APIResource), + // No need to do anything further if aggregatedDiscovery is supported and we did a lookup + if didAggregatedDiscovery { + failedGroups := make(map[schema.GroupVersion]error) + for _, version := range versions { + if m.knownGroups[groupName] == nil || m.knownGroups[groupName].VersionedResources[version] == nil { + failedGroups[schema.GroupVersion{Group: groupName, Version: version}] = &meta.NoResourceMatchError{ + PartialResource: schema.GroupVersionResource{ + Group: groupName, + Version: version, + }} + } + } + if len(failedGroups) > 0 { + return ptr.To(ErrResourceDiscoveryFailed(failedGroups)) + } + return nil + } } // Update information for group resources about versioned resources. @@ -194,13 +214,26 @@ func (m *mapper) addKnownGroupAndReload(groupName string, versions ...string) er return fmt.Errorf("failed to get API group resources: %w", err) } - if _, ok := m.knownGroups[groupName]; ok { - groupResources = m.knownGroups[groupName] - } + m.addGroupVersionResourcesToCacheAndReloadLocked(groupVersionResources) + return nil +} +// addGroupVersionResourcesToCacheAndReloadLocked does what the name suggests. The mutex must be held when +// calling it. +func (m *mapper) addGroupVersionResourcesToCacheAndReloadLocked(gvr map[schema.GroupVersion]*metav1.APIResourceList) { // Update information for group resources about the API group by adding new versions. - // Ignore the versions that are already registered. - for groupVersion, resources := range groupVersionResources { + // Ignore the versions that are already registered + for groupVersion, resources := range gvr { + var groupResources *restmapper.APIGroupResources + if _, ok := m.knownGroups[groupVersion.Group]; ok { + groupResources = m.knownGroups[groupVersion.Group] + } else { + groupResources = &restmapper.APIGroupResources{ + Group: metav1.APIGroup{Name: groupVersion.Group}, + VersionedResources: make(map[string][]metav1.APIResource), + } + } + version := groupVersion.Version groupResources.VersionedResources[version] = resources.APIResources @@ -214,60 +247,56 @@ func (m *mapper) addKnownGroupAndReload(groupName string, versions ...string) er if !found { groupResources.Group.Versions = append(groupResources.Group.Versions, metav1.GroupVersionForDiscovery{ - GroupVersion: metav1.GroupVersion{Group: groupName, Version: version}.String(), + GroupVersion: metav1.GroupVersion{Group: groupVersion.Group, Version: version}.String(), Version: version, }) } - } - // Update data in the cache. - m.knownGroups[groupName] = groupResources + // Update data in the cache. + m.knownGroups[groupVersion.Group] = groupResources + } - // Finally, update the group with received information and regenerate the mapper. + // Finally, reload the mapper. updatedGroupResources := make([]*restmapper.APIGroupResources, 0, len(m.knownGroups)) for _, agr := range m.knownGroups { updatedGroupResources = append(updatedGroupResources, agr) } m.mapper = restmapper.NewDiscoveryRESTMapper(updatedGroupResources) - return nil } -// findAPIGroupByNameLocked returns API group by its name. -func (m *mapper) findAPIGroupByName(groupName string) (*metav1.APIGroup, error) { - // Looking in the cache first. - { - m.mu.RLock() - group, ok := m.apiGroups[groupName] - m.mu.RUnlock() - if ok { - return group, nil - } +// findAPIGroupByNameAndMaybeAggregatedDiscoveryLocked tries to find the passed apiGroup. +// If the server supports aggregated discovery, it will always perform that. +func (m *mapper) findAPIGroupByNameAndMaybeAggregatedDiscoveryLocked(groupName string) (_ *metav1.APIGroup, didAggregatedDiscovery bool, _ error) { + // Looking in the cache first + group, ok := m.apiGroups[groupName] + if ok { + return group, false, nil } // Update the cache if nothing was found. - apiGroups, err := m.client.ServerGroups() + apiGroups, maybeResources, _, err := m.client.GroupsAndMaybeResources() if err != nil { - return nil, fmt.Errorf("failed to get server groups: %w", err) + return nil, false, fmt.Errorf("failed to get server groups: %w", err) } if len(apiGroups.Groups) == 0 { - return nil, fmt.Errorf("received an empty API groups list") + return nil, false, fmt.Errorf("received an empty API groups list") } - m.mu.Lock() + m.initialDiscoveryDone = true + if len(maybeResources) > 0 { + didAggregatedDiscovery = true + m.addGroupVersionResourcesToCacheAndReloadLocked(maybeResources) + } for i := range apiGroups.Groups { group := &apiGroups.Groups[i] m.apiGroups[group.Name] = group } - m.mu.Unlock() // Looking in the cache again. - m.mu.RLock() - defer m.mu.RUnlock() - // Don't return an error here if the API group is not present. // The reloaded RESTMapper will take care of returning a NoMatchError. - return m.apiGroups[groupName], nil + return m.apiGroups[groupName], didAggregatedDiscovery, nil } // fetchGroupVersionResourcesLocked fetches the resources for the specified group and its versions. @@ -283,10 +312,10 @@ func (m *mapper) fetchGroupVersionResourcesLocked(groupName string, versions ... if apierrors.IsNotFound(err) { // If the version is not found, we remove the group from the cache // so it gets refreshed on the next call. - if m.isAPIGroupCached(groupVersion) { + if m.isAPIGroupCachedLocked(groupVersion) { delete(m.apiGroups, groupName) } - if m.isGroupVersionCached(groupVersion) { + if m.isGroupVersionCachedLocked(groupVersion) { delete(m.knownGroups, groupName) } continue @@ -308,8 +337,8 @@ func (m *mapper) fetchGroupVersionResourcesLocked(groupName string, versions ... return groupVersionResources, nil } -// isGroupVersionCached checks if a version for a group is cached in the known groups cache. -func (m *mapper) isGroupVersionCached(gv schema.GroupVersion) bool { +// isGroupVersionCachedLocked checks if a version for a group is cached in the known groups cache. +func (m *mapper) isGroupVersionCachedLocked(gv schema.GroupVersion) bool { if cachedGroup, ok := m.knownGroups[gv.Group]; ok { _, cached := cachedGroup.VersionedResources[gv.Version] return cached @@ -318,8 +347,8 @@ func (m *mapper) isGroupVersionCached(gv schema.GroupVersion) bool { return false } -// isAPIGroupCached checks if a version for a group is cached in the api groups cache. -func (m *mapper) isAPIGroupCached(gv schema.GroupVersion) bool { +// isAPIGroupCachedLocked checks if a version for a group is cached in the api groups cache. +func (m *mapper) isAPIGroupCachedLocked(gv schema.GroupVersion) bool { cachedGroup, ok := m.apiGroups[gv.Group] if !ok { return false diff --git a/vendor/sigs.k8s.io/mcs-api/pkg/apis/v1alpha1/serviceimport.go b/vendor/sigs.k8s.io/mcs-api/pkg/apis/v1alpha1/serviceimport.go index 11103da04e..813cc7a74f 100644 --- a/vendor/sigs.k8s.io/mcs-api/pkg/apis/v1alpha1/serviceimport.go +++ b/vendor/sigs.k8s.io/mcs-api/pkg/apis/v1alpha1/serviceimport.go @@ -53,7 +53,7 @@ type ServiceImportSpec struct { // +listType=atomic Ports []ServicePort `json:"ports"` // ip will be used as the VIP for this service when type is ClusterSetIP. - // +kubebuilder:validation:MaxItems:=1 + // +kubebuilder:validation:MaxItems:=2 // +optional IPs []string `json:"ips,omitempty"` // type defines the type of this service.

$Ip!!bjO!XH^9&T5&{G6~7)+UyrHbczVYaF!d`Sq<0ld|2-dA z?%inE5pZ*um*