Instrukcja obsługi

Tygodniowe snapshoty backlinków na GitHub Actions: instrukcja obsługi

Cel: każdego poniedziałku workflow zapisuje dzisiejsze domeny odsyłające i kotwice w repozytorium. Nic więcej. Porównania (diffing) pojawią się później.

Most żelazny nad rzeką, symbolizujący niezawodną infrastrukturę zaplanowanych workflow
Zanim zaczniesz

Potrzebujesz repozytorium, klucza Linkzoid przechowywanego jako sekret LZ_KEY oraz jednej domeny, którą posiadasz. Budżet: około 6 kredytów na cel przy każdym uruchomieniu, co daje $0.0006. Snapshot to fakt dotyczący jednego miesiąca, więc cotygodniowe uruchomienia pobierają głównie ten sam indeks. Konfiguracja sposobu sprawdzania backlinków do Twojej strony w ten sposób zajmie jeden wieczór.

Instrukcja obsługi, krok po kroku

01

1. Dodaj sekret

Ustawienia repozytorium, następnie Secrets and variables, potem Actions. Nazwij go LZ_KEY. Jeśli wkleisz go do pliku workflow, obróć klucz jeszcze dziś.

02

2. Zatwierdź skrypt

Zapisz poniższy kod Pythona jako snap.py. Zapisuje on data/YYYY-MM-DD/refdomains.json i kończy działanie przy dowolnej odpowiedzi, gdzie ok jest false.

03

3. Zatwierdź workflow

Użyj poniższego YAML. Uruchom go raz ręcznie za pomocą wyzwalacza workflow_dispatch i przeczytaj log przed zaufaniem harmonogramowi.

04

4. Sprawdź pierwszy plik

Otwórz JSON. Potwierdź liczbę wierszy względem total i porównaj liczbę z tym, co zgłasza darmowe wywołanie overview dla Twojej domeny.

05

5. Dodaj alert

Nieudana praca domyślnie wysyła e-mail do właściciela repozytorium. Zostaw to tak jest. Praca, która cicho się kończy, to zwykle sposób, w jaki takie konfiguracje upadają.

snap.py

Biblioteka standardowa. Pętla kończy się na podstawie licznika, a nie na podstawie zgadywania.

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 w GitHub działa w UTC i może się rozpocząć z opóźnieniem, gdy runnerzy są zajęci. Nie buduj niczego, co zależy od minuty.

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
Ogrośnik przycinający mładą sadzonkę, reprezentujący przygotowanie przed rozpoczęciem harmonogramu

Zanim włączysz harmonogram

  • Klucz znajduje się w sekretach repozytorium, a YAML odwołuje się do niego tylko po nazwie.
  • Plik workflow znajduje się na domyślnej gałęzi, ponieważ to ta kopia jest odczytywana przez harmonogram.
  • Ręczne uruchomienie z workflow_dispatch zakończyło się i utworzyło jeden folder z datą.
  • Liczba wierszy w pliku odpowiada całkowitej liczbie zwróconej przez API dla tego wywołania.
  • Praca kończy się kodem niezerowym przy złej odpowiedzi, więc awaria oznacza czerwony wynik uruchomienia.

Błędy i poprawki

Co psuje się najpierw w zaplanowanej pracy dotyczącej backlinków
BłądCo widziszPoprawka
Klucz wklejony w YAMLKlucz widoczny w historii repozytoriumObróć go, przenieś do secrets.LZ_KEY
Nierówna minuta, np. 0 0Uruchomienie zaczyna się 20 minut późniejWybierz 17 6; początek godziny jest zatłoczony
Repozytorium bezczynne przez 60 dniGitHub wstrzymuje harmonogramZatwierdź coś lub ponownie włącz go w zakładce Actions
Pętla zatrzymuje się tylko na pustej stronieNieskończone uruchomienie przy limicie stronZatrzymaj się również, gdy len(rows) >= total
Kod wyjścia ignorowanyZielony znacznik, pusty folderUżyj sys.exit przy ok: false
Zatwierdzenie nie udaje się przy braku zmianCzerwone uruchomienie bez powoduDodaj || exit 0 po zatwierdzeniu

Bezpieczne przechowywanie klucza i repozytorium

Klucz to jedyna rzecz w tej konfiguracji warta ochrony. Traktuj go jak hasło, ponieważ każdy, kto go posiada, może wydać Twój balans.

Zaplanowane zadania cicho wyciekają. Klucz wklejony w log, workflow skopiowany do publicznego repozytorium lub były współpracownik z dostępem do zapisu to typowe ścieżki. Sprawdź każdą z nich raz na kwartał.

Obróć klucz, gdy ktoś odejdzie

Gdy współpracownik z dostępem odejdzie, utwórz nowy klucz, zaktualizuj sekret i wycofaj stary. Następnie potwierdź, że kolejne uruchomienie powiedzie się. Jedno zielone uruchomienie po zmianie to najtańszy test, jaki zrobisz w tym roku. Zapisz też datę obrotu w notatkach repozytorium, aby następny obrót nie był zaskoczeniem.

Ogranicz osobę, która może edytować workflow

Każdy, kto może edytować YAML, może wydrukować sekret w uruchomieniu. Ogranicz dostęp do zapisu i przeglądaj zmiany w pliku workflow tak, jak przeglądasz kod. Dwie osoby z dostępem do zapisu to zwykle wystarczająco dla małego repozytorium.

Nigdy nie drukuj URL żądania

Wydrukuj balans i liczbę wierszy, nigdy URL żądania. Klucz podróżuje w stringu zapytania, więc linia debugująca, która drukuje URL, zapisuje klucz w logu. Jeśli musisz udostępnić żądanie w issue, najpierw zamień klucz na placeholder.

Kompas i doniczkowa roślina, wskazujące na stały postęp i wczesne wykrywanie problemów

Czym jest snapshot, a czym nie

To, co otrzymasz, to obraz miesięczny. Nasz własny crawler odświeża indeks około raz w miesiącu, więc dwa poniedziałkowe uruchomienia w tym samym miesiącu często zwracają te same wiersze. To jest oczekiwane.

Co tydzień to dobra częstotliwość. Utrzymuje nawyk przy życiu, a zauważysz awarię pracy w ciągu siedmiu dni, a nie trzydziestu. Jeśli link, który zbudowałeś we wtorek, brakuje w poniedziałek, poczekaj na następne odświeżenie, zanim zaczniesz panikować.

Gdy masz trzy lub cztery foldery z datą, przejdź do różnicy profilu backlinków w SQLite. Jeśli utknąłeś na uporczywym kodzie odpowiedzi, tabela limitu szybkości wskazuje, co oznacza każdy status dla pętli.

Zachowaj pierwszy folder jako punkt odniesienia. Każde późniejsze porównanie odnosi się do niego, a folder nazwany datą jest znacznie łatwiejszy do zaufania niż pamięć tego, jak wyglądały liczby zeszłej wiosny. Bądź konsekwentny.

Dodawanie kotwic i najlepszych podstron

Jedna akcja na plik utrzymuje czytelność diffów. Skopiuj pętlę w snap.py, zmień refdomains na anchors lub toppages i zapisz do drugiego pliku. Każda kosztuje 2 kredyty.

Połączony plik ukrywa, która część się zmieniła, a recenzent przewijający pull request chce widzieć jedną koncepcję na diff. Trzymaj je oddzielnie. Jeśli śledzisz trzy domeny, zmapuj krótką listę w workflow za pomocą macierzy, aby każdy cel miał własne zadanie i własną awarię.

Kotwice to drugi plik z własnym limitem w diffie, więc przeglądaj je oddzielnie od domen odsyłających. Każde uruchomienie pozostaje tanie i powtarzalne, co jest głównym celem.

Czytanie logu uruchomienia

Otwórz log pierwszego uruchomienia. Zrób to przed zaufaniem harmonogramowi. Szukaj liczby wierszy, balansu i linii zatwierdzenia. Jeśli którakolwiek z tych trzech rzeczy brakuje, praca zrobiła mniej, niż twierdzi. Zapisuj też krótką notatkę z balansem przy każdym uruchomieniu, aby miesięczny wydatek był widoczny bez otwierania panelu.

Zielony znacznik mówi niewiele. Oznacza tylko, że proces zakończył się czysto. Nie mówi, że plik zawiera właściwe wiersze, dlatego skrypt drukuje własne podsumowanie. Zostaw te linie podsumowania niezmienione między wersjami skryptu, aby diff dwóch logów pokazywał tylko prawdziwe zmiany.

Jak wygląda zdrowy log

Zdrowe uruchomienie drukuje jedną linię z liczbą wierszy i balansem kredytów, a następnie zatwierdzenie z dzisiejszą datą. Wszystko, co zagrzebuje te linie pod dodatkowym szumem, warte jest drugiego spojrzenia.

Wykrywanie cichej awarii

Obserwuj pusty folder, zatwierdzenie, które nigdy nie pojawia się, lub liczbę wierszy, która różni się od total. Każda z tych rzeczy wskazuje na pętlę lub parsowanie, a nie na samo API. Zapisz pierwszy zdrowy log jako odniesienie do późniejszych porównań.

Niektóre awarie pozostawiają folder z mniejszą liczbą wierszy niż zwykle. Porównaj liczbę z poprzednim tygodniem, zanim zataczasz się od radości z zielonego wyniku, ponieważ cicha truncacja wygląda dokładnie jak cichy miesiąc.

Bezpieczne dodanie drugiego celu

Druga domena to wpis macierzy, a nie kopia całego workflow. Nadaj każdemu celowi własne zadanie, aby jedna awaria nie ukrywała innej. Trzymaj każde zadanie oddzielnie. Sprawdź, czy ścieżki zawierają nazwę domeny, aby dwa uruchomienia nigdy nie zapisywały się do tego samego pliku.

Zacznij od samego drugiego celu. Gdy jego folder wygląda poprawnie, dodaj resztę. Macierz, która zawodzi w połowie, jest trudniejsza do odczytania niż dwa proste uruchomienia.

Nazwij foldery według celu

Umieść domenę w ścieżce, np. data/<domain>/YYYY-MM-DD, a foldery pozostaną oddzielne, nawet gdy dwa zadania uruchomią się w tej samej minucie. Stare foldery mogą pozostać tam, gdzie są, ponieważ data w ścieżce ułatwia ich znalezienie.

Używaj tej samej reguły nazewnictwa dla każdego celu. Skrypt może wtedy listować foldery bez przypadków specjalnych.

Zaplanuj budżet kredytów najpierw

Pomnóż wywołania na cel przez liczbę celów, a następnie sprawdź całkowitą liczbę przeciwko swojemu balansowi przed pierwszym uruchomieniem. Macierz mnoży wydatki tak szybko, jak mnoży zadania. Zapisz spodziewany miesięczny total w repozytorium obok workflow. Gdy balans spada szybciej niż ten, prawdopodobnie pętla ponownie pobiera strony i możesz ją zatrzymać przed kolejnym uruchomieniem.

Pytania, które pojawiają się w pierwszym tygodniu

Czy mogę uruchomić to na prywatnym repozytorium za darmo?
Zazwyczaj tak, w ramach miesięcznych minut, które GitHub daje kontom darmowym. Zadanie snapshotu wykonuje się w znacznie mniej niż minutę, więc cotygodniowy harmonogram zużywa niewielką część. Sprawdź aktualne przydziały swojego planu, ponieważ GitHub zmienia je od czasu do czasu.
Gdzie powinien znajdować się klucz, jeśli kilku osób robi push?
W sekretach organizacji lub repozytorium, nigdy w plikach. Każdy, kto może edytować workflow, może wydrukować sekret w logu, więc ogranicz dostęp do zapisu i obróć klucz, jeśli ktoś opuści projekt.
Dlaczego moje zaplanowane uruchomienie nie wystąpiło?
Trzy typowe przyczyny. Plik workflow nie jest na domyślnej gałęzi, repozytorium było bezczynne przez 60 dni i GitHub wstrzymał harmonogram, lub ciąg cron ma literówkę. Uruchom go raz z workflow_dispatch, aby wykluczyć sam skrypt.
Jak duże stają się foldery danych?
Małe. Tysiąc domen odsyłających to kilka setek kilobajtów JSON. Rok cotygodniowych plików dla jednej domeny mieści się dobrze w stu megabajtach, co jest w porządku dla git, choć możesz skompresować starsze foldery, jeśli ci to przeszkadza.