{"id":4682,"date":"2020-02-24T08:17:51","date_gmt":"2020-02-24T06:17:51","guid":{"rendered":"https:\/\/www.almtoolbox.com\/blog_he\/?p=4682"},"modified":"2020-03-09T12:35:02","modified_gmt":"2020-03-09T10:35:02","slug":"gitlab-ci-cd-demo","status":"publish","type":"post","link":"https:\/\/www.almtoolbox.com\/blog_he\/gitlab-ci-cd-demo\/","title":{"rendered":"\u05d5\u05d9\u05d3\u05d0\u05d5 \u05d4\u05d3\u05d2\u05de\u05d4 \u05d7\u05d3\u05e9: GitLab CI\/CD Demo"},"content":{"rendered":"<p><a href=\"https:\/\/www.almtoolbox.com\/blog_he\/wp-content\/uploads\/2020\/02\/video-gitlab-ci-demo-2.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-4719 size-full\" src=\"https:\/\/www.almtoolbox.com\/blog_he\/wp-content\/uploads\/2020\/02\/video-gitlab-ci-demo-2.jpg\" alt=\"\" width=\"680\" height=\"400\" srcset=\"https:\/\/www.almtoolbox.com\/blog_he\/wp-content\/uploads\/2020\/02\/video-gitlab-ci-demo-2.jpg 680w, https:\/\/www.almtoolbox.com\/blog_he\/wp-content\/uploads\/2020\/02\/video-gitlab-ci-demo-2-300x176.jpg 300w\" sizes=\"auto, (max-width: 680px) 100vw, 680px\" \/><\/a><\/p>\n<p>\u05d0\u05e0\u05d9 \u05e9\u05de\u05d7 \u05dc\u05e9\u05ea\u05e3 \u05db\u05d0\u05df \u05d1\u05d5\u05d9\u05d3\u05d0\u05d5 \u05e9\u05d4\u05d5\u05d0 \u05d3\u05de\u05d5 \u05d8\u05db\u05e0\u05d9, \u05e2\u05d3\u05db\u05e0\u05d9 \u05d5\u05ea\u05de\u05e6\u05d9\u05ea\u05d9 \u05e2\u05dc GitLab CI\/CD &#8211; \u05d5\u05d9\u05d3\u05d0\u05d5 \u05e9\u05d1\u05d7\u05e8\u05ea\u05d9 \u05db\u05d8\u05d5\u05d1 \u05d1\u05d9\u05d5\u05ea\u05e8 \u05de\u05d1\u05d9\u05df \u05db\u05de\u05d4 \u05e1\u05e8\u05d8\u05d5\u05e0\u05d9\u05dd \u05e9\u05e6\u05e4\u05d9\u05ea\u05d9 \u05d1\u05d4\u05dd \u05dc\u05d0\u05d7\u05e8\u05d5\u05e0\u05d4.<\/p>\n<p>\u05dc\u05e0\u05d5\u05d7\u05d9\u05d5\u05ea\u05db\u05dd \u05d4\u05d5\u05e1\u05e4\u05e0\u05d5 \u05db\u05ea\u05d5\u05d1\u05d9\u05d5\u05ea , \u05e1\u05d9\u05db\u05d5\u05dd \u05e9\u05dc \u05d4\u05d5\u05d9\u05d3\u05d0\u05d5 \u05d5\u05d8\u05e7\u05e1\u05d8 \u05de\u05dc\u05d0 (transcription) \u05e9\u05dc \u05d4\u05d5\u05d9\u05d3\u05d0\u05d5. \u05d0\u05ea \u05d4\u05d5\u05d9\u05d3\u05d0\u05d5 \u05d4\u05de\u05dc\u05d0 \u05d5\u05d0\u05ea \u05d4\u05e1\u05d9\u05db\u05d5\u05dd \u05e0\u05d9\u05ea\u05df \u05dc\u05e7\u05d1\u05dc \u05de\u05d9\u05d9\u05d3\u05d9\u05ea \u05d1\u05d4\u05e9\u05d0\u05e8\u05ea \u05e4\u05e8\u05d8\u05d9\u05dd \u05db\u05d0\u05df \u05d1\u05d4\u05de\u05e9\u05da.<\/p>\n<h3>\u05de\u05d4 \u05e0\u05d9\u05ea\u05df \u05dc\u05dc\u05de\u05d5\u05d3 \u05de\u05e6\u05e4\u05d9\u05d4 \u05d1\u05d5\u05d9\u05d3\u05d0\u05d5 ?<\/h3>\n<ul>\n<li>\u05db\u05d9\u05e6\u05d3 \u05e2\u05d5\u05d1\u05d3 GitLab CI\/CD<\/li>\n<li>\u05d0\u05d9\u05da \u05dc\u05e7\u05e0\u05e4\u05d2 \u05d0\u05ea \u05d4\u05de\u05e2\u05e8\u05db\u05ea \u05dc\u05d1\u05e0\u05d9\u05d9\u05ea pipelines \u05e9\u05de\u05d5\u05ea\u05d0\u05de\u05d9\u05dd \u05dc\u05e6\u05e8\u05db\u05d9\u05dd \u05e9\u05dc\u05db\u05dd<\/li>\n<li>\u05db\u05d9\u05e6\u05d3 \u05dc\u05d4\u05e8\u05d9\u05e5 CI pipelines (\u05d1\u05d5\u05d9\u05d3\u05d0\u05d5 \u05de\u05d3\u05d2\u05d9\u05de\u05d9\u05dd \u05d6\u05d0\u05ea \u05e2\u05dc \u05d0\u05e4\u05dc\u05d9\u05e7\u05e6\u05d9\u05d4 \u05de\u05d1\u05d5\u05e1\u05e1\u05ea Java)<\/li>\n<li>\u05d0\u05d9\u05da \u05dc\u05e7\u05e0\u05e4\u05d2 runners (\u05d3\u05d4\u05d9\u05d9\u05e0\u05d5 nodes) \u05d5\u05d0\u05d9\u05da \u05dc\u05d4\u05e8\u05d9\u05e5 \u05d1\u05d3\u05d9\u05e7\u05d5\u05ea<\/li>\n<\/ul>\n<div class=\"alm-box alm-contact\">\n<div dir=\"rtl\">\n<h4>\u05dc\u05e6\u05e4\u05d9\u05d4 \u05d1\u05d5\u05d9\u05d3\u05d0\u05d5 \u05d4\u05de\u05dc\u05d0 \u05d5\u05dc\u05d4\u05d5\u05e8\u05d3\u05ea \u05d4\u05e1\u05d9\u05db\u05d5\u05dd \u05e0\u05d0 \u05dc\u05d4\u05d6\u05d9\u05df \u05d0\u05ea \u05d4\u05e4\u05e8\u05d8\u05d9\u05dd \u05d4\u05d1\u05d0\u05d9\u05dd \u05d5\u05d4\u05db\u05dc \u05d9\u05e9\u05dc\u05d7 \u05d0\u05dc\u05d9\u05db\u05dd \u05de\u05d9\u05d9\u05d3\u05d9\u05ea \u05dc\u05de\u05d9\u05d9\u05dc<\/h4>\n\n<div class=\"wpcf7 no-js\" id=\"wpcf7-f4681-o1\" lang=\"he-IL\" dir=\"rtl\" data-wpcf7-id=\"4681\">\n<div class=\"screen-reader-response\"><p role=\"status\" aria-live=\"polite\" aria-atomic=\"true\"><\/p> <ul><\/ul><\/div>\n<form action=\"\/blog_he\/wp-json\/wp\/v2\/posts\/4682#wpcf7-f4681-o1\" method=\"post\" class=\"wpcf7-form init\" aria-label=\"Contact form\" novalidate=\"novalidate\" data-status=\"init\">\n<fieldset class=\"hidden-fields-container\"><input type=\"hidden\" name=\"_wpcf7\" value=\"4681\" \/><input type=\"hidden\" name=\"_wpcf7_version\" value=\"6.1.4\" \/><input type=\"hidden\" name=\"_wpcf7_locale\" value=\"he_IL\" \/><input type=\"hidden\" name=\"_wpcf7_unit_tag\" value=\"wpcf7-f4681-o1\" \/><input type=\"hidden\" name=\"_wpcf7_container_post\" value=\"0\" \/><input type=\"hidden\" name=\"_wpcf7_posted_data_hash\" value=\"\" \/>\n<\/fieldset>\n<div class=\"gitlab-form\">\n\t<p>* \u05e9\u05dd \u05e4\u05e8\u05d8\u05d9 \u05d5\u05de\u05e9\u05e4\u05d7\u05d4:\n\t<\/p>\n\t<p><span class=\"wpcf7-form-control-wrap\" data-name=\"your-name\"><input size=\"40\" maxlength=\"400\" class=\"wpcf7-form-control wpcf7-text wpcf7-validates-as-required\" aria-required=\"true\" aria-invalid=\"false\" value=\"\" type=\"text\" name=\"your-name\" \/><\/span>\n\t<\/p>\n\t<p>* \u05d0\u05d9\u05de\u05d9\u05d9\u05dc:\n\t<\/p>\n\t<p><span class=\"wpcf7-form-control-wrap\" data-name=\"your-email\"><input size=\"40\" maxlength=\"400\" class=\"wpcf7-form-control wpcf7-email wpcf7-validates-as-required wpcf7-text wpcf7-validates-as-email\" aria-required=\"true\" aria-invalid=\"false\" placeholder=\"\u05e0\u05d0 \u05dc\u05e6\u05d9\u05d9\u05df \u05de\u05d9\u05d9\u05dc \u05d0\u05e8\u05d2\u05d5\u05e0\u05d9 (\u05d7\u05d1\u05e8\u05d4) \u05d1\u05dc\u05d1\u05d3\" value=\"\" type=\"email\" name=\"your-email\" \/><\/span>\n\t<\/p>\n\t<p>* \u05d4\u05d0\u05dd \u05db\u05d1\u05e8 \u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd \u05d0\u05e6\u05dc\u05da \u05d1\u05d7\u05d1\u05e8\u05d4 \u05d1- GitLab CI?\n\t<\/p>\n\t<p><span class=\"wpcf7-form-control-wrap\" data-name=\"menu-using-gitlab-ci\"><select class=\"wpcf7-form-control wpcf7-select wpcf7-validates-as-required\" aria-required=\"true\" aria-invalid=\"false\" name=\"menu-using-gitlab-ci\"><option value=\"\"><\/option><option value=\"\u05db\u05df\">\u05db\u05df<\/option><option value=\"\u05dc\u05d0 - \u05d0\u05d1\u05dc \u05e9\u05d5\u05e7\u05dc\u05d9\u05dd \u05dc\u05d4\u05ea\u05d7\u05d9\u05dc \u05dc\u05d4\u05e9\u05ea\u05de\u05e9 \u05d1\u05e7\u05e8\u05d5\u05d1\">\u05dc\u05d0 - \u05d0\u05d1\u05dc \u05e9\u05d5\u05e7\u05dc\u05d9\u05dd \u05dc\u05d4\u05ea\u05d7\u05d9\u05dc \u05dc\u05d4\u05e9\u05ea\u05de\u05e9 \u05d1\u05e7\u05e8\u05d5\u05d1<\/option><option value=\"\u05dc\u05d0\">\u05dc\u05d0<\/option><\/select><\/span>\n\t<\/p>\n\t<p><span class=\"wpcf7-form-control-wrap\" data-name=\"referer-page\"><input size=\"40\" maxlength=\"400\" class=\"wpcf7-form-control wpcf7-text referer-page\" aria-invalid=\"false\" value=\"\" type=\"text\" name=\"referer-page\" \/><\/span>\n\t<\/p>\n\t<p><input class=\"wpcf7-form-control wpcf7-submit has-spinner button button-large\" type=\"submit\" value=\"\u05d0\u05e9\u05de\u05d7 \u05dc\u05e6\u05e4\u05d5\u05ea \u05d1\u05d3\u05de\u05d5 \u05d5\u05dc\u05e7\u05d1\u05dc \u05d0\u05ea \u05d4\u05e1\u05d9\u05db\u05d5\u05dd\" \/>\n\t<\/p>\n<\/div><div class=\"wpcf7-form-control-wrap maspik-field\">\n                <label for=\"full-name-maspik-hp\" class=\"wpcf7-form-control-label\">Leave this field empty<\/label>\n                <input size=\"1\" type=\"text\" autocomplete=\"off\" aria-hidden=\"true\" tabindex=\"-1\" name=\"full-name-maspik-hp\" id=\"full-name-maspik-hp\" class=\"wpcf7-form-control wpcf7-text\" placeholder=\"Leave this field empty\">\n            <\/div><div class=\"wpcf7-response-output\" aria-hidden=\"true\"><\/div>\n<\/form>\n<\/div>\n\n<\/div>\n<div dir=\"rtl\"><\/div>\n<\/div>\n<p>&nbsp;<\/p>\n<h3>\u05d6\u05e7\u05d5\u05e7\u05d9\u05dd \u05dc\u05e1\u05d9\u05d5\u05e2 \u05d1\u05de\u05e2\u05d1\u05e8 \u05dc- GitLab CI\/CD?<\/h3>\n<p>\u05e4\u05e0\u05d5 \u05d0\u05dc\u05d9\u05e0\u05d5 &#8212;\u00a0\u05e0\u05d5\u05db\u05dc \u05dc\u05e1\u05d9\u05d9\u05e2 \u05d1:<br \/>\n\u05d4\u05d3\u05e8\u05db\u05d4,\u00a0\u05d1\u05e0\u05d9\u05d9\u05ea pipelines ,\u00a0\u05de\u05e2\u05d1\u05e8 \u05de\u05db\u05dc\u05d9\u05dd \u05d0\u05d7\u05e8\u05d9\u05dd \u05d3\u05d5\u05d2\u05de\u05ea Jenkins , \u05d4\u05e7\u05de\u05ea runners \u05de\u05e9\u05d5\u05dc\u05d1\u05d9\u05dd \u05e2\u05dd Kubernetes \u05d5\u05e9\u05d9\u05de\u05d5\u05e9 \u05d1\u05e2\u05e0\u05df, \u05d9\u05e6\u05d9\u05e8\u05ea \u05d3\u05d5&quot;\u05d7\u05d5\u05ea \u05d5\u05d2\u05e8\u05e4\u05d9\u05dd \u05de\u05d5\u05ea\u05d0\u05de\u05d9\u05dd \u05de\u05d1\u05d5\u05e1\u05e1\u05d9 GitLab API \/ Excel \u05d5\u05e2\u05d5\u05d3<\/p>\n<p>&nbsp;<\/p>\n<h3>\u05e7\u05d9\u05e9\u05d5\u05e8\u05d9\u05dd \u05e8\u05dc\u05d1\u05e0\u05d8\u05d9\u05dd:<\/h3>\n<ul>\n<li><a href=\"https:\/\/www.almtoolbox.com\/blog_he\/gitlab-ci-cd-overview\/\" target=\"_blank\" rel=\"noopener\">\u05e1\u05e7\u05d9\u05e8\u05d4 \u05e2\u05dc GitLab CI\/CD<\/a> (\u05de\u05d0\u05de\u05e8 \u05d1\u05e2\u05d1\u05e8\u05d9\u05ea)<\/li>\n<li><a href=\"https:\/\/www.almtoolbox.com\/il\/gitlab\" target=\"_blank\" rel=\"noopener\">\u05d0\u05ea\u05e8 GitLab \u05d1\u05e2\u05d1\u05e8\u05d9\u05ea<\/a><\/li>\n<li>\u05db\u05d3\u05d0\u05d9 \u05dc\u05d4\u05db\u05d9\u05e8: <a href=\"https:\/\/www.almtoolbox.com\/blog_he\/free-gitlab-ci-cd-serverless-utilization\/\" target=\"_blank\" rel=\"noopener\">\u05de\u05d9\u05de\u05d5\u05e9 Serverless \u05e9\u05ea\u05d5\u05db\u05dc\u05d5 \u05dc\u05de\u05de\u05e9 \u05e2\u05dd GitLab CI\/CD \u05d1\u05e2\u05e0\u05df \u2013 \u05d5\u05dc\u05dc\u05d0 \u05ea\u05e9\u05dc\u05d5\u05dd<\/a><\/li>\n<li>\u05d5\u05d5\u05e8\u05e7\u05e9\u05d5\u05e4 \u05e2\u05dc GitLab CI\/CD &#8211; \u05d1\u05e7\u05e8\u05d5\u05d1 (\u05e8\u05d5\u05e6\u05d9\u05dd \u05dc\u05e7\u05d1\u05dc \u05de\u05d9\u05d9\u05dc \u05dc\u05db\u05e9\u05d9\u05e6\u05d0? \u05e9\u05dc\u05d7\u05d5 \u05de\u05d9\u05d9\u05dc \u05d0\u05dc gitlab@almtoolbox.com)<\/li>\n<\/ul>\n<h3>\u05d4\u05d8\u05e7\u05e1\u05d8 \u05d4\u05de\u05dc\u05d0 (\u05d5\u05d4\u05dc\u05d0 \u05e2\u05e8\u05d5\u05da) \u05e9\u05dc \u05d4\u05d5\u05d9\u05d3\u05d0\u05d5:<\/h3>\n<p dir=\"ltr\">So here we're in GitLab so GitLab CI\u00a0is a it's an integrated it's scalable\u00a0it's flexible and it's a self-service tool<br \/>\nit's easy to set up maintain and\u00a0and it requires little intervention from\u00a0an admin and in order to perform those\u00a0tasks that that you need for your project.<br \/>\nI'm gonna look at GitLab as\u00a0GitLab is made up of two main parts:\u00a0the GitLab CI YAML file which\u00a0consider to be the brains<\/p>\n<p dir=\"ltr\">and the\u00a0GitLab runner which is the body.<br \/>\nwhat I'm gonna do is start with the GitLab CI\u00a0YAML file this is the pipeline definition\u00a0file which specifies the stages jobs and<br \/>\nactions that we want to perform.<\/p>\n<h4 dir=\"ltr\">gitlab-ci.yml<\/h4>\n<p dir=\"ltr\">As you can see this file is checked into our\u00a0repository which provides a number of\u00a0benefits: the file is versioned which means<br \/>\npipeline changes can be tested in\u00a0branches supporting any changes into\u00a0your app code similarly if you need to\u00a0go back to an old version of the the\u00a0associate pipeline will be exactly how\u00a0you left it for that particular release,<br \/>\nand because it's under version control\u00a0it's easy to diff the file between\u00a0versions for easy troubleshooting.<\/p>\n<p dir=\"ltr\">It also means that there are a large number\u00a0of ways to work with this file so nearly\u00a0all IDEs have direct integration with Git.<br \/>\nIf not GitLab so you can use your favorite editor.<br \/>\nClassic command line of course\u00a0is always possible as well as our<br \/>\nintegrated GitLab built-in web-based editor\u00a0that you can see here.<\/p>\n<p dir=\"ltr\">Let's take a closer look at this\u00a0file and we can see and see how we could<br \/>\ndefine the pipeline and integrate that<br \/>\nwith a wide variety of tools.<\/p>\n<p dir=\"ltr\">So at the top\u00a0of file we have\u00a0a few defined global defaults:<br \/>\na Docker image to run our command<br \/>\nthen in this case the official <em><strong>Maven<\/strong> <\/em>image.<br \/>\nNow this pipeline file: you'll see that I'll<br \/>\nprobably use a lot of containers and<br \/>\nthis doesn't mean that GitLab CI is\u00a0restricted to just using containerization.<br \/>\nWe'll talk a little bit\u00a0more about the GitLab runner.<\/p>\n<h4 dir=\"ltr\">GitLab Runner<\/h4>\n<p dir=\"ltr\">The runner can be installed on\u00a0a bare-metal machine or a virtual machine (VM).<br \/>\nJust think that a containerization makes things a lot\u00a0easier for folk in many cases.<br \/>\nYou can see that we have a few environment variables,\u00a0we have some cache settings<br \/>\nwith a lot of folders to be persisted\u00a0between jobs to increase our performance<br \/>\nand next what we're gonna start doing is\u00a0defining our stages and jobs and GitLab CI.<br \/>\nA pipeline is made up of a series of stages.<br \/>\nEach stage then contains one or\u00a0more jobs, so there are no limitations on<br \/>\nhow many jobs the single stage can have,<br \/>\nand so we see with that that<br \/>\nthe stages keyword is going to define<br \/>\nthe order the stages should execute<br \/>\nregardless of the order that you defined on the individual jobs.<br \/>\nSo in this case our flow is going to be<br \/>\nbuild, test, generate docs, deploy and trigger.<br \/>\nWhen we start to define our jobs<br \/>\nor the actions that we\u00a0want to perform, our first job is to\u00a0build our library which we utilize Maven for.<br \/>\nYou can see here we simply invoke\u00a0Maven as we would as if we were running<br \/>\nin our own machine.<br \/>\nThat is because the script you see here is actually\u00a0just a bash script.<br \/>\nThis provides a great amount of flexibility because you can<br \/>\nnow automate anything you normally would\u00a0do on your machine.<br \/>\nAfter we build our library we're now going<br \/>\nto test it so our test stage includes &#8230;<br \/>\nThis is just a demo so you<br \/>\nmay have more complex or more have more<br \/>\ncomplexity to the different stages and<br \/>\nmore jobs that you have within these, but<br \/>\nbut for demo purposes it's a<br \/>\ncouple of simple steps, so test stage<br \/>\nincludes two jobs, unit test and static<br \/>\nanalysis with Code Climate, and we're<br \/>\ngoing to leverage Maven again to run our<br \/>\nfirst test but will also include JaCoCo<br \/>\nto generate code coverage reports.<br \/>\nWe then are going to output\u00a0the coverage percentage into the\u00a0build log, and the last step in this job<br \/>\nthat takes our code coverage reports\u00a0and persists them with GitLab's<br \/>\nintegrated artifact repository,\u00a0so the result can be used by other jobs<br \/>\nor downloaded through the browser directly<br \/>\nHow we do this? By simply just\u00a0specifying the folders that we want to save.<br \/>\nWhile this is happening, we will also be running a static\u00a0analysis with Code Climate.<br \/>\nHere we override the default image to utilize<br \/>\nthe official Docker image,<br \/>\nand so we use that then to run Docker in Docker<br \/>\nto execute the Code Climate image<br \/>\nto analyze our source.<br \/>\nOnce that is done we retrieve<br \/>\nour JSON and persist it as an artifact.<br \/>\nThe doc stage is just simply generating<br \/>\nour Java Docs, again retaining them<br \/>\nas an artifact .<\/p>\n<h4 dir=\"ltr\">Release<\/h4>\n<p dir=\"ltr\">So now that we've tests of our library we are able to release it.<br \/>\nWe are going to use Maven again to publish our<br \/>\nlibrary out to the package cloud server.<br \/>\nNow if you're paying close attention\u00a0(hopefully you are), you'll see that we are<br \/>\nusing a variable we did not define above.<br \/>\nThat is because this is a credential\u00a0token which should not be checked into<br \/>\nthe repository. Instead we add this as\u00a0a protected variable in our project's<br \/>\nsettings which\u00a0only administrators can view.<br \/>\nSo as an admin I can go over to\u00a0Settings &gt; CI\/CD<br \/>\nI'll just go to variables, and we can see<br \/>\nthat we have that PACKAGECLOUD_TOKEN here.<br \/>\nIt's a hidden by default,\u00a0and if I want to reveal that, I could reveal that.<br \/>\nIf I want to, they can\u00a0protect it I could do so\u00a0If I want to choose a specific environment I can do<br \/>\nthat here.<br \/>\nNext, our pages job, and<br \/>\nthis is slightly unique and that this is<br \/>\na special job that works in tandem with<br \/>\nGitLab Pages, which is our static site<br \/>\nhosting feature with pages.<br \/>\nDeploying a static site is really as<br \/>\neasy as create an artifact.<br \/>\nWe do that here by specifying that<br \/>\nwe will utilize artifacts<br \/>\nof our two jobs, unit tests and javadocs<br \/>\nThis job then copies those into a single<br \/>\ndirectory structure and it persists it<br \/>\nas an artifact, so GitLab Pages will<br \/>\nthen take this and deploy out to the<br \/>\nintegrated hosting service providing<br \/>\na very easy and automated way of<br \/>\nposting in our case our code coverage and documentation.<br \/>\nSee that here.<br \/>\nNo the prettiest UI but it's still doing what we need it to do.<br \/>\nYou can see the coverage,<br \/>\nyou can see that being done here.<br \/>\nFinally we have our last stage, trigger.<br \/>\nFor this last job our Java app is made<br \/>\nup of two components. This is a library<br \/>\nand a front-end service, which used it,<br \/>\nwhich is another project, and at this<br \/>\npoint what we've done is we've confirmed<br \/>\nso actually at the trigger stage, at the<br \/>\nat the trigger point we've confirmed<br \/>\nthat all of our tests pass prior to this,<br \/>\nwhich is a great start, but now what about<br \/>\ndownstream projects that are utilizing this?<br \/>\nAnd this job kicks that off to what<br \/>\nwe refer to as a cross project pipeline,<br \/>\nand so we take a stock Alpine image.<br \/>\nIt's all curled and used to trigger<br \/>\nthe API web hook to start a new front-end<br \/>\nservice pipeline in the other project,<br \/>\nconfirming that downstream<br \/>\nprojects are not negatively affected by<br \/>\nupstream changes, and it's just pretty<br \/>\nsimple, it's very just easy as a few lines of YAML.<br \/>\nI'm gonna do that.<br \/>\nI know, it like we have a certain amount of time here<br \/>\nand I'm running through this<br \/>\nstuff and obviously always after<br \/>\nwebinar is done I'm one happy to follow-up<br \/>\nbut just base I'm keeping that just want<br \/>\nto make sure we get all the information<br \/>\nout to you as much as possible about CI\/CD and in the 50 minutes we have allotted.<br \/>\nSo as you can see,<br \/>\nthis supports our larger goals<br \/>\nof GitLab, so it's supporting the<br \/>\nscalability, it's supporting flexibility,<br \/>\nit's supporting self-service,<br \/>\nand so a developer, they can integrate with<br \/>\nany tool that they need.<br \/>\nJust a couple examples that we have just the YAML file<br \/>\nwithout having to worry about installing<br \/>\nplugins or involving administrators.<br \/>\nIn most cases they can simply provide the<br \/>\nrequired container or VM to run<br \/>\nthe script in or install their own runner<br \/>\non a bare metal machine. I would associated<br \/>\nrequirements, integrating with static<br \/>\nanalysis and unit test<br \/>\nframeworks is just a few lines of code.<br \/>\nWe also have a collection of templates<br \/>\nwhich can be used to help users get<br \/>\nstarted, and I will show you that over in<br \/>\nthe repository, so if I were going to<br \/>\ncreate a new file. As soon as I just get<br \/>\nthe .gitlab-ci.yml, which is\u00a0already pre-populated here, you'll see<br \/>\nthat I have some templates that pop up here<br \/>\nand give me a drop-down menu, and<br \/>\nthis makes things easier and faster just<br \/>\nas a jumping-off point for a lot of users.<br \/>\nTemplates are in almost most<br \/>\nlanguages, and I could choose whatever<br \/>\nI'd like. I'll just may be working on some<br \/>\nmobile app, specifically focus on Android.<br \/>\nOnce I clicked on that it's<br \/>\ngoing to give me some variables and some<br \/>\nbasic tests that we can run off the bat,<br \/>\nand you could customize this,<br \/>\nadd to it, take away from it as much as you'd like.<br \/>\nNow what I want to do is I want to take a<br \/>\nlook at a previously random pipeline for<br \/>\nthe YAML file that we just walked through,<br \/>\nso we'll dive in here, and\u00a0this is a graphical view of our pipeline<br \/>\nI'm going to jump into the unit test and<br \/>\nlook at the build log as it was executed by a runner.<br \/>\nWe could see here how Maven is executing<br \/>\nand finally how our tests have passed,<br \/>\nso the artifact from that is<br \/>\ndisplayed in an output of the test itself,<br \/>\nand we have a way to both download and<br \/>\nbrowse our job artifacts.<\/p>\n<p dir=\"ltr\">Over here is our code coverage, we will be able<br \/>\nto download and browse those job artifacts<br \/>\nand additionally these could<br \/>\nbe accessed in the future by<br \/>\nother jobs as we've seen through our<br \/>\npages functionality.<br \/>\nAll that right there easily accessible let's go over to<br \/>\nactually there's just it.<br \/>\nI wonder&#8230; I was on the wrong one&#8230;<br \/>\nPardon, got those mixed up. This was&#8230;<br \/>\nThat was a Code Climate I was looking at,<br \/>\nI just scrolled him too fast there&#8230;<br \/>\nIn the Code Climate&#8230;<br \/>\ndone this too much that I was looking at it<br \/>\nIn our code climate image&#8230; we can see&#8230; didn't always go in there&#8230;<br \/>\nSo in our<br \/>\nCode Climate&#8230; we could see that &#8230;<br \/>\nThe Code Climate image was executed within<br \/>\nin the dark lines, so we<br \/>\ncollected the output from that job<br \/>\nand again that's persists as an artifact,<br \/>\nwhich is also available as downloading and<br \/>\nbrowsing here on the side,<br \/>\non the right side. But what I want to do is hop<br \/>\ninto our deploy stage and then hop into<br \/>\nour deploy job,<br \/>\nand now be able to see<br \/>\nthat we were able to<br \/>\npublish our library to our package cloud<br \/>\nserver usually utilizing Maven.<br \/>\nSo if you remember earlier that we utilize a\u00a0<em>protected variable<\/em><br \/>\nand with that protected variable this was to ensure<br \/>\nthat the secure token was not committed<br \/>\nto the repository and we could see right<br \/>\nhere I'm where I highlighted one that<br \/>\nthat's referencing variable without<br \/>\nactually displaying token<br \/>\nin the log itself. So now our<br \/>\nlibrary is available for others to consume.<br \/>\nI jump into the pages job.<br \/>\nIt's just running these bash commands putting<br \/>\nthe files that we want to save<br \/>\nin a unified folder again and<br \/>\npersisting those artifacts. That is is<br \/>\nour pages functionality, and then it<br \/>\ndisplays those as that aesthetic website<br \/>\nthat I just showed earlier right here.<br \/>\nSo this is what this pages job is doing,<br \/>\ngiving us this information about code<br \/>\nquality or docs of our code coverage.<br \/>\nSomething to know about GitLab is,<br \/>\nthat GitLab provides a number of ways<br \/>\nfor notifications, to know either it's<br \/>\nsuccessful or unsuccessful run.<br \/>\nYou can get it in browser notifications,<br \/>\nif you have Mattermost or Slack (note Slack setup),<br \/>\nyou can integrate that with GitLab<br \/>\nand get notifications via those two<br \/>\nor you can receive email notifications<br \/>\non passed or failed pipelines, probably<br \/>\nfailed pipelines more often than not.<br \/>\nI'm top right here, you can see the favicon<br \/>\nshowing that it has passed.<br \/>\nIf it has failed you'd have a red X showing as well.<br \/>\nGoing back to our pipeline view.<br \/>\nWe see now how our cross-project pipeline<br \/>\nworked for our our front-end service.<br \/>\nSo we see all these green checkmarks,<br \/>\nwhich great and then our trigger<br \/>\nwhich fires off our downstream<br \/>\npipeline, and then what we're able to do<br \/>\nis if I go over here to this other<br \/>\nproject, demo-app, I can go on to that<br \/>\npipeline, which I did here.<br \/>\nSee that this pipeline was triggered from our upstream<br \/>\nproject and that our build, test, package,<br \/>\ndeploy and run stages all completed<br \/>\nsuccessfully, showing that our upstream<br \/>\nchanges didn't affect our downstream<br \/>\nproduct maliciously.<br \/>\nObviously, this kind of cross project pipeline<br \/>\ntrigger is great if you're having a<br \/>\nmicro service project that has multiple<br \/>\nprojects that makes up a a larger<br \/>\nproject itself.<br \/>\nAdditionally GitLab has a built-in<br \/>\ncontainer registry so if you have any<br \/>\ncustom images that you want to<br \/>\nstore in GitLab either for better<br \/>\nperformance or you just don't want them<br \/>\ndisplay it on Docker Hub, you can store<br \/>\nthose all within GitLab.<br \/>\nWe do have one container here and<br \/>\nI could want to click into it.<br \/>\nI can either manually prune these if I want,<br \/>\nand of course like GitLab does everywhere,<br \/>\nthere is instructions on using our<br \/>\nbuilt-in container registry on here as well.<br \/>\nSo that's a\u00a0CI pipeline and with a few lines of YAML, we've basically have accomplished<br \/>\nan integration with Maven<br \/>\nwith our units test, our code coverage and<br \/>\nCode Climate; we generate some<br \/>\ndocumentation, we published our library<br \/>\nto package cloud, we generated some so we<br \/>\nwill publish the latest<br \/>\ndocumentation to our pages website,<br \/>\ntrigger downstream project pipeline.<br \/>\nThat's to ensure that there are no negative<br \/>\nimpacts, and we can do all of that<br \/>\nwithout involving a single administrator<br \/>\nopening up a ticket, and this was<br \/>\ncompletely self-service by me<br \/>\nthe developer, with no plugins needed.<br \/>\nNow at the beginning of this demo I<br \/>\nmentioned that there are two parts to<br \/>\nGitLab CI\/CD, and and we've spent a lot<br \/>\nof this time here looking at the CI YAML file.<br \/>\nAnd so take a quick look<br \/>\nover at the GitLab runner, and we'll<br \/>\ntalk about a few minutes basically<br \/>\nabout how this is important part<br \/>\nof GitLab CI\/CD.<br \/>\nGitLab runner is a small portable app, you know, which<br \/>\nwe build for a wide variety of platforms.<br \/>\nIt's essentially the worker bee,<br \/>\nit picks up and executes the jobs<br \/>\nthat we specified in our pipelines.<br \/>\nIn our CI\/CD settings here this is where a<br \/>\ndeveloper can take a look at the<br \/>\nrunner configuration for their<br \/>\nprojects, so you'll see that we have, as we<br \/>\ntalked about earlier, two categories of runners, shared and specific.<br \/>\nShared runners are runners<br \/>\nthat have been provided by<br \/>\nadministration of the GitLab instance,<br \/>\nso we've been using several or one here.<br \/>\nA couple different shared runners as you<br \/>\ncan see, and what this does is by<br \/>\nallowing administrators to provide a<br \/>\nshared pool. There are a number of<br \/>\nbenefits, and those could be consolidation<br \/>\nof infrastructure, whether it's cloud or on-premise.<br \/>\nClusters and credentials can be centrally managed,<br \/>\nit can reduce efforts required to set up CI<br \/>\nfor each team, but there are some cases<br \/>\nwhere an administrator has maybe not<br \/>\nprovided a shared pool or they don't<br \/>\nmeet your needs and for these cases we<br \/>\nhave the ability for for any dev team to<br \/>\nconnect their own runners. They simply<br \/>\ndownload the runner, enter the URL and key<br \/>\nand you're just on your way.<br \/>\nAnd I mean to show how simple that is.<br \/>\nI'll just show the process real quick here<br \/>\nbut in the interest of time I did<br \/>\ninstall the GitLab runner,<br \/>\nso if I were&#8230;. I get this thing wait&#8230;<br \/>\nI'll just get, I've run register, it's<br \/>\ngonna ask for your URL, everything's<br \/>\nprovided here, I can simply copy that and<br \/>\nthen paste it, and then same thing with the token.<br \/>\nNot too much difficulty around that&#8230;<br \/>\nDo a description.<br \/>\nAnd then it's gonna ask you if<br \/>\nthere are any tags that we want to specify.<br \/>\nSo like we talked about, tags allow<br \/>\nyou to uniquely identify runners<br \/>\nwith certain properties. Maybe in this case<br \/>\nyou know, as we're<br \/>\nworking on mobile applications<br \/>\nand I'm working on iOS,<br \/>\nI'm just gonna give it that tag<br \/>\nto identify specifically what I've<br \/>\ninstalled with that tag,<br \/>\nand that could be specified in the .gitlab-ci.yml file<br \/>\nthat we went through for the job<br \/>\nthat we want to run.<br \/>\nLast choice what we<br \/>\nhave is what mode of operation we<br \/>\nwe want for a runner.<br \/>\nSo simple C shell<br \/>\nexecutes the script on the machine in<br \/>\nthe account that is installed on.<br \/>\nWe then have support for working with images and<br \/>\ncontainers via VirtualBox, Parallels,<br \/>\nof course Docker, and Kubernetes.<br \/>\nThe runner will start the specified image,<br \/>\nexecute the job and then clean up.<br \/>\nThese modes are great for shared runners<br \/>\nbecause the development team can bring<br \/>\ntheir own base image to start from.<br \/>\nOur last mode of operation is what we call<br \/>\nour autoscaling runner. We support this<br \/>\non Docker machine and Kubernetes and<br \/>\nand here this is when the runner will<br \/>\nelastically process jobs as needed<br \/>\nto process the CI queue.<br \/>\nI'm just gonna do &quot;shell&quot;<br \/>\nRegistered successfully and<br \/>\nrefresh the page, click on runners, and there we are,<br \/>\nand my runner up and ready to go.<br \/>\nIn that case pretty simple but it'll<br \/>\ntake a little bit of time here&#8230;<br \/>\nWe've got two of them&#8230; Oh, deleted the other one earlier someone else's.<br \/>\nIt's gonna do a couple minutes of back and forth and<br \/>\nthen it's gonna have a green.<br \/>\nI did it in this project and I'll have a green<br \/>\navailable ready to go.<br \/>\nI'm not gonna do any building beyond that,<br \/>\nbut I did want to talk on Canary<br \/>\ndeployments. I don't have it set up for<br \/>\nthis demo but talking about Canary<br \/>\ndeployments, when people are<br \/>\nlooking to embrace continuous delivery,<br \/>\ncompany often needs to decide what type<br \/>\nof deployment strategy to use. One of the<br \/>\nmore popular strategies is Canary<br \/>\ndeployments, where a small portion of the<br \/>\nfleet is updated to the newest version first.<br \/>\nThis subset then can serve<br \/>\nas a proverbial canary in the coal mine,<br \/>\nand if there's a problem with a new<br \/>\nversion of application, only a small<br \/>\npercentage of those users are affected<br \/>\nand the change can either be fixed or<br \/>\nquickly reverted. So if you're leveraging<br \/>\nKubernetes Canary deployments,<br \/>\nyou can visualize your Canary deployments<br \/>\nright inside your deploy board,<br \/>\nand you don't even have to leave GitLab to do that,<br \/>\nand I just want to show this is in a different demo,<br \/>\nbut only showing one here,<br \/>\na nice image to show that, and our<br \/>\nthe deploy board is here and we could see<br \/>\nseveral different instances that<br \/>\nhave been set up, so our Canary deployments<br \/>\ncan be used when you want to<br \/>\nship features to only a portion of your<br \/>\npods fleet and watch the behavior as a<br \/>\npercentage of your user base visits the<br \/>\ntemporary deployed feature.<br \/>\nIf all works well you can deploy the feature to production.<br \/>\nI'm knowing that it won't cause any problems.<br \/>\nCanary deployments,<br \/>\nyou know, a lot of times they're<br \/>\nvery very useful just for like backend refactors<br \/>\nor performance improvements,<br \/>\nmaybe other changes where the user<br \/>\ninterface doesn't change but you want to<br \/>\nmake sure performance stays the same or improves.<br \/>\nSo this is the ability of GitLab CI.<br \/>\nIt's to allow development teams to set up<br \/>\ntheir own CI\/CD infrastructure.<br \/>\nIt's very very transformative.<br \/>\nA couple of points: first is self service<br \/>\ninstead of needing to file a request for<br \/>\na new piece of hardware, the wait for the<br \/>\nresponse, justify the changes cost and<br \/>\nhave a PO potentially filed, dev team<br \/>\ntakes two minutes with an old machine<br \/>\nfrom maybe from the cabinet and they off<br \/>\nthey go. Dev team is happy and more<br \/>\nproductive. Infrastructure team is happy,<br \/>\nthey don't have to worry about managing<br \/>\nmaybe a flock of what Mac minis for iOS<br \/>\nteam in their data center.<br \/>\nSecond, it's going to provide a lot of flexibility.<br \/>\nSo if you need to run jobs<br \/>\nin IRM device perhaps, or Android, or deep<br \/>\nlearning, it's easy.<br \/>\nIt's easy as installing just the runner on Android.<br \/>\nNeed to run something you know like on a<br \/>\nmainframe, like ?, just build<br \/>\nthe runner, the way you go. If we<br \/>\ndon't support any operating systems, the<br \/>\nSSH executors that can login and and run<br \/>\nbash commands, so managing hardware and<br \/>\nsoftware when something like a<br \/>\ncontainer is not possible, it's pretty easy.<br \/>\nScalability: You know, with<br \/>\na handful of auto-scaling runners on gitlab.com,<br \/>\nthey routinely processing over thousand<br \/>\nconcurrently fifteen hundred or more CI<br \/>\njobs, and if more needed just simply turn dial.<br \/>\nSo GitLab CI\/CD and<br \/>\nyou know there's a lot to GitLab, and<br \/>\nI try to shove a lot<br \/>\nof it in the time frame, there's more that.<br \/>\nWe're hoping to keep doing more webinars,<br \/>\nmore technical deep dive and specific webinars or just videos that<br \/>\nwe'll post out to<br \/>\nYouTube, but GitLab CI, it's<br \/>\nvery very flexible.<br \/>\nIf you bash it, now you can<br \/>\nautomate it in the YAML file, you have<br \/>\nyou know self-service runners and no<br \/>\nexternal plugins to manage and maintain.<br \/>\nYou don't have a brittle<br \/>\nconfiguration, and you have SaaS QA LTI<br \/>\nwith auto scaling runners, if you<br \/>\nwant those available to you.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u05d0\u05e0\u05d9 \u05e9\u05de\u05d7 \u05dc\u05e9\u05ea\u05e3 \u05db\u05d0\u05df \u05d1\u05d5\u05d9\u05d3\u05d0\u05d5 \u05e9\u05d4\u05d5\u05d0 \u05d3\u05de\u05d5 \u05d8\u05db\u05e0\u05d9, \u05e2\u05d3\u05db\u05e0\u05d9 \u05d5\u05ea\u05de\u05e6\u05d9\u05ea\u05d9 \u05e2\u05dc GitLab CI\/CD &#8211; \u05d5\u05d9\u05d3\u05d0\u05d5 \u05e9\u05d1\u05d7\u05e8\u05ea\u05d9 \u05db\u05d8\u05d5\u05d1 \u05d1\u05d9\u05d5\u05ea\u05e8 \u05de\u05d1\u05d9\u05df \u05db\u05de\u05d4 \u05e1\u05e8\u05d8\u05d5\u05e0\u05d9\u05dd \u05e9\u05e6\u05e4\u05d9\u05ea\u05d9 \u05d1\u05d4\u05dd \u05dc\u05d0\u05d7\u05e8\u05d5\u05e0\u05d4. \u05dc\u05e0\u05d5\u05d7\u05d9\u05d5\u05ea\u05db\u05dd \u05d4\u05d5\u05e1\u05e4\u05e0\u05d5 \u05db\u05ea\u05d5\u05d1\u05d9\u05d5\u05ea , \u05e1\u05d9\u05db\u05d5\u05dd \u05e9\u05dc \u05d4\u05d5\u05d9\u05d3\u05d0\u05d5 \u05d5\u05d8\u05e7\u05e1\u05d8 \u05de\u05dc\u05d0 (transcription) \u05e9\u05dc \u05d4\u05d5\u05d9\u05d3\u05d0\u05d5. \u05d0\u05ea \u05d4\u05d5\u05d9\u05d3\u05d0\u05d5 \u05d4\u05de\u05dc\u05d0 \u05d5\u05d0\u05ea \u05d4\u05e1\u05d9\u05db\u05d5\u05dd \u05e0\u05d9\u05ea\u05df \u05dc\u05e7\u05d1\u05dc \u05de\u05d9\u05d9\u05d3\u05d9\u05ea \u05d1\u05d4\u05e9\u05d0\u05e8\u05ea \u05e4\u05e8\u05d8\u05d9\u05dd \u05db\u05d0\u05df \u05d1\u05d4\u05de\u05e9\u05da. \u05de\u05d4 \u05e0\u05d9\u05ea\u05df \u05dc\u05dc\u05de\u05d5\u05d3 \u05de\u05e6\u05e4\u05d9\u05d4 \u05d1\u05d5\u05d9\u05d3\u05d0\u05d5 ? \u05db\u05d9\u05e6\u05d3 [&hellip;]<\/p>\n","protected":false},"author":5,"featured_media":4710,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[60,111,112,179,62],"tags":[373,375,340,372,374],"class_list":["post-4682","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops","category-gitlab","category-gitlab-ci","category-179","category-62","tag-ci-pipelines","tag-code-climate","tag-demo","tag-gitlab-ci-cd","tag-java"],"_links":{"self":[{"href":"https:\/\/www.almtoolbox.com\/blog_he\/wp-json\/wp\/v2\/posts\/4682","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.almtoolbox.com\/blog_he\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.almtoolbox.com\/blog_he\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.almtoolbox.com\/blog_he\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/www.almtoolbox.com\/blog_he\/wp-json\/wp\/v2\/comments?post=4682"}],"version-history":[{"count":0,"href":"https:\/\/www.almtoolbox.com\/blog_he\/wp-json\/wp\/v2\/posts\/4682\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.almtoolbox.com\/blog_he\/wp-json\/wp\/v2\/media\/4710"}],"wp:attachment":[{"href":"https:\/\/www.almtoolbox.com\/blog_he\/wp-json\/wp\/v2\/media?parent=4682"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.almtoolbox.com\/blog_he\/wp-json\/wp\/v2\/categories?post=4682"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.almtoolbox.com\/blog_he\/wp-json\/wp\/v2\/tags?post=4682"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}