अपने ट्रैक के लिए कंटीन्यूअस इंटीग्रेशन (CI) सेट अप करना बहुत ज़रूरी है, क्योंकि इससे गलतियाँ पकड़ने में मदद मिलती है।
Exercism के रेपो (ट्रैक रेपो सहित) अपनी CI चलाने के लिए GitHub Actions का उपयोग करते हैं। GitHub Actions वर्कफ्लो पर आधारित होते हैं, जो तय करते हैं कि कोई खास घटना होने पर (जैसे कोई कमिट पुश करना) कौन-सी स्क्रिप्ट अपने आप चलनी है। GitHub Actions वर्कफ्लो के बारे में अधिक जानकारी के लिए वर्कफ्लो डॉक्स देखिए।
ट्रैक पहले से ही कई वर्कफ्लो के साथ आते हैं, जिनमें से ज़्यादातर को आपको नहीं बदलना चाहिए (इन्हें शेयर्ड वर्कफ्लो कहा जाता है)।
हाँ, एक वर्कफ्लो ऐसा है जिसे आपको बदलना चाहिए, और वह है test.yml वर्कफ्लो।
test.yml वर्कफ्लो का उद्देश्य यह जाँचना है कि ट्रैक के अभ्यास ठीक हालत में हैं।
यह वर्कफ्लो अपने आप चलने के लिए सेट किया गया है (GitHub Actions की शब्दावली में: ट्रिगर होता है) जब main ब्रांच या किसी पुल रिक्वेस्ट की ब्रांच पर पुश किया जाता है।
वर्कफ्लो को खुद ज़्यादा कुछ करना नहीं है, इनके अलावा:
जैसा कि बताया गया, अभ्यासों की जाँच एक स्क्रिप्ट से होती है, यानी bin/verify-exercises (bash) स्क्रिप्ट से।
यह स्क्रिप्ट लगभग तैयार है, और यह निम्न काम करती है:
unskip_tests फंक्शन को कॉल करती है, जिसमें आप अपनी टेस्ट फाइलों के टेस्ट अनस्किप कर सकते हैं (वैकल्पिक)run_tests फंक्शन को कॉल करती है, जिसमें आपको टेस्ट चलाने हैं (आवश्यक)सिर्फ run_tests और unskip_tests फंक्शन ही वे चीज़ें हैं जिन्हें आपको लागू करना है।
अगर आपका ट्रैक टेस्ट स्किप करने का समर्थन करता है, तो हमें यह सुनिश्चित करना होगा कि किसी अभ्यास के उदाहरण/एक्ज़ेंप्लर हल की जाँच करते समय कोई टेस्ट स्किप न हो। आम तौर पर ट्रैक टेस्ट "अनस्किप" करने के दो तरीके अपनाते हैं:
test.skip को test में बदलना।SKIP_TESTS=false सेट करना।अगर टेस्ट स्किप करना फाइल-आधारित है (ऊपर बताया गया पहला विकल्प), तो टेस्ट फाइलों को बदलने के लिए unskip_tests फंक्शन में बदलाव कीजिए (मौजूदा कोड टेस्ट फाइलों पर लूप चलाने का काम पहले से करता है)।
unskip_test फंक्शन अभ्यास डायरेक्टरी की एक कॉपी पर चलता है, इसलिए फाइलों में जैसा आपको उचित लगे वैसा बदलाव बेझिझक कीजिए।
Arturo ट्रैक की bin/verify-exercises file टेस्ट फाइलों के भीतर टेस्ट अनस्किप करने के लिए sed का उपयोग करती है:
unskip_tests() {
jq -r '.files.test[]' .meta/config.json | while read -r test_file; do
sed -i 's/test.skip/test/g' "${test_file}"
done
}
अगर टेस्ट अनस्किप करने के लिए कोई एनवायरनमेंट वेरिएबल सेट करना ज़रूरी है, तो पक्का कीजिए कि वह run_tests फंक्शन में सेट हो।
run_tests फंक्शन किसी अभ्यास के टेस्ट चलाने की ज़िम्मेदारी लेता है।
जब इस फंक्शन को कॉल किया जाता है, तब तक उदाहरण/एक्ज़ेंप्लर फाइलें (स्टब) हल फाइलों में कॉपी हो चुकी होती हैं, इसलिए आपको बस टेस्ट चलाने के लिए सही कमांड कॉल करनी है।
अगर सारे टेस्ट पास हो जाएँ, तो फंक्शन को एग्ज़िट कोड के रूप में शून्य लौटाना चाहिए, वरना शून्य के अलावा कोई एग्ज़िट कोड लौटाना चाहिए।
run_tests फंक्शन अभ्यास डायरेक्टरी की एक कॉपी पर चलता है, इसलिए फाइलों में जैसा आपको उचित लगे वैसा बदलाव बेझिझक कीजिए।
अभ्यास जाँचने वाली स्क्रिप्ट के लिए डिफ़ॉल्ट विकल्प यह है कि भाषा के टूल (SDK/बाइनरी/आदि) का उपयोग किया जाए, और ज़्यादातर ट्रैक यही करते हैं। हर ट्रैक का टेस्ट चलाने का अपना तरीका होगा, लेकिन आम तौर पर यह बस एक ही कमांड होती है।
Arturo ट्रैक की bin/verify-exercises file run_tests फंक्शन को बदलकर टेस्ट फाइल पर सीधे arturo कमांड कॉल करती है:
run_tests() {
arturo tester.art
}
दूसरा विकल्प यह है कि ट्रैक के टेस्ट रनर को चलाकर अभ्यासों की जाँच की जाए। यह निश्चित रूप से इस बात पर निर्भर करता है कि ट्रैक के पास काम करने वाला टेस्ट रनर हो।
अगर आपके ट्रैक में अभी टेस्ट रनर नहीं है, तो आप या तो:
डिफ़ॉल्ट bin/verify-exercises स्क्रिप्ट में ये बदलाव करने होंगे:
docker कमांड उपलब्ध हैdocker run का उपयोग कीजिएjq का उपयोग करके जाँचिए कि Docker कंटेनर से लौटी results.json फाइल बताती है कि सारे टेस्ट पास हुएunskip_test फंक्शन और उस फंक्शन को कॉल करना हटा दीजिएइस तरीके का सबसे बड़ा फायदा यह है कि यह सबसे अच्छी तरह उसी तरह की नकल करता है जैसे प्रोडक्शन में (वेबसाइट पर) टेस्ट चलाए जाते हैं। इस तरीके से यह संभावना कम हो जाती है कि CI में पास हुई कोई चीज़ प्रोडक्शन में फेल हो। इस तरीके का नुकसान यह है कि यह आम तौर पर धीमा होता है, क्योंकि Docker इमेज पुल करनी पड़ती है और Docker का ओवरहेड भी लगता है।
Unison ट्रैक की bin/verify-exercises file एक जाँच जोड़ती है ताकि पक्का हो सके कि docker कमांड भी इंस्टॉल है:
required_tool docker
फिर यह ट्रैक की टेस्ट रनर इमेज पुल करती है:
docker pull exercism/unison-test-runner
इसके बाद यह run_tests फंक्शन को बदलती है ताकि docker run से मौजूदा अभ्यास (जो वर्किंग डायरेक्टरी में है) पर टेस्ट रनर चले, और उसके बाद jq कमांड से सही स्टेटस की जाँच हो:
run_tests() {
local slug
slug="${1}"
docker run \
--rm \
--network none \
--mount type=bind,src="${PWD}",dst=/solution \
--mount type=bind,src="${PWD}",dst=/output \
--tmpfs /tmp:rw \
exercism/unison-test-runner "${slug}" "/solution" "/output"
jq -e '.status == "pass"' "${PWD}/results.json" >/dev/null 2>&1
}
आखिर में, हमें run_tests कमांड को कॉल करने का तरीका बदलना होगा, क्योंकि अब इसे स्लग चाहिए:
run_tests "${slug}"
अब जब verify-exercises स्क्रिप्ट तैयार है, तो test.yml वर्कफ्लो को अंतिम रूप देने का समय है।
यह कैसे करना है, यह इस पर निर्भर करता है कि verify-exercises स्क्रिप्ट लागू करने के लिए कौन-सा विकल्प चुना गया था।
अगर verify-exercises स्क्रिप्ट सीधे भाषा के टूल का उपयोग करती है, तो टेस्ट वर्कफ्लो को ये इंस्टॉल करने होंगे:
यह हो जाने के बाद verify-exercises अपेक्षा के अनुसार काम करनी चाहिए, और आपने सफलतापूर्वक CI सेट अप कर लिया है!
उदाहरण के लिए, Arturo ट्रैक का test.yml वर्कफ्लो देखिए:
name: Test
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
jobs:
ci:
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install libgtk-3-dev libwebkit2gtk-4.0-dev libmpfr-dev
- name: Install Arturo
run: bin/install-arturo
env:
GH_TOKEN: ${{ github.token }}
- name: Verify all exercises
run: bin/verify-exercises
दूसरा विकल्प यह है कि ट्रैक के टेस्ट रनर को चलाकर अभ्यासों की जाँच की जाए। इस विकल्प के लिए दो बातें सही होनी चाहिए:
verify-exercises स्क्रिप्ट किसी अभ्यास के टेस्ट चलाने के लिए टेस्ट रनर की Docker इमेज का उपयोग करती होअगर आपके ट्रैक में अभी टेस्ट रनर नहीं है, तो आप या तो:
इस तरीके के कुछ फायदे हैं:
मुख्य नुकसान यह है कि यह शायद धीमा होता है, क्योंकि Docker इमेज पुल करनी पड़ती है और Docker का ओवरहेड भी लगता है।
टेस्ट रनर की Docker इमेज पुल करने के कुछ तरीके हैं:
verify-exercises फाइल के अंदर ही इमेज डाउनलोड करना।
Unison ट्रैक यही तरीका अपनाता है।तो कौन-सा तरीका अपनाना चाहिए?
हमारी सलाह है कि कम से कम विकल्प 1 ज़रूर लागू कीजिए, ताकि verify-exercises स्क्रिप्ट स्टैंडअलोन हो जाए।
अगर आपकी इमेज खास तौर पर बड़ी है, तो विकल्प 3 भी लागू करना फायदेमंद हो सकता है, जो बनाई गई Docker इमेज को GitHub Actions के कैश में संग्रहीत कर देगा।
इसके बाद की बार चलने पर Docker इमेज डाउनलोड करने के बजाय सीधे कैश से पढ़ी जा सकती है, जो परफॉर्मेंस के लिए बेहतर हो सकता है (पक्का करने के लिए खुद नाप-तौल कीजिए)।
एक तीसरा, वैकल्पिक तरीका पिछले दो विकल्पों का मिश्रण है।
यहाँ भी हम टेस्ट रनर की Docker इमेज का उपयोग करते हैं, बस इस बार हम verify-exercises स्क्रिप्ट उसी Docker इमेज के अंदर चलाते हैं।
इस विकल्प को चालू करने के लिए हमें वर्कफ्लो के कंटेनर को टेस्ट रनर पर सेट करना होगा:
container:
image: exercism/vimscript-test-runner
इसके बाद हम डिपेंडेंसी और टूल इंस्टॉल करने के चरण छोड़ सकते हैं (क्योंकि वे टेस्ट रनर की Docker इमेज के अंदर इंस्टॉल हो चुके होंगे) और सीधे bin/verify-exercises स्क्रिप्ट चला सकते हैं।
vimscript ट्रैक का test.yml वर्कफ्लो यह विकल्प अपनाता है:
name: Verify Exercises
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
jobs:
ci:
runs-on: ubuntu-24.04
container:
image: exercism/vimscript-test-runner
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- name: Verify all exercises
run: bin/verify-exercises