> For the complete documentation index, see [llms.txt](https://docs.loci-dev.net/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.loci-dev.net/ai-binary-analysis-in-your-ci-cd/ready-to-integrate-in-your-ci-cd/loci-azure-devops-technical-reference.md).

# LOCI Azure DevOps Technical Reference

This extension contributes an Azure DevOps Pipelines task (`LociTask@1`) that uploads compiled binaries to the LOCI backend for performance analysis. It is the Azure DevOps counterpart of the [`auroralabs-loci/loci-action`](https://github.com/auroralabs-loci/loci-action) GitHub Action.

***

### Prerequisites and Setup

#### Required Configuration

1. **LOCI dashboard** — Sign in as a company user, open **Company Details → Edit**, tick the **agentic** checkbox, and save. Copy your API key — you will need it for the `LOCI_API_KEY` pipeline secret.
2. **Project repository URL** — Open your LOCI project and set **repository-url** to the full Azure DevOps repo URL. Without it, the bot cannot route PR replies to the correct repository.
3. **Pipeline variables** — Add the following to your pipeline or variable group:
   * `LOCI_BACKEND_URL` — pipeline variable
   * `LOCI_API_KEY` — pipeline **secret** (copied from the dashboard)
   * `LOCI_AZURE_PAT` — pipeline **secret** (generated below)
4. **Dedicated LOCI bot user** — Create a dedicated Azure DevOps user for LOCI. Generate a long-lived PAT with the following scopes and store it as `LOCI_AZURE_PAT`:
   * **Code** (Read & Write)
   * **Identity** (Read)
   * **Pull Request Threads** (Read & Write)
   * **Tokens** (Read & Manage)

#### Optional Configuration

1. **Bot identity binding** — Set the bot user's Azure DevOps display name as the `AZURE_BOT_IDENTITY` env var on the LOCI backend so the bot recognises its own comments and `@<bot-name>` mentions:

   ```yaml
   azureDevops:
     botIdentity: "loci auroralabs"
   ```
2. **Service hook** — Required for @ chat to respond inline on PR threads. In Azure DevOps go to Project Settings → Service hooks → Create subscription, choose Web Hooks, set the trigger to Pull request commented on, and point the URL to \<dash\_url>/webhook/azure. If you add a Basic auth password on the subscription, configure the same value as SERVICE\_HOOK\_PASSWORD on the LOCI backend.

### **Dedicated LOCI bot user**

Create a dedicated Azure DevOps user — the "LOCI bot" — that owns the PAT used for SCM API calls and posts the PR comments. Whatever **display name Azure DevOps shows for that user must be set on the LOCI backend as the `AZURE_BOT_IDENTITY` env var** so the bot recognizes its own comments and mentions. The `@<bot-name>` placeholder used throughout this README refers to that same value. Example:

```yaml
azureDevops:
botIdentity: "loci auroralabs"
```

Generate a long-lived PAT for that user with the following scopes:

* **Code** (Read & Write)
* **Identity** (Read)
* **Pull Request Threads** (Read & Write)
* **Tokens** (Read & Manage)

Store the PAT as an Azure DevOps pipeline secret (e.g. `LOCI_AZURE_PAT`) and pass it to the task as `scmToken`. The first task run uploads the token to the LOCI backend, which then uses it for the async post-upload calls (PR comments, `@<bot-name>` chat) that fire after the build ends. You can verify the stored token's validity in the LOCI dashboard under your project's **Personal Access Token** field (top-right of the project view).

### **Service hook for PR chat**

Register a service hook to propagate PR comment events from Azure DevOps to the LOCI backend — without it, the backend never sees the comments and `@<bot-name>` chat can't respond. In Azure DevOps go to **Project Settings → Service hooks → Create subscription**, choose **Web Hooks**, and set **Trigger on this type of event** to **Pull request commented on**. Set the URL to `<dash_url>/webhook/azure`. If you set a Basic authentication password on the subscription, that same value must be configured on the backend as the `SERVICE_HOOK_PASSWORD` env var (username is ignored).

### Azure DevOps pipeline setup

Set these on the pipeline (or as variable group entries):

* `LOCI_BACKEND_URL` — pipeline variable.
* `LOCI_API_KEY` — pipeline **secret** variable (copied from the LOCI dashboard above).
* `LOCI_AZURE_PAT` — pipeline **secret** variable holding the bot PAT generated above; passed to the task as `scmToken`.

### **Usage Examples**

#### **Example 1: Build + Upload**

```yaml
trigger:
  branches:
    include: [main]
pr:
  branches:
    include: [main]

pool:
  vmImage: 'ubuntu-latest'

variables:
  LOCI_PROJECT: AzureDevOpsDemo

steps:
  - checkout: self
    fetchDepth: 0
    persistCredentials: true

  - script: echo "Build project here"
    displayName: 'Build project'

  - task: LociTask@1
    name: LOCI_Upload
    displayName: 'LOCI Upload'
    inputs:
      mode: upload
      project: $(LOCI_PROJECT)
      binaries: path/to/your/binaries/
      scmToken: $(LOCI_AZURE_PAT)
    env:
      LOCI_API_KEY: $(LOCI_API_KEY)
      LOCI_BACKEND_URL: $(LOCI_BACKEND_URL)
```

### **Inputs**

<table><thead><tr><th width="129">Input</th><th width="115" align="center">Required</th><th width="240" align="center">Default</th><th>Description</th></tr></thead><tbody><tr><td><code>mode</code></td><td align="center">✅</td><td align="center"><code>upload</code></td><td>Operation to perform. v1 supports <code>upload</code> only.</td></tr><tr><td><code>project</code></td><td align="center">No</td><td align="center"><code>$(Build.Repository.Name)</code></td><td>LOCI project name to tag analysis results under. Defaults to the Azure DevOps repository name when omitted; set explicitly to override.</td></tr><tr><td><code>binaries</code></td><td align="center">✅</td><td align="center">—</td><td>Newline-separated list of binary paths, glob patterns, or a directory. Non-ELF entries are filtered out.</td></tr><tr><td><code>target</code></td><td align="center">No</td><td align="center"><code>&#x3C;branch>@&#x3C;shortSHA></code></td><td>Project version label for this run. Auto-resolved from build context; set explicitly to override.</td></tr><tr><td><code>base</code></td><td align="center">No</td><td align="center">PR merge base on PR builds</td><td>Base version to compare <code>target</code> against. Auto-resolved on PRs; set explicitly to override (or to force a comparison on non-PR builds).</td></tr><tr><td><code>waitBase</code></td><td align="center">No</td><td align="center"><code>true</code></td><td>Wait for the base version's processing to finish before uploading the target. Comparison analysis cannot run otherwise — leave on unless you specifically want to fail fast.</td></tr><tr><td><code>scmToken</code></td><td align="center">✅</td><td align="center">—</td><td>Long-lived Azure DevOps PAT used by LOCI for SCM API calls. Pass via a pipeline secret, e.g. <code>scmToken: $(LOCI_AZURE_PAT)</code>.</td></tr></tbody></table>

### Token Rotation

To rotate the LOCI bot's Personal Access Token: navigate to User Settings → Personal access tokens in Azure DevOps and revoke the existing token. Generate a new PAT for the same bot user with identical scopes - Code (Read & Write), Identity (Read), Pull Request Threads (Read & Write), Tokens (Read & Manage) - and copy the new token value. In your Azure DevOps pipeline, open Pipelines → Library (or the pipeline's Variables panel), locate the LOCI\_AZURE\_PAT secret variable, and replace it with the new token. No pipeline code changes are required; the updated secret takes effect on the next pipeline run.

### **Outputs**

| Variable      | Kind                                 | Description                                                |
| ------------- | ------------------------------------ | ---------------------------------------------------------- |
| `target`      | Step output (`$(<stepName>.target)`) | Resolved project version name for this run.                |
| `base`        | Step output (`$(<stepName>.base)`)   | Resolved base version name (may be empty).                 |
| `LOCI_TARGET` | Pipeline variable (`$(LOCI_TARGET)`) | Same value as `target`, available to all downstream tasks. |
| `LOCI_BASE`   | Pipeline variable (`$(LOCI_BASE)`)   | Same value as `base`, available to all downstream tasks.   |

***

### Viewing results

Open the **LOCI Upload** step's log and look at the last line — the task prints the LOCI dashboard URL there. On PR builds, the same analysis is also one click away from **Checks → Performance overview**, whose target URL deep-links straight to the latest comparison view.

***

### Rotating the SCM PAT

Azure DevOps PATs expire.&#x20;

To rotate, update the pipeline secret/variable (e.g. `LOCI_AZURE_PAT`) with the new token — the next task run uploads it to the LOCI backend and replaces the stored copy used for async post-upload calls (PR comments, `@<bot-name>` chat).&#x20;

If the old token expires before the next build runs, paste the new token directly into the project's **Personal Access Token** field in the LOCI dashboard to unblock those calls immediately. The project view shows an error indicator when the stored token is no longer valid.

***

### Troubleshooting

**Base version is missing.** The comparison can't run because the resolved base isn't available. The usual causes are: the base branch was never uploaded to LOCI, the base upload is still processing and `waitBase: false` was set, or the base's own analysis failed. Make sure the base branch has a successful LOCI run to compare against; for in-flight processing, keep `waitBase: true` (the default) so the task polls until the base is ready.

**Account is not configured for agentic mode.** Some features require the company to be agentic. In the LOCI dashboard, sign in as a company user, open **Company Details → Edit**, tick the **agentic** checkbox, and save (or ask a LOCI admin to do it).

**`@<bot-name>` chat isn't responding.** Check that **repository-url** is set on your LOCI project (see above) and that the service hook for **Pull request commented on** is registered and pointing at `<dash_url>/webhook/azure` with the matching `SERVICE_HOOK_PASSWORD` on the backend.


---

# 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:

```
GET https://docs.loci-dev.net/ai-binary-analysis-in-your-ci-cd/ready-to-integrate-in-your-ci-cd/loci-azure-devops-technical-reference.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.
