| # Copyright 2021 The Fuchsia Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| from PB.go.chromium.org.luci.buildbucket.proto import ( |
| builds_service as builds_service_pb2, |
| ) |
| from PB.go.chromium.org.luci.buildbucket.proto import common as common_pb2 |
| from recipe_engine import recipe_api |
| |
| |
| class BuilderStateApi(recipe_api.RecipeApi): |
| """Provides common logic for passing generic "state" data between |
| sequential builds of a single builder. |
| |
| `state` can be any JSON-serializable Python object. |
| """ |
| |
| def fetch_previous_state(self, limit=5): |
| """Fetch the state of the previous build of the current builder. |
| |
| Looks at the last `limit` builds in case the immediately previous |
| build did not save its state (for example, because it infra-failed |
| before it was able to save its state). |
| """ |
| state = {} |
| previous_runs = self.m.buildbucket.search( |
| builds_service_pb2.BuildPredicate( |
| builder=self.m.buildbucket.build.builder, |
| status=common_pb2.ENDED_MASK, # Include only completed builds. |
| ), |
| fields=["output.properties"], |
| limit=limit, |
| step_name="fetch previous build state", |
| ) |
| |
| for run in previous_runs: |
| try: |
| previous_state = run.output.properties["state"] |
| except ValueError: |
| continue |
| if previous_state: |
| state = self.m.json.loads(previous_state) |
| break |
| return state |
| |
| def save(self, state): |
| """Save the current build's state to an output property. |
| |
| So that it can be fetched by the next build. |
| """ |
| step = self.m.step.empty("record state") |
| step.presentation.properties["state"] = self.m.json.dumps(state) |