Go बिल्ड का ऑटो-नंबरिंग: वर्ज़निंग समस्या का एक बार और हमेशा के लिए समाधान

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

मैन्युअल वर्ज़निंग हर Go डेवलपर का दर्द क्यों है

\n

क्या आपने कभी सोचा है: "प्रोडक्शन पर अभी कौन सा संस्करण चल रहा है?" या यह पता लगाने में एक घंटा बिताया कि एक महीने पहले बनाए गए बाइनरी में किस कमिट ने बग पैदा किया? यदि हाँ, तो आप सही जगह पर हैं। प्रश्न "Application auto build versioning" Stack Overflow पर सबसे लोकप्रिय में से एक है (हज़ारों व्यू और दर्जनों समाधान)। और यह सही भी है: आधुनिक विकास में, जहाँ CI/CD पाइपलाइन हर 10 मिनट में बिल्ड चलाती हैं, मैन्युअल संस्करण डालना अराजकता का रास्ता है।

\n

इस लेख में हम Go में बिल्ड का स्वचालित वर्ज़निंग शुरू से अंत तक समझेंगे। आप सीखेंगे कि ऐसी प्रणाली कैसे लागू करें जो स्वचालित रूप से संस्करण संख्या, कमिट हैश, बिल्ड तिथि और यहाँ तक कि "गंदे" रिपॉजिटरी का फ्लैग भी सेट करती है। कोड स्थानीय विकास और GitHub Actions, GitLab CI या Jenkins दोनों में काम करेगा।

\n\n

समस्या: मैन्युअल version.go में क्या गलत है?

\n

कई नौसिखिए डेवलपर एक फ़ाइल version.go बनाते हैं और लिखते हैं:

\n
package main\n\nvar Version = "1.0.0"
\n

और यह पहले कमिट तक काम करता है। फिर शुरू होता है:

\n
    \n
  • "मैं बिल्ड से पहले संस्करण अपडेट करना भूल गया"
  • \n
  • "प्रोडक्शन पर एक संस्करण है, कोड में दूसरा"
  • \n
  • "यह बिल्ड किस कमिट से मेल खाता है?"
  • \n
\n

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

\n\n

समाधान: ldflags — Go का गुप्त हथियार

\n

Go कंपाइलर आपको -ldflags फ्लैग के माध्यम से बिल्ड के दौरान वेरिएबल के मान "डालने" की अनुमति देता है। यही auto build versioning का क्लासिक रूप है। हम संस्करण को कोड में स्टोर नहीं करते — हम इसे कंपाइलर को पास करते हैं।

\n\n

चरण 1: संस्करण संरचना परिभाषित करें

\n

आइए वेरिएबल के साथ एक पैकेज version बनाएँ जो बिल्ड चरण में भरे जाएँगे:

\n
// version/version.go\npackage version\n\nvar (\n    // Version — सिमैंटिक संस्करण (मैन्युअल या git टैग के माध्यम से सेट किया गया)\n    Version = "dev"\n\n    // Commit — कमिट का छोटा हैश\n    Commit = "none"\n\n    // BuildTime — ISO 8601 प्रारूप में बिल्ड समय\n    BuildTime = "unknown"\n\n    // IsDirty — फ्लैग कि रिपॉजिटरी में अनकमिटेड परिवर्तन हैं\n    IsDirty = "false"\n)\n\nfunc String() string {\n    return "v" + Version + " (commit: " + Commit + ", built: " + BuildTime + ")"\n}
\n\n

चरण 2: ldflags के साथ बिल्ड करें

\n

अब सबसे दिलचस्प भाग। go build के बजाय हम एक स्क्रिप्ट या Makefile का उपयोग करेंगे जो आवश्यक मानों की गणना करता है और उन्हें कंपाइलर को पास करता है:

\n
#!/bin/bash\n# build.sh\n\nVERSION=$(git describe --tags --always --dirty 2>/dev/null || echo "dev")\nCOMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "none")\nBUILD_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ")\nIS_DIRTY=$(git diff --quiet || echo "true")\n\ngo build -ldflags="\\\n    -X 'main/version.Version=$VERSION' \\\n    -X 'main/version.Commit=$COMMIT' \\\n    -X 'main/version.BuildTime=$BUILD_TIME' \\\n    -X 'main/version.IsDirty=$IS_DIRTY'" \\\n    -o myapp .
\n

महत्वपूर्ण: पथ main/version.Version आपकी प्रोजेक्ट संरचना पर निर्भर करता है। यदि पैकेज version रूट में है — तो main/version.Version लिखें। यदि एक अलग निर्देशिका में — github.com/आपका-उपयोगकर्ता-नाम/प्रोजेक्ट/version.Version।

\n\n

चरण 3: एप्लिकेशन में उपयोग करें

\n

अब प्रोग्राम में कहीं भी संस्करण प्रदर्शित किया जा सकता है:

\n
// main.go\npackage main\n\nimport (\n    "fmt"\n    "main/version"\n)\n\nfunc main() {\n    fmt.Println("App version:", version.String())\n    fmt.Println("Is dirty repo:", version.IsDirty)\n}
\n

बिल्ड करें और चलाएँ:

\n
$ ./build.sh\n$ ./myapp\nApp version: v1.2.3 (commit: a1b2c3d, built: 2024-03-15T10:30:00Z)\nIs dirty repo: false
\n\n

उन्नत स्तर: सिमैंटिक

ब्लॉग

पुस्तक अनुशंसाएँ