9 min de cititIntegrări

Scurtează linkurile din notele de lansare și urmărește descărcările

Scurtează linkurile din notele de lansare: un link latest stabil repoziționat la fiecare versiune, un link etichetat per canal și date de clic despre descărcări.

Marius Voß
DevRel · edge infra

Notele de lansare ajung mai departe decât aproape orice scrie o echipă de inginerie. Nimeni nu le măsoară. Lipești un link de descărcare în corpul lansării, cineva îl copiază în Slack, marketingul îl pune în newsletter, un maintainer îl postează pe X. Șase luni mai târziu, jumătate din acele linkuri indică un fișier care nu mai există, iar niciunul nu ți-a spus nimic. Ca să scurtezi corect linkurile din notele de lansare, ai nevoie de trei lucruri: un singur link scurt „latest" stabil, pe care îl repoziționezi la fiecare lansare, un link etichetat separat per canal pentru fiecare versiune și un workflow pe evenimentul release: published care le creează pe amândouă, ca nimeni să nu trebuiască să își amintească.

Acesta este răspunsul întreg. Restul articolului arată cum le conectezi fără să faci dezordine și ce îți pot și ce nu îți pot spune datele de clic după aceea.

Am văzut multe proiecte gestionând de mână linkurile din notele de lansare GitHub, iar modul de eșec e mereu același: cineva face link către un asset cu versiune, linkul e citat într-un thread de forum sau într-un răspuns Stack Overflow, iar următoarea lansare îl lasă orfan în tăcere. Dacă îți gestionezi deja linkurile ca cod, abordarea de mai jos se așază lângă linkurile scurte gestionate în Terraform, cu diferența că linkurile de lansare se schimbă după un program pe care nu îl controlezi de mână.

De ce putrezesc linkurile din notele de lansare și pierd atribuirea

Aici se ascund două probleme separate. Au nevoie de remedii diferite.

Prima este putrezirea linkurilor. GitHub îți oferă URL-uri stabile pentru pagina lansării (/releases/latest) și pentru fișiere, prin /releases/latest/download/asset-name, dar al doilea funcționează doar când asset-ul păstrează un nume identic între lansări, conform documentației GitHub despre linkurile către lansări. Majoritatea pipeline-urilor de build pun versiunea în numele fișierului, deci app-2.3.0.dmg devine app-2.4.0.dmg, iar URL-ul de descărcare „latest" care funcționa săptămâna trecută returnează acum 404. Linkurile către documentație putrezesc și ele, ori de câte ori un site de documentație e reorganizat. Tiparele mai largi sunt în strategia noastră de prevenire a putrezirii linkurilor; notele de lansare sunt doar locul unde mușcă cel mai tare, pentru că linkurile lor călătoresc cel mai departe.

A doua problemă este atribuirea, și e mai discretă. API-ul REST GitHub raportează un download_count pe fiecare asset de lansare, ceea ce e mai mult decât realizează majoritatea oamenilor. Ce nu raportează este de unde a venit descărcarea. Un vârf de 4.000 de descărcări în ziua de după lansare poate fi newsletterul, un thread pe Hacker News sau CI-ul unui singur client enterprise care trage binarul în buclă. Linkurile lipite în Slack și în mesaje directe pierd complet referrerul, adică problema atribuirii dark social în miniatură.

Creează un singur link scurt, de exemplu get.example.dev/latest, și tratează-l ca pe un pointer. Fiecare pagină de documentație, insignă din README și script de instalare îl folosește. La fiecare lansare stabilă, actualizezi spre ce indică. Slugul nu se schimbă niciodată, așa că nimic din ce l-a citat nu se rupe.

În Elido, acel pointer este un link obișnuit. Îl creezi o singură dată cu POST /v1/workspaces/{workspace_id}/links, transmițând domain_id al domeniului tău de brand, slug și destination_url. Salvează id din răspunsul 201. Repoziționarea este un PATCH /v1/workspaces/{workspace_id}/links/{link_id} cu un nou destination_url și nimic altceva; slugul, etichetele și istoricul clicurilor rămân pe loc.

Păstrează-l pe 302. Linkurile Elido folosesc implicit 302 și există un motiv să nu schimbi asta aici: un 301 poate fi reținut în cache implicit conform RFC 9110, deci un browser care a văzut redirecționarea de luna trecută poate să nu mai întrebe niciodată. Un pointer pe care browserele îl rețin pentru totdeauna nu mai este un pointer. Mai mult în redirecționări 301 vs 302 pentru linkuri scurte.

Diagramă cu un link scurt latest stabil repoziționat de la descărcarea v2.3.0 la descărcarea v2.4.0 când se publică o lansare, în timp ce linkurile per lansare pentru v2.3.0 continuă să indice propriul tag

Decide un lucru din start. Ar trebui linkul latest să indice fișierul sau pagina lansării? Eu l-aș îndrepta spre pagina lansării pentru orice are mai mult de un build pe platformă și aș păstra linkuri latest per platformă (/latest-mac, /latest-linux) doar dacă documentația ta de instalare chiar are nevoie de un fișier direct. Mai puține pointere mobile înseamnă mai puține lucruri de repoziționat greșit.

Etichetare per lansare pentru linkurile din notele de lansare GitHub

Linkul latest răspunde la „mai funcționează linkul". Nu poate răspunde la „ce canal a funcționat", pentru că toți dau clic pe același slug. Pentru asta, fiecare lansare primește propriul set mic de linkuri, câte unul pe canal, create în momentul publicării.

Iată partea pe care o sar majoritatea ghidurilor UTM. Să adaugi utm_source=slack la un URL github.com nu face nimic util, pentru că nu vei vedea niciodată analitica GitHub. UTM-urile își merită locul doar când destinația este un site pe care îl măsori, precum documentația sau propria ta pagină de descărcare. Când destinația este GitHub, linkul scurt separat per canal este atribuirea: clicul este numărat la redirecționare, înainte ca GitHub să îl vadă vreodată.

CanalSlug pentru v2.4.0DestinațieCe îți spun clicurile
Comunitate Slackv2-4-0-slackPagina lansării GitHubClicuri din propria comunitate
X / Mastodonv2-4-0-socialPagina lansării GitHubAcoperire dincolo de utilizatorii existenți
Newsletterv2-4-0-newsGhidul de upgrade din docs + UTMClicuri plus comportament pe site în analitica ta
Latest (stabil)latestLansarea curentă, repoziționatCererea totală pe toate versiunile

Etichetează fiecare link per lansare cu versiunea și canalul (["release", "v2.4.0", "slack"]), pentru că etichetele sunt felul în care vei scoate setul înapoi mai târziu: GET .../links?tags=v2.4.0 listează tot ce ține de o lansare. Păstrează valorile UTM banale și identice între lansări. Ghidul convențiilor de denumire UTM conține regulile pe care le-aș copia.

Crearea linkurilor la evenimentul Release Published

Un ghid-soră acoperă crearea generică de linkuri în CI, deci această secțiune rămâne la părțile specifice lansărilor. Triggerul este release cu tipul de activitate published. Conform listei de evenimente de workflow GitHub, published se declanșează atât pentru lansări stabile, cât și pentru pre-lansări, inclusiv pre-lansările publicate dintr-o schiță, motiv pentru care pasul de repoziționare de mai jos verifică flagul prerelease.

name: release-links
on:
  release:
    types: [published]

jobs:
  links:
    runs-on: ubuntu-latest
    env:
      API: https://api.elido.app/v1/workspaces/${{ vars.ELIDO_WORKSPACE_ID }}
      DOMAIN_ID: ${{ vars.ELIDO_DOMAIN_ID }}
      TAG: ${{ github.event.release.tag_name }}
      PAGE: ${{ github.event.release.html_url }}
      ELIDO_TOKEN: ${{ secrets.ELIDO_TOKEN }}
    steps:
      - name: Create one link per channel
        run: |
          v=$(echo "$TAG" | tr '.' '-')
          for ch in slack social news; do
            body=$(jq -n --argjson d "$DOMAIN_ID" --arg s "$v-$ch" \
              --arg u "$PAGE" --arg t "$TAG" --arg c "$ch" \
              '{domain_id:$d, slug:$s, destination_url:$u, tags:["release",$t,$c]}')
            code=$(curl -s -o /dev/null -w '%{http_code}' -X POST "$API/links" \
              -H "Authorization: Bearer $ELIDO_TOKEN" \
              -H "Content-Type: application/json" -d "$body")
            case "$code" in 201|409) ;; *) echo "create $ch failed: $code"; exit 1;; esac
            echo "- $ch: https://get.example.dev/$v-$ch" >> "$GITHUB_STEP_SUMMARY"
          done

      - name: Repoint the latest link
        if: ${{ !github.event.release.prerelease }}
        run: |
          curl -sf -X PATCH "$API/links/${{ vars.ELIDO_LATEST_LINK_ID }}" \
            -H "Authorization: Bearer $ELIDO_TOKEN" \
            -H "Content-Type: application/json" \
            -d "$(jq -n --arg u "$PAGE" '{destination_url:$u}')"

Rezumatul jobului îi dă celui care postează anunțul o listă gata de linkuri, iar un 409 la o rerulare înseamnă că slugul există deja, deci un workflow reîncercat nu eșuează și nu duplică nimic. Linkul pentru newsletter ar indica documentația ta cu UTM-uri în destinație; l-am lăsat aici pe pagina lansării ca exemplul să rămână scurt.

Trei capcane care m-au costat o după-amiază

Prima e tăcută. Dacă pipeline-ul tău de lansare publică lansarea cu GITHUB_TOKEN implicit, acest workflow nu rulează niciodată, pentru că evenimentele create cu GITHUB_TOKEN nu declanșează rulări noi de workflow. Nicio eroare, niciun job sărit, nimic. Publică în schimb cu un token de GitHub App.

A doua, punctele. Convertesc v2.4.0 în v2-4-0 pentru slug, pentru că șirurile de versiune cu puncte arată ca extensii de fișier în previzualizările din chat, iar unii clienți le transformă ciudat în linkuri.

A treia, nu lăsa workflowul să editeze corpul lansării decât dacă e nevoie. Merge (gh release edit --notes-file), dar rescrie un text pe care un om tocmai l-a aprobat și declanșează evenimente edited la care pot reacționa alte automatizări. Rezumatul pasului e mai puțin isteț și mult mai sigur. Reîncercările au propriul articol: limite de rată API și idempotență.

Dacă încă lipești linkurile de lansare de mână, workflowul de mai sus înseamnă vreo douăzeci de minute de configurare. Pornește un workspace Elido gratuit, îndreaptă un domeniu de brand spre el și lasă următorul tag să își creeze singur linkurile.

Cum urmărești clicurile din notele de lansare pe canale

După două-trei lansări, datele încep să răspundă la întrebări la care contorul GitHub nu poate.

Compararea pe canale este cea simplă. Extrage linkurile etichetate cu o versiune, apoi citește rezumatul de clicuri al fiecărui link, filtrat după link_id. Dacă v2-4-0-news îl bate pe v2-4-0-social cu cinci la unu timp de trei lansări la rând, ai aflat unde sunt de fapt utilizatorii tăi, și rareori e unde presupunea echipa. Anunțul cu cele mai multe aprecieri nu e adesea cel care trimite oamenii la descărcare, așa că așteaptă-te la obiecții prima dată când arăți cifrele și așteaptă a treia lansare la rând înainte ca cineva să rescrie planul de lansare în jurul lor.

Linkul latest are un truc mai puțin evident. Fiecare clic înregistrează destinația la care s-a rezolvat în acel moment, deci defalcarea analiticii după destinație, filtrată pe linkul latest, împarte traficul lui pe versiuni. După o repoziționare poți urmări cum scade ponderea vechii destinații și cât timp mai sosesc întârziații pe pagini din cache și pe vechi favorite. Aceasta este curba ta reală de upgrade, măsurată în vârful pâlniei.

Diagramă care arată cum urmărești clicurile din notele de lansare: linkurile Slack, social și newsletter ale unei lansări alimentează numărători de clicuri per link, în timp ce linkul latest defalcă clicurile după versiunea destinației

Două limite sincere. Clicurile nu sunt descărcări: cineva poate da clic pe pagina lansării și pleca, iar download_count de la GitHub rămâne sursa de adevăr pentru descărcările finalizate. Și boții dau clic pe linkurile de lansare, mai ales preluatoarele de previzualizare din aplicațiile de chat, așa că citește tendințele pe mai multe lansări în loc să te încrezi într-o singură zi. Pagina funcției de analitică listează ce defalcări sunt disponibile pe fiecare plan.

Păstrarea în viață a vechilor linkuri de lansare

Linkurile per lansare nu se mută niciodată. v2-3-0-slack indică tagul v2.3.0 în martie și tot acolo indică peste cinci ani, ceea ce se așteaptă cineva care citește un thread vechi de forum. Doar linkul latest se schimbă, și doar la lansările stabile.

Singurul caz în care ar trebui să atingi un link vechi este o lansare retrasă. Dacă v2.4.0 apare cu un bug de pierdere de date, nu șterge linkurile ei; repoziționează fiecare link v2-4-0-* către v2.4.1 cu același apel PATCH și o scurtă notă în corpul lansării. Ștergerea le dă celor care au salvat linkul un punct mort exact în momentul în care au cea mai mare nevoie de remediu. O versiune mai nouă bate un 404. De fiecare dată.

Pentru proiectele care păstrează vechi linkuri de lansare și în README-uri, scripturi de instalare și metadate de pachete, ghidul orientat spre dezvoltatori despre scurtătoarele de URL arată unde mai sunt utile linkurile scurte. Suprafața REST completă este pe pagina API și SDK-uri.

Citește articolul-pilon → Gestionează-ți linkurile scurte ca Terraform

Pe același subiect pe blog

Întrebări frecvente

Cum fac link către ultima lansare GitHub?

GitHub acceptă /releases/latest pentru pagina lansării și /releases/latest/download/asset-name pentru un fișier, atâta timp cât asset-ul păstrează același nume în fiecare lansare. Dacă numele asset-urilor tale conțin numărul versiunii, pune în față un link scurt și repoziționează-l la fiecare lansare.

Pot urmări clicurile pe descărcările din lansările GitHub?

Parțial. API-ul REST GitHub raportează un download_count per asset de lansare, dar nu are date despre referrer, țară sau canal, deci nu îți poate spune dacă descărcarea a venit de pe Slack, de pe X sau dintr-un newsletter. Un link scurt per canal, pus în fața asset-ului, îți dă această împărțire.

Ar trebui un link scurt către ultima lansare să folosească o redirecționare 301 sau 302?

Folosește 302. Browserele pot reține un 301 în cache pe termen nelimitat, deci un cititor care a dat clic luna trecută poate continua să ajungă la versiunea veche după ce repoziționezi linkul. Linkurile Elido folosesc implicit 302, ceea ce ține destinația sub controlul tău la fiecare clic.

De ce nu rulează workflowul meu de lansare când alt workflow publică lansarea?

Evenimentele create cu GITHUB_TOKEN-ul repository-ului nu pornesc rulări noi de workflow, în afară de workflow_dispatch și repository_dispatch. Dacă un pipeline de lansare publică cu GITHUB_TOKEN, triggerul release: published nu se declanșează niciodată. Publică în schimb cu un token de GitHub App sau cu un personal access token cu granulație fină.

Funcționează parametrii UTM pe linkurile către github.com?

Trec mai departe, dar nu îți folosesc la nimic, pentru că nu vezi niciodată analitica GitHub. UTM-urile se răsplătesc doar când destinația este un site pe care îl măsori, precum documentația sau pagina ta de descărcare. Pentru destinațiile github.com, linkul scurt separat per canal este atribuirea.

Ce se întâmplă cu vechile linkuri de lansare când apare o versiune nouă?

Nimic, dacă l-ai configurat așa. Linkurile per lansare continuă să indice pentru totdeauna propriul tag, iar doar linkul latest se mută. Dacă o lansare este retrasă, repoziționează linkurile ei către versiunea corectată în loc să le ștergi, ca cei care au salvat vechiul link să ajungă tot într-un loc util.

Încearcă Elido

Lipește un URL, obții un link scurt funcțional

Fără înregistrare. Linkul este activ timp de 30 de zile. Înregistrează-te ca să-l păstrezi pentru totdeauna.

Fără înregistrare. Creează un cont gratuit pentru 50 linkuri pe lună.

Încearcă Elido

Scurtător de URL-uri găzduit în UE, cu domenii personalizate, analiză avansată și un API deschis. Nivel gratuit - fără card bancar.

Etichete
shorten links in release notes
github release notes links
track clicks on release notes
github actions
release automation
link rot

Continuă lectura