> For the complete documentation index, see [llms.txt](https://docs.dogq.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.dogq.io/documentation/integrations/ci-cd.md).

# CI/CD

Today, CI/CD is one of the best practices development teams use to keep their production pipelines efficient. Automating build, test, and deployment processes helps save valuable time that can be used to focus more on development and innovation rather than manual, error-prone tasks.&#x20;

Using DogQ API you can execute your test suites and receive back the results as well as parameterize your tests by setting up variables.&#x20;

### Executing tests externally

To trigger an external execution of a Project you need to send a POST request to our API and provide the Project token associated with that Project.&#x20;

{% hint style="success" %}
API endpoint: `"https://dogq.io/projects/external_execute"`
{% endhint %}

To get to the Project Settings, go inside your Project and click on the gear button <img src="/files/SqXizfIQij4rvBUHROtn" alt="" data-size="line"> next to its name. **Token** is at the bottom of the general tab.&#x20;

<figure><img src="/files/mCVIU2P9pBc2YfGrix4f" alt=""><figcaption><p>The buttons next to the token are for copying and shuffling the token value.</p></figcaption></figure>

Here's an example POST request:

{% tabs %}
{% tab title="cURL" %}

```
curl --location --request POST "https://dogq.io/projects/external_execute" --header "TOKEN: your_token"
```

{% endtab %}

{% tab title="JS + Axios" %}

```javascript
const axios = require('axios');

const url = "https://dogq.io/projects/external_execute";
const token = 'your_token';

axios.post(url, {}, {
    headers: {
        'TOKEN': token,
        'Content-Type': 'application/x-www-form-urlencoded',
        'Accept': 'application/json'
    }
})
.then(response => {
    console.log(response.data);
})
.catch(error => {
    console.log(error.message)
})
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

url = "https://dogq.io/projects/external_execute"
headers = {
    "TOKEN": "your_token"
}

response = requests.post(url, headers=headers)

print(response.text)
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
$url = "https://dogq.io/projects/external_execute";
$token = "your_token";

$options = [
    'http' => [
        'header' => "TOKEN: $token\r\n" .
                    "Content-Type: application/x-www-form-urlencoded\r\n",
                    "Accept: application/json",
        'method' => 'POST',
        'content' => http_build_query([]),
    ],
];

$context  = stream_context_create($options);
$response = file_get_contents($url, false, $context);
?>
```

{% endtab %}
{% endtabs %}

If successful, it should return the following response `{"status":"ok"}`

Token triggers the execution of **the whole Project, i.e. all active Modules and Scenarios will be executed**. Project token can be changed. Clicking on the respective button next to the token will randomly generate a new one.

All such test executions will be available on the [**Executions**](https://dogq.io/executions) page and have an **External api call** status in the "Created by" column.&#x20;

### Receiving back the execution results

Also in the Project Settings <img src="/files/SqXizfIQij4rvBUHROtn" alt="" data-size="line"> inside Notifications there's a field for a Webhook Link. Here you can specify a URL of an open endpoint for DogQ to send POST requests to.

<figure><img src="/files/vSLdN2CqwN8NmAcmEWmO" alt="" width="563"><figcaption></figcaption></figure>

The payload this webhook carries is an object with test results using which you can further automate your pipeline, e.g., if there are no failed test runs -> deploy to production.

<figure><img src="/files/mIAIllYbqm5NxNVtnMmJ" alt=""><figcaption><p>This is what the webhook payload looks like.</p></figcaption></figure>

#### The key-value pairs are:

1. **project\_id** : the ID of your project
2. **project\_name** : your project name
3. **status** : "**passed**" (if all tests passed successfully) or "**failed**" (if at least one test failed)&#x20;
4. **full\_test\_run\_count** : the overall number tests executed
5. **test\_runs\_passed\_count** : the number of tests that passed successfully
6. **test\_runs\_failed\_count** : the number of tests that have failed during the execution
7. **test\_runs\_url** : a URL to Executions page with the results

{% hint style="info" %}
The Webhook Link feature, like other notifications, only works for **scheduled** and **externally executed** runs. Once you've provided the link DogQ will attempt to send a webhook every time the Project is executed via schedule or externally. If you would like DogQ to stop, remove the link from the settings.
{% endhint %}

### Setting variables via API endpoint

If a test you're running via API call has variables in it, you can change the test behavior by setting the variables in the body of your POST request.&#x20;

```
variables[name]=value
```

{% hint style="info" %}
Ensure that the variables you define in your API request **match the names** used in your test scripts and use **"variables"** as it's a mandatory key word.
{% endhint %}

In the following example we're defining a variable with the name "var\_url" and giving it a value of "staging-url.io":&#x20;

{% tabs %}
{% tab title="cURL" %}

```
curl --location --request POST "https://dogq.io/projects/external_execute"
--header "TOKEN: your_token"
--data-urlencode "variables[var_url]=staging-url.io"
```

{% endtab %}

{% tab title="JS + Axios" %}

```javascript
const axios = require('axios');

const url = 'https://dogq.io/projects/external_execute';
const token = 'your_token';
const data = new URLSearchParams();
data.append('variables[var_url]', 'staging-url.io');

axios.post(url, data, {
    headers: {
        'TOKEN': token,
        'Content-Type': 'application/x-www-form-urlencoded',
        'Accept': 'application/json'
    }
})
.then(response => {
    console.log(response.data);
})
.catch(error => {
    console.log(error.message)
})
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

url = "https://dogq.io/projects/external_execute"
headers = {
    "TOKEN": "your_token"
}
data = {
    "variables[var_url]": "staging-url.io"
}

response = requests.post(url, headers=headers, data=data)

print(response.text)
```

{% endtab %}

{% tab title="PHP" %}

<pre class="language-php"><code class="lang-php">&#x3C;?php
$url = "https://dogq.io/projects/external_execute";
$token = "your_token";

$data = [
    'variables[var_url]' => 'staging-url.io'
];

$options = [
    'http' => [
        'header'  => "TOKEN: $token\r\n" .
                     "Content-Type: application/x-www-form-urlencoded\r\n",
                     "Accept: application/json",
        'method'  => 'POST',
        'content' => http_build_query($data),
    ],
];

$context  = stream_context_create($options);
<strong>$response = file_get_contents($url, false, $context);
</strong>?>
</code></pre>

{% endtab %}
{% endtabs %}

And a Scenario in the Project we're executing via API request could look like this:

<figure><img src="/files/gqhtGCcJVcr6ppCrt0IT" alt=""><figcaption><p>This is an example Scenario for demo purposes</p></figcaption></figure>

#### Setting multiple variables

In case you need to set more than one variable for your tests, you can do so by listing them one by one, i.e. by adding multiple parameters.&#x20;

For example:

`curl --location --request POST "https://dogq.io/projects/external_execute"`\
`--header "TOKEN: UXfEcQhKDn6dCXbt8YwxkJkz"`\
`--data-urlencode "variables[url]=myapp-staging-url.io"`\
`--data-urlencode "variables[email]=qa_tester_email@gmail.com"`\
`--data-urlencode "variables[password]=12345"`

#### Using multiple datasets

You can go even further than that and batch execute your Project with multiple datasets by adding **{contexts}** object to the body of your API request. Each test in the Project you're executing this way will be run as many times as there are datasets in the request payload.

Here's the same example from before, but using **{contexts}** and with several datasets.

{% tabs %}
{% tab title="JS + Axios" %}

```javascript
const axios = require('axios');

const url = 'https://dogq.io/projects/external_execute';
const token = 'your_token';

const data = {
    contexts: [
        {
            id: 1,
            url: "myapp-staging-url.io",
            email: "qa_tester_email@gmail.com",
            password: "12345"
        },
        {
            id: 2,
            url: "myapp-staging-url.io",
            email: "johnsmith+qa-email@gmail.com",
            password: "0404qwerty"
        },
        {
            id: 3,
            url: "myapp-prod-url.io",
            email: "qa_admin_email@gmail.com",
            password: "superadminpass"
        }
    ]
};

axios.post(url, data, {
    headers: {
        'TOKEN': token,
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    }
})
.then(response => {
    console.log(response.data);
})
.catch(error => {
    console.error(error.message);
});
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

url = "https://dogq.io/projects/external_execute"
headers = {
    "TOKEN": "your_token"
}
data = {
    "contexts": [
        {
            "id": 1,
            "url": "myapp-staging-url.io",
            "email": "qa_tester_email@gmail.com",
            "password": "12345"
        },
        {
            "id": 2,
            "url": "myapp-staging-url.io",
            "email": "johnsmith+qa-email@gmail.com",
            "password": "0404qwerty"
        },
        {
            "id": 3,
            "url": "myapp-prod-url.io",
            "email": "qa_admin_email@gmail.com",
            "password": "superadminpass"
        }
    ]
}

response = requests.post(url, headers=headers, json=data)

print(response.text)
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

$url = "https://dogq.io/projects/external_execute";
$token = "your_token";

$data = [
    'contexts' => [
        [
            'id' => 1,
            'url' => 'myapp-staging-url.io',
            'email' => 'qa_tester_email@gmail.com',
            'password' => '12345'
        ],
        [
            'id' => 2,
            'url' => 'myapp-staging-url.io',
            'email' => 'johnsmith+qa-email@gmail.com',
            'password' => '0404qwerty'
        ],
        [
            'id' => 3,
            'url' => 'myapp-prod-url.io',
            'email' => 'qa_admin_email@gmail.com',
            'password' => 'superadminpass'
        ]
    ]
];

$options = [
    'http' => [
        'header'  => "TOKEN: $token\r\n" .
                    "Content-Type: application/json\r\n" .
                    "Accept: application/json",
        'method'  => 'POST',
        'content' => json_encode($data),
    ],
];

$context  = stream_context_create($options);
$response = file_get_contents($url, false, $context);

echo $response;
?>
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Be careful when using {contexts} with large projects, as the total amount of test runs may quickly skyrocket even with a moderate number of datasets (**total = tests \* datasets**).
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://docs.dogq.io/documentation/integrations/ci-cd.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
