@@ -0,0 +1,73 | |||||
|
1 | import requests | |||
|
2 | import traceback | |||
|
3 | import configparser | |||
|
4 | from os.path import expanduser | |||
|
5 | home = expanduser("~") | |||
|
6 | ||||
|
7 | class TeamCityJsonObject: | |||
|
8 | ||||
|
9 | def __init__(self, json): | |||
|
10 | self.__dict__.update(json) | |||
|
11 | ||||
|
12 | def __repr__(self): | |||
|
13 | return str(self.__dict__) | |||
|
14 | ||||
|
15 | ||||
|
16 | class TeamCityProject(TeamCityJsonObject): | |||
|
17 | ||||
|
18 | def __init__(self, json): | |||
|
19 | super(TeamCityProject, self).__init__(json) | |||
|
20 | ||||
|
21 | ||||
|
22 | class TeamCityBuildType(TeamCityJsonObject): | |||
|
23 | ||||
|
24 | def __init__(self, json): | |||
|
25 | super(TeamCityBuildType, self).__init__(json) | |||
|
26 | ||||
|
27 | class TeamCityBuild(TeamCityJsonObject): | |||
|
28 | ||||
|
29 | def __init__(self, json): | |||
|
30 | super(TeamCityBuild, self).__init__(json) | |||
|
31 | ||||
|
32 | ||||
|
33 | class TeamCityAPI: | |||
|
34 | ||||
|
35 | def __init__(self, server, user, password): | |||
|
36 | self.server = server if '/app/rest' in server else server + '/app/rest' | |||
|
37 | self.session = requests.Session() | |||
|
38 | self.session.auth = (user, password) | |||
|
39 | self.session.headers.update({ | |||
|
40 | 'Accept': 'application/json', | |||
|
41 | 'Content-Type': 'application/json' | |||
|
42 | }) | |||
|
43 | ||||
|
44 | def projects(self): | |||
|
45 | projects = self.session.get( | |||
|
46 | self.server + '/projects').json() | |||
|
47 | return [TeamCityProject(project) for project in projects['project']] | |||
|
48 | ||||
|
49 | def build_types(self, project_id=None, project_name=None): | |||
|
50 | if project_id is not None: | |||
|
51 | url = self.server + '/projects/id:' + project_id + '/buildTypes' | |||
|
52 | elif project_name is not None: | |||
|
53 | url = self.server + '/projects/name:' + project_id + '/buildTypes' | |||
|
54 | else: | |||
|
55 | url = self.server + '/buildTypes' | |||
|
56 | build_types = self.session.get(url).json() | |||
|
57 | return [ | |||
|
58 | TeamCityBuildType(build_type) | |||
|
59 | for build_type in build_types['buildType'] | |||
|
60 | ] | |||
|
61 | ||||
|
62 | def build_queue(self): | |||
|
63 | build_queue = self.session.get(tc.server+'/buildQueue').json() | |||
|
64 | return [ | |||
|
65 | TeamCityBuild(build) | |||
|
66 | for build in build_queue['build'] | |||
|
67 | ] | |||
|
68 | ||||
|
69 | config = configparser.ConfigParser() | |||
|
70 | config.read(home+"/.teamcity.conf") | |||
|
71 | ||||
|
72 | ||||
|
73 | tc = TeamCityAPI(config['DEFAULT']['server'], config['DEFAULT']['user'],config['DEFAULT']['password']) No newline at end of file |
@@ -2,11 +2,11 | |||||
2 | "cells": [ |
|
2 | "cells": [ | |
3 | { |
|
3 | { | |
4 | "cell_type": "code", |
|
4 | "cell_type": "code", | |
5 | "execution_count": 1, |
|
5 | "execution_count": 21, | |
6 | "metadata": { |
|
6 | "metadata": { | |
7 | "ExecuteTime": { |
|
7 | "ExecuteTime": { | |
8 |
"end_time": "2018-01-0 |
|
8 | "end_time": "2018-01-09T08:09:49.457463Z", | |
9 |
"start_time": "2018-01-0 |
|
9 | "start_time": "2018-01-09T08:09:49.451783Z" | |
10 | }, |
|
10 | }, | |
11 | "init_cell": true |
|
11 | "init_cell": true | |
12 | }, |
|
12 | }, | |
@@ -52,8 +52,10 | |||||
52 | "* Rich plugin ecosystem\n", |
|
52 | "* Rich plugin ecosystem\n", | |
53 | "* Really customizable system\n", |
|
53 | "* Really customizable system\n", | |
54 | "* Not so complex...\n", |
|
54 | "* Not so complex...\n", | |
|
55 | "* Updates so easy (Compared to redmine...)\n", | |||
55 | "* Mostly written in Java\n", |
|
56 | "* Mostly written in Java\n", | |
56 | "* Closed source :(" |
|
57 | "* Closed source :(\n", | |
|
58 | "* Limited to 100 build cfg & 3 agents " | |||
57 | ] |
|
59 | ] | |
58 | }, |
|
60 | }, | |
59 | { |
|
61 | { | |
@@ -143,10 +145,12 | |||||
143 | "cell_type": "markdown", |
|
145 | "cell_type": "markdown", | |
144 | "metadata": { |
|
146 | "metadata": { | |
145 | "slideshow": { |
|
147 | "slideshow": { | |
146 |
"slide_type": " |
|
148 | "slide_type": "subslide" | |
147 | } |
|
149 | } | |
148 | }, |
|
150 | }, | |
149 | "source": [ |
|
151 | "source": [ | |
|
152 | "# Vocabulary\n", | |||
|
153 | "\n", | |||
150 | "* **Build artifact**: <span style=\"color:blue\">a file or a folder produced during the build </span> ( [example](https://hephaistos.lpp.polytechnique.fr/teamcity/overview.html) )" |
|
154 | "* **Build artifact**: <span style=\"color:blue\">a file or a folder produced during the build </span> ( [example](https://hephaistos.lpp.polytechnique.fr/teamcity/overview.html) )" | |
151 | ] |
|
155 | ] | |
152 | }, |
|
156 | }, | |
@@ -154,6 +158,22 | |||||
154 | "cell_type": "markdown", |
|
158 | "cell_type": "markdown", | |
155 | "metadata": { |
|
159 | "metadata": { | |
156 | "slideshow": { |
|
160 | "slideshow": { | |
|
161 | "slide_type": "fragment" | |||
|
162 | } | |||
|
163 | }, | |||
|
164 | "source": [ | |||
|
165 | "\n", | |||
|
166 | "\n", | |||
|
167 | "\n", | |||
|
168 | "\n", | |||
|
169 | "\n", | |||
|
170 | "* **Meta-Runners**: <span style=\"color:blue\">a build config that has been extracted to make a template </span> ( [example](https://hephaistos.lpp.polytechnique.fr/teamcity/admin/editProject.html?projectId=_Root&tab=metaRunner) )" | |||
|
171 | ] | |||
|
172 | }, | |||
|
173 | { | |||
|
174 | "cell_type": "markdown", | |||
|
175 | "metadata": { | |||
|
176 | "slideshow": { | |||
157 | "slide_type": "slide" |
|
177 | "slide_type": "slide" | |
158 | } |
|
178 | } | |
159 | }, |
|
179 | }, | |
@@ -209,6 +229,17 | |||||
209 | "cell_type": "markdown", |
|
229 | "cell_type": "markdown", | |
210 | "metadata": { |
|
230 | "metadata": { | |
211 | "slideshow": { |
|
231 | "slideshow": { | |
|
232 | "slide_type": "subslide" | |||
|
233 | } | |||
|
234 | }, | |||
|
235 | "source": [ | |||
|
236 | "# LPP goals (What we want)" | |||
|
237 | ] | |||
|
238 | }, | |||
|
239 | { | |||
|
240 | "cell_type": "markdown", | |||
|
241 | "metadata": { | |||
|
242 | "slideshow": { | |||
212 | "slide_type": "fragment" |
|
243 | "slide_type": "fragment" | |
213 | } |
|
244 | } | |
214 | }, |
|
245 | }, | |
@@ -220,6 +251,17 | |||||
220 | "cell_type": "markdown", |
|
251 | "cell_type": "markdown", | |
221 | "metadata": { |
|
252 | "metadata": { | |
222 | "slideshow": { |
|
253 | "slideshow": { | |
|
254 | "slide_type": "fragment" | |||
|
255 | } | |||
|
256 | }, | |||
|
257 | "source": [ | |||
|
258 | "* Give users maximum freedom" | |||
|
259 | ] | |||
|
260 | }, | |||
|
261 | { | |||
|
262 | "cell_type": "markdown", | |||
|
263 | "metadata": { | |||
|
264 | "slideshow": { | |||
223 | "slide_type": "slide" |
|
265 | "slide_type": "slide" | |
224 | } |
|
266 | } | |
225 | }, |
|
267 | }, | |
@@ -232,11 +274,15 | |||||
232 | }, |
|
274 | }, | |
233 | { |
|
275 | { | |
234 | "cell_type": "markdown", |
|
276 | "cell_type": "markdown", | |
235 |
"metadata": { |
|
277 | "metadata": { | |
|
278 | "slideshow": { | |||
|
279 | "slide_type": "slide" | |||
|
280 | } | |||
|
281 | }, | |||
236 | "source": [ |
|
282 | "source": [ | |
237 | "# Available build agents\n", |
|
283 | "# Available build agents\n", | |
238 | "\n", |
|
284 | "\n", | |
239 | "* Based on Docker cloud plugin\n", |
|
285 | "* Based on [Docker cloud plugin](https://plugins.jetbrains.com/plugin/9306-docker-cloud)\n", | |
240 | "* Virtually anything that runs either inside **Docker** or **VirtualBox**(Vagrant)\n", |
|
286 | "* Virtually anything that runs either inside **Docker** or **VirtualBox**(Vagrant)\n", | |
241 | "* Spawn on demand\n", |
|
287 | "* Spawn on demand\n", | |
242 | "* For now **Windows**, **Linux**(Fedora, Ubuntu), **FreeBSD** and **Mac OSX** 10.12.2(Siera)\n" |
|
288 | "* For now **Windows**, **Linux**(Fedora, Ubuntu), **FreeBSD** and **Mac OSX** 10.12.2(Siera)\n" | |
@@ -250,13 +296,33 | |||||
250 | } |
|
296 | } | |
251 | }, |
|
297 | }, | |
252 | "source": [ |
|
298 | "source": [ | |
|
299 | "# FreeBSD & Mac \n", | |||
|
300 | "\n", | |||
|
301 | "[meson@lpp](https://hephaistos.lpp.polytechnique.fr/teamcity/viewLog.html?buildId=6388&tab=buildLog&buildTypeId=mesonbuild_Build_2&logTab=tree&filter=all) [meson@travis](https://travis-ci.org/mesonbuild/meson/builds/325859215?utm_source=github_status&utm_medium=notification)\n", | |||
|
302 | "\n", | |||
|
303 | "[OSX agent](https://github.com/jeandet/teamcity-docker-agent-osx) [FreeBSD agent](https://github.com/jeandet/teamcity-docker-agent-freebsd)\n", | |||
|
304 | "\n", | |||
|
305 | "* Vagrant inside Docker\n", | |||
|
306 | "* Few txt files produces several GB machines\n", | |||
|
307 | "* Easy to deploy\n", | |||
|
308 | "* Hard to debug\n" | |||
|
309 | ] | |||
|
310 | }, | |||
|
311 | { | |||
|
312 | "cell_type": "markdown", | |||
|
313 | "metadata": { | |||
|
314 | "slideshow": { | |||
|
315 | "slide_type": "slide" | |||
|
316 | } | |||
|
317 | }, | |||
|
318 | "source": [ | |||
253 | "# I want to choose where I get built!\n", |
|
319 | "# I want to choose where I get built!\n", | |
254 | "\n", |
|
320 | "\n", | |
255 | "**Team city introduce the notion of build requirements.**\n", |
|
321 | "**Team city introduce the notion of build requirements.**\n", | |
256 | "\n", |
|
322 | "\n", | |
257 | "- Agents expose [parameters](https://hephaistos.lpp.polytechnique.fr/teamcity/agentDetails.html?agentTypeId=72&tab=agentParameters)(<=> properties). [sources](https://github.com/jeandet/teamcity-docker-complete-agent/blob/master/Dockerfile#L36)\n", |
|
323 | "- Agents expose [parameters](https://hephaistos.lpp.polytechnique.fr/teamcity/agentDetails.html?agentTypeId=72&tab=agentParameters)(<=> properties). ( [sources](https://github.com/jeandet/teamcity-docker-complete-agent/blob/master/Dockerfile#L36) )\n", | |
258 | "\n", |
|
324 | "\n", | |
259 |
"- |
|
325 | "- For each build config, ones can declare some [requirements](https://hephaistos.lpp.polytechnique.fr/teamcity/admin/editRequirements.html?id=buildType:Miniphare_Build) that the agent has to match to get spawned." | |
260 | ] |
|
326 | ] | |
261 | }, |
|
327 | }, | |
262 | { |
|
328 | { | |
@@ -267,7 +333,13 | |||||
267 | } |
|
333 | } | |
268 | }, |
|
334 | }, | |
269 | "source": [ |
|
335 | "source": [ | |
270 | "# What about reports?\n" |
|
336 | "# What about reports?\n", | |
|
337 | "\n", | |||
|
338 | "* As build artifact ( [LFR](https://hephaistos.lpp.polytechnique.fr/teamcity/viewLog.html?buildId=292&tab=artifacts&buildTypeId=LfrFlightSoftware_Build), [Hephaistos Web](https://hephaistos.lpp.polytechnique.fr/teamcity/project.html?projectId=HephaistosWeb&tab=projectOverview), [LibCDF](https://hephaistos.lpp.polytechnique.fr/teamcity/project.html?projectId=LibCDF&tab=projectOverview) )\n", | |||
|
339 | "* As Mail\n", | |||
|
340 | "* As slack message\n", | |||
|
341 | "* As stdout values ( [GStreamer Ninja](https://hephaistos.lpp.polytechnique.fr/teamcity/admin/editRunType.html?id=buildType:mesonbuild_GStreamerNightly&runnerId=RUNNER_69&cameFromUrl=%2Fteamcity%2Fadmin%2FeditBuildRunners.html%3Fid%3DbuildType%253Amesonbuild_GStreamerNightly%26init%3D1&cameFromTitle=) )\n", | |||
|
342 | "* As XML File ( [LibCDF GTest](https://hephaistos.lpp.polytechnique.fr/teamcity/admin/editBuildFeatures.html?id=buildType:LibCDF_Build) )" | |||
271 | ] |
|
343 | ] | |
272 | }, |
|
344 | }, | |
273 | { |
|
345 | { | |
@@ -278,7 +350,13 | |||||
278 | } |
|
350 | } | |
279 | }, |
|
351 | }, | |
280 | "source": [ |
|
352 | "source": [ | |
281 | "# API?" |
|
353 | "# Interactions with other tools\n", | |
|
354 | "\n", | |||
|
355 | "* SonarQube ([example](https://sonarcloud.io/dashboard?id=sciqlop), [config](https://hephaistos.lpp.polytechnique.fr/teamcity/admin/editRunType.html?id=buildType:SciQLop_Build&runnerId=RUNNER_22&cameFromUrl=%2Fteamcity%2Fadmin%2FeditBuildRunners.html%3Fid%3DbuildType%253ASciQLop_Build%26init%3D1&cameFromTitle=))\n", | |||
|
356 | "* Slack ([example](https://sciqlop.slack.com/messages/C57HU1KBJ/), [config](https://hephaistos.lpp.polytechnique.fr/teamcity/slacknotifications/index.html?projectId=SciQLop))\n", | |||
|
357 | "* Github, Bitbucket, VS Team Services...\n", | |||
|
358 | "* Rhodecode ([Miniphare PR](https://hephaistos.lpp.polytechnique.fr/rhodecode/GIT_REPOSITORIES/LPP/phare/miniphare/miniphare/pull-request/410), [config](https://hephaistos.lpp.polytechnique.fr/teamcity/admin/editRunType.html?id=buildType:Miniphare_Build&runnerId=RUNNER_82&cameFromUrl=%2Fteamcity%2Fadmin%2FeditBuildRunners.html%3Fid%3DbuildType%253AMiniphare_Build%26init%3D1&cameFromTitle=))\n", | |||
|
359 | "* [VS IDE plugin](https://confluence.jetbrains.com/display/TCD10/Visual+Studio+Addin), [Eclipse plugin](https://confluence.jetbrains.com/display/TCD10/Eclipse+Plugin), [IntelliJ-based IDEs](https://blog.jetbrains.com/teamcity/2017/10/teamcity-integration-with-intellij-based-ides/)" | |||
282 | ] |
|
360 | ] | |
283 | }, |
|
361 | }, | |
284 | { |
|
362 | { | |
@@ -289,8 +367,62 | |||||
289 | } |
|
367 | } | |
290 | }, |
|
368 | }, | |
291 | "source": [ |
|
369 | "source": [ | |
292 | "# Time to play!" |
|
370 | "# API?\n", | |
|
371 | "\n", | |||
|
372 | "* Quite easy to [understand](https://confluence.jetbrains.com/display/TCD10/REST+API) ( [buildTypes](https://hephaistos.lpp.polytechnique.fr/teamcity/app/rest/buildTypes/), [projects](https://hephaistos.lpp.polytechnique.fr/teamcity/app/rest/projects/) )\n", | |||
|
373 | "* Almost everything can be done through API" | |||
293 | ] |
|
374 | ] | |
|
375 | }, | |||
|
376 | { | |||
|
377 | "cell_type": "code", | |||
|
378 | "execution_count": 31, | |||
|
379 | "metadata": { | |||
|
380 | "ExecuteTime": { | |||
|
381 | "end_time": "2018-01-09T08:37:54.802150Z", | |||
|
382 | "start_time": "2018-01-09T08:37:54.793474Z" | |||
|
383 | }, | |||
|
384 | "slideshow": { | |||
|
385 | "slide_type": "slide" | |||
|
386 | } | |||
|
387 | }, | |||
|
388 | "outputs": [], | |||
|
389 | "source": [ | |||
|
390 | "import teamcity\n" | |||
|
391 | ] | |||
|
392 | }, | |||
|
393 | { | |||
|
394 | "cell_type": "markdown", | |||
|
395 | "metadata": { | |||
|
396 | "slideshow": { | |||
|
397 | "slide_type": "slide" | |||
|
398 | } | |||
|
399 | }, | |||
|
400 | "source": [ | |||
|
401 | "# What Next?\n", | |||
|
402 | "\n", | |||
|
403 | "* Improve Rhodecode integration\n", | |||
|
404 | "* Boost agents startup time\n", | |||
|
405 | "* Switch to Docker swarm\n", | |||
|
406 | "* More Meta-Runners" | |||
|
407 | ] | |||
|
408 | }, | |||
|
409 | { | |||
|
410 | "cell_type": "markdown", | |||
|
411 | "metadata": { | |||
|
412 | "slideshow": { | |||
|
413 | "slide_type": "slide" | |||
|
414 | } | |||
|
415 | }, | |||
|
416 | "source": [ | |||
|
417 | "# Questions?\n" | |||
|
418 | ] | |||
|
419 | }, | |||
|
420 | { | |||
|
421 | "cell_type": "code", | |||
|
422 | "execution_count": null, | |||
|
423 | "metadata": {}, | |||
|
424 | "outputs": [], | |||
|
425 | "source": [] | |||
294 | } |
|
426 | } | |
295 | ], |
|
427 | ], | |
296 | "metadata": { |
|
428 | "metadata": { |
General Comments 0
You need to be logged in to leave comments.
Login now