DEV Community

MohamedAmr-DevOps
MohamedAmr-DevOps

Posted on

Azure DevOps Flutter IOS CI Pipeline

Since it took a long time and effort to get all of my issues solved in Azure DevOps to get my build pipeline works. I need to share what I faced and how I got it working at the end

Certificates and Profiles

CocoaPods

Pipeline steps

Issues and how I got it solved

  • Module not found
  • Certificate generated from xcode not working on pipeline
  • Pod Doesn't support provisioning profile

Certificates and Profiles:
In Android play store you have one certificate for all and its related to your application so in your configuration and build you just need to sign you application bundle file with one certificate in all of your cases. In Apple no you have too different types for each purpose and its not just certificate its certificate with profile. Which makes this more complicated than what is there in Android. So in development you have adhoc profile and certificate in app-store you have app-store and so on

CocoaPods:
Cocoapods is the dependency modules which your project requires so you need to consider this as part of your build pipeline as I will mention later in the article

*Pipeline Steps: *
Here I will mention the whole pipeline steps with all issues I faced during my build

pool:
  name: Azure Pipelines
  demands: xcode

steps:
# getting version number and build number from pubsec.yaml file , please change it if you don't need this to work like this 
- bash: |
   echo "preparing build variables"
   echo "getting build version and build number from pubsec file"
   buildVersion=`grep version src/app/pubspec.yaml |  cut -d':' -f2 | cut -d'+' -f1 | sed 's/ //'`
   buildNumber=`grep version src/app/pubspec.yaml |  cut -d':' -f2 | cut -d'+' -f2 | sed 's/ //'`
   echo "version will be ===> $buildVersion"
   echo "build number will be ===> $buildNumber"
   echo "##vso[task.setvariable variable=buildVersion;]$buildVersion"
   echo "##vso[task.setvariable variable=buildNumber;]$buildNumber"

  displayName: 'prepare build variables '

- task: InstallAppleCertificate@2
  displayName: 'Install an Apple certificate'
  inputs:
    certSecureFile: '********'
    certPwd: '$(P12password)'
    setUpPartitionIdACLForPrivateKey: false

- task: InstallAppleProvisioningProfile@1
  displayName: 'Install an Apple provisioning profile'
  inputs:
    provProfileSecureFile: '******'

- task: Hey24sheep.flutter.flutter-install.FlutterInstall@0
  displayName: 'Flutter Install'

- task: Hey24sheep.flutter.flutter-build.FlutterBuild@0
  displayName: 'Flutter Build ios'
  inputs:
    target: ios
    projectDirectory: src/app
    iosCodesign: false

## This step is very important to consider .. because of pod doesn't support code sign and profile,
## I removed last 6 lines of Podfile which contains post_install section .. please check how many lines you have and remove them 
## After I removed it I added the below section 
- bash: |
   echo "podfile old =================================================================="
   cat Podfile 
   awk 'NR>c{print A[NR%c]} {A[NR%c]=$0}' c=6 Podfile > PodfileTemp
   echo "podfile new =================================================================="
   cat PodfileTemp
   mv PodfileTemp Podfile 
   echo " " >> Podfile
   echo "post_install do |installer| " >> Podfile
   echo "  installer.pods_project.targets.each do |target| " >> Podfile
   echo "    flutter_additional_ios_build_settings(target)" >> Podfile
   echo "    target.build_configurations.each do |config| " >> Podfile
   echo "      config.build_settings['EXPANDED_CODE_SIGN_IDENTITY'] = \"\" " >> Podfile
   echo "      config.build_settings['CODE_SIGNING_REQUIRED'] = \"NO\" " >> Podfile
   echo "      config.build_settings['CODE_SIGNING_ALLOWED'] = \"NO\" " >> Podfile
   echo "    end " >> Podfile
   echo "  end " >> Podfile
   echo "end " >> Podfile

   sudo gem uninstall cocoapods -ax
   sudo gem install cocoapods

  workingDirectory: src/app/ios
  displayName: 'Modify Podfile'

# This is the trick again .. after you prepare your Podfile you will need to run cocoapod install again .. else the above step will not reflect 
- task: CocoaPods@0
  displayName: 'pod install'
  inputs:
    workingDirectory: src/app/ios
# MARKETING_VERSION and CURRENT_PROJECT_VERSION are variables defined in my code to represent version and build 
# please change it with yours 
- task: Xcode@5
  displayName: 'Xcode build'
  inputs:
    xcWorkspacePath: src/app/ios/Runner.xcworkspace
    scheme: Runner
    packageApp: true
    signingOption: manual
    signingIdentity: '$(APPLE_CERTIFICATE_SIGNING_IDENTITY)'
    provisioningProfileUuid: '$(APPLE_PROV_PROFILE_UUID)'
    args: 'MARKETING_VERSION="$(buildVersion)" CURRENT_PROJECT_VERSION="$(buildNumber)"'

- task: CopyFiles@2
  displayName: 'Copy Files to: $(build.artifactstagingdirectory)'
  inputs:
    SourceFolder: '$(system.defaultworkingdirectory)'
    Contents: '**/*.ipa'
    TargetFolder: '$(build.artifactstagingdirectory)'
  condition: succeededOrFailed()

- task: PublishBuildArtifacts@1
  displayName: 'Publish Artifact: drop'
  inputs:
    PathtoPublish: '$(build.artifactstagingdirectory)'
  condition: succeededOrFailed()

Enter fullscreen mode Exit fullscreen mode

`

Top comments (0)