# Handling Unexpected Closure of Testing Executions

In case, your **testing execution is aborted** because of any failure, it is **important to close all the executions left open** because the Testing framework was not able to perform a graceful shutdown for example.

Below is a sample code that checks the list of remaining open executions and closes them one by one as part of a post-build section in a Jenkins pipeline script used to execute the tests.

Details on the *Get Executions Status List API* can be found in our dedicated documentation page [Test Sessions API (a.k.a TIA API)](/knowledgebase/setup-and-configuration/integrations/rest-apis/test-sessions-api-a.k.a-tia-api.md#get-executions-status-list).\
For example, you have the ability to query the list of executions with a filter based on the Test Stage name or the LabId in addition to the execution status “created”.

{% tabs fullWidth="true" %}
{% tab title="GitHub Actions/Python" %}
GitHub Action Yaml executing the Sealights Cleanup step on UIT failure (or cancellation)

{% code overflow="wrap" lineNumbers="true" fullWidth="true" %}

```yaml
  unit-tests:
    needs: build
    runs-on: ubuntu-latest
    env:
      SEALIGHTS_TEST_STAGE: "Unit Tests"
    steps:
      ## ...
      - name: Run Unit Tests
        id: unittest
        env:
          SEALIGHTS_TEST_STAGE: "Unit Tests"
        continue-on-error: true
        run: ##Unit test command
      - name: Sealights - Cleanup Open Executions
        if: (cancelled() || steps.unittest.outcome == 'failure') && env.SEALIGHTS_ENABLED == 'true'
        run: |
          pip install requests
          python -u scripts/sealights-utils.py --cleanup \
            "${{ needs.build.outputs.build_session_id }}" \
            "${{ secrets.SL_AGENT_TOKEN }}" \
            "${{ env.SEALIGHTS_TEST_STAGE }}"
```

{% endcode %}

Python script

{% code overflow="wrap" lineNumbers="true" fullWidth="true" %}

```python
def cleanup_open_executions(build_session_id, sealights_agent_token, test_stage=None):
    url = f"{SEALIGHTS_BASE_URL}/v1/executions"
    headers = {
        "Authorization": f"Bearer {sealights_agent_token}",
        "Content-Type": "application/json",
    }
    params = {"bsid": build_session_id, "status": "created"}
    if test_stage:
        params["testStage"] = test_stage
    print(f"[Sealights] Cleanup executions left open for build session {build_session_id} and test stage '{test_stage}'")

    try:
        response = requests.get(url, headers=headers, params=params, timeout=30)
        response.raise_for_status()
    except Exception as e:
        print(f"Failed to query executions: {e}")
        return 0

    data = response.json()
    execution_ids = [
        item["executionId"]
        for item in data.get("data", {}).get("list", [])
    ]
    print(f"Found {len(execution_ids)} open execution(s)")

    closed = 0
    for execution_id in execution_ids:
        delete_url = f"{SEALIGHTS_BASE_URL}/v1/test-sessions/{execution_id}"
        try:
            resp = requests.delete(delete_url, headers=headers, timeout=30)
            print(f"Closing test session {execution_id}: HTTP {resp.status_code}")
            closed += 1
        except Exception as e:
            print(f"Error closing session {execution_id}: {e}")

    return closed
```

{% endcode %}
{% endtab %}

{% tab title="Jenkins/Bash" %}
{% code overflow="wrap" lineNumbers="true" fullWidth="true" %}

```groovy
    post {
        aborted{
            echo '[Sealights] Cleanup executions left open.'
            withCredentials([string(credentialsId: 'sl.agent.token', variable: 'SL_TOKEN')]) {
                sh '''
                    set +x
                    SL_SESSION_IDs=(`curl -sX GET "https://$DOMAIN/sl-api/v1/executions?bsid=$BSID&status=created" \
                                              -H "Authorization: Bearer $SL_TOKEN" -H "Content-Type: application/json" \
                    						  | jq -r '.data.list | map(.executionId) | join(" ")'`)
                    #Optional: filter based on the Test Stage name and/or labId (especially relevant in case of parallel testing)
                    
                    echo "Found ${#SL_SESSION_IDs[@]} executions"
                    
                    for id in ${SL_SESSION_IDs[@]}
                    do 
                    	echo -n "Closing Test Session ID $id: "
                    	curl -isX DELETE "https://$DOMAIN/sl-api/v1/test-sessions/$id" \
                    	  -H "Authorization: Bearer $SL_TOKEN" -H "Content-Type: application/json" | grep HTTP
                    done
                '''
            }
        }
    }
```

{% endcode %}
{% endtab %}

{% tab title="ADO/Powershell" %}
{% code fullWidth="true" %}

```yaml
steps:
- task: Bash@3
  name: RunTests
  displayName: "Run my tests"
  inputs:
    targetType: inline
    script: |
      ./run-tests.sh
# ========================================================================
# 2. Sealights cleanup ONLY if RunTests failed or cancelled
# ========================================================================
- task: PowerShell@2
  displayName: "Sealights cleanup for this specific task (PowerShell)"
  condition: or(failed('RunTests'), canceled('RunTests'))
  env:
    SL_TOKEN: $(sl.agent.token)
    DOMAIN: $(DOMAIN)
    BSID: $(BSID)
  inputs:
    targetType: inline
    script: |
      Write-Host "[Sealights] Cleanup executions left open."

      # Build API URL
      $url = "https://$env:DOMAIN/sl-api/v1/executions?bsid=$env:BSID&status=created"

      # Prepare headers
      $headers = @{
        "Authorization" = "Bearer $env:SL_TOKEN"
        "Content-Type"  = "application/json"
      }

      # Get execution IDs
      try {
        $response = Invoke-RestMethod -Method GET -Uri $url -Headers $headers -ErrorAction Stop
        $sessionIds = $response.data.list | ForEach-Object { $_.executionId }
      }
      catch {
        Write-Host "Failed to fetch execution list: $($_.Exception.Message)"
        exit 0   # do not fail pipeline
      }

      if (!$sessionIds) {
        Write-Host "No executions found."
        exit 0
      }

      Write-Host "Found $($sessionIds.Count) executions"

      # Close each Sealights test session
      foreach ($id in $sessionIds) {
        Write-Host ("Closing Test Session ID {0}: " -f $id) -NoNewline

        $deleteUrl = "https://$env:DOMAIN/sl-api/v1/test-sessions/$id"

        try {
          $deleteResponse = Invoke-RestMethod -Method DELETE -Uri $deleteUrl -Headers $headers -ErrorAction Stop
          Write-Host "OK"
        }
        catch {
          # Still print HTTP response if possible
          Write-Host "Failed: $($_.Exception.Message)"
        }
      }
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.sealights.io/knowledgebase/setup-and-configuration/troubleshooting-faq/general/handling-unexpected-closure-of-testing-executions.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
