Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ Create `config.yaml` in your data directory:
# yaml-language-server: $schema=https://raw.githubusercontent.com/myk-org/github-webhook-server/refs/heads/main/webhook_server/config/schema.yaml

github-app-id: 123456
webhook_ip: https://your-domain.com
webhook-ip: https://your-domain.com
github-tokens:
- ghp_your_github_token

Expand Down Expand Up @@ -244,10 +244,10 @@ repositories:
my-project:
name: my-org/my-project
log-level: DEBUG
slack_webhook_url: https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK
slack-webhook-url: https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK

# CI/CD Features
verified_job: true
verified-job: true
pre-commit: true

# Testing Configuration
Expand Down Expand Up @@ -364,18 +364,18 @@ uv run pytest webhook_server/tests/test_config_schema.py::TestConfigSchema::test
| ------------ | ---------------------------------------------------------------------------------------- |
| **Server** | `ip-bind`, `port`, `max-workers`, `log-level`, `log-file` |
| **Security** | `webhook-secret`, `verify-github-ips`, `verify-cloudflare-ips`, `disable-ssl-warnings` |
| **GitHub** | `github-app-id`, `github-tokens`, `webhook_ip` |
| **Defaults** | `docker`, `default-status-checks`, `auto-verified-and-merged-users`, `branch_protection` |
| **GitHub** | `github-app-id`, `github-tokens`, `webhook-ip` |
| **Defaults** | `docker`, `default-status-checks`, `auto-verified-and-merged-users`, `branch-protection`, `create-issue-for-new-pr` |

#### Repository Level Options

| Category | Options |
| ----------------- | --------------------------------------------------------------------- |
| **Basic** | `name`, `log-level`, `log-file`, `slack_webhook_url`, `events` |
| **Features** | `verified_job`, `pre-commit`, `pypi`, `tox`, `container` |
| **Pull Requests** | `minimum-lgtm`, `conventional-title`, `can-be-merged-required-labels` |
| **Basic** | `name`, `log-level`, `log-file`, `slack-webhook-url`, `events` |
| **Features** | `verified-job`, `pre-commit`, `pypi`, `tox`, `container` |
| **Pull Requests** | `minimum-lgtm`, `conventional-title`, `can-be-merged-required-labels`, `create-issue-for-new-pr` |
| **Automation** | `set-auto-merge-prs`, `auto-verified-and-merged-users` |
| **Protection** | `protected-branches`, `branch_protection` |
| **Protection** | `protected-branches`, `branch-protection` |

## Deployment

Expand Down
15 changes: 9 additions & 6 deletions examples/.github-webhook-server.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ log-level: DEBUG # Options: INFO, DEBUG
log-file: /path/to/repository-specific.log

# Slack integration
slack_webhook_url: https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK
slack-webhook-url: https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK

# Job verification settings
verified_job: true # Enable/disable verified job functionality
verified-job: true # Enable/disable verified job functionality

# PyPI publishing configuration
pypi:
Expand Down Expand Up @@ -70,12 +70,12 @@ github-tokens:
- ghp_your_repository_specific_token_here

# Branch protection rules
branch_protection:
branch-protection:
strict: true
require_code_owner_reviews: true
dismiss_stale_reviews: true
required_approving_review_count: 2
required_linear_history: false
dismiss_stale_reviews: false
required_approving_review_count: 1
required_linear_history: true
required_conversation_resolution: true

# Auto-merge configuration
Expand All @@ -94,3 +94,6 @@ conventional-title: "feat,fix,docs,style,refactor,test,chore"

# Minimum LGTM count required
minimum-lgtm: 2

# Issue creation for new pull requests
create-issue-for-new-pr: true # Create tracking issues for new PRs
13 changes: 8 additions & 5 deletions examples/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ github-tokens:
- <GITHIB TOKEN1>
- <GITHIB TOKEN2>

webhook_ip: <HTTP://IP OR URL:PORT>
webhook-ip: <HTTP://IP OR URL:PORT>

docker: # Used to pull images from docker.io
username: <username>
Expand All @@ -26,7 +26,9 @@ auto-verified-and-merged-users:
- "renovate[bot]"
- "pre-commit-ci[bot]"

branch_protection:
create-issue-for-new-pr: true # Global default: create tracking issues for new PRs

branch-protection:
strict: True
require_code_owner_reviews: True
dismiss_stale_reviews: False
Expand All @@ -39,8 +41,8 @@ repositories:
name: my-org/my-repository
log-level: DEBUG # Override global log-level for repository
log-file: my-repository.log # Override global log-file for repository
slack_webhook_url: <Slack webhook url> # Send notification to slack on several operations
verified_job: true
slack-webhook-url: <Slack webhook url> # Send notification to slack on several operations
verified-job: true
pypi:
token: <PYPI TOKEN>

Expand Down Expand Up @@ -88,7 +90,7 @@ repositories:
- my-label2

conventional-title: "ci,docs,feat,fix,refactor,test,release" # Check PR title start with any of these words + :
branch_protection:
branch-protection:
strict: True
require_code_owner_reviews: True
dismiss_stale_reviews: False
Expand All @@ -97,5 +99,6 @@ repositories:
required_conversation_resolution: True

minimum-lgtm: 0 # The minimum PR lgtm required before approve the PR
create-issue-for-new-pr: true # Override global setting: create tracking issues for new PRs (default: true)
set-auto-merge-prs:
- main
18 changes: 13 additions & 5 deletions webhook_server/config/schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ properties:
items:
type: string
description: Global GitHub token for all repositories
webhook_ip:
webhook-ip:
type: string
description: IP or FQDN address of the webhook server for adding to the repositories

Expand Down Expand Up @@ -62,8 +62,12 @@ properties:
type: array
items:
type: string
create-issue-for-new-pr:
type: boolean
description: Create a tracking issue for new pull requests (global default)
default: true

branch_protection:
branch-protection:
type: object
properties:
strict:
Expand Down Expand Up @@ -95,10 +99,10 @@ properties:
log-file:
type: string
description: Override global log-file for repository
slack_webhook_url:
slack-webhook-url:
type: string
description: Slack webhook URL
verified_job:
verified-job:
type: boolean
default: true
description: Enable verified job functionality
Expand Down Expand Up @@ -187,7 +191,7 @@ properties:
items:
type: string
description: Override GitHub tokens for this repository
branch_protection:
branch-protection:
type: object
properties:
strict:
Expand Down Expand Up @@ -219,3 +223,7 @@ properties:
type: integer
description: Minimum number of LGTM required before approving PR
default: 0
create-issue-for-new-pr:
type: boolean
description: Create a tracking issue for new pull requests
default: true
10 changes: 9 additions & 1 deletion webhook_server/libs/github_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ def _repo_data_from_config(self, repository_config: dict[str, Any]) -> None:
)
self.tox: dict[str, str] = self.config.get_value(value="tox", extra_dict=repository_config)
self.tox_python_version: str = self.config.get_value(value="tox-python-version", extra_dict=repository_config)
self.slack_webhook_url: str = self.config.get_value(value="slack_webhook_url", extra_dict=repository_config)
self.slack_webhook_url: str = self.config.get_value(value="slack-webhook-url", extra_dict=repository_config)

self.build_and_push_container: dict[str, Any] = self.config.get_value(
value="container", return_on_none={}, extra_dict=repository_config
Expand Down Expand Up @@ -275,6 +275,14 @@ def _repo_data_from_config(self, repository_config: dict[str, Any]) -> None:
self.minimum_lgtm: int = self.config.get_value(
value="minimum-lgtm", return_on_none=0, extra_dict=repository_config
)
# Load global create_issue_for_new_pr setting as fallback
global_create_issue_for_new_pr: bool = self.config.get_value(
value="create-issue-for-new-pr", return_on_none=True
)
# Repository-specific setting overrides global setting
self.create_issue_for_new_pr: bool = self.config.get_value(
value="create-issue-for-new-pr", return_on_none=global_create_issue_for_new_pr, extra_dict=repository_config
)

async def get_pull_request(self, number: int | None = None) -> PullRequest | None:
if number:
Expand Down
14 changes: 12 additions & 2 deletions webhook_server/libs/pull_request_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,13 @@ def _prepare_welcome_comment(self) -> str:
> **Note**: You are an auto-verified user. Your PRs will be automatically verified and may be auto-merged when all requirements are met.
"""

# Check if issue creation is enabled
issue_creation_note = ""
if self.github_webhook.create_issue_for_new_pr:
issue_creation_note = "* **Issue Creation**: A tracking issue is created for this PR and will be closed when the PR is merged or closed\n"
else:
issue_creation_note = "* **Issue Creation**: Disabled for this repository\n"

return f"""
{self.github_webhook.issue_url_for_welcome_msg}

Expand All @@ -193,8 +200,7 @@ def _prepare_welcome_comment(self) -> str:
### 🔄 Automatic Actions
* **Reviewer Assignment**: Reviewers are automatically assigned based on the OWNERS file in the repository root
* **Size Labeling**: PR size labels (XS, S, M, L, XL, XXL) are automatically applied based on changes
* **Issue Creation**: A tracking issue is created for this PR and will be closed when the PR is merged or closed
* **Pre-commit Checks**: [pre-commit](https://pre-commit.ci/) runs automatically if `.pre-commit-config.yaml` exists
{issue_creation_note}* **Pre-commit Checks**: [pre-commit](https://pre-commit.ci/) runs automatically if `.pre-commit-config.yaml` exists
* **Branch Labeling**: Branch-specific labels are applied to track the target branch
* **Auto-verification**: Auto-verified users have their PRs automatically marked as verified

Expand Down Expand Up @@ -430,6 +436,10 @@ async def process_opened_or_synchronize_pull_request(self, pull_request: PullReq
self.logger.error(f"{self.log_prefix} Async task failed: {result}")

async def create_issue_for_new_pull_request(self, pull_request: PullRequest) -> None:
if not self.github_webhook.create_issue_for_new_pr:
self.logger.info(f"{self.log_prefix} Issue creation for new PRs is disabled for this repository")
return

if self.github_webhook.parent_committer in self.github_webhook.auto_verified_and_merged_users:
self.logger.info(
f"{self.log_prefix} Committer {self.github_webhook.parent_committer} is part of "
Expand Down
6 changes: 3 additions & 3 deletions webhook_server/tests/manifests/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ github-tokens:
- GITHIB TOKEN1
- GITHIB TOKEN2

webhook_ip: HTTP://IP OR URL:PORT
webhook-ip: HTTP://IP OR URL:PORT
webhook-secret: test-webhook-secret # pragma: allowlist secret

docker: # Used to pull images from docker.io
Expand All @@ -27,8 +27,8 @@ repositories:
name: my-org/test-repo
log-level: DEBUG # Override global log-level for repository
log-file: test-repo.log # Override global log-file for repository
slack_webhook_url: Slack webhook url # Send notification to slack on several operations
verified_job: true
slack-webhook-url: Slack webhook url # Send notification to slack on several operations
verified-job: true
pypi:
token: PYPI TOKEN

Expand Down
9 changes: 5 additions & 4 deletions webhook_server/tests/test_branch_protection.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
from typing import Any

import pytest
from webhook_server.libs.config import Config
Expand All @@ -9,14 +10,14 @@


@pytest.fixture()
def branch_protection_rules(request, mocker):
def branch_protection_rules(request: pytest.FixtureRequest, mocker: Any) -> dict[str, Any]:
config_path = "webhook_server.libs.config.Config"
os.environ["WEBHOOK_SERVER_DATA_DIR"] = "webhook_server/tests/manifests"
repo_name = "test-repo"
config = Config(repository=repo_name)
root_data = config.root_data
root_data.setdefault("branch_protection", request.param.get("global", {}))
root_data["repositories"][repo_name].setdefault("branch_protection", request.param.get("repo"))
root_data.setdefault("branch-protection", request.param.get("global", {}))
root_data["repositories"][repo_name].setdefault("branch-protection", request.param.get("repo"))

mocker.patch(f"{config_path}.root_data", new_callable=mocker.PropertyMock, return_value=root_data)

Expand Down Expand Up @@ -93,7 +94,7 @@ def branch_protection_rules(request, mocker):
],
indirect=["branch_protection_rules"],
)
def test_branch_protection_setup(branch_protection_rules, expected):
def test_branch_protection_setup(branch_protection_rules: dict[str, Any], expected: dict[str, Any]) -> None:
mismatch = {}
for key in expected:
if branch_protection_rules[key] != expected[key]:
Expand Down
Loading