Last active
February 11, 2022 10:49
-
-
Save ingvaldlorentzen/92796c98fa6a26a592f94200eb161cf8 to your computer and use it in GitHub Desktop.
Create Dependency Updates MR
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
import json | |
import os | |
from itertools import chain | |
from gitlab import Gitlab, GitlabGetError | |
from mdutils import MdUtils | |
# Hosted on: https://gist.github.com/ingvaldlorentzen/92796c98fa6a26a592f94200eb161cf8 | |
# Raw: https://gist.githubusercontent.com/ingvaldlorentzen/92796c98fa6a26a592f94200eb161cf8/raw/create_mr.py | |
def format_package_links(dependencies: [{}]): | |
""" | |
Formats package links in update.json into markdown | |
:param dependencies: List of dependencies with info from update.json | |
:return: Dictionary with package as key and formatted markdown links as value | |
""" | |
registry = 'npm' if os.environ['TYPE'] == 'npm' else 'PyPI' | |
return { | |
dependency['package']: '<br/>'.join( | |
[f"[Homepage]({dependency['home_page']})"] | |
+ [f"[{registry}]({dependency['package_url']})"] | |
# Add arbitrary links but filter out homepage as it has own key | |
+ [f'[{name}]({link})' for name, link in dependency['project_urls'].items() if name != 'Homepage'] | |
) | |
for dependency in dependencies | |
} | |
def format_table_content(dependencies: [{}], ignored: bool = False): | |
""" | |
Formats packages in update.json into list for markdown | |
:param dependencies: List of dependencies with info from update.json | |
:param ignored: Add reason to table if dependency is ignored | |
:return: List of table content | |
""" | |
package_links = format_package_links(dependencies) | |
if not ignored: | |
return list( | |
chain.from_iterable( | |
[ | |
[ | |
dependency['package'], | |
dependency['current_version'], | |
dependency['new_version'], | |
package_links[dependency['package']], | |
] | |
for dependency in dependencies | |
] | |
) | |
) | |
else: | |
return list( | |
chain.from_iterable( | |
[ | |
[ | |
dependency['package'], | |
dependency['current_version'], | |
dependency['new_version'], | |
package_links[dependency['package']], | |
dependency['reason'], | |
] | |
for dependency in dependencies | |
] | |
) | |
) | |
def get_merge_request_description(): | |
""" | |
Read updates.json from last pipeline and creates markdown description for merge request with links and version info | |
:return: Markdown formatted merge request description | |
""" | |
with open('updates.json', 'r') as file: | |
updates = json.load(file) | |
file.close() | |
dependencies = [update for update in updates if update['type'] == 'dependencies'] | |
dev_dependencies = [update for update in updates if update['type'] == 'dev-dependencies'] | |
ignored_dependencies = [update for update in updates if update['type'] == 'ignored'] | |
md = MdUtils('mr_description') | |
table_headers = ['Package', 'Previous Version', 'New Version', 'Links'] | |
if dependencies: | |
md.new_header(level=1, title='Dependency Updates') | |
md.new_table(columns=4, rows=len(dependencies) + 1, text=table_headers + format_table_content(dependencies)) | |
if dev_dependencies: | |
md.new_header(level=1, title='Dev Dependency Updates') | |
md.new_table( | |
columns=4, rows=len(dev_dependencies) + 1, text=table_headers + format_table_content(dev_dependencies) | |
) | |
if ignored_dependencies: | |
md.new_header(level=1, title='Ignored Dependency Updates') | |
md.new_table( | |
columns=5, | |
rows=len(ignored_dependencies) + 1, | |
text=table_headers + ['Reason'] + format_table_content(ignored_dependencies, ignored=True), | |
) | |
return md.file_data_text | |
gitlab = Gitlab(os.environ['CI_SERVER_URL'], private_token=os.environ['GITLAB_API_TOKEN']) | |
project = gitlab.projects.get(os.environ['CI_PROJECT_PATH']) | |
branch_name = 'dependencies_update' | |
try: | |
merge_request = next( | |
merge_request | |
for merge_request in project.mergerequests.list(state='opened') | |
if merge_request.source_branch == branch_name | |
) | |
merge_request.state_event = 'close' | |
merge_request.save() | |
except StopIteration: | |
pass | |
# Delete branch if it exists | |
try: | |
if branch := project.branches.get(branch_name): | |
branch.delete() | |
except GitlabGetError as error: | |
if error.response_code != 404: | |
raise | |
project.branches.create({'branch': branch_name, 'ref': 'main'}) | |
dependency_file = 'package.json' if os.environ['TYPE'] == 'npm' else 'pyproject.toml' | |
lock_file = 'package-lock.json' if os.environ['TYPE'] == 'npm' else 'poetry.lock' | |
commit_data = { | |
'actions': [ | |
{ | |
'action': 'update', | |
'content': open(dependency_file).read(), | |
'file_path': dependency_file, | |
}, | |
{ | |
'action': 'update', | |
'content': open(lock_file).read(), | |
'file_path': lock_file, | |
}, | |
], | |
'branch': branch_name, | |
'commit_message': 'Dependencies Update', | |
} | |
commit = project.commits.create(commit_data) | |
merge_request = project.mergerequests.create( | |
{ | |
'description': get_merge_request_description(), | |
'source_branch': branch_name, | |
'target_branch': 'main', | |
'title': 'Dependency Updates', | |
} | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment