{"id":63278,"date":"2024-08-14T11:50:13","date_gmt":"2024-08-14T06:20:13","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=63278"},"modified":"2024-08-14T12:29:53","modified_gmt":"2024-08-14T06:59:53","slug":"ios-ci-cd-integration-using-gitlab-fastlane-firebase-part-1-page-2","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/ios-ci-cd-integration-using-gitlab-fastlane-firebase-part-1-page-2\/","title":{"rendered":"iOS: CI\/CD Integration via FastLane &amp; Firebase using Gitlab : Part \u2013 2"},"content":{"rendered":"<p>In the<a href=\"https:\/\/www.tothenew.com\/blog\/ios-ci-cd-integration-using-gitlab-fastlane-firebase-part-1-page-1\/\"> first part of the blog<\/a>, we covered the Fastlane setup\/Installation with multiple files like Appfile, Gymfile, and Fastfile. Now we are moving to the next part of this series where we will use CI\/CD workflow via Fastlane &amp; Firebase on the local machine.<\/p>\n<p>We will use the next step of the Code Signing approach via the <strong><em>match import <\/em><\/strong>command. This will create a separate repository and upload your private keys and certificates in a Gitlab repo for syncing them across the machines. This approach <a href=\"https:\/\/docs.fastlane.tools\/actions\/match\/#is-this-secure\">is secure<\/a>.<\/p>\n<p><b>Code Signing approach:\u00a0 <\/b><b>Using Fastlane <\/b><a href=\"https:\/\/fastlane.tools\/match\"><b>match<\/b><\/a><\/p>\n<p><span style=\"font-weight: 400;\">The concept of <\/span><a href=\"https:\/\/fastlane.tools\/match\"><i><span style=\"font-weight: 400;\">match<\/span><\/i><\/a><span style=\"font-weight: 400;\"> command is described in the <\/span><a href=\"https:\/\/codesigning.guide\/\"><span style=\"font-weight: 400;\">codesigning guide<\/span><\/a><span style=\"font-weight: 400;\">.<\/span><\/p>\n<h2><b>Import: Prepare Certificates Using Match(Only one-time setup)<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">To import and encrypt a certificate <em>(<\/em><\/span><em><span style=\"font-weight: 400;\">.cer<\/span><\/em><span style=\"font-weight: 400;\"><em>)<\/em>, the private key <em>(<\/em><\/span><em><span style=\"font-weight: 400;\">.p12<\/span><\/em><span style=\"font-weight: 400;\"><em>),<\/em> and the provisioning profiles <em>(<\/em><\/span><em><span style=\"font-weight: 400;\">.mobileprovision<\/span><span style=\"font-weight: 400;\"> or <\/span><span style=\"font-weight: 400;\">.provisionprofile<\/span><\/em><span style=\"font-weight: 400;\"><em>)<\/em> into the <\/span><i><span style=\"font-weight: 400;\">match<\/span><\/i><span style=\"font-weight: 400;\"> repo run:<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">\r\n<strong>$ fastlane match import\r\n<\/strong><\/span>\r\n<\/pre>\n<p><span style=\"font-weight: 400;\">You will be prompted for the certificate (<\/span><span style=\"font-weight: 400;\">.cer<\/span><span style=\"font-weight: 400;\">), the private key (<\/span><span style=\"font-weight: 400;\">.p12<\/span><span style=\"font-weight: 400;\">), and the provisioning profiles (<\/span><span style=\"font-weight: 400;\">.mobileprovision<\/span><span style=\"font-weight: 400;\"> or <\/span><span style=\"font-weight: 400;\">.provisionprofile<\/span><span style=\"font-weight: 400;\">) paths. <\/span><i><span style=\"font-weight: 400;\">match<\/span><\/i><span style=\"font-weight: 400;\"> will first validate the certificate (<\/span><span style=\"font-weight: 400;\">.cer<\/span><span style=\"font-weight: 400;\">) against the Developer Portal before importing the certificate, the private key, and the provisioning profiles into the specified <\/span><em><strong>match<\/strong><\/em><span style=\"font-weight: 400;\"> repository.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">However, if there is no access to the developer portal but there are certificates, private keys, and profiles provided, you can use the <\/span><strong><em>skip_certificate_matching<\/em><\/strong><span style=\"font-weight: 400;\"> option to tell <\/span><strong><i>match<\/i><\/strong><span style=\"font-weight: 400;\"> not to verify the certificates. Like this:<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">\r\n<strong>$ fastlane match import --skip_certificate_matching true\r\n<\/strong><\/span>\r\n<\/pre>\n<p><span style=\"font-weight: 400;\">The default type is \u2018<\/span><span style=\"font-weight: 400;\"><em><strong>development<\/strong><\/em>\u2019. So we need to specify the type explicitly.<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">\r\n<strong>$ fastlane match import --type enterprise --skip_certificate_matching true\r\n\r\n<\/strong><\/span><\/pre>\n<p><span style=\"font-weight: 400;\">This step will skip login to the Apple Developer Portal and will import the provided certificate, private key, and profile directly to the certificates Gitlab repo.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">We need to be careful when using this option and ensure the certificates and profiles match the type (development, adhoc, appstore, enterprise, developer_id) and are not revoked or expired.\u00a0<\/span><\/p>\n<p><b>4. Matchfile- <\/b>Please follow the steps while initializing the <strong>match<\/strong> command with prompted options.<\/p>\n<p><span style=\"font-weight: 400;\"><strong>Step-1. <\/strong>Initialize Match in your iOS project by running the command <\/span><em><strong>fastlane match init <\/strong><\/em><span style=\"font-weight: 400;\">in the root directory of your project.<\/span><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/07\/unnamed-4.png\" alt=\"null\" \/><\/p>\n<p><span style=\"font-weight: 400;\"><strong>Step-2<\/strong>. Fastlane Match supports multiple storage modes and will ask you to select the one you want to use like options <\/span><b>1, 2, and so on. <\/b>In this blog, We have selected option 1 which is &#8216;<strong>git<\/strong>&#8216;.<\/p>\n<p><span style=\"font-weight: 400;\"><strong>Step-3<\/strong>. The system will ask you for the URL of the Git Repo t<\/span><span style=\"font-weight: 400;\">hen Enter the <\/span><b><i>EMPTY GIT-CETIFICATE URL (it&#8217;s added on prerequisites new to provide a separate shared repository ).<\/i><\/b><\/p>\n<p><span style=\"font-weight: 400;\">Now Match file will be created on your root Directory-<\/span><br \/>\n<a href=\"https:\/\/gitlab.com\/ios-tester\/Todo_ios\/-\/blob\/main\/fastlane\/Matchfile?ref_type=heads\"><img decoding=\"async\" loading=\"lazy\" class=\"alignright\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/08\/data-copy.png\" alt=\"null\" width=\"56\" height=\"56\" \/><\/a><\/p>\n<pre><span style=\"font-weight: 400;\">\r\n<strong><span class=\"hljs-built_in\" style=\"color: #ff00ff;\"> git_url<\/span>(\"EMPTY GIT-CETIFICATE Repoistory\")\r\n<span class=\"hljs-built_in\" style=\"color: #ff00ff;\"> storage_mode<\/span>(\"git\")\r\n<span class=\"hljs-built_in\" style=\"color: #ff00ff;\"> type<\/span>(\"enterprise\") # The default type, can be: appstore, adhoc, enterprise or development\r\n ENV[<span class=\"hljs-string\" style=\"color: #ff0000;\">\"MATCH_PASSWORD\"<\/span>] = <span class=\"hljs-string\" style=\"color: #ff0000;\">\"MATCH_PASSWORD\"<\/span>\r\n\r\n<\/strong><\/span><\/pre>\n<p><b>Setup Fastfile actions-<\/b><span style=\"font-weight: 400;\"> In the Fastlfile Actions, We will set up all the actions like custom variables, and lanes to execute the set of tasks in a sequential manner.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Add the Below Script on the Fastlane File-<\/span><br \/>\n<a href=\"https:\/\/gitlab.com\/ios-tester\/Todo_ios\/-\/blob\/main\/fastlane\/Fastfile?ref_type=heads\"><img decoding=\"async\" loading=\"lazy\" class=\"alignright\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/08\/data-copy.png\" alt=\"null\" width=\"56\" height=\"56\" \/><\/a><\/p>\n<pre><span style=\"font-weight: 400;\">\r\n<strong># This file contains the fastlane.tools configuration\r\n# You can find the documentation at https:\/\/docs.fastlane.tools\r\n#\r\n# For a list of all available actions, check out\r\n#\r\n#     https:\/\/docs.fastlane.tools\/actions\r\n#\r\n# For a list of all available plugins, check out\r\n#\r\n#     https:\/\/docs.fastlane.tools\/plugins\/available-plugins\r\n#\r\n\r\n# Uncomment the line if you want fastlane to automatically update itself\r\n# update_fastlane\r\n\r\n#Variables\r\nAPP_BUNDLE_ID = \"com.test.iOS\"\r\n#APP_BUNDLE_ID_NSE = \"com.test.iOS.Todo_ios-NSE\"\r\n#APP_BUNDLE_ID_NCE = \"com.test.iOS.Todo_ios-NCE\"\r\n\r\nAPP_PROVISION_TITLE = \"AdhocDistribution\"\r\n#APP_PROVISION_TITLE_NSE = \"Todo_ios Adhoc NSE\"\r\n#APP_PROVISION_TITLE_NCE = \"Todo_ios Adhoc NCE\"\r\n\r\n#App Method support list\r\n#[\"app-store\", \"validation\", \"ad-hoc\", \"package\", \"enterprise\", \"development\", \"developer-id\", \"mac-application\"]\r\nAPP_METHOD = \"enterprise\"\r\n\r\n# The default type, can be: appstore, adhoc, enterprise or development\r\nMATCH_METHOD = \"enterprise\"\r\n\r\nPROJECT_SCHEMA_QA = 'Todo_ios'\r\nPROJECT_WORKSPACE = 'Todo_ios.xcworkspace'\r\nPROJECT_XCODEPROJ = 'Todo_ios.xcodeproj'\r\nIPA_FILE_NAME = \"Todo_ios\"\r\nBUILD_PATH = \".\/builds\"\r\nINCLUDE_BITCODE = false\r\nINCLUDE_SYMBOLS = false\r\n\r\nFIREBASE_APP_ID = \"FIREBASE_APP_ID\"# i.e, \"1:58453............\"\r\nTESTER_LIST = \"test@gmail.com\" # Add with coma separated\r\nRELEASE_NOTES_FILE_PATH = \".\/fastlane\/release-notes.txt\"\r\n\r\nMY_TEAM = \"MY_TEAM\" # i.e, \"RT......\"\r\n\r\nGIT_URL_CERTIFICATES = \"GIT_URL_CERTIFICATES\"# i.e, \"https:.........\/todo_ios_certificate\"\r\n\r\n#Fetch values from environmental variables\r\nusername = ENV['USERNAME']\r\npersonal_github_access_token = \"PERSONAL_GITHUB_ACCESS_TOKEN\" # i.e, \"gl..........\"\r\nauthorization_token_str = \"#{username}:#{personal_github_access_token}\"\r\nbasic_authorization_token = Base64.strict_encode64(authorization_token_str)\r\n\r\n#Key chain passcode of MacOS machine\r\nKEYCHAIN_PASSWORD = \"KEYCHAIN_PASSWORD\" # i.e, \"Raj.........\"\r\n\r\ndefault_platform(:ios)\r\n\r\nplatform :ios do\r\n\r\n desc \"Sync certificates\"\r\n  lane :sync_certificates do\r\n   #read-only disables match from overriding the existing certificates.\r\n   match(type: MATCH_METHOD,\r\n    app_identifier: APP_BUNDLE_ID,\r\n    git_url: GIT_URL_CERTIFICATES,\r\n    git_basic_authorization: basic_authorization_token,\r\n    keychain_password: KEYCHAIN_PASSWORD,\r\n    readonly: true,\r\n    skip_certificate_matching: true,\r\n    verbose: true)\r\n\r\n end\r\n \r\n \r\ndesc \"Update project provisioning\"\r\n lane :update_provisioning do\r\n     \r\n    CERTIFICATE_NAME = ENV[\"sigh_#{APP_BUNDLE_ID}_#{MATCH_METHOD}_certificate-name\"]\r\n    APP_PROVISION_PROFILE_PATH = ENV[\"sigh_#{APP_BUNDLE_ID}_#{MATCH_METHOD}_profile-path\"]\r\n     \r\n    update_project_provisioning(\r\n    xcodeproj: PROJECT_XCODEPROJ,\r\n    profile: APP_PROVISION_PROFILE_PATH,\r\n    build_configuration: \"QA\",\r\n    code_signing_identity: CERTIFICATE_NAME\r\n    )\r\n\r\n end\r\n \r\ndesc \"Disable automatic code signing\"\r\n lane :disable_auto_code_sign do\r\n    # more advanced manual code signing\r\n    update_code_signing_settings(\r\n    use_automatic_signing: false,\r\n    path: \".\/#{PROJECT_XCODEPROJ}\",\r\n    team_id: MY_TEAM,\r\n    bundle_identifier: APP_BUNDLE_ID,\r\n    code_sign_identity: \"\",\r\n    profile_name: \"\"\r\n    )\r\n end\r\n     \r\n \r\n \r\ndesc \"QA Build\"\r\n  lane :qa_build do\r\n  \r\n    APP_PROVISION_PROFILE_NAME = ENV[\"sigh_#{APP_BUNDLE_ID}_#{MATCH_METHOD}_profile-name\"]\r\n    #EXPORT_TEAM_ID  = ENV[\"sigh_#{APP_BUNDLE_ID}_#{MATCH_METHOD}_team-id\"]\r\n        \r\n    gym(scheme: PROJECT_SCHEMA_QA,\r\n    workspace: PROJECT_WORKSPACE,\r\n    clean: true,\r\n    silent: false,\r\n    include_bitcode: INCLUDE_BITCODE,\r\n    include_symbols: INCLUDE_SYMBOLS,\r\n    xcargs: {\r\n        BUNDLE_IDENTIFIER: APP_BUNDLE_ID,\r\n        #PROVISIONING_PROFILE_SPECIFIER: APP_PROVISION_PROFILE_NAME,\r\n        DEVELOPMENT_TEAM: MY_TEAM,\r\n        CODE_SIGN_STYLE: \"Manual\"\r\n    },\r\n    export_xcargs: \"-allowProvisioningUpdates\",\r\n    skip_profile_detection: true,\r\n    export_options: {\r\n        method: APP_METHOD,\r\n        provisioningProfiles: {\r\n         APP_BUNDLE_ID =&gt; APP_PROVISION_TITLE,\r\n        }\r\n    },\r\n    configuration: 'Release',\r\n    output_name: IPA_FILE_NAME,\r\n    output_directory:BUILD_PATH,\r\n    skip_codesigning: false,\r\n    #export_team_id: EXPORT_TEAM_ID,\r\n    verbose: true)\r\n  end\r\n  \r\n  \r\ndesc \"Increament build version\"\r\n  lane :increment_version do\r\n    LATEST_VERSION = 0\r\n  latest_release = firebase_app_distribution_get_latest_release(\r\n    app: FIREBASE_APP_ID\r\n  )\r\n  \r\n  if latest_release != nil\r\n    LATEST_VERSION = latest_release[:buildVersion].to_i\r\n  end\r\n  increment_build_number({ build_number: LATEST_VERSION + 1 })\r\nend\r\n    \r\ndesc \"clean\"\r\n  lane :clean do\r\n    clear_derived_data(derived_data_path: BUILD_PATH)\r\n  end\r\n  \r\ndesc \"Create ipa\"\r\n  lane :build do\r\n    #clean derived data for path\r\n    clean\r\n    \r\n    # Disable automatic code signing\r\n    #disable_auto_code_sign\r\n    \r\n    #match certificate &amp; profile\r\n    sync_certificates\r\n    \r\n    #update project provisioning\r\n    #update_provisioning\r\n    \r\n    # Creates a signed file\r\n    qa_build\r\n end\r\nend\r\n<\/strong><\/span><\/pre>\n<p>Note: Please update your own detail in the above script i.e,.<\/p>\n<p>APP_BUNDLE_ID,<\/p>\n<p>APP_PROVISION_TITLE,<\/p>\n<p>FIREBASE_APP_ID,<\/p>\n<p>TESTER_LIST,<\/p>\n<p>MY_TEAM,<\/p>\n<p>GIT_URL_CERTIFICATES,<\/p>\n<p>PERSONAL_GITHUB_ACCESS_TOKEN,<\/p>\n<p>KEYCHAIN_PASSWORD.<\/p>\n<p><span style=\"font-weight: 400;\">Now run <\/span><b><i>fastlane ios build<\/i><\/b><span style=\"font-weight: 400;\"> command,\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><strong>Result:-<\/strong> The above command will generate the .ipa file using above configuration setup with the fastlane summary.\u00a0\u00a0<\/span><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/07\/unnamed-3-1.png\" alt=\"null\" \/><\/p>\n<h2><b>Trouble Shoot:-<\/b><\/h2>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Validate Bundle Identifiers on FastFile.<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Validate that Schema and Project names are Proper.<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Make Sure You have disabled automatic Sign-in and manually add profiles.<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Make sure that your iOS project is properly set up Locally on Xcode and you are able to archive and export to the app store by disabling automatic signing.<br \/>\n<\/span><\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<h1><b>Upload to firebase<\/b><\/h1>\n<p><span style=\"font-weight: 400;\">Next, you need to set up the Firebase App Distribution plugin. This tool allows you to upload to Firebase from Fastlane with an action. <\/span><span style=\"font-weight: 400;\">From the Terminal, run the following command to add the App Distribution plugin to your Fastlane installation:<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">\r\n<strong>$ fastlane add_plugin firebase_app_distribution\r\n\r\n<\/strong><\/span><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/07\/unnamed-5.png\" alt=\"null\" \/><\/p>\n<p><span style=\"font-weight: 400;\">If for some reason, plugins are not installed, try again after disabling the VPN.<\/span><\/p>\n<p><b>The next step is to log in to Firebase. Follow the steps mentioned on the website.<\/b><\/p>\n<pre><strong>  <a class=\"af nd\" href=\"https:\/\/firebase.google.com\/docs\/cli\" target=\"_blank\" rel=\"noopener ugc nofollow\">https:\/\/firebase.google.com\/docs\/cli<\/a>\r\n<\/strong><\/pre>\n<p><span style=\"font-weight: 400;\">Now open Fastfile in a text editor, and paste the code below fastlane lane:<\/span><br \/>\n<a href=\"https:\/\/gitlab.com\/ios-tester\/Todo_ios\/-\/blob\/main\/fastlane\/Fastfile?ref_type=heads\"><img decoding=\"async\" loading=\"lazy\" class=\"alignright\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/08\/data-copy.png\" alt=\"null\" width=\"56\" height=\"56\" \/><\/a><\/p>\n<pre> <span style=\"font-weight: 400;\">\r\n<strong>desc \"Upload build to Firebase\" \r\n  lane :upload_build_to_firebase do \r\n  firebase_app_distribution( \r\n  ipa_path: \"#{BUILD_PATH}\/#{IPA_FILE_NAME}.ipa\", \r\n  app: FIREBASE_APP_ID, testers: TESTER_LIST, \r\n  #groups: \"\", \r\n  #release_notes_file: RELEASE_NOTES_FILE_PATH, \r\n  release_notes: \"Testing build upload\") \r\nend\r\n<\/strong><\/span><\/pre>\n<p>Also, add the code below the fastlane <strong><em>build<\/em><\/strong> lane<br \/>\n<a href=\"https:\/\/gitlab.com\/ios-tester\/Todo_ios\/-\/blob\/main\/fastlane\/Fastfile?ref_type=heads\"><img decoding=\"async\" loading=\"lazy\" class=\"alignright\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/08\/data-copy.png\" alt=\"null\" width=\"56\" height=\"56\" \/><\/a><\/p>\n<pre> <span style=\"font-weight: 400;\">\r\n<strong>desc \"Create ipa\"\r\n............\r\n......\r\n\r\n# Increases the build number by 1 \r\n#increment_version\r\n \r\n# Creates a signed file \r\nqa_build \r\n\r\n# Build upload to firebase \r\nupload_build_to_firebase\r\n\r\nend<\/strong><\/span><\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400;\">After all these setups, run the following command from Terminal: <\/span><b><i>fastlane ios build.\u00a0<\/i><\/b><\/p>\n<p><strong>Result<\/strong><span style=\"font-weight: 400;\"><strong>:-<\/strong> This will generate the .ipa file and upload to Firebase App Distribution on Firebase Console.<\/span><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/07\/unnamed-6-1.png\" alt=\"null\" \/><\/p>\n<p><span style=\"font-weight: 400;\">Uploaded build link:<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/07\/unnamed-7.png\" alt=\"null\" width=\"763\" height=\"112\" \/><\/p>\n<p>Concluding that we have covered the CI\/CD workflow via Fastlane &amp; Firebase on the local machine in Part &#8211; 2. We&#8217;ll cover in the next part how to use CI\/CD workflow via Fastlane &amp; Firebase with Gitlab Actions. Stay tuned!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the first part of the blog, we covered the Fastlane setup\/Installation with multiple files like Appfile, Gymfile, and Fastfile. Now we are moving to the next part of this series where we will use CI\/CD workflow via Fastlane &amp; Firebase on the local machine. We will use the next step of the Code Signing [&hellip;]<\/p>\n","protected":false},"author":1898,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":223},"categories":[1400],"tags":[4252,6073,4848,4078],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/63278"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/1898"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=63278"}],"version-history":[{"count":32,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/63278\/revisions"}],"predecessor-version":[{"id":64063,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/63278\/revisions\/64063"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=63278"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=63278"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=63278"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}