mirror of https://github.com/microsoft/vcpkg.git
[skill] Add skill to analyze CI failures (#51188)
This commit is contained in:
parent
d034cf165b
commit
12dc3f54ca
|
|
@ -0,0 +1,448 @@
|
|||
---
|
||||
name: analyze-ci-failures
|
||||
description: 'Analyze vcpkg Azure DevOps CI build failures. Downloads failure logs, identifies regression root causes, and generates a structured report categorizing build errors by package, triplet, and failure type.'
|
||||
argument-hint: 'Azure DevOps build URL (e.g., "https://dev.azure.com/vcpkg/public/_build/results?buildId=129315")'
|
||||
---
|
||||
|
||||
# vcpkg CI Failures Analyzer
|
||||
|
||||
## When to Use
|
||||
|
||||
- Investigating why a CI build failed on Azure DevOps
|
||||
- Identifying which packages regressed in a PR or scheduled build
|
||||
- Triaging root causes before assigning bugs or reverting changes
|
||||
- Getting a quick summary of failures across all triplets in one build
|
||||
|
||||
## Overview
|
||||
|
||||
This skill fetches build metadata and failure logs directly from the Azure DevOps REST API, cross-references them with `scripts/ci.baseline.txt`, and produces a structured regression report:
|
||||
|
||||
- **Build Summary**: Overall build result, trigger type (PR vs scheduled), and which jobs (triplets) failed
|
||||
- **Artifact Download**: Fetches every "failure logs for *" artifact published by the CI pipeline
|
||||
- **Log Analysis**: Parses per-package failure logs to extract compiler errors, missing dependencies, linker errors, and other root causes
|
||||
- **Regression Classification**: Distinguishes new regressions from known failures already listed in `ci.baseline.txt`
|
||||
- **Structured Report**: Organized by triplet, then package, with concise root-cause summaries
|
||||
|
||||
## Detailed Workflow
|
||||
|
||||
### Step 1: Parse the Build URL
|
||||
|
||||
Given a URL such as:
|
||||
```
|
||||
https://dev.azure.com/vcpkg/public/_build/results?buildId=129315&view=results
|
||||
```
|
||||
|
||||
Extract:
|
||||
- **organization**: `vcpkg`
|
||||
- **project**: `public`
|
||||
- **buildId**: `129315`
|
||||
|
||||
The REST API base is: `https://dev.azure.com/{organization}/{project}/_apis`
|
||||
|
||||
### Step 2: Fetch Build Metadata
|
||||
|
||||
**Get overall build info:**
|
||||
```
|
||||
GET https://dev.azure.com/{org}/{project}/_apis/build/builds/{buildId}?api-version=7.0
|
||||
```
|
||||
Key fields in the response:
|
||||
- `status` — `completed`, `inProgress`, etc.
|
||||
- `result` — `succeeded`, `failed`, `partiallySucceeded`, `canceled`
|
||||
- `reason` — `pullRequest`, `schedule`, `manual`, `individualCI`
|
||||
- `requestedFor.displayName` — who triggered the build
|
||||
- `sourceBranch` — branch or PR reference
|
||||
- `sourceVersion` — commit SHA
|
||||
- `_links.web.href` — canonical link back to the build page
|
||||
- `finishTime` — when it completed
|
||||
|
||||
**Get the build timeline (all jobs and tasks):**
|
||||
```
|
||||
GET https://dev.azure.com/{org}/{project}/_apis/build/builds/{buildId}/timeline?api-version=7.0
|
||||
```
|
||||
The response contains a `records` array. Each record has:
|
||||
- `type` — `"Job"`, `"Task"`, `"Stage"`, `"Phase"`
|
||||
- `name` — display name (e.g., `"x64_windows"`, `"*** Test Modified Ports"`)
|
||||
- `result` — `"succeeded"`, `"failed"`, `"skipped"`, `"canceled"`
|
||||
- `state` — `"completed"`, `"inProgress"`, `"pending"`
|
||||
- `log.url` — URL to the raw task log (for individual task logs)
|
||||
- `parentId` — parent record ID (tasks belong to jobs)
|
||||
|
||||
Filter for `type == "Job"` and `result == "failed"` to get a list of failing triplets.
|
||||
|
||||
### Step 2b: Scan "Test Modified Ports" Step Logs for REGRESSION Lines
|
||||
|
||||
**This step is required** — some failure types (notably `FILE_CONFLICTS`) are only reported in the step console output and do **not** produce entries in the failure log artifacts. Skipping this step will miss those regressions entirely.
|
||||
|
||||
For each failed job in the timeline, find the task named `"*** Test Modified Ports"` (type `"Task"`, child of that job) and fetch its log:
|
||||
|
||||
```
|
||||
GET {record.log.url}?api-version=7.0
|
||||
```
|
||||
|
||||
The log is plain text. Scan it for lines matching the pattern:
|
||||
```
|
||||
REGRESSION: {port}:{triplet} failed with {FAILURE_TYPE}.
|
||||
```
|
||||
|
||||
**Example output from a real build:**
|
||||
```
|
||||
REGRESSION: kf6i18n:x64-windows failed with FILE_CONFLICTS. If expected, add kf6i18n:x64-windows=fail to D:\a\_work\1\s\scripts\azure-pipelines/../ci.baseline.txt.
|
||||
REGRESSION: kf6itemmodels:x64-windows failed with FILE_CONFLICTS. If expected, add kf6itemmodels:x64-windows=fail to D:\a\_work\1\s\scripts\azure-pipelines/../ci.baseline.txt.
|
||||
```
|
||||
|
||||
**Known `FAILURE_TYPE` values found in this log:**
|
||||
| Failure type | Also has artifact log? | Notes |
|
||||
|---|---|---|
|
||||
| `BUILD_FAILED` | ✅ Yes | Full build logs in "failure logs for {triplet}" artifact |
|
||||
| `FILE_CONFLICTS` | ❌ No | Port installs files that conflict with another port; only in step log |
|
||||
| `MISSING_FROM_BASELINE` | ❌ No | Port passed but is listed as `fail` in baseline; no artifact |
|
||||
| `CASCADE_BUILD_FAILED` | Sometimes | Dependency failure; root port has artifact, downstream may not |
|
||||
|
||||
**PowerShell to extract all REGRESSION lines from a job's "Test Modified Ports" step:**
|
||||
```powershell
|
||||
# Get the timeline to find log URLs
|
||||
$timeline = Invoke-RestMethod "https://dev.azure.com/{org}/{project}/_apis/build/builds/{buildId}/timeline?api-version=7.0"
|
||||
|
||||
# For each failed job, find its "Test Modified Ports" task
|
||||
$failedJobs = $timeline.records | Where-Object { $_.type -eq 'Job' -and $_.result -eq 'failed' }
|
||||
foreach ($job in $failedJobs) {
|
||||
$testTask = $timeline.records | Where-Object {
|
||||
$_.type -eq 'Task' -and
|
||||
$_.parentId -eq $job.id -and
|
||||
$_.name -like '*Test Modified Ports*'
|
||||
}
|
||||
if ($testTask -and $testTask.log.url) {
|
||||
$logText = Invoke-RestMethod "$($testTask.log.url)?api-version=7.0"
|
||||
$regressions = $logText -split "`n" | Where-Object { $_ -match '^REGRESSION:' }
|
||||
$regressions | ForEach-Object { Write-Host "$($job.name): $_" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Collect all `REGRESSION:` lines from all jobs into a master list before proceeding to artifact download. This list is your **ground truth** for what failed — the failure log artifacts are supplementary evidence for diagnosing *why*.
|
||||
|
||||
### Step 3: List Published Artifacts
|
||||
|
||||
```
|
||||
GET https://dev.azure.com/{org}/{project}/_apis/build/builds/{buildId}/artifacts?api-version=7.0
|
||||
```
|
||||
Each artifact in `value[]` has:
|
||||
- `name` — e.g., `"failure logs for x64-windows"`, `"file lists for x64-windows"`, `"format.diff"`
|
||||
- `resource.type` — **`"PipelineArtifact"`** (not `"Container"` — the Container listing API does **not** work for these)
|
||||
- `resource.downloadUrl` — direct ZIP download URL hosted on `artprodwus21.artifacts.visualstudio.com`; no auth required for public builds
|
||||
|
||||
**Focus on artifacts whose name starts with `"failure logs for"`** — these contain one subdirectory per failing port.
|
||||
|
||||
**Prioritize by compressed artifact size** (from `resource.properties.artifactsize`):
|
||||
|
||||
| Compressed size | Interpretation | Analysis depth |
|
||||
|---|---|---|
|
||||
| < 10 MB | Few failures (< ~15 ports) | Analyze all ports fully |
|
||||
| 10–50 MB | Moderate failures | Sample all ports, deep-dive key ones |
|
||||
| 50–120 MB | Many failures | Focus on unique error categories only |
|
||||
| > 120 MB | Mass failures — likely a systemic issue | Find the common root, skip per-port deep-dive |
|
||||
|
||||
Start with the smallest artifacts (fastest feedback). Android triplets typically produce 115–123 MB artifacts and share root causes with Linux.
|
||||
|
||||
### Step 4: Download Failure Log Artifacts
|
||||
|
||||
**`web_fetch` cannot download binary ZIP files.** Use PowerShell with `Invoke-WebRequest` instead:
|
||||
|
||||
```powershell
|
||||
$tmpDir = "$env:TEMP\vcpkg-ci-{buildId}"
|
||||
New-Item -ItemType Directory -Path $tmpDir -Force | Out-Null
|
||||
|
||||
# Download the artifact ZIP using the downloadUrl from the artifacts API response
|
||||
$downloadUrl = "{resource.downloadUrl from artifacts API}"
|
||||
Invoke-WebRequest -Uri $downloadUrl -OutFile "$tmpDir\{triplet}.zip" -UseBasicParsing
|
||||
|
||||
# Extract
|
||||
Expand-Archive "$tmpDir\{triplet}.zip" -DestinationPath "$tmpDir\{triplet}" -Force
|
||||
|
||||
# List failed ports — each is a subdirectory inside "failure logs for {triplet}/"
|
||||
$root = "$tmpDir\{triplet}\failure logs for {triplet}"
|
||||
Get-ChildItem $root -Directory | Select-Object -ExpandProperty Name
|
||||
```
|
||||
|
||||
**Confirmed ZIP structure (from build #129315):**
|
||||
```
|
||||
failure logs for x64-windows.zip
|
||||
└── failure logs for x64-windows/ ← top-level folder = artifact name
|
||||
├── boost-filesystem/ ← one subdirectory per failing port
|
||||
│ ├── stdout-x64-windows.log ← PRIMARY: full vcpkg output, final error
|
||||
│ ├── config-x64-windows-out.log ← CMake configure stdout
|
||||
│ ├── config-x64-windows-err.log ← CMake configure stderr
|
||||
│ ├── config-x64-windows-dbg-CMakeConfigureLog.yaml.log
|
||||
│ ├── config-x64-windows-dbg-CMakeCache.txt.log
|
||||
│ ├── config-x64-windows-dbg-ninja.log
|
||||
│ ├── build-x64-windows-dbg-out.log ← compiler stdout (can be very large)
|
||||
│ ├── build-x64-windows-dbg-err.log ← compiler stderr
|
||||
│ ├── install-x64-windows-dbg-out.log
|
||||
│ ├── install-x64-windows-dbg-err.log
|
||||
│ ├── patch-x64-windows-0-err.log ← patch application errors (numbered)
|
||||
│ ├── patch-x64-windows-0-out.log
|
||||
│ ├── extract-out.log / extract-err.log
|
||||
│ └── generate-x64-windows-dbg-err.log ← GN builds (v8, crashpad) only
|
||||
├── curl/
|
||||
├── openssl/
|
||||
└── ...
|
||||
```
|
||||
|
||||
**For Meson ports (e.g., mesa):**
|
||||
```
|
||||
mesa/
|
||||
├── cmake-get-vars_C_CXX-x64-linux-dbg.cmake.log
|
||||
├── config-x64-linux-dbg-meson-log.txt.log
|
||||
├── meson-x64-linux-dbg.log
|
||||
├── pip-install-packages-x64-linux-err.log
|
||||
├── venv-setup-x64-linux-err.log
|
||||
└── stdout-x64-linux.log
|
||||
```
|
||||
|
||||
**For autotools ports (e.g., libxt):**
|
||||
```
|
||||
libxt/
|
||||
├── autoconf-x64-windows-err.log
|
||||
├── build-x64-windows-dbg-err.log ← compiler warnings/errors
|
||||
├── build-x64-windows-dbg-out.log
|
||||
└── stdout-x64-windows.log
|
||||
```
|
||||
|
||||
### Step 5: Analyze Log Content — Two-Phase Approach
|
||||
|
||||
**Phase 1: Classify all failures quickly (one pass)**
|
||||
|
||||
For each failing port, read only `stdout-{triplet}.log` last 20 lines:
|
||||
```powershell
|
||||
$ports = Get-ChildItem $root -Directory | Sort-Object Name
|
||||
foreach ($port in $ports) {
|
||||
$stdout = Get-ChildItem $port.FullName -Filter "stdout*" | Select-Object -First 1
|
||||
if ($stdout) {
|
||||
$lines = Get-Content $stdout.FullName -Encoding UTF8
|
||||
# Extract final error line
|
||||
$keyError = ($lines | Where-Object { $_ -match "error:|CMake Error|FAILED" } | Select-Object -Last 1) -replace '^\s+',''
|
||||
Write-Host "$($port.Name): $keyError"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This gives a one-line classification per port. Identify common patterns across ports (many ports → same error = systemic issue).
|
||||
|
||||
**Phase 2: Deep-dive the specific stage log for each port**
|
||||
|
||||
After classifying, choose the right log file based on failure type:
|
||||
|
||||
| Failure type indicated by stdout | Log to read next |
|
||||
|---|---|
|
||||
| `Command failed: cmake --build` (build/install) | `install-{triplet}-dbg-out.log` — grep for `error:` |
|
||||
| `Command failed: ninja -v` (configure) | `config-{triplet}-out.log` — last 20 lines |
|
||||
| `Command failed: ninja -v` (configure) | `config-{triplet}-dbg-CMakeConfigureLog.yaml.log` |
|
||||
| `Command failed: gn gen` or `ninja` (GN) | `generate-{triplet}-dbg-err.log` |
|
||||
| `Command failed: meson setup` | `config-{triplet}-dbg-meson-log.txt.log` |
|
||||
| `Command failed: make` (autotools) | `build-{triplet}-dbg-err.log` |
|
||||
| `Command failed: autoreconf` | `autoconf-{triplet}-err.log` |
|
||||
| Patch error | `patch-{triplet}-N-err.log` |
|
||||
|
||||
**Important**: `install-*-out.log` and `build-*-out.log` can be very large (100KB–2MB+). Always grep for errors rather than reading the full file:
|
||||
```powershell
|
||||
$lines = Get-Content "install-x64-windows-dbg-out.log" -Encoding UTF8
|
||||
$lines | Where-Object { $_ -match "error:" -and $_ -notmatch "^--" } | Select-Object -First 10
|
||||
```
|
||||
|
||||
**Note on empty error logs**: Many `*-err.log` files are empty (0 bytes) — the actual error output goes to stdout for CMake/ninja builds. Always check `*-out.log` if `*-err.log` is empty.
|
||||
|
||||
**Note on test results API**: `GET /_apis/test/runs?buildId=...` requires authentication even for public projects. Skip this API; the failure logs contain sufficient information.
|
||||
|
||||
### Step 5 (continued): Pattern Catalogue
|
||||
|
||||
For each failure log, identify the root cause by scanning for known error patterns.
|
||||
See `references/vcpkg-failure-patterns.md` for a comprehensive pattern catalogue and `references/report-template.md` for a table of the most common high-frequency patterns to check first.
|
||||
|
||||
**Quick triage checklist (scan each log in order):**
|
||||
|
||||
1. **Dependency failure** — the port didn't actually fail itself; a dependency did:
|
||||
```
|
||||
error: package dependency-name:triplet is not installed
|
||||
-- Building dependency-name[core]:triplet failed
|
||||
```
|
||||
Root cause: the dependency listed in the log, not the current package.
|
||||
|
||||
2. **CMake configure error** — dependency not found or incompatible version:
|
||||
```
|
||||
CMake Error: Could not find a package configuration file provided by "XYZ"
|
||||
CMake Error at CMakeLists.txt:NN: find_package(XYZ REQUIRED)
|
||||
```
|
||||
|
||||
3. **Compiler error** — actual source code compile failure:
|
||||
```
|
||||
error C2065: (MSVC)
|
||||
error: use of undeclared identifier (Clang/GCC)
|
||||
fatal error: 'header.h' file not found
|
||||
```
|
||||
|
||||
4. **Linker error**:
|
||||
```
|
||||
error LNK2019: unresolved external symbol (MSVC)
|
||||
undefined reference to (GCC/Clang)
|
||||
```
|
||||
|
||||
5. **SHA512 mismatch** — downloaded archive hash changed:
|
||||
```
|
||||
error: File does not have the expected hash
|
||||
Expected: ...
|
||||
Actual: ...
|
||||
```
|
||||
|
||||
6. **Download failure** — network or URL issue:
|
||||
```
|
||||
error: Failed to download
|
||||
error: curl: (22)
|
||||
```
|
||||
|
||||
7. **Post-build check failure** — installed files don't pass vcpkg checks:
|
||||
```
|
||||
error: The following files are not installed
|
||||
error: Usage of deprecated function
|
||||
```
|
||||
|
||||
8. **Test failure** — port tests failed (check xUnit results):
|
||||
```
|
||||
Test failed: ...
|
||||
FAILED - ...
|
||||
```
|
||||
|
||||
### Step 6: Cross-Reference with CI Baseline
|
||||
|
||||
Read `scripts/ci.baseline.txt` from the local repository to classify each failure:
|
||||
|
||||
```
|
||||
# Format: port-name=fail|skip|pass [# comment]
|
||||
boost-filesystem=fail # needs icu update
|
||||
```
|
||||
|
||||
**Classification logic:**
|
||||
- If the failing port is listed as `fail` or `skip` in the baseline → **Known / Expected** (not a regression)
|
||||
- If the failing port is NOT in the baseline, or listed as `pass` → **Regression** (new failure)
|
||||
- If a port that is expected to `fail` is now succeeding → **Unexpected Pass** (may need baseline update)
|
||||
|
||||
### Step 7: Generate the Regression Report
|
||||
|
||||
Produce a structured markdown report with the following sections:
|
||||
|
||||
---
|
||||
|
||||
**Template:**
|
||||
|
||||
```markdown
|
||||
# vcpkg CI Failure Report
|
||||
|
||||
**Build:** [#{buildId}]({build_web_url})
|
||||
**Triggered by:** {reason} — {requestedFor} on `{sourceBranch}` @ `{sourceVersion[:8]}`
|
||||
**Result:** {result} | **Finished:** {finishTime}
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Triplet | Status | New Regressions | Known Failures |
|
||||
|---------|--------|-----------------|----------------|
|
||||
| x64-windows | ❌ Failed | 3 | 1 |
|
||||
| x64-linux | ✅ Passed | 0 | 0 |
|
||||
| ... | | | |
|
||||
|
||||
---
|
||||
|
||||
## 🔴 New Regressions (Action Required)
|
||||
|
||||
### x64-windows
|
||||
|
||||
#### `portname` — Root Cause Category
|
||||
- **Error:** `<first relevant error line>`
|
||||
- **File:** `path/to/file.cpp:42`
|
||||
- **Analysis:** Short description of why this likely broke.
|
||||
- **Suggested fix:** ...
|
||||
|
||||
...
|
||||
|
||||
---
|
||||
|
||||
## 🟡 Known / Expected Failures (Baseline)
|
||||
|
||||
| Port | Triplet | Baseline Entry |
|
||||
|------|---------|----------------|
|
||||
| portname | x64-windows | `fail # reason` |
|
||||
...
|
||||
|
||||
---
|
||||
|
||||
## ℹ️ Notes
|
||||
|
||||
- Dependency chain failures: {n} ports failed due to a common upstream failure in `dep-name`
|
||||
- Download failures: {n} (may be transient network issues)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 8: Dependency Chain Deduplication
|
||||
|
||||
Before listing regressions, collapse dependency chains:
|
||||
|
||||
- If `libA` fails and `libB`, `libC`, `libD` all fail because `libA` is a dependency, list only `libA` as the regression with a note: "caused {n} downstream failures: libB, libC, libD"
|
||||
- Check dependency info from the log: lines containing `-- Building {dep}:{triplet} failed` indicate the root of the chain
|
||||
|
||||
### Step 9: Transient vs. Persistent Failures
|
||||
|
||||
Flag failures that are likely transient (not actual regressions):
|
||||
- Download failures (network errors, SHA mismatches from upstream file changes)
|
||||
- Timeout failures (`error: build timed out`)
|
||||
- Flaky test failures (same port fails in one triplet but passes in others for unrelated reasons)
|
||||
|
||||
Suggest re-running the build for transient failures rather than filing issues.
|
||||
|
||||
## Quick Start
|
||||
|
||||
**Minimal 3-step process:**
|
||||
1. Provide the build URL: `analyze-ci-failure https://dev.azure.com/vcpkg/public/_build/results?buildId=129315`
|
||||
2. Skill fetches build metadata, downloads all failure log artifacts, reads baseline
|
||||
3. Receive structured regression report
|
||||
|
||||
## Output Format
|
||||
|
||||
When generating the report, follow the exact format defined in `references/report-template.md`.
|
||||
That file contains:
|
||||
- The full markdown template with placeholder variables
|
||||
- A real worked example (build #129315, 24 ports) to calibrate tone and depth
|
||||
- Formatting rules (section order, priority levels, error quoting style)
|
||||
- Artifact size heuristics to guide how deeply to analyze each triplet
|
||||
- A table of common high-frequency patterns to scan for first
|
||||
|
||||
When asked to produce the report, default to the full structured markdown report. You can also produce:
|
||||
- **Summary only**: Just the summary table and count of regressions
|
||||
- **Regressions only**: Skip known failures, show only new regressions
|
||||
- **Single triplet**: Focus on one platform (e.g., "x64-windows only")
|
||||
- **Port-focused**: Group by port name instead of triplet
|
||||
|
||||
### Saving the Report
|
||||
|
||||
After generating the report, **always save it as a markdown file** in the repository root:
|
||||
|
||||
```
|
||||
ci-report-{buildId}.md
|
||||
```
|
||||
|
||||
Use the `create` tool to write the full report content to this path. This ensures the report is persisted and can be easily reviewed or shared.
|
||||
|
||||
## Important Notes
|
||||
|
||||
- The vcpkg Azure DevOps project (`vcpkg/public`) is **publicly accessible** — no authentication token is required for artifact downloads or build/artifact API calls
|
||||
- **`web_fetch` cannot download binary ZIP files** — use PowerShell `Invoke-WebRequest` for artifact downloads
|
||||
- **`resource.type` is `"PipelineArtifact"`**, not `"Container"` — the Container listing API (`/_apis/resources/Containers/{id}`) does not work; use `downloadUrl` directly
|
||||
- **The test results API (`/_apis/test/runs`) requires authentication** even for public projects — skip it; failure logs contain sufficient information
|
||||
- **Many `*-err.log` files are 0 bytes** — CMake, ninja, and make typically write errors to stdout; always check `*-out.log` when `*-err.log` is empty
|
||||
- If a build is still `inProgress`, only partial results will be available; note this in the report
|
||||
- Failure log artifacts are only published when there are actual failures; a missing artifact for a triplet means that triplet passed
|
||||
- **`FILE_CONFLICTS` failures are invisible in artifacts** — they only appear as `REGRESSION:` lines in the "Test Modified Ports" step log; always scan step logs (Step 2b) before concluding the artifact list is complete
|
||||
- The `"format.diff"` artifact (if present) indicates formatting or version file issues, not port build failures — report these separately
|
||||
- `"z azcopy logs"` artifacts are infrastructure logs; skip these unless diagnosing asset cache issues
|
||||
- **Android artifact sizes (~115–123 MB) typically share root causes with Linux** — if Linux analysis reveals a systemic issue (e.g., compiler header change, Python version), assume Android is affected too without full re-analysis
|
||||
- **Clean up the temp directory** (`$env:TEMP\vcpkg-ci-{buildId}`) after analysis to avoid disk clutter
|
||||
|
|
@ -0,0 +1,271 @@
|
|||
# Azure DevOps REST API Reference for vcpkg CI
|
||||
|
||||
## Base URL
|
||||
|
||||
```
|
||||
https://dev.azure.com/vcpkg/public/_apis
|
||||
```
|
||||
|
||||
All endpoints below are appended to this base. The `vcpkg/public` project is **publicly readable** — no Authorization header is required.
|
||||
|
||||
## API Version
|
||||
|
||||
Always append `?api-version=7.0` (or include it in query strings).
|
||||
|
||||
---
|
||||
|
||||
## Build Endpoints
|
||||
|
||||
### Get Build Details
|
||||
|
||||
```
|
||||
GET https://dev.azure.com/{org}/{project}/_apis/build/builds/{buildId}?api-version=7.0
|
||||
```
|
||||
|
||||
**Response fields:**
|
||||
```json
|
||||
{
|
||||
"id": 129315,
|
||||
"buildNumber": "20240315.1",
|
||||
"status": "completed",
|
||||
"result": "failed",
|
||||
"reason": "pullRequest",
|
||||
"sourceBranch": "refs/pull/12345/merge",
|
||||
"sourceVersion": "abc123def456...",
|
||||
"requestedFor": { "displayName": "Jane Developer" },
|
||||
"startTime": "2024-03-15T10:00:00Z",
|
||||
"finishTime": "2024-03-15T14:30:00Z",
|
||||
"definition": { "name": "vcpkg.CI" },
|
||||
"_links": {
|
||||
"web": { "href": "https://dev.azure.com/vcpkg/public/_build/results?buildId=129315" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**`result` values:** `succeeded` | `failed` | `partiallySucceeded` | `canceled`
|
||||
**`reason` values:** `pullRequest` | `schedule` | `manual` | `individualCI` | `batchedCI`
|
||||
|
||||
---
|
||||
|
||||
### Get Build Timeline
|
||||
|
||||
```
|
||||
GET https://dev.azure.com/{org}/{project}/_apis/build/builds/{buildId}/timeline?api-version=7.0
|
||||
```
|
||||
|
||||
Returns all stages, jobs, tasks and their results.
|
||||
|
||||
**Response structure:**
|
||||
```json
|
||||
{
|
||||
"records": [
|
||||
{
|
||||
"id": "guid",
|
||||
"parentId": "parent-guid-or-null",
|
||||
"type": "Job",
|
||||
"name": "x64_windows",
|
||||
"displayName": "x64_windows",
|
||||
"state": "completed",
|
||||
"result": "failed",
|
||||
"startTime": "2024-03-15T10:05:00Z",
|
||||
"finishTime": "2024-03-15T12:15:00Z",
|
||||
"log": {
|
||||
"id": 42,
|
||||
"type": "Container",
|
||||
"url": "https://dev.azure.com/vcpkg/public/_apis/build/builds/129315/logs/42"
|
||||
},
|
||||
"errorCount": 1,
|
||||
"warningCount": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**`type` values:** `Stage` | `Phase` | `Job` | `Task`
|
||||
**`result` values:** `succeeded` | `failed` | `skipped` | `canceled` | `succeededWithIssues`
|
||||
|
||||
**To find failed jobs:**
|
||||
```python
|
||||
failed_jobs = [r for r in records if r['type'] == 'Job' and r['result'] == 'failed']
|
||||
```
|
||||
|
||||
**Job names map to triplets** (underscores in job names, hyphens in triplets):
|
||||
- `x64_windows` → `x64-windows`
|
||||
- `x64_windows_static` → `x64-windows-static`
|
||||
- `arm64_osx` → `arm64-osx`
|
||||
- `x64_linux` → `x64-linux`
|
||||
- `arm_neon_android` → `arm-neon-android`
|
||||
|
||||
---
|
||||
|
||||
### Get a Specific Log
|
||||
|
||||
```
|
||||
GET https://dev.azure.com/{org}/{project}/_apis/build/builds/{buildId}/logs/{logId}?api-version=7.0
|
||||
```
|
||||
|
||||
Returns plain text of the log. Use this to read the "*** Test Modified Ports" task log, which contains `REGRESSION:` lines for **all** failures including those without artifact logs (e.g., `FILE_CONFLICTS`).
|
||||
|
||||
**Finding the right log ID:** Look up the task record in the timeline response — the `log.id` field on the `"*** Test Modified Ports"` task record gives the log ID. Alternatively, use `log.url` directly.
|
||||
|
||||
**Scanning for REGRESSION lines:**
|
||||
```powershell
|
||||
$logText = Invoke-RestMethod "https://dev.azure.com/{org}/{project}/_apis/build/builds/{buildId}/logs/{logId}?api-version=7.0"
|
||||
$logText -split "`n" | Where-Object { $_ -match '^REGRESSION:' }
|
||||
```
|
||||
|
||||
**Example output:**
|
||||
```
|
||||
REGRESSION: kf6i18n:x64-windows failed with FILE_CONFLICTS. If expected, add kf6i18n:x64-windows=fail to .../ci.baseline.txt.
|
||||
REGRESSION: kf6itemmodels:x64-windows failed with FILE_CONFLICTS. If expected, add kf6itemmodels:x64-windows=fail to .../ci.baseline.txt.
|
||||
REGRESSION: v8:x64-windows failed with BUILD_FAILED. If expected, add v8:x64-windows=fail to .../ci.baseline.txt.
|
||||
```
|
||||
|
||||
> ⚠️ **`FILE_CONFLICTS` failures do NOT produce failure log artifacts.** The only record of them is in this step log. Always scan all "Test Modified Ports" task logs before relying on artifacts alone.
|
||||
|
||||
### List All Logs
|
||||
|
||||
```
|
||||
GET https://dev.azure.com/{org}/{project}/_apis/build/builds/{buildId}/logs?api-version=7.0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Artifact Endpoints
|
||||
|
||||
### List All Artifacts
|
||||
|
||||
```
|
||||
GET https://dev.azure.com/{org}/{project}/_apis/build/builds/{buildId}/artifacts?api-version=7.0
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"count": 39,
|
||||
"value": [
|
||||
{
|
||||
"id": 1107682,
|
||||
"name": "failure logs for x64-windows",
|
||||
"source": "7922e5c4-...",
|
||||
"resource": {
|
||||
"type": "PipelineArtifact",
|
||||
"data": "DCCD3D9C96CE79A758B255BD87397A07371B8394EE52F6BFF35346C144D63F3501",
|
||||
"properties": {
|
||||
"RootId": "196FDE3B...",
|
||||
"artifactsize": "8586850",
|
||||
"HashType": "DEDUP1024K",
|
||||
"DomainId": "0"
|
||||
},
|
||||
"url": "https://dev.azure.com/vcpkg/.../_apis/build/builds/129315/artifacts?artifactName=failure%20logs%20for%20x64-windows&api-version=7.0",
|
||||
"downloadUrl": "https://artprodwus21.artifacts.visualstudio.com/.../_apis/artifact/{base64hash}/content?format=zip"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
> ⚠️ **`resource.type` is `"PipelineArtifact"`**, not `"Container"`. The Container listing API
|
||||
> (`GET /_apis/resources/Containers/{id}`) does **not** work for these artifacts.
|
||||
> Use `resource.downloadUrl` directly to download the ZIP.
|
||||
|
||||
**Artifact naming conventions:**
|
||||
| Artifact Name Pattern | Contents | Priority |
|
||||
|---|---|---|
|
||||
| `failure logs for {triplet}` | Per-port build failure log directories | **High** — primary source |
|
||||
| `file lists for {triplet}` | Installed file manifests | Low — skip unless needed |
|
||||
| `format.diff` | Formatting/manifest diff | **Medium** — indicates PR format issues |
|
||||
| `z azcopy logs for {triplet}` | Binary cache transfer logs | Low — infrastructure only |
|
||||
|
||||
---
|
||||
|
||||
### Download Artifact ZIP (Confirmed Working)
|
||||
|
||||
Use the `downloadUrl` from the artifact listing. It resolves to an `artprodwus21.artifacts.visualstudio.com` URL. **`web_fetch` cannot download binary ZIPs** — use PowerShell:
|
||||
|
||||
```powershell
|
||||
# $downloadUrl = value from resource.downloadUrl in the artifacts list response
|
||||
Invoke-WebRequest -Uri $downloadUrl -OutFile "$tmpDir\{triplet}.zip" -UseBasicParsing
|
||||
Expand-Archive "$tmpDir\{triplet}.zip" -DestinationPath "$tmpDir\{triplet}" -Force
|
||||
|
||||
# List failing ports — each is a subdirectory inside the artifact folder
|
||||
$root = "$tmpDir\{triplet}\failure logs for {triplet}"
|
||||
Get-ChildItem $root -Directory | Select-Object -ExpandProperty Name
|
||||
```
|
||||
|
||||
The ZIP always contains one top-level folder named exactly `"failure logs for {triplet}"`.
|
||||
Inside that folder, each **failing port has its own subdirectory** named after the port.
|
||||
|
||||
> ❌ The Container API (`GET /_apis/resources/Containers/{containerId}`) does **not** work
|
||||
> for `PipelineArtifact` type. Do not attempt to use it.
|
||||
|
||||
---
|
||||
|
||||
## Test Results Endpoints
|
||||
|
||||
### List Test Runs for a Build
|
||||
|
||||
```
|
||||
GET https://dev.azure.com/{org}/{project}/_apis/test/runs?buildId={buildId}&api-version=7.0
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"value": [
|
||||
{
|
||||
"id": 9876,
|
||||
"name": "x64-windows",
|
||||
"state": "Completed",
|
||||
"totalTests": 500,
|
||||
"passedTests": 497,
|
||||
"failedTests": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Get Test Run Results
|
||||
|
||||
```
|
||||
GET https://dev.azure.com/{org}/{project}/_apis/test/runs/{runId}/results?api-version=7.0&outcomes=Failed
|
||||
```
|
||||
|
||||
Filter by `outcomes=Failed` to get only failures.
|
||||
|
||||
**Response includes:**
|
||||
- `testCaseName` — usually `portname:triplet`
|
||||
- `outcome` — `Failed`
|
||||
- `errorMessage` — short error description
|
||||
- `stackTrace` — full failure output
|
||||
|
||||
---
|
||||
|
||||
## URL Parsing
|
||||
|
||||
Given `https://dev.azure.com/vcpkg/public/_build/results?buildId=129315&view=results`:
|
||||
|
||||
| Component | Value | How to Extract |
|
||||
|-----------|-------|----------------|
|
||||
| Organization | `vcpkg` | 4th path segment |
|
||||
| Project | `public` | 5th path segment |
|
||||
| Build ID | `129315` | `buildId` query parameter |
|
||||
|
||||
```python
|
||||
# Python example
|
||||
from urllib.parse import urlparse, parse_qs
|
||||
url = "https://dev.azure.com/vcpkg/public/_build/results?buildId=129315&view=results"
|
||||
parts = urlparse(url)
|
||||
segments = parts.path.strip('/').split('/')
|
||||
org = segments[0] # "vcpkg"
|
||||
project = segments[1] # "public"
|
||||
build_id = parse_qs(parts.query)['buildId'][0] # "129315"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Rate Limits and Auth
|
||||
|
||||
- **Public projects** (like `vcpkg/public`): No authentication needed; anonymous access is allowed
|
||||
- **Rate limit**: ~200 requests per minute for anonymous; increase by adding a PAT as Bearer token if needed
|
||||
- **PAT header**: `Authorization: Basic {base64(":pat_token")}`
|
||||
|
|
@ -0,0 +1,176 @@
|
|||
# vcpkg CI Failure Report Template
|
||||
|
||||
This file provides the canonical output format for the `analyze-ci-failure` skill.
|
||||
Use it as the exact template when generating reports.
|
||||
|
||||
---
|
||||
|
||||
## Report Format
|
||||
|
||||
```markdown
|
||||
# vcpkg CI Failure Report — Build #{buildId}
|
||||
|
||||
**Build:** [{buildNumber}]({build_web_url}) · `{definition_name}`
|
||||
**Triggered by:** {reason} on `{sourceBranch}` @ `{sourceVersion[:8]}`
|
||||
**Duration:** {startTime} → {finishTime} UTC (~{duration})
|
||||
**Result:** ❌ **FAILED** — {baseline_summary}
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Triplet | Unique Failures |
|
||||
|---------|----------------|
|
||||
| x64-windows | N |
|
||||
| x64-windows-release | N (identical to x64-windows / N unique) |
|
||||
| x64-linux | N (M shared with Windows) |
|
||||
| {other triplets} | *artifacts present (not analyzed)* |
|
||||
|
||||
**Total unique failing ports across all analyzed triplets: N**
|
||||
**Estimated cross-platform failures: ≥N ports fail on multiple triplets**
|
||||
|
||||
---
|
||||
|
||||
## 🔴 Cross-Platform Regressions (Windows + Linux)
|
||||
|
||||
### N. `port-name` — Short Root Cause Title
|
||||
|
||||
- **Triplets:** x64-windows, x64-windows-release, x64-linux
|
||||
- **Error:** `exact error message from log`
|
||||
in `path/to/file.ext:line`
|
||||
- **Root cause:** Explanation of why this happened — what changed, what broke.
|
||||
- **Suggested fix:** Concrete actionable recommendation.
|
||||
|
||||
```cmake
|
||||
# Code snippet if applicable
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔴 Windows-Only Regressions
|
||||
|
||||
### N. `port-name` — Short Root Cause Title
|
||||
|
||||
- **Triplets:** x64-windows, x64-windows-release
|
||||
- **Error:** `exact error message`
|
||||
- **Root cause:** ...
|
||||
- **Suggested fix:** ...
|
||||
|
||||
---
|
||||
|
||||
## 🔴 Linux-Only Regressions
|
||||
|
||||
### N. `port-name` — Short Root Cause Title
|
||||
|
||||
- **Triplet:** x64-linux
|
||||
- **Error:** `exact error message`
|
||||
- **Root cause:** ...
|
||||
- **Suggested fix:** ...
|
||||
|
||||
---
|
||||
|
||||
## 📋 Action Recommendations
|
||||
|
||||
| Priority | Port(s) | Recommended Action |
|
||||
|---|---|---|
|
||||
| 🔴 Immediate | `port` | Short action description |
|
||||
| 🟠 High | `port` | Short action description |
|
||||
| 🟡 Medium | `port` | Short action description |
|
||||
| ℹ️ Baseline | `port` | Add `=fail/skip # reason` to `ci.baseline.txt` |
|
||||
| ℹ️ Investigate | `port` | What to look into |
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Real-World Example (Build #129315)
|
||||
|
||||
The following is a real report generated for the scheduled master build on 2026-03-30.
|
||||
Use this as a reference for tone, depth, and structure.
|
||||
|
||||
### Build Metadata
|
||||
|
||||
- **Build:** [20260330.1](https://dev.azure.com/vcpkg/public/_build/results?buildId=129315)
|
||||
- **Reason:** Scheduled run on `refs/heads/master` @ `c4de8d6f`
|
||||
- **Duration:** ~35 hours
|
||||
- **Artifacts with failure logs:** all 13 triplets had failures
|
||||
|
||||
### Failure Inventory
|
||||
|
||||
| Port | Triplets | Root Cause Category | Severity |
|
||||
|------|----------|---------------------|----------|
|
||||
| `v8` | win | Python 3.13 removed `pipes` module | 🔴 Immediate |
|
||||
| `onnxruntime` | win, linux | CMake `math()` on empty TensorRT variable | 🔴 Immediate |
|
||||
| `wpilib` | win, linux | `wpi::Logger::Log` API mismatch in `DataLog.cpp` | 🔴 Immediate |
|
||||
| `ntf-core` | win, linux | `bal` dep ordering (win); missing UFID cmake file (linux) | 🟠 High |
|
||||
| `rmqcpp` | win, linux | Transitive `libpcre2-8` not found via `bal→bdl` | 🟠 High |
|
||||
| `azure-storage-cpp` | linux | Boost.ASIO `deadline_timer` removed | 🟠 High |
|
||||
| `cppcoro` | linux | `<experimental/coroutine>` removed in GCC 14 | 🟠 High |
|
||||
| `zookeeper` | win, linux | Java not found at configure time | 🟡 Medium |
|
||||
| `moos-essential` | win | POSIX socket headers + Winsock2 conflict | 🟡 Medium |
|
||||
| `libxt` | win | Clang `-Wunsafe-buffer-usage` promoted to error | 🟡 Medium |
|
||||
| `saucer` | linux | Upstream compiler version check too strict | 🟡 Medium |
|
||||
| `libaiff` | linux | Missing `#include <stdint.h>` in public header | 🟡 Medium |
|
||||
| `libhdfs3` | linux | `mode` macro conflict + missing `<stdint.h>` | 🟡 Medium |
|
||||
| `yubico-piv-tool` | linux | Clang-only flag `-Wshorten-64-to-32` passed to GCC | 🟡 Medium |
|
||||
| `libnick` | linux | `sqlcipher` not available via pkg-config | 🟡 Medium |
|
||||
| `salome-medcoupling` | linux | Missing `metis` vcpkg dependency | 🟡 Medium |
|
||||
| `mesa` | linux | `glslangValidator` not found by Meson | 🟡 Medium |
|
||||
| `crashpad` | linux | Compiler not found (exit code 127, likely Docker image change) | ℹ️ Investigate |
|
||||
| `arrayfire` | linux | Build truncated at 117/832 — likely OOM kill | ℹ️ Investigate |
|
||||
| `xbitmaps` | linux | `xorg-macros < 1.20` in Docker image | ℹ️ Investigate |
|
||||
| `nana` | linux | CMake generate fails, no detail in logs | ℹ️ Investigate |
|
||||
| `openslide` | win | Portfile explicitly rejects MSVC (`use clang-cl`) | ℹ️ Baseline |
|
||||
| `openzl` | win | Portfile explicitly rejects MSVC (`use clang-cl`) | ℹ️ Baseline |
|
||||
| `ms-gdkx` | win | Requires Microsoft GDK Xbox Extensions (not in CI) | ℹ️ Baseline |
|
||||
|
||||
---
|
||||
|
||||
## Formatting Rules
|
||||
|
||||
1. **Section order**: Cross-Platform → Windows-Only → Linux-Only → macOS-Only → Android-Only → Action Table
|
||||
2. **Numbering**: Sequential across all sections (1, 2, 3 … N)
|
||||
3. **Error quotes**: Always quote the exact first meaningful error line from the log verbatim
|
||||
4. **Triplet notation**: Use short forms in narrative (`win`, `linux`) but full names in bullet points (`x64-windows`)
|
||||
5. **Baseline ports**: Ports that explicitly reject a platform by design (`MSVC is not supported`, environment requirements) go to the Baseline section, not regressions
|
||||
6. **Dependency chain**: If port A fails because port B failed, list only port B as the regression with a note "causes N downstream failures: portA, portC, …"
|
||||
7. **Transient failures**: Download failures (curl errors, SHA mismatches) and exit-code-127 failures should be flagged as potentially transient
|
||||
8. **Priority levels**:
|
||||
- 🔴 **Immediate** — Core/popular ports, failures on 3+ triplets, or CI-environment regressions affecting many ports
|
||||
- 🟠 **High** — Failures on 2+ triplets, popular ports, or clear upstream API breaks
|
||||
- 🟡 **Medium** — Single-triplet failures with clear fixes
|
||||
- ℹ️ **Baseline/Investigate** — Expected failures, environment issues, or unclear root cause
|
||||
|
||||
---
|
||||
|
||||
## Artifact Size Heuristics
|
||||
|
||||
Use artifact sizes (from the artifacts list API response) to prioritize analysis:
|
||||
|
||||
| Artifact Size | Interpretation |
|
||||
|---|---|
|
||||
| < 10 MB | Very few failures (< ~15 ports), analyze fully |
|
||||
| 10–50 MB | Moderate failures (~15–80 ports), sample representative ones |
|
||||
| 50–120 MB | Many failures (~80–200 ports), focus on unique errors only |
|
||||
| > 120 MB | Mass failures — likely a systemic issue (toolchain, CI image, common dep) |
|
||||
|
||||
In build #129315, x64-windows (8.5 MB) and x64-linux (4.6 MB compressed) were small enough for complete analysis.
|
||||
Android artifacts (~115–123 MB) indicate widespread failures likely sharing a common root cause.
|
||||
|
||||
---
|
||||
|
||||
## Common Root Cause Patterns to Look For First
|
||||
|
||||
When analyzing a new build, scan for these high-frequency patterns before deep-diving individual ports:
|
||||
|
||||
| Pattern | Indicator in logs | Likely cause |
|
||||
|---|---|---|
|
||||
| `No module named 'pipes'` or similar Python import error | Python stdlib change | Python version upgrade on CI |
|
||||
| `fatal error: experimental/coroutine` | Many Linux ports | GCC 14 / compiler image upgrade |
|
||||
| `deadline_timer` / `posix_time` | Boost-dependent ports | Boost.ASIO API break |
|
||||
| `error: unrecognized command-line option` | Configure-time test | Wrong compiler flags for toolchain |
|
||||
| `FAILED: [code=127]` | Many compilation units | Compiler not in PATH (Docker image change) |
|
||||
| `math cannot parse the expression: ""` | CMake configure | Empty variable in math() — missing guard |
|
||||
| `Cannot open include file: 'sys/socket.h'` | Win + POSIX code | Missing WIN32 socket porting |
|
||||
| `must install xorg-macros` | autotools ports | CI image missing xorg-dev package |
|
||||
| Build truncated, no error message | OOM or timeout | Use `DISABLE_PARALLEL` or check resources |
|
||||
| Many ports → same dependency fails | dep chain | Find root dep; rest are downstream casualties |
|
||||
|
|
@ -0,0 +1,361 @@
|
|||
# vcpkg CI Failure Patterns Reference
|
||||
|
||||
This reference catalogues common failure patterns found in vcpkg CI failure log artifacts. Use these patterns to triage and classify failures when analyzing build output.
|
||||
|
||||
---
|
||||
|
||||
## Log File Structure
|
||||
|
||||
Each failure log (`*.log`) in the `"failure logs for {triplet}"` artifact contains the full vcpkg install output for a single port. The log typically follows this structure:
|
||||
|
||||
```
|
||||
-- Downloading <url>...
|
||||
-- Extracting source...
|
||||
-- Applying patches...
|
||||
-- Using cached binary package. ← binary cache hit (may skip build)
|
||||
-- Building <port>:<triplet>...
|
||||
-- Configuring...
|
||||
-- Building... ← compiler output here
|
||||
-- Installing...
|
||||
-- Running tests... ← if test feature enabled
|
||||
-- Completed.
|
||||
|
||||
error: building <port>:<triplet> failed with: BUILD_FAILED
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Category 1: Dependency Chain Failures
|
||||
|
||||
**Symptom**: The port itself did not fail — a dependency failed first.
|
||||
|
||||
**Log indicators:**
|
||||
```
|
||||
-- Building dependency-name[core]:x64-windows... failed
|
||||
error: package dependency-name:x64-windows is not installed
|
||||
```
|
||||
|
||||
or more explicitly:
|
||||
```
|
||||
error: building portname:x64-windows failed with: BUILD_FAILED
|
||||
... the dependency 'depname:x64-windows' failed to install
|
||||
```
|
||||
|
||||
**Triage action:**
|
||||
- Identify the root failing dependency (the one that failed first in the log)
|
||||
- All other ports in this chain are "downstream casualties"
|
||||
- Fix the root dependency; downstream failures should resolve automatically
|
||||
- In the report, list only the root dependency as a regression; collapse others with a note
|
||||
|
||||
**How to find the root:**
|
||||
- Sort failure logs by time or by name
|
||||
- A port whose own build commands (not just dependency resolution) fail is the root
|
||||
- If `portA.log` shows `error: package portB is not installed` and `portB.log` shows actual compiler output, portB is the root
|
||||
|
||||
---
|
||||
|
||||
## Category 2: CMake Configuration Failures
|
||||
|
||||
**Symptom**: `cmake --build` stage fails before any source is compiled.
|
||||
|
||||
**Log indicators:**
|
||||
```
|
||||
CMake Error at CMakeLists.txt:42 (find_package):
|
||||
By not providing "FindXYZ.cmake" in CMAKE_MODULE_PATH this project has
|
||||
requested CMake to find a package configuration file provided by "XYZ",
|
||||
but CMake did not find one.
|
||||
|
||||
CMake Error: Could not find a package configuration file provided by "XYZ"
|
||||
with any of the following names:
|
||||
XYZConfig.cmake
|
||||
xyz-config.cmake
|
||||
```
|
||||
|
||||
**Common root causes:**
|
||||
- A dependency is not exposing its CMake targets correctly
|
||||
- A port's `vcpkg.cmake` or `vcpkg-cmake-config` integration is broken
|
||||
- A `find_package()` call in the upstream CMakeLists.txt uses a non-standard config name
|
||||
|
||||
**Other CMake configure patterns:**
|
||||
```
|
||||
-- The CXX compiler identification is unknown ← toolchain issue (rare in CI)
|
||||
CMake Error: Generator: ... not found ← MSBuild/Ninja not available
|
||||
CMake Error (cmake_policy): ... ← policy violation
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Category 3: Compiler Errors
|
||||
|
||||
**Symptom**: Source code fails to compile.
|
||||
|
||||
### MSVC (Windows)
|
||||
```
|
||||
error C2065: 'identifier': undeclared identifier
|
||||
error C2039: 'member': is not a member of 'class'
|
||||
error C3861: 'function': identifier not found
|
||||
error C4996: 'function': This function may be unsafe ← treated as error with /WX
|
||||
fatal error C1083: Cannot open include file: 'header.h'
|
||||
```
|
||||
|
||||
### Clang (macOS, Linux)
|
||||
```
|
||||
error: use of undeclared identifier 'name'
|
||||
error: no member named 'member' in 'class'
|
||||
error: 'header.h' file not found
|
||||
error: unknown type name 'type_name'
|
||||
```
|
||||
|
||||
### GCC (Linux)
|
||||
```
|
||||
error: 'name' was not declared in this scope
|
||||
error: invalid use of incomplete type
|
||||
error: 'header.h': No such file or directory
|
||||
```
|
||||
|
||||
**Root cause categories:**
|
||||
- **C++ standard incompatibility**: Code uses features not available in the configured standard (C++14/17/20)
|
||||
- **Missing Windows includes**: `#include <windows.h>` missing or wrong order
|
||||
- **API deprecation**: Uses a function/class removed in a newer version of a dependency
|
||||
- **Compiler flag conflict**: vcpkg sets `-Werror` or `/WX`; warning-as-error triggers on upstream code
|
||||
|
||||
---
|
||||
|
||||
## Category 4: Linker Errors
|
||||
|
||||
**Symptom**: Compilation succeeds but linking fails.
|
||||
|
||||
### MSVC
|
||||
```
|
||||
error LNK2019: unresolved external symbol "__declspec(dllimport) ..." referenced in function "..."
|
||||
error LNK2001: unresolved external symbol
|
||||
error LNK1120: N unresolved externals
|
||||
```
|
||||
|
||||
### GCC/Clang
|
||||
```
|
||||
undefined reference to `function_name'
|
||||
ld: symbol(s) not found for architecture arm64
|
||||
```
|
||||
|
||||
**Root cause categories:**
|
||||
- **Missing `__declspec(dllexport)`**: Library exports are missing for DLL builds
|
||||
- **Static vs. dynamic mismatch**: Port links against static lib but needs dynamic (or vice versa)
|
||||
- **Missing dependency in vcpkg.json**: Library calls into another library not declared as a dependency
|
||||
- **Symbol visibility**: On Linux/macOS, symbols not exported with `__attribute__((visibility("default")))`
|
||||
|
||||
---
|
||||
|
||||
## Category 5: SHA512 Hash Mismatch
|
||||
|
||||
**Symptom**: Download succeeds but hash verification fails.
|
||||
|
||||
```
|
||||
error: File does not have the expected hash:
|
||||
url: https://github.com/owner/repo/archive/v1.2.3.tar.gz
|
||||
expected: abc123...
|
||||
actual: def456...
|
||||
```
|
||||
|
||||
**Root causes:**
|
||||
- **Upstream archive changed**: The upstream author re-tagged or replaced the release archive (mutable tags, force-push)
|
||||
- **Mirror cache stale**: vcpkg asset cache has an old version of the file
|
||||
- **Port hash not updated**: A PR updated the version but forgot to recalculate SHA512
|
||||
|
||||
**Triage action**: Recalculate hash with:
|
||||
```bash
|
||||
vcpkg install portname --no-binarycaching
|
||||
```
|
||||
The error message will contain the correct new hash.
|
||||
|
||||
---
|
||||
|
||||
## Category 6: Download / Network Failures
|
||||
|
||||
**Symptom**: vcpkg cannot download the source archive.
|
||||
|
||||
```
|
||||
error: Failed to download https://example.com/archive.tar.gz
|
||||
error: curl: (22) The requested URL returned error: 404
|
||||
error: curl: (6) Could not resolve host: example.com
|
||||
```
|
||||
|
||||
**Root causes:**
|
||||
- **URL moved**: Upstream deleted or moved the release (common with GitHub releases being retracted)
|
||||
- **CI network issue**: Transient connectivity problem (likely if only 1–2 ports fail this way, or a retry succeeds)
|
||||
- **Domain changed**: Package moved to a new hosting location
|
||||
|
||||
**Triage action**: Check if the URL is still valid. If transient, re-run the build.
|
||||
|
||||
---
|
||||
|
||||
## Category 7: Post-Build Check Failures
|
||||
|
||||
**Symptom**: Build and install succeed, but vcpkg's post-install checks fail.
|
||||
|
||||
```
|
||||
error: The following files are not installed:
|
||||
share/portname/copyright
|
||||
|
||||
error: Found forbidden pattern in installed file:
|
||||
include/portname/config.h: #define PORTNAME_EXPORTS
|
||||
|
||||
error: Usage of deprecated vcpkg function 'vcpkg_apply_patches'
|
||||
```
|
||||
|
||||
**Common post-build checks:**
|
||||
- Copyright file must exist at `share/{portname}/copyright`
|
||||
- No `.pdb` files in release packages (debug-only)
|
||||
- Headers must be in `include/`, not `include/{portname}/include/`
|
||||
- CMake config files in `share/{portname}/` not `lib/cmake/`
|
||||
- No absolute paths in installed CMake files
|
||||
|
||||
---
|
||||
|
||||
## Category 8: Test Failures
|
||||
|
||||
**Symptom**: The port itself builds and installs successfully, but its tests fail.
|
||||
|
||||
```
|
||||
Test #1: my_test ... FAILED
|
||||
The following tests FAILED:
|
||||
1 - my_test (Failed)
|
||||
```
|
||||
|
||||
or in xUnit format (from test results API):
|
||||
```xml
|
||||
<testcase name="portname:x64-windows" ...>
|
||||
<failure message="Test failed: ..." />
|
||||
</testcase>
|
||||
```
|
||||
|
||||
**Triage action:**
|
||||
- Check whether the test passes on other triplets (may be platform-specific)
|
||||
- Check if this is a flaky test (re-run to confirm)
|
||||
- Check if the test was previously failing (baseline)
|
||||
|
||||
---
|
||||
|
||||
## Category 9: Formatting / Manifest Check Failures
|
||||
|
||||
**Symptom**: The `"format.diff"` artifact is present and non-empty.
|
||||
|
||||
This is not a port build failure but a CI check failure. The `format.diff` artifact contains a unified diff showing:
|
||||
- `vcpkg.json` manifest files that need formatting via `vcpkg format-manifest`
|
||||
- Baseline files (`ci.baseline.txt`) that need formatting via `vcpkg format-feature-baseline`
|
||||
- Version database files that need updating via `vcpkg x-add-version`
|
||||
|
||||
**Triage action**: Apply the diff, or run the formatting commands locally:
|
||||
```bash
|
||||
./vcpkg format-manifest --all
|
||||
./vcpkg format-feature-baseline scripts/ci.baseline.txt
|
||||
./vcpkg x-add-version --all
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Category 10: Build Timeout
|
||||
|
||||
**Symptom**: Job exceeds the 2-day timeout limit (rare).
|
||||
|
||||
```
|
||||
##[error]The job running on agent ... has exceeded the maximum execution time of 2880 minutes.
|
||||
```
|
||||
|
||||
**Triage action**: Almost always an infinite loop or hang in the build system. Check the last lines of the log for the hanging operation.
|
||||
|
||||
---
|
||||
|
||||
## Category 11: File Conflicts
|
||||
|
||||
**Symptom**: The port installs files that conflict with files already installed by another port. This failure is **only visible in the "Test Modified Ports" step log** — it does NOT produce a failure log artifact.
|
||||
|
||||
```
|
||||
REGRESSION: kf6i18n:x64-windows failed with FILE_CONFLICTS. If expected, add kf6i18n:x64-windows=fail to .../ci.baseline.txt.
|
||||
```
|
||||
|
||||
The error in the step log reads (before the REGRESSION summary line):
|
||||
```
|
||||
error: File conflicts:
|
||||
C:\path\to\installed\x64-windows\bin\some-tool.exe → installed by portA and portB
|
||||
C:\path\to\installed\x64-windows\include\shared.h → installed by portA and portB
|
||||
```
|
||||
|
||||
**Where to find it**: In the "*** Test Modified Ports" task log for the affected job (not in any artifact ZIP).
|
||||
|
||||
**Triage action**:
|
||||
- Identify which two ports are claiming the same installed files
|
||||
- Usually caused by: a new port that duplicates files from an existing one, or a port that started installing an additional binary that conflicts
|
||||
- Fix: rename the conflicting file, split the port, or add `conflicts` to the port manifest
|
||||
|
||||
---
|
||||
|
||||
## Category 12: Missing From Baseline (Unexpected Pass)
|
||||
|
||||
**Symptom**: A port that is listed as `fail` in `ci.baseline.txt` now passes. This is reported as a regression only in the step log:
|
||||
|
||||
```
|
||||
REGRESSION: portname:x64-windows failed with MISSING_FROM_BASELINE.
|
||||
```
|
||||
|
||||
**Triage action**: Remove the `portname=fail` entry from `scripts/ci.baseline.txt` — the port is fixed.
|
||||
|
||||
The file `scripts/ci.baseline.txt` in the repository root controls which ports are expected to fail.
|
||||
|
||||
**Format:**
|
||||
```
|
||||
# Comment lines start with #
|
||||
portname=fail # will skip in PR CI, attempt in scheduled
|
||||
portname=skip # never built in CI
|
||||
portname=pass # (same as not listed) must succeed
|
||||
```
|
||||
|
||||
**Triplets covered by CI baseline:**
|
||||
- `arm-neon-android`
|
||||
- `arm64-android`
|
||||
- `arm64-osx`
|
||||
- `arm64-windows`
|
||||
- `arm64-windows-static-md`
|
||||
- `x64-android`
|
||||
- `x64-linux`
|
||||
- `x64-osx`
|
||||
- `x64-uwp`
|
||||
- `x64-windows`
|
||||
- `x64-windows-static`
|
||||
- `x64-windows-static-md`
|
||||
- `x86-windows`
|
||||
|
||||
**Important**: Baseline entries apply to all triplets unless a triplet-specific entry exists (not currently supported; all triplet failures for a port use the same baseline entry).
|
||||
|
||||
---
|
||||
|
||||
## Regression Severity Levels
|
||||
|
||||
Use these levels when reporting failures:
|
||||
|
||||
| Level | Criteria | Action |
|
||||
|---|---|---|
|
||||
| 🔴 **Critical** | Core port (boost, openssl, curl, zlib, cmake) or many dependents fail | Immediate fix required |
|
||||
| 🟠 **High** | Popular port fails on multiple triplets | Fix before merge |
|
||||
| 🟡 **Medium** | Single port fails on 1–2 triplets | Fix or add to baseline |
|
||||
| 🟢 **Low** | Port already in baseline, or transient failure | No immediate action |
|
||||
| ℹ️ **Info** | Formatting/version file issues | Easy to fix with automated tools |
|
||||
|
||||
---
|
||||
|
||||
## Common vcpkg CI Triplet Notes
|
||||
|
||||
| Triplet | Notes |
|
||||
|---|---|
|
||||
| `x64-windows` | Most common; MSVC, dynamic linking |
|
||||
| `x64-windows-static` | MSVC, static linking (`/MT`) |
|
||||
| `x64-windows-static-md` | MSVC, static linking (`/MD`) |
|
||||
| `arm64-windows` | Cross-compiled on x64 Windows; run tests on separate ARM hardware |
|
||||
| `x64-linux` | Ubuntu in Docker; GCC or Clang |
|
||||
| `arm64-linux` | Ubuntu ARM64 in Docker |
|
||||
| `arm64-osx` | macOS ARM (Apple Silicon); Clang |
|
||||
| `x64-osx` | macOS x86_64; Clang |
|
||||
| `x64-android` | Cross-compiled; Android NDK Clang |
|
||||
| `arm64-android` | Cross-compiled; Android NDK Clang |
|
||||
| `arm-neon-android` | Cross-compiled; Android NDK Clang |
|
||||
| `x64-uwp` | Universal Windows Platform; WinRT restrictions |
|
||||
Loading…
Reference in New Issue