रनबुक

GitHub Actions पर साप्ताहिक बैकलिंक स्नैपशॉट: एक रनबुक

लक्ष्य: हर सोमवार एक वर्कफ़्लो आज के रेफरिंग डोमेन्स और एंकर टेक्स्ट को रीपो में लिखता है। कुछ और नहीं। डिफ़िंग बाद में आएगी।

नदी पर एक लोहे की पुल, विश्वसनीय शेड्यूल्ड वर्कफ़्लो इंफ्रास्ट्रक्चर का प्रतीक
शुरू करने से पहले

आपके पास एक रीपो, एक Linkzoid कुंजी जो LZ_KEY के रूप में सेक्रेट में स्टोर है, और एक डोमेन की आवश्यकता है जिसे आप स्वयं चलाते हैं। बजट: रन प्रति टारगेट लगभग 6 क्रेडिट्स, जो $0.0006 है। एक स्नैपशॉट एक महीने के बारे में तथ्य है, इसलिए साप्ताहिक रन ज्यादातर उसी इंडेक्स को फिर से खींचते हैं। इस तरह अपनी वेबसाइट पर बैकलिंक्स की जाँच कैसे करें, इसकी सेटिंग करने में एक शाम लगती है।

रनबुक, क्रम में

01

1. सेक्रेट जोड़ें

रीपो सेटिंग्स, फिर Secrets and variables, फिर Actions। इसे LZ_KEY नाम दें। यदि आप इसे वर्कफ़्लो फ़ाइल में पेस्ट करते हैं, तो आज ही कुंजी रोटेट करें।

02

2. स्क्रिप्ट कमिट करें

नीचे दी गई Python को snap.py के रूप में सेव करें। यह data/YYYY-MM-DD/refdomains.json लिखता है और किसी भी प्रतिक्रिया पर फेल होता है जहाँ ok गलत है।

03

3. वर्कफ़्लो कमिट करें

नीचे दी गई YAML का उपयोग करें। शेड्यूल पर भरोसा करने से पहले workflow_dispatch ट्रिगर के साथ इसे एक बार मैन्युअल रूप से चलाएं और लॉग पढ़ें।

04

4. पहली फ़ाइल की जाँच करें

JSON खोलें। total के खिलाफ़ रो काउंट की पुष्टि करें, और अपने डोमेन के लिए फ्री overview कॉल द्वारा रिपोर्ट किए गए नंबर से तुलना करें।

05

5. अलर्ट जोड़ें

एक फेल हुई जॉब डिफ़ॉल्ट रूप से रीपो मालिक को ईमेल भेजती है। उसे वैसे ही छोड़ें। एक जॉब जो शांति से रुक जाती है, ये सेटअप मरने का सामान्य तरीका है।

snap.py

स्टैंडर्ड लाइब्रेरी। लूप काउंट पर समाप्त होता है, अनुमान पर नहीं।

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

GitHub में Cron UTC में चलता है और रनर्स व्यस्त होने पर देर से शुरू हो सकता है। किसी भी चीज़ पर निर्भर न करें जो मिनट पर निर्भर करती है।

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
एक युवा अंकुर की कटाव करते हुए एक बगीचे का कामगार, शेड्यूल शुरू करने से पहले तैयारी का प्रतिनिधित्व

शेड्यूल चालू करने से पहले

  • कुंजी रीपो सेक्रेट्स में है, और YAML केवल उसका नाम संदर्भित करता है।
  • वर्कफ़्लो फ़ाइल डिफ़ॉल्ट ब्रांच पर है, क्योंकि वही कॉपी शेड्यूल पढ़ता है।
  • workflow_dispatch के साथ एक मैन्युअल रन समाप्त हो गया और एक तारीख-वाली फ़ोल्डर लिखी।
  • फ़ाइल में रो काउंट उस कॉल के लिए API द्वारा लौटाए गए टोटल से मेल खाता है।
  • जॉब खराब प्रतिक्रिया पर नॉन-ज़ीरो एग्जिट कोड के साथ समाप्त होती है, इसलिए एक फेल्योर रन को लाल बना देता है।

गलतियाँ और समाधान

एक शेड्यूल्ड बैकलिंक जॉब में सबसे पहले क्या टूटता है
गलतीआपको क्या दिखता हैसमाधान
YAML में कुंजी पेस्ट की गईरीपो इतिहास में कुंजी दिखाई देती हैइसे रोटेट करें, secrets.LZ_KEY में ले जाएं
अजीब मिनट जैसे 0 0रन 20 मिनट देर से शुरू होता है17 6 चुनें; घंटे की शुरुआत भीड़भाड़ वाली होती है
रीपो 60 दिनों के लिए आइडलGitHub शेड्यूल को रोक देता हैकुछ भी कमिट करें, या Actions टैब में इसे फिर से सक्षम करें
लूप केवल खाली पेज पर रुकता हैपेज कैप पर अनंत रनlen(rows) >= total होने पर भी रुकें
एग्जिट कोड अनदेखा किया गयाहरा चेक, खाली फ़ोल्डरok: false पर sys.exit का उपयोग करें
बदलाव न होने पर कम्माइट फेल हो जाता हैबिना किसी वजह लाल रनकम्माइट के बाद || exit 0 जोड़ें

कुंजी और रिपॉजिटरी को सुरक्षित रखना

इस सेटअप में कुंजी ही एकमात्र चीज है जिसे बचाने की जरूरत है। इसे पासवर्ड की तरह मानें, क्योंकि इसे पकड़ने वाला किसी भी व्यक्ति आपके बैलेंस का इस्तेमाल कर सकता है।

शेड्यूल किए गए जॉब धीरे-धीरे लीक होते हैं। लॉग में पेस्ट की गई कुंजी, पब्लिक रिपॉजिटरी में कॉपी किया गया वर्कफ़्लो, या लिखने का एक्सेस रखने वाला एक पूर्व सहकर्मी आमतौर पर लीक के रास्ते होते हैं। हर तिमाही में इनकी जाँच करें।

जब कोई व्यक्ति चला जाता है तो कुंजी बदलें

जब एक्सेस रखने वाला सहकर्मी चला जाता है, तो एक नई कुंजी बनाएं, सीक्रेट अपडेट करें और पुरानी कुंजी को निष्क्रिय कर दें। फिर पुष्टि करें कि अगला रन पास हो गया है। बदलाव के बाद एक ही हरा रन वह सबसे सस्ता परीक्षण है जो आप पूरे साल करेंगे। अगली बार कुंजी बदलने की तारीख रिपॉजिटरी नोट्स में भी लिखें, ताकि अगली बार कुंजी बदलने पर कोई हैरानी न हो।

वर्कफ़्लो को एडिट करने वालों की संख्या सीमित करें

जो भी YAML एडिट कर सकता है, वह रन के दौरान सीक्रेट प्रिंट कर सकता है। लिखने का एक्सेस छोटा रखें, और वर्कफ़्लो फ़ाइल में बदलावों की समीक्षा उसी तरह करें जैसे आप कोड की समीक्षा करते हैं। एक छोटे रिपॉजिटरी के लिए दो लोगों के पास लिखने का एक्सेस आमतौर पर काफी होता है।

रिक्वेस्ट URL कभी प्रिंट न करें

बैलेंस और रो काउंट प्रिंट करें, कभी भी रिक्वेस्ट URL नहीं। कुंजी क्वेरी स्ट्रिंग में यात्रा करती है, इसलिए URL प्रिंट करने वाली एक डीबग लाइन कुंजी को लॉग में लिख देती है। यदि आपको किसी इश्यू में रिक्वेस्ट शेयर करनी है, तो पहले कुंजी को एक प्लेसहोल्डर से बदल दें।

कंपास और पॉटेड प्लांट, स्थिर प्रगति और शुरुआती समस्या पहचान को दर्शाता है

स्नैपशॉट क्या है, और क्या नहीं

आपको जो मिलता है वह एक मासिक तस्वीर है। हमारा अपना क्रॉलर इंडेक्स को लगभग एक बार महीने में रीफ्रेश करता है, इसलिए एक ही महीने में दो सोमवार के रन अक्सर एक ही रो लौटाते हैं। यह अपेक्षित है।

एक साप्ताहिक कैडेंस काम करता है। यह आदत को जीवित रखता है, और आप एक फेल हुए जॉब को तीस दिन की जगह सात दिनों के भीतर पकड़ लेते हैं। यदि मंगलवार को बनाया गया लिंक सोमवार को गायब है, तो घबराने से पहले अगले रीफ्रेश का इंतज़ार करें।

जब आपके पास तीन या चार तारीख वाली फ़ोल्डर हो जाएं, तो SQLite डीफ़ पर जाएं। यदि आप किसी जिद्दी रिस्पॉन्स कोड पर फंसे हैं, तो रेट-लिमिट टेबल में लिस्ट किया गया है कि लूप के लिए प्रत्येक स्टेटस का क्या मतलब है।

पहला फ़ोल्डर बेसलाइन के रूप में रखें। हर बाद की तुलना उसी की ओर इशारा करती है, और तारीख से नामित फ़ोल्डर इस बात के भरोसे करने में कहीं ज्यादा आसान है कि अंकों की स्थिति पिछले बसंत में कैसी थी। स्थिर रहें।

एंकर और टॉप पेज जोड़ना

प्रत्येक फ़ाइल में एक एक्शन डीफ़ को पठनीय रखता है। snap.py में लूप कॉपी करें, refdomains को anchors या toppages में बदलें, और एक दूसरी फ़ाइल नाम में लिखें। प्रत्येक की लागत 2 क्रेडिट है।

एक संयुक्त फ़ाइल यह छुपा देती है कि किस भाग में बदलाव हुआ है, और एक रिव्यूअर जो पुल रिक्वेस्ट में स्क्रॉल कर रहा है, वह एक डीफ़ में एक ही कॉन्सेप्ट देखना चाहता है। उन्हें अलग रखें। यदि आप तीन डोमेन ट्रैक करते हैं, तो वर्कफ़्लो में एक शॉर्ट लिस्ट पर लूप चलाएं मैट्रिक्स के साथ, ताकि प्रत्येक टारगेट को अपना जॉब और अपनी फेलियर मिले।

एंकर एक दूसरी फ़ाइल हैं जिनका अपना कैप डीफ़ में होता है, इसलिए उन्हें रिफरिंग डोमेन से अलग समीक्षा करें। प्रत्येक रन सस्ता और दोहराने योग्य रहता है, जो कि पूरा विचार है।

रन लॉग पढ़ना

पहले रन का लॉग खोलें। इसे शेड्यूल पर भरोसा करने से पहले करें। रो काउंट, बैलेंस और कम्माइट लाइन की तलाश करें। यदि इनमें से कोई भी गायब है, तो जॉब ने जो दावा किया है उससे कम किया है। प्रत्येक रन के दौरान बैलेंस का एक छोटा नोट भी रखें, ताकि मासिक खर्च डैशबोर्ड खोले बिना दिखाई दे।

एक हरा चेक कम बात कहता है। यह केवल इतना बताता है कि प्रक्रिया साफ़ तरीके से समाप्त हुई। यह यह नहीं बताता कि फ़ाइल में सही रो हैं, इसलिए स्क्रिप्ट अपना सारांश प्रिंट करती है। स्क्रिप्ट के संस्करणों के बीच इन सारांश लाइनों को अपरिवर्तित रखें, ताकि दो लॉग का डीफ़ केवल असली बदलाव दिखाए।

एक स्वस्थ लॉग कैसा दिखता है

एक स्वस्थ रन रो काउंट और क्रेडिट बैलेंस वाली एक लाइन प्रिंट करता है, फिर आज की तारीख के साथ एक कम्माइट। कोई भी चीज जो उन लाइनों को अतिरिक्त शोर के नीचे दबा देती है, उस पर एक बार फिर देखने की जरूरत है।

एक सilent फेलियर को पहचानना

एक खाली फ़ोल्डर, एक कम्माइट जो कभी नहीं आता, या एक रो काउंट जो टोटल से अलग है, इसकी ओर ध्यान दें। इनमें से प्रत्येक लूप या पार्स की ओर इशारा करता है, API की ओर नहीं। बाद की तुलना के लिए पहले स्वस्थ लॉग को एक संदर्भ के रूप में सहेजें।

कुछ फेलियर एक फ़ोल्डर पीछे छोड़ते हैं जिसमें आमतौर से कम रो होते हैं। एक हरे रन की जश्न मनाने से पहले पिछले सप्ताह के साथ काउंट की तुलना करें, क्योंकि एक शांत ट्रंकेशन एक शांत महीने की तरह ही दिखता है।

एक दूसरे टारगेट को सुरक्षित रूप से जोड़ना

एक दूसरा डोमेन एक मैट्रिक्स एंट्री है, पूरे वर्कफ़्लो की कॉपी नहीं। प्रत्येक टारगेट को अपना जॉब दें ताकि एक फेलियर दूसरे को छुपा न दे। प्रत्येक जॉब को अलग रखें। जांचें कि पाथ में डोमेन नाम शामिल है, ताकि दो रन कभी एक ही फ़ाइल में न लिखें।

पहले दूसरे टारगेट के साथ शुरू करें। जब उसका फ़ोल्डर सही दिखने लगे, तो बाकी जोड़ें। एक मैट्रिक्स जो आधे रास्ते में फेल हो जाता है, दो सरल रनों की तुलना में पढ़ने में कहीं ज्यादा कठिन है।

फ़ोल्डर को टारगेट के नाम से नाम दें

पाथ में डोमेन डालें, उदाहरण के लिए data/<domain>/YYYY-MM-DD, और फ़ोल्डर अलग रहेंगे भले ही दो जॉब एक ही मिनट में चलें। पुराने फ़ोल्डर वहीं रह सकते हैं, क्योंकि पाथ में तारीख उन्हें आसानी से खोजने योग्य बनाती है।

हर टारगेट के लिए एक ही नामकरण नियम का उपयोग करें। एक स्क्रिप्ट तब विशेष मामलों के बिना फ़ोल्डर की सूची बना सकती है।

पहले क्रेडिट बजट की योजना बनाएं

प्रत्येक टारगेट के लिए कॉल्स को टारगेट की संख्या से गुणा करें, फिर पहले रन से पहले कुल राशि को अपने बैलेंस से मिलाएं। एक मैट्रिक्स जॉब की तरह ही खर्च को तेज़ी से बढ़ाता है। वर्कफ़्लो के बगल में रिपॉजिटरी में अपेक्षित मासिक कुल लिखें। जब बैलेंस उससे तेज़ी से गिरता है, तो एक लूप शायद पेजों को फिर से फेच कर रहा है, और आप अगले रन से पहले इसे रोक सकते हैं।

पहले सप्ताह में आने वाले सवाल

क्या मैं इसे निजी रिपॉजिटरी पर मुफ्त चला सकता हूँ?
आमतौर पर हाँ, मासिक मिनटों के भीतर जिन्हें गिटहब फ्री अकाउंट देता है। एक स्नैपशॉट जॉब एक मिनट से भी कम समय में चलता है, इसलिए एक साप्ताहिक शेड्यूल एक छोटा हिस्सा उपयोग करता है। अपने प्लान की वर्तमान अनुमति की जाँच करें, क्योंकि गिटहब कभी-कभी इसे बदल देता है।
यदि कई लोग पश करते हैं तो कुंजी कहाँ रहनी चाहिए?
एक संगठन या रिपॉजिटरी सीक्रेट में, फ़ाइलों में कभी नहीं। जो भी वर्कफ़्लो एडिट कर सकता है, वह लॉग में एक सीक्रेट प्रिंट कर सकता है, इसलिए लिखने का एक्सेस सीमित रखें, और कुंजी को बदलें यदि कोई व्यक्ति प्रोजेक्ट छोड़ देता है।
मेरा शेड्यूल्ड रन क्यों फायर नहीं हुआ?
तीन आमतौर पर कारण। वर्कफ़्लो फ़ाइल डिफ़ॉल्ट ब्रांच पर नहीं है, रिपॉजिटरी 60 दिनों के लिए आइडल रहा और गिटहब ने शेड्यूल को रोका, या क्रॉन स्ट्रिंग में टाइपो है। स्क्रिप्ट को छोड़ने के लिए इसे एक बार workflow_dispatch के साथ चलाएं।
डेटा फ़ोल्डर कितने बड़े होते हैं?
छोटे। एक हज़ार रिफरिंग डोमेन JSON के कुछ सौ किलोबाइट हैं। एक डोमेन के लिए एक साल के साप्ताहिक फ़ाइलें गिट के लिए ठीक हैं, हालाँकि यदि यह परेशान करता है तो आप पुराने फ़ोल्डर को कंप्रेस कर सकते हैं।