Core/Dash CI/CD -suorituskykytarkistukset

Pysäytä raskas sivu ennen julkaisua. Anna sitten oikean käyttäjädatan kertoa, mitä kukin julkaisu teki.

Ilmainen kokeilu

Trusted by market leaders · Client results

perionmonarchhappyhorizonsaturnwhowhatwearkpnvpnebaysnvmy work featured on web.devfotocasaloopearplugsnestlenina caremarktplaatsharvardcompareadevintadpg mediaworkivaerasmusmcaleteia

Mikä julkaisu teki siitä hitaamman?

LCP oli kesäkuussa 2,1 sekuntia. Nyt se on 2,9 sekuntia. Teit noiden kahdeksan viikon aikana 40 julkaisua, eikä mikään seurannassasi kerro, mikä niistä oli syyllinen.

Tämä ei ole dataongelma. CoreDash mittaa jo jokaisen sivunlatauksen jokaiselta oikealta vierailijalta. Se ei kuitenkaan pysty yksin päättelemään, mikä puolellasi muuttui tiistaina kello 14.32. Ilman tätä tietoa regressio on vain "jokin hidastui viime kuussa" eikä "v2.4.1 teki tämän". Joudut etsimään syytä muistinvaraisesti, kysyt tiimiltä mitä julkaistiin, ja yleensä luovutat ja optimoit jotain aivan muuta.

CI/CD-integraatio sulkee tämän kuilun kahdesta suunnasta. Ennen julkaisua Core/Dash skannaa esikatseluversiosi ja pysäyttää pipelinen, jos sivu ylittää budjetin. Julkaisun jälkeen jokainen sivunlataus merkitään sivun tarjonneella versiolla, jotta jokaista julkaisua voidaan mitata sen omalla liikenteellä.

Molemmat ovat valinnaisia ja itsenäisiä. Aja toinen, aja molemmat, tai älä kumpaakaan. Kumpikaan ei vaadi sinua muuttamaan riviäkään front-end-koodia tai lisäämään toista skriptiä sivuillesi.

Kaksi tarkistusta yhden julkaisun ympärillä

Nämä kaksi puoliskoa nappaavat eri virheitä. Tämä on syytä ymmärtää, ennen kuin asennat mitään.

Julkaisua edeltävä tarkistus on synteettinen. Se lataa esikatseluversiosi Lighthousessa ja tarkastelee asioita, jotka koskevat itse buildia: kuinka monta tavua sivu siirtää, kuinka paljon skriptiä on, kuinka suuria kuvat ovat ja kuinka monta DOM-solmua on olemassa. Nämä ovat regressioita, jotka ihminen jättää huomaamatta katselmoinnissa. Kukaan ei huomaa diffissä, että uusi hero-kuva on 4 megatavun PNG, tai että markkinointitägi veti 300 kilotavua ylimääräistä JavaScriptiä bundleen.

Julkaisuvertailu on field dataa. Oikeat laitteet, oikeat verkot, oikeat käyttäjät, mitattuna koodin mentyä tuotantoon. Se on ainoa paikka, jossa LCP, INP ja CLS todella ovat olemassa. Synteettinen ajo Googlen infrastruktuurissa ei voi kertoa, että indonesialainen Android-liikenteesi hidastui 900 ms, koska Iowassa sijaitseva datakeskus ei ole Android-puhelin 4G-yhteydellä.

Haluat molemmat, koska kumpikaan ei korvaa toista. Synteettinen mittaus nappaa ilmiselvät virheet aikaisin ja halvalla. Field data kertoo, mitä käyttäjäsi saivat, ja se on ainoa asia, jonka perusteella Google sijoittaa sinut hakutuloksissa.

Ennen julkaisua: julkaisua edeltävä tarkistus

Yksi POST-pyyntö pipelinestasi esikatselu-URL-osoitettasi vasten. Core/Dash ajaa Lighthousen seuratuille sivuillesi kyseisessä esikatselu-originissa, pisteyttää ne olemassa olevia Lighthouse-budjettejasi vasten ja vastaa pass tai breach. Tämä kestää noin 30–45 sekuntia.

Mitä tarkistetaan

Core/Dash ottaa neljä ensimmäistä seurattua Lighthouse-sivua, joilla on budjettirivi, jonka se voi pisteyttää. Se säilyttää jokaisen sivun oman polun, kyselymerkkijonon ja laiteasetuksen, ja vaihtaa hostin lähettämääsi esikatselu-originiin. Tarkistamasi sivu on siis sama reitti, jonka öinen skannauksesi tarkistaa, mutta buildissa jota ei ole vielä julkaistu.

Neljä sivua on katto, ja se on tarkoituksellinen sellainen. Neljä skannausta ajetaan rinnakkain PageSpeed Insights APIa vasten, ja jokaisen enimmäiskesto on 75 sekuntia, jotta yksittäinen hidas sivu ei voi viivästyttää buildiasi.

Mitä pisteytetään ja mitä ei

Vain mittaukset, jotka eivät muutu saman buildin kahden ajon välillä:

PisteytetäänEi pisteytetä
Sivun kokonaiskokoTotal Blocking Time
Kolmannen osapuolen koodin kokoBootup Time
Skriptien kokoMain thread -työ
Kuvien kokoLighthouse-suorituskykypisteet
CSS:n koko
Fonttien koko
Käyttämätön JavaScript
DOM:in koko

Lighthouse-suorituskykypisteet CI:ssä ovat lähellä satunnaislukugeneraattoria. Aja sama muuttumaton sivu viisi kertaa, ja voit nähdä pisteiden heilahtelevan 10 pistettä. Pisteitä hallitsevat CPU-sidonnaiset ajoitukset, eikä auditoinnin ajava kone ole koskaan sama kahdesti. Jos portitat buildisi tällä, saat punaisia pipelineja, jotka eivät merkitse mitään. Tämä opettaa kaikki ajamaan työn uudelleen, kunnes se muuttuu vihreäksi. Se on pahempi kuin ei tarkistusta lainkaan.

Tavut eivät tee näin. Jos buildisi siirtää 1,4 Mt skriptiä tänään ja 1,9 Mt huomenna, se johtuu omasta commitistasi, ei Googlen laitteistosta. Tarkistus pisteyttää siis nämä rivit. Ajoitusmittarit pysyvät siellä minne ne kuuluvat: oikeassa käyttäjädatassa, missä CPU on vierailijan oikea puhelin.

Suodatin toimii budjettirivikohtaisesti. Budjetti, joka sekoittaa molempia tyyppejä, tarjoaa ne rivit, jotka voidaan pisteyttää. Jokainen vastaus listaa, mitä se ohitti ja miksi.

Kutsu sitä pipelinestasi

Luo ensin projektin API-avain (sovelluksessa: projektisi, sitten AI Insights, sitten Connect Your AI) ja tallenna se CI-salaisuuksiisi nimellä COREDASH_API_KEY. Avaimet alkavat cdk_ ja on rajattu yhteen projektiin. Toimiston master-avain (master agency key) hylätään tässä, koska sitä ei ole sidottu projektiin, johon julkaisu voitaisiin liittää.

STATUS=$(curl -sS -o gate.json -w '%{http_code}' -X POST "https://app.coredash.app/api/project/releases/check" \
  -H "Authorization: Bearer $COREDASH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tag":"v1.2.3","origin":"https://preview.example.app"}')

if [ "$STATUS" != "200" ]; then
  echo "Gate call failed with HTTP $STATUS: $(cat gate.json)" >&2
  exit 1
fi

jq -e '.data.check.status != "breach"' gate.json > /dev/null

Älä lyhennä tuota pätkää putkittamalla curlia suoraan jq:hun. Huono avain vastaa 401 ja huono tägi 400, eikä näissä vastauksissa ole data-objektia lainkaan. Jos luet .data.check.status puuttuvalta data-objektilta, saat jq:ssa arvon null. Null ei ole "breach", jolloin putki palauttaa 0. Vanhentunut API-avain näyttäisi täsmälleen onnistumiselta, ja porttisi lakkaisi hiljaisesti toimimasta. HTTP-tilakoodin tarkistus pitää tämän rehellisenä.

Parametrit

KenttäPakollinenKuvaus
tagkylläVersiomerkkijonosi. Kirjaimia, numeroita, . _ / -, enintään 64 merkkiä.
originkylläEsikatselun origin, esimerkiksi https://pr-42.example.app. Vain scheme ja host.
sha, branch, actor, repo, prNumber, runUrleiGit-konteksti. Tallennetaan sovelluksen syvälinkkejä varten. Mikään ohjelmalogiikka ei riipu siitä.

Originin täytyy olla paljas. Polku, kyselymerkkijono, fragmentti tai basic auth -tunnukset URL-osoitteessa palauttavat kaikki 400. Tämä on tarkoituksellista: skanneri kopioi vain schemen ja hostin jokaisen seuratun sivun URL-osoitteeseen. Siten osoitteessa /pr-42/ tarjoiltu esikatselu skannattaisiin hiljaisesti väärissä osoitteissa, ja se ilmoittaisi puhtaan läpäisyn sivuista, joita ei ole olemassa.

Mitä palautuu

Kelvollinen pyyntö vastaa aina HTTP 200. Tuomio on bodyn polussa data.check.status:

TilaMerkitysBuildisi
passJokainen pisteytetty rivi on budjetissaJatka
breachVähintään yksi rivi ylittää budjetinPysäytä
errorYhtäkään sivua ei saatu skannattuaJatka
no-budgetsYhdelläkään seuratulla sivulla ei ole budjettia, jonka tarkistus voisi pisteyttääJatka

Huono tägi tai huono origin vastaa 400, huono tai puuttuva avain vastaa 401. Nämä bodyt sisältävät vain kentät status ja message.

Tarkistus epäonnistuu turvallisesti (fails open) sivukohtaisesti. Jos PageSpeed Insights saa timeoutin yhdellä neljästä sivustasi, kyseinen sivu raportoidaan virheenä ja muut kolme pisteytetään yhä. Buildiasi ei estetä siksi, että Googlella oli huono minuutti. Virhe raportoidaan eikä sitä niellä, joten näet vastauksesta, mitä sivua ei saatu mitattua.

Kaksi muutakin asiaa on hyvä tietää. Esikatselun on oltava saavutettavissa julkisesta internetistä, koska PageSpeed Insights hakee sen Googlen puolelta. Salasanalta suojattua tai IP-sallittua (IP-allowlisted) esikatselua ei voi skannata, eikä tähän ole kiertotietä (jos esikatselusi ovat autentikoinnin takana, aja tarkistus julkista staging-originiä vasten). Lisäksi tarkistus ei koskaan kirjoita tuotannon budjettitaulullesi. Esikatselunumerot pysyvät poissa niistä luvuista, joiden perusteella arvioit tuotantosivuasi.

900x500?text=Pre deploy+Lighthouse+check+card+on+release+detail

Julkaisun jälkeen: kirjaa julkaisu

Kun julkaisu onnistuu, kerro Core/Dashille, että versio meni tuotantoon:

curl -sS -X POST "https://app.coredash.app/api/project/releases/ingest" \
  -H "Authorization: Bearer $COREDASH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tag":"v1.2.3"}'

GitHub Actionsissa, käyttäen git-refiä versiona:

- name: Report release to CoreDash
  if: success()
  env:
    COREDASH_API_KEY: ${{ secrets.COREDASH_API_KEY }}
  run: |
    curl -sS -f -X POST "https://app.coredash.app/api/project/releases/ingest" \
      -H "Authorization: Bearer ${COREDASH_API_KEY}" \
      -H "Content-Type: application/json" \
      -d "{\"tag\":\"${{ github.ref_name }}\"}"

Mikä tahansa CI, joka pystyy ajamaan curlin, toimii. GitLab, Jenkins, CircleCI tai bash-julkaisuskripti jollain palvelimella.

KenttäPakollinenKuvaus
tagkylläSamat säännöt kuin tarkistuksessa. Käytä samaa merkkijonoa, jonka lähetit tarkistukseen.
deployedAteiISO-aikaleima. Oletuksena nyt. Aseta se menneisyyteen kirjataksesi jälkikäteen julkaisun, jonka olet jo tehnyt.
noteseiMitä julkaistiin. Enintään 2000 merkkiä.
sha, branch, actor, repo, prNumber, runUrleiGit-konteksti, sama kuin tarkistuksessa.

Julkaisu on uniikki projektia ja tägiä kohden. Saman tägin lähettäminen uudelleen päivittää olemassa olevan rivin eikä luo uutta. Rollback, joka uudelleenkäyttää versiota, sulautuu siis takaisin alkuperäiseen julkaisuunsa.

Ei pipelinea? Releases-sivulla on Tag deployment -lomake: versio, julkaisuaika ja valinnaiset muistiinpanot. Se luo saman rivin, mutta lähteenä on site eikä ci. Käytä sitä täyttääksesi jo tekemäsi julkaisut jälkikäteen. Se on heikompi vaihtoehto, ja siitä kannattaa olla rehellinen. Se tallentaa vain ne julkaisut, jotka joku muistaa kirjoittaa, ja julkaisuaika on vain niin tarkka kuin heidän muistinsa.

Miten liikenne kohdennetaan julkaisulle

Julkaisun kirjaaminen leimaa sen projektiin nykyiseksi versioksi. Seurantaskriptiäsi tarjoava host lukee leiman ja injektoi tägin tarjoamaansa skriptiin. Tästä hetkestä eteenpäin jokainen sivunlataus kantaa versiota rel-dimensiossa. Skriptin edge-kopio tyhjennetään (purged) Cloudflaresta heti kun leima siirtyy, joten et joudu odottamaan CDN-välimuistin päivittymistä.

Sivusi eivät muutu. Ei build-vaihetta, ei data-attribuuttia jota pitäisi templatettaa sisään, eikä toista SDK:ta.

Jos haluat mieluummin omistaa arvon itse, aseta window.__CWVREL ennen seurantaskriptin latautumista, niin se voittaa injektoidun arvon. Tämä on reitti kokoonpanoille, joissa sovellus tietää oman build-id:nsä, mutta CI ei. Pitäydy oikeassa versiomerkkijonossa. Jos sidot sen pyyntökohtaiseen build-hashiin, saat uuden dimension arvon jokaisella sivunlatauksella. Tämä heikentää jokaista myöhemmin ajamaasi ryhmiteltyä kyselyä.

Mittarit löytävät julkaisunsa tämän tägin kautta, eikä minkään muun. Ei ole olemassa aikaikkunaan perustuvaa fallbackia, jossa Core/Dash arvaisi kahden aikaleiman välisen liikenteen kuuluvan todennäköisesti johonkin julkaisuun. Jos julkaisulla ei ole tägättyä liikennettä, sen rivi näyttää viivoja. Se on rehellinen vastaus, ja se voittaa luvun, joka hiljaisesti lukee edellisen version käyttäjät uuden versiosi ansioksi.

Anna sille noin 200 sivunlatausta ennen kuin odotat tuomiota. Sen alle p75 liikkuu yksittäisten käyttäjien mukaan, ja läpäisy tai hylkäys olisi vain kohinaa.

Tuomiot tulevat niistä RUM-budjeteista, joita ajat jo alerts and notifications -puolella. Julkaisuja varten ei ole erillistä raja-arvojen joukkoa määritettävänä, eivätkä nämä kaksi voi olla eri mieltä keskenään.

Julkaisun tilat

Molemmat puoliskot kirjoittavat samalle julkaisuriville, joten versiolla on elinkaari tarkistetusta julkaistuun:

TilaAsettajaMerkitys
blockedTarkistus, ylityksen (breach) yhteydessäTällä tägillä ei julkaistu mitään
pendingTarkistus, kaikissa muissa tapauksissaLäpäisty, julkaisua ei ole vielä raportoitu
releasedIngest tai sovelluksen lomakeTuotannossa, oikealla julkaisuajalla

Vain released-tilan saavuttaminen leimaa projektin ja tyhjentää seurantaskriptin. Julkaisemattomat rivit näkyvät yhä aikajanalla merkinnällä "Blocked" tai "Awaiting deploy", ilman julkaisuaikaa ja oikeita käyttäjämittareita. Estetty (blocked) rivi kantaa ylittyneitä mittareita, joten vielä viikkoa myöhemmin näet, miksi kyseinen versio ei koskaan mennyt tuotantoon.

Tarkistuksen ajaminen uudelleen tägille, joka on jo julkaistu, tallentaa uuden tuloksen muuttamatta sen tilaa tai julkaisuaikaa. Julkaisuilla, jotka kirjasit ennen tämän ominaisuuden julkaisua, ei ole tilaa lainkaan, ja ne luetaan julkaistuiksi.

Koko prosessi päästä päähän

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # ... build and publish your preview here ...

      - name: Check the preview against budgets
        env:
          COREDASH_API_KEY: ${{ secrets.COREDASH_API_KEY }}
        run: |
          STATUS=$(curl -sS -o gate.json -w '%{http_code}' -X POST \
            "https://app.coredash.app/api/project/releases/check" \
            -H "Authorization: Bearer $COREDASH_API_KEY" \
            -H "Content-Type: application/json" \
            -d '{"tag":"${{ github.ref_name }}","origin":"https://preview.example.app","sha":"${{ github.sha }}","runUrl":"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}')

          if [ "$STATUS" != "200" ]; then
            echo "Gate call failed with HTTP $STATUS: $(cat gate.json)" >&2
            exit 1
          fi

          jq -e '.data.check.status != "breach"' gate.json > /dev/null

      # ... deploy to production here ...

      - name: Report release to CoreDash
        if: success()
        env:
          COREDASH_API_KEY: ${{ secrets.COREDASH_API_KEY }}
        run: |
          curl -sS -f -X POST "https://app.coredash.app/api/project/releases/ingest" \
            -H "Authorization: Bearer ${COREDASH_API_KEY}" \
            -H "Content-Type: application/json" \
            -d "{\"tag\":\"${{ github.ref_name }}\",\"sha\":\"${{ github.sha }}\"}"

Käytä samaa tag-arvoa molemmissa kutsuissa. Tämä sulauttaa tarkistuksen tuloksen ja oikeat käyttäjämittarit yhteen julkaisuun kahden sijaan.

Mitä näet Core/Dashissa

Releases-sivu listaa viimeiset 30 päivää, uusimmat ensin. Jokaisesta julkaisusta näet version, tuliko se CI:stä vai sovelluksesta, julkaisuajan, kunkin Core Web Vitals -mittarin p75-arvon, erotuksen (delta) edelliseen julkaisuun sekä budjetin reaaliaikaisen tilan. Julkaisemattomat versiot istuvat samassa listassa oman tilamerkkinsä (state chip) kanssa.

Release detail asettaa julkaisun koko sivustoa vasten samojen suodattimien alaisuudessa. Julkaisua edeltävän tarkistuksen tulokset ovat ylinnä: yksi rivi skannattua sivua ja budjettiriviä kohden, sekä ohitetut mittarit. Sen alla on reaaliaikainen taulu (live board) jokaisesta RUM-budjetista, jota et ole mykistänyt.

Performance Snapshots -osiossa on Releases-kytkin, joka piirtää julkaisumerkit kaavioihin. Merkit näkyvät vain versioille, jotka oikeasti julkaistiin, joten estetty build ei koskaan näy viivana kaaviossa sellaisen liikenteen vieressä, jota se ei koskaan tarjoillut.

1200x600?text=Releases+list+with+deltas+and+state+chips

Yksi muutos Lighthouse-budjettiehdotuksiin

Ehdotetut Lighthouse-budjetit saavat nyt 30 % liikkumavaran mitatun arvon päälle, aiemman 15 % sijaan. Auto-setup ja ryömintäehdotus (crawl suggestion) käyttävät molemmat uutta lukua. Jo asettamasi budjetit pysyvät koskemattomina.

Syy tähän on julkaisua edeltävä tarkistus. Budjetti, joka on asetettu 15 % yli sen mitä sivu mittaa luontipäivänä, ylittyy ensimmäisestä todellisesta muutoksesta, ja normaalista työstä laukeava portti otetaan pois päältä viikossa. 30 % jättää tilaa oikealle ominaisuudelle ja nappaa silti sen 4 megatavun kuvan.

Kun julkaisu ei näytä mitään

Viivat julkaisurivillä tarkoittavat, ettei tägättyä liikennettä ole vielä. Siihen on vain muutama syy. Julkaisu raportoitiin ennen kuin koodi oli oikeasti tuotannossa, joten sisään tulleet sivunlataukset tarjoiltiin yhä vanhasta versiosta. Tai julkaisu kirjattiin minuutteja sitten, eikä 200 sivunlatausta ole vielä tapahtunut. Tai CI:n lähettämä tägi ei vastaa beaconien tägiä, mikä tapahtuu, kun sivu asettaa window.__CWVREL-arvoksi jotain muuta ja voittaa.

Ryhmittele datataulukko Release-dimension mukaan nähdäksesi asian suoraan. Jos tägisi on tuossa listassa ja sen takana on sivunlatauksia, kohdennus (attribution) toimii ja odotat vain volyymia.

Katso myös: Core/Dash API kyseisen datan kyselyyn skriptistä tai tekoälyagentista, alerts and notifications näiden tuomioiden käyttämiin budjetteihin, ja installation, jos et ole vielä asentanut seurantaskriptiä sivustollesi.