1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ # <bitbar.title>Gitlab CI</bitbar.title>
5
+ # <bitbar.desc>Shows currently running pipelines from your GitLab in your bar.</bitbar.desc>
6
+ # <bitbar.version>v0.21</bitbar.version>
7
+ # <bitbar.author>Martin Kluska</bitbar.author>
8
+ # <bitbar.author.github>pionl</bitbar.author.github>
9
+ # <bitbar.dependencies>python</bitbar.dependencies>
10
+ #
11
+
12
+ import json
13
+
14
+ try :
15
+ # For Python 3.0 and later
16
+ from urllib .request import urlopen
17
+ except ImportError :
18
+ # Fall back to Python 2's urllib2
19
+ from urllib2 import urlopen
20
+
21
+ # Define your server and projects (name: id)
22
+ PRIVATE_TOKEN = 'token'
23
+ URL = 'https://gitlab.example.com'
24
+ # To get id go to project -> Settings -> General -> General project settings
25
+ PROJECTS = {"React" : 3 }
26
+
27
+ pipelines = []
28
+
29
+ # Converts the gitlab status to emoji
30
+ def stateIcon (status ):
31
+ return {
32
+ "created" : "💤" ,
33
+ "pending" : "💤" ,
34
+ "running" : "🚀" ,
35
+ "failed" : "❗" ,
36
+ "success" : "✔️" ,
37
+ "skipped" : "🚀" ,
38
+ "manual" : "🚀"
39
+ }[status ]
40
+
41
+ # Calls gitlab API endpoint with private_token
42
+ def api (method ):
43
+ url = URL + "/api/v4/" + method
44
+ param = 'private_token=' + PRIVATE_TOKEN
45
+ # Detect if method has query string (we need to append private token)
46
+ url = url + (('&' ) if "?" in url else ('?' )) + param
47
+ body = urlopen (url ).read ()
48
+ return json .loads (body .decode ('utf-8' ))
49
+
50
+ # Project details
51
+ class Project :
52
+ def __init__ (self , name , id ):
53
+ self .name = name
54
+ self .id = id
55
+
56
+ # Pipile job
57
+ class Job :
58
+ def __init__ (self , json ):
59
+ self .name = json ["stage" ] + (": " + json ["name" ] if json ["name" ] != json ["stage" ] else "" )
60
+ self .status = json ["status" ]
61
+ self .duration = 0 if json ["duration" ] is None or self .status == 'running' else int (json ["duration" ])
62
+ self .commit = json ['commit' ]['title' ]
63
+
64
+ # Jobs name with duration
65
+ def displayName (self ):
66
+ return self .name + (' ' + str (self .duration ) + 's' if self .duration > 0 else '' )
67
+
68
+ # Pipile
69
+ class Pipeline :
70
+ def __init__ (self , projectName , projectId , json ):
71
+ self .project = Project (projectName , projectId )
72
+ self .id = json ["id" ]
73
+ self .jobs = []
74
+ self .runningJobs = []
75
+ self .ref = str (json ["ref" ])
76
+ self .commit = None
77
+
78
+ # Display name with current running jobs
79
+ def displayName (self ):
80
+ jobsString = '💤'
81
+
82
+ # Get running jobs and append the name
83
+ if len (self .runningJobs ) > 0 :
84
+ strings = []
85
+ for job in self .runningJobs :
86
+ strings .append (job .displayName ())
87
+
88
+ jobsString = ', ' .join (strings )
89
+
90
+ return self .project .name + ' - ' + self .ref + ' (' + jobsString + ')'
91
+
92
+ # Add jobs array json
93
+ def addJobs (self , jobsArray ):
94
+ for jobJson in jobsArray :
95
+ # Parse the job
96
+ job = Job (jobJson )
97
+ # Add the jobs array
98
+ self .jobs .append (job )
99
+
100
+ # Get the commit from the first job
101
+ if self .commit is None :
102
+ self .commit = job .commit
103
+
104
+ # Check if the job is running for running jobs array
105
+ if job .status == 'running' :
106
+ self .runningJobs .append (job )
107
+
108
+
109
+ # Loop the projects and get thy jobs
110
+ for name , project in PROJECTS .iteritems ():
111
+ runningPipelines = api ("projects/" + str (project )+ "/pipelines?scope=running" )
112
+
113
+ for pipelineJson in runningPipelines :
114
+ pipeline = Pipeline (name , project , pipelineJson )
115
+ jobsArray = api ("projects/" + str (project )+ "/pipelines/" + str (pipeline .id )+ "/jobs" )
116
+ if jobsArray .count > 0 :
117
+ pipeline .addJobs (jobsArray )
118
+ pipelines .append (pipeline )
119
+
120
+ pipelineCount = len (pipelines )
121
+ if pipelineCount == 0 :
122
+ print "💤"
123
+ exit
124
+
125
+
126
+ ## Render the pipelines names (bitbar will loop)
127
+ for index , pipeline in enumerate (pipelines ):
128
+ print '🚀 ' ,
129
+
130
+ if pipelineCount > 1 :
131
+ print str (index + 1 ) + '/' + str (pipelineCount ) + ' ' ,
132
+
133
+ print pipeline .displayName ()
134
+
135
+
136
+ ## Start menu
137
+ print "---"
138
+
139
+ for pipeline in pipelines :
140
+ print '🚀 ' + pipeline .project .name + ' - ' + pipeline .ref + '| color=black'
141
+ print '-- commit: ' + pipeline .commit + '| color=black'
142
+ print '---'
143
+ for job in pipeline .jobs :
144
+ print stateIcon (job .status ) + " " ,
145
+
146
+ style = ''
147
+ if job .status == 'success' :
148
+ style = '| color=green'
149
+ elif job .status == 'running' :
150
+ style = '| color=blue'
151
+
152
+ print job .displayName () + style
153
+
154
+
0 commit comments