Commit 36b6bbb0 authored by Laurent Peuch's avatar Laurent Peuch
Browse files

feat: add qa dashboard

parent 33cef36b0fcb
Pipeline #12325 passed with stages
in 1 minute and 42 seconds
......@@ -20,6 +20,16 @@ pipelines_status:
- public/index.html
expire_in: 1 hour
cubes_qa:
before_script:
- pip install -r requirements.txt
script:
- TOKEN=$GITLAB_TOKEN python qa_dashboard.py
artifacts:
paths:
- public/qa.html
expire_in: 1 hour
pages:
stage: deploy
script:
......
......@@ -95,3 +95,18 @@ span.job-warning {
span.job-empty {
padding: 0 4px 0 4px;
}
table.qa, .qa th, .qa td {
border: 1px solid #AAA;
border-collapse: collapse;
padding: 5px 10px 5px 10px;
}
table.qa .true {
background-color: lightgreen;
}
table.qa .false {
background-color: lightsalmon;
}
\ No newline at end of file
......@@ -9,6 +9,7 @@
<ul>
<li><a href="mr.html">MRs that needs attention</a></li>
<li><a href="pipelines.html">Projects pipelines status</a></li>
<li><a href="qa.html">Cubes QA dashboard</a></li>
</ul>
</body>
</html>
#!/usr/bin/env python3
import os
import gitlab
import jinja2
gl = gitlab.Gitlab("https://forge.extranet.logilab.fr", oauth_token=os.environ.get("TOKEN"))
context = {"cubes": {}}
all_cubes = [x for x in gl.projects.list(all=True) if x.namespace["name"] == "cubes"]
for cube in all_cubes:
# black
# check-manifest
# tests
# python3
# flake8
# doc8
# a de la doc
# safety
# deprecation warnings ?
try:
cube.files.get("tox.ini", ref="branch/default")
has_tox = True
except (gitlab.GitlabHttpError, gitlab.GitlabGetError):
has_tox = False
try:
cube.files.get(".gitlab-ci.yml", ref="branch/default")
has_gitlab_ci = True
except (gitlab.GitlabHttpError, gitlab.GitlabGetError):
has_gitlab_ci = False
try:
cube.files.get("README.rst", ref="branch/default")
has_readme_rst = True
except (gitlab.GitlabHttpError, gitlab.GitlabGetError):
try:
cube.files.get("README.md", ref="branch/default")
has_readme_rst = True
except (gitlab.GitlabHttpError, gitlab.GitlabGetError):
has_readme_rst = False
context["cubes"][cube.name] = {
"cube": cube.attributes,
"has_tox": has_tox,
"has_gitlab_ci": has_gitlab_ci,
"has_readme_rst": has_readme_rst,
}
os.system("mkdir -p public") # XXX lazy
result = jinja2.Template(open("template/qa.html", "r").read()).render(**context)
open("public/qa.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}
<!doctype html>
<html>
<head>
<title>QA dashboard for cubes</title>
<link href="css/style.css" rel="stylesheet" type="text/css">
</head>
<body>
<h1>QA dashboard for cubes</h1>
<h2>Project Cubes</h2>
<table class="qa">
<tr>
<th>Cube</th>
<th>has tox?</th>
<th>has gitlab-ci?</th>
<th>README.rst? (or md)</th>
</tr>
{% for cube in cubes.values() %}
{% if "project-dependency" in cube["cube"]["tag_list"] %}
<tr>
<td><a target="_blank" href="{{ cube["cube"]["web_url"] }}">{{ cube["cube"]["name"] }}</a></td>
<td class="{{ "true" if cube["has_tox"] else "false" }}"></td>
<td class="{{ "true" if cube["has_gitlab_ci"] else "false" }}"></td>
<td class="{{ "true" if cube["has_readme_rst"] else "false" }}"></td>
</tr>
{% endif %}
{% endfor %}
</table>
<hr>
<h2>Unused Cubes</h2>
<table class="qa">
<tr>
<th>Cube</th>
<th>has tox?</th>
<th>has gitlab-ci?</th>
<th>README.rst? (or md)</th>
</tr>
{% for cube in cubes.values() %}
{% if "project-dependency" not in cube["cube"]["tag_list"] %}
<tr>
<td><a target="_blank" href="{{ cube["cube"]["web_url"] }}">{{ cube["cube"]["name"] }}</a></td>
<td class="{{ "true" if cube["has_tox"] else "false" }}"></td>
<td class="{{ "true" if cube["has_gitlab_ci"] else "false" }}"></td>
<td class="{{ "true" if cube["has_readme_rst"] else "false" }}"></td>
</tr>
{% 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