-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #34 from ivellios/main
Automatyczne tworzenie Pull Requesta z nową organizacją
- Loading branch information
Showing
18 changed files
with
485 additions
and
209 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
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 exceptions import BranchModifiedError | ||
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): | ||
validation_warnings = [] | ||
|
||
org_name = data.get(OrgFormSchemaIds.name) | ||
|
||
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 - not continuing") | ||
return | ||
|
||
if not (org := KRSDataPuller.get_org_by_krs(issue, data.get(OrgFormSchemaIds.krs))): | ||
logger.error("KRS db validation failed") | ||
validation_warnings.append("Nie można zweryfikować KRS") | ||
else: | ||
org_name = org.name | ||
|
||
# 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}") | ||
|
||
logger.info("Adding auto-verified label") | ||
if not validation_warnings: | ||
issue.add_to_labels(Label.AUTO_VERIFIED) | ||
|
||
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." | ||
) | ||
|
||
# create organization yaml file and add to the Pull Request | ||
yaml_string = render_organization_yaml(data) | ||
|
||
try: | ||
create_organization_yaml_pr(issue, yaml_string, data) | ||
except BranchModifiedError: | ||
logger.error("Branch was modified by someone else") | ||
issue.create_comment( | ||
"Aktualizacja pliku organizacji na podstawie opisu zgłoszenia niemożliwa. " | ||
"Plik organizacji został już zmodyfikowany przez innego użytkownika." | ||
) | ||
|
||
|
||
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
class BranchModifiedError(ValueError): | ||
pass | ||
|
||
|
||
class KRSMaintenanceError(Exception): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
import logging | ||
from dataclasses import dataclass | ||
|
||
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 exceptions import BranchModifiedError | ||
from parsers import GithubIssueFormDataParser | ||
|
||
|
||
logger = logging.getLogger(__file__) | ||
|
||
|
||
@dataclass | ||
class GitManager: | ||
"""Manager for creating a new branch and pull request with a file commit in the repo.""" | ||
|
||
repo: Repository | ||
|
||
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: | ||
source = self.repo.get_branch(source_branch) | ||
try: | ||
branch_ref = self.repo.get_git_ref(f"heads/{new_branch_name}") | ||
logger.info(f"Found existing branch '{new_branch_name}'.") | ||
except GithubException as e: | ||
if e.status == 404: | ||
# Branch does not exist, create it from the 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}") | ||
logger.info( | ||
f"Branch '{new_branch_name}' created from '{source_branch}'." | ||
) | ||
else: | ||
raise e | ||
|
||
latest_commit = self.repo.get_commit(branch_ref.object.sha) | ||
if ( | ||
latest_commit.sha != source.commit.sha | ||
and not latest_commit.commit.message.startswith("[auto] ") | ||
): | ||
logger.error(f"Branch was modified: {latest_commit.commit.message}") | ||
raise BranchModifiedError() | ||
|
||
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] | ||
|
||
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"[auto] 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, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.