Clarity on phases/sections and their lifecycles

We are doing something fairly unique in regards to what we are testing, which is doing integration-level tests for a solution that configures an entire cloud (i.e. an instance of our infrastructure at a DC) via a single CLI execution (composes Ansible at a lower layer and exposes a simple interface via a bash-based CLI). The workflow to perform these integration tests looks like:

  • Install Tugboat, a CLI for DigitalOcean, and Ansible (dependencies.pre)
  • Create a ~16 node/droplet cloud on DigitalOcean via Tugboat (?, right now dependenies.pre)
  • Run Ansible site.yml which can be thought of as a test itself, exiting 0 on success and 1 on failure (test.override)
  • Run other integration-like Ansible playbooks which test for proper cloud state, exiting 0 on success and 1 on failure (test.override)
  • Destroy the ~16 node/droplet cloud on DigitalOcean via Tugboat (?, right now teardown.post)

With all that in mind, a few pointed questions on the phases/sections and their lifecycles:

  • Right now, I have the cloud creation step in dependencies.pre because it has a desirable feature in that if it fails it will not run the test phase/section. test.pre does not have this characteristic while database.pre does. Is there a better spot for this?
  • Right now, I have the cloud destruction step in the undocumented teardown.post, however it does not run in certain circumstances leaving the cloud up. For instance, if dependencies.pre fails, for whatever reason, this phase/section will not run. Are there any phases/sections and lifecycles steps that exhibit the characteristic of always running, no matter which previous phases/sections failed? Kinda like a finally block.

I would keep the cloud creation step in dependencies: pre for the exact reason of the build not continuing if that fails. If your test command is a single command, it might make sense to move the cloud creation to the test step and chain the two things:

test:
  override:
    - create-cloud && run-tests || fail-loudly

In this case, run-tests will only be executed if create-cloud returns 0.

Potentially, chaining could be the answer to your second question:

dependencies:
  pre:
    - create-cloud || cleanup-cloud

Would something like that work for you?

Sorry for not having a better way to perform the cleanup steps during the builds right now.

Yep, that would work and we are doing much of that already (done since first posting the question). Simply was curious if the phases/sections/lifecycle natively supported the needed functionality over a shell based approach.

We ended up needing to use tee and such to ensure that if the “test” fails that it fails the build via exit 1 while also still destroying the cloud which would return exit 0. It works though! :smile:

Really appreciate the insight!

1 Like