def test_quiet_period(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) jb = jk.create_job("test_quiet_period", FreestyleJob) with clean_job(jb): jb.quiet_period = 0 # first set our quiet period expected_duration = 10 jb.quiet_period = expected_duration expected_output = "Testing my quiet period" failing_step = ShellBuilder.instantiate("echo " + expected_output) jb.add_builder(failing_step) async_assert(lambda: jb.builders) assert jb.quiet_period_enabled is True assert jb.quiet_period == expected_duration # Launch a build and time how long it takes to complete start = timeit.default_timer() jb.start_build() async_assert(lambda: jb.last_build, expected_duration + 5) duration = timeit.default_timer() - start assert duration >= expected_duration bld = jb.last_build assert expected_output in bld.console_output
def test_add_then_edit_unstable_return_code(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) job_name = "test_add_then_edit_unstable_return_code" jb = jk.create_job(job_name, FreestyleJob) with clean_job(jb): jb.quiet_period = 0 rcode = 12 failing_step = ShellBuilder.instantiate("exit " + str(rcode)) failing_step.unstable_return_code = 1 jb.add_builder(failing_step) # Edit the build step using the original failed_step object - # these changes should still get applied to the job the step is # associated with failing_step.unstable_return_code = rcode # Get a fresh copy of our job to ensure we have an up to date # copy of the config.xml for the job async_assert(lambda: jk.find_job(job_name).builders) jb2 = jk.find_job(job_name) # run a build to see if the changes were auto applied jb2.start_build() async_assert(lambda: jb2.last_build) bld = jb2.last_build # Because of our changes to the configuration, the returned error code # should have resulted in an unstable build instead of a failed build assert bld.result == "UNSTABLE"
def test_never_run_condition(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) expected_job_name = "test_never_run_condition" jb = jk.create_job(expected_job_name, FreestyleJob) with clean_job(jb): expected_output = "Here is my sample output..." shell_builder = ShellBuilder.instantiate("echo " + expected_output) condition = NeverRun.instantiate() conditional_builder = ConditionalBuilder.instantiate( condition, shell_builder) jb.add_builder(conditional_builder) # Get a fresh copy of our job to ensure we have an up to date # copy of the config.xml for the job async_assert(lambda: jk.find_job(expected_job_name).builders) builders = jk.find_job(expected_job_name).builders # Make sure the builder was correctly configured assert builders[0].condition is not None assert isinstance(builders[0].condition, NeverRun) assert builders[0].condition.get_friendly_name() == "never" # Finally, just to be sure our build actually did something relevant # we make sure the output from our shell command appears in the # build output for a build (ie: to ensure the conditional build step # actually ran) jb.start_build() async_assert(lambda: jb.last_build) assert expected_output not in jb.last_build.console_output
def test_build_blocker_functionality(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) job_name1 = "test_build_blocker_functionality1" jb1 = jk.create_job(job_name1, FreestyleJob) with clean_job(jb1): job_name2 = "test_build_blocker_functionality2" jb2 = jk.create_job(job_name2, FreestyleJob) with clean_job(jb2): expected_jobs = job_name2 build_blocker = BuildBlockerProperty.instantiate(expected_jobs) jb1.quiet_period = 0 jb1.add_property(build_blocker) # Get a fresh copy of our job to ensure we have an up to date # copy of the config.xml for the job async_assert(lambda: jk.find_job(job_name1).properties) build_step = ShellBuilder.instantiate("sleep 10") jb2.quiet_period = 0 jb2.add_builder(build_step) async_assert(lambda: jb2.builders) queue2 = jb2.start_build() async_assert(lambda: not queue2.waiting) queue1 = jb1.start_build() assert job_name2 in queue1.reason queue2.build.abort() assert queue1.waiting is False
def test_add_conditional_builder(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) expected_job_name = "test_add_conditional_builder" jb = jk.create_job(expected_job_name, FreestyleJob) with clean_job(jb): expected_output = "Here is my sample output..." expected_cmd = "echo " + expected_output shell_builder = ShellBuilder.instantiate(expected_cmd) condition = AlwaysRun.instantiate() conditional_builder = ConditionalBuilder.instantiate(condition, shell_builder) jb.add_builder(conditional_builder) # Get a fresh copy of our job to ensure we have an up to date # copy of the config.xml for the job async_assert(lambda: jk.find_job(expected_job_name).builders) builders = jk.find_job(expected_job_name).builders # Make sure the builder was successfully added and it's response # data can be parsed correctly assert isinstance(builders, list) assert len(builders) == 1 assert isinstance(builders[0], ConditionalBuilder) assert builders[0].builder is not None assert isinstance(builders[0].builder, ShellBuilder) assert builders[0].builder.script == expected_cmd assert_elements_equal(builders[0].builder.node, shell_builder.node)
def test_always_run_condition(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) expected_job_name = "test_always_run_condition" jb = jk.create_job(expected_job_name, FreestyleJob) with clean_job(jb): expected_output = "Here is my sample output..." expected_cmd = "echo " + expected_output shell_builder = ShellBuilder.instantiate(expected_cmd) condition = AlwaysRun.instantiate() conditional_builder = ConditionalBuilder.instantiate( condition, shell_builder) jb.add_builder(conditional_builder) # Wait until our job config has been applied successfully async_assert(lambda: jk.find_job(expected_job_name).builders) # Make sure the condition is loaded correctly builders = jk.find_job(expected_job_name).builders assert isinstance(builders[0].condition, AlwaysRun) assert builders[0].condition.get_friendly_name() == "always" # Run a build and make sure the build operation actually executed jb.start_build() async_assert(lambda: jb.last_build) assert expected_output in jb.last_build.console_output
def test_wait_for_idle(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) node = jk.nodes[0] expected_job_name = "test_wait_for_idle_job" jb = jk.create_job(expected_job_name, FreestyleJob) with clean_job(jb): jb.quiet_period = 0 shell_builder = ShellBuilder.instantiate("sleep 2") jb.add_builder(shell_builder) # Get a fresh copy of our job to ensure we have an up to date # copy of the config.xml for the job async_assert(lambda: jk.find_job(expected_job_name).builders) # Trigger a build jb.start_build() # The 'last_build' reference becomes available as soon as the previously # triggered build exits the queue and starts running. So we wait for the # last build to become valid before checking the node activity async_assert(lambda: jb.last_build) assert node.is_idle is False assert node.wait_for_idle() assert node.is_idle
def test_artifacts_archived(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) job_name = "test_artifacts_archived_job" jb = jk.create_job(job_name, FreestyleJob) with clean_job(jb): publisher = ArtifactArchiverPublisher.instantiate("*.txt") jb.add_publisher(publisher) # Wait until our publisher config get's applied async_assert(lambda: jk.find_job(job_name).publishers) expected_file = "test_artifacts_archived_job.txt" shell_builder = ShellBuilder.instantiate("echo hello > " + expected_file) jb.add_builder(shell_builder) # Wait until our builder get's applied async_assert(lambda: jk.find_job(job_name).builders) # Next, trigger a build jb.start_build() async_assert(lambda: len(jb.all_builds) == 1) # finally, make sure the list or archived artifacts looks correct bld = jb.all_builds[0] results = bld.artifact_urls assert isinstance(results, list) assert len(results) == 1 assert expected_file in results[0]
def test_artifacts_archived(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) job_name = "test_artifacts_archived_job" jb = jk.create_job(job_name, FreestyleJob) with clean_job(jb): publisher = ArtifactArchiverPublisher.instantiate("*.txt") jb.add_publisher(publisher) # Wait until our publisher config get's applied async_assert(lambda: jk.find_job(job_name).publishers) expected_file = "test_artifacts_archived_job.txt" shell_builder = ShellBuilder.instantiate("echo hello > " + expected_file) jb.add_builder(shell_builder) # Wait until our builder get's applied async_assert(lambda: jk.find_job(job_name).builders) # Next, trigger a build jb.start_build() async_assert(lambda: len(jb.all_builds) == 1) # finally, make sure the list or archived artifacts looks correct bld = jb.all_builds[0] results = bld.artifact_urls assert isinstance(results, list) assert len(results) == 1 assert expected_file in results[0]
def test_build_git_scm(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) job_name = "test_build_git_scm" jb = jk.create_job(job_name, FreestyleJob) with clean_job(jb): jb.quiet_period = 0 expected_url = "https://github.com/TheFriendlyCoder/pyjen.git" test_scm = GitSCM.instantiate(expected_url) jb.scm = test_scm async_assert(lambda: isinstance(jb.scm, GitSCM)) # If the Git SCM was set up correctly, the job should check out the # source code for pyjen into the workspace when building. That being # the case there should be a setup.py script in the root folder. We # can therefore check to see if the SCM operation completed successfully # by looking for that file and setting a non-zero error code as part # of a shell builder operation shell_builder = ShellBuilder.instantiate("[ -f setup.py ]") jb.add_builder(shell_builder) # Get a fresh copy of our job to ensure we have an up to date # copy of the config.xml for the job async_assert(lambda: jk.find_job(job_name).builders) jb.start_build() async_assert(lambda: jb.last_good_build or jb.last_failed_build) assert jb.last_good_build is not None
def test_build_blocker_functionality(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) job_name1 = "test_build_blocker_functionality1" jb1 = jk.create_job(job_name1, FreestyleJob) with clean_job(jb1): job_name2 = "test_build_blocker_functionality2" jb2 = jk.create_job(job_name2, FreestyleJob) with clean_job(jb2): expected_jobs = job_name2 build_blocker = BuildBlockerProperty.instantiate(expected_jobs) jb1.quiet_period = 0 jb1.add_property(build_blocker) # Get a fresh copy of our job to ensure we have an up to date # copy of the config.xml for the job async_assert(lambda: jk.find_job(job_name1).properties) build_step = ShellBuilder.instantiate("sleep 10") jb2.quiet_period = 0 jb2.add_builder(build_step) async_assert(lambda: jb2.builders) queue2 = jb2.start_build() async_assert(lambda: not queue2.waiting) queue1 = jb1.start_build() assert job_name2 in queue1.reason queue2.build.abort() assert queue1.waiting is False
def test_clone_job(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) jb = jk.create_job("test_clone_job", FreestyleJob) with clean_job(jb): # add a builder to our source job so we can check to make sure the # configuration has been properly cloned expected_script = "echo Hello From TestCloneJob" failing_step = ShellBuilder.instantiate(expected_script) jb.add_builder(failing_step) async_assert(lambda: jb.builders) # now, clone our job configuration and make sure the entire config # has been cloned correctly expected_name = "test_clone_job2" jb_clone = jb.clone(expected_name) with clean_job(jb_clone): assert jb_clone is not None assert jb_clone.name == expected_name assert jb_clone.is_disabled results = jb_clone.builders assert results is not None assert isinstance(results, list) assert len(results) == 1 assert isinstance(results[0], ShellBuilder) assert results[0].script == expected_script
def test_quiet_period(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) jb = jk.create_job("test_quiet_period", FreestyleJob) with clean_job(jb): jb.quiet_period = 0 # first set our quiet period expected_duration = 10 jb.quiet_period = expected_duration expected_output = "Testing my quiet period" failing_step = ShellBuilder.instantiate("echo " + expected_output) jb.add_builder(failing_step) async_assert(lambda: jb.builders) assert jb.quiet_period_enabled is True assert jb.quiet_period == expected_duration # Launch a build and time how long it takes to complete start = timeit.default_timer() jb.start_build() async_assert(lambda: jb.last_build, expected_duration + 5) duration = timeit.default_timer() - start assert duration >= expected_duration bld = jb.last_build assert expected_output in bld.console_output
def test_always_run_condition(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) expected_job_name = "test_always_run_condition" jb = jk.create_job(expected_job_name, FreestyleJob) with clean_job(jb): expected_output = "Here is my sample output..." expected_cmd = "echo " + expected_output shell_builder = ShellBuilder.instantiate(expected_cmd) condition = AlwaysRun.instantiate() conditional_builder = ConditionalBuilder.instantiate(condition, shell_builder) jb.add_builder(conditional_builder) # Wait until our job config has been applied successfully async_assert(lambda: jk.find_job(expected_job_name).builders) # Make sure the condition is loaded correctly builders = jk.find_job(expected_job_name).builders assert isinstance(builders[0].condition, AlwaysRun) assert builders[0].condition.get_friendly_name() == "always" # Run a build and make sure the build operation actually executed jb.start_build() async_assert(lambda: jb.last_build) assert expected_output in jb.last_build.console_output
def test_clone_job(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) jb = jk.create_job("test_clone_job", FreestyleJob) with clean_job(jb): # add a builder to our source job so we can check to make sure the # configuration has been properly cloned expected_script = "echo Hello From TestCloneJob" failing_step = ShellBuilder.instantiate(expected_script) jb.add_builder(failing_step) async_assert(lambda: jb.builders) # now, clone our job configuration and make sure the entire config # has been cloned correctly expected_name = "test_clone_job2" jb_clone = jb.clone(expected_name) with clean_job(jb_clone): assert jb_clone is not None assert jb_clone.name == expected_name assert jb_clone.is_disabled results = jb_clone.builders assert results is not None assert isinstance(results, list) assert len(results) == 1 assert isinstance(results[0], ShellBuilder) assert results[0].script == expected_script
def test_wait_for_idle(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) node = jk.nodes[0] expected_job_name = "test_wait_for_idle_job" jb = jk.create_job(expected_job_name, FreestyleJob) with clean_job(jb): jb.quiet_period = 0 shell_builder = ShellBuilder.instantiate("sleep 2") jb.add_builder(shell_builder) # Get a fresh copy of our job to ensure we have an up to date # copy of the config.xml for the job async_assert(lambda: jk.find_job(expected_job_name).builders) # Trigger a build jb.start_build() # The 'last_build' reference becomes available as soon as the previously # triggered build exits the queue and starts running. So we wait for the # last build to become valid before checking the node activity async_assert(lambda: jb.last_build) assert node.is_idle is False assert node.wait_for_idle() assert node.is_idle
def test_add_conditional_builder(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) expected_job_name = "test_add_conditional_builder" jb = jk.create_job(expected_job_name, FreestyleJob) with clean_job(jb): expected_output = "Here is my sample output..." expected_cmd = "echo " + expected_output shell_builder = ShellBuilder.instantiate(expected_cmd) condition = AlwaysRun.instantiate() conditional_builder = ConditionalBuilder.instantiate( condition, shell_builder) jb.add_builder(conditional_builder) # Get a fresh copy of our job to ensure we have an up to date # copy of the config.xml for the job async_assert(lambda: jk.find_job(expected_job_name).builders) builders = jk.find_job(expected_job_name).builders # Make sure the builder was successfully added and it's response # data can be parsed correctly assert isinstance(builders, list) assert len(builders) == 1 assert isinstance(builders[0], ConditionalBuilder) assert builders[0].builder is not None assert isinstance(builders[0].builder, ShellBuilder) assert builders[0].builder.script == expected_cmd assert_elements_equal(builders[0].builder.node, shell_builder.node)
def test_never_run_condition(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) expected_job_name = "test_never_run_condition" jb = jk.create_job(expected_job_name, FreestyleJob) with clean_job(jb): expected_output = "Here is my sample output..." shell_builder = ShellBuilder.instantiate("echo " + expected_output) condition = NeverRun.instantiate() conditional_builder = ConditionalBuilder.instantiate(condition, shell_builder) jb.add_builder(conditional_builder) # Get a fresh copy of our job to ensure we have an up to date # copy of the config.xml for the job async_assert(lambda: jk.find_job(expected_job_name).builders) builders = jk.find_job(expected_job_name).builders # Make sure the builder was correctly configured assert builders[0].condition is not None assert isinstance(builders[0].condition, NeverRun) assert builders[0].condition.get_friendly_name() == "never" # Finally, just to be sure our build actually did something relevant # we make sure the output from our shell command appears in the # build output for a build (ie: to ensure the conditional build step # actually ran) jb.start_build() async_assert(lambda: jb.last_build) assert expected_output not in jb.last_build.console_output
def test_is_unstable(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) jb = jk.create_job("test_is_unstable_job", FreestyleJob) with clean_job(jb): jb.quiet_period = 0 rcode = 12 failing_step = ShellBuilder.instantiate("exit " + str(rcode)) failing_step.unstable_return_code = rcode jb.add_builder(failing_step) async_assert(lambda: jb.builders) jb.start_build() async_assert(lambda: jb.last_unsuccessful_build) assert jb.is_unstable
def test_is_unstable(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) jb = jk.create_job("test_is_unstable_job", FreestyleJob) with clean_job(jb): jb.quiet_period = 0 rcode = 12 failing_step = ShellBuilder.instantiate("exit " + str(rcode)) failing_step.unstable_return_code = rcode jb.add_builder(failing_step) async_assert(lambda: jb.builders) jb.start_build() async_assert(lambda: jb.last_unsuccessful_build) assert jb.is_unstable
def test_get_last_failed_build(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) jb = jk.create_job("test_get_last_failed_build", FreestyleJob) with clean_job(jb): jb.quiet_period = 0 failing_step = ShellBuilder.instantiate("exit -1") jb.add_builder(failing_step) async_assert(lambda: jb.builders) jb.start_build() async_assert(lambda: jb.last_build) bld = jb.last_failed_build assert bld is not None assert isinstance(bld, Build) assert bld.number == 1 assert bld.result == "FAILURE"
def test_get_last_failed_build(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) jb = jk.create_job("test_get_last_failed_build", FreestyleJob) with clean_job(jb): jb.quiet_period = 0 failing_step = ShellBuilder.instantiate("exit -1") jb.add_builder(failing_step) async_assert(lambda: jb.builders) jb.start_build() async_assert(lambda: jb.last_build) bld = jb.last_failed_build assert bld is not None assert isinstance(bld, Build) assert bld.number == 1 assert bld.result == "FAILURE"
def test_get_last_unsuccessful_build(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) jb = jk.create_job("test_get_last_unsuccessful_build", FreestyleJob) with clean_job(jb): jb.quiet_period = 0 rcode = 12 failing_step = ShellBuilder.instantiate("exit " + str(rcode)) failing_step.unstable_return_code = rcode jb.add_builder(failing_step) async_assert(lambda: jb.builders) jb.start_build() async_assert(lambda: jb.last_unsuccessful_build) bld = jb.last_unsuccessful_build assert bld is not None assert isinstance(bld, Build) assert bld.number == 1 assert bld.result == "UNSTABLE"
def test_console_text(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) expected_job_name = "test_console_text_job" jb = jk.create_job(expected_job_name, FreestyleJob) with clean_job(jb): jb.quiet_period = 0 expected_output = "Here is my sample output..." shell_builder = ShellBuilder.instantiate("echo " + expected_output) jb.add_builder(shell_builder) # Get a fresh copy of our job to ensure we have an up to date # copy of the config.xml for the job async_assert(lambda: jk.find_job(expected_job_name).builders) # Trigger a build and wait for it to complete jb.start_build() async_assert(lambda: jb.last_build) assert expected_output in jb.last_build.console_output
def test_add_simple_shell_builder(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) job_name = "test_add_simple_shell_builder" jb = jk.create_job(job_name, FreestyleJob) with clean_job(jb): expected_script = "echo hello" shell_builder = ShellBuilder.instantiate(expected_script) jb.add_builder(shell_builder) # Get a fresh copy of our job to ensure we have an up to date # copy of the config.xml for the job async_assert(lambda: jk.find_job(job_name).builders) builders = jk.find_job(job_name).builders assert isinstance(builders, list) assert len(builders) == 1 assert isinstance(builders[0], ShellBuilder) assert builders[0].script == expected_script assert builders[0].unstable_return_code is None
def test_unstable_return_code(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) job_name = "test_unstable_return_code" jb = jk.create_job(job_name, FreestyleJob) with clean_job(jb): rcode = 12 failing_step = ShellBuilder.instantiate("exit " + str(rcode)) failing_step.unstable_return_code = rcode jb.add_builder(failing_step) async_assert(lambda: jb.builders) # Get a fresh copy of our job to ensure we have an up to date # copy of the config.xml for the job async_assert(lambda: jk.find_job(job_name).builders) builders = jk.find_job(job_name).builders assert isinstance(builders, list) assert len(builders) == 1 assert builders[0].unstable_return_code == rcode
def test_get_last_unsuccessful_build(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) jb = jk.create_job("test_get_last_unsuccessful_build", FreestyleJob) with clean_job(jb): jb.quiet_period = 0 rcode = 12 failing_step = ShellBuilder.instantiate("exit " + str(rcode)) failing_step.unstable_return_code = rcode jb.add_builder(failing_step) async_assert(lambda: jb.builders) jb.start_build() async_assert(lambda: jb.last_unsuccessful_build) bld = jb.last_unsuccessful_build assert bld is not None assert isinstance(bld, Build) assert bld.number == 1 assert bld.result == "UNSTABLE"
def test_abort(jenkins_env): jk = Jenkins(jenkins_env["url"], (jenkins_env["admin_user"], jenkins_env["admin_token"])) expected_job_name = "test_abort" jb = jk.create_job(expected_job_name, FreestyleJob) with clean_job(jb): jb.quiet_period = 0 shell_builder = ShellBuilder.instantiate("echo 'waiting for sleep' && sleep 40") jb.add_builder(shell_builder) # Get a fresh copy of our job to ensure we have an up to date # copy of the config.xml for the job async_assert(lambda: jk.find_job(expected_job_name).builders) # Trigger a build and wait for it to complete jb.start_build() async_assert(lambda: jb.last_build) async_assert(lambda: "waiting for sleep" in jb.last_build.console_output) jb.last_build.abort() assert jb.last_build.is_building is False assert jb.last_build.result == "ABORTED"