Integrace

CI/CD přes API

Aktualizováno: 22. září 2026 Pro koho: vývojář Tarif: Enterprise

Nasazení, které rozbije měření, se nejlíp chytá dřív, než se dostane na produkci. API umí přehrát uložené cesty proti náhledu konkrétní změny, porovnat výsledek s očekávaným stavem a vrátit jednoznačné „prošlo / neprošlo“, podle kterého CI job skončí. Tenhle návod popisuje, jak ten tok postavit a na čem se obvykle zasekne.

Celý postup má čtyři kroky: spustit, počkat, vyhodnotit bránu a případně vydat SARIF nebo komentář.

POST · 202 /targets/{id}/scans {"url": náhled} GET · ČEKÁNÍ /scans/{id}?wait=120 status není konečný ∨ settled = false BRÁNA · NEBO gate.passed ?gate={…} false → exit 1 SARIF 2.1.0 ?format=sarif POST · KOMENTÁŘ …/explain
Spuštění vrátí id skenu. Čekání se opakuje, dokud sken neskončí a jeho nálezy nejsou uložené. Brána rozhodne o výsledku jobu, SARIF a komentář jsou jen výstupy.

GitHub App, akce, nebo vlastní volání

Na GitHubu máte tři cesty a všechny stojí na stejném API:

  • GitHub App (kontrola pull requestu) se nastaví v dashboardu a do repozitáře nic nepřidáváte. Pravidlo je pevné: hlásí jen přímé změny dataLayer a blokuje jen kritické nálezy.
  • Kompozitní akce analyticsproof běží ve vašem workflow. Zkopírujete ji do repozitáře jako .github/actions/analyticsproof a zavoláte řádkem uses:. Workflow, které k ní patří, je v receptech pro CI. Proti náhledu přehraje všechny cesty, které plán dovolí spustit (pozastavené vynechá), použije stejné pevné pravidlo, zapíše soubor SARIF a komentář k pull requestu.
  • Vlastní volání API funguje v jakémkoli CI a pravidlo brány si určíte sami. Čekání a vyhodnocení si ale napíšete sami.

Stačí vám výchozí pravidlo na GitHubu? Vezměte App. Chcete mít kontrolu ve workflow nebo výsledky v code scanningu? Akci. Jiné CI nebo jiné pravidlo znamená API.

Klíč

Klíč vytvoří editor nebo vyšší role v Nastavení projektu › API klíče. Pro CI stačí dvě oprávnění: „Spouštět scany“ a „Číst scany a výsledky“. Víc klíč nepotřebuje. Vypršení je volitelné a celý klíč uvidíte jen jednou, hned po vytvoření.

Klíč začíná ap_live_ a posílá se v hlavičce Authorization: Bearer … nebo X-API-Key: …. Uložte ho jako maskovanou proměnnou nebo secret, nikdy do repozitáře. API je v plánu Enterprise. Když projekt Enterprise nemá, platný klíč dostane 403 tier_forbidden. Podrobnosti jsou v referenci API.

Spuštění proti náhledu

Sken se spouští přes POST /api/v1/targets/{id}/scans. Id testu najdete přes GET /api/v1/targets. Když do těla pošlete url s adresou náhledu, běží sken jako dry-run: vzniknou rozdíly a výsledek pro bránu, ale do cesty se nic nezapíše. Očekávaný stav, hlídané nástroje ani historie regresí se nezmění. Bez url spustí stejné volání běžný sken uloženého testu.

U testu webu samotné url na přehrání cesty nestačí. Bez typu skenu spustí výchozí sken testu, tedy compliance audit náhledu. Jednu cestu přehrajete s "scanType": "web_datalayer" a volitelně s journeyId. Bez něj se použije první cesta testu, kterou plán dovolí spustit. Odpověď pak obsahuje jedno scanId a jeho pollUrl.

S "journeys": "all" se přehrají všechny cesty testu, které plán dovolí spustit, a maxJourneys jejich počet omezí. Odpověď má pak jiný tvar: nemá scanId na nejvyšší úrovni, jen pole scans se scanId a pollUrl pro každou cestu a pole failed s cestami, které se nepodařilo spustit. Skript musí počkat na každé scans[].pollUrl, stejně jako to dělá kompozitní akce. Neprázdné failed by mělo shodit job.

Dvě věci, které se vyplatí nastavit hned:

  • Hlavička Idempotency-Key. Opakovaný pokus se stejným klíčem nespustí druhý sken, ale vrátí ten první. Klíč označuje jeden konkrétní požadavek: test, výběr cest a adresu náhledu. Při opakování téhož požadavku ho neměňte a neodvozujte ho jen z hashe commitu. Stejný commit se může nasadit na druhý náhled nebo zkontrolovat s jinými cestami a s klíčem jen z commitu byste dostali zpátky starý sken.
  • Země skenu. Náhled se skenuje ze země, kterou jste zvolili při vytvoření testu. Pokud je náhled za IP allowlistem, povolte adresu této země.

Viz dry-run v referenci.

Čekání na výsledek

Stav skenu čtete přes GET /api/v1/scans/{id}?wait=N. Server drží požadavek otevřený, dokud sken neskončí a nejsou uložené jeho nálezy, nejdéle N sekund. Strop je 300 sekund. Praktičtější je čekat kolem 120 sekund a dotaz opakovat, protože dlouhá spojení ráda přeruší proxy nebo runner.

Sken skončil, když je jeho status jeden z těchto:

Hodnota v API V dashboardu
completed Dokončeno
failed Selhalo
cancelled Zrušeno
broken_step Přerušený krok
no_data Bez dat

Opakujte, dokud nebude status konečný a zároveň settled rovno true. settled: false znamená, že vám vypršelo čekání ve chvíli, kdy se nálezy teprve ukládaly. Stačí se zeptat znovu.

Jeden klíč smí mít najednou nejvýš pět čekajících dotazů. Šestý dostane 429 too_many_long_polls. Pokud spouštíte víc cest najednou, čtěte je postupně, ne paralelně.

Návrh brány

Bránu předáte při čtení skenu jako ?gate= s URL-kódovaným JSONem. Predikáty se sčítají přes „nebo“: brána selže, když platí kterýkoli z nich. Všechny predikáty jsou v referenci. Pro náhled a dataLayer je rozumný začátek tohle:

{ "failOnSeverity": "critical", "failOnBrokenStep": true }

Pravidla, která z tabulky predikátů nevyčtete:

  • Sken ve stavu failed, cancelled nebo no_data bránou neprojde nikdy, ať nastavíte cokoli. Sken bez dat nedostane ani falešné „skóre pod limitem“, má vlastní kód.
  • Přerušený krok ve výchozím stavu bránu neshodí. Skončí jen jako varování a rozdíly toho skenu se nevyhodnotí. Pokud změna rozbije tlačítko v košíku, brána bez failOnBrokenStep projde. Proto ho doporučujeme zapnout.
  • Posun události o jeden krok je v toleranci a bránu nikdy neshodí.
  • Když cesta ještě nemá očekávaný stav, predikáty nad dataLayer nemají s čím porovnávat. Nemůžou selhat a ve warnings přijde datalayer_gate_no_baseline. Vyplatí se na tohle varování v CI reagovat.
  • Bez ?gate= odpověď žádnou bránu neobsahuje. Skript proto musí brát chybějící gate.passed jako neúspěch, ne jako úspěch.
  • minComplianceScore hodnotí compliance skóre, takže patří k compliance testu. Cestu hodnotí rozdíly.

Parametr scope=direct-datalayer zúží rozdíly na to, co web posílá přímo do window.dataLayer. Požadavky, které z toho vyrábějí GA4 a další nástroje, zůstanou v dashboardu, ale bránu neovlivní. Stejné zúžení používá App i akce. Porovnává se přítomnost událostí a parametrů a jejich JavaScriptový typ, ne hodnoty. Výjimkou jsou signály souhlasu, u kterých je změna hodnoty samostatný nález.

SARIF a komentář

S ?format=sarif vrátí skončený sken dokument SARIF 2.1.0. Sken, který ještě neskončil, vrátí běžný JSON, takže SARIF si stahujte až po odpovědi JSON, ve které je status konečný a zároveň settled rovno true. Dokud se nálezy ukládají, SARIF by mohl být neúplný. SARIF obsahuje stejné nálezy, které posuzuje brána, a navíc události posunuté o jeden krok, které brána toleruje (kritické jako error, varování jako warning, informace jako note). Verdikt v něm není. O výsledku jobu dál rozhoduje gate.passed. Aby soubor odpovídal bráně, přidejte stejný scope.

Komentář k pull requestu nebo merge requestu vám připraví POST /api/v1/scans/{id}/explain. Vrátí vysvětlení rozdílů v běžné řeči bez hodnot parametrů. Před koncem skenu odpoví 409 scan_not_terminal.

Příklad: GitLab CI a jiná CI

Postup je stejný v každém CI, které umí curl a jq:

  1. Klíč a id testu uložte jako maskované proměnné CI.
  2. Job zařaďte až za nasazení náhledu, aby znal jeho adresu.
  3. Spusťte dry-run s url, "journeys": "all" a Idempotency-Key složeným z ID testu, výběru cest a adresy náhledu. Uložte si všechna pollUrl ze scans a neprázdné failed ukončete chybou.
  4. Každý sken čtěte s wait=120, bránou a scope, dokud nebude konečný a zároveň settled rovno true. Celé čekání omezte timeoutem jobu.
  5. Job selže, když gate.passed u kterékoli cesty není true. Do logu vypište gate.failures a warnings.
  6. Pokud CI SARIF nezobrazuje, uložte ho jako artefakt jobu.

Hotový skript pro GitLab je v receptech pro CI. Spouští běžný sken uloženého testu a čte jedno scanId. Pro náhled jedné cesty pošlete tělo {"url": "…", "scanType": "web_datalayer"}, do Idempotency-Key přidejte adresu náhledu a minComplianceScore vyměňte za bránu pro cestu z části výše. Zbytek skriptu zůstane, jak je. Pro "journeys": "all" potřebuje smyčku přes scans[], protože odpověď scanId nemá.

Chyby a co s nimi

Kód Obvyklá příčina Co udělat
missing_credentials, invalid_key Secret se do jobu nedostal nebo je oříznutý Zkontrolujte proměnnou a hlavičku
key_revoked, key_expired Klíč je zrušený nebo prošlý Vytvořte nový a vyměňte secret
tier_forbidden Projekt nemá Enterprise API je jen v Enterprise
insufficient_scope Klíči chybí oprávnění Spouštění potřebuje „Spouštět scany“, čtení „Číst scany a výsledky“
journey_required Test nemá cestu, kterou by přehrál Nahrajte cestu
journey_sleeping Cesta je nad limitem plánu Změňte pořadí cest nebo plán
scan_in_progress Běžný sken testu už běží Počkejte, nebo pošlete url pro dry-run
idempotency_conflict Stejný klíč pro jiný druh požadavku Pro jiné tělo použijte nový klíč
rate_limited, too_many_long_polls Víc než 60 požadavků za minutu nebo pět čekání najednou Počkejte podle Retry-After

Kódy v gate.failures nejsou chyby API, ale důvody, proč brána neprošla. Popis všech kódů najdete v přehledu chyb.



Našli jste v návodu chybu, nebo vám v něm něco chybí? Napište nám

Všechny návody