Instantanee săptămânale ale backlinkurilor cu GitHub Actions: un manual de operațiuni
Obiectiv: în fiecare luni, un flux de lucru scrie domeniile care fac referire și anchor textele din ziua respectivă în repo. Nimic altceva. Compararea (diffing) vine mai târziu.
Echipa editorială Linkzoid ·
Înainte de a începe
Ai nevoie de un repo, o cheie Linkzoid stocată ca secretul LZ_KEY și un domeniu deținut de tine. Buget: aproximativ 6 credite pe țintă per execuție, adică $0.0006. Un instantaneu este o constatare pentru o lună, deci execuțiile săptămânale vor reîncărca în mare parte același index. Configurarea modului de verificare a backlinkurilor către site-ul meu în acest fel necesită o seară.
Manualul de operațiuni, în ordine
01
1. Adaugă secretul
Setări repo, apoi Secrets and variables, apoi Actions. Denumește-l LZ_KEY. Dacă îl lipești în fișierul workflow, rotirea cheii trebuie făcută azi.
02
2. Commită scriptul
Salvează Pythonul de mai jos ca snap.py. Acesta scrie data/YYYY-MM-DD/refdomains.json și eșuează la orice răspuns unde ok este false.
03
3. Commită workflow-ul
Folosește YAML-ul de mai jos. Rulează-l o dată manual cu trigger-ul workflow_dispatch și citește logul înainte de a avea încredere în programare.
04
4. Verifică primul fișier
Deschide JSON-ul. Confirmă numărul de rânduri împotriva total și compară numărul cu ceea ce raportează apelul gratuit overview pentru domeniul tău.
05
5. Adaugă alertarea
Un job eșuat trimite un email proprietarului repo implicit. Lasă asta activ. Un job care se oprește liniștit este de obicei modul în care aceste configurații mor.
snap.py
Biblioteca standard. Bucla se termină la numărul de înregistrări, niciodată pe baza unei presupuneri.
python
import json, os, sys, datetime, pathlib, urllib.request as u
KEY = os.environ['LZ_KEY']
TARGET = sys.argv[1]
def get(**p):
q = '&'.join(f'{k}={v}' for k, v in p.items())
url = f'https://linkzoid.pro/api.php?{q}&key={KEY}'
with u.urlopen(url, timeout=30) as r:
return json.load(r)
rows, page = [], 1
while True:
d = get(action='refdomains', q=TARGET, page=page, per=1000)
if not d['ok']:
sys.exit(f'bad response: {d}')
rows += d['rows']
if not d['rows'] or len(rows) >= d['total']:
break
page += 1
day = datetime.date.today().isoformat()
out = pathlib.Path('data') / day
out.mkdir(parents=True, exist_ok=True)
(out / 'refdomains.json').write_text(json.dumps(rows))
print(len(rows), 'rows, balance', d['_credits'])
.github/workflows/snapshot.yml
Cron-ul în GitHub rulează în UTC și poate începe târziu când runner-ele sunt ocupate. Nu construi nimic care depinde de minut.
Cheia stă în repository secrets, iar YAML-ul doar o referă prin nume.
Fișierul workflow este pe branch-ul default, deoarece acesta este copia pe care o citește programarea.
O execuție manuală cu workflow_dispatch s-a terminat și a scris un dosar datat.
Numărul de rânduri din fișier se potrivește cu totalul returnat de API pentru acel apel.
Jobul iese cu cod non-zero la un răspuns greșit, astfel încât un eșec face ca execuția să fie roșie.
Greșeli și remedieri
Ce se strică primul într-un job programat de backlinkuri
Greșeală
Ce vezi
Remediere
Cheia lipită în YAML
Cheie vizibilă în istoricul repo
Rotire cheie, mutare în secrets.LZ_KEY
Minut ciudat precum 0 0
Execuția începe cu 20 de minute întârziere
Alege 17 6; vârful de oră este aglomerat
Repo inactiv timp de 60 de zile
GitHub pune în pauză programarea
Fă un commit sau re-activare în tabul Actions
Bucla se oprește doar la o pagină goală
Execuție infinită la capul de pagină
Oprește-te și când len(rows) >= total
Codul de ieșire ignorat
Bifă verde, dosar gol
Folosește sys.exit pe ok: false
Commitul eșuează dacă nu sunt modificări
Execuție roșie degeaba
Adaugă || exit 0 după commit
Menținerea cheii și a repo-ului în siguranță
Cheia este singurul lucru din această configurație care merită protejat. Trateaz-o ca pe o parolă, deoarece oricine deține cheie poate cheltui soldul tău.
Joburile programate scapă chei liniștit. O cheie lipită într-un log, un workflow copiat într-un repo public sau un fost coleg cu acces de scriere sunt căile uzuale. Verifică fiecare o dată pe trimestru.
Rotirea cheii când cineva pleacă
Când un coleg cu acces pleacă, creează o cheie nouă, actualizează secretul și retrage pe cel vechi. Apoi confirmă că următoarea execuție trece. O singură execuție verde după modificare este cel mai ieftin test pe care îl vei face în tot anul. Scrie data rotirii în notele repo-ului, astfel încât următoarea rotire să nu fie o surpriză.
Limitează pe cine poate edita workflow-ul
Oricine poate edita YAML-ul poate tipări secretul într-o execuție. Menține accesul de scriere scurt și revizuiește modificările la fișierul workflow așa cum revizuiești codul. Două persoane cu acces de scriere sunt de obicei suficiente pentru un repo mic.
Nu tipă niciodată URL-ul cererii
Tipărește soldul și numărul de rânduri, niciodată URL-ul cererii. Cheia circulă în șirul de interogare, deci o linie de debug care tipărește URL-ul scrie cheia în log. Dacă trebuie să partajezi o cerere într-o problemă, înlocuiește mai întâi cheia cu un placeholder.
Ce este instantaneul și ce nu este
Ceea ce primești este o imagine lunară. Crawler-ul nostru actualizează indexul aproximativ o dată pe lună, deci două execuții de luni în aceeași lună returnează adesea aceleași rânduri. Acesta este un lucru normal.
Un ritm săptămânal funcționează. Menține obiceiul viu și prinde un job eșuat în șapte zile în loc de treizeci. Dacă un link construit marți lipsește luni, așteaptă următoarea actualizare înainte de a te alarma.
Când ai trei sau patru dosare datate, treci la difuzarea SQLite. Dacă ești blocat de un cod de răspuns încăpățânat, tabelul de limitare a ratelor listează ce înseamnă fiecare status pentru o buclă.
Păstrează primul dosar ca bază. Fiecare comparație ulterioară se întoarce la el, iar un dosar numit după dată este mult mai ușor de încredere decât o amintire despre cum arătau numerele vara trecută. Fii consecvent.
Adăugarea anchor textelor și a paginilor top
O acțiune per fișier menține diff-urile lizibile. Copiază bucla din snap.py, schimbă refdomains în anchors sau toppages și scrie într-un al doilea nume de fișier. Fiecare costă 2 credite.
Un fișier combinat ascunde care parte s-a schimbat, iar un reviewer care derulează un pull request vrea să vadă un concept per diff. Ține-le separate. Dacă urmărești trei domenii, buclează peste o listă scurtă în workflow cu o matrice, astfel încât fiecare țintă să aibă propriul job și propria eroare.
Anchor textele sunt un al doilea fișier cu propriul cap în diff, astfel încât revizuiește-le separat de domeniile care fac referire. Fiecare execuție rămâne ieftină și repetabilă, acesta fiind ideea de bază.
Citirea logului de execuție
Deschide logul primei execuții. Fă-o înainte de a avea încredere în programare. Caută numărul de rânduri, soldul și linia de commit. Dacă oricare dintre cele trei lipsește, jobul a făcut mai puțin decât pretinde. Ține și un scurt note al soldului la fiecare execuție, astfel încât cheltuiala lunară să fie vizibilă fără a deschide dashboard-ul.
O bifă verde spune puțin. Înseamnă doar că procesul a ieșit curat. Nu spune că fișierul conține rândurile corecte, de aceea scriptul își tipărește propriul sumar. Păstrează acele linii de sumar neschimbate între versiunile scriptului, astfel încât un diff al două loguri să arate doar modificări reale.
Cum arată un log sănătos
O execuție sănătoasă tipărește o linie cu numărul de rânduri și soldul de credite, apoi un commit cu data de azi. Orice îngroapă acele linii sub zgomot suplimentar merită o a doua privire.
Detectarea unui eșec tăcut
Urmărește un dosar gol, un commit care nu apare niciodată sau un număr de rânduri care diferă de total. Fiecare dintre acestea indică bucla sau parsarea, nu API-ul în sine. Salvează primul log sănătos ca referință pentru comparațiile viitoare.
Unele eșecuri lasă în urmă un dosar cu mai puține rânduri decât de obicei. Compară numărul cu săptămâna precedentă înainte de a sărbători o execuție verde, deoarece o trunchiere liniștită arată exact ca o lună liniștită.
Adăugarea unei a doua ținte în siguranță
Un al doilea domeniu este o intrare matrice, nu o copie a întregului workflow. Dă fiecărei ținte propriul job astfel încât un eșec să nu ascundă altul. Menține fiecare job separat. Verifică că căile includ numele domeniului, astfel încât două execuții să nu scrie niciodată în același fișier.
Începe doar cu a doua țintă. Odată ce dosarul arată corect, adaugă restul. O matrice care eșuează pe jumătate este mai greu de citit decât două execuții simple.
Numirea dosarelor după țintă
Pune domeniul în cale, de exemplu data/<domain>/YYYY-MM-DD, și dosarele rămân separate chiar și când două joburi rulează în același minut. Dosarele vechi pot rămâne unde sunt, deoarece o dată în cale le face ușor de găsit.
Folosește aceeași regulă de numire pentru fiecare țintă. Un script poate apoi să listeze dosarele fără cazuri speciale.
Planifică bugetul de credite mai întâi
Înmulțește apelurile pe țintă cu numărul de ținte, apoi verifică totalul împotriva soldului înainte de prima execuție. O matrice multiplică cheltuiala la fel de repede pe cât multiplică joburile. Scrie totalul lunar așteptat în repo lângă workflow. Când soldul scade mai repede decât atât, o buclă probabil reîncarcă pagini și poți opri înainte de următoarea execuție.
Întrebări care apar în prima săptămână
Pot rula asta pe un repo privat gratuit?
De obicei da, în limitele minutelor lunare pe care GitHub le oferă conturilor gratuite. Un job de instantaneu rulează în mult sub un minut, deci o programare săptămânală folosește o fracțiune mică. Verifică allowance-ul curent al planului tău, deoarece GitHub îl schimbă din când în când.
Unde ar trebui să trăiască cheia dacă mai multe persoane fac push?
Într-un secret de organizație sau repository, niciodată în fișiere. Oricine poate edita workflow-ul poate tipări un secret într-un log, deci limitează pe cine are acces de scriere și rotește cheia dacă cineva părăsește proiectul.
De ce nu s-a declanșat execuția programată?
Trei motive uzuale. Fișierul workflow nu este pe branch-ul default, repo a fost inactiv timp de 60 de zile și GitHub a pus în pauză programarea, sau șirul cron are o greșeală de tastare. Rulează-l o dată cu workflow_dispatch pentru a exclude scriptul în sine.
Cât de mari devin dosarele de date?
Mici. O mie de domenii care fac referire este câteva sute de kilobyți de JSON. Un an de fișiere săptămânale pentru un domeniu rămâne mult sub o sută de megabytes, ceea ce este bine pentru git, deși poți comprima dosarele mai vechi dacă te deranjează.