CI/CD Runs & External Signals
Baby-step guide to wire your pipeline to TestNeo, see Recent Runs with a full Report, and optionally post External CI signals (build / security / foreign smoke) so Release Readiness can show “also ran” — without confusing the two.
- Open /web/ci → Integration → Generate an API key.
- Update your repo: add the workflow from Integration (Setup A) so Recent Runs + Report appear.
- Optional — Update other jobs (CodeQL, build, Jenkins): add the copy-paste
POST(Setup B) for External signals. - Refresh /web/ci — Runs at the top, External signals below. Not the same rows.
CI_8614… under Recent Runs is
not the same row as External CI signals below it. They are two data pipes on one page.
Runs = TestNeo executed your suite. External = another system finished and told TestNeo via HTTP.
Problem we solve
- Teams already run builds, security scans, and tests in GitHub Actions / Jenkins — but the ship story is scattered across tabs.
- You need one place that shows: “Did TestNeo run our suite?” and “Did other checks also finish?”
- Release owners want a simple Also ran in CI line next to Release Readiness — without turning TestNeo into a log warehouse.
What TestNeo does: execute your NLP/API tests from CI (Runs + Report), accept small receipts from any pipeline (External signals), and optionally soft-weight those receipts into the release gate.
Read this first: two pipes
Recent Runs (CI_…) | External CI signals | |
|---|---|---|
| Who runs? | TestNeo agent / cloud runner | Jenkins, GHA, CodeQL, Snyk, your script — their runner |
| What runs? | Your TestNeo tests (tags / folder) | Whatever their job is (image build, security scan, foreign smoke) |
| How it hits TestNeo | Trigger job → download tests → upload results | One POST /release-readiness/ci-evidence with API key |
| What you see | Pass/fail counts + Report link | Status, kind, summary, optional console URL / counts |
| Agent online? | Needed if jobs run on a self-hosted agent | Not required — receipt only |
| Connected to each other? | No automatic link today. Same page for comparison; optional later correlate by sha. |
|
Where in the product
| Place | URL | Use for |
|---|---|---|
| CI/CD · Runs + External signals | /web/ci or /web/projects/<id>/ci |
Setup keys, see jobs, post/view receipts |
| Job Report | /web/ci/report/CI_… |
Per-test detail for a TestNeo run |
| Release Readiness | /web/release-readiness |
“Also ran in CI” + optional Soft-weight external CI |
| Analytics | /web/analytics |
Trends over time (not a substitute for Report) |
Setup A — Recent Runs (TestNeo executes your suite)
Goal: push to GitHub → see a row like CI_8614… with 10✓ / 0✗ and a Report button.
Open CI/CD in the app
Go to app.testneo.ai/web/ci → select your project → open the Integration tab.
Generate an API key
Click Generate API Key, name it (e.g. GitHub Actions), copy the tn_… value once.
Store it as a GitHub Actions secret named TESTNEO_API_KEY.
Add secrets / variables
In your CI platform (GitHub → Settings → Secrets and variables):
| Name | Example |
|---|---|
TESTNEO_API_KEY | tn_… from step 2 |
TESTNEO_PROJECT_ID | Your project number (e.g. 8) |
TESTNEO_SERVER | https://app.testneo.ai (or your self-hosted API base) |
Update your repo with the workflow
On the same Integration tab, pick GitHub Actions (or Jenkins / GitLab) and copy the generated workflow into
.github/workflows/testneo.yml (or your Jenkinsfile). Tag tests in TestNeo with
@smoke / @regression so the workflow can select them.
Push, then refresh Recent Runs
Push to the branch that triggers the workflow. Refresh CI/CD → Runs.
You should see Job ID, Status, Tests (✓ / ✗), Branch, Duration, and Report.
Setup B — External CI signals (receipt only)
Goal: after CodeQL / image build / foreign Jenkins smoke finishes, TestNeo shows a row under External CI signals and on Release Readiness Also ran in CI.
No tech-stack limit. Anything that can POST JSON with a Bearer API key works:
GitHub Actions, Jenkins, GitLab, Azure DevOps, CodeQL, Snyk, Sonar, Trivy, or a shell script.
Reuse the same API key
Use TESTNEO_API_KEY from Setup A (or generate another key on Integration). Auth header:
Authorization: Bearer tn_… (not X-API-Key for this endpoint).
Update the external job — add a last step
Example — after CodeQL (or any job) in GitHub Actions:
- name: Tell TestNeo about this check
if: always()
env:
TESTNEO_API_KEY: ${{ secrets.TESTNEO_API_KEY }}
TESTNEO_SERVER: ${{ vars.TESTNEO_SERVER }}
run: |
STATUS=pass
[ "${{ job.status }}" = "failure" ] && STATUS=fail
curl -fsS -X POST "$TESTNEO_SERVER/api/web/v1/release-readiness/ci-evidence" \
-H "Authorization: Bearer $TESTNEO_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"project_id\": ${{ vars.TESTNEO_PROJECT_ID }},
\"provider\": \"github_actions\",
\"kind\": \"security\",
\"status\": \"$STATUS\",
\"external_ref\": \"actions/runs/${{ github.run_id }}\",
\"environment_name\": \"Staging\",
\"sha\": \"${{ github.sha }}\",
\"summary\": \"CodeQL finished with status $STATUS\",
\"details_url\": \"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\",
\"payload\": { \"source\": \"codeql\" }
}"
Confirm in the UI
Open /web/ci → scroll to External CI signals (under Recent Runs),
or open Release Readiness → Also ran in CI.
Demo without a pipeline: click Record signal on the CI page.
Evidence field reference
| Field | Required? | What to put |
|---|---|---|
project_id | Yes | TestNeo project number |
provider | Yes | github_actions, jenkins, gitlab, … |
kind | Yes | build, smoke, security, e2e, … |
status | Yes | pass / fail / warn / skipped |
external_ref | Yes | Their job id, e.g. actions/runs/902 |
environment_name | No | QA, Staging, … |
summary | No | One human line (“CodeQL: 2 medium findings”) |
sha | No | Commit hash (shown short in UI) |
details_url | No | Link to their console (makes Open CI console work) |
payload | No | Small extras: passed/failed/total — not full logs |
Tip: If TestNeo already ran the suite, use Recent Runs → Report. Do not also Record signal for the same suite unless you intentionally want a duplicate billboard.
How to read /web/ci
- Recent Runs (top) — TestNeo jobs. Click Report for per-test detail.
- “How to read this page” — short reminder of the two pipes.
- External CI signals (bottom) — receipts. Click a row for detail; Open CI console only if
details_urlis a real external URL.
Filter Failed on Runs to focus on broken TestNeo jobs. External fails/warns show as status badges in the signals table.
How to read a Report
From Recent Runs → Report opens /web/ci/report/CI_….
- Use this for which tests passed/failed, duration, and triage of a TestNeo execution.
- For trends across many days, use Analytics — not the External signals panel.
- External signal detail will never replace Report unless that foreign system posted rich
payloadcounts (still no TestNeo step video).
Not observability
External signals are a release billboard, not Datadog / logs / APM.
| We store | We do not scrape |
|---|---|
| Status, kind, summary, optional counts, console link | Full job logs, traces, metrics streams |
Deep analysis stays in CodeQL / Jenkins / your observability tool via details_url. TestNeo answers: “did that check also finish for this ship?”
Optional soft gate
By default, external receipts are display-first — they do not change confidence.
- Open Release Readiness → select a bundle → check Soft-weight external CI → Evaluate gate.
- Critical fails (e.g. smoke/security/e2e
fail) can demote PASS; securitywarncan demote to WARN. - Full gate policies (BLOCK PRs, min confidence): see Release Intelligence · CI/CD Gate.
FAQ & troubleshooting
| Symptom | What to check |
|---|---|
| Recent Runs empty | Integration key + workflow pushed? Job triggered? Agent online if using self-hosted runner? |
| External signals empty | Did the pipeline POST? Auth Bearer tn_…? Correct project_id? Try Record signal once. |
403 Not authenticated | Use Authorization: Bearer, not X-API-Key, for this endpoint. |
| No Open CI console | Set details_url to a real GitHub/Jenkins URL (not an in-app /web/… link). |
Is CI_… linked to External? | No — different tables. Correlate manually by commit SHA if needed. |
| Agent Online = 0 | OK for External signals. Only matters for agent-backed Recent Runs. |