iOS பயன்பாடுகளை உருவாக்கி வழங்குவதற்கான அம்சங்கள்

இந்தக் கட்டுரையில், CI/CD பிழைத்திருத்தம் செய்யும் செயல்பாட்டில் Plarium Krasnodar ஸ்டுடியோ திரட்டிய iOS பயன்பாடுகளை அசெம்பிள் செய்து பயனர்களுக்கு வழங்கும் அனுபவத்தைப் பகிர்ந்து கொள்கிறோம்.

iOS பயன்பாடுகளை உருவாக்கி வழங்குவதற்கான அம்சங்கள்

பயிற்சி

ஆப்பிள் சாதனங்களுக்கான பயன்பாடுகளின் மேம்பாட்டில் ஈடுபட்டுள்ள ஒவ்வொரு நபரும் ஏற்கனவே உள்கட்டமைப்பின் சர்ச்சைக்குரிய வசதியைப் பாராட்டியுள்ளனர். எல்லா இடங்களிலும் சிரமங்கள் காணப்படுகின்றன: டெவலப்பர் சுயவிவர மெனுவிலிருந்து பிழைத்திருத்தம் மற்றும் உருவாக்க கருவிகள் வரை.

இணையத்தில் "அடிப்படைகள்" பற்றி நிறைய கட்டுரைகள் உள்ளன, எனவே முக்கிய விஷயத்தை முன்னிலைப்படுத்த முயற்சிப்போம். உங்கள் விண்ணப்பத்தை வெற்றிகரமாக உருவாக்க நீங்கள் செய்ய வேண்டியது இங்கே:

  • டெவலப்பர் கணக்கு;
  • உருவாக்க சேவையகமாக செயல்படும் மேகோஸ் அடிப்படையிலான சாதனம்;
  • உருவாக்கப்பட்டது டெவலப்பர் சான்றிதழ், விண்ணப்பத்தில் கையொப்பமிட மேலும் பயன்படுத்தப்படும்;
  • தனித்துவமான பயன்பாட்டை உருவாக்கியது ID (தொகுப்பு அடையாளங்காட்டியின் முக்கியத்துவம் கவனிக்கப்பட வேண்டும், ஏனெனில் வைல்டு கார்டு ஐடியின் பயன்பாடு பயன்பாட்டின் பல செயல்பாடுகளைப் பயன்படுத்த இயலாது, எடுத்துக்காட்டாக: தொடர்புடைய டொமைன்கள், புஷ் அறிவிப்புகள், ஆப்பிள் உள்நுழைவு மற்றும் பிற);
  • சுயவிவர விண்ணப்ப கையொப்பங்கள்.

எந்தவொரு மேகோஸ் சாதனத்திலும் கீச்செயின் வழியாக டெவலப்பர் சான்றிதழ் உருவாக்கப்பட வேண்டும். சான்றிதழ் வகை மிகவும் முக்கியமானது. பயன்பாட்டு சூழலைப் பொறுத்து (தேவ், க்யூஏ, நிலைப்படுத்தல், உற்பத்தி) இது வேறுபட்டது (மேம்பாடு அல்லது விநியோகம்), பயன்பாட்டு கையொப்ப சுயவிவரத்தின் வகை.

சுயவிவரங்களின் முக்கிய வகைகள்:

  • மேம்பாடு - மேம்பாட்டுக் குழுவின் விண்ணப்பத்தில் கையொப்பமிடுவதற்காக, ஒரு மேம்பாட்டுச் சான்றிதழ் பயன்படுத்தப்படுகிறது (வகை பெயர் ஐபோன் டெவலப்பர்: XXXX);
  • தற்காலிக - QA துறையின் சோதனை விண்ணப்பம் மற்றும் உள் சரிபார்ப்புக்கு கையொப்பமிடுவதற்காக, டெவலப்பரின் விநியோகச் சான்றிதழ் பயன்படுத்தப்படுகிறது (வகை பெயர் iPhone விநியோகம்: XXXX);
  • ஆப் ஸ்டோர் - டெவலப்பரின் விநியோகச் சான்றிதழானது, TestFlight மற்றும் ஆப் ஸ்டோரில் பதிவேற்றம் மூலம் வெளிப்புற சோதனைக்கான உருவாக்கத்தை வெளியிடுகிறது.

டெவலப்மென்ட் மற்றும் அட் ஹாக் சுயவிவரங்களை உருவாக்கும் போது, ​​அதுவும் குறிக்கப்படுகிறது சாதன பட்டியல், நீங்கள் ஒரு கட்டமைப்பை நிறுவலாம், இது பயனர்களுக்கான அணுகலை மேலும் கட்டுப்படுத்த உங்களை அனுமதிக்கிறது. ஆப் ஸ்டோர் சுயவிவரத்தில் சாதனங்களின் பட்டியல் எதுவும் இல்லை, ஏனெனில் மூடிய பீட்டா சோதனையின் போது அணுகல் கட்டுப்பாடு TestFlight ஆல் கையாளப்படுகிறது, இது பின்னர் விவாதிக்கப்படும்.

தெளிவுக்காக, டெவலப்பரின் சுயவிவரத்தை கீழே உள்ள அட்டவணையின் வடிவத்தில் வழங்கலாம். சட்டசபைக்கு என்ன அளவுருக்கள் தேவை மற்றும் அவற்றை எங்கிருந்து பெறுவது என்பதைப் புரிந்துகொள்வதை இது எளிதாக்குகிறது.

iOS பயன்பாடுகளை உருவாக்கி வழங்குவதற்கான அம்சங்கள்

சட்டசபை

திட்டம் மற்றும் சுற்றுச்சூழலின் அடிப்படையில் அசெம்பிளிகளை பிரிப்பதை எளிதாக்க, நாங்கள் சுயவிவரப் பெயர்களைப் பயன்படுத்துகிறோம் ${ProjectName}_${Instance}, அதாவது, திட்டத்தின் பெயர் + நிகழ்வு (பயன்பாட்டு சூழலைப் பொறுத்தது: Dev, QA, GD, Staging, Live மற்றும் பல).

உருவாக்க சேவையகத்திற்கு இறக்குமதி செய்யும் போது, ​​சுயவிவரமானது அதன் பெயரை தனிப்பட்ட ஐடிக்கு மாற்றி கோப்புறைக்கு நகர்த்தப்படும் /Users/$Username/Library/MobileDevice/Provisioning Profiles (எங்கே $Username உருவாக்க சேவையகத்தின் பயனர் கணக்கு பெயருடன் ஒத்துள்ளது).

*.ipa கோப்பை உருவாக்க இரண்டு வழிகள் உள்ளன - மரபு (PackageApplication) மற்றும் நவீன (XcAchive உருவாக்கம் மற்றும் ஏற்றுமதி மூலம்). பதிப்பு 8.3 முதல் பயன்பாட்டு கோப்பு பேக்கேஜிங் தொகுதி Xcode விநியோகத்திலிருந்து அகற்றப்பட்டதால், முதல் முறை வழக்கற்றுப் போனதாகக் கருதப்படுகிறது. அதைப் பயன்படுத்த, நீங்கள் பழைய Xcode (பதிப்பு 8.2 மற்றும் அதற்கு முந்தைய) இலிருந்து தொகுதியை கோப்புறையில் நகலெடுக்க வேண்டும்:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/

பின்னர் கட்டளையை இயக்கவும்:

chmod +x /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/*

அடுத்து நீங்கள் பயன்பாட்டின் *.app கோப்பை சேகரிக்க வேண்டும்:

xcodebuild 
-workspace $ProjectDir/$ProjectName.xcworkspace 
-scheme $SchemeName 
-sdk iphoneos 
build 
-configuration Release 
-derivedDataPath build 
CODE_SIGN_IDENTITY=”$DevAccName”
PROVISIONING_PROFILE=”$ProfileId”
DEPLOYMENT_POSTPROCESSING=YES 
SKIP_INSTALL=YES 
ENABLE_BITCODE=NO

எங்கே:

-workspace - திட்டக் கோப்பிற்கான பாதை.

-scheme - பயன்படுத்தப்படும் திட்டம், திட்டத்தில் குறிப்பிடப்பட்டுள்ளது.

-derivedDataPath — கூடியிருந்த பயன்பாட்டைப் பதிவிறக்குவதற்கான பாதை (*.app).

CODE_SIGN_IDENTITY — டெவெலப்பர் கணக்கின் பெயர், இது Keychain இல் சரிபார்க்கப்படலாம் (iPhone டெவலப்பர்: XXXX XXXXXXX, அடைப்புக்குறிக்குள் TeamID இல்லாமல்).

iOS பயன்பாடுகளை உருவாக்கி வழங்குவதற்கான அம்சங்கள்

PROVISIONING_PROFILE — விண்ணப்பத்தில் கையொப்பமிடுவதற்கான சுயவிவர ஐடி, கட்டளையுடன் பெறலாம்:

cd "/Users/$Username/Library/MobileDevice/Provisioning Profiles/" && find *.mobileprovision -type f | xargs grep -li ">${ProjectName}_${Instance}<" | sed -e 's/.mobileprovision//'

பயன்பாடு கூடுதல் சுயவிவரத்தைப் பயன்படுத்தினால் (எடுத்துக்காட்டாக, புஷ் அறிவிப்புகளுக்கு), அதற்குப் பதிலாக PROVISIONING_PROFILE குறிப்பிடவும்:

APP_PROFILE=”$AppProfile” 
EXTENSION_PROFILE=”$ExtProfile” 

அடுத்து, இதன் விளைவாக வரும் *.app கோப்பு *.ipa இல் தொகுக்கப்பட வேண்டும். இதைச் செய்ய, நீங்கள் ஒரு கட்டளையைப் பயன்படுத்தலாம்:

/usr/bin/xcrun --sdk iphoneos PackageApplication 
-v $(find "$ProjectDir/build/Build/Products/Release-iphoneos" -name "*.app") 
-o "$ProjectDir/$ProjectName_$Instance.ipa"

இருப்பினும், ஆப்பிளின் பார்வையில் இருந்து இந்த முறை வழக்கற்றுப் போனதாகக் கருதப்படுகிறது. பயன்பாட்டுக் காப்பகத்திலிருந்து ஏற்றுமதி செய்வதன் மூலம் *.ipa ஐப் பெறுவது பொருத்தமானது.

முதலில் நீங்கள் கட்டளையுடன் காப்பகத்தை சேகரிக்க வேண்டும்:

xcodebuild 
-workspace $ProjectDir/$ProjectName.xcworkspace 
-scheme $SchemeName 
-sdk iphoneos 
-configuration Release 
archive 
-archivePath $ProjectDir/build/$ProjectName.xcarchive 
CODE_SIGN_IDENTITY=”$DevAccName” 
PROVISIONING_PROFILE=”$ProfileId”
ENABLE_BITCODE=NO 
SYNCHRONOUS_SYMBOL_PROCESSING=FALSE

வேறுபாடுகள் சட்டசபை முறை மற்றும் விருப்பங்களில் உள்ளன SYNCHRONOUS_SYMBOL_PROCESSING, இது உருவாக்க நேரத்தில் சின்னத்தை இறக்குவதை முடக்குகிறது.

அடுத்து நாம் ஏற்றுமதி அமைப்புகளுடன் ஒரு கோப்பை உருவாக்க வேண்டும்:

ExportSettings="$ProjectDir/exportOptions.plist"

cat << EOF > $ExportSettings
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>compileBitcode</key>
<false/>
<key>uploadBitcode</key>
<false/>
<key>uploadSymbols</key>
<false/>
<key>method</key>
<string>$Method</string>
<key>provisioningProfiles</key>
<dict>
<key>$BundleID</key>
<string>$ProfileId</string>
</dict>
<key>signingCertificate</key>
<string>$DevAccName</string>
<key>signingStyle</key>
<string>manual</string>
<key>stripSwiftSymbols</key>
<true/>
<key>teamID</key>
<string>$TeamID</string>
<key>thinning</key>
<string><none></string>
</dict>
</plist>
EOF

எங்கே:

$Method — டெலிவரி முறை, பயன்பாட்டு கையொப்ப சுயவிவர வகைக்கு ஒத்திருக்கிறது, அதாவது, டெவலப்மென்டிற்கான மதிப்பு டெவலப்மென்டாக இருக்கும், அட் ஹாக் - அட்-ஹாக், மற்றும் ஆப் ஸ்டோர் - ஆப்-ஸ்டோருக்கு.

$BundleID - பயன்பாட்டு ஐடி, இது பயன்பாட்டு அமைப்புகளில் குறிப்பிடப்பட்டுள்ளது. கட்டளை மூலம் நீங்கள் சரிபார்க்கலாம்:

defaults read $ProjectDir/Info CFBundleIdentifier

$DevAccName и $ProfileId - டெவலப்பர் பெயர் மற்றும் கையொப்ப சுயவிவர ஐடி அமைப்புகள் முன்பு பயன்படுத்தப்பட்டன மற்றும் ஏற்றுமதி அமைப்புகளில் உள்ள மதிப்புகளுடன் பொருந்த வேண்டும்.

$TeamID — டெவலப்பரின் பெயருக்குப் பிறகு அடைப்புக்குறிக்குள் பத்து இலக்க ஐடி, உதாரணம்: iPhone டெவலப்பர்: …… (XXXXXXXXXX); கீசெயினில் சரிபார்க்கலாம்.

அடுத்து, ஏற்றுமதி கட்டளையைப் பயன்படுத்தி, தேவையான *.ipa கோப்பைப் பெறுகிறோம்:

xcodebuild 
-exportArchive 
-archivePath $ProjectDir/build/$ProjectName.xcarchive 
-exportPath $ProjectDir 
-exportOptionsPlist $ExportSettings

Доставка

இப்போது சேகரிக்கப்பட்ட கோப்பு இறுதி பயனருக்கு வழங்கப்பட வேண்டும், அதாவது சாதனத்தில் நிறுவப்பட்டுள்ளது.

HockeyApp, AppBlade மற்றும் பிற போன்ற டெவலப்மென்ட் மற்றும் அட் ஹாக் பில்ட்களை விநியோகிக்க பல சேவைகள் உள்ளன, ஆனால் இந்த கட்டுரையில் பயன்பாடுகளை விநியோகிப்பதற்கான ஒரு முழுமையான சேவையகத்தைப் பற்றி பேசுவோம்.

IOS க்கான பயன்பாட்டை நிறுவுவது 2 நிலைகளில் நடைபெறுகிறது:

  1. உருப்படிகள் சேவை மூலம் பயன்பாட்டு நிறுவல் மேனிஃபெஸ்டைப் பெறுதல்.
  2. HTTPS வழியாக மேனிஃபெஸ்ட்டில் குறிப்பிடப்பட்டுள்ள தகவலின்படி *.ipa கோப்பை நிறுவுதல்.

எனவே, நாம் முதலில் கட்டளையுடன் நிறுவல் மேனிஃபெஸ்டை (கோப்பு வகை *.plist) உருவாக்க வேண்டும்:

cat << EOF > $manifest
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>items</key>
<array>
<dict>
<key>assets</key>
<array>
<dict>
<key>kind</key>
<string>software-package</string>
<key>url</key>
<string>$ipaUrl</string>
</dict>
</array>
<key>metadata</key>
<dict>
<key>bundle-identifier</key>
<string>$BundleID</string>
<key>bundle-version</key>
<string>$AppVersion</string>
<key>kind</key>
<string>software</string>
<key>title</key>
<string>$ProjectName_$Instance</string>
<key>subtitle</key>
<string>$Instance</string>
</dict>
</dict>
</array>
</dict>
</plist>
EOF

நீங்கள் பார்க்க முடியும் என, மேனிஃபெஸ்ட்டில் பயன்பாட்டை உருவாக்குவதில் ஈடுபட்டுள்ள அனைத்து அளவுருக்களும் உள்ளன.

பயன்பாட்டு பதிப்பு ($AppVersion) கட்டளை மூலம் சரிபார்க்கலாம்:

defaults read $ProjectDir/Info CFBundleVersion

அளவுரு $ipaUrl *.ipa கோப்பைப் பதிவிறக்குவதற்கான நேரடி இணைப்பு உள்ளது. iOS இன் ஏழாவது பதிப்பிலிருந்து, பயன்பாடு HTTPS வழியாக நிறுவப்பட வேண்டும். எட்டாவது பதிப்பில், மேனிஃபெஸ்ட்டின் வடிவம் சிறிது மாறிவிட்டது: போன்ற பயன்பாட்டு ஐகான்களுக்கான அமைப்புகளுடன் தொகுதிகள்

<images>
   <image>...</image>
</images>

எனவே, பயன்பாட்டை நிறுவ, இது போன்ற இணைப்பைக் கொண்ட எளிய HTML பக்கம் போதுமானது:

itms-services://?action=download-manifest&url=https://$ServerUrl/$ProjectName/$Instance/iOS/$AppVersion/manifest.plist

மேம்பாடு மற்றும் சோதனைத் துறைகளின் தேவைகளுக்காக, பிளாரியம் அதன் சொந்த உருவாக்க நிறுவல் பயன்பாட்டை உருவாக்கியுள்ளது, இது எங்களுக்கு வழங்குகிறது:

  • சுயாட்சி மற்றும் சுதந்திரம்,
  • அணுகல் கட்டுப்பாட்டை மையப்படுத்துதல் மற்றும் "தற்காலிக" மாறும் வகையில் உருவாக்கப்பட்ட இணைப்புகள் மூலம் பயன்பாடுகளின் பாதுகாப்பான நிறுவல்,
  • விரிவாக்கக்கூடிய செயல்பாடு (அதாவது, மேம்பாட்டுக் குழு, தேவைப்பட்டால், காணாமல் போன செயல்பாடுகளை ஏற்கனவே உள்ள பயன்பாட்டில் ஒருங்கிணைக்க முடியும்).

சோதனை

இப்போது நாம் பயன்படுத்தும் பயன்பாட்டின் முன் வெளியீட்டு சோதனை பற்றி பேசுவோம் டெஸ்ட் ஃப்ளைட்.

பதிவிறக்குவதற்கு தேவையான நிபந்தனைகள் ஆப் ஸ்டோர் கையொப்ப சுயவிவரத்தின் வகை மற்றும் உருவாக்கப்பட்ட API விசைகளின் இருப்பு ஆகும்.

பயன்பாட்டைப் பதிவிறக்க பல வழிகள் உள்ளன:

  • Xcode வழியாக (அமைப்பாளர்),
  • ஆல்டூல் மூலம்,
  • Xcode இன் பழைய பதிப்புகளுக்கான விண்ணப்ப ஏற்றி வழியாக (இப்போது டிரான்ஸ்போர்ட்டர்).

தானியங்கி பதிவிறக்கத்திற்கு, ஆல்டூல் பயன்படுத்தப்படுகிறது, இதில் இரண்டு அங்கீகார முறைகளும் உள்ளன:

  • ஆப்-குறிப்பிட்ட கடவுச்சொல்,
  • API விசை.

API விசையைப் பயன்படுத்தி பயன்பாட்டைப் பதிவிறக்குவது விரும்பத்தக்கது.

API விசையைப் பெற, செல்லவும் இணைப்பை மற்றும் ஒரு விசையை உருவாக்கவும். *.p8 வடிவத்தில் உள்ள விசைக்கு கூடுதலாக, எங்களுக்கு இரண்டு அளவுருக்கள் தேவைப்படும்: IssuerID மற்றும் KeyID.

iOS பயன்பாடுகளை உருவாக்கி வழங்குவதற்கான அம்சங்கள்

அடுத்து, பதிவிறக்கம் செய்யப்பட்ட விசையை உருவாக்க சேவையகத்திற்கு இறக்குமதி செய்யவும்:

mkdir -p ~/.appstoreconnect/private_keys
mv ~/Downloads/AuthKey_${KeyID}.p8 ~/.appstoreconnect/private_keys/

TestFlight இல் பயன்பாட்டைப் பதிவேற்றும் முன், நீங்கள் பயன்பாட்டை சரிபார்க்க வேண்டும், நாங்கள் கட்டளையுடன் இதைச் செய்கிறோம்:

xcrun altool 
--validate-app 
-t ios 
-f $(find "$ProjectDir" -name "*.ipa") 
--apiKey “$KeyID” 
--apiIssuer “$IssuerID” 

எங்கே apiKey и apiIssuer API விசை உருவாக்கப் பக்கத்திலிருந்து புல மதிப்புகளைக் கொண்டிருங்கள்.

அடுத்து, வெற்றிகரமான சரிபார்ப்புக்குப் பிறகு, கட்டளையுடன் பயன்பாட்டை ஏற்றுவோம் --upload-app அதே அளவுருக்களுடன்.

பயன்பாடு ஒன்று அல்லது இரண்டு நாட்களுக்குள் Apple ஆல் சோதிக்கப்படும், பின்னர் வெளிப்புற சோதனையாளர்களுக்குக் கிடைக்கும்: நிறுவலுக்கான இணைப்புகள் மின்னஞ்சல் மூலம் அனுப்பப்படும்.

ஆல்டூல் மூலம் பயன்பாட்டைப் பதிவிறக்குவதற்கான மற்றொரு வழி, ஆப்-குறிப்பிட்ட கடவுச்சொல்லைப் பயன்படுத்துவது.

ஆப்ஸ்-குறிப்பிட்ட கடவுச்சொல்லைப் பெற நீங்கள் செல்ல வேண்டும் இணைப்பை பாதுகாப்பு பிரிவில் அதை உருவாக்கவும்.

iOS பயன்பாடுகளை உருவாக்கி வழங்குவதற்கான அம்சங்கள்

அடுத்து, இந்த கடவுச்சொல்லைக் கொண்டு Keychain இல் ஒரு உருவாக்க சர்வர் பதிவை உருவாக்க வேண்டும். Xcode இன் பதிப்பு 11 இலிருந்து கட்டளை மூலம் இதைச் செய்யலாம்:

xcrun altool --store-password-in-keychain-item "Altool" -u "$DeveloperName" -p $AppPswd

எங்கே:

$DeveloperName — Apple சேவைகளில் உள்நுழைய பயன்படுத்தப்படும் iOS டெவலப்பர் கணக்கின் பெயர்.

$AppPswd — உருவாக்கப்பட்ட பயன்பாடு சார்ந்த கடவுச்சொல்.

அடுத்து, asc-provider அளவுருவின் மதிப்பைப் பெறுகிறோம் மற்றும் கட்டளையுடன் கடவுச்சொல் இறக்குமதியின் வெற்றியை சரிபார்க்கவும்:

xcrun altool --list-providers -u "$DeveloperName" -p "@keychain:Altool"

நாங்கள் வெளியீட்டைப் பெறுகிறோம்:

Provider listing:
- Long Name - - Short Name -
XXXXXXX        XXXXXXXXX

நீங்கள் பார்க்க முடியும் என, தேவையான குறுகிய பெயர் மதிப்பு (asc-provider) பயன்பாட்டை உருவாக்கும் போது நாங்கள் பயன்படுத்திய $TeamID அளவுருவுடன் ஒத்துப்போகிறது.

TestFlight இல் பயன்பாட்டை சரிபார்த்து ஏற்ற, கட்டளையைப் பயன்படுத்தவும்:

xcrun altool 
--(validate|upload)-app   
-f $(find "$ProjectDir" -name "*.ipa") 
-u "$DeveloperName" 
-p "@keychain:Altool" 

அளவுரு மதிப்பாக -p நீங்கள் மதிப்பை எடுத்துக் கொள்ளலாம் $AppPswd மறைகுறியாக்கப்படாத (வெளிப்படையான) வடிவத்தில்.

இருப்பினும், ஏற்கனவே குறிப்பிட்டுள்ளபடி, செயல்திறனின் பார்வையில், ஆல்டூல் அங்கீகாரத்திற்கான API விசையைத் தேர்ந்தெடுப்பது நல்லது, ஏனெனில் Xcode இன் வெவ்வேறு பதிப்புகளில் சில சிக்கல்கள் உள்ளன (“பார்க்கவில்லை” Keychain, பதிவேற்றத்தின் போது அங்கீகார பிழைகள் போன்றவை).

அவ்வளவுதான், உண்மையில். App Store இல் வெற்றிகரமான உருவாக்கங்கள் மற்றும் சிக்கல் இல்லாத வெளியீடுகளில் ஈடுபட்டுள்ள அனைவருக்கும் எனது வாழ்த்துக்கள்.

ஆதாரம்: www.habr.com

கருத்தைச் சேர்