Skip to main content

Python API with high level build flow constructs (parallel/serial) for Jenkins.

Project description

Build Status Coverage Documentation Status PyPi Package License

jenkinsflow

Python API with high level build flow constructs (parallel/serial) for Jenkins. Allows full scriptable control over the execution of Jenkins jobs. Allows a flow running on one Jenkins to control Jobs on other Jenkins instances. Also allows running ‘jobs’ as python scripts locally without using Jenkins.

import os

from jenkinsflow.flow import serial
from jenkinsflow.jenkins_api import JenkinsApi


def _flow():
    """Execute jobs on the same Jenkins that run the flow, or Jenkins on localhost if not running from a Jenkins job."""
    url = os.environ.get("JENKINS_URL") or "http://localhost:8080"
    username = os.environ["JENKINS_USERNAME"]
    token = os.environ["JENKINS_TOKEN"]

    # Jenkinsflow uses it's own specialized *JenkinsApi* to access Jenkins, using the Jenkins rest api.
    api = JenkinsApi(url, username=username, password=token)
    with serial(api, timeout=70, report_interval=3) as outer_ctrl:
        outer_ctrl.invoke("prepare")
        outer_ctrl.invoke("deploy_component")

        with outer_ctrl.parallel(timeout=0, report_interval=3) as report_prepare_ctrl:
            report_prepare_ctrl.invoke("report_deploy")
            report_prepare_ctrl.invoke("prepare_tests")

        with outer_ctrl.parallel(timeout=0, report_interval=3) as test_ctrl:
            test_ctrl.invoke("test_x")
            test_ctrl.invoke("test_y")

        outer_ctrl.invoke("report", password="Y", s1="tst", c1="complete")


if __name__ == "__main__":
    _flow()

Output (assuming all jobs ran succesfully):

=== Jenkinsflow ===

Legend:
Serial builds: []
Parallel builds: ()
Invocation-N (w/x,y/z):
    -N: 'Invocation N of same job', where N is invocation number which is increased every time a job has been explicitly
            invoked (as opposed to retried). '-N' is only present for jobs with multiple invocations.
    w=current retry invocation in current flow scope, x=max in scope, y=total number of invocations, z=total max invocations
Elapsed time: 'after: x/y': x=time spent during current run of job, y=time elapsed since start of outermost flow

--- Calculating flow graph ---
serial flow: [
   job: 'prepare'
   job: 'deploy_component'
   parallel flow: (
      job: 'report_deploy'
      job: 'prepare_tests'
   )

   parallel flow: (
      job: 'test_x'
      job: 'test_y'
   )

   job: 'report'
]



--- Getting initial job status ---
serial flow: [
   job: 'prepare' Status IDLE - latest build: #275
   job: 'deploy_component' Status IDLE - latest build: #273
   parallel flow: (
      job: 'report_deploy' Status IDLE - latest build: #273
      job: 'prepare_tests' Status IDLE - latest build: #273
   )

   parallel flow: (
      job: 'test_x' Status IDLE - latest build: #273
      job: 'test_y' Status IDLE - latest build: #273
   )

   job: 'report' Status IDLE - latest build: #273
]

Defined Invocation http://larsesmbp:8080/job/prepare
Defined Invocation http://larsesmbp:8080/job/deploy_component
Defined Invocation http://larsesmbp:8080/job/report_deploy
Defined Invocation http://larsesmbp:8080/job/prepare_tests
Defined Invocation http://larsesmbp:8080/job/test_x
Defined Invocation http://larsesmbp:8080/job/test_y
Defined Invocation http://larsesmbp:8080/job/report - parameters:
     c1 = 'complete'
     password = '******'
     s1 = 'tst'


--- Starting flow ---

Flow Invocation (1/1,1/1): ['prepare', 'deploy_component', ('report_deploy', 'prepare_tests'), ('test_x', 'test_y'), 'report']

Job Invocation (1/1,1/1): http://larsesmbp:8080/job/prepare
Build started: 'prepare' - http://larsesmbp:8080/job/prepare/276/console
job: 'prepare' stopped running
job: 'prepare' Status IDLE - build: #276
SUCCESS: 'prepare' - build: http://larsesmbp:8080/job/prepare/276/console after: 0.929s/1.013s

Job Invocation (1/1,1/1): http://larsesmbp:8080/job/deploy_component
Build started: 'deploy_component' - http://larsesmbp:8080/job/deploy_component/274/console
job: 'deploy_component' stopped running
job: 'deploy_component' Status IDLE - build: #274
SUCCESS: 'deploy_component' - build: http://larsesmbp:8080/job/deploy_component/274/console after: 0.755s/2.356s

Flow Invocation (1/1,1/1): ('report_deploy', 'prepare_tests')

Job Invocation (1/1,1/1): http://larsesmbp:8080/job/report_deploy
job: 'report_deploy' Status QUEUED

Job Invocation (1/1,1/1): http://larsesmbp:8080/job/prepare_tests
job: 'prepare_tests' Status QUEUED
Build started: 'report_deploy' - http://larsesmbp:8080/job/report_deploy/274/console
job: 'report_deploy' stopped running
job: 'report_deploy' Status IDLE - build: #274
SUCCESS: 'report_deploy' - build: http://larsesmbp:8080/job/report_deploy/274/console after: 0.831s/3.774s
Build started: 'prepare_tests' - http://larsesmbp:8080/job/prepare_tests/274/console
job: 'prepare_tests' stopped running
job: 'prepare_tests' Status IDLE - build: #274
SUCCESS: 'prepare_tests' - build: http://larsesmbp:8080/job/prepare_tests/274/console after: 0.835s/3.855s
Flow SUCCESS ('report_deploy', 'prepare_tests') after: 0.913s/3.855s

Flow Invocation (1/1,1/1): ('test_x', 'test_y')

Job Invocation (1/1,1/1): http://larsesmbp:8080/job/test_x
job: 'test_x' Status QUEUED

Job Invocation (1/1,1/1): http://larsesmbp:8080/job/test_y
job: 'test_y' Status QUEUED
Build started: 'test_x' - http://larsesmbp:8080/job/test_x/274/console
job: 'test_x' stopped running
job: 'test_x' Status IDLE - build: #274
SUCCESS: 'test_x' - build: http://larsesmbp:8080/job/test_x/274/console after: 0.833s/5.277s
Build started: 'test_y' - http://larsesmbp:8080/job/test_y/274/console
job: 'test_y' stopped running
job: 'test_y' Status IDLE - build: #274
SUCCESS: 'test_y' - build: http://larsesmbp:8080/job/test_y/274/console after: 0.830s/5.358s
Flow SUCCESS ('test_x', 'test_y') after: 0.914s/5.358s

Job Invocation (1/1,1/1): http://larsesmbp:8080/job/report
Build started: 'report' - http://larsesmbp:8080/job/report/274/console
job: 'report' stopped running
job: 'report' Status IDLE - build: #274
SUCCESS: 'report' - build: http://larsesmbp:8080/job/report/274/console after: 0.756s/6.708s
Flow SUCCESS ['prepare', 'deploy_component', ('report_deploy', 'prepare_tests'), ('test_x', 'test_y'), 'report'] after: 6.624s/6.708s

--- Final status ---
serial flow: [
   job: 'prepare' SUCCESS
   job: 'deploy_component' SUCCESS
   parallel flow: (
      job: 'report_deploy' SUCCESS
      job: 'prepare_tests' SUCCESS
   )

   parallel flow: (
      job: 'test_x' SUCCESS
      job: 'test_y' SUCCESS
   )

   job: 'report' SUCCESS
]

Finished: SUCCESS

See demo/... for some usage examples. The demo jobs can be loaded by running tests, see below.

Installation

A recent Jenkins is required.

  1. Install python-devel (required by the psutil dependency of the script_api) E.g on fedora:

    sudo dnf install python-devel
  2. Install jenkinsflow:

    pip install --user --upgrade jenkinsflow
  3. Read the file demo/demo_security.py if you have security enabled your Jenkins.

All set! You can now create jobs which will a use this library to control the running of other jobs.

Test

  1. The test can be run using nox:

    pip install nox

    There are three different apis for running the unit tests, jenkins, script and mock. The mock and script api test do not require any Jenkins setup. The mock api ony tests the flow logic, it does not exeute any jobs. See the ‘–api’ option below.

  2. Important Jenkins setup and test preparation

    • Configure security

      Some of the tests requires security to be enabled. You need to create two users in Jenkins: Read the file demo/demo_security.py and create the user specified. Create a user called jenkinsflow_authtest1, password abcæøåÆØÅ. ( u’u00e6u00f8u00e5u00c6u00d8u00c5’ )

    • Set the number of executers

      Jenkins is default configured with only two executors on ‘built-in’ node. To avoid time-outs in the test cases this must be raised to at least 32. This is necessary because some of the test cases will execute a large amount of jobs in parallel.

    • Change the ‘Quite period’

      Jenkins is default configured with a ‘Quiet period’ of 5 seconds. To avoid time-outs in the test cases this must be set to 0.

    • Set Jenkins URL

      Jenkins: Manage Jenkins -> Configure System -> Jenkins Location -> Jenkins URL

      The URL should not use localhost.

    • Install “Pipeline: Stage” plugin.

    Your Jenkins needs to be on the host where you are running the test. If it is not, you will need to make jenkinsflow available to Jenkins. See test/framework/tmp_install.sh

  3. Run the tests using nox:

    JENKINS_URL=<your Jenkins> nox --mock-speedup=100 --direct-url <non proxied URL different from JENKINS_URL>

    The test script will run the test suite with mocked jenkins_api, script_api and jenkins_api in parallel. The mocked api is a very fast test of the flow logic. Mocked tests and script-api tests do not require Jenkins. The test jobs are automatically created in Jenkins.

    It is possible to select a subset of the apis using the --api option.

    The value given to --mock-speedup is the time speedup for the mocked tests. If you have a reasonably fast computer, try 2000. If you get FlowTimeoutException try a lower value. If you get <job> is expected to be running, but state is IDLE try a lower value.

    By default tests are run in parallel using xdist and jobs are not deleted (but will be updated) before each run. You should have 32 executors or more for this, the CPU/disk load will be small, as the test jobs don’t really do anything except sleep. To disable the use of xdist use --job-delete.

    All jobs created by the test script are prefixed with jenkinsflow_, so they can be easily removed.

    The test suite creates jobs called …_0flow. These jobs are not executed by the test suite, by you can run them to see what the flows look like in a Jenkins job. If your Jenkins is not secured, you must set username and password to ‘’ in demo_security.py, in order to be able to run all the …_0flow jobs.

Demos

  1. Run tests as described above to load jobs into Jenkins

  2. Demo scripts can be executed from command line:

    python ./demo/<demo>.py
  3. Demo scripts can be executed from the loaded ‘jenkinsflow_demo__<demo-name>__0flow’ Jenkins jobs. Jenkins needs to be able to find the scripts, executing nox creates a test installation.

Flow Graph Visualisation

To see a flow graph of the basic demo in your browser, execute:

python ./visual/server.py' --json-dir '/tmp/jenkinsflow-test/graphs/jenkinsflow_demo__basic

before running ./demo/basic.py

Open http://localhost:9090 in your browser.

The test suite also puts some other graphs in subdirectories under /tmp/jenkinsflow-test/graphs. The visual feature is still experimental and does not yet show live info about the running flow/jobs.

If you run …0flow jobs that generate graphs from Jenkins the json graph file will be put in the workspace.

Documentation

Run nox to build documentation:

nox -s docs

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jenkinsflow-7.0.6.tar.gz (128.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jenkinsflow-7.0.6-py3-none-any.whl (43.7 kB view details)

Uploaded Python 3

File details

Details for the file jenkinsflow-7.0.6.tar.gz.

File metadata

  • Download URL: jenkinsflow-7.0.6.tar.gz
  • Upload date:
  • Size: 128.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.11

File hashes

Hashes for jenkinsflow-7.0.6.tar.gz
Algorithm Hash digest
SHA256 75634ce3576811583cb2d5d17721fd1f418405342cd10fe511747d1e6a9daecb
MD5 44d38499f1d17044a4ac6eae7ff8486a
BLAKE2b-256 068ac646952df2ccbb1dac96ba6c539490f197b93e72f5fd9bb6e67f5a44b495

See more details on using hashes here.

File details

Details for the file jenkinsflow-7.0.6-py3-none-any.whl.

File metadata

  • Download URL: jenkinsflow-7.0.6-py3-none-any.whl
  • Upload date:
  • Size: 43.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.11

File hashes

Hashes for jenkinsflow-7.0.6-py3-none-any.whl
Algorithm Hash digest
SHA256 4d4d8172c44cd7824f02717315fe1897022abb907212c554fc2d53e6861491ba
MD5 a5ba130f3603040020a7669ceba8c7d3
BLAKE2b-256 59ce77b50903e226b328ba4469d9a288ba41de1db5f703e954ff9707f5365ed7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page