{"id":14195,"date":"2022-07-15T07:00:44","date_gmt":"2022-07-15T05:00:44","guid":{"rendered":"https:\/\/sii.pl\/blog\/?p=14195"},"modified":"2023-07-10T14:05:42","modified_gmt":"2023-07-10T12:05:42","slug":"swift-package-ci-with-github-actions-up-to-date-with-xcode-13-3","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/en\/swift-package-ci-with-github-actions-up-to-date-with-xcode-13-3\/","title":{"rendered":"Swift Package CI with GitHub Actions. Up-to-date with Xcode 13.3!"},"content":{"rendered":"\n<p>This article is a continuation of the <a href=\"https:\/\/sii.pl\/blog\/quick-and-simple-modularising-your-project-with-swift-packages-up-to-date-with-xcode-13-2-1\/\">Quick and Simple Modularising Your Project with Swift Packages<\/a> tutorial where we created a local Swift Package and then moved it to the remote repository so we could reuse the module across multiple projects.<\/p>\n\n\n\n<p>This time, we will go through some additional setups, such as versioning the package, upgrading the package in your project, and creating simple CI with GitHub Actions. If you haven\u2019t read the previous article, I encourage you to do so to have the same starting point, however, that\u2019s not mandatory to complete the below steps.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Versioning Swift Package<\/h2>\n\n\n\n<p>You are familiar with the Xcode App versioning system \u2013 you can change the version by opening your project settings in Xcode, selecting the app target, choosing the General tab, and changing the Version or\/and Build number, which appears in the repository as the change to <strong>MARKETING_VERSION<\/strong> and <strong>CURRENT_PROJECT_VERSION<\/strong> in <strong>.xcodeproj\/project\/pbxproj<\/strong> file.<\/p>\n\n\n\n<p>If you are using GitFlow, you are doing those steps and committing change during a new release which \u2013 upon finishing \u2013 is adding a new Git tag with the version number you specify.<\/p>\n\n\n\n<p>Here comes the beauty of the Swift Package. The versioning of your Package is much simpler as there is no file to edit the version. Your <strong>Package.swift<\/strong> configuration does not declare the Package version. All the magic happens with the Git tags! In fact, you don\u2019t even need to version your Swift Package, and you can use it by referring to the Git branch (which we did in the previous article), although, if you think of continuing developing your Package and keeping it public, it might be much more maintainable to start adding the version tags.<\/p>\n\n\n\n<p>Feel free to add the first version tag in your Package Git and call it 1.0.0. Don\u2019t forget to also change the Version Rules of your Package used in the project from Branch to Version.<\/p>\n\n\n\n<p>In Xcode, select your <strong>Project<\/strong> and under the <strong>Package Dependencies<\/strong> in the <strong>Packages<\/strong> section, double click your Package.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/versioning_01.png\"><img decoding=\"async\" width=\"966\" height=\"264\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/versioning_01.png\" alt=\"\" class=\"wp-image-14197\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/versioning_01.png 966w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/versioning_01-300x82.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/versioning_01-768x210.png 768w\" sizes=\"(max-width: 966px) 100vw, 966px\" \/><\/a><\/figure>\n\n\n\n<p>The recommended rule is to use Version \u201cUp to Next Major\u201d.<\/p>\n\n\n\n<p>Press <strong>Done<\/strong> to finish.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/versioning_02.png\"><img decoding=\"async\" width=\"483\" height=\"202\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/versioning_02.png\" alt=\"\" class=\"wp-image-14198\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/versioning_02.png 483w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/versioning_02-300x125.png 300w\" sizes=\"(max-width: 483px) 100vw, 483px\" \/><\/a><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Important:<\/strong> The version tag must contain only numbers separated by dots in a common major.minor.patch version pattern.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Updating Swift Package<\/h2>\n\n\n\n<p>Updating Swift Package used in your project is a very trivial task. In fact, if you set the Version Rules to be \u201cUp to Next Major\u201d and recompile the project, Xcode will automatically pull the latest Minor version of your Package (or any other third-party Packages) for you.<\/p>\n\n\n\n<p>In a few clicks, you can also do it manually, simply, by right-clicking on the Package in Xcodes\u2019 Project Navigator and selecting <strong>Update Package<\/strong>.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/updating_packages_01.png\"><img decoding=\"async\" width=\"333\" height=\"505\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/updating_packages_01.png\" alt=\"\" class=\"wp-image-14199\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/updating_packages_01.png 333w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/updating_packages_01-198x300.png 198w\" sizes=\"(max-width: 333px) 100vw, 333px\" \/><\/a><\/figure>\n\n\n\n<p>Keep in mind, that with the \u201cUp to Next Major\u201d version rule in use, when the Major version of the Package will change, the <strong>Update Package<\/strong> won\u2019t pull that version.<\/p>\n\n\n\n<p>To fix that, in Xcode, select your <strong>Project<\/strong> and under the <strong>Package Dependencies<\/strong> in the <strong>Packages<\/strong> section, double click your Package. In the popup window, bump the version to the latest Major version and press <strong>Done<\/strong>.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/updating_packages_02.png\"><img decoding=\"async\" width=\"485\" height=\"205\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/updating_packages_02.png\" alt=\"\" class=\"wp-image-14200\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/updating_packages_02.png 485w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/updating_packages_02-300x127.png 300w\" sizes=\"(max-width: 485px) 100vw, 485px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting<\/h2>\n\n\n\n<p>Swift Package is not recognized by the Xcode project. With any issues related to Swift Package used in your project (project unable to compile, importing Package in Swift files can\u2019t find dependency in the scope, and any other), the best silver bullet to resolve them all is to remove and re-add the Swift Package to the project.<\/p>\n\n\n\n<p>To remove the Package, select your <strong>Project,<\/strong> and under the <strong>Package Dependencies<\/strong> in the <strong>Packages<\/strong> section. Single-click your Package and press the minus \u201c-\u201d button below.<\/p>\n\n\n\n<p>Then, re-add the Package by following the steps in the <a href=\"https:\/\/github.com\/LooseMarek\/SwiftPackageTutorial\" rel=\"nofollow\" >Quick and Simple Modularising Your Project with Swift Packages<\/a> tutorial.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Use GitHub Actions to Build a Simple CI for Your Swift Package<\/h2>\n\n\n\n<p>By hosting your Swift Package repository in GitHub, you are getting access to the <a href=\"https:\/\/github.com\/features\/actions\" rel=\"nofollow\" >GitHub Actions<\/a> which may build and test your Package.<\/p>\n\n\n\n<p>As of the time of writing this article, if you have a Free account, you will have a total of 2000 minutes per month for running your GitHub Action workflows. There is a catch, though. If you are running your workflows on a macOS (which you need, to build the Swift Packages) each minute counts as 10 minutes, so this works out for three hours and 20 minutes of total run time. But don\u2019t worry &#8211; if you will use the Swift Packages to keep small, quickly testable components, your builds will take about three to five minutes, so you won\u2019t hit that monthly threshold.<\/p>\n\n\n\n<p>You can read more about this in the <a href=\"https:\/\/docs.github.com\/en\/billing\/managing-billing-for-github-actions\/about-billing-for-github-actions\" rel=\"nofollow\" >billing<\/a> section of the GitHub documentation.<\/p>\n\n\n\n<p>The entire workflow setups bring down to creating one YAML file containing 35 lines of code (25 lines without spacing) inside <strong>.github\/workflows<\/strong> directory (you will need to create those folders as well). That\u2019s all.<\/p>\n\n\n\n<p>Yes, it\u2019s that simple!<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/gha_ci_01.png\"><img decoding=\"async\" width=\"1094\" height=\"442\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/gha_ci_01.png\" alt=\"\" class=\"wp-image-14201\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/gha_ci_01.png 1094w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/gha_ci_01-300x121.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/gha_ci_01-1024x414.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/gha_ci_01-768x310.png 768w\" sizes=\"(max-width: 1094px) 100vw, 1094px\" \/><\/a><\/figure>\n\n\n\n<p>Your YAML file looks like <a href=\"https:\/\/github.com\/LooseMarek\/MyFirstSwiftPackage\/blob\/main\/.github\/workflows\/build_and_test.yml\" rel=\"nofollow\" >this<\/a>:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/gha_ci_02.png\"><img decoding=\"async\" width=\"1022\" height=\"743\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/gha_ci_02.png\" alt=\"\" class=\"wp-image-14202\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/gha_ci_02.png 1022w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/gha_ci_02-300x218.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/gha_ci_02-768x558.png 768w\" sizes=\"(max-width: 1022px) 100vw, 1022px\" \/><\/a><\/figure>\n\n\n\n<p>A brief overview of what is happening in that workflow is as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>(lines 3-5) Workflow triggered by the push to the main branch<\/li>\n\n\n\n<li>(lines 7-9) Setup scheme name to build and test simulator as environment variables<\/li>\n\n\n\n<li>(lines 12-22) Build job which checks out the repository and builds the Package with the <strong>xcodebuild\u2026build<\/strong> command in the bash<\/li>\n\n\n\n<li>(lines 24-34) Test job which checks out the repository and tests the Package with the <strong>xcodebuild\u2026test<\/strong> command in the bash<\/li>\n<\/ul>\n\n\n\n<p>Finally, commit the changes and push\/merge them to the main branch. The workflow will trigger automatically, and you will be able to see the results on GitHub under the <strong>Actions<\/strong> tab.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/gha_ci_03.png\"><img decoding=\"async\" width=\"2590\" height=\"828\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/gha_ci_03.png\" alt=\"\" class=\"wp-image-14203\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/gha_ci_03.png 2590w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/gha_ci_03-300x96.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/gha_ci_03-1024x327.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/gha_ci_03-768x246.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/gha_ci_03-1536x491.png 1536w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/gha_ci_03-2048x655.png 2048w\" sizes=\"(max-width: 2590px) 100vw, 2590px\" \/><\/a><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Note: <\/strong>If you were creating your Swift Package based on the <a href=\"https:\/\/github.com\/LooseMarek\/MyFirstSwiftPackage\" rel=\"nofollow\" >MyFirstSwiftPackage<\/a> example, the test job may fail as the testExample() wasn\u2019t updated with the change of the example label. You should also get an email notification about the failing job. Change the test assertion to \u201cHello, World from Swift Package!\u201d to fix it.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Bonus Tip: Creating Dynamic Tags in Your Documentation<\/h2>\n\n\n\n<p>If you made your Swift Package public, you may consider adding <a href=\"https:\/\/shields.io\/\" rel=\"nofollow\" >Shields IO<\/a> tags to your <strong>README.md<\/strong> file. This will give a quick overview of your Package such as version, language, issues count, and many more.<\/p>\n\n\n\n<p>If you completed the previous step, you could add the status of the project as well.<\/p>\n\n\n\n<p>All those tags may help other developers to decide if it\u2019s worth using your Package.<\/p>\n\n\n\n<p>The syntax for the tags in the MarkDown file is the same as for images, which is! <strong>[description](url)<\/strong>.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/documentation_tags_01.png\"><img decoding=\"async\" width=\"1114\" height=\"217\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/documentation_tags_01.png\" alt=\"\" class=\"wp-image-14204\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/documentation_tags_01.png 1114w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/documentation_tags_01-300x58.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/documentation_tags_01-1024x199.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/documentation_tags_01-768x150.png 768w\" sizes=\"(max-width: 1114px) 100vw, 1114px\" \/><\/a><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Note: <\/strong>For better clarity of the failing CI job, you may want to break .github\/workflows\/build_and_test.yml workflow into two separate workflows (one for build and one for test) and have two separate tags in the documentation.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Resources<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/www.swift.org\/package-manager\/\" rel=\"nofollow\" >Swift Package Manager<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/features\/actions\" rel=\"nofollow\" >GitHub Actions<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/shields.io\/\" rel=\"nofollow\" >Shields IO<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/docs.github.com\/en\/billing\/managing-billing-for-github-actions\/about-billing-for-github-actions\" rel=\"nofollow\" >GitHub Actions Billings<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/LooseMarek\/SwiftPackageTutorial\" rel=\"nofollow\" >SwiftPackageTutorial project example<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/LooseMarek\/MyFirstSwiftPackage\" rel=\"nofollow\" >MyFirstSwiftPackage Swift Package example<\/a><\/li>\n<\/ul>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;14195&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;4&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;4.7&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;11&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;4.7\\\/5 ( votes: 4)&quot;,&quot;size&quot;:&quot;18&quot;,&quot;title&quot;:&quot;Swift Package CI with GitHub Actions. Up-to-date with Xcode 13.3!&quot;,&quot;width&quot;:&quot;130.8&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} ( {votes}: {count})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 130.8px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 14.4px;\">\n            4.7\/5 ( votes: 4)    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>This article is a continuation of the Quick and Simple Modularising Your Project with Swift Packages tutorial where we created &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/en\/swift-package-ci-with-github-actions-up-to-date-with-xcode-13-3\/\">Continued<\/a><\/p>\n","protected":false},"author":284,"featured_media":19755,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1319],"tags":[],"class_list":["post-14195","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-soft-development"],"acf":[],"aioseo_notices":[],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/08\/Swift-Package-CI-with-GitHub-Actions.-Up-to-date-with-Xcode-13.3-1.jpg","category_names":["Soft development"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/14195"}],"collection":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/users\/284"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/comments?post=14195"}],"version-history":[{"count":2,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/14195\/revisions"}],"predecessor-version":[{"id":22785,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/14195\/revisions\/22785"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/media\/19755"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/media?parent=14195"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/categories?post=14195"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/tags?post=14195"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}