diff --git a/.github/workflows/label-analysis.yml b/.github/workflows/label-analysis.yml index 7c4345e2ec323..4799e2f6519e7 100644 --- a/.github/workflows/label-analysis.yml +++ b/.github/workflows/label-analysis.yml @@ -138,3 +138,22 @@ jobs: run: pip install -r requirements.txt -r tasks/requirements.txt - name: Check agent telemetry metric list run: inv -e github.agenttelemetry-list-change-ack-check --pr-id=${{ github.event.pull_request.number }} + + ask-reviews: + if: github.triggering_actor != 'dd-devflow[bot]' && github.event.action != 'synchronize' + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + - name: Setup python + uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 + with: + python-version-file: .python-version + cache: 'pip' + cache-dependency-path: '**/requirements*.txt' + - name: Install dependencies + run: pip install -r requirements.txt -r tasks/requirements.txt + - name: Ask for code reviews + run: inv -e issue.ask-reviews -p ${{ github.event.pull_request.number }} diff --git a/tasks/issue.py b/tasks/issue.py index 4615d39716dae..3e68fd42c40c4 100644 --- a/tasks/issue.py +++ b/tasks/issue.py @@ -5,7 +5,7 @@ from tasks.libs.ciproviders.github_api import GithubAPI from tasks.libs.issue.assign import assign_with_model, assign_with_rules from tasks.libs.issue.model.actions import fetch_data_and_train_model -from tasks.libs.pipeline.notifications import GITHUB_SLACK_MAP +from tasks.libs.pipeline.notifications import GITHUB_SLACK_MAP, GITHUB_SLACK_REVIEW_MAP @task @@ -40,3 +40,57 @@ def assign_owner(_, issue_id, dry_run=False): @task def generate_model(_): fetch_data_and_train_model() + + +WAVES = [ + "wave", + "waveboi", + "capy-wave", + "wastelands-wave", + "wave_hello", + "wave-hokusai", + "wave_moomin", + "wave2", + "wave3", + "wallee-wave", + "vaporeon_wave", + "turtle-wave", + "softwave", + "shiba-wave", + "minion-wave", + "meow_wave_comfy", + "mario-wave", + "link-wave", + "kirby_wave", + "frog-wave", + "fox_wave", + "duckwave", + "cyr-wave", + "cozy-wave", + "cat-wave", + "bufo-wave", + "bongo-wave", + "blobwave", + "birb-wave", + "arnaud-wave", +] + + +@task +def ask_reviews(_, pr_id): + gh = GithubAPI() + pr = gh.repo.get_pull(int(pr_id)) + if any(label.name == 'ask-review' for label in pr.get_labels()): + reviewers = [f"@datadog/{team.slug}" for team in pr.requested_teams] + import random + + from slack_sdk import WebClient + + client = WebClient(os.environ['SLACK_API_TOKEN']) + for reviewer in reviewers: + channel = next( + (chan for team, chan in GITHUB_SLACK_REVIEW_MAP.items() if team.casefold() == reviewer.casefold()), + '#agent-devx-help', + ) + message = f'Hello :{random.choice(WAVES)}:! Can you please review <{pr.html_url}/s|{pr.title}>?\n Thanks in advance {channel}!' + client.chat_postMessage(channel=channel, text=message) diff --git a/tasks/libs/pipeline/github_slack_review_map.yaml b/tasks/libs/pipeline/github_slack_review_map.yaml new file mode 100644 index 0000000000000..e08a00015b97c --- /dev/null +++ b/tasks/libs/pipeline/github_slack_review_map.yaml @@ -0,0 +1,48 @@ +# This file contains a mapping of DataDog Github teams to slack channels for reviews. +# The DEFAULT_SLACK_CHANNEL value is interpreted as '#agent-devx-ops'. +# Note that the values must be quoted if they contain a '#' symbol, because +# YAML interprets that as the beginning of a comment. Keys must also be quoted +# because the '@' symbol is reserved in YAML. +'@datadog/agent-platform': DEFAULT_SLACK_CHANNEL +'@datadog/documentation': '#documentation' +'@datadog/container-integrations': '#container-integrations' +'@datadog/container-platform': '#container-platform' +'@datadog/container-ecosystems': '#container-ecosystems' +'@datadog/platform-integrations': '#platform-integrations' +'@datadog/agent-security': '#security-and-compliance-agent' +'@datadog/agent-apm': '#apm-agent' +'@datadog/network-device-monitoring': '#network-device-monitoring' +'@datadog/ndm-core': '#ndm-core' +'@datadog/ndm-integrations': '#ndm-integrations' +'@datadog/container-intake': '#process-agent-ops' +'@datadog/agent-metrics-logs': '#agent-metrics-logs' +'@datadog/agent-processing-and-routing': '#agent-processing-and-routing' +'@datadog/agent-shared-components': '#agent-shared-components' +'@datadog/container-app': '#container-app' +'@datadog/metrics-aggregation': '#metrics-aggregation' +'@datadog/serverless': '#serverless-agent' +'@datadog/remote-config': '#remote-config-monitoring' +'@datadog/fleet': '#fleet-automation-monitoring' +'@datadog/agent-all': '#datadog-agent-pipelines' +'@datadog/ebpf-platform': '#ebpf-platform' +'@datadog/networks': '#network-performance-monitoring' +'@datadog/universal-service-monitoring': '#universal-service-monitoring' +'@datadog/windows-agent': '#windows-agent-reviews' +'@datadog/windows-kernel-integrations': '#windows-kernel-integrations-reviews' +'@datadog/opentelemetry': '#opentelemetry' +'@datadog/agent-e2e-testing': '#agent-e2e-framework-devs' +'@datadog/software-integrity-and-trust': '#sit' +'@datadog/single-machine-performance': '#single-machine-performance' +'@datadog/agent-integrations': '#agent-integrations' +'@datadog/debugger': '#debugger' +'@datadog/database-monitoring': '#database-monitoring' +'@datadog/agent-cspm': '#k9-cspm' +'@datadog/telemetry-and-analytics': '#instrumentation-telemetry' +'@datadog/apm-trace-storage': '#apm-trace-storage' +'@datadog/asm-go': '#k9-library-go' +'@datadog/agent-delivery': '#agent-delivery-reviews' +'@datadog/agent-devx-infra': '#agent-devx-infra-reviews' +'@datadog/agent-devx-loops': '#agent-devx-loops-reviews' +'@datadog/apm-onboarding': '#apm-onboarding' +'@datadog/apm-ecosystems-performance': '#apm-benchmarking-platform' +'@DataDog/container-ecosystems': '#container-ecosystems' diff --git a/tasks/libs/pipeline/notifications.py b/tasks/libs/pipeline/notifications.py index b121dc1b6b2ef..92e6af39bdc70 100644 --- a/tasks/libs/pipeline/notifications.py +++ b/tasks/libs/pipeline/notifications.py @@ -42,6 +42,9 @@ def load_and_validate( # Map keys in lowercase GITHUB_SLACK_MAP = load_and_validate("github_slack_map.yaml", "DEFAULT_SLACK_CHANNEL", DEFAULT_SLACK_CHANNEL) GITHUB_JIRA_MAP = load_and_validate("github_jira_map.yaml", "DEFAULT_JIRA_PROJECT", DEFAULT_JIRA_PROJECT) +GITHUB_SLACK_REVIEW_MAP = load_and_validate( + "github_slack_review_map.yaml", "DEFAULT_SLACK_CHANNEL", DEFAULT_SLACK_CHANNEL +) def check_for_missing_owners_slack_and_jira(print_missing_teams=True, owners_file=".github/CODEOWNERS"):