Task: gitlab.star-fork-create-milestone-issues
Goal: Star the Pytorch GAN repo with most stars repo and fork it/them. Create a "task of cleaning sensitive information" milestone starting on March 15, 2044 and ending 10 days from the start date. Then create three issues in the forked repo(s) with the titles, "clean names", "clean addresses" and "clean phone numbers and email addresses" and assign them to the milestone.
Task configuration:
repo: the Pytorch GAN repo with most stars
original_namespace: eriklindernoren
namespace: byteblaze
project_name: PyTorch-GAN
event: task of cleaning sensitive information
search_keywords: clean sensitive information
text_start_date: March 15, 2044
start_date: 2044-03-15
text_end_date: 10 days from the start date
end_date: 2044-03-25
issue_title_1: clean names
issue_title_2: clean addresses
issue_title_3: clean phone numbers and email addresses

Validation code:
from typing import Any, Dict, List
from urllib.parse import quote

import requests
import json
import os

def _get_headers():
    return {
        "Content-Type": "application/json",
        "Accept": "application/json",
        **json.loads(os.getenv("GITLAB_EXTRA_HTTP_HEADERS", "{}")),
    }

def validate(messages: List[Dict[str, str]], config: Dict[str, Any]) -> int:

    if not messages:
        return 0

    base_url = os.getenv("GITLAB_BASE_URL", "").rstrip("/")

    # -- Star repos --
    # Check that the repo is starred. Use project_name for matching since
    # config["repo"] may contain descriptive text like "the 2019-nCov"
    if "project_name" not in config:
        raise ValueError("Target must contain 'project_name'")

    starred_url = base_url + "/api/v4/projects?starred=true&per_page=100"
    response = requests.get(url=starred_url, headers=_get_headers())
    if response.status_code != 200:
        return 0
    result = response.json()

    repo_names = [repo["name"].strip().lower() for repo in result]
    if config["project_name"].strip().lower() not in repo_names:
        return 0

    # -- Fork repos --
    if (
        "original_namespace" not in config
        or "namespace" not in config
    ):
        raise ValueError(
            "Target must contain 'original_namespace' and 'namespace'"
        )

    project_id = quote(
        f"{config['original_namespace']}/{config['project_name']}", safe=""
    ).replace(".", "%2E")
    forks_url = base_url + "/api/v4/projects/" + project_id + "/forks"
    response = requests.get(url=forks_url, headers=_get_headers())
    if response.status_code != 200:
        return 0
    result = response.json()
    found = False
    for repo in result:
        repo_ns = repo.get("namespace", {})
        ns_path = repo_ns.get("path", "") if isinstance(repo_ns, dict) else ""
        if (
            ns_path.lower() == config["namespace"].lower()
            and repo["name"].lower() == config["project_name"].lower()
        ):
            found = True
            break
    if not found:
        return 0

    # -- Create Milestone --
    if (
        "search_keywords" not in config
        or "start_date" not in config
        or "end_date" not in config
    ):
        raise ValueError(
            "Target must contain 'search_keywords', 'start_date', and 'end_date'"
        )

    # Search for the milestone in the forked repo (under the user's namespace)
    forked_project_id = quote(
        f"{config['namespace']}/{config['project_name']}", safe=""
    ).replace(".", "%2E")
    milestones_url = (
        base_url
        + "/api/v4/projects/"
        + forked_project_id
        + "/milestones"
        + "?search="
        + quote(config["search_keywords"], safe="")
    )
    response = requests.get(url=milestones_url, headers=_get_headers())
    if response.status_code != 200:
        return 0
    result = response.json()
    if len(result) == 0:
        return 0
    milestone = result[0]

    if config.get("start_date"):
        if milestone["start_date"] != config["start_date"]:
            return 0

    if config.get("end_date"):
        if milestone["due_date"] != config["end_date"]:
            return 0

    # -- Create Issues --
    issues_url = base_url + "/api/v4/projects/" + forked_project_id + "/issues"
    response = requests.get(url=issues_url, headers=_get_headers())
    response.raise_for_status()
    result = response.json()
    if len(result) == 0:
        return 0

    for issue_title in [
        config["issue_title_1"],
        config["issue_title_2"],
        config["issue_title_3"],
    ]:
        found = False
        for issue in result:
            if issue["title"] == issue_title:
                found = True
                break
        if not found:
            return 0

    return 1