Runbook

Snapshot settimanali dei backlink su GitHub Actions: un runbook

Obiettivo: ogni lunedì un flusso di lavoro scrive i domini di riferimento e gli anchor text del giorno nel repository. Nient'altro. Il confronto (diff) verrà in un secondo momento.

Ponte di ferro che attraversa un fiume, simboleggiando un'infrastruttura di flusso di lavoro programmato affidabile
Prima di iniziare

Hai bisogno di un repository, di una chiave Linkzoid memorizzata come segreto LZ_KEY e di un dominio di tua proprietà. Budget: circa 6 crediti per target per esecuzione, pari a $0.0006. Una snapshot è un'istantanea di un mese, quindi le esecuzioni settimanali recuperano principalmente lo stesso indice. Configurare questo metodo per verificare i backlink richiede una sera.

Il runbook, in ordine

01

1. Aggiungi il segreto

Impostazioni del repository, poi Segreti e variabili, poi Actions. Chiamalo LZ_KEY. Se lo incolli nel file del flusso di lavoro, ruota la chiave oggi stesso.

02

2. Commit dello script

Salva il Python qui sotto come snap.py. Scriverà data/YYYY-MM-DD/refdomains.json e fallirà in caso di risposta dove ok è false.

03

3. Commit del flusso di lavoro

Usa il YAML qui sotto. Esegui una volta manualmente con il trigger workflow_dispatch e leggi il log prima di fidarti della programmazione.

04

4. Controlla il primo file

Apri il JSON. Conferma il numero di righe rispetto a total e confronta il numero con quanto riportato dalla chiamata overview gratuita per il tuo dominio.

05

5. Aggiungi l'allerta

Un lavoro fallito invia un'email al proprietario del repository per impostazione predefinita. Lascia questa opzione attiva. Un lavoro che si interrompe silenziosamente è il modo in cui solitamente muoiono queste configurazioni.

snap.py

Libreria standard. Il ciclo termina sul conteggio, mai su un'ipotesi.

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

Il cron in GitHub esegue in UTC e può partire in ritardo quando i runner sono occupati. Non costruire nulla che dipenda dal minuto.

yaml
name: backlink-snapshot
on:
  schedule:
    - cron: '17 6 * * 1'
  workflow_dispatch:
jobs:
  snap:
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
      - run: python snap.py example.com
        env:
          LZ_KEY: ${{ secrets.LZ_KEY }}
      - run: |
          git config user.name snapshot-bot
          git config user.email "snapshot-bot@localhost"
          git add data
          git commit -m "snapshot $(date -u +%F)" || exit 0
          git push
Giardiniere che pota una giovane piantina, rappresentando la preparazione prima di avviare la programmazione

Prima di attivare la programmazione

  • La chiave è nei segreti del repository, e il YAML la richiama solo per nome.
  • Il file del flusso di lavoro è sul branch di default, perché è quella la copia che legge la programmazione.
  • Un'esecuzione manuale con workflow_dispatch è terminata e ha scritto una cartella datata.
  • Il conteggio delle righe nel file corrisponde al totale restituito dall'API per quella chiamata.
  • Il lavoro termina con codice di errore diverso da zero in caso di risposta negativa, quindi un fallimento rende rossa l'esecuzione.

Errori e correzioni

Cosa si rompe per primo in un lavoro programmato di backlink
ErroreCosa vediCorrezione
Chiave incollata nel YAMLChiave visibile nella cronologia del repositoryRuotala, spostala in secrets.LZ_KEY
Minuto dispari come 0 0L'esecuzione parte in ritardo di 20 minutiScegli 17 6; la cima dell'ora è affollata
Repository inattivo per 60 giorniGitHub mette in pausa la programmazioneFai un commit o riabilitalo nella scheda Actions
Il ciclo termina solo su una pagina vuotaEsecuzione infinita al limite di paginaFerma anche quando len(rows) >= total
Codice di uscita ignoratoSpunta verde, cartella vuotaUsa sys.exit su ok: false
Il commit fallisce se non ci sono modificheEsecuzione rossa per nullaAggiungi || exit 0 dopo il commit

Mantenere la chiave e il repository al sicuro

La chiave è l'unica cosa in questa configurazione che vale la pena proteggere. Trattala come una password, perché chiunque la possieda può spendere il tuo saldo.

I lavori programmati perdono dati silenziosamente. Una chiave incollata in un log, un flusso di lavoro copiato in un repository pubblico o un ex collega con accesso in scrittura sono le vie di fuga più comuni. Controlla ciascuna volta ogni trimestre.

Ruota la chiave quando qualcuno se ne va

Quando un collega con accesso se ne va, crea una nuova chiave, aggiorna il segreto e disabilita quella vecchia. Poi conferma che la prossima esecuzione passa. Una sola esecuzione verde dopo la modifica è il test più economico che farai tutto l'anno. Scrivi anche la data di rotazione nelle note del repository, così la prossima rotazione non sarà una sorpresa.

Limita chi può modificare il flusso di lavoro

Chiunque possa modificare lo YAML può stampare il segreto in un'esecuzione. Mantieni l'accesso in scrittura limitato e revisiona le modifiche al file del flusso di lavoro come faresti con il codice. Due persone con accesso in scrittura sono solitamente sufficienti per un repository piccolo.

Non stampare mai l'URL della richiesta

Stampa il saldo e il conteggio delle righe, mai l'URL della richiesta. La chiave viaggia nella stringa di query, quindi una riga di debug che stampa l'URL scrive la chiave nel log. Se devi condividere una richiesta in una issue, sostituisci prima la chiave con un segnaposto.

Bussola e pianta in vaso, indicante un progresso costante e il rilevamento precoce dei problemi

Cos'è e cosa non è la snapshot

Quello che ottieni è un'istantanea mensile. Il nostro crawler aggiorna l'indice circa una volta al mese, quindi due esecuzioni di lunedì nello stesso mese spesso restituiscono le stesse righe. È previsto.

Una cadenza settimanale funziona. Mantiene l'abitudine viva e ti permette di catturare un lavoro fallito entro sette giorni invece che trenta. Se un link che hai creato martedì manca lunedì, aspetta il prossimo aggiornamento prima di farti prendere dal panico.

Quando hai tre o quattro cartelle datate, passa a la diff SQLite. Se sei bloccato su un codice di risposta ostinato, la tabella dei limiti di velocità elenca cosa significa ogni stato per un ciclo.

Mantieni la prima cartella come baseline. Ogni confronto successivo punta a essa, e una cartella nominata per data è molto più facile da fidarsi rispetto al ricordo di come apparivano i numeri la primavera scorsa. Mantieni la coerenza.

Aggiungere anchor text e pagine principali

Un'azione per file mantiene le diff leggibili. Copia il ciclo in snap.py, cambia refdomains in anchors o toppages e scrivi in un secondo nome di file. Ognuno costa 2 crediti.

Un file combinato nasconde quale parte è cambiata, e un revisore che scorre una pull request vuole vedere un concetto per diff. Tienili separati. Se tracci tre domini, cicla su una breve lista nel flusso di lavoro con una matrice, così ogni target ottiene il suo lavoro e il suo fallimento.

Gli anchor text sono un secondo file con il proprio limite nella diff, quindi revisionali separatamente dai domini di riferimento. Ogni esecuzione rimane economica e ripetibile, che è l'idea principale.

Leggere il log dell'esecuzione

Apri il log della prima esecuzione. Fallo prima di fidarti della programmazione. Cerca il conteggio delle righe, il saldo e la riga del commit. Se uno dei tre manca, il lavoro ha fatto meno di quanto afferma. Tieni anche una breve nota del saldo a ogni esecuzione, così la spesa mensile è visibile senza aprire il dashboard.

Una spunta verde dice poco. Significa solo che il processo è terminato pulitamente. Non dice che il file contiene le righe giuste, motivo per cui lo script stampa il suo riepilogo. Mantieni quelle righe di riepilogo invariate tra le versioni dello script, così una diff di due log mostra solo cambiamenti reali.

Come appare un log sano

Un'esecuzione sana stampa una riga con il conteggio delle righe e il saldo dei crediti, poi un commit con la data odierna. Qualsiasi cosa seppellisca quelle righe sotto rumore extra merita un secondo sguardo.

Rilevare un fallimento silenzioso

Attento a una cartella vuota, un commit che non appare mai o un conteggio delle righe che differisce dal totale. Ognuno di questi punti verso il ciclo o il parsing, non verso l'API stessa. Salva il primo log sano come riferimento per confronti futuri.

Alcuni fallimenti lasciano una cartella con meno righe del solito. Confronta il conteggio con la settimana precedente prima di festeggiare una esecuzione verde, perché una troncamento silenzioso sembra esattamente come un mese silenzioso.

Aggiungere un secondo target in modo sicuro

Un secondo dominio è una voce di matrice, non una copia dell'intero flusso di lavoro. Assegna a ogni target il suo lavoro così un fallimento non ne nasconde un altro. Mantieni ogni lavoro separato. Controlla che i percorsi includano il nome del dominio, così due esecuzioni non scrivono mai nello stesso file.

Inizia con il secondo target da solo. Una volta che la sua cartella sembra corretta, aggiungi il resto. Una matrice che fallisce a metà è più difficile da leggere di due esecuzioni semplici.

Nominare le cartelle per target

Metti il dominio nel percorso, ad esempio data/<domain>/YYYY-MM-DD, e le cartelle rimangono separate anche quando due lavori eseguono nello stesso minuto. Le cartelle vecchie possono rimanere dove sono, poiché una data nel percorso le rende facili da trovare.

Usa la stessa regola di denominazione per ogni target. Uno script può poi elencare le cartelle senza casi speciali.

Pianifica prima il budget dei crediti

Moltiplica le chiamate per target per il numero di target, poi controlla il totale contro il tuo saldo prima della prima esecuzione. Una matrice moltiplica la spesa tanto velocemente quanto moltiplica i lavori. Scrivi il totale mensile previsto nel repository accanto al flusso di lavoro. Quando il saldo scende più velocemente di così, un ciclo sta probabilmente recuperando di nuovo le pagine, e puoi fermarlo prima della prossima esecuzione.

Domande che sorgono nella prima settimana

Posso eseguirlo su un repository privato gratuitamente?
Di solito sì, entro i minuti mensili che GitHub offre agli account gratuiti. Un lavoro di snapshot richiede meno di un minuto, quindi una programmazione settimanale usa una piccola quota. Controlla l'attuale allowance del tuo piano, perché GitHub lo cambia di tanto in tanto.
Dove dovrebbe vivere la chiave se spingono diverse persone?
In un segreto di organizzazione o repository, mai nei file. Chiunque possa modificare il flusso di lavoro può stampare un segreto in un log, quindi limita chi ha accesso in scrittura e ruota la chiave se qualcuno lascia il progetto.
Perché la mia esecuzione programmata non è partita?
Tre motivi soliti. Il file del flusso di lavoro non è sul branch di default, il repository è stato inattivo per 60 giorni e GitHub ha messo in pausa la programmazione, o la stringa cron ha un errore di battitura. Esegui una volta con workflow_dispatch per escludere lo script stesso.
Quanto grandi diventano le cartelle dei dati?
Piccole. Mille domini di riferimento sono qualche centinaio di kilobyte di JSON. Un anno di file settimanali per un dominio rimane ben sotto i cento megabyte, il che va bene per git, anche se puoi comprimere le cartelle più vecchie se ti dà fastidio.