{"id":14350,"date":"2023-06-27T12:52:49","date_gmt":"2023-06-27T07:22:49","guid":{"rendered":"https:\/\/opstree.com\/blog\/\/?p=14350"},"modified":"2025-11-20T15:03:35","modified_gmt":"2025-11-20T09:33:35","slug":"cicd-for-mobile-app-development-using-capacitor-js-on-azure-devops","status":"publish","type":"post","link":"https:\/\/opstree.com\/blog\/2023\/06\/27\/cicd-for-mobile-app-development-using-capacitor-js-on-azure-devops\/","title":{"rendered":"CICD for Mobile App Development Using Capacitor JS on Azure DevOps"},"content":{"rendered":"\r\n<p>In the world of iOS mobile app development, implementing a robust CI\/CD (Continuous Integration\/Continuous Delivery) pipeline is essential to ensure efficient and reliable software delivery. Capacitor JS is a powerful framework that allows developers to build cross-platform mobile apps using web technologies. When combined with Azure DevOps, it enables a seamless CI\/CD pipeline for iOS app development. In this blog post, we will guide you through the process of setting up a <a href=\"https:\/\/www.buildpiper.io\/secure-pipelines\/\" target=\"_blank\" rel=\"noopener\">CI\/CD pipeline<\/a> for iOS mobile apps using Capacitor JS and Azure DevOps.<\/p>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading\">A Note on <em>Capacitor JS<\/em><\/h2>\r\n\r\n\r\n\r\n<p>Capacitor is a free and open source (MIT-licensed) platform that enables web developers to build cross-platform apps with standard web technology that runs in modern browsers. Capacitor takes your existing web application and runs it as a native app on each platform, providing hooks into the native platform via JavaScript. These hooks can be built directly into the app, or as standalone plugins to be reused and distributed to others.<br \/><br \/><strong>Can I reuse existing web code and share new code with a web app?<\/strong><br \/>Yes! One of the strengths of Capacitor is that it runs normal web apps natively. In many cases, teams have a single codebase for web and mobile using Capacitor.<\/p>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading\"><strong>Prerequisite &#8211;<\/strong><\/h2>\r\n\r\n\r\n\r\n<p>1. An azure devops account.<br \/>2. Working Web app code<br \/>3. App center account for distribution<\/p>\r\n\r\n\r\n\r\n<p><!--more--><\/p>\r\n\r\n\r\n\r\n<h5 class=\"wp-block-heading\"><strong>Let&#8217;s begin<\/strong> &#8230;<\/h5>\r\n\r\n\r\n\r\n<p><em>Setup an azure devops account.\u00a0<\/em><br \/>By default under free subscription we get to use linux VMs. In order to use mac VM, we will need to get subscription. Only one agent will be more than enough for our CICD pipeline.<\/p>\r\n\r\n\r\n\r\n<p>Create an <strong>organization<\/strong> and a project.\u00a0Once we have create our project, we move forward to create a new pipeline.<br \/><br \/><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh6.googleusercontent.com\/SpN16Sp-1jP8LohwYmnJPkK3Q-AGnXvmausy1uYqB5zMECGsq79xDeG7fYomW37Op261ed3ZzsWODDD9s6fbGG7EwbjoG9S-trBHiPu1tl1qtwhD3Up8UIWLrCdvGlmT3CqyJUeWxh9cAdkrcDMBTzg\" width=\"624\" height=\"80\" \/><\/p>\r\n\r\n\r\n\r\n<p><br \/>Configure to link the current project with your code base, which can reside in any VCS. We will be using bitbucket cloud so need to configure the same.<\/p>\r\n\r\n\r\n\r\n<p><br \/><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/bfISHYULSPGJ9kYDBbpamiD484zF885iywMKxpZHM8mfBBI7hyhJjJAg3xNG87eSDjrcjvOLs_P3-XNpA5Jgd-Dd45PXoA5c6yYNjwr15A9JSdgn5NvNODkfeKDHZc9oSUB-9NI7K7jgsGK8RAYQvLc\" width=\"517\" height=\"461\" \/><\/p>\r\n\r\n\r\n\r\n<p>Connect, select, configure and review according to your requirements.<\/p>\r\n\r\n\r\n\r\n<p>Once done, we will start with writing code for the pipeline. If you already worked with azure pipelines, you might know how easy it is to add steps since azure provides us with an assistant.<\/p>\r\n\r\n\r\n\r\n<p><br \/><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/bJDfleuKtoTqhWHwQdr_pAlCv55ga67H0_znWeSNbWiELKuyJZ4vG0vTXItgB4DZzEtK5Xw1Z5t3kEJvPtv-63O18nMxhnXuPAbLQidQkKXg7_rOkPDv49WCwSiGhPXf1kSk27LKnPwhQyuJ3FjPwww\" width=\"380\" height=\"471\" \/><br \/><br \/><strong>Step 1 &#8211;<\/strong> configure pool image &#8211; we are developing for ios so have configured macOS-12, since the default xcode version provided by macOS-12 is xcode 14, which satisfies our requirement.<\/p>\r\n\r\n\r\n\r\n<p>&nbsp;<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"663\" height=\"84\" class=\"wp-image-14354\" src=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2023\/06\/screenshot-from-2023-03-23-11-16-37.png?w=663\" alt=\"\" \/><\/figure>\r\n\r\n\r\n\r\n<p><br \/><strong>Step 2 &#8211;<\/strong> <em>optional<\/em> &#8211; configure environment variables for your pipeline. In this I&#8217;m adding variable to specify the deployment environment.<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"660\" height=\"215\" class=\"wp-image-14369\" src=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2023\/06\/env-variables.png?w=660\" alt=\"\" \/><\/figure>\r\n\r\n\r\n\r\n<p><br \/><strong>Step 3 &#8211;<\/strong> Download the required node version on the agent.<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"645\" height=\"163\" class=\"wp-image-14420\" src=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2023\/06\/install_node_version.png?w=645\" alt=\"\" \/><\/figure>\r\n\r\n\r\n\r\n<p><br \/><strong>Step 4 &#8211;<\/strong> Installing dependencies and capacitor core and cli.<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/n816YnjiO9HXBQnJGUg-O7lazs-i1-y5gR_kNeB4syqzxUyH0lAauySlYNKTFBQhMRfGn7tm4IRvGPo-79YixbNO2zRlmP52iaM45pZ27h8yKGxqbeCEheIsDoumLbsgS224DqmtTXv2gpNPKMt6rEk\" alt=\"\" \/><\/figure>\r\n\r\n\r\n\r\n<p><br \/><strong>Step 5 &#8211;<\/strong> Building the app using <em>\u201cnpm run ng build\u201d<\/em><\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/v25OJxUAXoNntN9YDSKLem93E5i3xOmikUHGuhzkb_oBjxvhnrQgBaqoxXUUQgTyCjy5sCxXjIVlTmPVWjvr17hyBkRWi99k4JB5mqiTziJk_088a6B2SfPU952lXrVF-VQmFMlChxg1-Lh1oAjr_bs\" alt=\"\" \/><\/figure>\r\n\r\n\r\n\r\n<p><br \/><strong>Step 6 &#8211;<\/strong> npx sync for ios\/android folder\u00a0<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/VavVRCSizRZYRzE8EgvRPTfBqabyTdBa3ybUEci4dtrlD0ktIAi2At97gsSrxErX88hN-Jmec-nFQgRflemu086blvNue5S6FookizJWpcSlGwDWwfXiltmq4DITiLgM34k8Vbm6TKZde6JBE8cDMgc\" alt=\"\" \/><\/figure>\r\n\r\n\r\n\r\n<p><br \/><strong>Step 7 &#8211;<\/strong> Install apple provisioning certificate and profiles. This requires us to first upload the certificate and profile files to azure, under secure files inside the library in pipelines.<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"785\" height=\"540\" class=\"wp-image-14388\" src=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2023\/06\/upload-certificate-and-secure-files.jpg?w=785\" alt=\"\" \/><\/figure>\r\n\r\n\r\n\r\n<p>&nbsp;<\/p>\r\n\r\n\r\n\r\n<p>Once uploaded, we need to add step in our pipeline to install the profile and certificate<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"648\" height=\"311\" class=\"wp-image-14419\" src=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2023\/06\/install-cocoapods.png?w=648\" alt=\"\" \/><\/figure>\r\n\r\n\r\n\r\n<p><br \/><strong>Step 8 &#8211;<\/strong> Install cocoapods in synced ios folder. Cocoapods helps you to manage and incorporate third-party libraries into your project without getting concerned about setting up and configuring your project.<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"645\" height=\"157\" class=\"wp-image-14418\" src=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2023\/06\/cocoapods.png?w=645\" alt=\"\" \/><\/figure>\r\n\r\n\r\n\r\n<p><br \/><strong>Step 9 &#8211;<\/strong> Xcode build- this will be the step where we bundle and package our application to .ipa file<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"649\" height=\"331\" class=\"wp-image-14417\" src=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2023\/06\/new_xcode_build.png?w=649\" alt=\"\" \/><\/figure>\r\n\r\n\r\n\r\n<p>&nbsp;<\/p>\r\n\r\n\r\n\r\n<p><strong>Step 10 &#8211;<\/strong> <em>optional<\/em> &#8211; Naming ipa file.It\u00a0 is best practice to name the app with some meaningful name, based on environment and version and moving finished app to artifact staging<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/nsnUsPWxi7406PqGax54ec7_CWMTFySyMoCkL7jiTG54K1lvSPlNg0WA4Wra7HcNG7jtixTaVO9sRlvtStnv2NvlyiVA8CjDzvUOGjANHFGzHPBgCKUNt2aCnc3NdGf3M5DIWCMx81l5xLerQgesEo0\" alt=\"\" \/><\/figure>\r\n\r\n\r\n\r\n<p><br \/><strong>Step 11 &#8211;<\/strong> Publish artifact\u00a0<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/JvkDDwVG-YvwYtwqHaQs2XpZmg3Q4b9iwZ-L9kefw936RCq8SBkO3YFdg3wcEeBi5Vul8B8MVJiEoMBGKeRN2-veRoTozu1JmJ4hWa5pwlDYwv0tLLkv1_5LFuAOBswuYM0xMMOOnKJsuo_0n1u1aB4\" alt=\"\" \/><\/figure>\r\n\r\n\r\n\r\n<p><br \/><strong>Step 12 &#8211;<\/strong> Publish to App center. For this, add a service connection for App center in Project setting&gt;Service connection. To generate a service connection, create an account at app center and create a new API token, making sure the API token has full access (so that Azure DevOps can create new releases for distribution), then copy the key. We will use this service connection to establish communication between azure devops and the app center. Alternatively, we can upload the artifact at s3 bucket as well, depending upon the requirements.<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"647\" height=\"288\" class=\"wp-image-14422\" src=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2023\/06\/screenshot-from-2023-06-21-21-15-39.png?w=647\" alt=\"\" \/><\/figure>\r\n\r\n\r\n\r\n<p><br \/>We&#8217;ll need to add the appSlug and distributionGroupId from app center account as well.<br \/>Once done, this is what the pipeline looks like &#8211;\u00a0\u00a0<\/p>\r\n\r\n\r\n\r\n<pre class=\"wp-block-code\"><code>pool:\r\n    vmImage: macOS-12\r\n\r\nparameters:\r\n  - name: environment\r\n    displayName: Configuration based on env\r\n    type: string\r\n    default: DEV\r\n    values:\r\n    - PROD\r\n    - UAT\r\n    - SIT\r\n    - DEV\r\n        \r\nsteps:\r\n     \r\n- task: NodeTool@0\r\n  displayName: install node version\r\n  inputs:\r\n    versionSource: 'spec'\r\n    versionSpec: '16.18.0'\r\n\r\n- task: CmdLine@2\r\n  displayName: install dependecies\r\n  inputs:\r\n    script: |\r\n      npm install --ignore-scripts\r\n      npm install typescript@4.6.4 --save-dev\r\n      npm i @capacitor\/core\r\n      npm i -D @capacitor\/cli\r\n      npm install @capacitor\/ios\r\n      \r\n- task: CmdLine@2\r\n  displayName: npm build\r\n  inputs:\r\n    script: 'npm run ng build -- --c=${{ parameters.environment }}'\r\n\r\n- task: CmdLine@2\r\n  displayName: sync up android and iOS folder\r\n  inputs:\r\n    script: |\r\n        npx cap sync\r\n\r\n- task: InstallAppleCertificate@2\r\n  displayName: install apple signing certificate\r\n  inputs:\r\n    certSecureFile: 'P12_signing_cert.p12'\r\n    certPwd: '****'\r\n    keychain: 'temp'\r\n\r\n- task: InstallAppleProvisioningProfile@1\r\n  displayName: install apple provisioning profile\r\n  inputs:\r\n    provisioningProfileLocation: 'secureFiles'\r\n    provProfileSecureFile: 'DEV_PROFILE.mobileprovision'\r\n\r\n- task: CocoaPods@0\r\n  displayName: install cocoapods\r\n  inputs:\r\n    workingDirectory: 'ios\/App'\r\n    forceRepoUpdate: false\r\n\r\n- task: Xcode@5\r\n  displayName: 'Building IPA File'\r\n  inputs:\r\n    actions: 'build archive'\r\n    sdk: iphoneos\r\n    xcWorkspacePath: 'ios\/App\/App.xcworkspace'\r\n    scheme: 'App'\r\n    packageApp: true\r\n    signingOption: manual\r\n    signingIdentity: '$(APPLE_CERTIFICATE_SIGNING_IDENTITY)'\r\n    provisioningProfileUuid: '$(APPLE_PROV_PROFILE_UUID)'\r\n    teamId: '******'\r\n    xcodeVersion: \"default\"\r\n  \r\n\r\n- task: CmdLine@2\r\n  displayName: Naming ipa file\r\n  inputs:\r\n    script: |\r\n        appversion=$(cat package.json | head | grep -w \"version\" | awk '{print $2}' |cut -c 2-6)\r\n        mv \/Users\/runner\/work\/1\/s\/output\/App.ipa \/Users\/runner\/work\/1\/s\/output\/myapp_${{parameters.environment}}_${appversion}.ipa\r\n\r\n- task: CopyFiles@2\r\n  displayName: 'Copy Files to: $(build.artifactStagingDirectory)' \r\n  inputs:\r\n    SourceFolder: '\/Users\/runner\/work\/1\/s\/output'\r\n    Contents: '*.ipa'\r\n    TargetFolder: '$(Build.ArtifactStagingDirectory)'\r\n\r\n\r\n- task: PublishBuildArtifacts@1\r\n  displayName: 'Publish Artifact: drop'\r\n  inputs:\r\n    PathtoPublish: '$(Build.ArtifactStagingDirectory)'\r\n    ArtifactName: 'ios'\r\n    publishLocation: 'Container'\r\n\r\n- task: AppCenterDistribute@3\r\n  displayName: distribute to app center\r\n  inputs:\r\n      serverEndpoint: 'mobileCI'\r\n      appSlug: '******'\r\n      appFile: '$(Build.ArtifactStagingDirectory)\/**\/*.ipa'\r\n      releaseNotesOption: 'input'\r\n      releaseNotesInput: 'Test Version'\r\n      symbolsOption: 'Apple'\r\n      destinationType: 'groups'\r\n      isSilent: False\r\n      distributionGroupId: '*******'\r\n    \r\n<\/code><\/pre>\r\n\r\n\r\n\r\n<p>Save and run the pipeline. Once completed, we can see the published artifact on <a href=\"https:\/\/opstree.com\/blog\/2025\/10\/14\/data-engineering-with-azure-databricks\/\">Azure devops pipelines<\/a> build page. Check at the app center for the latest version of the app available.<\/p>\r\n\r\n\r\n\r\n<p>Additionally, we can also configure teams channel notifications to notify team whenever a build is triggered :\u00a0<\/p>\r\n\r\n\r\n\r\n<p>Create a teams channel, and add azure pipelines app to the channel.<br \/>Login to the azure account, but first we will also need to allow third party application access via oAuth\u00a0 in our azure <em>organization settings &#8211; under Security &gt; Policies<\/em><\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-large is-resized\"><img decoding=\"async\" class=\"wp-image-14371\" src=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2023\/06\/oauth-ettings.jpg?w=1024\" alt=\"\" width=\"800\" \/><\/figure>\r\n\r\n\r\n\r\n<p>Now from teams channel, we need to subscribe to our pipeline\/project, depending on what all notifications we need.<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-large is-resized\"><img decoding=\"async\" class=\"wp-image-14372\" src=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2023\/06\/subscirbe-teams.jpg?w=951\" alt=\"\" width=\"800\" \/><\/figure>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\r\n\r\n\r\n\r\n<p>Implementing a CI\/CD pipeline for iOS mobile app development using Capacitor JS and Azure DevOps streamlines the software delivery process, enhances collaboration, and ensures the quality of your iOS apps. By following the steps outlined in this blog post, you can establish an efficient CI\/CD pipeline to automate build, test, and deployment processes, allowing you to deliver high-quality iOS apps to your users quickly and reliably.<\/p>\r\n\r\n\r\n\r\n<p><strong>Blog Pundits: <strong><a href=\"https:\/\/www.linkedin.com\/in\/mehul-sharma-devops\/\" target=\"_blank\" rel=\"noreferrer noopener\">Mehul Sharma<\/a><\/strong> and <a href=\"https:\/\/opstree.com\/blog\/\/author\/sandeep7c51ad81ba\/\" target=\"_blank\" rel=\"noreferrer noopener\">Sandeep Rawat<\/a><\/strong><\/p>\r\n\r\n\r\n\r\n<p><strong>Related Searches &#8211;\u00a0 <a href=\"https:\/\/opstree.com\/services\/\" target=\"_blank\" rel=\"noreferrer noopener\">DevOps Solution<\/a> | <a href=\"https:\/\/opstree.com\/services\/database-and-data-engineering\/\" target=\"_blank\" rel=\"noopener\">Data Engineering Services<\/a>\u00a0\u00a0<\/strong><\/p>\r\n\r\n\r\n\r\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\"><\/div>\r\n\r\n\r\n\r\n<ul class=\"wp-block-social-links aligncenter is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-1 wp-block-social-links-is-layout-flex\"><li class=\"wp-social-link wp-social-link-linkedin  wp-block-social-link\"><a rel=\"noopener nofollow\" target=\"_blank\" href=\"https:\/\/www.linkedin.com\/company\/opstree-solutions\" class=\"wp-block-social-link-anchor\"><svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z\"><\/path><\/svg><span class=\"wp-block-social-link-label screen-reader-text\">LinkedIn<\/span><\/a><\/li>\r\n\r\n<li class=\"wp-social-link wp-social-link-youtube  wp-block-social-link\"><a rel=\"noopener nofollow\" target=\"_blank\" href=\"https:\/\/www.youtube.com\/channel\/UCeLma6SpNYH7jjYKSBNSexw\" class=\"wp-block-social-link-anchor\"><svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z\"><\/path><\/svg><span class=\"wp-block-social-link-label screen-reader-text\">YouTube<\/span><\/a><\/li>\r\n\r\n<li class=\"wp-social-link wp-social-link-github  wp-block-social-link\"><a rel=\"noopener nofollow\" target=\"_blank\" href=\"https:\/\/github.com\/OpsTree\" class=\"wp-block-social-link-anchor\"><svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z\"><\/path><\/svg><span class=\"wp-block-social-link-label screen-reader-text\">GitHub<\/span><\/a><\/li>\r\n\r\n<li class=\"wp-social-link wp-social-link-facebook  wp-block-social-link\"><a rel=\"noopener nofollow\" target=\"_blank\" href=\"https:\/\/www.facebook.com\/opstree\" class=\"wp-block-social-link-anchor\"><svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z\"><\/path><\/svg><span class=\"wp-block-social-link-label screen-reader-text\">Facebook<\/span><\/a><\/li>\r\n\r\n<li class=\"wp-social-link wp-social-link-medium  wp-block-social-link\"><a rel=\"noopener nofollow\" target=\"_blank\" href=\"https:\/\/medium.com\/buildpiper\" class=\"wp-block-social-link-anchor\"><svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M20.962,7.257l-5.457,8.867l-3.923-6.375l3.126-5.08c0.112-0.182,0.319-0.286,0.527-0.286c0.05,0,0.1,0.008,0.149,0.02 c0.039,0.01,0.078,0.023,0.114,0.041l5.43,2.715l0.006,0.003c0.004,0.002,0.007,0.006,0.011,0.008 C20.971,7.191,20.98,7.227,20.962,7.257z M9.86,8.592v5.783l5.14,2.57L9.86,8.592z M15.772,17.331l4.231,2.115 C20.554,19.721,21,19.529,21,19.016V8.835L15.772,17.331z M8.968,7.178L3.665,4.527C3.569,4.479,3.478,4.456,3.395,4.456 C3.163,4.456,3,4.636,3,4.938v11.45c0,0.306,0.224,0.669,0.498,0.806l4.671,2.335c0.12,0.06,0.234,0.088,0.337,0.088 c0.29,0,0.494-0.225,0.494-0.602V7.231C9,7.208,8.988,7.188,8.968,7.178z\"><\/path><\/svg><span class=\"wp-block-social-link-label screen-reader-text\">Medium<\/span><\/a><\/li>\r\n\r\n<li class=\"wp-social-link wp-social-link-twitter  wp-block-social-link\"><a rel=\"noopener nofollow\" target=\"_blank\" href=\"https:\/\/twitter.com\/opstreedevops\" class=\"wp-block-social-link-anchor\"><svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M22.23,5.924c-0.736,0.326-1.527,0.547-2.357,0.646c0.847-0.508,1.498-1.312,1.804-2.27 c-0.793,0.47-1.671,0.812-2.606,0.996C18.324,4.498,17.257,4,16.077,4c-2.266,0-4.103,1.837-4.103,4.103 c0,0.322,0.036,0.635,0.106,0.935C8.67,8.867,5.647,7.234,3.623,4.751C3.27,5.357,3.067,6.062,3.067,6.814 c0,1.424,0.724,2.679,1.825,3.415c-0.673-0.021-1.305-0.206-1.859-0.513c0,0.017,0,0.034,0,0.052c0,1.988,1.414,3.647,3.292,4.023 c-0.344,0.094-0.707,0.144-1.081,0.144c-0.264,0-0.521-0.026-0.772-0.074c0.522,1.63,2.038,2.816,3.833,2.85 c-1.404,1.1-3.174,1.756-5.096,1.756c-0.331,0-0.658-0.019-0.979-0.057c1.816,1.164,3.973,1.843,6.29,1.843 c7.547,0,11.675-6.252,11.675-11.675c0-0.178-0.004-0.355-0.012-0.531C20.985,7.47,21.68,6.747,22.23,5.924z\"><\/path><\/svg><span class=\"wp-block-social-link-label screen-reader-text\">Twitter<\/span><\/a><\/li><\/ul>\r\n","protected":false},"excerpt":{"rendered":"<p>In the world of iOS mobile app development, implementing a robust CI\/CD (Continuous Integration\/Continuous Delivery) pipeline is essential to ensure efficient and reliable software delivery. Capacitor JS is a powerful framework that allows developers to build cross-platform mobile apps using web technologies. When combined with Azure DevOps, it enables a seamless CI\/CD pipeline for iOS &hellip; <a href=\"https:\/\/opstree.com\/blog\/2023\/06\/27\/cicd-for-mobile-app-development-using-capacitor-js-on-azure-devops\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;CICD for Mobile App Development Using Capacitor JS on Azure DevOps&#8221;<\/span><\/a><\/p>\n","protected":false},"author":236397665,"featured_media":29900,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[28070474],"tags":[44070,335778,460,768739308,676319247,4996032],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/opstree.com\/blog\/wp-content\/uploads\/2025\/11\/DevSecOps-1.jpg","jetpack_likes_enabled":false,"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pfDBOm-3Js","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts\/14350"}],"collection":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/users\/236397665"}],"replies":[{"embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/comments?post=14350"}],"version-history":[{"count":26,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts\/14350\/revisions"}],"predecessor-version":[{"id":29924,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts\/14350\/revisions\/29924"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/media\/29900"}],"wp:attachment":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/media?parent=14350"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/categories?post=14350"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/tags?post=14350"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}