تجربه CICD موبایل: یک استاندارد fastlane برای بسیاری از برنامه های کاربردی تلفن همراه

تجربه CICD موبایل: یک استاندارد fastlane برای بسیاری از برنامه های کاربردی تلفن همراه
من می خواهم در مورد یکپارچه سازی و تحویل مداوم برای برنامه های تلفن همراه با استفاده از fastlane صحبت کنم. چگونه CI/CD را روی همه برنامه های موبایل پیاده سازی می کنیم، چگونه به آنجا رسیدیم و در پایان چه اتفاقی افتاد.

در حال حاضر مطالب کافی در شبکه در مورد ابزار وجود دارد که در ابتدا فاقد آن بودیم، بنابراین من عمداً ابزار را با جزئیات شرح نمی دهم، بلکه فقط به آنچه در آن زمان داشتیم اشاره می کنم:

مقاله شامل دو بخش است:

  • پیشینه ظهور CI/CD موبایل در شرکت
  • راه حل فنی برای راه اندازی CI/CD برای برنامه های N

قسمت اول بیشتر نوستالژی قدیم است و دومی تجربه ای است که می توانید آن را برای خودتان به کار ببرید.

از نظر تاریخی اینطور شد

2015 سال

ما به تازگی شروع به توسعه برنامه های کاربردی تلفن همراه کردیم، سپس چیزی در مورد یکپارچه سازی مداوم، در مورد DevOps و سایر چیزهای مد روز نمی دانستیم. هر به‌روزرسانی برنامه توسط خود توسعه‌دهنده از دستگاهش منتشر شد. و اگر برای Android بسیار ساده است - مونتاژ شده، امضا شده است .apk و آن را در کنسول توسعه‌دهنده Google آپلود کرد، سپس برای iOS، ابزار توزیع آن زمان از طریق Xcode، عصرهای خوبی را برای ما به ارمغان آورد - تلاش‌ها برای دانلود بایگانی اغلب با خطا به پایان می‌رسید و ما مجبور بودیم دوباره تلاش کنیم. مشخص شد که پیشرفته ترین توسعه دهنده چندین بار در ماه کد نمی نویسد، بلکه برنامه را منتشر می کند.

2016 سال

ما بزرگ شدیم، قبلاً به این فکر می کردیم که چگونه توسعه دهندگان را از یک روز کامل برای انتشار آزاد کنیم و یک برنامه دوم نیز ظاهر شد که فقط ما را بیشتر به سمت اتوماسیون سوق داد. در همان سال، ما برای اولین بار جنکینز را نصب کردیم و مجموعه ای از فیلمنامه های ترسناک نوشتیم، بسیار شبیه به آنهایی که fastlane در مستندات خود نشان می دهد.

$ xcodebuild clean archive -archivePath build/MyApp 
    -scheme MyApp

$ xcodebuild -exportArchive 
                        -exportFormat ipa 
                        -archivePath "build/MyApp.xcarchive" 
                        -exportPath "build/MyApp.ipa" 
                        -exportProvisioningProfile "ProvisioningProfileName"

$ cd /Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/A/Support/

$ ./altool —upload-app 
-f {abs path to your project}/build/{release scheme}.ipa  
-u "[email protected]" 
-p "PASS_APPLE_ID"

متأسفانه، تا به حال فقط توسعه دهندگان ما می دانستند که این اسکریپت ها چگونه کار می کنند و چرا این پشته بی پایان از کلیدها مورد نیاز است، و هنگامی که چیزی دوباره شکست، آنها "عصرهای زیبا" را برای تجزیه و تحلیل گزارش ها دریافت کردند.

2017 سال

امسال فهمیدیم که چیزی به نام fastlane وجود دارد. اطلاعات زیادی به اندازه اکنون وجود نداشت - چگونه یکی را شروع کنیم، چگونه از آن استفاده کنیم. و خود ابزار در آن زمان هنوز خام بود: اشتباهات مداوم فقط ما را ناامید می کرد و باور کردن به اتوماسیون جادویی که آنها وعده داده بودند دشوار بود.

با این حال، ابزارهای اصلی موجود در هسته fastlane هستند gym и pilot، موفق شدیم آن را شروع کنیم.

فیلمنامه های ما کمی بهبود یافته است.

$ fastlane gym  —-workspace "Example.xcworkspace" 
                --scheme "AppName" 
                —-buildlog_path "/tmp" 
                -—clean

آنها بهبود یافته اند، اگر تنها به این دلیل که تمام پارامترهای لازم برای xcodebuild، باید نشان دهید - gym به طور مستقل درک خواهد کرد که کجا و چه چیزی نهفته است. و برای تنظیم دقیق تر، می توانید همان کلیدهای موجود را مشخص کنید xcodebuild، فقط نام کلیدها واضح تر است.

این بار، به لطف Gym و فرمت‌کننده داخلی xcpretty، لاگ‌های ساخت بسیار خواناتر شده‌اند. این باعث صرفه جویی در زمان در تعمیر مجموعه های شکسته شد و گاهی اوقات تیم انتشار به تنهایی می توانست آن را کشف کند.

متأسفانه، اندازه گیری سرعت مونتاژ xcodebuild и gym ما این کار را انجام ندادیم، اما به اسناد اعتماد خواهیم کرد - تا 30٪ سرعت.

فرآیند واحد برای همه برنامه ها

سال 2018 و اکنون

تا سال 2018، روند ساخت و عرضه برنامه‌ها به طور کامل به جنکینز منتقل شد، توسعه‌دهندگان انتشار از دستگاه‌های خود را متوقف کردند و فقط تیم انتشار حق انتشار داشت.

ما قبلاً می خواستیم راه اندازی تست ها و تجزیه و تحلیل استاتیک را بهبود ببخشیم و اسکریپت های ما رشد کردند و رشد کردند. همراه با برنامه های ما رشد کرد و تغییر کرد. در آن زمان، حدود 10 برنامه وجود داشت، با توجه به اینکه ما دو پلتفرم داریم، این حدود 20 اسکریپت "زنده" است.

هر بار که می خواستیم یک مرحله جدید به اسکریپت اضافه کنیم، باید قطعات را در تمام اسکریپت های پوسته کپی پیست می کردیم. شاید می‌توانستیم با دقت بیشتری کار کنیم، اما اغلب چنین تغییراتی به اشتباهات تایپی ختم می‌شد، که تبدیل به شب‌هایی برای تیم انتشار می‌شد تا اسکریپت‌ها را اصلاح کنند و بفهمند کدام مرد باهوش این دستور را اضافه کرده و در واقع چه می‌کند. به طور کلی، نمی توان گفت که اسکریپت های مونتاژ برای یک پلتفرم حداقل تا حدودی مشابه بودند. اگرچه آنها قطعاً همین کار را کردند.

برای شروع یک فرآیند برای یک برنامه جدید، لازم بود یک روز وقت صرف کنید تا یک نسخه "تازه" از این اسکریپت ها را انتخاب کنید، آن را اشکال زدایی کنید و بگویید "بله، کار می کند".

در تابستان 2018، ما یک بار دیگر به سمت فست‌لین هنوز در حال توسعه نگاه کردیم.

وظیفه شماره 1: تمام مراحل اسکریپت را خلاصه کنید و آنها را در Fastfile بازنویسی کنید

وقتی شروع کردیم، فیلمنامه‌های ما شبیه یک پارچه پا بود که شامل تمام مراحل و عصاها در یک فیلمنامه پوسته در جنکینز بود. ما هنوز به خط لوله و تقسیم به مرحله تغییر نکرده ایم.

ما به آنچه داریم نگاه کردیم و 4 مرحله را شناسایی کردیم که با توضیحات CI/CD ما مطابقت دارد:

  • ساخت - نصب وابستگی ها، مونتاژ آرشیو،
  • تست - اجرای تست‌های واحد توسعه‌دهنده، محاسبه پوشش،
  • سونار - همه لینترها را راه اندازی می کند و گزارش ها را به SonarQube ارسال می کند.
  • استقرار - ارسال یک مصنوع به آلفا (TestFlight).

و اگر وارد جزئیات نشوید، کلیدهای مورد استفاده در اقدامات را حذف کنید، این Fastfile را دریافت خواهید کرد:

default_platform(:ios)

platform :ios do
  before_all do
    unlock
  end

  desc "Build stage"
  lane :build do
    match
    prepare_build
    gym
  end

  desc "Prepare build stage: carthage and cocoapods"
  lane :prepare_build do
    pathCartfile = ""
    Dir.chdir("..") do
      pathCartfile = File.join(Dir.pwd, "/Cartfile")
    end
    if File.exist?(pathCartfile)
      carthage
    end
    pathPodfile = ""
    Dir.chdir("..") do
      pathPodfile = File.join(Dir.pwd, "/Podfile")
    end
    if File.exist?(pathPodfile)
      cocoapods
    end
  end

  desc "Test stage"
  lane :test do
    scan
    xcov
  end

  desc "Sonar stage (after run test!)"
  lane :run_sonar do
    slather
    lizard
    swiftlint
    sonar
  end

  desc "Deploy to testflight stage"
  lane :deploy do
    pilot
  end

  desc "Unlock keychain"
  private_lane :unlock do
    pass = ENV['KEYCHAIN_PASSWORD']
    unlock_keychain(
      password: pass
    )
  end
end

در واقع، با توجه به برخی از عصاهایی که هنوز به آن نیاز داشتیم و تعداد پارامترهایی که جایگزین کردیم، اولین Fastfile ما بسیار هیولا بود:

lane :build do
carthage(
  command: "update",
  use_binaries: false,
  platform: "ios",
  cache_builds: true)
cocoapods(
  clean: true,
    podfile: "./Podfile",
    use_bundle_exec: false)

gym(
  workspace: "MyApp.xcworkspace",
  configuration: "Release",
  scheme: "MyApp",
  clean: true,
  output_directory: "/build",
  output_name: "my-app.ipa")
end 

lane :deploy do
 pilot(
  username: "[email protected]",
  app_identifier: "com.example.app",
  dev_portal_team_id: "TEAM_ID_NUMBER_DEV",
  team_id: "ITS_TEAM_ID")
end

در مثال بالا، تنها بخشی از پارامترهایی که باید مشخص کنیم: اینها پارامترهای ساخت - طرح، پیکربندی، نام‌های نمایه ارائه، و همچنین پارامترهای توزیع - Apple ID حساب توسعه‌دهنده، رمز عبور، شناسه برنامه و غیره هستند. بر. به عنوان اولین تقریب، ما همه این کلیدها را در فایل های ویژه قرار می دهیم - Gymfile, Matchfile и Appfile.

اکنون در جنکینز می توانید دستورات کوتاهی را فراخوانی کنید که دید را تار نمی کنند و به راحتی توسط چشم قابل خواندن هستند:

# fastlane ios <lane_name>

$ fastlane ios build
$ fastlane ios test
$ fastlane ios run_sonar
$ fastlane ios deploy

هورا، ما عالی هستیم

چی به دست آوردی؟ دستورات را برای هر مرحله پاک کنید. اسکریپت‌های پاک‌شده، مرتب در فایل‌های fastlane. با خوشحالی به سمت توسعه‌دهندگان دویدیم و از آنها خواستیم هر آنچه را که نیاز دارند به مخازن خود اضافه کنند.

اما ما به موقع متوجه شدیم که با همان مشکلات روبرو خواهیم شد - ما هنوز 20 اسکریپت اسمبلی خواهیم داشت که به هر طریقی زندگی خود را شروع می کنند ، ویرایش آنها دشوارتر است ، زیرا اسکریپت ها به مخازن منتقل می شوند. و ما به آنجا دسترسی نداشتیم. و در مجموع نمی توان درد ما را از این طریق حل کرد.

تجربه CICD موبایل: یک استاندارد fastlane برای بسیاری از برنامه های کاربردی تلفن همراه

وظیفه شماره 2: یک Fastfile برای N برنامه دریافت کنید

اکنون به نظر می رسد که حل مشکل چندان دشوار نیست - متغیرها را تنظیم کنید و بیایید برویم. بله، در واقع، این چگونه مشکل حل شد. اما در لحظه‌ای که داشتیم آن را خراب می‌کردیم، نه در خود fastlane تخصص داشتیم، نه در Ruby، که در آن fastlane نوشته شده است، و نه نمونه‌های مفیدی در شبکه - همه کسانی که در آن زمان در مورد fastlane نوشتند به یک مثال برای یک برنامه محدود می‌شدند. برای یک توسعه دهنده

Fastlane می‌تواند متغیرهای محیطی را مدیریت کند، و ما قبلاً این را با تنظیم رمز عبور Keychain امتحان کرده‌ایم:

ENV['KEYCHAIN_PASSWORD']

پس از بررسی اسکریپت های خود، بخش های مشترک را شناسایی کردیم:

#for build, test and deploy
APPLICATION_SCHEME_NAME=appScheme
APPLICATION_PROJECT_NAME=app.xcodeproj
APPLICATION_WORKSPACE_NAME=app.xcworkspace
APPLICATION_NAME=appName

OUTPUT_IPA_NAME=appName.ipa

#app info
APP_BUNDLE_IDENTIFIER=com.example.appName
[email protected]
TEAM_ID=ABCD1234
FASTLANE_ITC_TEAM_ID=123456789

حال، برای شروع استفاده از این کلیدها در فایل‌های fastlane، باید نحوه تحویل آن‌ها را در آنجا کشف می‌کردیم. Fastlane برای این راه حل دارد: بارگیری متغیرها از طریق dotenv. مستندات می گوید که اگر برای شما مهم است که کلیدها را برای اهداف مختلف بارگیری کنید، چندین فایل پیکربندی را در دایرکتوری fastlane ایجاد کنید. .env, .env.default, .env.development.

و سپس تصمیم گرفتیم از این کتابخانه کمی متفاوت استفاده کنیم. بیایید نه اسکریپت های fastlane و اطلاعات متا آن، بلکه کلیدهای منحصر به فرد این برنامه را در فایل در مخزن توسعه دهندگان قرار دهیم. .env.appName.

خودشان Fastfile, Appfile, Matchfile и Gymfile، ما آن را در یک مخزن جداگانه پنهان کردیم. یک فایل اضافی با کلیدهای رمز عبور از سرویس های دیگر در آنجا پنهان شده بود - .env.
می توانید یک نمونه را ببینید اینجا.

تجربه CICD موبایل: یک استاندارد fastlane برای بسیاری از برنامه های کاربردی تلفن همراه

در CI، تماس تغییر زیادی نکرده است؛ یک کلید پیکربندی برای یک برنامه خاص اضافه شده است:

# fastlane ios <lane_name> --env appName

$ fastlane ios build --env appName
$ fastlane ios test --env appName
$ fastlane ios run_sonar --env appName
$ fastlane ios deploy --env appName

قبل از اجرای دستورات، مخزن خود را با اسکریپت بارگذاری می کنیم. خیلی خوب به نظر نمی رسد:

git clone [email protected]/FastlaneCICD.git fastlane_temp

cp ./fastlane_temp/fastlane/* ./fastlane/
cp ./fastlane_temp/fastlane/.env fastlane/.env

فعلاً این راه حل را رها کنید، اگرچه Fastlane راه حلی برای دانلود Fastfile از طریق دارد اقدام import_from_git، اما فقط برای Fastfile کار می کند، اما برای سایر فایل ها نه. اگر "واقعا زیبا" می خواهید، می توانید خودتان بنویسید action.

مجموعه مشابهی برای برنامه های اندروید و ReactNative ساخته شده است، فایل ها در یک مخزن هستند، اما در شاخه های مختلف iOS, android и react_native.

زمانی که تیم انتشار می خواهد چند مرحله جدید اضافه کند، تغییرات در اسکریپت از طریق MR در git ثبت می شود، دیگر نیازی به جستجوی مقصران اسکریپت های شکسته نیست و به طور کلی، اکنون باید برای شکستن آن تلاش کنید.

حالا مطمئناً همین است

پیش از این، ما زمانی را صرف حفظ همه اسکریپت ها، به روز رسانی آنها و رفع تمام عواقب به روز رسانی می کردیم. بسیار ناامیدکننده بود وقتی که دلایل خطاها و خرابی‌ها در نسخه‌ها اشتباهات تایپی ساده‌ای بود که پیگیری آن‌ها در شلوغی اسکریپت‌های پوسته بسیار دشوار بود. اکنون چنین خطاهایی به حداقل رسیده است. تغییرات به طور همزمان در همه برنامه ها اعمال می شود. و 15 دقیقه طول می کشد تا یک برنامه جدید وارد فرآیند شود - یک خط لوله الگو بر روی CI راه اندازی کنید و کلیدها را به مخزن توسعه دهنده اضافه کنید.

به نظر می رسد که نکته Fastfile برای اندروید و امضای اپلیکیشن نامشخص مانده است؛ اگر مطلب جالب باشد، ادامه آن را خواهم نوشت. خوشحال می شوم سوالات یا پیشنهادات شما را "چگونه این مشکل را حل کنید" در نظرات یا در تلگرام ببینم. باشیرووا.

منبع: www.habr.com

اضافه کردن نظر