Skip to content

Add --rp-purge/-X option to remove previous test results before execution#348

Merged
kkaarreell merged 2 commits into
mainfrom
ks_rm_suite
Apr 17, 2026
Merged

Add --rp-purge/-X option to remove previous test results before execution#348
kkaarreell merged 2 commits into
mainfrom
ks_rm_suite

Conversation

@kkaarreell

@kkaarreell kkaarreell commented Apr 16, 2026

Copy link
Copy Markdown
Collaborator

This commit introduces a new --rp-purge/-X option for the execute command that removes previous test results from ReportPortal launches before executing new Testing Farm requests. This feature is useful when restarting specific TF requests to avoid duplicate test results in the same launch.

Key changes:

  • Add --rp-purge/-X option to execute command with per-request removal
  • Implement delete_request() method in ReportPortal service
  • Add remove_test_suite_by_tag() to remove test suites by newa_batch ID
  • Update workers to load previous execute_job for both --continue and --force
  • Support suite removal with --restart-request, --restart-result, and --force
  • Fix ReportPortal API filtering using filter.has.compositeAttribute syntax
  • Update README with comprehensive documentation and examples

Implementation details:

  • Test results are identified using newa_batch tag (unique per execution)
  • Only removes results for requests being executed, not entire launch
  • Works per-worker to ensure only scheduled requests are cleaned up
  • Launch UUID is converted to numeric ID for API compatibility
  • Loads previous execute_job regardless of --continue flag for batch_id access

🤖 Generated with Claude Code

Summary by Sourcery

Add support for purging previous ReportPortal test results before executing Testing Farm requests and document the new behavior.

New Features:

  • Introduce a --rp-purge/-X option for the execute command to remove previous test results from ReportPortal launches per request.
  • Add ReportPortal service capabilities to delete resources and remove test suites based on a newa_batch tag within a launch.

Enhancements:

  • Ensure workers always load the previous execute job when available to support restart and ReportPortal purge workflows.
  • Improve handling of existing execute jobs by asserting their presence when reusing requests.

Documentation:

  • Document the --rp-purge/-X option in the README with usage details, behavior description, and example commands.

@kkaarreell kkaarreell self-assigned this Apr 16, 2026
@sourcery-ai

sourcery-ai Bot commented Apr 16, 2026

Copy link
Copy Markdown

Reviewer's Guide

Implements a new --rp-purge/-X execute option that, when enabled, loads prior execute job metadata to identify per-request ReportPortal test suites via a newa_batch tag and removes them through new ReportPortal service delete/search helpers before re-submitting Testing Farm requests, plus updates CLI context wiring and README docs.

Sequence diagram for execute with --rp-purge purge flow

sequenceDiagram
    actor User
    participant CLI as cmd_execute
    participant Ctx as CLIContext
    participant Worker as tf_worker
    participant RPInit as initialize_rp_connection
    participant RP as ReportPortalService
    participant TF as TestingFarm

    User->>CLI: newa execute --rp-purge ...
    CLI->>Ctx: set rp_purge = True
    CLI->>Worker: start tf_worker(ctx, schedule_job)

    Worker->>Worker: compute execute_job_file path
    Worker->>Worker: ExecuteJob.from_yaml_file(...)
    Worker->>Worker: decide start_new_request

    alt start_new_request and ctx.rp_purge and reportportal configured
        Worker->>Worker: read launch_uuid from schedule_job.request.reportportal
        Worker->>Worker: read newa_batch_id from execute_job.execution.batch_id
        Worker->>RPInit: initialize_rp_connection(ctx)
        RPInit-->>Worker: ReportPortalService instance
        Worker->>RP: remove_test_suite_by_tag(launch_uuid, newa_batch_id, logger)
        RP->>RP: get_launch_info(launch_uuid)
        RP-->>RP: launch_id
        RP->>RP: get_request(/item, filter by launchId, type=suite, newa_batch)
        RP-->>RP: items content
        loop for each matching suite
            RP->>RP: delete_request(/item/{item_id})
        end
        RP-->>Worker: removed = True/False
    end

    Worker->>Request: initiate_tf_request(ctx)
    Request->>TF: create TF request
    TF-->>Worker: TFRequest(uuid)
    Worker-->>Ctx: save_execute_job(execute_job)
Loading

Class diagram for new ReportPortal purge support

classDiagram
    class CLIContext {
        bool continue_execution
        bool no_wait
        bool rp_purge
        list~str~ restart_request
        list~RequestResult~ restart_result
    }

    class ReportPortalService {
        url
        project
        token
        post_request(path: str, data: dict, version: int) dict
        get_request(path: str, params: dict, version: int) dict
        get_launch_info(launch_uuid: str) dict
        delete_request(path: str, version: int) bool
        remove_test_suite_by_tag(launch_uuid: str, newa_batch_id: str, logger: logging.Logger) bool
    }

    class ExecuteJob {
        +from_yaml_file(path: Path) ExecuteJob
        execution: Execution
        request: Request
    }

    class Execution {
        result: RequestResult
        request_api
        request_uuid: str
        batch_id: str
    }

    class ScheduleJob {
        request: Request
    }

    class Request {
        id: str
        reportportal: dict
        initiate_tf_request(ctx: CLIContext) TFRequest
    }

    class TFRequest {
        api
        uuid: str
    }

    CLIContext "1" --> "many" ScheduleJob : used_by
    ScheduleJob "1" --> "1" Request : contains
    ExecuteJob "1" --> "1" Execution : has
    ExecuteJob "1" --> "1" Request : has
    Execution "1" --> "1" RequestResult : uses
    Request "1" --> "1" TFRequest : creates
    CLIContext "1" --> "1" ReportPortalService : initializes
    ReportPortalService "1" --> "many" TFRequest : reports_results_for
Loading

File-Level Changes

Change Details Files
Add ReportPortal helpers to delete test suites by newa_batch tag within a launch
  • Introduce generic delete_request() helper that issues authenticated DELETEs against the ReportPortal API
  • Implement remove_test_suite_by_tag() to look up the numeric launch ID, search suite items by composite attribute newa_batch, and delete matching items while logging outcomes
  • Fix API filtering by using filter.has.compositeAttribute for attribute-based search of test items
newa/services/reportportal_service.py
Purge old ReportPortal suites per request when executing or restarting jobs
  • Always attempt to load the corresponding execute_job YAML for a schedule file so prior execution metadata is available even without --continue
  • When starting a new request and --rp-purge is set, derive launch_uuid and batch_id and call remove_test_suite_by_tag() before initiating the Testing Farm request
  • Document the assumption that execute_job is present when reusing existing requests via assertions
newa/cli/workers.py
Expose the --rp-purge/-X CLI flag and propagate it through execution context
  • Add --rp-purge/-X option to the execute command and plumb its value into CLIContext
  • Extend CLIContext with an rp_purge boolean used by workers to decide whether to clean ReportPortal suites before execution
newa/cli/commands/execute_cmd.py
newa/models/settings.py
Document rp-purge behavior and usage scenarios
  • Expand README execute section with a dedicated --rp-purge option description, behavior notes, and usage examples in combination with restart and force flags
README.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 3 issues, and left some high level feedback:

  • In remove_test_suite_by_tag, the /item lookup appears to assume a single page of results; if ReportPortal paginates this endpoint you may need to handle pagination to ensure all suites with the given newa_batch tag are removed.
  • The current implementation of remove_test_suite_by_tag aborts and returns False on the first failed delete; consider deleting all matching items and aggregating/logging failures so that one problematic suite does not prevent others from being purged.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `remove_test_suite_by_tag`, the `/item` lookup appears to assume a single page of results; if ReportPortal paginates this endpoint you may need to handle pagination to ensure all suites with the given `newa_batch` tag are removed.
- The current implementation of `remove_test_suite_by_tag` aborts and returns `False` on the first failed delete; consider deleting all matching items and aggregating/logging failures so that one problematic suite does not prevent others from being purged.

## Individual Comments

### Comment 1
<location path="newa/services/reportportal_service.py" line_range="218-227" />
<code_context>
+            'filter.has.compositeAttribute': f'newa_batch:{newa_batch_id}',
+            }
+
+        # Get test items matching the criteria
+        items = self.get_request('/item', params=params, version=1)
+
+        if not items or not items.get('content'):
+            if logger:
+                logger.debug(
+                    f'No test suite found with tag newa_batch={newa_batch_id} '
+                    f'in launch {launch_uuid}')
+            return False
+
+        # Delete each matching suite
+        for item in items['content']:
+            item_id = item['id']
+            if logger:
</code_context>
<issue_to_address>
**issue:** ReportPortal item retrieval appears to handle only a single page of results.

This request to `/item` appears to process only the first page of `items['content']`. If the ReportPortal API paginates this endpoint, additional suites with the `newa_batch` tag will be skipped. Please confirm whether the response includes pagination metadata (e.g., `page`, `size`, `totalPages`) and, if so, iterate through all pages when `rp_purge` is used.
</issue_to_address>

### Comment 2
<location path="newa/cli/workers.py" line_range="45-54" />
<code_context>
-        if execute_job_file.exists():
-            execute_job = ExecuteJob.from_yaml_file(execute_job_file)
+    execute_job = None
+    # Try to load former execute_job in case --continue or --rp-purge will need it
+    parent = schedule_file.parent
+    name = schedule_file.name
+    from newa import EXECUTE_FILE_PREFIX, SCHEDULE_FILE_PREFIX
+    execute_job_file = Path(
+        os.path.join(
+            parent,
+            name.replace(
+                SCHEDULE_FILE_PREFIX,
+                EXECUTE_FILE_PREFIX,
+                1)))
+    if execute_job_file.exists():
+        execute_job = ExecuteJob.from_yaml_file(execute_job_file)
+        if ctx.continue_execution:
</code_context>
<issue_to_address>
**suggestion (performance):** Eagerly loading execute_job for every run may be unnecessary overhead.

This now loads `execute_job` whenever the file exists, even when neither `--continue` nor `--rp-purge` is used. For many or large jobs, that extra I/O and deserialization could be costly. Consider only loading it when `ctx.continue_execution` or `ctx.rp_purge` is true.

Suggested implementation:

```python
    execute_job = None
    # Compute the path to a former execute_job; only load it if actually needed
    parent = schedule_file.parent
    name = schedule_file.name
    from newa import EXECUTE_FILE_PREFIX, SCHEDULE_FILE_PREFIX
    execute_job_file = Path(
        os.path.join(
            parent,
            name.replace(
                SCHEDULE_FILE_PREFIX,
                EXECUTE_FILE_PREFIX,
                1)))
    if ctx.continue_execution or ctx.rp_purge:
        if execute_job_file.exists():
            execute_job = ExecuteJob.from_yaml_file(execute_job_file)

```

If there is logic immediately after the removed `if ctx.continue_execution:` (e.g. a block that assumes `execute_job` has been loaded), it may need to be re-indented or guarded to ensure it still only runs when `ctx.continue_execution` is true. Please adjust any such block to either:
- Nest it under `if ctx.continue_execution:` again (but without the load), or
- Use `if ctx.continue_execution and execute_job is not None:` depending on the intended behavior when the file is missing.
</issue_to_address>

### Comment 3
<location path="README.md" line_range="1544" />
<code_context>
 #### Option `--restart-result`, `-r`
 This option can be used to reschedule NEWA request that have ended with a particular result - `passed, failed, error`. For example, `--restart-result error`. Result can be either `passed`, `failed` or `error` where 'error' means that test execution hasn't been finished correctly. This option can be used multiple times. Implies `--continue`.

+#### Option `--rp-purge`, `-X`
</code_context>
<issue_to_address>
**issue (typo):** Use plural "requests" to match the verb "have" in this sentence.

Change "NEWA request that have" to "NEWA requests that have" for correct subject–verb agreement.

```suggestion
This option can be used to reschedule NEWA requests that have ended with a particular result - `passed, failed, error`. For example, `--restart-result error`. Result can be either `passed`, `failed` or `error` where 'error' means that test execution hasn't been finished correctly. This option can be used multiple times. Implies `--continue`.
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread newa/services/reportportal_service.py Outdated
Comment thread newa/cli/workers.py Outdated
Comment thread README.md Outdated
…tion

This commit introduces a new --rp-purge/-X option for the execute command
that removes previous test results from ReportPortal launches before
executing new Testing Farm requests. This feature is useful when restarting
specific TF requests to avoid duplicate test results in the same launch.

Key changes:
- Add --rp-purge/-X option to execute command with per-request removal
- Implement delete_request() method in ReportPortal service
- Add remove_test_suite_by_tag() to remove test suites by newa_batch ID
- Update workers to load previous execute_job for both --continue and --force
- Support suite removal with --restart-request, --restart-result, and --force
- Fix ReportPortal API filtering using filter.has.compositeAttribute syntax
- Update README with comprehensive documentation and examples

Implementation details:
- Test results are identified using newa_batch tag (unique per execution)
- Only removes results for requests being executed, not entire launch
- Works per-worker to ensure only scheduled requests are cleaned up
- Launch UUID is converted to numeric ID for API compatibility
- Loads previous execute_job regardless of --continue flag for batch_id access

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Enhance the NEWA agent definition to incorporate the new --rp-purge/-X
option for ReportPortal result cleanup during test rescheduling.

The agent will now:
- Proactively ask users about removing previous test results when
  rescheduling tests with --restart-request, --restart-result, or --force
- Explain that --rp-purge only removes results for requests being
  re-executed, not the entire launch
- Only suggest this option during rescheduling operations, never for
  initial test runs
- Provide correct command syntax with examples

This makes the --rp-purge feature more discoverable and helps users
maintain clean ReportPortal launches when restarting tests.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@kkaarreell kkaarreell merged commit c6bec9f into main Apr 17, 2026
18 checks passed
@kkaarreell kkaarreell deleted the ks_rm_suite branch April 17, 2026 11:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant