Skip to content

Commit

Permalink
Dodane automatyczne tworzenie lub aktualizacja branchy/commitów/Pull …
Browse files Browse the repository at this point in the history
…Requestów dla zgłoszeń nowej organizacji; formatowanie plików blackiem; zmiana końców linii CRLF na LF
  • Loading branch information
ivellios committed Dec 17, 2024
1 parent 55396b6 commit 4919770
Show file tree
Hide file tree
Showing 14 changed files with 423 additions and 197 deletions.
16 changes: 8 additions & 8 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
blank_issues_enabled: true
contact_links:
- name: Usuwanie produktu
url: https://github.com/wyslijco/wyslijco.github.io/wiki
about: Zobacz, jak możesz usunąć produkt ze strony swojej organizacji w Wyślij.co
- name: Usuwanie organizacji
url: https://github.com/wyslijco/wyslijco.github.io/wiki
about: Zobacz, jak usunąć swoją organizację z Wyślij.co
blank_issues_enabled: true
contact_links:
- name: Usuwanie produktu
url: https://github.com/wyslijco/wyslijco.github.io/wiki
about: Zobacz, jak możesz usunąć produkt ze strony swojej organizacji w Wyślij.co
- name: Usuwanie organizacji
url: https://github.com/wyslijco/wyslijco.github.io/wiki
about: Zobacz, jak usunąć swoją organizację z Wyślij.co
76 changes: 38 additions & 38 deletions .github/ISSUE_TEMPLATE/dodanieproduktu.yaml
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
name: Dodanie produktu
description: Dodaj produkt do strony swojej organizacji.
title: "[Dodanie produktu]"
labels: ["organizacje", "nowy-produkt"]
assignees:
- ivellios

body:
- type: markdown
attributes:
value: |
Ten formularz pomoże Ci w dodaniu produktu do strony Twojej organizacji w Wyślij.co
- type: dropdown
id: nazwa_organizacji
attributes:
label: Twoja organizacja
options:
- Testowa
validations:
required: true
- type: input
id: nazwa
attributes:
label: Nazwa produktu
validations:
required: true
- type: input
id: opis
attributes:
label: Krótki opis produktu
validations:
required: false
- type: input
id: link
attributes:
label: Link do produktu w sklepie internetowym
validations:
required: true
name: Dodanie produktu
description: Dodaj produkt do strony swojej organizacji.
title: "[Dodanie produktu]"
labels: ["organizacje", "nowy-produkt"]
assignees:
- ivellios

body:
- type: markdown
attributes:
value: |
Ten formularz pomoże Ci w dodaniu produktu do strony Twojej organizacji w Wyślij.co
- type: dropdown
id: nazwa_organizacji
attributes:
label: Twoja organizacja
options:
- Testowa
validations:
required: true
- type: input
id: nazwa
attributes:
label: Nazwa produktu
validations:
required: true
- type: input
id: opis
attributes:
label: Krótki opis produktu
validations:
required: false
- type: input
id: link
attributes:
label: Link do produktu w sklepie internetowym
validations:
required: true
78 changes: 78 additions & 0 deletions .github/scripts/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import json
import logging
import os

from github import Auth, Github, Issue

from consts import OrgFormSchemaIds, NEW_ORG_ISSUE_DEFAULT_TITLE, NEW_ORG_FORM_SCHEMA_FILENAME
from git_managers import create_organization_yaml_pr
from labels import Label
from parsers import GithubIssueFormDataParser
from pullers import KRSDataPuller
from utils import has_label
from validators import OrgValidator
from renderers import render_organization_yaml

logging.basicConfig(
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__file__)

GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")
GITHUB_REPOSITORY = os.getenv("GITHUB_REPOSITORY")

auth = Auth.Token(GITHUB_TOKEN)
g = Github(auth=auth)
repo = g.get_repo(GITHUB_REPOSITORY)


def process_new_org_issue(issue: Issue, data: GithubIssueFormDataParser):
if has_label(issue, Label.AUTO_VERIFIED):
issue.remove_from_labels(Label.AUTO_VERIFIED)

validator = OrgValidator(data, issue)
if not validator.validate():
logger.error("Validation failed")
return

if not (org := KRSDataPuller.get_org_by_krs(issue, data.get(OrgFormSchemaIds.krs))):
logger.error("KRS db validation failed")
return

# Update issue title
if issue.title == NEW_ORG_ISSUE_DEFAULT_TITLE:
logger.info("Updating issue title")
issue.edit(
title=f"{NEW_ORG_ISSUE_DEFAULT_TITLE} {org.name or data.get(OrgFormSchemaIds.name)}"
)

logger.info("Adding auto-verified label")
if not has_label(issue, Label.WAITING):
issue.add_to_labels(Label.WAITING)
issue.create_comment(
f"@{issue.user.login}, dziękujemy za podanie informacji. "
f"Przyjęliśmy zgłoszenie dodania nowej organizacji. "
f"Wkrótce skontaktujemy się celem weryfikacji zgłoszenia."
)

# mark as verified
issue.add_to_labels(Label.AUTO_VERIFIED)

# create organization yaml file and add to the Pull Request
yaml_string = render_organization_yaml(data)
create_organization_yaml_pr(issue, yaml_string, data)


def main():
github_form_json = os.getenv("GITHUB_FORM_JSON")
github_issue_number = int(os.getenv("GITHUB_ISSUE_NUMBER"))

issue = repo.get_issue(github_issue_number)
data = GithubIssueFormDataParser(
json.loads(github_form_json), NEW_ORG_FORM_SCHEMA_FILENAME
)
process_new_org_issue(issue, data)


if __name__ == "__main__":
main()
7 changes: 4 additions & 3 deletions .github/scripts/consts.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import enum


class OrgSchemaIds(enum.StrEnum):
class OrgFormSchemaIds(enum.StrEnum):
name = "nazwa"
www = "www"
website = "www"
krs = "krs"
slug = "nazwa_strony"
street = "ulica"
postal_code = "kod_pocztowy"
city = "miasto"
phone_number = "telefon"


NEW_ORG_ISSUE_DEFAULT_TITLE = "[Nowa Organizacja]"
NEW_ORG_SCHEMA_FILENAME = "nowa.yaml"
NEW_ORG_FORM_SCHEMA_FILENAME = "nowa.yaml"


ORG_SCHEMA_SLUG_FIELD = "adres"
129 changes: 129 additions & 0 deletions .github/scripts/git_managers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import logging

from github import GithubException, InputGitTreeElement
from github.GitCommit import GitCommit
from github.GitRef import GitRef
from github.Issue import Issue
from github.PullRequest import PullRequest
from github.Repository import Repository

from consts import OrgFormSchemaIds
from parsers import GithubIssueFormDataParser


logger = logging.getLogger(__file__)


class GitManager:
"""Manager for creating a new branch and pull request with a file commit in the repo."""

def __init__(self, repo: Repository):
self.repo = repo

def commit_file_contents_to_branch(
self, branch_ref: GitRef, file_path: str, contents: str, commit_message: str
) -> GitCommit:
latest_commit = self.repo.get_commit(branch_ref.object.sha)
blob = self.repo.create_git_blob(contents, "utf-8")
tree_element = InputGitTreeElement(
path=file_path, mode="100644", type="blob", sha=blob.sha
)
base_tree = latest_commit.commit.tree
new_tree = self.repo.create_git_tree([tree_element], base_tree)
new_commit = self.repo.create_git_commit(
message=commit_message, tree=new_tree, parents=[latest_commit.commit]
)
return new_commit

def get_or_create_branch(self, source_branch: str, new_branch_name: str) -> GitRef:
try:
branch_ref = self.repo.get_git_ref(f"heads/{new_branch_name}")
print(f"Branch '{new_branch_name}' already exists.")
except GithubException as e:
if e.status == 404:
# Branch does not exist, create it from the source branch
source = self.repo.get_branch(source_branch)
self.repo.create_git_ref(
ref=f"refs/heads/{new_branch_name}", sha=source.commit.sha
)
branch_ref = self.repo.get_git_ref(f"heads/{new_branch_name}")
print(f"Branch '{new_branch_name}' created from '{source_branch}'.")
else:
raise e
return branch_ref

def get_or_create_pr(
self, target_branch: str, new_branch_name: str, pr_title: str, pr_body: str
) -> PullRequest:
pulls = self.repo.get_pulls(
state="open",
head=f"{self.repo.owner.login}:{new_branch_name}",
base=target_branch,
)
if pulls.totalCount > 0:
logger.warning(
f"Pull request already exists for branch '{new_branch_name}': {pulls[0].html_url}"
)
return pulls[0]
else:
logger.info(f"Creating pull request for branch '{new_branch_name}'")
return self.repo.create_pull(
title=pr_title, body=pr_body, head=new_branch_name, base=target_branch
)

def create_or_update_remote_branch_with_file_commit(
self,
source_branch: str,
new_branch: str,
file_path: str,
file_contents: str,
commit_message: str,
) -> GitRef:
"""Create or update a remote branch with a file commit."""
branch = self.get_or_create_branch(source_branch, new_branch)
commit = self.commit_file_contents_to_branch(
branch, file_path, file_contents, commit_message
)
branch.edit(commit.sha)
return branch

def create_or_update_pr_with_file(
self,
source_branch: str,
new_branch: str,
pr_title: str,
pr_body: str,
file_path: str,
file_contents: str,
commit_message: str,
) -> PullRequest:
self.create_or_update_remote_branch_with_file_commit(
source_branch, new_branch, file_path, file_contents, commit_message
)
return self.get_or_create_pr(source_branch, new_branch, pr_title, pr_body)


def create_organization_yaml_pr(
issue: Issue, yaml_string: str, data: GithubIssueFormDataParser
):
repo = issue.repository

source_branch = "main"
new_branch_name = f"nowa-organizacja-zgloszenie-{issue.number}"

commit_message = f"Dodana nowa organizacja: {data.get(OrgFormSchemaIds.name)} | Zgłoszenie: #{issue.number}"
pr_title = f"Dodana nowa organizacja: {data.get(OrgFormSchemaIds.name)} | Zgłoszenie: #{issue.number}"
pr_body = f"Automatycznie dodana nowa organizacja na podstawie zgłoszenia z issue #{issue.number}.\n\n Closes #{issue.number}"

file_path = "organizations/organization.yaml"

manager = GitManager(repo)
manager.create_or_update_pr_with_file(
source_branch=source_branch,
new_branch=new_branch_name,
pr_title=pr_title,
pr_body=pr_body,
file_path=file_path,
file_contents=yaml_string,
commit_message=commit_message,
)
11 changes: 6 additions & 5 deletions .github/scripts/labels.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import enum

from consts import OrgSchemaIds
from consts import OrgFormSchemaIds


class Label(enum.StrEnum):
Expand All @@ -9,11 +9,12 @@ class Label(enum.StrEnum):
INVALID_PHONE = "niepoprawny numer telefonu"
INVALID_SLUG = "niepoprawna nazwa strony"
AUTO_VERIFIED = "zweryfikowana automatycznie"
WAITING = "oczekuje na akceptację"


INVALID_FIELD_TO_LABEL = {
OrgSchemaIds.krs: Label.INVALID_KRS,
OrgSchemaIds.postal_code: Label.INVALID_POSTAL_CODE,
OrgSchemaIds.phone_number: Label.INVALID_PHONE,
OrgSchemaIds.slug: Label.INVALID_SLUG,
OrgFormSchemaIds.krs: Label.INVALID_KRS,
OrgFormSchemaIds.postal_code: Label.INVALID_POSTAL_CODE,
OrgFormSchemaIds.phone_number: Label.INVALID_PHONE,
OrgFormSchemaIds.slug: Label.INVALID_SLUG,
}
18 changes: 18 additions & 0 deletions .github/scripts/organization.yaml.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
nazwa: {{ organization.name }}

# wyslij.co/testowej - adres, pod którym będzie dostępna strona
adres: {{ organization.slug }}

strona: {{ organization.website }}
krs: {{ organization.krs }}

dostawa:
ulica: {{ organization.street }}
kod: {{ organization.postal_code }}
miasto: {{ organization.city }}
telefon: {{ organization.phone_number }}

produkty:
- nazwa: Testowy produkt
link: http://example.com

6 changes: 5 additions & 1 deletion .github/scripts/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
import yaml


class FormDataParser:
class GithubIssueFormDataParser:
"""
Parses data comming from a Github issue form converted
to a dictionary and provides methods to access the data
"""

def __init__(self, form_data: dict[str, Any], form_schema_filename: str):
self.form_data = form_data
Expand Down
Loading

0 comments on commit 4919770

Please sign in to comment.