Captures hebdomadaires des backlinks avec GitHub Actions : un runbook
Objectif : chaque lundi, un workflow écrit les domaines référents et les ancres du jour dans le dépôt. Rien d'autre. Le diff viendra plus tard.
Équipe éditoriale Linkzoid ·
Avant de commencer
Vous avez besoin d'un dépôt, d'une clé Linkzoid stockée en tant que secret LZ_KEY, et d'un domaine que vous possédez. Budget : environ 6 crédits par cible par exécution, soit $0.0006. Une capture est un fait sur un mois, donc les exécutions hebdomadaires récupèrent principalement le même index. La mise en place de cette méthode pour vérifier les backlinks prend une soirée.
Le runbook, dans l'ordre
01
1. Ajoutez le secret
Paramètres du dépôt, puis Secrets et variables, puis Actions. Nommez-le LZ_KEY. Si vous le collez dans le fichier de workflow, faites tourner la clé dès aujourd'hui.
02
2. Commitez le script
Enregistrez le Python ci-dessous sous le nom snap.py. Il écrit data/YYYY-MM-DD/refdomains.json et échoue si ok est faux.
03
3. Commitez le workflow
Utilisez le YAML ci-dessous. Exécutez-le une fois manuellement avec le déclencheur workflow_dispatch et lisez le journal avant de faire confiance à la planification.
04
4. Vérifiez le premier fichier
Ouvrez le JSON. Confirmez le nombre de lignes par rapport à total, et comparez le nombre avec ce que l'appel overview gratuit rapporte pour votre domaine.
05
5. Ajoutez l'alerte
Un échec de job envoie un email au propriétaire du dépôt par défaut. Laissez cela activé. Un job qui s'arrête silencieusement est la façon habituelle dont ces configurations meurent.
snap.py
Bibliothèque standard. La boucle se termine sur le compte, jamais sur une supposition.
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
Le cron dans GitHub s'exécute en UTC et peut démarrer en retard lorsque les runners sont occupés. Ne construisez rien qui dépende de la minute.
La clé est dans les secrets du dépôt, et le YAML ne la référence que par son nom.
Le fichier de workflow est sur la branche par défaut, car c'est la copie que lit la planification.
Une exécution manuelle avec workflow_dispatch est terminée et a écrit un dossier daté.
Le nombre de lignes dans le fichier correspond au total retourné par l'API pour cet appel.
Le job se termine avec un code non nul en cas de réponse incorrecte, donc un échec rend l'exécution rouge.
Erreurs et correctifs
Ce qui casse en premier dans un job de backlinks planifié
Erreur
Ce que vous voyez
Correctif
Clé collée dans le YAML
Clé visible dans l'historique du dépôt
Faites-la tourner, déplacez-la vers secrets.LZ_KEY
Minute étrange comme 0 0
L'exécution démarre 20 minutes en retard
Choisissez 17 6; le début de l'heure est encombré
Dépôt inactif pendant 60 jours
GitHub met la planification en pause
Commitez quelque chose, ou réactivez-le dans l'onglet Actions
La boucle s'arrête uniquement sur une page vide
Exécution infinie au plafond de pages
Arrêtez aussi quand len(rows) >= total
Code de sortie ignoré
Vérification verte, dossier vide
Utilisez sys.exit sur ok: false
Le commit échoue s'il n'y a pas de changement
Exécution rouge pour rien
Ajoutez || exit 0 après le commit
Garder la clé et le dépôt en sécurité
La clé est la seule chose dans cette configuration qui mérite d'être protégée. Traitez-la comme un mot de passe, car quiconque la détient peut dépenser votre solde.
Les jobs planifiés fuient silencieusement. Une clé collée dans un journal, un workflow copié dans un dépôt public, ou un ancien collègue avec un accès en écriture sont les voies habituelles. Vérifiez chacun une fois par trimestre.
Faites tourner la clé quand quelqu'un part
Quand un collègue avec accès part, créez une nouvelle clé, mettez à jour le secret et mettez hors service l'ancienne. Puis confirmez que la prochaine exécution passe. Une seule exécution verte après le changement est le test le moins cher que vous ferez de l'année. Notez aussi la date de rotation dans les notes du dépôt, pour que la prochaine rotation ne soit pas une surprise.
Limitez qui peut modifier le workflow
Quiconque peut modifier le YAML peut imprimer le secret dans un run. Gardez l'accès en écriture court, et révisez les changements dans le fichier de workflow comme vous révisez du code. Deux personnes avec un accès en écriture sont généralement suffisantes pour un petit dépôt.
N'imprimez jamais l'URL de la requête
Imprimez le solde et le nombre de lignes, jamais l'URL de la requête. La clé voyage dans la chaîne de requête, donc une ligne de débogage qui imprime l'URL écrit la clé dans le journal. Si vous devez partager une requête dans un ticket, remplacez d'abord la clé par un espace réservé.
Ce qu'est la capture, et ce qu'elle n'est pas
Ce que vous obtenez est une image mensuelle. Notre propre crawler rafraîchit l'index environ une fois par mois, donc deux exécutions du lundi dans le même mois retournent souvent les mêmes lignes. C'est attendu.
Une cadence hebdomadaire fonctionne. Elle maintient l'habitude en vie, et vous détectez un job en échec dans les sept jours au lieu de trente. Si un lien que vous avez construit mardi manque lundi, attendez le prochain rafraîchissement avant de paniquer.
Quand vous avez trois ou quatre dossiers datés, passez à la différence SQLite. Si vous êtes bloqué sur un code de réponse têtu, le tableau des limites de débit liste ce que chaque statut signifie pour une boucle.
Gardez le premier dossier comme référence. Chaque comparaison ultérieure pointe vers lui, et un dossier nommé par date est bien plus facile à faire confiance qu'un souvenir de à quoi ressemblaient les chiffres le printemps dernier. Restez cohérent.
Ajout des ancres et des pages principales
Une action par fichier garde les diffs lisibles. Copiez la boucle dans snap.py, changez refdomains en anchors ou toppages, et écrivez dans un deuxième nom de fichier. Chaque opération coûte 2 crédits.
Un fichier combiné cache quelle partie a changé, et un réviseur qui fait défiler une pull request veut voir un concept par diff. Gardez-les séparés. Si vous suivez trois domaines, bouclez sur une courte liste dans le workflow avec une matrice, afin que chaque cible ait son propre job et son propre échec.
Les ancres sont un deuxième fichier avec leur propre plafond dans le diff, donc révisez-les séparément des domaines référents. Chaque exécution reste peu coûteuse et répétable, c'est tout l'intérêt.
Lire le journal d'exécution
Ouvrez le journal de la première exécution. Faites-le avant de faire confiance à la planification. Cherchez le nombre de lignes, le solde et la ligne de commit. Si l'un des trois manque, le job a fait moins qu'il ne le prétend. Notez brièvement le solde à chaque exécution, afin que la dépense mensuelle soit visible sans ouvrir le tableau de bord.
Une coche verte dit peu. Elle signifie seulement que le processus s'est terminé proprement. Elle ne dit pas que le fichier contient les bonnes lignes, c'est pourquoi le script imprime son propre résumé. Gardez ces lignes de résumé inchangées entre les versions du script, afin qu'un diff de deux journaux ne montre que de vrais changements.
À quoi ressemble un journal sain
Une exécution saine imprime une ligne avec le nombre de lignes et le solde de crédits, puis un commit avec la date du jour. Tout ce qui enterr ces lignes sous du bruit supplémentaire mérite un deuxième regard.
Repérer un échec silencieux
Surveillez un dossier vide, un commit qui n'apparaît jamais, ou un nombre de lignes qui diffère du total. Chacun de ces points indique la boucle ou l'analyse, pas l'API elle-même. Sauvegardez le premier journal sain comme référence pour des comparaisons futures.
Certains échecs laissent un dossier derrière avec moins de lignes que d'habitude. Comparez le compte avec la semaine précédente avant de célébrer une exécution verte, car une troncature silencieuse ressemble exactement à un mois tranquille.
Ajouter une deuxième cible en sécurité
Un deuxième domaine est une entrée de matrice, pas une copie de tout le workflow. Donnez à chaque cible son propre job pour qu'un échec n'en cache pas un autre. Gardez chaque job séparé. Vérifiez que les chemins incluent le nom du domaine, pour que deux exécutions n'écrivent jamais dans le même fichier.
Commencez avec la deuxième cible seule. Une fois que son dossier semble correct, ajoutez le reste. Une matrice qui échoue à mi-parcours est plus difficile à lire que deux exécutions simples.
Nommez les dossiers par cible
Mettez le domaine dans le chemin, par exemple data/<domain>/YYYY-MM-DD, et les dossiers restent séparés même lorsque deux jobs s'exécutent dans la même minute. Les anciens dossiers peuvent rester où ils sont, car une date dans le chemin les rend faciles à trouver.
Utilisez la même règle de nommage pour chaque cible. Un script peut alors lister les dossiers sans cas spéciaux.
Planifiez d'abord le budget de crédits
Multipliez les appels par cible par le nombre de cibles, puis vérifiez le total par rapport à votre solde avant la première exécution. Une matrice multiplie la dépense aussi vite qu'elle multiplie les jobs. Écrivez le total mensuel attendu dans le dépôt à côté du workflow. Lorsque le solde baisse plus vite que cela, une boucle est probablement en train de récupérer à nouveau des pages, et vous pouvez l'arrêter avant la prochaine exécution.
Questions qui se posent la première semaine
Puis-je exécuter cela sur un dépôt privé gratuitement ?
Généralement oui, dans les minutes mensuelles que GitHub offre aux comptes gratuits. Un job de capture s'exécute en bien moins d'une minute, donc une planification hebdomadaire utilise une part minuscule. Vérifiez l'allocation actuelle de votre propre plan, car GitHub la modifie de temps en temps.
Où devrait vivre la clé si plusieurs personnes pushent ?
Dans un secret d'organisation ou de dépôt, jamais dans les fichiers. Quiconque peut modifier le workflow peut imprimer un secret dans un journal, donc limitez qui a un accès en écriture, et faites tourner la clé si quelqu'un quitte le projet.
Pourquoi mon exécution planifiée ne s'est-elle pas déclenchée ?
Trois raisons habituelles. Le fichier de workflow n'est pas sur la branche par défaut, le dépôt était inactif pendant 60 jours et GitHub a mis la planification en pause, ou la chaîne cron a une faute de frappe. Exécutez-le une fois avec workflow_dispatch pour écarter le script lui-même.
À quel point les dossiers de données grossissent-ils ?
Petits. Un millier de domaines référents représente quelques centaines de kilo-octets de JSON. Une année de fichiers hebdomadaires pour un domaine reste bien en dessous de cent mégaoctets, ce qui est bien pour git, bien que vous puissiez compresser les dossiers plus anciens si cela vous dérange.