Skip to content

Instantly share code, notes, and snippets.

@ingvaldlorentzen
Last active February 11, 2022 10:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ingvaldlorentzen/92796c98fa6a26a592f94200eb161cf8 to your computer and use it in GitHub Desktop.
Save ingvaldlorentzen/92796c98fa6a26a592f94200eb161cf8 to your computer and use it in GitHub Desktop.
Create Dependency Updates MR
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