summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ick2/__init__.py1
-rw-r--r--ick2/state.py25
-rw-r--r--ick2/workapi.py38
-rw-r--r--ick2/workapi_tests.py4
-rw-r--r--yarns/400-build.yarn85
-rw-r--r--yarns/500-build-fail.yarn13
6 files changed, 131 insertions, 35 deletions
diff --git a/ick2/__init__.py b/ick2/__init__.py
index 9af0521..1715e62 100644
--- a/ick2/__init__.py
+++ b/ick2/__init__.py
@@ -22,6 +22,7 @@ from .state import (
Workers,
Projects,
PipelineInstances,
+ Builds,
)
from .exceptions import (
BadUpdate,
diff --git a/ick2/state.py b/ick2/state.py
index 806b2a7..3a985a8 100644
--- a/ick2/state.py
+++ b/ick2/state.py
@@ -40,9 +40,9 @@ class ControllerState:
def get_resource_directory(self, type_name):
return os.path.join(self.get_state_directory(), type_name)
- def get_resource_filename(self, type_name, project_name):
- return os.path.join(
- self.get_resource_directory(type_name), project_name + '.yaml')
+ def get_resource_filename(self, type_name, resource_name):
+ dirname = self.get_resource_directory(type_name)
+ return os.path.join(dirname, resource_name + '.yaml')
def load_resources(self, type_name):
assert self._statedir is not None
@@ -107,10 +107,14 @@ class ResourceStore: # pragma: no cover
self._category = category
self._name_field = name_field
+ def get_resource_name(self, name):
+ return str(name)
+
def list(self):
return self._state.get_resources(self._category)
def get(self, name):
+ name = self.get_resource_name(name)
try:
return self._state.get_resource(self._category, name)
except ick2.NotFound:
@@ -119,10 +123,11 @@ class ResourceStore: # pragma: no cover
}
def add(self, name, resource):
+ name = self.get_resource_name(name)
self._state.add_resource(self._category, name, resource)
def update(self, resource):
- name = resource[self._name_field]
+ name = self.get_resource_name(resource[self._name_field])
try:
self._state.get_resource(self._category, name)
except ick2.NotFound:
@@ -155,6 +160,18 @@ class Projects(ResourceStore): # pragma: no cover
self.update(project)
+class Builds(ResourceStore): # pragma: no cover
+
+ def __init__(self, state):
+ super().__init__(state, 'builds', 'build_id')
+
+ def get_builds(self):
+ return self.list()
+
+ def update_build(self, build):
+ self.update(build)
+
+
class PipelineInstances(ResourceStore): # pragma: no cover
def __init__(self, state):
diff --git a/ick2/workapi.py b/ick2/workapi.py
index f4c76a7..7edafe0 100644
--- a/ick2/workapi.py
+++ b/ick2/workapi.py
@@ -23,6 +23,7 @@ class WorkAPI(ick2.APIbase):
self._workers = ick2.Workers(state)
self._projects = ick2.Projects(state)
self._pinstances = ick2.PipelineInstances(state)
+ self._builds = ick2.Builds(state)
self._type_name = 'work'
def get_routes(self, path): # pragma: no cover
@@ -55,8 +56,10 @@ class WorkAPI(ick2.APIbase):
self._start_build(project, pipeline, worker, build_id)
self._start_log(build_id)
+ build = self._get_build(build_id)
+ actions = build['actions']
+ current_action = build['current_action']
- index = 0
doing = {
'build_id': build_id,
'worker': worker,
@@ -64,8 +67,7 @@ class WorkAPI(ick2.APIbase):
'pipeline': pipeline['name'],
'parameters': project.get('parameters', {}),
'fresh_workspace': True,
- 'step': pipeline['actions'][index],
- 'step_index': index,
+ 'step': actions[current_action],
'log': '/logs/{}'.format(build_id),
}
@@ -108,10 +110,15 @@ class WorkAPI(ick2.APIbase):
'pipeline': pipeline['name'],
'parameters': parameters,
'status': 'building',
+ 'actions': pipeline['actions'],
+ 'current_action': 0,
}
- self._state.add_resource('builds', str(build_id), build)
+ self._builds.add(build_id, build)
return build_id
+ def _get_build(self, build_id):
+ return self._builds.get(build_id)
+
def _start_log(self, build_id):
ick2.log.log('info', msg_text='Starting new log', build_id=build_id)
log = {
@@ -134,16 +141,20 @@ class WorkAPI(ick2.APIbase):
exit_code = update.get('exit_code')
if exit_code == 0:
- index = doing['step_index'] + 1
- actions = pipeline['actions']
- if index >= len(actions):
+ build_id = doing['build_id']
+ build = self._get_build(build_id)
+ actions = build['actions']
+ current_action = build['current_action']
+ if current_action + 1 >= len(actions):
pipeline['status'] = 'idle'
self._update_pipeline(project, pipeline)
doing = {}
self._finish_build(update)
else:
- doing['step_index'] = index
- doing['step'] = dict(actions[index])
+ index = current_action + 1
+ build['current_action'] = index
+ self._update_build(build)
+ doing['step'] = actions[index]
doing['fresh_workspace'] = False
worker_state = {
@@ -197,10 +208,15 @@ class WorkAPI(ick2.APIbase):
log['log'] += text
self._state.update_resource('log', str(build_id), log)
+ def _update_build(self, build):
+ self._builds.update_build(build)
+
def _finish_build(self, update):
- build = self._state.get_resource('builds', str(update['build_id']))
+ build_id = update['build_id']
+ build = self._get_build(build_id)
build['status'] = update['exit_code']
- self._state.update_resource('builds', str(update['build_id']), build)
+ build['current_action'] = None
+ self._update_build(build)
def create(self, body, **kwargs): # pragma: no cover
pass
diff --git a/ick2/workapi_tests.py b/ick2/workapi_tests.py
index d7ebfa9..51ac604 100644
--- a/ick2/workapi_tests.py
+++ b/ick2/workapi_tests.py
@@ -90,7 +90,6 @@ class WorkAPITests(unittest.TestCase):
'step': {
'shell': 'step-1',
},
- 'step_index': 0,
'log': '/logs/1',
}
self.assertEqual(work.get_work('asterix'), expected)
@@ -117,7 +116,6 @@ class WorkAPITests(unittest.TestCase):
'step': {
'shell': 'step-1',
},
- 'step_index': 0,
'log': '/logs/1',
}
self.assertEqual(work.get_work('asterix'), expected)
@@ -145,7 +143,6 @@ class WorkAPITests(unittest.TestCase):
# We should get the next step now.
expected['step'] = {'shell': 'step-2'}
- expected['step_index'] = 1
expected['fresh_workspace'] = False
self.assertEqual(work.get_work('asterix'), expected)
@@ -180,7 +177,6 @@ class WorkAPITests(unittest.TestCase):
'step': {
'shell': 'step-1',
},
- 'step_index': 0,
'log': '/logs/1',
}
self.assertEqual(work.get_work('asterix'), expected)
diff --git a/yarns/400-build.yarn b/yarns/400-build.yarn
index c8746b4..225bc3b 100644
--- a/yarns/400-build.yarn
+++ b/yarns/400-build.yarn
@@ -123,8 +123,7 @@ be in the path or can we get it in the access token?**
... "fresh_workspace": true,
... "step": {
... "shell": "day 1"
- ... },
- ... "step_index": 0
+ ... }
... }
WHEN worker-manager makes request GET /work/obelix
@@ -142,8 +141,7 @@ be in the path or can we get it in the access token?**
... "fresh_workspace": true,
... "step": {
... "shell": "day 1"
- ... },
- ... "step_index": 0
+ ... }
... }
User can now see pipeline is running and which worker is building it.
@@ -170,7 +168,6 @@ User can now see pipeline is running and which worker is building it.
... "foo": "bar"
... },
... "fresh_workspace": true,
- ... "step_index": 0,
... "step": {
... "shell": "day 1"
... }
@@ -188,6 +185,11 @@ User can now see pipeline is running and which worker is building it.
... "worker": "obelix",
... "project": "rome",
... "pipeline": "construct",
+ ... "actions": [
+ ... { "shell": "day 1" },
+ ... { "shell": "day 2" }
+ ... ],
+ ... "current_action": 0,
... "parameters": {
... "foo": "bar"
... },
@@ -217,7 +219,8 @@ Worker reports some build output. Note the null exit code.
... }
THEN result has status code 201
-Still the same job, since the first build step didnt't finish.
+Worker-manager still gets the same step, since the first build step
+didnt't finish.
WHEN worker-manager makes request GET /work/obelix
THEN result has status code 200
@@ -234,8 +237,7 @@ Still the same job, since the first build step didnt't finish.
... "fresh_workspace": true,
... "step": {
... "shell": "day 1"
- ... },
- ... "step_index": 0
+ ... }
... }
The build log is immediately accessible.
@@ -265,6 +267,33 @@ Report the step is done, and successfully.
AND result has header Content-Type: text/plain
AND body text is "hey ho, hey ho\n"
+The build status now shows the next step as the active one.
+
+ WHEN user makes request GET /builds
+ THEN result has status code 200
+ AND body matches
+ ... {
+ ... "builds": [
+ ... {
+ ... "build_id": 1,
+ ... "log": "/logs/1",
+ ... "worker": "obelix",
+ ... "project": "rome",
+ ... "pipeline": "construct",
+ ... "actions": [
+ ... { "shell": "day 1" },
+ ... { "shell": "day 2" }
+ ... ],
+ ... "current_action": 1,
+ ... "parameters": {
+ ... "foo": "bar"
+ ... },
+ ... "status": "building",
+ ... "log": "/logs/1"
+ ... }
+ ... ]
+ ... }
+
Now there's another step to do.
WHEN worker-manager makes request GET /work/obelix
@@ -282,8 +311,7 @@ Now there's another step to do.
... "fresh_workspace": false,
... "step": {
... "shell": "day 2"
- ... },
- ... "step_index": 1
+ ... }
... }
User sees changed status.
@@ -302,7 +330,6 @@ User sees changed status.
... "foo": "bar"
... },
... "fresh_workspace": false,
- ... "step_index": 1,
... "step": {
... "shell": "day 2"
... },
@@ -337,7 +364,8 @@ The pipeline status indicates success.
THEN result has status code 200
AND body matches { "status": "idle" }
-Also, there's a build with a log.
+Also, there's a build with a log. Also, the build status shows there's
+no current action.
WHEN user makes request GET /builds
THEN result has status code 200
@@ -350,6 +378,11 @@ Also, there's a build with a log.
... "worker": "obelix",
... "project": "rome",
... "pipeline": "construct",
+ ... "actions": [
+ ... { "shell": "day 1" },
+ ... { "shell": "day 2" }
+ ... ],
+ ... "current_action": null,
... "parameters": {
... "foo": "bar"
... },
@@ -368,6 +401,11 @@ Also, there's a build with a log.
... "worker": "obelix",
... "project": "rome",
... "pipeline": "construct",
+ ... "actions": [
+ ... { "shell": "day 1" },
+ ... { "shell": "day 2" }
+ ... ],
+ ... "current_action": null,
... "parameters": {
... "foo": "bar"
... },
@@ -401,8 +439,7 @@ Start build again. This should become build number 2.
... "fresh_workspace": true,
... "step": {
... "shell": "day 1"
- ... },
- ... "step_index": 0
+ ... }
... }
WHEN user makes request GET /builds
@@ -416,6 +453,11 @@ Start build again. This should become build number 2.
... "worker": "obelix",
... "project": "rome",
... "pipeline": "construct",
+ ... "actions": [
+ ... { "shell": "day 1" },
+ ... { "shell": "day 2" }
+ ... ],
+ ... "current_action": null,
... "parameters": {
... "foo": "bar"
... },
@@ -427,6 +469,11 @@ Start build again. This should become build number 2.
... "worker": "obelix",
... "project": "rome",
... "pipeline": "construct",
+ ... "actions": [
+ ... { "shell": "day 1" },
+ ... { "shell": "day 2" }
+ ... ],
+ ... "current_action": 0,
... "parameters": {
... "foo": "bar"
... },
@@ -475,6 +522,11 @@ Start build again. This should become build number 2.
... "worker": "obelix",
... "project": "rome",
... "pipeline": "construct",
+ ... "actions": [
+ ... { "shell": "day 1" },
+ ... { "shell": "day 2" }
+ ... ],
+ ... "current_action": null,
... "parameters": {
... "foo": "bar"
... },
@@ -486,6 +538,11 @@ Start build again. This should become build number 2.
... "worker": "obelix",
... "project": "rome",
... "pipeline": "construct",
+ ... "actions": [
+ ... { "shell": "day 1" },
+ ... { "shell": "day 2" }
+ ... ],
+ ... "current_action": null,
... "parameters": {
... "foo": "bar"
... },
diff --git a/yarns/500-build-fail.yarn b/yarns/500-build-fail.yarn
index bc0a5ab..a88108c 100644
--- a/yarns/500-build-fail.yarn
+++ b/yarns/500-build-fail.yarn
@@ -91,8 +91,7 @@ Worker wants work and gets the first step to run.
... "fresh_workspace": true,
... "step": {
... "shell": "day 1"
- ... },
- ... "step_index": 0
+ ... }
... }
Worker reports some build output. Note the exit code indicating
@@ -147,6 +146,11 @@ Also, there's a build with a log.
... "worker": "obelix",
... "project": "rome",
... "pipeline": "construct",
+ ... "actions": [
+ ... { "shell": "day 1" },
+ ... { "shell": "day 2" }
+ ... ],
+ ... "current_action": null,
... "parameters": {},
... "status": 1,
... "log": "/logs/1"
@@ -163,6 +167,11 @@ Also, there's a build with a log.
... "worker": "obelix",
... "project": "rome",
... "pipeline": "construct",
+ ... "actions": [
+ ... { "shell": "day 1" },
+ ... { "shell": "day 2" }
+ ... ],
+ ... "current_action": null,
... "parameters": {},
... "status": 1,
... "log": "/logs/1"