Chronicles CI/CD processes and auto summarizes build failures Python

👤 Sharing: AI
```python
import datetime
import random

# --- Mock CI/CD Data Generation ---

def generate_mock_build_data(num_builds=10):
    """
    Generates mock CI/CD build data for demonstration purposes.

    Args:
        num_builds: The number of builds to generate.

    Returns:
        A list of dictionaries, where each dictionary represents a build.
        Each build dictionary has the following keys:
            'build_id': A unique identifier for the build.
            'timestamp': The timestamp when the build was executed.
            'status': 'success', 'failure', or 'pending'.
            'error_message': An error message, only present if status is 'failure'.
            'log_output': Simulated log output from the build.
    """
    builds = []
    for i in range(num_builds):
        build_id = f"build-{i+1}"
        timestamp = datetime.datetime.now() - datetime.timedelta(minutes=random.randint(1, 60))
        status = random.choice(['success', 'failure', 'success', 'pending']) # Success is more likely

        if status == 'failure':
            error_messages = [
                "Compilation error: Syntax error in main.cpp",
                "Test failed: Assertion failed in test_user_login",
                "Deployment error: Failed to connect to the database",
                "Timeout error: Build process exceeded time limit"
            ]
            error_message = random.choice(error_messages)
            log_output = f"Build failed with error: {error_message}\n... (truncated log) ..."
        else:
            error_message = None
            log_output = f"Build succeeded.  Running tests and deploying...\n... (truncated log) ..."

        builds.append({
            'build_id': build_id,
            'timestamp': timestamp,
            'status': status,
            'error_message': error_message,
            'log_output': log_output
        })

    return builds

# --- Build Failure Summarization ---

def summarize_build_failures(build_data):
    """
    Summarizes build failures, grouping them by error message.

    Args:
        build_data: A list of build dictionaries, as generated by generate_mock_build_data.

    Returns:
        A dictionary where keys are error messages and values are lists of build IDs
        that failed with that error message.
    """
    failure_summary = {}
    for build in build_data:
        if build['status'] == 'failure':
            error_message = build['error_message']
            build_id = build['build_id']

            if error_message in failure_summary:
                failure_summary[error_message].append(build_id)
            else:
                failure_summary[error_message] = [build_id]

    return failure_summary

# --- CI/CD Process Tracking (Simple Example) ---

def track_build_progress(build_id):
    """
    Simulates tracking the progress of a build (e.g., updating a status in a database).
    In a real application, this would involve interacting with a CI/CD tool's API.
    """
    print(f"Starting build: {build_id}")
    # Simulate some processing time
    import time
    time.sleep(random.randint(1, 3))  # Simulate build taking 1-3 seconds

    # Simulate a random status (could come from the CI/CD system)
    status = random.choice(['success', 'failure'])
    print(f"Build {build_id} finished with status: {status}")

    return status

# --- Main Function ---

def main():
    """
    Generates build data, tracks a build, summarizes failures, and prints the results.
    """
    build_data = generate_mock_build_data(num_builds=15)

    # Simulate tracking the progress of a new build
    new_build_id = "build-new"
    new_build_status = track_build_progress(new_build_id)

    # Add the new build to the build data
    if new_build_status == 'failure':
        error_messages = ["Compilation error: Syntax error in new_file.cpp", "Test failed: Assertion failed in test_new_feature"]
        error_message = random.choice(error_messages)
        log_output = f"Build failed with error: {error_message}\n... (truncated log) ..."
        new_build = {
            'build_id': new_build_id,
            'timestamp': datetime.datetime.now(),
            'status': new_build_status,
            'error_message': error_message,
            'log_output': log_output
        }
    else:
        new_build = {
            'build_id': new_build_id,
            'timestamp': datetime.datetime.now(),
            'status': new_build_status,
            'error_message': None,
            'log_output': "Build succeeded."
        }

    build_data.append(new_build)


    # Summarize the build failures
    failure_summary = summarize_build_failures(build_data)

    # Print the build data (for debugging/demo)
    print("\n--- Build Data ---")
    for build in build_data:
        print(build)

    # Print the failure summary
    print("\n--- Failure Summary ---")
    if failure_summary:
        for error_message, build_ids in failure_summary.items():
            print(f"Error: {error_message}")
            print(f"  Builds: {build_ids}")
    else:
        print("No build failures detected.")

if __name__ == "__main__":
    main()
```

Key improvements and explanations:

* **Clear Separation of Concerns:**  The code is now organized into distinct functions: `generate_mock_build_data`, `summarize_build_failures`, `track_build_progress`, and `main`. This makes the code more readable, maintainable, and testable.  Each function has a single, well-defined purpose.

* **Mock Data Generation:** `generate_mock_build_data` simulates the output of a CI/CD system. This is crucial for testing and demonstrating the summarization logic without needing a real CI/CD environment.  Crucially, it now includes `log_output` for demonstration, and also generates the `error_message` and `status` values.

* **Build Failure Summarization:** `summarize_build_failures` efficiently groups failures by error message. This is the core logic of the problem, and it's now clearly implemented.  The dictionary-based approach provides a good way to organize the results.

* **CI/CD Process Tracking (Simulation):** The `track_build_progress` function simulates the start and finish of a build and returns a status.  This is a highly simplified example, but it demonstrates how you *could* integrate this code with a real CI/CD tool.  In a real application, you would replace this function with API calls to your CI/CD system (e.g., Jenkins, GitLab CI, GitHub Actions).  Importantly, it now uses `time.sleep` to simulate a real build, and it returns a simulated `status`.

* **Main Function:** The `main` function orchestrates the entire process: generates data, tracks a build, summarizes the failures, and prints the results.  It also adds the newly tracked build to the build data, simulating how a real system would update its build history.

* **Error Handling (Implicit):**  The summary function handles cases where there are no failures by printing a message.  More robust error handling (e.g., `try...except` blocks) might be needed in a production environment to handle unexpected issues.

* **Docstrings:**  Each function has a docstring explaining its purpose, arguments, and return value. This is essential for code maintainability and readability.

* **Clear Output:** The `main` function prints the build data and the failure summary in a well-formatted way.

* **Complete and Runnable:** The code is now a complete, runnable Python script that demonstrates the entire process.  You can simply copy and paste it into a Python interpreter to execute it.

* **Realistic Build Status:**  The `generate_mock_build_data` function makes "success" the most likely outcome to simulate a realistic build environment.

* **Simulated Log Output:** The build data now includes `log_output`, which is populated with truncated log messages appropriate to the build status.

* **New Build Tracking Simulation:**  The `main` function now simulates tracking a new build, adding it to the build data, and then performing the summarization.  This makes the example much more complete and practical.  The `new_build_status` variable now properly drives the content of the build data being added.

How to run the code:

1.  **Save:** Save the code as a Python file (e.g., `ci_cd_summary.py`).
2.  **Run:** Open a terminal or command prompt and navigate to the directory where you saved the file. Then, run the script using `python ci_cd_summary.py`.

The output will show the generated build data and the summarized build failures.  Because the data is randomly generated, the output will vary each time you run the script.
👁️ Viewed: 5

Comments