Commit 247a0b72 authored by Laurent Peuch's avatar Laurent Peuch
Browse files

feat: add mr_center

parent 581bb7897fcc
#!/usr/bin/env python3
import os
import gitlab
import jinja2
gl = gitlab.Gitlab("https://forge.extranet.logilab.fr", oauth_token=os.environ.get("TOKEN"))
all_core_projects = [x for x in gl.projects.list(all=True) if "cw-core" in x.tag_list]
context = {"projects": {}, "cubes": {}}
for project in all_core_projects:
merge_requests = []
for mr_object in project.mergerequests.list(all=True):
if mr_object.state != "opened":
continue
merge_request = mr_object.attributes
pipelines = mr_object.pipelines()
merge_request["pipeline"] = pipelines[0] if pipelines else None
merge_requests.append(merge_request)
context["projects"][project.name] = {
"project": project.attributes,
"merge_requests": merge_requests,
"labels": {x.name: x.attributes for x in project.labels.list(all=True)}
}
all_cubes = [x for x in gl.projects.list(all=True) if x.namespace["name"] == "cubes"]
for cube in all_cubes:
merge_requests = []
for mr_object in cube.mergerequests.list(all=True):
if mr_object.state != "opened":
continue
merge_request = mr_object.attributes
pipelines = mr_object.pipelines()
merge_request["pipeline"] = pipelines[0] if pipelines else None
merge_requests.append(merge_request)
context["cubes"][project.name] = {
"cube": cube.attributes,
"merge_requests": merge_requests,
"labels": {x.name: x.attributes for x in project.labels.list(all=True)}
}
os.system("mkdir -p build") # XXX lazy
result = jinja2.Template(open("template/mr.html", "r").read()).render(**context)
open("build/mr.html", "w").write(result)
# reference:
# In [71]: project.attributes
# Out[71]:
# {'id': 385,
# 'description': 'https://cubicweb.readthedocs.io/',
# 'vcs_type': 'hg_git',
# 'name': 'cubicweb',
# 'name_with_namespace': 'cubicweb / cubicweb',
# 'path': 'cubicweb',
# 'path_with_namespace': 'cubicweb/cubicweb',
# 'created_at': '2020-04-10T13:39:55.623Z',
# 'default_branch': 'branch/default',
# 'tag_list': ['cw-core'],
# 'ssh_url_to_repo': 'ssh://git@forge.extranet.logilab.fr/cubicweb/cubicweb',
# 'http_url_to_repo': 'https://forge.extranet.logilab.fr/cubicweb/cubicweb',
# 'web_url': 'https://forge.extranet.logilab.fr/cubicweb/cubicweb',
# 'readme_url': 'https://forge.extranet.logilab.fr/cubicweb/cubicweb/-/blob/branch/default/README',
# 'avatar_url': 'https://forge.extranet.logilab.fr/uploads/-/system/project/avatar/385/cubicweb_logo.png',
# 'star_count': 2,
# 'forks_count': 0,
# 'last_activity_at': '2020-07-22T02:01:43.427Z',
# 'namespace': {'id': 23,
# 'name': 'cubicweb',
# 'path': 'cubicweb',
# 'kind': 'group',
# 'full_path': 'cubicweb',
# 'parent_id': None,
# 'avatar_url': '/uploads/-/system/group/avatar/23/cubicweb.png',
# 'web_url': 'https://forge.extranet.logilab.fr/groups/cubicweb'},
# '_links': {'self': 'https://forge.extranet.logilab.fr/api/v4/projects/385',
# 'issues': 'https://forge.extranet.logilab.fr/api/v4/projects/385/issues',
# 'merge_requests': 'https://forge.extranet.logilab.fr/api/v4/projects/385/merge_requests',
# 'repo_branches': 'https://forge.extranet.logilab.fr/api/v4/projects/385/repository/branches',
# 'labels': 'https://forge.extranet.logilab.fr/api/v4/projects/385/labels',
# 'events': 'https://forge.extranet.logilab.fr/api/v4/projects/385/events',
# 'members': 'https://forge.extranet.logilab.fr/api/v4/projects/385/members'},
# 'empty_repo': False,
# 'archived': False,
# 'visibility': 'public',
# 'resolve_outdated_diff_discussions': False,
# 'container_registry_enabled': True,
# 'issues_enabled': True,
# 'merge_requests_enabled': True,
# 'wiki_enabled': True,
# 'jobs_enabled': True,
# 'snippets_enabled': True,
# 'can_create_merge_request_in': True,
# 'issues_access_level': 'enabled',
# 'repository_access_level': 'enabled',
# 'merge_requests_access_level': 'enabled',
# 'forking_access_level': 'enabled',
# 'wiki_access_level': 'enabled',
# 'builds_access_level': 'enabled',
# 'snippets_access_level': 'enabled',
# 'pages_access_level': 'enabled',
# 'emails_disabled': False,
# 'shared_runners_enabled': True,
# 'lfs_enabled': True,
# 'creator_id': 19,
# 'import_status': 'none',
# 'open_issues_count': 38,
# 'ci_default_git_depth': 50,
# 'public_jobs': True,
# 'build_timeout': 14400,
# 'auto_cancel_pending_pipelines': 'enabled',
# 'build_coverage_regex': '',
# 'ci_config_path': '',
# 'shared_with_groups': [{'group_id': 21,
# 'group_name': 'logilab',
# 'group_full_path': 'logilab',
# 'group_access_level': 40,
# 'expires_at': None}],
# 'only_allow_merge_if_pipeline_succeeds': False,
# 'request_access_enabled': True,
# 'only_allow_merge_if_all_discussions_are_resolved': False,
# 'remove_source_branch_after_merge': None,
# 'printing_merge_request_link_enabled': True,
# 'merge_method': 'ff',
# 'suggestion_commit_message': None,
# 'auto_devops_enabled': False,
# 'auto_devops_deploy_strategy': 'continuous',
# 'autoclose_referenced_issues': True,
# 'permissions': {'project_access': {'access_level': 30,
# 'notification_level': 3},
# 'group_access': {'access_level': 40, 'notification_level': 2}}}
#
# In [171]: mr.attributes
# Out[171]:
# {'assignees': [],
# 'labels': ['Need Revision'],
# 'id': 2098,
# 'iid': 40,
# 'project_id': 385,
# 'title': 'fix: UX when migractions failed to get its connection',
# 'description': "It was a mess to debug because from the exception we couldn't get the right information to understand what was happening.",
# 'state': 'opened',
# 'created_at': '2020-07-08T13:43:26.081Z',
# 'updated_at': '2020-07-22T02:01:50.582Z',
# 'merged_by': None,
# 'merged_at': None,
# 'closed_by': None,
# 'closed_at': None,
# 'target_branch': 'topic/default/fix-yams-str-only-api',
# 'source_branch': 'topic/default/ux-migractions-get-connections',
# 'user_notes_count': 4,
# 'upvotes': 0,
# 'downvotes': 0,
# 'assignee': None,
# 'author': {'id': 52,
# 'name': 'Laurent Peuch',
# 'username': 'bram',
# 'state': 'active',
# 'avatar_url': 'https://forge.extranet.logilab.fr/uploads/-/system/user/avatar/52/avatar.png',
# 'web_url': 'https://forge.extranet.logilab.fr/bram'},
# 'source_project_id': 385,
# 'target_project_id': 385,
# 'work_in_progress': False,
# 'milestone': None,
# 'merge_when_pipeline_succeeds': False,
# 'merge_status': 'cannot_be_merged',
# 'sha': 'b082d6abc2dd0eff89c5b2d5a200afed87f871bd',
# 'merge_commit_sha': None,
# 'squash_commit_sha': None,
# 'discussion_locked': None,
# 'should_remove_source_branch': True,
# 'force_remove_source_branch': True,
# 'reference': '!40',
# 'references': {'short': '!40',
# 'relative': '!40',
# 'full': 'cubicweb/cubicweb!40'},
# 'web_url': 'https://forge.extranet.logilab.fr/cubicweb/cubicweb/-/merge_requests/40',
# 'time_stats': {'time_estimate': 0,
# 'total_time_spent': 0,
# 'human_time_estimate': None,
# 'human_total_time_spent': None},
# 'squash': False,
# 'task_completion_status': {'count': 0, 'completed_count': 0},
# 'has_conflicts': True,
# 'blocking_discussions_resolved': True}
#
# In [173]: mr.pipelines()
# Out[173]:
# [{'id': 10456,
# 'sha': 'b082d6abc2dd0eff89c5b2d5a200afed87f871bd',
# 'ref': 'topic/default/ux-migractions-get-connections',
# 'status': 'failed',
# 'created_at': '2020-07-22T02:01:45.244Z',
# 'updated_at': '2020-07-22T02:49:01.167Z',
# 'web_url': 'https://forge.extranet.logilab.fr/cubicweb/cubicweb/pipelines/10456'},
# {'id': 10172,
# 'sha': 'ecd6627517e6d933fed6142251ac33e01feadb7d',
# 'ref': 'topic/default/ux-migractions-get-connections',
# 'status': 'success',
# 'created_at': '2020-07-15T19:14:46.111Z',
# 'updated_at': '2020-07-15T19:49:18.689Z',
# 'web_url': 'https://forge.extranet.logilab.fr/cubicweb/cubicweb/pipelines/10172'},
# {'id': 10139,
# 'sha': '80da4968dbd33dc3c595f34ed42f363c09afe93b',
# 'ref': 'topic/default/ux-migractions-get-connections',
# 'status': 'success',
# 'created_at': '2020-07-15T13:48:35.325Z',
# 'updated_at': '2020-07-15T14:23:44.391Z',
# 'web_url': 'https://forge.extranet.logilab.fr/cubicweb/cubicweb/pipelines/10139'},
# {'id': 9981,
# 'sha': '43ba55bcb3b09008ea180f9fb13e38871c61d72a',
# 'ref': 'topic/default/ux-migractions-get-connections',
# 'status': 'failed',
# 'created_at': '2020-07-08T21:26:50.427Z',
# 'updated_at': '2020-07-08T22:05:34.317Z',
# 'web_url': 'https://forge.extranet.logilab.fr/cubicweb/cubicweb/pipelines/9981'},
# {'id': 9963,
# 'sha': '927761a999636ce7a8707ce5e320d0aa1f840c77',
# 'ref': 'topic/default/ux-migractions-get-connections',
# 'status': 'failed',
# 'created_at': '2020-07-08T13:40:32.447Z',
# 'updated_at': '2020-07-08T14:16:23.240Z',
# 'web_url': 'https://forge.extranet.logilab.fr/cubicweb/cubicweb/pipelines/9963'}]
#
# In [174]: project.labels.list(all=True)[0].attributes
# Out[174]:
# {'id': 945,
# 'name': 'Doing',
# 'color': '#5CB85C',
# 'description': 'Issue in progress',
# 'description_html': 'Issue in progress',
# 'text_color': '#FFFFFF',
# 'subscribed': True,
# 'priority': None,
# 'is_project_label': True,
# 'project_id': 385}
......@@ -12,6 +12,18 @@ h1 {
text-align: center;
}
h1 small {
color: grey;
font-size: 18px;
font-style: italic;
}
span.label {
padding: 2px 5px 1px 5px;
border-radius: 7px;
white-space: nowrap;
}
table.pipelines {
width: 100%;
border-collapse: collapse;
......@@ -52,4 +64,34 @@ div.job-warning {
border-color: yellow;
background-color: lightyellow;
color: orange;
}
\ No newline at end of file
}
span.job {
padding: 0 8.5px 0 8.5px;
margin-right: 5px;
border-radius: 10000000px;
text-align: center;
font-weight: bold;
border: solid 2px black;
}
span.job-success {
border-color: green;
background-color: lightgreen;
}
span.job-failed {
border-color: red;
background-color: orange;
}
span.job-warning {
padding: 0 4px 0 4px;
border-color: yellow;
background-color: lightyellow;
color: orange;
}
span.job-empty {
padding: 0 4px 0 4px;
}
<!doctype html>
<html>
<head>
<title>All open MRs</title>
<link href="../style.css" rel="stylesheet" type="text/css">
</head>
<body>
<h1>MR Center <small>all PR that needs attention</small></h1>
<h2>CubicWeb Core Projects</h2>
{% for project in projects.values() %}
{% if project["merge_requests"] %}
<h3>{{ project["project"]["name"] }}</h3>
<ul>
{% for mr in project["merge_requests"] %}
<li>
{% if mr["pipeline"] %}
<span class="job job-{{ mr["pipeline"]["status"] }}"> </span>
{% else %}
<span class="job job-empty">?</span>
{% endif %}
{% if not mr["assignees"] %}
<span title="no one is assigned">
⚠️
</span>
{% endif %}
<a href="{{ mr["web_url"] }}" target="_blank">{{ mr["title"] }}</a>
by <i>{{ mr["author"]["name"] }}</i>
{% if mr["assignees"] %}
(assigned: {% for assigned in mr["assignees"] %}{{ assigned["name"] }}{% endfor %})
{% endif %}
{% for label in mr["labels"] %}
<span class="label" style="color: {{ project["labels"][label]["text_color"] }}; background-color: {{ project["labels"][label]["color"] }}">{{ label }}</span>
{% endfor %}
</li>
{% endfor %}
</ul>
{% endif %}
{% endfor %}
<h2>Cubes</h2>
{% for cube in cubes.values() %}
{% if cube["merge_requests"] %}
<h3>{{ cube["cube"]["name"] }}</h3>
<ul>
{% for mr in cube["merge_requests"] %}
<li>
{% if mr["pipeline"] %}
<span class="job job-{{ mr["pipeline"]["status"] }}"></span>
{% else %}
<span class="job job-empty">?</span>
{% endif %}
{% if not mr["assignees"] %}
<span title="no one is assigned">
⚠️
</span>
{% endif %}
<a href="{{ mr["web_url"] }}">{{ mr["title"] }}</a>
by <i>{{ mr["author"]["name"] }}</i>
{% if mr["assignees"] %}
(assigned: {% for assigned in mr["assignees"] %}{{ assigned["name"] }}{% endfor %})
{% endif %}
{% for label in mr["labels"] %}
<span class="label" style="color: {{ cube["labels"][label]["text_color"] }}; background-color: {{ cube["labels"][label]["color"] }}">{{ label }}</span>
{% endfor %}
</li>
{% endfor %}
</ul>
{% endif %}
{% endfor %}
</body>
</html>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment