newestuser / github-workflow-dashboard Goto Github PK
View Code? Open in Web Editor NEWWEB and CLI dashboard for github action workflows
WEB and CLI dashboard for github action workflows
Add new verbose flag and change all logs in non-server-mode to use verbose logging.
@NewestUser another problem of github is to delete workflow runs. Nobody wants to klick thousands of buttons. I added a python script into my tooling.
If you want to, you can implement this into your dashboard. (Did you know the "Lost-runs" problem, by changing the name of a worklfow name in the yml file?)
Greetings and best wishes. I use PyGithub.
def cleanup_workflow_runs(self, repo, workflow_selection=None, run_selection=None, interactive:bool=True):
''' Delete workflow runs.
Actual you have to do this manual, because a good-usable functionality to clean up the workflow runs on the github page is not implemented... This is lame.
This function will help you and saves your time.
see: https://support.github.com/ticket/personal/0/1260794
In case of interactive-mode
1. List workflows
-> Select workflow: Name, >LOST-RUNS< or all
2. List selectable runs
-> Select runs to delete (black list): Run Number(s), all, all-except-last, cancelled, failure or success
-> Select runs to not delete (white list): Run Number(s)
3. List selected runs (to delete)
-> Confirm
Parameter:
repo: Repository with type 'Github.get_repo()' or as str.
workflow_selection: default = None, e.g. 'Self Hosted CI'
run_selection: default = None, e.g. 'all', 'all-except-last', 'cancelled', 'failure' or 'success'
interactive: default = True. If True the function will expact yout input/selection. If False all workflow-runs will be deleted.
'''
# input management
if isinstance(repo, str):
repo = self.get_repo(repo)
if repo == None:
raise Exception("Selected Repository is not in your organization!")
# get runs
totalRunList = repo.get_workflow_runs()
# get a list of all workflows in the repo
workflowList = repo.get_workflows()
if workflowList.totalCount == 0:
print("There are no workflows in your selected repository: '{}'".format(repo.name))
return
# print list
print("List of all workflows of your selected repository: '{}'".format(repo.name))
run_count = 0
for workflow in workflowList:
runs = workflow.get_runs()
run_count = run_count + runs.totalCount
print(" ID: '{}', Name: '{}', State: '{}': Run(s): '{}'".format(workflow.id, workflow.name, workflow.state, runs.totalCount))
# calculate lost runs
lost_run_count = totalRunList.totalCount-run_count
if lost_run_count > 0:
print(" LOST-RUNS: There are '{}' workflow run(s) without an active yaml-file!".format(lost_run_count))
# if no selection of a workflow is initiated by function-call
if workflow_selection == None and interactive:
workflow_selection = input("Please select a workflow by Name (e.g. >CI< or >LOST-RUNS< or press [Return] for all):")
# if no interactive and no selection is done: choose the first workflow of the list
elif workflow_selection == None and not interactive:
print("No workflow chosen.")
# search workflow in list
found = False
# if no workflow chosen
if workflow_selection == None or workflow_selection == '':
found = True
runList = totalRunList
print("{} run(s) found.".format(totalRunList.totalCount))
# in case of lost runs
elif workflow_selection == 'LOST-RUNS':
found = True
runList = []
for run in totalRunList:
run_found = False
# check if run has a workflow
for workflow in workflowList:
if run.workflow_id == workflow.id:
run_found = True
# if not, add it to the run list
if run_found == False:
runList.append(run)
# raise exception if something went wrong
if len(runList) != lost_run_count:
raise Exception("Something went wrong with get lost runs!")
print("{} run(s) found.".format(lost_run_count))
# if workflow chosen
else:
for workflow in workflowList:
if workflow.name == workflow_selection:
print("Workflow found in list above: {}".format(workflow_selection))
found = True
# get runs
runList = workflow.get_runs()
print("{} run(s) found.".format(runList.totalCount))
break
# if workflow found
if found:
print("Run List: ")
for run in runList:
#print(" Run Number: '{}', Satus: '{}', Conclusion: '{}', ID: '{}'".format(run.run_number, run.status, run.conclusion, run.id))
print(" Run Number: '{}', Satus: '{}', Conclusion: '{}', ID: '{}', Branch: '{}', SHA: '{}'".format(run.run_number, run.status, run.conclusion, run.id, run.head_branch, run.head_sha[0:7]))
# get input
if run_selection == None and interactive:
ans = input("Select a special run number (e.g. 123), a list of workflow run numbers seperated by comma (e.g. 123, 111, 112) or type >all<, >all-except-last<, >cancelled<, >failure< or >success<:")
# choose all if no selection is done an not interaction is used
elif run_selection == None and not interactive:
ans = 'all'
# choose selection if special run is selected
else:
ans = run_selection
# manage input: choose selection
selectedRuns = []
# special run number is selected
if ans not in ['all', 'cancelled', 'failure', 'success', 'all-except-last']:
ansSplit = ans.split(',')
for id in ansSplit:
if id.isnumeric():
selectedRuns.append(int(id))
else:
raise Exception("Invalid input '{}'!".format(id))
else:
for run in runList:
# delete all runs
if ans == 'all':
selectedRuns.append(run.run_number)
# check conclusion
elif ans in ['cancelled', 'failure', 'success'] and run.conclusion == ans:
selectedRuns.append(run.run_number)
# in case of "all-except-last"
elif ans == 'all-except-last' and not run == runList[0]:
selectedRuns.append(run.run_number)
# whitelist
if interactive:
ans = input("Do you want to keep runs? Select a special run number (e.g. 123) or a list of workflow run numbers seperated by comma (e.g. 123, 111, 112). For no run keeping press [Return]:")
if ans != '':
keepRuns = []
# convert run slection
ansSplit = ans.split(',')
for id in ansSplit:
keepRuns.append(int(id))
# step over keep runs
for keepRun in keepRuns:
# search in list and change List
for selectedRun in selectedRuns:
if selectedRun == keepRun:
# delete keepRunId from run List (keeping)
selectedRuns.remove(keepRun)
break
# list runs to delete
if interactive:
print("Selected Run List: ")
for run in runList:
if run.run_number in selectedRuns:
#print(" Run Number: '{}', Satus: '{}', Conclusion: '{}', ID: '{}'".format(run.run_number, run.status, run.conclusion, run.id))
print(" Run Number: '{}', Satus: '{}', Conclusion: '{}', ID: '{}', Branch: '{}', SHA: '{}'".format(run.run_number, run.status, run.conclusion, run.id, run.head_branch, run.head_sha[0:7]))
ans = input("Confirm selection! Yes [default] or No:")
if ans in ['y', 'Y', 'yes', 'YES', 'Yes', '']:
pass
elif ans in ['n', 'N', 'no', 'NO', 'No']:
return
else:
print("Unkown input! Skip.")
return
# interate over list and
for run in runList:
if run.run_number in selectedRuns:
# delete completed workflow run
if run.status == 'completed':
print(" delete run with number: '{}'".format(run.run_number))
repo._requester.requestJson("DELETE", run.url)
# ask for cancel workflow run
else:
print("It is not possible to delete run: '{}'. This is not completed.".format(run.run_number))
if interactive:
ans = input("Do you want to cancel it? Yes [default] or No:")
if ans in ['y', 'Y', 'yes', 'YES', 'Yes', '']:
run.cancel()
print("Please rerun cleanup")
elif ans in ['n', 'N', 'no', 'NO', 'No']:
print("No cancel selected!")
else:
print("Unkown input! Skip.")
else:
print("Workflow '{}' not found in list above.".format(workflow_selection))```
检测到 NewestUser/github-workflow-dashboard 一共引入了80个开源组件,存在2个漏洞
漏洞标题:go-yaml < 2.2.8拒绝服务漏洞
缺陷组件:gopkg.in/[email protected]
漏洞编号:CVE-2019-11254
漏洞描述:gopkg.in/yaml.v2是go语言中用于处理yaml格式的包。
在2.2.8之前的版本中,处理恶意的yaml数据时,会导致CPU资源耗尽。
漏洞由Kubernetes开发者在fuzz测试中发现并提交修复补丁。
国家漏洞库信息:https://www.cnvd.org.cn/flaw/show/CNVD-2020-35519
影响范围:(∞, 2.2.8)
最小修复版本:2.2.8
缺陷组件引入路径:main@->gopkg.in/[email protected]
另外还有2个漏洞,详细报告:https://mofeisec.com/jr?p=a6272e
If you have a lot's of runs you wouln't find them anymore. They get be lost.
AND (the worst) they need a lots of space.
They should be deleted!
In the python script at issue #9 you can see how to filter the lost-runs.
Cheers
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.