{"library":"shrub-py","title":"Shrub.py","description":"Shrub.py is a Python library designed for programmatically building Evergreen project configurations. It allows users to define complex CI/CD task graphs and build variants using Python objects, which can then be serialized into the JSON format required by Evergreen. The library is actively maintained, with its latest version being 3.10.0, released in April 2025.","language":"python","status":"active","last_verified":"Thu May 21","install":{"commands":["pip install shrub-py"],"cli":null},"imports":["from shrub.v3.evg_task import EvgTask","from shrub.v3.shrub_service import ShrubService"],"auth":{"required":false,"env_vars":[]},"quickstart":{"code":"from shrub.v3.evg_task import EvgTask, EvgTaskDependency\nfrom shrub.v3.evg_build_variant import BuildVariant, DisplayTask\nfrom shrub.v3.evg_command import FunctionCall\nfrom shrub.v3.evg_project import EvgProject\nfrom shrub.v3.shrub_service import ShrubService\nimport json\n\nn_tasks = 3\n\ndef define_task(index):\n    name = f\"my_test_task_{index}\"\n    return EvgTask(\n        name=name,\n        commands=[\n            FunctionCall(func=\"do_setup_function\"),\n            FunctionCall(\n                func=\"run_test_script\",\n                vars={\n                    \"param1\": f\"value_{index}\",\n                    \"param2\": \"static_value\"\n                }\n            ),\n            FunctionCall(func=\"do_teardown_function\")\n        ],\n        depends_on=[EvgTaskDependency(name=\"compile_job\")]\n    )\n\ntasks = [define_task(i) for i in range(n_tasks)]\ndisplay_task = DisplayTask(\n    name=\"full_test_suite\",\n    execution_tasks=[t.name for t in tasks]\n)\n\nvariant = BuildVariant(\n    name=\"linux-build\",\n    tasks=[],\n    display_tasks=[display_task]\n)\n\nproject = EvgProject(buildvariants=[variant], tasks=tasks)\n\n# Generate the Evergreen JSON configuration\nevergreen_config_json = ShrubService.generate_json(project)\n\nprint(json.dumps(evergreen_config_json, indent=4))\n","lang":"python","description":"This quickstart demonstrates how to define an Evergreen project configuration using shrub.py. It creates multiple parallel tasks, groups them under a display task, associates them with a build variant, and then generates the corresponding Evergreen JSON output. This example illustrates task definition, command execution with variables, and task dependencies.","tag":null,"tag_description":null,"last_tested":null,"results":[]},"compatibility":{"tag":null,"tag_description":null,"last_tested":"2026-05-21","installed_version":"3.10.0","pypi_latest":"3.10.0","is_stale":false,"summary":{"python_range":"3.10–3.9","success_rate":100,"avg_install_s":3.7,"avg_import_s":0.52,"wheel_type":"wheel"},"results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"shrub-py","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.42,"mem_mb":11.1,"disk_size":"31.3M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"shrub-py","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.48,"mem_mb":11.1,"disk_size":"31.3M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"shrub-py","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":4.1,"import_time_s":0.31,"mem_mb":11.1,"disk_size":"32M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"shrub-py","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.32,"mem_mb":11.1,"disk_size":"32M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"shrub-py","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.62,"mem_mb":12.4,"disk_size":"34.4M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"shrub-py","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.74,"mem_mb":12.4,"disk_size":"34.4M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"shrub-py","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":3.5,"import_time_s":0.57,"mem_mb":12.4,"disk_size":"35M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"shrub-py","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.6,"mem_mb":12.4,"disk_size":"35M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"shrub-py","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.78,"mem_mb":12.3,"disk_size":"26.1M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"shrub-py","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.88,"mem_mb":12.3,"disk_size":"26.1M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"shrub-py","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":2.9,"import_time_s":0.78,"mem_mb":12.3,"disk_size":"26M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"shrub-py","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.85,"mem_mb":12.3,"disk_size":"26M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"shrub-py","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.4,"mem_mb":8.7,"disk_size":"25.9M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"shrub-py","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.43,"mem_mb":8.7,"disk_size":"25.7M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"shrub-py","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":3,"import_time_s":0.4,"mem_mb":8.7,"disk_size":"26M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"shrub-py","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.41,"mem_mb":8.7,"disk_size":"26M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"shrub-py","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.34,"mem_mb":10.3,"disk_size":"30.9M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"shrub-py","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.4,"mem_mb":10.3,"disk_size":"30.9M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"shrub-py","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":4.8,"import_time_s":0.35,"mem_mb":10.3,"disk_size":"31M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"shrub-py","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.39,"mem_mb":10.3,"disk_size":"31M"}]}}