Skip to content

Conversation

aThorp96
Copy link
Member

📝 Description of the Change

Add support for optional namespace parameter in incoming webhook

When a Repository CR does not have a unique name in the cluster, a user must disambiguate the desired Repository by specifying a Namespace. The namespace is optional by default, but if the matcher finds more than one Repository of the same name then PaC will respond with the code 400 and indicate that the "namespace" parameter is required due to the ambiguity.

👨🏻‍ Linked Jira

https://issues.redhat.com/browse/SRVKP-5837

🔗 Linked GitHub Issue

Fixes #

🚀 Type of Change

  • 🐛 Bug fix (fix:)
  • ✨ New feature (feat:)
  • 💥 Breaking change (feat!:, fix!:)
  • 📚 Documentation update (docs:)
  • ⚙️ Chore (chore:)
  • 💅 Refactor (refactor:)
  • 🔧 Enhancement (enhance:)
  • 📦 Dependency update (deps:)

🧪 Testing Strategy

  • Unit tests
  • Integration tests
  • End-to-end tests
  • Manual testing
  • Not Applicable

🤖 AI Assistance

  • I have not used any AI assistance for this PR.
  • I have used AI assistance for this PR.

If you have used AI assistance, please provide the following details:

Which LLM was used?

  • GitHub Copilot
  • ChatGPT (OpenAI)
  • Claude (Anthropic)
  • Cursor
  • Gemini (Google)
  • Other: ____________

Extent of AI Assistance:

  • Documentation and research only
  • Unit tests or E2E tests only
  • Code generation (parts of the code)
  • Full code generation (most of the PR)
  • PR description and comments
  • Commit message(s)

Important

If the majority of the code in this PR was generated by an AI, please add a Co-authored-by trailer to your commit message.
For example:

Co-authored-by: Gemini [email protected]
Co-authored-by: ChatGPT [email protected]
Co-authored-by: Claude [email protected]
Co-authored-by: Cursor [email protected]
Co-authored-by: Copilot [email protected]

**💡You can use the script ./hack/add-llm-coauthor.sh to automatically add
these co-author trailers to your commits.

✅ Submitter Checklist

  • 📝 My commit messages are clear, informative, and follow the project's How to write a git commit message guide. The Gitlint linter ensures in CI it's properly validated
  • ✨ I have ensured my commit message prefix (e.g., fix:, feat:) matches the "Type of Change" I selected above.
  • ♽ I have run make test and make lint locally to check for and fix any
    issues. For an efficient workflow, I have considered installing
    pre-commit and running pre-commit install to
    automate these checks.
  • 📖 I have added or updated documentation for any user-facing changes.
  • 🧪 I have added sufficient unit tests for my code changes.
  • 🎁 I have added end-to-end tests where feasible. See README for more details.
  • 🔎 I have addressed any CI test flakiness or provided a clear reason to bypass it.
  • If adding a provider feature, I have filled in the following and updated the provider documentation:
    • GitHub App
    • GitHub Webhook
    • Gitea/Forgejo
    • GitLab
    • Bitbucket Cloud
    • Bitbucket Data Center

Copy link

Summary of Changes

Hello @aThorp96, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the incoming webhook functionality by introducing an optional namespace parameter. This allows for precise targeting of Repository Custom Resources, resolving potential naming conflicts in environments where repository names might not be globally unique. The change includes significant refactoring of webhook payload parsing and validation, leading to more robust error handling and clearer documentation for users.

Highlights

  • Optional Namespace Parameter for Incoming Webhooks: Added support for an optional namespace parameter in incoming webhook requests. This parameter allows users to specify the Kubernetes namespace of a Repository Custom Resource (CR) to disambiguate when multiple repositories with the same name exist across different namespaces.
  • Improved Ambiguity Handling: If an incoming webhook request targets a repository name that is not unique in the cluster and no namespace is provided, the system will now respond with an HTTP 400 Bad Request error, explicitly indicating that the namespace parameter is required.
  • Refactored Webhook Payload Parsing: The internal logic for parsing incoming webhook payloads has been refactored. A new incomingPayload struct and parseIncomingPayload function were introduced to handle both legacy URL query parameters and the recommended JSON POST body, improving code clarity and maintainability.
  • Enhanced Error Reporting: More specific error messages are now returned for missing required fields in incoming webhook requests, aiding in debugging and user experience.
  • Documentation Update: The documentation for incoming webhooks has been updated to include the new namespace parameter in the 'Required Parameters' table, clarifying its usage and conditional requirement.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for an optional namespace parameter for incoming webhooks, which is a great feature for disambiguating repositories with conflicting names. The refactoring to introduce an incomingPayload struct and the performance improvement in GetRepoByName by using a field selector are excellent changes. The documentation has also been updated clearly.

I have a couple of suggestions for improvement. First, the error handling for incoming webhooks doesn't cover all cases, potentially leaving client requests without a response on certain errors. Second, the logic for parsing webhook parameters could lead to confusing behavior by implicitly mixing parameters from the URL query and the JSON body. My review includes suggestions to address these points.

Comment on lines +180 to +184
if errors.Is(err, errMissingFields) {
l.writeResponse(response, http.StatusBadRequest, err.Error())
}
l.logger.Errorf("error processing incoming webhook: %v", err)
return

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The error handling here is improved, but it still doesn't handle all error cases correctly. If l.detectIncoming returns an error that is not errDeprecatedRequestMode or errMissingFields, the error is logged but no HTTP response is sent to the client. This will likely result in the client request timing out or receiving an empty response, which is not ideal.

You should handle all other errors by sending an appropriate HTTP status code, for example, http.StatusInternalServerError for unexpected errors.

if errors.Is(err, errMissingFields) {
					l.writeResponse(response, http.StatusBadRequest, err.Error())
				} else {
					l.writeResponse(response, http.StatusInternalServerError, "Error processing incoming webhook")
				}
				l.logger.Errorf("error processing incoming webhook: %v", err)
				return

Copy link
Member Author

@aThorp96 aThorp96 Oct 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This preserves the current behavior and I believe it is expected? Leaving up to @chmouel or @zakisk to resolve or confirm this needs to be addressed

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't come back with custom HTTP Status code currently, it's not a bad idea, but this hasn't been requested yet, so we may skip it

When a Repository CR does not have a unique name in the cluster, a user
must disambiguate the desired Repository by specifying a Namespace.
The namespace is optional by default, but if the matcher finds more than
one Repository of the same name then PaC will respond with the code 400
and indicate that the "namespace" parameter is required due to the
ambiguity.
@aThorp96 aThorp96 force-pushed the srvkp-5837-incoming-webhook-repo-conflict branch from 60619ad to 66f9939 Compare October 13, 2025 23:18
Comment on lines +175 to +179
if errors.Is(err, errDeprecatedRequestMode) {
// TODO: change this to a request failure once the deprecation is removed
// In this specific case the error can be non-nil while the rest of the return values are valid
response.Header().Add("Deprecation", "true")
} else {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: this is new behavior and not particularly related to the principal change.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we should use a X- prefixed header for that?

Comment on lines +180 to +182
if errors.Is(err, errMissingFields) {
l.writeResponse(response, http.StatusBadRequest, err.Error())
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea here being: If the required fields are missing then an errMissingFields is returned. If an optional field becomes required at runtime, the handler just cares that there was a missing field so an errMissingFields is also returned.

}

repo, err := matcher.GetRepo(ctx, l.run, repository)
repo, err := matcher.GetRepoByName(ctx, l.run, payload.RepoName, payload.Namespace)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If no namespace is provided, the zero value "" acts as a wildcard in GetRepoByName's kubeapi request

Comment on lines +28 to +45
var errDeprecatedRequestMode = errors.New("requesting with secret name in query parameters is deprecated and will not be supported in future versions")

var errMissingFields = errors.New("missing required fields")

func errMissingSpecificFields(fields []string) error {
return fmt.Errorf("%w: %s", errMissingFields, fields)
}

type incomingPayload struct {
legacyMode bool // indicates the request was made using the deprecated queryparams method

RepoName string `json:"repository"`
Namespace string `json:"namespace,omitempty"` // Optional unless Repository name is not unique
Branch string `json:"branch"`
PipelineRun string `json:"pipelinerun"`
Secret string `json:"secret"`
Params map[string]any `json:"params"`
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aThorp96 I see a lot done for deprecation, can we have it in separate commit for better tracking?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah i agree i think we can add the feature in one PR and refactoring and depreactioin in the other

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I can factor that into a separate PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants