diff --git a/.github/copilot-code-review.yml b/.github/copilot-code-review.yml new file mode 100644 index 000000000..faab45ea5 --- /dev/null +++ b/.github/copilot-code-review.yml @@ -0,0 +1,71 @@ +# Copyright 2026 The kpt 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. + +# Copilot code review configuration for Porch +# Porch is a Kubernetes package orchestration system using controller-runtime. + +review: + instructions: + # Linter overlap — these are already enforced by golangci-lint in CI + - "Do not comment on issues caught by: errcheck, govet, ineffassign, staticcheck, unused, nosprintfhostport, gofmt" + - "Do not comment on import ordering or formatting" + - "Do not flag SA1019 deprecation warnings on client.Apply — this is intentionally suppressed" + + # Style — established project conventions, not up for debate + - "Do not comment on error wrapping style (this project uses fmt.Errorf with %w consistently)" + - "Do not suggest renaming variables, functions, or packages" + - "Do not suggest extracting single-use helper functions" + - "Do not suggest adding comments to exported symbols unless the function is non-obvious" + + # Architecture context + - "This project uses Kubernetes controller-runtime with Server-Side Apply (SSA)" + - "Controllers use distinct field managers and ForceOwnership — do not flag this as a concern" + - "Reconcile functions returning (*ctrl.Result, error) where nil result means continue is an intentional pattern" + - "Errors intentionally not returned to controller-runtime (returned as nil) is a deliberate choice to avoid requeue backoff — do not flag this" + - "log.FromContext(ctx) with V-levels is the logging convention — do not suggest alternatives" + + # What to actually review + - "Focus on: logic errors, race conditions, resource leaks, deadlocks, nil pointer dereferences" + - "Flag: missing context cancellation checks, unbounded goroutines, missing error handling in deferred Close calls" + - "Flag: incorrect SSA field manager usage, writing fields owned by another controller" + - "Flag: security issues (credential leaks, injection, TOCTOU)" + - "Flag: incorrect Kubernetes API usage (wrong GVK, missing RBAC, broken owner references)" + + path_instructions: + - path: "api/generated/**" + instructions: "Do not review — generated by k8s code-generator" + - path: "**/zz_generated*" + instructions: "Do not review — generated by controller-tools" + - path: "test/mockery/mocks/**" + instructions: "Do not review — generated by mockery" + - path: "third_party/**" + instructions: "Do not review — vendored upstream code" + - path: "go.sum" + instructions: "Do not review" + - path: "go.mod" + instructions: "Only flag if a dependency looks suspicious or has a known CVE" + - path: "docs/**" + instructions: "Only flag factual errors or broken links. Do not comment on grammar or style" + - path: "**/*_test.go" + instructions: "Focus on correctness, flakiness risks, and missing edge case coverage. Do not suggest style changes. testify (assert/require/mock) and Ginkgo/Gomega are the test frameworks. Suggest using testify assertions or Ginkgo/Gomega matchers instead of raw t.Errorf/t.Fatalf" + - path: "test/e2e/**" + instructions: "Focus on test reliability and resource cleanup. Do not suggest refactoring test helpers" + - path: "test/**" + instructions: "Only flag correctness/security issues; avoid style/linter-overlap feedback. Note: golangci-lint excludes test/ from CI linting." + - path: ".github/**" + instructions: "Focus on security (pinned actions, minimal permissions, injection risks). Do not suggest cosmetic changes" + - path: "deployments/**" + instructions: "Focus on correctness of RBAC, resource limits, and security context. Do not comment on YAML style" + - path: "examples/**" + instructions: "Do not review — tutorial/example configs excluded from CI linting" diff --git a/.github/workflows/copilot-review.yaml b/.github/workflows/copilot-review.yaml new file mode 100644 index 000000000..ee3cbaf47 --- /dev/null +++ b/.github/workflows/copilot-review.yaml @@ -0,0 +1,57 @@ +# Copyright 2026 The kpt 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. + +# Request Copilot review when a PR is opened, reopened, or marked ready for review (non-draft). +# Further reviews can be requested manually via the GitHub UI. +# +# Prerequisite: Disable automatic Copilot code review in repo settings +# (Settings → Copilot → Code review → Disable automatic reviews) + +name: Copilot Code Review + +on: + pull_request: + types: [opened, ready_for_review, reopened] + +permissions: {} + +jobs: + request-copilot-review: + if: github.event.pull_request.draft == false && github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - name: Request Copilot review + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + with: + script: | + const prNumber = context.payload.pull_request.number; + core.info(`Requesting Copilot review for PR #${prNumber}`); + + try { + await github.rest.pulls.requestReviewers({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber, + reviewers: ['copilot-pull-request-reviewer[bot]'], + }); + core.info(`✅ Copilot review requested for PR #${prNumber}`); + } catch (error) { + if (error.status === 422) { + core.info(`Copilot review already requested or cannot be requested: ${error.message}`); + } else { + core.warning(`Could not request Copilot review: ${error.message}`); + } + }