<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>CI &#8211; Best DevOps</title>
	<atom:link href="https://www.bestdevops.com/tag/ci/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.bestdevops.com</link>
	<description>Lets Learn, Do it &#38; Share! Thats a Best DevOps!!!</description>
	<lastBuildDate>Mon, 12 Oct 2026 20:42:51 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.3</generator>
	<item>
		<title>Harness Revamps User Interface for CI Platform</title>
		<link>https://www.bestdevops.com/harness-revamps-user-interface-for-ci-platform/</link>
					<comments>https://www.bestdevops.com/harness-revamps-user-interface-for-ci-platform/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Sat, 20 Mar 2021 05:46:42 +0000</pubDate>
				<category><![CDATA[Continuous Deployment]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[GitOps]]></category>
		<category><![CDATA[Harness]]></category>
		<category><![CDATA[interface]]></category>
		<category><![CDATA[platform]]></category>
		<category><![CDATA[Revamps]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=16017</guid>

					<description><![CDATA[Source:-https://devops.com/ Harness today announced it has updated the community edition of its continuous integration (CI) platform with, among other updates, [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Source:-https://devops.com/</p>
<p>Harness today announced it has updated the community edition of its continuous integration (CI) platform with, among other updates, a revamped user interface.</p>
<p>Formerly known as Drone.io, the latest release also adds pipeline execution visualizations, governance and security controls and live CI pipeline debugging capabilities. Harness last year acquired Drone.io, an open source CI project, to extend its existing continuous delivery (CD) platform into the realm of CI. Harness claims there are now more than 50,000 active monthly users of the community edition of Harness CI.</p>
<p>The update to the community edition of Harness CI comes at a time when the debate over how tightly integrated CI and CD platforms need to be is heating up. Harness launched a namesake CD platform before it acquired Drone.io to add a CI capability. While most DevOps teams are proficient with CI, the CD side of the DevOps equation has proven more elusive. There are now GitOps advocates that contend the rise of Kubernetes makes it more advantageous to enable a separate CD platform to pull updates from a Git repository, rather than having them pushed out by a CI/CD platform. The challenge with CD has always been that each platform on which code is deployed is unique. Kubernetes, however, now provides a de facto standard layer of abstraction that runs atop multiple platforms.</p>
<p>Rydzewski said the integrated CI/CD approach will ultimately prevail, because it enables DevOps teams to more easily integrate a range of processes, including testing, that are required to consistently build and deploy applications at scale. Harness is, essentially, making a case for solving the CD challenge using a platform that encourages – but doesn’t require – a DevOps team to replace their existing CI platform.</p>
<p>Regardless of how DevOps evolves, the CD issue needs to be addressed. As the enterprise becomes more extended with the rise of both cloud and edge computing, the number of platforms a DevOps team needs to support continuously expands.</p>
<p>Despite the fact that DevOps teams employ CI/CD platforms, it is clear most of those organizations are not overly committed to the way they currently manage CD. It may be years before most organizations finally implement a consistent set of processes for automating application deployment.</p>
<p>In the meantime, the number of organizations just starting out on their DevOps journey continues to increase. There are still plenty of instances where organizations have yet to deploy any type of CI/CD platform. It’s also worth noting that, in many cases, different DevOps teams within the same enterprise have decided to deploy different CI/CD platforms.</p>
<p>Regardless of how DevOps evolves the pressure to automate is rising. The challenge many DevOps teams face today is the current platform they are relying on to automate the building and deployment of applications requires a small army of specialists relying on all too often manual processes to maintain.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/harness-revamps-user-interface-for-ci-platform/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Securing the CI/CD pipelines with DevSecOps</title>
		<link>https://www.bestdevops.com/securing-the-ci-cd-pipelines-with-devsecops-2/</link>
					<comments>https://www.bestdevops.com/securing-the-ci-cd-pipelines-with-devsecops-2/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Thu, 03 Dec 2020 05:29:33 +0000</pubDate>
				<category><![CDATA[Continuous Delivery]]></category>
		<category><![CDATA[CD]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[DevSecOps]]></category>
		<category><![CDATA[Pipelines]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=14787</guid>

					<description><![CDATA[Source:-https://www.devopsonline.co.uk Continuous Integration and Continuous Delivery (CI/CD) can bring a seamless integration from end-to-end for the software development and deployment [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Source:-<strong>https://www.devopsonline.co.uk</strong></p>
<p>Continuous Integration and Continuous Delivery (CI/CD) can bring a seamless integration from end-to-end for the software development and deployment process. By doing this, CI/CD allows developers to dedicate more of their time developing code to improve software features instead of worrying about the deployment.</p>
<p>Yet, they are still faced with many security challenges. CI/CD might speed up the process but not the security. With DevSecOps – Development, Security, and Operations -, however, there is a possibility to accelerate the delivery of security within the software. DevSecOps engineers try to operate most security controls as part of the software by introducing it as a design constraint and then getting it checked by the CI/CD pipelines without damaging the integrity of controls.</p>
<p><strong>Why DevSecOps?</strong></p>
<p>As digital transformations increase, there is a vital need for safe and secure software, otherwise, everything, from the building to the delivery can be at risk. Security breaches are now one of the biggest threats to companies and products.</p>
<p>DevSecOps promotes collaboration between the development and security teams, hence, avoiding late handoffs to security professionals. By introducing security at the beginning of the process, the value and quality of the product can only be reinforced. Indeed, without DevSecOps, the software might be considered unsafe at the last minute, thus causing multiple costly iterations. With DevSecOps, security standards are implemented directly into the pipelines making the products more secure from the beginning.</p>
<p>Overall, DevSecOps ensures credibility and agility in the market, as well as trust with consumers.</p>
<p><strong>DevSecOps in CI/CD</strong></p>
<p>There are many security vulnerabilities that can exist in open-source software. Hence, implementing DevSecOps practices within CI/CD will bring continuity to securing software deliveries.</p>
<p>Integrating automated security checks within the pipeline will allow developers to have early warnings of vulnerabilities and monitor any security defects or else. With an integrated continuous security approach, companies can expand while upgrading their security and development process as it goes.</p>
<p>Moreover, unit tests and static code analysis operate close to source code as well as run checks without executing the code. Hence, investing in security unit tests and static analyzers will only be beneficial as it can speed up the lifecycle while detecting quickly any vulnerabilities.</p>
<p><strong>The future of DevSecOps and CI/CD pipelines</strong></p>
<p>With the many challenges our world bring today, security is crucial in order to remain on top of the market. With DevSecOps, companies are able to speed up their CI/CD pipelines all the while keeping it secure from any vulnerabilities. Collaboration and communication are then vital between development and security teams and shouldn’t be overlooked.</p>
<p>With the rise of DevSecOps, security has become an important part of the continuous delivery pipeline. Having continuity and security ensures the best software delivery.</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/securing-the-ci-cd-pipelines-with-devsecops-2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Securing the CI/CD pipelines with DevSecOps</title>
		<link>https://www.bestdevops.com/securing-the-ci-cd-pipelines-with-devsecops/</link>
					<comments>https://www.bestdevops.com/securing-the-ci-cd-pipelines-with-devsecops/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Wed, 02 Dec 2020 06:07:12 +0000</pubDate>
				<category><![CDATA[Continuous Deployment]]></category>
		<category><![CDATA[CD]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[Delivery]]></category>
		<category><![CDATA[DevSecOps]]></category>
		<category><![CDATA[Integration]]></category>
		<category><![CDATA[Pipelines]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=14744</guid>

					<description><![CDATA[Source:-https://www.devopsonline.co.uk Continuous Integration and Continuous Delivery (CI/CD) can bring a seamless integration from end-to-end for the software development and deployment [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Source:-https://www.devopsonline.co.uk</p>
<p>Continuous Integration and Continuous Delivery (CI/CD) can bring a seamless integration from end-to-end for the software development and deployment process. By doing this, CI/CD allows developers to dedicate more of their time developing code to improve software features instead of worrying about the deployment.</p>
<p>Yet, they are still faced with many security challenges. CI/CD might speed up the process but not the security. With DevSecOps – Development, Security, and Operations -, however, there is a possibility to accelerate the delivery of security within the software. DevSecOps engineers try to operate most security controls as part of the software by introducing it as a design constraint and then getting it checked by the CI/CD pipelines without damaging the integrity of controls.</p>
<p><strong>Why DevSecOps?</strong></p>
<p>As digital transformations increase, there is a vital need for safe and secure software, otherwise, everything, from the building to the delivery can be at risk. Security breaches are now one of the biggest threats to companies and products.</p>
<p>DevSecOps promotes collaboration between the development and security teams, hence, avoiding late handoffs to security professionals. By introducing security at the beginning of the process, the value and quality of the product can only be reinforced. Indeed, without DevSecOps, the software might be considered unsafe at the last minute, thus causing multiple costly iterations. With DevSecOps, security standards are implemented directly into the pipelines making the products more secure from the beginning.</p>
<p>Overall, DevSecOps ensures credibility and agility in the market, as well as trust with consumers.</p>
<p><strong>DevSecOps in CI/CD</strong></p>
<p>There are many security vulnerabilities that can exist in open-source software. Hence, implementing DevSecOps practices within CI/CD will bring continuity to securing software deliveries.</p>
<p>Integrating automated security checks within the pipeline will allow developers to have early warnings of vulnerabilities and monitor any security defects or else. With an integrated continuous security approach, companies can expand while upgrading their security and development process as it goes.</p>
<p>Moreover, unit tests and static code analysis operate close to source code as well as run checks without executing the code. Hence, investing in security unit tests and static analyzers will only be beneficial as it can speed up the lifecycle while detecting quickly any vulnerabilities.</p>
<p><strong>The future of DevSecOps and CI/CD pipelines</strong></p>
<p>With the many challenges our world bring today, security is crucial in order to remain on top of the market. With DevSecOps, companies are able to speed up their CI/CD pipelines all the while keeping it secure from any vulnerabilities. Collaboration and communication are then vital between development and security teams and shouldn’t be overlooked.</p>
<p>With the rise of DevSecOps, security has become an important part of the continuous delivery pipeline. Having continuity and security ensures the best software delivery.</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/securing-the-ci-cd-pipelines-with-devsecops/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Continuous Integration Tools (CI) Market Is Booming Worldwide (2020-2027) &#124; By Top Leading Players – Atlassian, AWS, Cloudbees, IBM Corporation, Jetbrains</title>
		<link>https://www.bestdevops.com/continuous-integration-tools-ci-market-is-booming-worldwide-2020-2027-by-top-leading-players-atlassian-aws-cloudbees-ibm-corporation-jetbrains/</link>
					<comments>https://www.bestdevops.com/continuous-integration-tools-ci-market-is-booming-worldwide-2020-2027-by-top-leading-players-atlassian-aws-cloudbees-ibm-corporation-jetbrains/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Thu, 12 Nov 2020 05:54:07 +0000</pubDate>
				<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[Automotive]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[CloudBees]]></category>
		<category><![CDATA[Jetbrains]]></category>
		<category><![CDATA[Manufacturing]]></category>
		<category><![CDATA[Worldwide]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=14411</guid>

					<description><![CDATA[Source:-https://prnewsleader.com The Global Continuous Integration Tools (CI) Market is anticipated to rise at a considerable rate over the estimated period [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Source:-https://prnewsleader.com</p>
<p>The Global Continuous Integration Tools (CI) Market is anticipated to rise at a considerable rate over the estimated period between 2020 and 2027. The Global Continuous Integration Tools (CI) Market Industry Research Report is an exhaustive study and a detailed examination of the recent scenario of the Global Continuous Integration Tools (CI) industry.</p>
<p>Continuous integration is a software development practice in which developers regularly unite their codes changed into a central fount, automated builds and tests are being processed. The main objective of continuous integration (CI) is to discover quick address bugs.</p>
<p>Growing demand for continuous integration (CI) tools in all industry verticals, high demand of automation in the development process of software, and rising productivity with the help of continuous integration (CI) tools are the factors driving the growth of the continuous integration (CI) tools market. Traditional integration methods and customers attraction towards the software updates are the factors restraining the growth of continuous integration (CI) tools market.</p>
<p>Major Key Players Covered In This Report: Atlassian, AWS, Cloudbees, IBM Corporation, Jetbrains, Micro Focus, Microsoft Corporation, Oracle, Puppet, Red Hat</p>
<p>The study conducts SWOT analysis to evaluate strengths and weaknesses of the key players in the Continuous Integration Tools (CI) market. Further, the report conducts an intricate examination of drivers and restraints operating in the market. The report also evaluates the trends observed in the parent market, along with the macro-economic indicators, prevailing factors, and market appeal with regard to different segments. The report predicts the influence of different industry aspects on the Continuous Integration Tools (CI) market segments and regions.</p>
<p>The global Continuous integration tools (CI) market is segmented on the basis of, deployment model, and size. On the basis of deployment model, market is segmented as on premises, on cloud. On the basis of size, market is segmented as SMEs, large enterprise.</p>
<p>The research on the Continuous Integration Tools (CI) market focuses on mining out valuable data on investment pockets, growth opportunities, and major market vendors to help clients understand their competitor’s methodologies. The research also segments the Continuous Integration Tools (CI) market on the basis of end user, product type, application, and demography for the forecast period 2020–2027. Comprehensive analysis of critical aspects such as impacting factors and competitive landscape are showcased with the help of vital resources, such as charts, tables, and infographics.</p>
<p>This report strategically examines the micro-markets and sheds light on the impact of technology upgrades on the performance of the Continuous Integration Tools (CI) market.</p>
<p>Continuous Integration Tools (CI) Market Segmented by Region/Country: North America, Europe, Asia Pacific, Middle East &amp; Africa, and Central &amp; South America</p>
<p>Highlights of the report:</p>
<p>A complete backdrop analysis, which includes an assessment of the parent market<br>
Important changes in market dynamics<br>
Market segmentation up to the second or third level<br>
Historical, current, and projected size of the market from the standpoint of both value and volume<br>
Reporting and evaluation of recent industry developments<br>
Market shares and strategies of key players<br>
Emerging niche segments and regional markets<br>
An objective assessment of the trajectory of the market<br>
Recommendations to companies for strengthening their foothold in the market</p>
<p>The Insight Partners is a one stop industry research provider of actionable intelligence. We help our clients in getting solutions to their research requirements through our syndicated and consulting research services. We are a specialist in Technology, Healthcare, Manufacturing, Automotive and Defence.</p>


<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe  id="_ytid_45405"  width="675" height="379"  data-origwidth="675" data-origheight="379" src="https://www.youtube.com/embed/?enablejsapi=1&#038;list=PLTCuRW0ikUdMFARYSiWm733n1DcCem6bN&#038;autoplay=0&#038;cc_load_policy=0&#038;cc_lang_pref=&#038;iv_load_policy=1&#038;loop=0&#038;rel=1&#038;fs=1&#038;playsinline=0&#038;autohide=2&#038;theme=dark&#038;color=red&#038;controls=1&#038;disablekb=0&#038;" class="__youtube_prefs__  epyt-is-override  no-lazyload" title="YouTube player"  allow="fullscreen; accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen data-no-lazy="1" data-skipgform_ajax_framebjll=""></iframe>
</div></figure>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/continuous-integration-tools-ci-market-is-booming-worldwide-2020-2027-by-top-leading-players-atlassian-aws-cloudbees-ibm-corporation-jetbrains/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AWS DevOps Engineer</title>
		<link>https://www.bestdevops.com/aws-devops-engineer/</link>
					<comments>https://www.bestdevops.com/aws-devops-engineer/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Thu, 15 Oct 2020 05:40:02 +0000</pubDate>
				<category><![CDATA[AWS]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Ansible]]></category>
		<category><![CDATA[Architecture]]></category>
		<category><![CDATA[AWS DevOps Engineer]]></category>
		<category><![CDATA[CD]]></category>
		<category><![CDATA[Chef]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[Programme]]></category>
		<category><![CDATA[Puppet]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=13900</guid>

					<description><![CDATA[source:-https://www.irishjobs.ie Are you an AWS DevOps Engineer who is keen to lead and define the DevOps practices of an organization [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>source:-https://www.irishjobs.ie</p>
<p>Are you an AWS DevOps Engineer who is keen to lead and define the DevOps practices of an organization going through a major transformation? Reporting to the CTO you will have the opportunity to work closely with the architects and delivery team and define how operations work. You will be responsible for delivery DevOps best practice and will help define how the operations will work.</p>
<p><strong>Key Benefits of this role</strong></p>
<p>Opportunity to be a lead in a transformation programme<br>
Very competitive salary and benefits<br>
Challenging role with ability to make a real difference to the delivery process<br>
The Role</p>
<p><strong>You will be required to</strong></p>
<p>1 Provide technical leadership in effectively managing the AWS environment and DevOps toolchain<br>
2 Automate deployment of container applications/services in Kubernetes, system configurations and security settings<br>
3 Provide guidance and support during deployment<br>
4 Create and manage CI/CD pipelines in Jenkins<br>
5 Write and maintain Terraform scripts<br>
6 Build DevOps data flow architecture map<br>
7 Help define development standards, procedures and guidelines to improve the overall&nbsp; development process<br>
<strong>The Person:</strong></p>
<p>1 You will have experience as a technically hands on DevOps Engineer (with leadership experience)<br>
2 Demonstrable experience of driving DevOps best practice and creating and managing CI/CD pipelines and ideally have experience with Jenkins<br>
Experience with Kubernetes<br>
3 Strong experience in AWS administration and development<br>
4 Experience of configuration management tools such as Chef, Puppet, Ansible<br>
5 Excellent communication skills and ability to lead and get buy in for new project roll outs<br>
Strong people management and leadership skills</p>


<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe  id="_ytid_35020"  width="675" height="379"  data-origwidth="675" data-origheight="379" src="https://www.youtube.com/embed/?enablejsapi=1&#038;list=PLTCuRW0ikUdMFARYSiWm733n1DcCem6bN&#038;autoplay=0&#038;cc_load_policy=0&#038;cc_lang_pref=&#038;iv_load_policy=1&#038;loop=0&#038;rel=1&#038;fs=1&#038;playsinline=0&#038;autohide=2&#038;theme=dark&#038;color=red&#038;controls=1&#038;disablekb=0&#038;" class="__youtube_prefs__  epyt-is-override  no-lazyload" title="YouTube player"  allow="fullscreen; accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen data-no-lazy="1" data-skipgform_ajax_framebjll=""></iframe>
</div></figure>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/aws-devops-engineer/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>DevOps World &#124; Jenkins World 2019 Agenda Preview Available for Industry’s Largest DevOps and Jenkins Event</title>
		<link>https://www.bestdevops.com/devops-world-jenkins-world-2019-agenda-preview-available-for-industrys-largest-devops-and-jenkins-event/</link>
					<comments>https://www.bestdevops.com/devops-world-jenkins-world-2019-agenda-preview-available-for-industrys-largest-devops-and-jenkins-event/#respond</comments>
		
		<dc:creator><![CDATA[Roushan Kumar]]></dc:creator>
		<pubDate>Thu, 30 May 2019 05:11:57 +0000</pubDate>
				<category><![CDATA[DevOps]]></category>
		<category><![CDATA[CDF]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[CloudBees]]></category>
		<category><![CDATA[Jenkins]]></category>
		<category><![CDATA[SDM]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=5156</guid>

					<description><![CDATA[Source:- finance.yahoo.com San Francisco conference to offer 135 sessions presented by experts on current digital transformation and software delivery topics [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Source:- finance.yahoo.com</p>
<p class="canvas-atom canvas-text Mb(1.0em) Mb(0)--sm Mt(0.8em)--sm" style="margin: 0px 0px 1em; color: #26282a; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;" data-reactid="12"><i>San Francisco conference to offer 135 sessions presented by experts on current digital transformation and software delivery topics</i></p>
<p class="canvas-atom canvas-text Mb(1.0em) Mb(0)--sm Mt(0.8em)--sm" style="margin: 0px 0px 1em; color: #26282a; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;" data-reactid="13">CloudBees, the lead organizing sponsor, the Jenkins community and the Jenkins X community, announced today availability of the agenda preview for DevOps World | Jenkins World 2019 San Francisco. This year’s theme is “Deliver” and the conference will educate attendees on the value that digital transformation has in delivering software more efficiently, more quickly and with higher quality.</p>
<p class="canvas-atom canvas-text Mb(1.0em) Mb(0)--sm Mt(0.8em)--sm" data-reactid="14">The conference is taking place in two locations this year:</p>
<ul class="canvas-list List(d)" data-type="list" data-reactid="15">
<li data-reactid="16">August 12 &#8211; 15, Moscone West, San Francisco</li>
<li data-reactid="17">December 2 &#8211; 5, Lisbon Congress Center, Lisbon, Portugal<br />
(Agenda preview available in August)</li>
</ul>
<p class="canvas-atom canvas-text Mb(1.0em) Mb(0)--sm Mt(0.8em)--sm" data-reactid="18">The conferences will be the largest gathering of IT executives, DevOps practitioners and Jenkins users in the world, with DevOps and continuous delivery experts presenting sessions. There are many opportunities for attendees to learn, network and explore DevOps and many software delivery topics.</p>
<p class="canvas-atom canvas-text Mb(1.0em) Mb(0)--sm Mt(0.8em)--sm" data-reactid="19">This year’s conference in San Francisco includes a total of 135 sessions covering diverse DevOps, software delivery and Jenkins topics. In San Francisco, sessions will be conducted by practitioners from organizations such as: Adobe, Capital One, CloudBees, CVS, Eli Lilly, Fugue, Google, IBM, Microsoft, SAP Labs and Verizon. Sessions will cover topics ranging from cloud native and Kubernetes, to pipeline development and management, CI/CD topics, release management, data and reporting, DevOps and security/compliance.</p>
<ul class="canvas-list List(d)" data-type="list" data-reactid="20">
<li data-reactid="21"><b>Conference sessions</b><br />
A sampling of sessions from the DevOps World | Jenkins World San Francisco agenda includes:</p>
<ul>
<li class="bwlistitemmargb"><i>From Zero to DevOps Superhero: The Container Edition</i><br />
Jessica Dean, Microsoft</li>
<li class="bwlistitemmargb"><i>Creating a CI/CD Pipeline for Your Shared Libraries</i><br />
Roderick Randolph, Capital One</li>
<li class="bwlistitemmargb"><i>Cloud Native CI/CD with Jenkins X and Tekton</i><br />
James Rawlings, CloudBees</li>
<li class="bwlistitemmargb"><i>Using Chaos Engineering for Resilient Cloud Infrastructure Security</i><br />
Josh Stella, Fugue</li>
<li class="bwlistitemmargb"><i>Jenkins X Optimized for Google Cloud Platform</i><br />
Craig Barber, Google</li>
<li class="bwlistitemmargb"><i>Continuous Delivery Directly to the Car</i><br />
Rafal Kowalski, Grape Up</li>
<li class="bwlistitemmargb"><i>10 Attributes of the DevSecOps Elite</i><br />
Derek Weeks, Sonatype and Hasan Yasar, Carnegie Mellon Software Engineering Institute</li>
<li class="bwlistitemmargb"><i>Can Jenkins be the Engine of Mobile DevOps?</i><br />
Shashikant Jagtop, XCTEQ Limited</li>
</ul>
</li>
</ul>
<p class="canvas-atom canvas-text Mb(1.0em) Mb(0)--sm Mt(0.8em)--sm" data-reactid="22">“DevOps World | Jenkins World provides a broad range of software delivery topics. It is the most comprehensive event for IT practitioners around the globe to learn how to accelerate software delivery and decrease time to value,” said Sacha Labourey, CEO and co-founder, CloudBees.</p>
<p class="canvas-atom canvas-text Mb(1.0em) Mb(0)--sm Mt(0.8em)--sm" style="margin: 0px 0px 1em; color: #26282a; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;" data-reactid="23"><b>US Sponsors</b></p>
<p class="canvas-atom canvas-text Mb(1.0em) Mb(0)--sm Mt(0.8em)--sm" data-reactid="24">Sonatype, Delphix, IBM, KPMG, MacStadium, Sauce Labs, GitHub, Go2Group, Harness, LogDNA, Micro Focus, NowSecure, Perfecto, Plutora, SmartBear, SonarSource, WhiteSource Software, Applitools, CheckMarx, CircleCI, Codefresh, Column Technologies, Compuware, Datical, GitLab, iTMethods, LaunchDarkly, Neotys, Perforce, Synopsys, Sysdig, Twistlock, XebiaLabs, XpandIT (XRAY), GitKraken by Axosoft, Gradle, Honeycomb, IncrediBuild, Instana, OverOps, Scalyr, Grape Up and Verifa.</p>
<p class="canvas-atom canvas-text Mb(1.0em) Mb(0)--sm Mt(0.8em)--sm" style="margin: 0px 0px 1em; color: #26282a; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;" data-reactid="32"><b>About CloudBees</b></p>
<p class="canvas-atom canvas-text Mb(1.0em) Mb(0)--sm Mt(0.8em)--sm" data-reactid="33">CloudBees is powering the continuous economy by offering the world’s first end-to-end continuous software delivery management system (SDM). For millions of developers and product teams driving innovation for businesses large or small, SDM builds on continuous integration (CI) and continuous delivery (CD) to enable all functions and teams within and around the software delivery organization to best work together to amplify value creation.</p>
<p class="canvas-atom canvas-text Mb(1.0em) Mb(0)--sm Mt(0.8em)--sm" style="margin: 0px 0px 1em; color: #26282a; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;" data-reactid="34">CloudBees is the CI, CD and application release orchestration (ARO) powerhouse, built on the commercial success of its products as well as its open source leadership. CloudBees is the largest contributor to Jenkins and Jenkins X, and a founding member of the Continuous Delivery Foundation (CDF). From startups with full-stack developers practicing NoOps to large Fortune 100 companies, CloudBees enables all software-driven organizations to intelligently deploy the right capabilities at the right time.</p>
<p class="canvas-atom canvas-text Mb(1.0em) Mb(0)--sm Mt(0.8em)--sm" data-reactid="35">Over 3,500 of the world’s best-known brands and over 50% of the Fortune 500, invest in CloudBees because of its ability to work across any cloud, in any development environment and to balance corporate governance and control with developer flexibility and freedom. CloudBees is home to the world’s leading DevOps experts, helping thousands of companies harness the power of “continuous everything” and putting them on the fastest path from great idea, to great software, to great business value.</p>
<p class="canvas-atom canvas-text Mb(1.0em) Mb(0)--sm Mt(0.8em)--sm" style="margin: 0px 0px 1em; color: #26282a; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;" data-reactid="36">Backed by Matrix Partners, Lightspeed Venture Partners, Verizon Ventures, Delta-v Capital, Golub Capital and Unusual Ventures, CloudBees was founded in 2010 by former JBoss CTO Sacha Labourey and an elite team of continuous integration, continuous delivery and DevOps professionals.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/devops-world-jenkins-world-2019-agenda-preview-available-for-industrys-largest-devops-and-jenkins-event/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Not Sure How to Start with DevOps? Here&#8217;s a Practical Approach</title>
		<link>https://www.bestdevops.com/not-sure-how-to-start-with-devops-heres-one-option/</link>
					<comments>https://www.bestdevops.com/not-sure-how-to-start-with-devops-heres-one-option/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Fri, 25 May 2018 05:39:07 +0000</pubDate>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Continuous Delivery]]></category>
		<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[CD]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[DevOps transformations]]></category>
		<category><![CDATA[Software Development]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=3782</guid>

					<description><![CDATA[Starting a DevOps transformation is daunting, especially for organizations steeped in legacy culture. Learn how breaking the journey into small, actionable steps — and focusing on cultural change before tooling — can help any team make real progress.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><em>This article is based on a case study originally published by TechTarget, featuring the consulting firm Sodo (Ship On Day One) and their approach to DevOps adoption.</em></p>



<h2 class="wp-block-heading">The Real Problem: Culture, Not Tools</h2>



<p class="wp-block-paragraph">When organizations ask how to start with DevOps, the instinct is often to reach for tools — adopt containers, migrate to the cloud, stand up a CI/CD pipeline. But according to Eric Schoonover and Robert Duffy, co-founders of the consultancy Sodo (Ship On Day One), that instinct misses the deeper issue.</p>



<p class="wp-block-paragraph">Duffy, who brings experience from Amazon and Time magazine, and Schoonover, who has worked at Microsoft, Netflix, and the U.S. Department of Defense&#8217;s Digital Service, argue that the cultural transformation is the hard part — and the part most organizations underestimate.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>&#8220;A lot of companies are still doing engineering delivery like 1800s manufacturing was done. It&#8217;s a craft-based system, parsing work out to different teams. We want to help non-tech companies think about the cultural transformation. It&#8217;s not just about moving to the cloud and installing Docker.&#8221;</p><cite>— Robert Duffy, co-founder, Sodo</cite></blockquote>



<p class="wp-block-paragraph">Notably, Duffy points out that neither he nor Schoonover used the term &#8220;DevOps&#8221; during their time at Amazon and Netflix. The practices were simply how software engineering was done. That framing is useful: DevOps is not a product you install, but a set of behaviors and capabilities that high-performing teams exhibit naturally.</p>



<h2 class="wp-block-heading">Small Plans Work Best: The 15-Capability Framework</h2>



<p class="wp-block-paragraph">To create a repeatable starting point, Duffy and Schoonover interviewed approximately 150 high-performing software development teams, documenting observations and patterns. From that research, they distilled their findings into 15 capabilities, each broken into four stages of maturity.</p>



<p class="wp-block-paragraph">The goal of this structure is deliberate: avoid overwhelming the organization. Instead of presenting a sweeping transformation roadmap, the framework identifies the highest-priority items and sequences them so that early wins build credibility with business stakeholders.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>&#8220;We try to get to a small set of very actionable items that we helped select that justify the ROI calculations and case studies. We help companies recognize the size of the problem and attack it in small identified chunks to gain credibility with the business.&#8221;</p><cite>— Robert Duffy, co-founder, Sodo</cite></blockquote>



<p class="wp-block-paragraph">This approach mirrors advice found throughout DevOps literature: start with a value stream mapping exercise, identify bottlenecks, pick one constraint to improve, and demonstrate measurable progress before expanding scope. The specifics of Sodo&#8217;s 15 capabilities were not publicly detailed in the original source, but the principle — narrow focus, visible momentum — is well-established in DevOps practice.</p>



<h2 class="wp-block-heading">Key Principles for Starting a DevOps Transformation</h2>



<p class="wp-block-paragraph">Whether you engage external consultants or pursue transformation internally, the following principles reflect what high-performing teams consistently do:</p>



<ul class="wp-block-list">
<li><strong>Start with culture, then process, then tools.</strong> Technology is the easiest part to change. Organizational habits and incentive structures are the hard part.</li>
<li><strong>Identify your value stream.</strong> Understand how work flows from idea to production, and where it gets stuck. This surfaces the highest-leverage improvement opportunities.</li>
<li><strong>Pick small, visible wins first.</strong> Early successes build trust with leadership and reduce resistance from skeptical engineers. Don&#8217;t attempt to transform everything at once.</li>
<li><strong>Make CI/CD a baseline expectation.</strong> Continuous integration and continuous delivery pipelines are not optional extras — they are the foundation that enables everything else, including fast feedback and safe deployments.</li>
<li><strong>Treat legacy systems as a continuum.</strong> Not every system is equally amenable to DevOps practices. Some will adopt CI/CD quickly; others, particularly those involving custom hardware or highly regulated environments, require more time and creative approaches. Acknowledge this spectrum explicitly rather than pretending all workloads are equal.</li>
<li><strong>Ship something.</strong> The discipline of getting working software out the door — even incrementally — creates real feedback loops and real learning. &#8220;Something shipped out the door is really what we preach,&#8221; Duffy said.</li>
</ul>



<h2 class="wp-block-heading">DevOps in Non-Traditional Environments: The Legacy and Defense Context</h2>



<p class="wp-block-paragraph">One of the more instructive aspects of the Sodo case study involves a defense contractor — an environment about as far from a Silicon Valley startup as possible. A senior engineering manager at that organization described the challenge plainly: the organization wanted a consistent software delivery process across all systems, but the range of environments was enormous, from straightforward web applications to custom hardware with deeply embedded software.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>&#8220;We want to look at software development as a continuum. But at one spectrum, we have the low-hanging fruit that it&#8217;s easy to see how to make changes to, and on the other spectrum we have custom hardware and software that is not low-hanging fruit. We want to have the same kind of systems in place for both so that we can have CI and CD running. That&#8217;s the area we&#8217;re a little concerned about.&#8221;</p><cite>— Senior engineering manager, defense contractor (anonymous)</cite></blockquote>



<p class="wp-block-paragraph">This is a real and common challenge. Organizations in aerospace, defense, financial services, healthcare, and manufacturing all face legacy systems that resist easy automation. The practical answer is not to exclude those systems from DevOps thinking, but to apply the same principles at whatever pace and with whatever constraints the system imposes — while capturing quick wins on the more flexible parts of the portfolio.</p>



<p class="wp-block-paragraph">The same manager noted that the Sodo team&#8217;s willingness to work alongside engineers — rather than simply diagnosing problems and leaving — was a key factor in acceptance. Engineers, who are often skeptical of outside consultants, responded positively precisely because the consultants did not arrive claiming to have all the answers.</p>



<h2 class="wp-block-heading">The Role of External Help: When Consultants Make Sense</h2>



<p class="wp-block-paragraph">Bringing in external consultants to help start a DevOps transformation is not the only option, but it is a legitimate one — particularly for organizations where internal advocates lack the organizational authority or cross-functional visibility to drive change on their own.</p>



<p class="wp-block-paragraph">The value a good DevOps consultancy brings is not primarily technical knowledge (your engineers likely already know what CI/CD pipelines and infrastructure-as-code are). The value is in:</p>



<ul class="wp-block-list">
<li>Providing an outside perspective that internal politics cannot easily dismiss</li>
<li>Translating engineering improvements into business ROI language that resonates with executives</li>
<li>Offering a structured, repeatable approach that prevents the team from getting lost in tool debates</li>
<li>Creating accountability and momentum through regular check-ins and visible milestones</li>
</ul>



<p class="wp-block-paragraph">The Sodo team explicitly declined to simply deliver projects for clients. Their stated focus was on teaching organizations how to sustain DevOps practices independently — which is the right model. A transformation that depends indefinitely on external consultants is not a transformation.</p>



<h2 class="wp-block-heading">Patience and Momentum Are Both Required</h2>



<p class="wp-block-paragraph">Duffy&#8217;s framing of &#8220;patience is important, but so is momentum&#8221; captures a genuine tension in DevOps transformations. Moving too fast burns out teams and produces fragile systems. Moving too slowly allows organizational inertia to kill the initiative before it gains traction.</p>



<p class="wp-block-paragraph">The practical resolution is to run a short, focused pilot — a single team, a single service, a single pipeline — and make that work well before expanding. Document what changed, measure the outcome, and use that story to justify the next step. This is the pattern that works in organizations of all sizes and industries.</p>



<p class="wp-block-paragraph">DevOps is not a destination you reach; it is a direction you move in. The question of how to start matters less than the decision to start — and the discipline to keep going.</p>



<hr class="wp-block-separator"/>



<p class="wp-block-paragraph"><em>Original reporting by TechTarget. This article summarizes and expands on the source material for a DevOps engineering audience.</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/not-sure-how-to-start-with-devops-heres-one-option/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>3 Git Hooks for Continuous Integration</title>
		<link>https://www.bestdevops.com/3-git-hooks-for-continuous-integration/</link>
					<comments>https://www.bestdevops.com/3-git-hooks-for-continuous-integration/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Mon, 05 Jun 2017 08:12:30 +0000</pubDate>
				<category><![CDATA[DevOps]]></category>
		<category><![CDATA[DevOps Tools]]></category>
		<category><![CDATA[BestDevOps]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[Git Hooks]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=1740</guid>

					<description><![CDATA[Git hooks are Git's built-in plugin system for triggering custom scripts around repository operations. Here are three practical hooks that strengthen your CI workflow: enforcing clean branch builds, protecting code coverage, and surfacing branch build status at checkout.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><em>This article is based on content originally published by Atlassian. Hook scripts referenced were authored by Atlassian developer advocate Tim Petterson and designed for use with Bamboo, Clover, and Bitbucket.</em></p>



<h2 class="wp-block-heading">Understanding Git Hooks</h2>



<p class="wp-block-paragraph">Git hooks are Git&#8217;s native mechanism for triggering custom scripts before or after core repository operations such as commit, merge, push, and checkout. Think of them as Git&#8217;s plugin system — lightweight, portable, and entirely under your control.</p>



<p class="wp-block-paragraph">Every Git repository contains a <code>.git/hooks</code> directory populated with example hook scripts. To activate a hook, rename the relevant example file (removing its <code>.sample</code> extension), make it executable, and add your logic. The Git documentation covers installation in detail.</p>



<figure class="wp-block-image"><img decoding="async" src="https://wac-cdn-a.atlassian.com/dam/jcr:37ce790b-0d4c-42d9-ac7d-057fdcb16082/githooksdirectory.png" alt="The .git/hooks directory showing sample hook scripts" /></figure>



<h3 class="wp-block-heading">Client-Side vs. Server-Side Hooks</h3>



<p class="wp-block-paragraph">Hooks fall into two broad categories:</p>



<ul class="wp-block-list">
<li><strong>Client-side hooks</strong> run on a developer&#8217;s local workstation and affect local operations like committing and checking out branches.</li>
<li><strong>Server-side hooks</strong> run on the remote Git host (e.g., Bitbucket Server, GitLab, or GitHub Enterprise) and can gate pushes and merges centrally across the whole team.</li>
</ul>



<h3 class="wp-block-heading">Pre-Receive vs. Post-Receive Hooks</h3>



<p class="wp-block-paragraph">Hooks are also classified by when they fire relative to the triggering operation:</p>



<ul class="wp-block-list">
<li><strong>Pre-receive (pre-) hooks</strong> run <em>before</em> an operation completes. Crucially, they can exit with a non-zero status to cancel the operation entirely — making them ideal for enforcing quality gates.</li>
<li><strong>Post-receive (post-) hooks</strong> run <em>after</em> an operation has already completed and cannot cancel it. They are well-suited for automation tasks like sending notifications or triggering deployments.</li>
</ul>



<p class="wp-block-paragraph">Common tasks automated with Git hooks include:</p>



<ul class="wp-block-list">
<li>Validating that a commit message references the correct issue tracker key (e.g., a Jira ticket)</li>
<li>Enforcing merge preconditions such as passing tests or minimum code coverage</li>
<li>Posting build or merge notifications to a team chat channel</li>
<li>Configuring the workspace automatically when switching branches</li>
</ul>



<figure class="wp-block-image"><img decoding="async" src="https://wac-cdn-a.atlassian.com/dam/jcr:744af6c8-aecc-4a33-909c-3345b3a9da24/githooksgrid.png" alt="Grid overview of Git hook types and their use cases" /></figure>



<h2 class="wp-block-heading">Hook 1: Enforce Clean Builds Before Merging to Main</h2>



<p class="wp-block-paragraph">Developers are generally diligent, but it is easy to forget to check the CI status on a branch — especially when multiple contributors are pushing changes concurrently. A server-side pre-receive hook closes this gap by making the check automatic and mandatory.</p>



<p class="wp-block-paragraph">The hook inspects incoming push operations targeting the main (or master) branch. When it detects a merge, it queries the CI server for the latest build result on the source branch. If any tests are failing, the hook exits with a non-zero code, rejecting the push and printing a message explaining why.</p>



<p class="wp-block-paragraph">A reference implementation by Atlassian&#8217;s Tim Petterson, designed to work with Bamboo CI, is available on Bitbucket. The script is intentionally straightforward to customise for other CI servers such as Jenkins or CircleCI — the key integration point is an API call to retrieve the latest build status for a given branch and revision.</p>



<h3 class="wp-block-heading">How It Works in Practice</h3>



<ol class="wp-block-list">
<li>A developer runs <code>git push origin feature/my-branch</code> and opens a pull request to merge into main.</li>
<li>On push (or on merge attempt, depending on your server configuration), the pre-receive hook fires.</li>
<li>The hook script calls the CI server&#8217;s API to retrieve the build status for the branch&#8217;s HEAD revision.</li>
<li>If the build is red (failing tests), the push is rejected with a descriptive error message.</li>
<li>If the build is green, the push proceeds normally.</li>
</ol>



<h2 class="wp-block-heading">Hook 2: Protect Hard-Earned Code Coverage</h2>



<p class="wp-block-paragraph">Teams that have invested significant effort in retroactively adding test coverage to a legacy codebase know how painful it is to watch that coverage percentage erode as new features ship without accompanying tests. A pre-receive server-side hook can enforce a coverage floor on the main branch.</p>



<figure class="wp-block-image"><img decoding="async" src="https://wac-cdn-a.atlassian.com/dam/jcr:37798a8d-c9e5-4e26-8f90-90a36eb862cf/githookscodecoverage.png" alt="Terminal output showing a rejected merge due to insufficient code coverage" /></figure>



<p class="wp-block-paragraph">This hook also intercepts incoming merges to main. It then performs two lookups against the CI server:</p>



<ol class="wp-block-list">
<li><strong>Current coverage on main</strong> — the baseline the incoming branch must meet or exceed.</li>
<li><strong>Coverage on the feature branch</strong> — pulled from the build associated with the commit being merged.</li>
</ol>



<p class="wp-block-paragraph">If the branch&#8217;s coverage is lower than main&#8217;s, the merge is rejected.</p>



<h3 class="wp-block-heading">Prerequisites and Configuration</h3>



<p class="wp-block-paragraph">Because most CI servers do not expose code coverage metrics through a standard remote API, the script fetches the coverage report directly as a build artifact. This requires that your build pipeline is configured to publish the coverage report as a shared artifact on every build — for both the main branch and feature branches.</p>



<p class="wp-block-paragraph">The reference implementation targets Bamboo and Clover (Atlassian&#8217;s code coverage tool for Java and Groovy). It can be adapted for other tool combinations — the essential requirement is that your CI server makes coverage report artifacts accessible via a predictable URL or API endpoint.</p>



<p class="wp-block-paragraph"><strong>Important:</strong> This hook does not generate code coverage. It only reads coverage data that your existing build process already produces. If your builds do not measure coverage today, you will need to add that to your pipeline first.</p>



<h2 class="wp-block-heading">Hook 3: Surface Branch Build Status at Checkout</h2>



<p class="wp-block-paragraph">Because friends don&#8217;t let friends check out broken branches.</p>



<p class="wp-block-paragraph">This is a client-side post-checkout hook. Unlike the server-side hooks above, it runs on each developer&#8217;s local workstation and fires automatically whenever they switch branches with <code>git checkout</code> (or <code>git switch</code>).</p>



<figure class="wp-block-image"><img decoding="async" src="https://wac-cdn-a.atlassian.com/dam/jcr:97ecbcdd-9129-4c78-b996-b1f3e1b755f9/githookpostcheckout.png" alt="Terminal showing branch build status displayed immediately after git checkout" /></figure>



<h3 class="wp-block-heading">What the Hook Does</h3>



<ol class="wp-block-list">
<li>After <code>git checkout</code> completes, the script reads the HEAD revision of the newly checked-out branch from the local repository.</li>
<li>It queries the CI server to determine whether that revision has been built — and if so, whether the build passed or failed.</li>
<li>The result is printed directly in the terminal alongside the normal checkout output.</li>
</ol>



<h3 class="wp-block-heading">Two Practical Scenarios</h3>



<p class="wp-block-paragraph"><strong>Creating a new feature branch from main:</strong> The hook tells you immediately whether the HEAD of main built successfully, confirming it is a safe and stable starting point for new work.</p>



<p class="wp-block-paragraph"><strong>Detecting a stale local copy:</strong> If the hook reports a failed build for a revision but the team&#8217;s CI dashboard shows a green build for that branch, your local copy is behind. You can then decide whether to <code>git pull</code> before continuing.</p>



<p class="wp-block-paragraph">This hook is the lowest-friction option to introduce to a team. It requires no server-side configuration, no repository admin access, and no changes to the shared workflow — each developer installs it independently in their local <code>.git/hooks</code> directory.</p>



<h2 class="wp-block-heading">Tooling and Portability</h2>



<p class="wp-block-paragraph">The three hooks described above were originally written to target Bamboo (build server), Clover (code coverage), and Bitbucket (Git hosting). However, Git hooks themselves are vendor-neutral — they are simply executable scripts in a well-known directory. The CI-specific logic in any hook script is limited to a handful of HTTP API calls or artifact URL patterns, which can be swapped out for equivalent calls to Jenkins, GitHub Actions, GitLab CI, CircleCI, or any other system that exposes build and coverage status via HTTP.</p>



<p class="wp-block-paragraph">If you work in a polyglot environment or want to manage hooks consistently across a team, tools such as <a href="https://pre-commit.com/">pre-commit</a> or <a href="https://typicode.github.io/husky/">Husky</a> can help version-control and distribute client-side hooks alongside your project code.</p>



<h2 class="wp-block-heading">Summary</h2>



<figure class="wp-block-table"><table><thead><tr><th>Hook</th><th>Type</th><th>Trigger</th><th>What It Enforces</th></tr></thead><tbody><tr><td>Clean branch builds</td><td>Server-side pre-receive</td><td>Push / merge to main</td><td>All tests must pass on the source branch</td></tr><tr><td>Code coverage floor</td><td>Server-side pre-receive</td><td>Push / merge to main</td><td>Branch coverage must not be lower than main</td></tr><tr><td>Branch build status</td><td>Client-side post-checkout</td><td>git checkout / switch</td><td>Displays CI build result for the checked-out revision</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">Git hooks are one of the most underutilised features in a CI/CD toolkit. Introducing even one of these hooks can measurably reduce the number of broken builds that reach your main branch — and the post-checkout hook in particular pays dividends immediately with zero team coordination required.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/3-git-hooks-for-continuous-integration/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Why Automation Is the Real Key to Effective DevOps and Continuous Delivery</title>
		<link>https://www.bestdevops.com/continuous-delivery-book-asserts-automation-is-key-to-effective-devops/</link>
					<comments>https://www.bestdevops.com/continuous-delivery-book-asserts-automation-is-key-to-effective-devops/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Thu, 18 May 2017 06:45:38 +0000</pubDate>
				<category><![CDATA[Continuous Delivery]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Automation]]></category>
		<category><![CDATA[BestDevOps]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[effective DevOps]]></category>
		<category><![CDATA[IT]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=1555</guid>

					<description><![CDATA[Running a CI server does not automatically mean you are doing continuous integration correctly. Eberhard Wolff, author of A Practical Guide to Continuous Delivery, explains why automation, testing, and eliminating human intervention are the true foundations of effective DevOps.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><em>This article draws on an interview with Eberhard Wolff, software architect and Fellow at innoQ, originally published by <strong>TheServerSide.com</strong>, discussing themes from his book <em>A Practical Guide to Continuous Delivery</em>.</em></p>



<h2 class="wp-block-heading">The CI Server Is Not Enough</h2>



<p class="wp-block-paragraph">Installing a CI server such as Jenkins or Concourse is now standard practice for any team that claims to be doing DevOps. But having a server that runs a job every hour or two is not the same as practising continuous integration in any meaningful sense.</p>



<p class="wp-block-paragraph">&#8220;I&#8217;d say that continuous integration is nowadays a commodity, up to the point where people actually have forgotten what it actually means. People are using integration servers just to do a regular compile,&#8221; said Eberhard Wolff, a software architect and Fellow at innoQ, in an interview with TheServerSide.</p>



<p class="wp-block-paragraph">Wolff points to a pattern he sees repeatedly: a team creates a long-lived feature branch in their Git repository, works on that branch independently for weeks or months, and uses the CI server only to compile that branch. The CI server is doing work, but the team is not integrating continuously — they are integrating rarely, in large batches, which is the opposite of what CI is designed to achieve.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>&#8220;They&#8217;re missing the original point about continuous integration. That&#8217;s the state we are in. People have forgotten about the original ideas behind CI.&#8221;</p><cite>— Eberhard Wolff, innoQ</cite></blockquote>



<p class="wp-block-paragraph">True continuous integration requires that every developer integrates their work into a shared mainline frequently — ideally at least once per day — so that integration problems are caught early and in small, manageable increments. A CI server is a tool that supports this workflow; it cannot create the workflow by itself.</p>



<h2 class="wp-block-heading">Continuous Integration and Effective DevOps</h2>



<p class="wp-block-paragraph">The relationship between CI and DevOps is more than superficial. DevOps as a practice aims to shorten the feedback loop between writing code and running it in production. CI is the first stage of that loop — catching defects before they accumulate. Without genuine CI (frequent integration into a shared branch, automated build, automated tests), the later stages of the pipeline — continuous delivery and continuous deployment — become unreliable.</p>



<p class="wp-block-paragraph">Wolff argues that the CI server is only one small piece of the puzzle. The larger pieces are <strong>comprehensive automated testing</strong> and the <strong>automation of manual processes</strong> that would otherwise interrupt the pipeline.</p>



<h2 class="wp-block-heading">The &#8220;Continuously Interrupted&#8221; Anti-Pattern</h2>



<p class="wp-block-paragraph">One of the most instructive concepts in Wolff&#8217;s thinking is what happens when a pipeline is technically automated but still requires a human to approve or perform steps along the way. He describes this as turning &#8220;continuous delivery&#8221; into &#8220;interrupted delivery.&#8221;</p>



<p class="wp-block-paragraph">&#8220;Just having Jenkins and just having a deployment pipeline is not the key challenge. The key challenge is going into production without sign-off,&#8221; Wolff said.</p>



<p class="wp-block-paragraph">When Wolff works with new customers, he starts by asking what the biggest impediments to running their continuous delivery pipeline are. The answer is almost always the same: a manual process — frequently in the user acceptance testing (UAT) phase — that requires a human to review and approve before the pipeline can proceed. That single manual gate can negate much of the speed and reliability benefit that automation is supposed to provide.</p>



<p class="wp-block-paragraph">This does not mean that all governance and oversight should be eliminated. It means that wherever possible, checks that currently require human intervention should be replaced with automated tests that can make the same determination faster and more consistently. The goal is to shift quality assurance left — catching problems earlier in the pipeline through automation rather than relying on a human reviewer at the end.</p>



<h2 class="wp-block-heading">Automation, Testing, and Confidence in Deployment</h2>



<p class="wp-block-paragraph">There is an important dependency that is easy to overlook: you cannot safely automate deployment unless you have a comprehensive automated test suite. Without tests that reliably catch regressions, removing human sign-off from a deployment pipeline is genuinely risky. This is why Wolff treats testing and automation as inseparable topics.</p>



<p class="wp-block-paragraph">A robust test strategy for a continuous delivery pipeline typically includes:</p>



<ul class="wp-block-list">
<li><strong>Unit tests</strong> — fast, isolated tests that verify individual functions or classes and run on every commit.</li>
<li><strong>Integration tests</strong> — tests that verify how components interact, including databases, message queues, and external services.</li>
<li><strong>Acceptance tests</strong> — automated tests written in terms of business behaviour (often using tools such as Cucumber or Gherkin) that replace or supplement manual UAT.</li>
<li><strong>Performance and security tests</strong> — automated checks that can be run on a schedule or as a pipeline stage to catch non-functional regressions.</li>
</ul>



<p class="wp-block-paragraph">Only when this test pyramid is in place can a team confidently remove the manual sign-off gate and allow the pipeline to deploy to production automatically.</p>



<h2 class="wp-block-heading">A Practical Approach: Tools, Examples, and Hands-On Guidance</h2>



<p class="wp-block-paragraph">Wolff&#8217;s book, <em>A Practical Guide to Continuous Delivery</em>, is designed to be less theoretical than much of the existing literature on the subject. Rather than explaining concepts in the abstract, it covers specific tools — including Chef, Docker, Vagrant, Jenkins, and SonarQube — and provides concrete examples of how to use them to build a real continuous delivery pipeline.</p>



<p class="wp-block-paragraph">&#8220;I talk about specific tools, I provide advice about how to use them, I have examples of how to use the tools,&#8221; Wolff said. The goal is to give readers enough practical experience with individual tools that they can assemble a working pipeline themselves, rather than understanding only the theory behind why such a pipeline should exist.</p>



<p class="wp-block-paragraph">This practical orientation matters because one of the common failure modes when adopting DevOps practices is that teams understand the goals — faster delivery, fewer defects, higher confidence — but struggle to translate those goals into a working system of pipelines, scripts, and configuration. A tool-focused, example-driven resource closes that gap.</p>



<h2 class="wp-block-heading">Key Takeaways for DevOps Engineers</h2>



<ul class="wp-block-list">
<li><strong>A CI server is a prerequisite, not a solution.</strong> Running builds on Jenkins or any other CI platform does not make your process continuous integration unless developers are integrating into a shared branch frequently.</li>
<li><strong>Long-lived feature branches undermine CI.</strong> The longer a branch lives in isolation, the larger and riskier the eventual merge becomes. Trunk-based development or very short-lived branches are the approaches most compatible with genuine CI.</li>
<li><strong>Manual gates break the pipeline.</strong> Any step that requires a human to intervene — approving a deployment, executing a test case by hand — introduces delay and variability. Identify these gates and replace them with automated equivalents.</li>
<li><strong>Automation requires test coverage.</strong> Before removing human oversight from a deployment pipeline, invest in a comprehensive automated test suite. The tests are what make automation safe.</li>
<li><strong>DevOps is defined by outcomes, not tools.</strong> The goal is to reduce the cycle time from code commit to production deployment while maintaining quality and reliability. Tools support that goal; they do not achieve it automatically.</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/continuous-delivery-book-asserts-automation-is-key-to-effective-devops/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Continuous Integration in Agile Software Development: Why CI and TDD Are Non-Negotiable</title>
		<link>https://www.bestdevops.com/continuous-integration-in-agile-software-development/</link>
					<comments>https://www.bestdevops.com/continuous-integration-in-agile-software-development/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Wed, 17 May 2017 06:55:49 +0000</pubDate>
				<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[Agility]]></category>
		<category><![CDATA[BestDevOps]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[Software Development]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=1546</guid>

					<description><![CDATA[Continuous Integration (CI) is a cornerstone of genuine Agile delivery. This article explains what CI is, how it pairs with Test-Driven Development, and the concrete benefits it brings to software engineering teams.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">A lot of teams call themselves Agile, yet still spend days resolving merge conflicts, discovering integration bugs late in a sprint, or waiting hours for manual test results. True agility in software development requires a technical foundation — and Continuous Integration (CI) is at its core.</p>



<h2 class="wp-block-heading">What Is Continuous Integration?</h2>



<p class="wp-block-paragraph">Continuous Integration is a software development practice in which every team member integrates their work into a shared repository frequently — ideally at least once per day. Each integration is verified by an automated build that runs a regression test suite, allowing the team to detect errors as quickly as possible.</p>



<p class="wp-block-paragraph">Martin Fowler, whose writing on CI remains widely referenced, describes the practice as the foundation that keeps a team&#8217;s codebase in a consistently working state. The key rule is simple but strict: <strong>the build must never be left in a broken state overnight.</strong> If a developer&#8217;s commit breaks the build, it is their responsibility to fix it before the end of the working day.</p>



<p class="wp-block-paragraph">CI did not appear in isolation. It was popularised as a core practice of Extreme Programming (XP) and sits alongside other engineering disciplines such as configuration management, automated compilation, build scripting, automated deployment, and comprehensive testing — all combined into a single, repeatable automated pipeline.</p>



<h2 class="wp-block-heading">Why CI Is Inseparable from Agile</h2>



<p class="wp-block-paragraph">Agile methodology is built on iterative, incremental delivery and rapid feedback loops. Without CI, those principles break down quickly. Consider the alternative: a team that relies primarily on manual testing may not receive feedback on a code change for several hours or even days. During that window, other changes accumulate, making it extremely difficult to isolate the root cause of any failure.</p>



<p class="wp-block-paragraph">CI closes this feedback loop. At the end of each working day, every team member knows that their code compiles, passes the test suite, and integrates correctly with the rest of the codebase. That confidence is what allows Agile teams to move fast without accumulating hidden technical debt.</p>



<h2 class="wp-block-heading">CI and Test-Driven Development</h2>



<p class="wp-block-paragraph">CI provides the delivery mechanism; Test-Driven Development (TDD) provides the quality gate. In TDD, a developer writes a failing unit test before writing the implementation code, then writes just enough code to make the test pass, and refactors. As the codebase grows, the test suite grows with it.</p>



<p class="wp-block-paragraph">When CI runs the build on every commit, it executes the full test suite automatically. New code that breaks existing behaviour is caught immediately and attributed to a specific commit — not discovered weeks later during an integration phase. This combination means:</p>



<ul class="wp-block-list">
<li>Developers get rapid, precise feedback on every change.</li>
<li>Regressions are caught at the earliest possible moment.</li>
<li>The team can refactor with confidence, knowing the test suite will flag unintended side effects.</li>
<li>An always-green build pipeline becomes a reliable signal of software quality.</li>
</ul>



<p class="wp-block-paragraph">Together, CI and TDD form a safety net that makes it realistic — not reckless — to ship frequently and respond to changing requirements inside a sprint.</p>



<h2 class="wp-block-heading">Key Benefits of Continuous Integration</h2>



<h3 class="wp-block-heading">1. Reduced Integration Risk</h3>



<p class="wp-block-paragraph">The longer a feature branch lives without being merged, the greater the divergence from the mainline. Frequent integration keeps the gap small. There is less room for conflicting assumptions between developers, fewer &#8220;works on my machine&#8221; surprises, and a dramatically lower risk of expensive rework caused by late-discovered incompatibilities.</p>



<h3 class="wp-block-heading">2. Fast Issue Detection</h3>



<p class="wp-block-paragraph">Automated builds and tests run on every commit. Problems surface within minutes rather than days. Think of it as a smoke detector for your codebase: it does not prevent fires, but it ensures that when something goes wrong, the team knows about it immediately — while the change is still fresh in the committing developer&#8217;s mind.</p>



<h3 class="wp-block-heading">3. Process Automation</h3>



<p class="wp-block-paragraph">Agile is fundamentally about efficiency. CI eliminates slow, error-prone manual steps — compiling code, running tests, packaging artefacts — by making them automatic and repeatable. Engineers spend time writing code, not running manual build procedures.</p>



<h3 class="wp-block-heading">4. Deployable Software at Any Time</h3>



<p class="wp-block-paragraph">A well-configured CI pipeline produces a tested, deployable artefact on every successful build. This means a release decision becomes a business decision, not a technical crisis. Teams that lack CI frequently experience delayed releases caused by unforeseen integration problems that only surface when all the moving parts are finally assembled.</p>



<h3 class="wp-block-heading">5. Confidence in Code Quality</h3>



<p class="wp-block-paragraph">With every green build, the team has evidence — not just hope — that the software behaves as specified. Automated checks can also enforce coding standards, run static analysis, and measure test coverage, making quality a continuous measurement rather than a checkpoint at the end of a release cycle.</p>



<h3 class="wp-block-heading">6. Team Transparency</h3>



<p class="wp-block-paragraph">Build status should be visible to everyone. A passing build increases collective confidence. A failing build is an immediate, unambiguous signal that prompts collaboration: the developer who broke the build can ask colleagues to help diagnose the problem while the context is still current. Transparency in the pipeline removes the &#8220;who broke it?&#8221; culture and replaces it with shared ownership of quality.</p>



<h2 class="wp-block-heading">Business Impact</h2>



<p class="wp-block-paragraph">For engineering managers and product owners, the case for CI is equally compelling from a business perspective:</p>



<ul class="wp-block-list">
<li><strong>Faster time to market:</strong> Smaller, frequently integrated changes can be released as soon as they are validated, rather than waiting for a large batch release.</li>
<li><strong>Better response to changing requirements:</strong> When integration is cheap and continuous, teams can pivot quickly without accumulating a mountain of deferred integration work.</li>
<li><strong>Lower rework costs:</strong> Bugs caught at commit time cost a fraction of what they cost to fix after they have propagated through the system.</li>
<li><strong>Predictable delivery:</strong> Stakeholders can rely on a steady stream of working software increments rather than infrequent, high-risk releases.</li>
</ul>



<h2 class="wp-block-heading">Getting Started with CI</h2>



<p class="wp-block-paragraph">If your team is new to CI, the following practices form a practical starting point:</p>



<ol class="wp-block-list">
<li><strong>Maintain a single source repository</strong> and ensure every developer commits to the mainline (or short-lived feature branches that merge daily).</li>
<li><strong>Automate the build</strong> so that a single command compiles and packages the entire application.</li>
<li><strong>Write automated tests</strong> that cover critical paths, and add to the suite with every new feature or bug fix.</li>
<li><strong>Run the build on every commit</strong> using a CI server (Jenkins, GitHub Actions, GitLab CI, CircleCI, and others are common choices).</li>
<li><strong>Fix broken builds immediately.</strong> A broken build is the team&#8217;s top priority — nothing else is merged until the build is green again.</li>
<li><strong>Make build results visible</strong> to the whole team via dashboards, notifications, or status badges.</li>
</ol>



<h2 class="wp-block-heading">Conclusion</h2>



<p class="wp-block-paragraph">Agile transformation is not complete with stand-ups and Kanban boards alone. The engineering practices that underpin genuine agility — Continuous Integration and Test-Driven Development — are what give teams the technical foundation to deliver quickly, safely, and repeatedly. CI is not an optional add-on; it is the mechanism that makes iterative delivery sustainable at scale.</p>



<p class="wp-block-paragraph">Teams that invest in CI consistently report fewer integration failures, faster feedback cycles, and greater confidence in their releases. Once adopted, CI is rarely abandoned — because the alternative, going back to infrequent manual integration, is simply too costly.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/continuous-integration-in-agile-software-development/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>CI/CD with Jenkins Pipelines and Blue Ocean: A Practical Setup Guide</title>
		<link>https://www.bestdevops.com/continuous-integration-and-delivery-with-jenkins-pipelines-blue-ocean/</link>
					<comments>https://www.bestdevops.com/continuous-integration-and-delivery-with-jenkins-pipelines-blue-ocean/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Thu, 04 May 2017 07:42:36 +0000</pubDate>
				<category><![CDATA[Continuous Delivery]]></category>
		<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Blue Ocean]]></category>
		<category><![CDATA[CD]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[Jenkins]]></category>
		<category><![CDATA[Pipelines]]></category>
		<category><![CDATA[Software Development]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=1459</guid>

					<description><![CDATA[Learn how to run Jenkins Blue Ocean with Docker Compose, write declarative Jenkinsfiles with Docker agents, and use stages, conditional steps, and post actions to build a maintainable CI/CD pipeline.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><em>This article is based on a post originally published by R. Moorman at Moor Interactive (<strong>moori.nl</strong>), describing their team&#8217;s hands-on evaluation of Jenkins Blue Ocean and Pipelines.</em></p>



<h2 class="wp-block-heading">Why Jenkins Pipelines and Blue Ocean?</h2>



<p class="wp-block-paragraph">Mature engineering teams tend to iterate constantly on their CI/CD workflows. Jenkins has long been a staple of that process, but its classic UI and job-configuration model can become unwieldy as project count grows. Cloud-native alternatives like Travis CI and Drone gained popularity in part because they store build configuration alongside source code in Git — something Jenkins historically made difficult.</p>



<p class="wp-block-paragraph">Two Jenkins features close that gap significantly:</p>



<ul class="wp-block-list">
<li><strong>Jenkins Pipelines</strong> — lets you define your entire build, test, and deployment process as code in a <code>Jenkinsfile</code> committed to your repository.</li>
<li><strong>Blue Ocean</strong> — a plugin that rethinks the Jenkins user experience, surfacing pipeline status, stage results, and test data with minimal navigation.</li>
</ul>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>&#8220;Blue Ocean is a project that rethinks the user experience of Jenkins, modelling and presenting the process of software delivery by surfacing information that&#8217;s important to development teams with as few clicks as possible.&#8221;</p></blockquote>



<p class="wp-block-paragraph">The sections below walk through spinning up Jenkins Blue Ocean with Docker Compose, writing a declarative <code>Jenkinsfile</code>, and using key Pipeline features such as Docker agents, conditional stages, and post actions.</p>



<h2 class="wp-block-heading">Running Jenkins Blue Ocean with Docker Compose</h2>



<p class="wp-block-paragraph">Containerising Jenkins keeps your host clean and makes the setup reproducible. You need three files: a <code>Dockerfile</code>, a <code>docker-compose.yaml</code>, and a <code>docker.conf</code> that exposes the Docker socket so Jenkins can spin up agent containers.</p>



<h3 class="wp-block-heading">Dockerfile</h3>



<p class="wp-block-paragraph">Start from the official Blue Ocean image and copy in the Docker daemon configuration:</p>


<pre class="wp-block-code"><span><code class="hljs language-xml">FROM jenkinsci/blueocean:latest
MAINTAINER R. Moorman <span class="hljs-tag">&lt;<span class="hljs-name">rob@moori.nl</span>&gt;</span>
USER root
COPY docker.conf /etc/init.d/docker</code></span></pre>


<h3 class="wp-block-heading">docker-compose.yaml</h3>



<p class="wp-block-paragraph">Mount the Docker socket so Jenkins can create sibling containers on the host, and persist Jenkins home to a local directory:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">version: <span class="hljs-string">'2'</span>
<span class="hljs-attr">services</span>:
  jenkins:
    build: .
    ports:
      - <span class="hljs-number">8080</span>:<span class="hljs-number">8080</span>
    <span class="hljs-attr">volumes</span>:
      - ./jenkins_home:<span class="hljs-regexp">/var/</span>jenkins_home
      - <span class="hljs-regexp">/var/</span>run/docker.sock:<span class="hljs-regexp">/var/</span>run/docker.sock</code></span></pre>


<h3 class="wp-block-heading">docker.conf</h3>



<p class="wp-block-paragraph">Expose the Docker daemon on TCP as well as the Unix socket so the Jenkins Docker plugin can reach it:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">DOCKER_OPTS=<span class="hljs-string">"-H tcp://0.0.0.0:4243 -H unix:///var/run/docker.sock --tls=false"</span></code></span></pre>


<p class="wp-block-paragraph">With all three files in the same directory, start the stack:</p>


<pre class="wp-block-code"><span><code class="hljs">docker-compose up</code></span></pre>


<p class="wp-block-paragraph">Jenkins will be available at <code>http://localhost:8080/</code>. Complete the initial setup wizard, then navigate to the Blue Ocean view via the sidebar.</p>



<figure class="wp-block-image"><img decoding="async" src="https://www.moori.nl/media/images/jenkins-login.original.jpg" alt="Jenkins login screen after installation"/><figcaption>Jenkins login screen after installation</figcaption></figure>



<h2 class="wp-block-heading">Writing Your First Declarative Jenkinsfile</h2>



<p class="wp-block-paragraph">After switching to the Blue Ocean view you can create a new Pipeline and point it at a source repository. Blue Ocean will look for a <code>Jenkinsfile</code> at the repository root. You can also use the built-in visual Pipeline editor for quick experiments, but writing the <code>Jenkinsfile</code> by hand gives you full version-control history and the most flexibility.</p>



<p class="wp-block-paragraph">The following example is based on a Python project. It checks out source code, runs the <code>flake8</code> linter, converts results to JUnit XML format, and publishes them so Blue Ocean can display them as test results. The full example repository is available at <a href="https://github.com/robmoorman/jenkins-blueocean" rel="noopener">https://github.com/robmoorman/jenkins-blueocean</a>.</p>


<pre class="wp-block-code"><span><code class="hljs language-php">pipeline {
  agent {
    docker <span class="hljs-string">'python:3.6.1'</span>
  }
  stages {
    stage(<span class="hljs-string">'Install dependencies'</span>) {
      steps {
        sh <span class="hljs-string">'pip install -r requirements.txt'</span>
      }
    }
    stage(<span class="hljs-string">'Test'</span>) {
      steps {
        sh <span class="hljs-string">'flake8 src/ --exit-zero --output-file flake8-output.txt'</span>
        sh <span class="hljs-string">'flake8_junit flake8-output.txt flake8-output.xml'</span>
      }
    }
  }
  post {
    always {
      junit <span class="hljs-string">'flake8-output.xml'</span>
    }
    failure {
      <span class="hljs-keyword">echo</span> <span class="hljs-string">'Failed!'</span>
    }
    success {
      <span class="hljs-keyword">echo</span> <span class="hljs-string">'Done!'</span>
    }
  }
}</code></span></pre>


<figure class="wp-block-image"><img decoding="async" src="https://www.moori.nl/media/images/jenkins-tests.original.jpg" alt="Test results displayed in the Jenkins Blue Ocean UI"/><figcaption>Test results from the Jenkinsfile rendered in Blue Ocean</figcaption></figure>



<h2 class="wp-block-heading">Key Pipeline Concepts Explained</h2>



<h3 class="wp-block-heading">Agents</h3>



<p class="wp-block-paragraph">The <code>agent</code> directive tells Jenkins where and how to run a pipeline or an individual stage. Specifying a Docker image as the agent is especially clean: Jenkins pulls the image, runs your steps inside the container, then discards it. This mirrors the approach used by Travis CI and Drone, so teams familiar with those platforms adapt quickly.</p>



<p class="wp-block-paragraph">You can define different agents per stage, which makes it straightforward to compile in one environment and deploy from another — all within the same <code>Jenkinsfile</code>.</p>



<h3 class="wp-block-heading">Stages and Steps</h3>



<p class="wp-block-paragraph">Splitting your build into named stages and steps serves two purposes:</p>



<ul class="wp-block-list">
<li><strong>Visibility</strong> — Blue Ocean renders each stage as a column in its pipeline view, making it immediately obvious where a build failed.</li>
<li><strong>Control flow</strong> — when a step fails, the pipeline halts and subsequent steps are skipped. You can also attach <code>post</code> blocks to individual stages (for example, always publishing coverage reports after the test stage, regardless of pass/fail).</li>
</ul>



<h3 class="wp-block-heading">Conditional Steps with <code>when</code></h3>



<p class="wp-block-paragraph">The <code>when</code> directive lets you gate a stage on branch name, environment variable, or other conditions. This is particularly useful for deployment stages that should only run on specific branches:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">stage(<span class="hljs-string">'Deploy'</span>) {
  when {
    branch <span class="hljs-string">'develop'</span>
  }
  steps {
    sh <span class="hljs-string">'sh ./etc/deploy_test.sh'</span>
  }
}</code></span></pre>


<p class="wp-block-paragraph">Combining branch conditions with pull-request detection keeps a single <code>Jenkinsfile</code> as the authoritative source of truth for the entire delivery process — from feature branch lint checks through to production deployment.</p>



<h3 class="wp-block-heading">Post Actions and Notifications</h3>



<p class="wp-block-paragraph">The <code>post</code> block supports conditional sections including <code>always</code>, <code>success</code>, <code>failure</code>, <code>unstable</code>, and <code>changed</code>. Common uses include:</p>



<ul class="wp-block-list">
<li>Publishing JUnit test results (<code>junit</code> step)</li>
<li>Sending Slack notifications on build failure</li>
<li>Archiving build artefacts</li>
<li>Triggering downstream pipelines</li>
</ul>



<p class="wp-block-paragraph">Note that at the time this was written (early 2017, around the first public Blue Ocean release), not all Jenkins plugins had been updated to render correctly within the Blue Ocean UI. The classic Jenkins view remained fully compatible, so plugin incompatibility was an inconvenience rather than a blocker. Plugin compatibility has continued to improve since then — check the Blue Ocean compatibility matrix for current status.</p>



<figure class="wp-block-image"><img decoding="async" src="https://www.moori.nl/media/images/failing-pipeline.original.png" alt="A more complex failing pipeline visualised in Blue Ocean"/><figcaption>A more complex Pipeline execution in Blue Ocean, showing a failing stage</figcaption></figure>



<h2 class="wp-block-heading">Conclusion</h2>



<p class="wp-block-paragraph">Jenkins Pipelines, with declarative <code>Jenkinsfiles</code> and Docker agents, offer a flexible and version-controlled approach to CI/CD that competes directly with cloud-native platforms. Storing pipeline logic in the repository itself — rather than in Jenkins job configuration — addresses one of the longest-standing pain points of traditional Jenkins setups.</p>



<p class="wp-block-paragraph">Blue Ocean addresses the usability gap with a modern, stage-oriented interface that makes pipeline status easy to understand at a glance. Plugin ecosystem maturity was a real limitation at the time of Blue Ocean&#8217;s initial release, but it should not be treated as a dealbreaker given the pace of development in the Jenkins ecosystem.</p>



<p class="wp-block-paragraph">If you are evaluating whether to migrate from a cloud CI platform back to self-hosted Jenkins, or simply looking to modernise an existing Jenkins setup, starting with a Dockerised Blue Ocean instance and declarative Pipelines is a low-risk way to assess the workflow before committing fully.</p>



<p class="wp-block-paragraph"><strong>Next steps:</strong> Explore shared libraries to make pipeline steps reusable across repositories, and look at the <code>parallel</code> directive for running independent stages concurrently to cut build times.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/continuous-integration-and-delivery-with-jenkins-pipelines-blue-ocean/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Continuous Integration Best Practices</title>
		<link>https://www.bestdevops.com/continuous-integration-best-practices/</link>
					<comments>https://www.bestdevops.com/continuous-integration-best-practices/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Wed, 03 May 2017 18:09:27 +0000</pubDate>
				<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[DevOps Best Practices]]></category>
		<category><![CDATA[Best practices]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[Continuous Integration Best Practices]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=1446</guid>

					<description><![CDATA[A practical guide to the core best practices every engineering team should follow when implementing Continuous Integration, from version control discipline to fast, visible builds.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Continuous Integration (CI) is a software development discipline where every team member integrates their work into a shared mainline frequently — ideally at least once per day. Each integration is verified by an automated build and test suite, allowing teams to detect problems early. The practices below represent the foundational principles that make CI effective in real-world engineering environments.</p>



<h2 class="wp-block-heading">1. Maintain a Single Source-of-Truth Repository</h2>



<p class="wp-block-paragraph">Every artifact required to build, test, and deploy your application should live in version control. This includes application source code, infrastructure-as-code scripts, database migration scripts, build configuration files, and deployment manifests. Using a system such as Git ensures that any developer or CI server can check out a known revision and produce a deterministic build from scratch, without relying on files that exist only on a local machine or a shared network drive.</p>



<p class="wp-block-paragraph"><strong>Practical tip:</strong> Treat your repository as the single source of truth. If it is not in version control, it does not officially exist.</p>



<h2 class="wp-block-heading">2. Automate the Build</h2>



<p class="wp-block-paragraph">The build process must be fully automated and triggerable by a single command or a CI server webhook. Manual build steps introduce human error and make reproducibility impossible. Whether your toolchain is Make, Gradle, Maven, MSBuild, npm scripts, or a custom shell script, the goal is the same: any engineer — or a headless CI agent — should be able to run the complete build without prior knowledge of local environment quirks.</p>



<p class="wp-block-paragraph"><strong>Practical tip:</strong> Store build scripts alongside application code. Avoid build logic that only works inside a specific IDE or on a specific developer&#8217;s laptop.</p>



<h2 class="wp-block-heading">3. Make the Build Self-Testing</h2>



<p class="wp-block-paragraph">A successful compilation is not the same as a working application. Incorporate automated tests — unit tests at a minimum, and integration tests where practical — directly into the build pipeline. The CI server should run these tests on every triggered build and report failures immediately. A build that compiles but ships broken behavior has failed, even if the compiler reported success.</p>



<p class="wp-block-paragraph"><strong>Practical tip:</strong> Structure your test suite so that fast unit tests run first. Slower integration or end-to-end tests can run in a subsequent pipeline stage to keep early feedback rapid.</p>



<h2 class="wp-block-heading">4. Everyone Commits to the Mainline Every Day</h2>



<p class="wp-block-paragraph">Long-lived feature branches are the enemy of CI. The longer a branch lives, the larger the eventual merge conflict and the longer integration problems stay hidden. Encourage every developer to integrate their in-progress work into the mainline branch at least once per working day, using techniques like feature flags or branch-by-abstraction to keep incomplete features invisible to end users while still allowing code to merge continuously.</p>



<p class="wp-block-paragraph"><strong>Practical tip:</strong> If a change is too large to commit daily, the task is probably too large. Break it into smaller, independently mergeable increments.</p>



<h2 class="wp-block-heading">5. Every Commit to the Mainline Triggers a Build</h2>



<p class="wp-block-paragraph">CI servers should be configured to watch the mainline branch and trigger a full build-and-test cycle automatically on every push. If a build fails, the team&#8217;s top priority becomes restoring the build to green — either by fixing the defect or reverting the offending commit. A broken mainline blocks every other developer from having confidence in their own integrations.</p>



<p class="wp-block-paragraph"><strong>Practical tip:</strong> Define a clear team agreement: whoever breaks the build is responsible for fixing it immediately, not at the end of the sprint.</p>



<h2 class="wp-block-heading">6. Keep the Build Fast</h2>



<p class="wp-block-paragraph">Feedback latency is the enemy of CI. A build that takes 45 minutes to complete will be ignored; developers will push and move on without waiting for results. Aim to keep the primary build-and-unit-test cycle short — many teams target under 10 minutes as a practical ceiling, though the right number depends on project size. Techniques that help include parallelising test execution, caching dependency downloads, and separating slow integration tests into a later pipeline stage.</p>



<p class="wp-block-paragraph"><strong>Practical tip:</strong> Profile your build regularly. Identify the slowest steps and investigate whether they can be parallelised, cached, or moved to a later stage.</p>



<h2 class="wp-block-heading">7. Make Build Results Visible to Everyone</h2>



<p class="wp-block-paragraph">Build status should not be hidden inside a tool that only the DevOps team monitors. Display the current state of every pipeline — passed, failed, or running — on a shared dashboard visible to the whole team. CI platforms such as Jenkins, GitLab CI/CD, GitHub Actions, CircleCI, and TeamCity all provide build dashboards and notification integrations (email, Slack, Teams) out of the box. Visibility creates shared accountability.</p>



<p class="wp-block-paragraph"><strong>Practical tip:</strong> Consider a physical build radiator (a wall-mounted monitor showing CI status) in open-plan offices. The visual signal of a red build creates immediate social pressure to fix it.</p>



<h2 class="wp-block-heading">Summary</h2>



<figure class="wp-block-table"><table><thead><tr><th>Best Practice</th><th>Core Goal</th></tr></thead><tbody><tr><td>Maintain a version-controlled repository</td><td>Single source of truth for all artifacts</td></tr><tr><td>Automate the build</td><td>Reproducibility and consistency</td></tr><tr><td>Make the build self-testing</td><td>Catch defects automatically on every change</td></tr><tr><td>Commit to mainline daily</td><td>Reduce merge conflict and integration risk</td></tr><tr><td>Build every mainline commit</td><td>Immediate defect detection</td></tr><tr><td>Keep the build fast</td><td>Short feedback loops</td></tr><tr><td>Publish build results visibly</td><td>Shared accountability and transparency</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">Implementing these practices consistently transforms CI from a tool you have installed into a genuine engineering discipline. The result is a codebase that is always in a releasable state and a team that can detect and fix integration problems in minutes rather than days.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/continuous-integration-best-practices/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Why We Always Start With Continuous Integration and Continuous Delivery</title>
		<link>https://www.bestdevops.com/why-we-always-start-with-continuous-integration-and-continuous-delivery/</link>
					<comments>https://www.bestdevops.com/why-we-always-start-with-continuous-integration-and-continuous-delivery/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Fri, 07 Apr 2017 10:15:22 +0000</pubDate>
				<category><![CDATA[Continuous Delivery]]></category>
		<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[DevOps Process]]></category>
		<category><![CDATA[(CI/CD)]]></category>
		<category><![CDATA[CD]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[Continuous testing]]></category>
		<category><![CDATA[Software Testing]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=1177</guid>

					<description><![CDATA[CI/CD isn't just a nice-to-have pipeline feature — it's the foundation of a healthy engineering culture. Here's why experienced DevOps teams insist on establishing Continuous Integration and Continuous Delivery from day one of every project.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><em>This article is based on practical experience from software development teams and reflects common CI/CD adoption patterns in the industry. Original source attribution: 126kr.com / TailorDev.</em></p>



<h2 class="wp-block-heading">Testing Is No Longer Optional</h2>



<p class="wp-block-paragraph">Not long ago, development teams had to actively argue that software testing was a core part of building software — not a budget-dependent luxury. That battle is largely won. Today it is widely accepted that shipping an application or a feature means delivering code, tests, and documentation together as a single unit.</p>



<p class="wp-block-paragraph">Open Source projects have operated this way for decades. Platforms like GitHub have generalised those good practices across the broader industry, and hosted CI services such as Travis CI and CircleCI made automated testing more accessible by providing tight version-control integrations that developers could enable with minimal configuration.</p>



<h2 class="wp-block-heading">What Continuous Integration Actually Means</h2>



<p class="wp-block-paragraph"><strong>Continuous Integration (CI)</strong> is the practice of using a build server to automatically:</p>



<ol class="wp-block-list">
<li>Build the software from its source code.</li>
<li>Run the full test suite.</li>
<li>Report the results back to the development team.</li>
</ol>



<p class="wp-block-paragraph">By connecting a CI service to a repository hosted on GitHub or GitLab (which includes built-in CI), developers get near-instant feedback on the health of the codebase. This feedback loop is primarily aimed at developers: it tells them whether their changes can be safely integrated with the current stable version of the software, typically indicated by a green (passing) or red (failing) build status.</p>



<p class="wp-block-paragraph">In its strictest definition, CI requires developers to push changes to the mainline branch at least once per day, minimising long-running divergent work. In practice, most teams — including the team behind this article — use <strong>feature branches</strong> and merge them when the build is green rather than on a strict daily schedule.</p>



<h2 class="wp-block-heading">Feature Branches and the Pull Request Workflow</h2>



<p class="wp-block-paragraph">Feature branches became standard with the rise of Distributed Version Control Systems (DVCS) like Git, and both GitHub and GitLab are built around them. A feature branch is a short-lived branch that encapsulates a single change — a bug fix, a new feature, or a refactor — keeping the mainline stable.</p>



<p class="wp-block-paragraph">The typical workflow looks like this:</p>



<ol class="wp-block-list">
<li>Create a new branch from the latest state of the mainline.</li>
<li>Develop and commit incrementally.</li>
<li>Push the branch to the shared remote repository.</li>
<li>Open a Pull Request (GitHub) or Merge Request (GitLab).</li>
<li>The CI server runs the build and test suite, updating the branch status.</li>
<li>Once the build is green and conflicts are resolved, merge into the mainline.</li>
</ol>



<p class="wp-block-paragraph">GitHub and GitLab both surface conflict detection and build status directly in the Pull Request / Merge Request UI, making it easy for the whole team to assess readiness at a glance. Many teams use a simple Git branching model that treats <code>master</code> (or <code>main</code>) as the mainline and uses <code>rebase</code> to keep history clean and avoid unnecessary merge commits.</p>



<h2 class="wp-block-heading">Organisational Benefits: Ownership and Code Review</h2>



<p class="wp-block-paragraph">Adopting CI with a feature-branch workflow naturally introduces useful team conventions:</p>



<ul class="wp-block-list">
<li><strong>Branch ownership:</strong> The developer who opens a feature branch is responsible for it until it is merged. This prevents orphaned branches and unclear accountability.</li>
<li><strong>Code review:</strong> Pull Requests and Merge Requests make peer review a natural part of the workflow. Both GitHub and GitLab provide inline commenting tools that make code review efficient.</li>
<li><strong>Build health accountability:</strong> The developer who breaks the build is responsible for fixing it. This simple rule removes ambiguity and encourages everyone to keep the mainline green.</li>
</ul>



<p class="wp-block-paragraph">The result is a mainline branch that can reasonably be treated as the current stable version of the software — buildable and deployable at any time.</p>



<h2 class="wp-block-heading">From CI to Continuous Delivery and Continuous Deployment</h2>



<p class="wp-block-paragraph">A stable, always-deployable mainline is the prerequisite for the next step: <strong>Continuous Delivery (CD)</strong>.</p>



<p class="wp-block-paragraph">Continuous Delivery means having the methods, tooling, and processes in place to release software to production at any time — safely, repeatably, and with confidence. It does not mean every commit goes to production automatically; it means every commit <em>could</em>.</p>



<p class="wp-block-paragraph"><strong>Continuous Deployment</strong> goes one step further: every change that passes the pipeline is deployed to production automatically, without manual intervention. It is an extension of Continuous Delivery, not a replacement for it.</p>



<p class="wp-block-paragraph">The key relationship: <strong>you cannot achieve reliable Continuous Delivery without Continuous Integration</strong>. CI is the foundation on which CD is built.</p>



<h2 class="wp-block-heading">The Continuous Delivery Feedback Loop</h2>



<p class="wp-block-paragraph">While the CI feedback loop is primarily developer-facing, Continuous Delivery extends the feedback loop to multiple stakeholders:</p>



<ul class="wp-block-list">
<li><strong>Developers</strong> learn whether a change behaves as expected in a production-like environment.</li>
<li><strong>Operations teams</strong> get confirmation that the software deploys correctly and that infrastructure is not overloaded.</li>
<li><strong>Business stakeholders</strong> can ship features to users more frequently, shortening the distance between idea and value.</li>
<li><strong>End users</strong> benefit from more frequent, smaller, lower-risk updates.</li>
</ul>



<p class="wp-block-paragraph">This multi-stakeholder feedback loop is closely connected to the broader <strong>DevOps</strong> cultural movement, which emphasises collaboration between development, operations, and quality assurance functions.</p>



<h2 class="wp-block-heading">Practical CI/CD Setup: Environments and Deployment Scripts</h2>



<p class="wp-block-paragraph">In practice, teams implementing CD typically maintain multiple deployment environments:</p>



<ul class="wp-block-list">
<li><strong>Development (dev):</strong> Updated automatically on every merge to the mainline. Used for integration testing.</li>
<li><strong>Staging:</strong> A production-like environment used for pre-release verification with customers or stakeholders.</li>
<li><strong>Production:</strong> The live environment, deployed manually (Continuous Delivery) or automatically (Continuous Deployment) depending on team policy.</li>
</ul>



<p class="wp-block-paragraph">Deployment scripts should be kept as simple as possible. A shell script that describes exactly the commands needed to build and deploy the software becomes the single source of truth for the deployment process. That process should also be documented in a <code>README</code> so any team member can understand it without tribal knowledge.</p>



<p class="wp-block-paragraph">GitLab CI/CD pipelines can expose manual deploy buttons directly in the GitLab UI, allowing any authorised team member to trigger a deployment to a specific environment without SSH access or specialist knowledge. GitHub offers similar capabilities through its Deployments API and integrations with chat-ops tools.</p>



<h2 class="wp-block-heading">Four Concrete Benefits of This Approach</h2>



<ol class="wp-block-list">
<li><strong>Automated, reproducible, documented deployments:</strong> The deployment script is the definitive record of how the software is built and shipped. There is no undocumented manual step hiding in someone&#8217;s head.</li>
<li><strong>Anyone can deploy at any time:</strong> When deployments are automated and exposed through a UI or chat-ops command, deploying is no longer a specialist task. This reduces bottlenecks and single points of failure.</li>
<li><strong>Smaller, more frequent releases:</strong> Shipping smaller chunks of work more often reduces risk. Each release is easier to reason about, easier to test, and easier to roll back if needed. As Eric S. Raymond put it: release early, release often.</li>
<li><strong>Faster bug resolution:</strong> Automated tests catch many issues, but real production data surfaces edge cases that tests miss. Frequent deployments mean bugs introduced in production are identified and fixed quickly, because the delta between releases is small. As Edsger Dijkstra observed, testing reveals the presence of bugs, not their absence — so fast feedback from production is invaluable.</li>
</ol>



<h2 class="wp-block-heading">Why Start Every Project With CI/CD?</h2>



<p class="wp-block-paragraph">Setting up CI/CD at the start of a project — rather than retrofitting it later — has compounding benefits:</p>



<ul class="wp-block-list">
<li><strong>Quality controls are automated from day one.</strong> The team can focus on building value rather than manually verifying that nothing is broken.</li>
<li><strong>Standards are established early.</strong> Feature branches, code reviews, and green-build policies become habits before bad practices take root.</li>
<li><strong>The project remains accessible to new contributors.</strong> Documented, automated pipelines mean a new developer can get productive quickly without needing a lengthy onboarding session from a senior engineer.</li>
<li><strong>Handoffs are cleaner.</strong> When a consulting team or contractor finishes an engagement, a project with working CI/CD and clear deployment scripts is far easier for the client team to take ownership of than one with undocumented manual processes.</li>
</ul>



<p class="wp-block-paragraph">The upfront investment — typically a few days to configure pipelines, write deployment scripts, and set up environments — pays dividends throughout the life of the project. It is one of the highest-return early decisions a development team can make.</p>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">Continuous Integration ensures every code change is automatically built and tested, giving developers fast feedback and keeping the mainline stable. Continuous Delivery extends that stability into a reliable, repeatable release process that every stakeholder benefits from. Together, they form the backbone of a healthy engineering culture — reducing risk, improving collaboration, and allowing teams to focus on delivering value rather than managing chaos. Starting with CI/CD is not perfectionism; it is pragmatism.</p>



<p class="wp-block-paragraph"><strong>Further reading:</strong> <a href="http://www.scmgalaxy.com/courses/agenda/devops/continuous-integration-training.html">Continuous Integration training resources</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/why-we-always-start-with-continuous-integration-and-continuous-delivery/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Benefits of Integrating a CI Tool with Docker</title>
		<link>https://www.bestdevops.com/what-are-the-benefits-of-integrating-a-ci-tool-with-docker/</link>
					<comments>https://www.bestdevops.com/what-are-the-benefits-of-integrating-a-ci-tool-with-docker/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Tue, 28 Mar 2017 06:32:27 +0000</pubDate>
				<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[DevOps Process]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[CI Tools]]></category>
		<category><![CDATA[Continuous Integration With Docker]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Docker Integration]]></category>
		<category><![CDATA[Software Development]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=1068</guid>

					<description><![CDATA[Learn why integrating Docker with a CI tool like Jenkins or CircleCI is essential for DevOps pipelines, and how to get started with the integration.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><em>This article is based on a source originally published at techtarget.com. Attribution is preserved accordingly.</em></p>



<h2 class="wp-block-heading">Why Integrate Docker with Your CI Tool?</h2>



<p class="wp-block-paragraph">DevOps is fundamentally about moving toward <strong>continuous integration (CI)</strong> and <strong>continuous delivery (CD)</strong>. Every step in the software lifecycle should be programmatic, repeatable, and automated. That goal is difficult to achieve when development, QA, and operations teams work in silos, each using different environments and toolchains.</p>



<p class="wp-block-paragraph">Two complementary technologies help break down those silos:</p>



<ul class="wp-block-list">
<li><strong>CI tools</strong> (such as Jenkins, CircleCI, or GitLab CI) automate the build, test, and release workflow.</li>
<li><strong>Docker</strong> provides a consistent, portable packaging format so the same container image runs identically across development, test, and production environments.</li>
</ul>



<p class="wp-block-paragraph">Combining the two eliminates the classic &#8220;works on my machine&#8221; problem and lays the groundwork for a reliable CD pipeline. If you plan to graduate from CI to full CD, integrating Docker with your CI tool is a prerequisite, not an optional enhancement.</p>



<h2 class="wp-block-heading">What Happens When a CI Tool and Docker Work Together?</h2>



<p class="wp-block-paragraph">When your CI tool and Docker are integrated, a typical pipeline executes the following steps automatically whenever a developer pushes new code:</p>



<ol class="wp-block-list">
<li><strong>Build</strong> – The CI tool builds a Docker image from the <code>Dockerfile</code> in your repository.</li>
<li><strong>Test</strong> – The freshly built image is spun up as a container and your automated test suite runs inside it, ensuring tests execute against the exact same environment that will reach production.</li>
<li><strong>Push</strong> – If tests pass, the CI tool pushes the verified image to Docker Hub or a private container registry.</li>
<li><strong>Deploy</strong> – The CI/CD tool pulls the image from the registry and deploys it to the target environment (staging or production), often on a cloud host.</li>
</ol>



<p class="wp-block-paragraph">This four-step loop gives every team a single source of truth: the Docker image. Developers, testers, and operations engineers all work with the same artifact, removing environment-specific surprises.</p>



<h2 class="wp-block-heading">How to Integrate Docker with Popular CI Tools</h2>



<h3 class="wp-block-heading">Jenkins</h3>



<p class="wp-block-paragraph">Jenkins extends its Docker capabilities through a set of plugins. The commonly used ones include:</p>



<ul class="wp-block-list">
<li><strong>Jenkins Cloud Plugin for Docker</strong> – Allows Jenkins to spin up Docker containers as dynamic build agents.</li>
<li><strong>CloudBees Docker Traceability</strong> – Tracks which Docker images were used in which builds for audit and compliance purposes.</li>
<li><strong>CloudBees Docker Hub Notification</strong> – Triggers Jenkins jobs when a new image is pushed to Docker Hub.</li>
<li><strong>CloudBees Docker Build and Publish</strong> – Automates building a Docker image from a <code>Dockerfile</code> and publishing it to a registry as part of a Jenkins job.</li>
<li><strong>CloudBees Docker Pipeline</strong> – Provides Docker-aware steps for use inside a Jenkins Pipeline (<code>Jenkinsfile</code>), enabling fine-grained control over container lifecycle within a declarative or scripted pipeline.</li>
</ul>



<p class="wp-block-paragraph">Each plugin addresses a distinct stage of the pipeline. A typical Jenkins setup uses several of them in combination to cover build, publish, and deploy phases.</p>



<h3 class="wp-block-heading">CircleCI</h3>



<p class="wp-block-paragraph">CircleCI takes a configuration-file approach rather than a plugin model. To enable Docker support, you declare it as a required service in your <code>circle.yml</code> configuration file:</p>


<pre class="wp-block-code"><span><code class="hljs">machine:
  services:
    - docker</code></span></pre>


<p class="wp-block-paragraph">With Docker enabled as a service, you can use standard Docker CLI commands anywhere in your <code>circle.yml</code> build steps, for example:</p>


<pre class="wp-block-code"><span><code class="hljs language-php">test:
  override:
    - docker build -t myapp .
    - docker run myapp ./run-tests.sh

deploy:
  override:
    - docker tag myapp myorg/myapp:$CIRCLE_SHA1
    - docker push myorg/myapp:$CIRCLE_SHA1</code></span></pre>


<p class="wp-block-paragraph">CircleCI triggers these steps automatically based on events it watches for, such as a push to a specific branch or the opening of a pull request.</p>



<p class="wp-block-paragraph"><strong>Note:</strong> CircleCI has since evolved beyond <code>circle.yml</code> to a <code>.circleci/config.yml</code> format with version 2.x and later syntax. The example above reflects the older v1 configuration style described in the original source. Check the current CircleCI documentation for up-to-date syntax.</p>



<h3 class="wp-block-heading">GitLab CI and Other Tools</h3>



<p class="wp-block-paragraph">GitLab CI integrates with Docker through its <code>.gitlab-ci.yml</code> file and the Docker-in-Docker (<code>dind</code>) service or by running jobs inside Docker containers directly. Most modern CI platforms provide first-class Docker support through similar configuration-file mechanisms, making the integration pattern consistent regardless of the tool you choose.</p>



<h2 class="wp-block-heading">Key Benefits at a Glance</h2>



<ul class="wp-block-list">
<li><strong>Environment consistency</strong> – The same Docker image runs in dev, test, and production, eliminating environment drift.</li>
<li><strong>Faster feedback loops</strong> – Automated builds and tests trigger on every commit, catching regressions immediately.</li>
<li><strong>Repeatable deployments</strong> – Immutable container images mean deployments are predictable and rollbacks are straightforward.</li>
<li><strong>Cross-team collaboration</strong> – A shared image registry gives dev, QA, and ops a common artifact to work from.</li>
<li><strong>Scalable build infrastructure</strong> – CI tools can spin Docker containers up and down as ephemeral build agents, optimizing resource usage.</li>
</ul>



<h2 class="wp-block-heading">Getting Started</h2>



<p class="wp-block-paragraph">If you are new to this integration, a practical starting point is:</p>



<ol class="wp-block-list">
<li>Write a <code>Dockerfile</code> for your application if you have not already done so.</li>
<li>Choose a CI tool and create a pipeline configuration file (<code>Jenkinsfile</code>, <code>.circleci/config.yml</code>, <code>.gitlab-ci.yml</code>, etc.).</li>
<li>Add a build step that runs <code>docker build</code>.</li>
<li>Add a test step that runs your test suite inside the built container.</li>
<li>Add a publish step that pushes a tagged image to your registry when tests pass.</li>
<li>Optionally, add a deploy step that pulls the image to your target environment.</li>
</ol>



<p class="wp-block-paragraph">Integrating Docker with your CI tool is one of the highest-leverage steps you can take on the journey to a mature DevOps practice. It brings consistency, automation, and traceability to every stage of your delivery pipeline.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/what-are-the-benefits-of-integrating-a-ci-tool-with-docker/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Using 3 Tiers of Continuous Integration</title>
		<link>https://www.bestdevops.com/using-3-tiers-of-continuous-integration/</link>
					<comments>https://www.bestdevops.com/using-3-tiers-of-continuous-integration/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Tue, 28 Mar 2017 06:14:57 +0000</pubDate>
				<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[Continuous integration environment]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Tier]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=1064</guid>

					<description><![CDATA[Source:- rhonabwy.com Tier your tests Not all tests are equal, and you don’t want to treat them as such. I [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Source:- rhonabwy.com</p>
<p><strong>Tier your tests</strong></p>
<p>Not all tests are equal, and you don’t want to treat them as such. I have found 3 tiers to be extremely effective, assuming you’re working on a system that can have some deep complexity to review.</p>
<p><strong>The first tier: “smoke test”.</strong> Lots of projects have this concept and it is a good one to optimize for. This is where the 10 minute rule that SemaphoreCI is promoting is a fine rule of thumb. You want to verify as much of the most common paths of functionality that you can, within a time-boxed boundary – you pick the time. This is the same tier that I generally encourage for pull request feedback testing, and I try to include all unit testing into this tier, as well as some functional testing and even integration tests. If these tests don’t pass, I’ve generally assumed that a pull request isn’t acceptable for merge – which makes this tier a quality gate.</p>
<p>I also recommend you have a consistent and clearly documented means of letting a developer run all of these tests themselves, without having to resort to your CI system. The CI system provides a needed “source of truth”, but it behooves you to expose all the detail of what this tier does, and how it does it, so that you don’t run into blocks where a developer can’t reproduce the issue locally to debug and resolve it.</p>
<p><strong>The second tier: “regression tests”.</strong> Once you acknowledge that timely feedback is critical and pick a marker, you may start to find some testing scenarios (especially in larger systems) that take longer to validate than the time you’ve allowed. Some you’ll include in the first tier, where you can fit things to the time box you’ve set – but the rest should live somewhere and get run at some point. These are often the corner cases, the regression tests, integration tests, upgrade tests, and so forth. In my experience, running these consistently (or even continuously) is valuable – so this is often the “nightly build &amp; test” sequence. This is the tier that starts “after the fact” feedback, and as you’re building a CI system, you should consider how you want to handle it when something doesn’t pass these tests.</p>
<p>If you’re doing continuous deployment to a web service then I recommend you have this entire set “pass” prior to rolling out software from a staging environment to production. You can batch up commits that have been validated from the first tier, pull them all together, and then only promote to your live service once these have passed.</p>
<p>If you’re developing a service or library that someone else will install and use, then I recommend running these tests continuously on your master or release branch, and if any fail then consider what your process needs to accommodate: Do you want to freeze any additional commits until the tests are fixed? Do you want to revert the offending commits? Or do you open a bug that you consider a “release blocker” that has to be resolved before your next release?</p>
<blockquote><p>An aside here on “<em>flakes</em>“. The reason I recommend running the second tier of tests on a continuous basis is to keep a close eye on an unfortunate reality of complex systems and testing: Flakey Tests. Flakes an invaluable for feedback, and often a complete pain to track down. These are the tests that “mostly pass”, but don’t always return consistently. As you build into more asynchronous systems, these become more prevalent – from insufficient resources (such as CPU, Disk IO or Network IO on your test systems) to race conditions that only appear periodically. I recommend you take the feedback from this tier seriously, and collect information that allows you to identify flakey tests over time. Flakes can happen at any tier, and are the worst in first tier. When I find a flakey test in the first tier, I evaluate if it should “stop the whole train” – freeze the commits until it’s resolved, or if I should move it into a second tier and open a bug. It’s up to you and your development process, but think about how you want to handle it and have a plan.</p></blockquote>
<p><strong>The third tier: “deep regression, matrix and performance tests”</strong>. You may not always have this tier, but if you have acceptance or release validation that takes an extended amount of time (such as over say a few hours) to complete, then consider shifting it back into another tier. This is also the tier where I tend to handle the (time consuming) and complex matrixes when they apply. In my experience, if you’re testing across some matrix or configurations (be that software or hardware), the resources are generally constrained and the testing scenarios head towards asymptotic in terms of time. As a rule of thumb, I don’t include “release blockers” in this tier – it’s more about thoroughly describing your code. Benchmarks, matrix validations that wouldn’t block a release, and performance characterization all fall into this tier. I recommend if you have this tier that you run it prior to ever major release, and if resources allow on a recurring periodic basis to enable you to build trends of system characterizations.</p>
<p>There’s a good argument for “duration testing” that sort of fits between the second and third tiers. If you have tests where you want to validate a system operating over an extended period of time, where you validate availability, recovery, and system resource consumption – like looking for memory leaks – then you might want to consider failing some of these tests as a release blocker. I’ve generally found that I can find memory leaks within a couple of hours, but if you’re working with a system that will deployed where intervention is prohibitively expensive, then you might want to consider duration tests to validate operation and even chaos-monkey style recover of services over longer periods of time. Slow memory leaks, pernicious deadlocks, and distributed system recovery failures are all types of tests that are immensely valuable, but take a long “wall clock” time to run.</p>
<h6>Reporting on your tiers</h6>
<p>As you build our your <a href="http://www.scmgalaxy.com/courses/agenda/devops/continuous-integration-training.html"><strong>continuous integration</strong></a> environment, take the time and plan and implement reporting for your tiers as well. The first tier is generally easiest – it’s what most CI systems do with annotating in pull requests. The second and third third take more time and resources. You want to watch for flakey tests, collecting and analyzing failures. More complex open source systems look towards their release process to help coral this information – OpenStack uses Zuul (unfortunately rather OpenStack specific, but they’re apparently working on that), Kubernetes has Gubernator and TestGrid. When I was at Nebula, we invested in a service that collected and collated test results across all our tiers and reported not just the success/failure of the latest run but also a history of success failure to help us spot those flakes I mentioned above.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/using-3-tiers-of-continuous-integration/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Continuous Integration for Salesforce Using Team Foundation Server (TFS)</title>
		<link>https://www.bestdevops.com/continuous-integration-ci-in-salesforce-using-team-foundation-server-tfs/</link>
					<comments>https://www.bestdevops.com/continuous-integration-ci-in-salesforce-using-team-foundation-server-tfs/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Tue, 21 Mar 2017 09:56:22 +0000</pubDate>
				<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[Continuous Integration in Salesforce]]></category>
		<category><![CDATA[Salesforce]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Team Foundation Server]]></category>
		<category><![CDATA[TFS]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=999</guid>

					<description><![CDATA[A step-by-step guide to setting up Continuous Integration for Salesforce metadata deployments using Microsoft Team Foundation Server (TFS) / Visual Studio Team Services, Apache ANT, and the Salesforce Migration Toolkit.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><em>This guide is based on a walkthrough originally published by Jitendra Zaa at jitendrazaa.com. It covers how to configure Microsoft Team Foundation Server (TFS) — now known as Azure DevOps Server — to run automated Salesforce metadata deployments using Apache ANT and the Salesforce Migration Toolkit.</em></p>



<h2 class="wp-block-heading">Overview</h2>



<p class="wp-block-paragraph">Continuous Integration (CI) for Salesforce metadata differs from traditional software CI because deployments target a cloud platform rather than a compiled binary. The Salesforce Metadata API, exposed through the ANT Migration Toolkit, is the standard mechanism for scripted deployments. By combining TFS (or its cloud-hosted equivalent, Visual Studio Team Services) with Apache ANT, teams can trigger automated retrieve-and-deploy cycles on every code commit or on a schedule.</p>



<p class="wp-block-paragraph">This guide uses the <strong>cloud-hosted</strong> version of TFS (Visual Studio Team Services) to avoid the overhead of maintaining a local TFS installation, but the same build definition steps apply to an on-premises TFS server.</p>



<h2 class="wp-block-heading">Prerequisites</h2>



<ul class="wp-block-list">
<li>A Microsoft account (used to sign in to Visual Studio Team Services)</li>
<li>Apache ANT installed on your local machine for local testing</li>
<li>The Salesforce ANT Migration Toolkit (<code>ant-salesforce.jar</code>), downloaded from your Salesforce org&#8217;s Setup page</li>
<li>A Git client (for example, TortoiseGit) for pushing code to TFS</li>
<li>Credentials for the source and target Salesforce orgs</li>
</ul>



<h2 class="wp-block-heading">Step 1: Create a Developer Account on Visual Studio Team Services</h2>



<p class="wp-block-paragraph">Navigate to <strong>https://www.visualstudio.com/</strong> and choose <em>Get Started for free</em> under the Visual Studio Team Services section. If you do not already have a Microsoft developer account, you will be prompted to create one during sign-up. Once registered, you will land in the VSTS dashboard where you can create your first Team Project.</p>



<h2 class="wp-block-heading">Step 2: Create a TFS Git Repository for Your Salesforce Metadata</h2>



<p class="wp-block-paragraph">One advantage TFS has over Jenkins-based CI setups is that source control is built in — you do not need a separate GitHub or Bitbucket account. After logging in, use the <em>New Project</em> wizard to create a project. The wizard is straightforward: provide a project name, choose a version control type (select <strong>Git</strong>), and choose a process template.</p>



<figure class="wp-block-image"><img decoding="async" src="http://www.jitendrazaa.com/blog/wp-content/uploads/2017/03/Visual-Studio-Team-Foundation-Server-New-Project.png" alt="Visual Studio Team Foundation Server – New Project Screen"/><figcaption>Visual Studio Team Foundation Server – New Project Screen</figcaption></figure>



<p class="wp-block-paragraph">Once the project exists, clone the repository to your local machine using any Git client. For authentication you can use your VSTS username and password, or generate an SSH key pair and register the public key in your VSTS profile under <em>Security &gt; SSH public keys</em>. SSH key authentication is recommended for CI agents because it avoids storing plain-text passwords.</p>



<h2 class="wp-block-heading">Step 3: Create and Test the ANT Deployment Script Locally</h2>



<p class="wp-block-paragraph">Before wiring ANT into TFS, verify that the scripts work correctly on your local workstation. You need two files in the root of your repository: <code>build.properties</code> (credentials and environment URLs) and <code>build.xml</code> (the ANT targets).</p>



<h3 class="wp-block-heading">build.properties</h3>



<p class="wp-block-paragraph">This file stores environment-specific values. Keep it in version control for non-sensitive settings, but consider externalising passwords as TFS build variables or secrets so that plain-text credentials are never committed to source control.</p>


<pre class="wp-block-code"><span><code class="hljs language-php"><span class="hljs-comment"># build.properties</span>

<span class="hljs-comment"># Server URLs</span>
sfSandbox.serverurl = https:<span class="hljs-comment">//test.salesforce.com</span>
sfPRO.serverurl    = https:<span class="hljs-comment">//login.salesforce.com</span>

<span class="hljs-comment"># Source org (retrieve)</span>
sfdc.cb.df14.username        = your-source-org@example.com
sfdc.cb.df14.password        = yourPasswordPlusSecurityToken
sfdc.cb.df14.retrieveTarget  = src
sfdc.cb.df14.unpackaged      = src/package.xml
sfdc.cb.df14.retrieveMessage = Retrieve metadata from source Salesforce org

<span class="hljs-comment"># Target org (deploy)</span>
sfdc.cb.df15.username        = your-target-org@example.com
sfdc.cb.df15.password        = yourPasswordPlusSecurityToken
sfdc.cb.df15.retrieveTarget  = src
sfdc.cb.df15.unpackaged      = src/package.xml
sfdc.cb.df15.retrieveMessage = Deploy metadata to target Salesforce org

<span class="hljs-comment"># Salesforce ANT JAR — path relative to repository root</span>
sfdcJarFile = ant-salesforce.jar</code></span></pre>


<h3 class="wp-block-heading">build.xml</h3>



<p class="wp-block-paragraph">The <code>build.xml</code> file defines two ANT targets: <code>df14</code> retrieves metadata from the source org, and <code>deploy</code> pushes that metadata to the target org. Notice that <code>classpath</code> points to <code>${sfdcJarFile}</code>, which resolves to a path <em>relative to the repository root</em>. This is essential for cloud CI agents that have no pre-installed copy of the Salesforce JAR, so the JAR must be committed to the repository alongside the build scripts.</p>


<pre class="wp-block-code"><span><code class="hljs language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">project</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Deployment Scripts"</span> <span class="hljs-attr">default</span>=<span class="hljs-string">"deploy"</span> <span class="hljs-attr">basedir</span>=<span class="hljs-string">"."</span> <span class="hljs-attr">xmlns:sf</span>=<span class="hljs-string">"antlib:com.salesforce"</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">file</span>=<span class="hljs-string">"build.properties"</span>/&gt;</span>

    <span class="hljs-comment">&lt;!-- Retrieve metadata from source org --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">target</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"df14"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">taskdef</span> <span class="hljs-attr">resource</span>=<span class="hljs-string">"com/salesforce/antlib.xml"</span>
                 <span class="hljs-attr">uri</span>=<span class="hljs-string">"antlib:com.salesforce"</span>
                 <span class="hljs-attr">classpath</span>=<span class="hljs-string">"${sfdcJarFile}"</span>/&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">echo</span> <span class="hljs-attr">message</span>=<span class="hljs-string">"Retrieving as: ${sfdc.cb.df14.username}"</span>/&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">sf:retrieve</span>
            <span class="hljs-attr">username</span>=<span class="hljs-string">"${sfdc.cb.df14.username}"</span>
            <span class="hljs-attr">password</span>=<span class="hljs-string">"${sfdc.cb.df14.password}"</span>
            <span class="hljs-attr">serverurl</span>=<span class="hljs-string">"${sfPRO.serverurl}"</span>
            <span class="hljs-attr">retrieveTarget</span>=<span class="hljs-string">"${sfdc.cb.df14.retrieveTarget}"</span>
            <span class="hljs-attr">unpackaged</span>=<span class="hljs-string">"${sfdc.cb.df14.unpackaged}"</span>/&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">target</span>&gt;</span>

    <span class="hljs-comment">&lt;!-- Deploy metadata to target org --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">target</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"deploy"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">taskdef</span> <span class="hljs-attr">resource</span>=<span class="hljs-string">"com/salesforce/antlib.xml"</span>
                 <span class="hljs-attr">uri</span>=<span class="hljs-string">"antlib:com.salesforce"</span>
                 <span class="hljs-attr">classpath</span>=<span class="hljs-string">"${sfdcJarFile}"</span>/&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">sf:deploy</span>
            <span class="hljs-attr">username</span>=<span class="hljs-string">"${sfdc.cb.df15.username}"</span>
            <span class="hljs-attr">password</span>=<span class="hljs-string">"${sfdc.cb.df15.password}"</span>
            <span class="hljs-attr">serverurl</span>=<span class="hljs-string">"${sfPRO.serverurl}"</span>
            <span class="hljs-attr">deployRoot</span>=<span class="hljs-string">"src"</span>
            <span class="hljs-attr">maxPoll</span>=<span class="hljs-string">"1000"</span>
            <span class="hljs-attr">testLevel</span>=<span class="hljs-string">"NoTestRun"</span>
            <span class="hljs-attr">checkOnly</span>=<span class="hljs-string">"false"</span>
            <span class="hljs-attr">pollWaitMillis</span>=<span class="hljs-string">"10000"</span>
            <span class="hljs-attr">rollbackOnError</span>=<span class="hljs-string">"true"</span>/&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">target</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">project</span>&gt;</span></code></span></pre>


<p class="wp-block-paragraph">To test locally, run the following command from the repository root:</p>


<pre class="wp-block-code"><span><code class="hljs">ant df14 deploy</code></span></pre>


<p class="wp-block-paragraph">The <code>df14</code> target retrieves metadata from the source Salesforce instance; the <code>deploy</code> target then pushes that retrieved metadata to the target instance. Confirm that both targets complete without errors before moving to the TFS build definition.</p>



<h3 class="wp-block-heading">Files to commit to the repository</h3>



<ul class="wp-block-list">
<li><code>build.xml</code></li>
<li><code>build.properties</code> (with passwords replaced by TFS build variables in production)</li>
<li><code>ant-salesforce.jar</code> — the Salesforce Migration Toolkit JAR, committed so the TFS cloud agent can find it</li>
<li><code>src/package.xml</code> — your metadata manifest</li>
<li><code>src/</code> — the retrieved metadata directory</li>
</ul>



<h2 class="wp-block-heading">Step 4: Create a New Build Definition in Team Foundation Server</h2>



<p class="wp-block-paragraph">With the scripts in the repository, you can now tell TFS how to run them automatically.</p>



<p class="wp-block-paragraph">In the VSTS portal, navigate to <strong>Build &amp; Release → Builds → New definition</strong> and select the <strong>ANT</strong> template.</p>



<figure class="wp-block-image"><img decoding="async" src="http://www.jitendrazaa.com/blog/wp-content/uploads/2017/03/Team-Foundation-Server-TFS-New-Build-definition-1024x804.png" alt="Team Foundation Server (TFS) – New Build definition"/><figcaption>Team Foundation Server (TFS) – New Build definition</figcaption></figure>



<h3 class="wp-block-heading">Select the repository and branch</h3>



<p class="wp-block-paragraph">On the repository selection screen, choose your TFS-hosted Git repository. You can also connect to GitHub, a remote Git server, or SVN if your code lives elsewhere. Select the branch you want this build definition to monitor. TFS supports multiple build definitions per project, so you can configure, for example, a nightly build on <code>main</code> and a triggered build on a <code>develop</code> branch independently.</p>



<figure class="wp-block-image"><img decoding="async" src="http://www.jitendrazaa.com/blog/wp-content/uploads/2017/03/Team-Foundation-Server-TFS-New-Build-definition-Select-repository.png" alt="Team Foundation Server (TFS) – New Build definition – Select repository"/><figcaption>Team Foundation Server (TFS) – New Build definition – Select repository</figcaption></figure>



<h3 class="wp-block-heading">Configure the ANT build step</h3>



<p class="wp-block-paragraph">In the build steps editor, configure the ANT task:</p>



<ul class="wp-block-list">
<li><strong>ANT build file</strong>: <code>build.xml</code></li>
<li><strong>Options</strong>: specify the targets to run, for example <code>df14 deploy</code>, or leave blank to use the default target defined in <code>build.xml</code></li>
<li><strong>JDK version</strong>: ensure a compatible JDK is selected on the build agent</li>
</ul>



<figure class="wp-block-image"><img decoding="async" src="http://www.jitendrazaa.com/blog/wp-content/uploads/2017/03/Team-Foundation-Server-TFS-New-Build-definition-add-build-steps-1024x594.png" alt="Team Foundation Server (TFS) – New Build definition – add build steps"/><figcaption>Team Foundation Server (TFS) – New Build definition – add build steps</figcaption></figure>



<p class="wp-block-paragraph">Save the build definition. You can trigger it manually the first time using the <em>Queue build</em> button to confirm everything works end to end before enabling a continuous integration trigger.</p>



<h2 class="wp-block-heading">Security Considerations</h2>



<p class="wp-block-paragraph">Storing Salesforce credentials in <code>build.properties</code> and committing that file to source control is convenient for demonstration purposes but is a security risk in production. Instead:</p>



<ul class="wp-block-list">
<li>Define Salesforce usernames and passwords as <strong>TFS/VSTS build variables</strong> marked as secret. Reference them in <code>build.xml</code> using ANT property overrides passed via the build options field (e.g., <code>-Dsfdc.cb.df15.password=$(SF_PASSWORD)</code>).</li>
<li>Use a <strong>connected app with OAuth</strong> and a session ID instead of username/password where your tooling supports it.</li>
<li>Consider whether committing <code>ant-salesforce.jar</code> to Git is appropriate for your organisation; an alternative is to download it as an artifact during the build using a script step.</li>
</ul>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">Setting up Salesforce CI with TFS involves four main steps: creating a VSTS account and project, pushing your Salesforce metadata and ANT scripts (including the Salesforce JAR) to the built-in Git repository, validating the ANT script locally, and then creating an ANT build definition in TFS that executes the same script on every commit or on a schedule. The integrated source control in TFS/VSTS reduces the number of third-party tools required compared to a Jenkins-based approach, making it a practical choice for teams already in the Microsoft ecosystem.</p>



<p class="wp-block-paragraph"><em>Original source: jitendrazaa.com</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/continuous-integration-ci-in-salesforce-using-team-foundation-server-tfs/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Continuous Integration Testing with Jenkins</title>
		<link>https://www.bestdevops.com/continuous-integration-testing-with-jenkins/</link>
					<comments>https://www.bestdevops.com/continuous-integration-testing-with-jenkins/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Wed, 01 Mar 2017 06:38:27 +0000</pubDate>
				<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[DevOps Tools]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[CI with Jenkins]]></category>
		<category><![CDATA[Continuous Integration With Jenkins]]></category>
		<category><![CDATA[Jenkin pipeline]]></category>
		<category><![CDATA[Jenkins]]></category>
		<category><![CDATA[Jenkins Testing]]></category>
		<category><![CDATA[QA Testing]]></category>
		<category><![CDATA[Software Development]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=840</guid>

					<description><![CDATA[In software development and testing fields, Continuous Integration (CI) is an exercise of combining all development work to a shared [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>In software development and testing fields, Continuous Integration (CI) is an exercise of combining all development work to a shared main server several times a day.  The goal of CI is to reduce time and effort required for a product launch. The process of continuous integration is achieved with the help of version control, strategies &amp; contracts and special tools.</p>
<p><a href="http://www.scmgalaxy.com/courses/agenda/continous-integration-tools/jenkins-training.html"><em>One of the famous tools used for CI testing is <strong>Jenkins</strong>.</em></a><span id="more-6937"></span></p>
<blockquote><p><strong>“Jenkins is an open source automation tool, which can be used to program all categories of tasks such as building, testing, and deploying software. Jenkins can be installed through native system packages, Docker, or even run standalone by any machine with the Java Run-time Environment installed.”</strong></p></blockquote>
<p>It helps to automate the non-human part of the software development life-cycle.</p>
<p>Jenkin pipeline is a package of plugins used for implementing the CI process in the delivery pipeline. Extensive set of tools are available with pipeline for modelling simple to complex delivery pipelines. It is a server based tool, which runs on Java servlet such as Apache Tomcat. It supports source control management such as AccuRev, CVS, Git, Mercurial, Subversion, RTC, Perforce and Clearcase.</p>
<p>There are a lot of plugins released for Jenkins to extend its use to projects, which are written in various languages besides Java.</p>
<p>Below is the flow diagram to explain how continuous integration testing can be done with Jenkins.</p>
<p><img fetchpriority="high" decoding="async" class="size-full wp-image-7029 aligncenter" src="http://www.indiumsoft.com/Blog/wp-content/uploads/2017/02/jenkins-automation-steps.png" sizes="(max-width: 584px) 100vw, 584px" srcset="http://www.indiumsoft.com/Blog/wp-content/uploads/2017/02/jenkins-automation-steps-300x173.png 300w, http://www.indiumsoft.com/Blog/wp-content/uploads/2017/02/jenkins-automation-steps.png 584w" alt="jenkins automation steps" width="584" height="336" /></p>
<h1>Now let’s take a look how to configure and manage Jenkins</h1>
<p class="sh">Step 1</p>
<p>Download Jenkins from the website <a href="https://jenkins.io/" target="_blank" rel="noopener">https://jenkins.io</a></p>
<p class="sh">Step 2</p>
<p>Login to the Jenkins<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-6975" src="http://www.indiumsoft.com/Blog/wp-content/uploads/2017/02/jenkins-open-source-automation-tool-1.jpg" alt="jenkins-open-source-automation-tool-1" width="1201" height="675" /></p>
<p><strong>E-Mail Configuration:</strong></p>
<p class="sh">Step 3</p>
<p>Click on ‘Manage Jenkins’ link<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-6975" src="http://www.indiumsoft.com/Blog/wp-content/uploads/2017/02/jenkins-open-source-automation-tool-2.jpg" alt="jenkins-open-source-automation-tool-2" width="1201" height="675" /></p>
<p class="sh">Step 4</p>
<p>Click on ‘Configure System’ link<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-6975" src="http://www.indiumsoft.com/Blog/wp-content/uploads/2017/02/jenkins-open-source-automation-tool-3.jpg" alt="jenkins-open-source-automation-tool-3" width="1201" height="675" /></p>
<p class="sh">Step 5</p>
<p>Configure the fields given as screenshot<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-6975" src="http://www.indiumsoft.com/Blog/wp-content/uploads/2017/02/jenkins-open-source-automation-tool-4.jpg" alt="jenkins-open-source-automation-tool-4" width="1201" height="675" /></p>
<p class="sh">Step 6</p>
<p>Enter ‘System Admin’ Email Id<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-6975" src="http://www.indiumsoft.com/Blog/wp-content/uploads/2017/02/jenkins-open-source-automation-tool-5.jpg" alt="jenkins-open-source-automation-tool-5" width="1201" height="675" /></p>
<p class="sh">Step 7</p>
<p>Enter the following fields on the ‘Extended Email Notification section –Ref’ screenshot</p>
<p><strong>SMTP Server: </strong>smtp.gmail.com</p>
<p><strong>Default user E-mail suffix: </strong>@gmail.com</p>
<p><strong>Default Recipients:</strong> your123@gmail.com</p>
<p><strong>Reply To List:</strong> noreply@gmail.com</p>
<p><strong>Default Content Type</strong>: $PROJECT_NAME – Build # $BUILD_NUMBER – $BUILD_STATUS!</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-6975" src="http://www.indiumsoft.com/Blog/wp-content/uploads/2017/02/jenkins-open-source-automation-tool-6.jpg" alt="jenkins-open-source-automation-tool-6" width="1201" height="675" /></p>
<p class="sh">Step 8</p>
<p>Select the checkbox option given on the screen shot to Trigger the Email<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-6975" src="http://www.indiumsoft.com/Blog/wp-content/uploads/2017/02/jenkins-open-source-automation-tool-7.jpg" alt="jenkins-open-source-automation-tool-7" width="1201" height="675" /></p>
<p class="sh">Step 9</p>
<p>Enter the fields on the ‘E-mail Notification’ section as given on the screenshot</p>
<p>Select ‘Test Configuration’ checkbox then click on ‘Test Configuration’ button. You will get success message like – “Email was successfully sent” [if you get this message means you have configured successfully] then Click on ‘Save’ button.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-6975" src="http://www.indiumsoft.com/Blog/wp-content/uploads/2017/02/jenkins-open-source-automation-tool-8.jpg" alt="jenkins-open-source-automation-tool-8" width="1201" height="675" /></p>
<h1><strong>Steps to create a new Project in Jenkins and Project Configuration</strong></h1>
<p class="sh">Step 1</p>
<p>Go to Jenkins -&gt; New Item</p>
<p class="sh">Step 2</p>
<p>Enter project name and select ‘Freestyle Project’ then click on ‘OK’ button<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-6975" src="http://www.indiumsoft.com/Blog/wp-content/uploads/2017/02/jenkins-open-source-automation-tool-8.jpg" alt="jenkins-open-source-automation-tool-8" width="1201" height="675" /></p>
<p class="sh">Step 3</p>
<p>Click on tab ‘General’</p>
<p class="sh">Step 4</p>
<p>Set the time on ‘Build Trigger’ Section<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-6975" src="http://www.indiumsoft.com/Blog/wp-content/uploads/2017/02/jenkins-open-source-automation-tool-9.jpg" alt="jenkins-open-source-automation-tool-9" width="1201" height="675" /></p>
<p>Example Time:</p>
<blockquote><p># every fifteen minutes (perhaps at :07, :22, :37, :52)</p>
<p>H/15 * * * *</p>
<p># every ten minutes in the first half of every hour (three times, perhaps at :04, :14, :24)</p>
<p>H(0-29)/10 * * * *</p>
<p># once every two hours at 45 minutes past the hour starting at 9:45 AM and finishing at 3:45 PM every weekday.</p>
<p>45 9-16/2 * * 1-5</p>
<p># once in every two hours slot between 9 AM and 5 PM every weekday (perhaps at 10:38 AM, 12:38 PM, 2:38 PM, 4:38 PM)</p>
<p>H H(9-16)/2 * * 1-5</p>
<p># once a day on the 1st and 15th of every month except December</p>
<p>H H 1,15 1-11 *</p></blockquote>
<p class="sh">Step 5</p>
<p>Enter the name of your <strong>.bat</strong> file on the ‘Build’ section<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-6975" src="http://www.indiumsoft.com/Blog/wp-content/uploads/2017/02/jenkins-open-source-automation-tool-10.jpg" alt="jenkins-open-source-automation-tool-10" width="1201" height="675" /></p>
<p class="sh">Step 6</p>
<p>Fill the field on the ‘Post-build Actions’ section given as screenshot<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-6975" src="http://www.indiumsoft.com/Blog/wp-content/uploads/2017/02/jenkins-open-source-automation-tool-11.jpg" alt="jenkins-open-source-automation-tool-11" width="1201" height="675" /><br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-6975" src="http://www.indiumsoft.com/Blog/wp-content/uploads/2017/02/jenkins-open-source-automation-tool-12.jpg" alt="jenkins-open-source-automation-tool-12" width="1201" height="675" /></p>
<p class="sh">Step 7</p>
<p>Click on ‘Save’ button</p>
<p class="sh">Step 8</p>
<p>Click on your Project then click -&gt; Build Now; you will get the ‘<a href="http://localhost:8080/computer/">Build Executor Status</a>’ as following screenshot.<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-6975" src="http://www.indiumsoft.com/Blog/wp-content/uploads/2017/02/jenkins-open-source-automation-tool-13.jpg" alt="jenkins-open-source-automation-tool-13" width="1201" height="675" /></p>
<p class="sh">Step 9</p>
<p>Once if the build get completed click on the build number then view the console output<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-6975" src="http://www.indiumsoft.com/Blog/wp-content/uploads/2017/02/jenkins-open-source-automation-tool-14.jpg" alt="jenkins-open-source-automation-tool-14" width="1201" height="675" /></p>
<p class="sh">Step 10</p>
<p>The console output will be following screenshot<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-6975" src="http://www.indiumsoft.com/Blog/wp-content/uploads/2017/02/jenkins-open-source-automation-tool-16.jpg" alt="jenkins-open-source-automation-tool-16" width="1201" height="675" /></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/continuous-integration-testing-with-jenkins/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Continuous Integration with GitLab: A Practical Migration from Jenkins</title>
		<link>https://www.bestdevops.com/continuous-integration-with-gitlab/</link>
					<comments>https://www.bestdevops.com/continuous-integration-with-gitlab/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Wed, 22 Feb 2017 05:32:47 +0000</pubDate>
				<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[DevOps Best Practices]]></category>
		<category><![CDATA[DevOps Tools]]></category>
		<category><![CDATA[Build infrastructure]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[GitLab]]></category>
		<category><![CDATA[Jenkins]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=744</guid>

					<description><![CDATA[Learn how one team migrated from Jenkins to GitLab CI, covering .gitlab-ci.yml pipeline configuration, docker-in-docker challenges, Unix socket workarounds, and the GitLab Container Registry.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><em>This article is based on a real-world migration experience from Team Alfonzó, originally published on 126kr.com, describing their move from Jenkins and DockerHub to GitLab CI and the GitLab Container Registry.</em></p>



<h2 class="wp-block-heading">Why Migrate from Jenkins to GitLab CI?</h2>



<p class="wp-block-paragraph">Jenkins has long been a staple of continuous integration pipelines, but as teams grow and infrastructure scales, its centralized architecture can become a bottleneck. Team Alfonzó, working alongside their Build Team, decided to explore a more distributed build infrastructure. Their Implementation Wizard project became the test bed for adopting GitLab CI and the GitLab Container Registry — replacing both Jenkins and DockerHub in their workflow.</p>



<h2 class="wp-block-heading">GitLab CI vs. Jenkins: Pipeline Configuration Compared</h2>



<p class="wp-block-paragraph">If you have written a Jenkinsfile using Groovy-based DSL, you will likely find GitLab CI&#8217;s approach cleaner and more immediately readable. Instead of writing pipeline logic in Groovy, GitLab CI uses a <code>.gitlab-ci.yml</code> file checked into the root of your repository. In this YAML file you declare your build stages and the shell scripts that run at each stage.</p>



<h3 class="wp-block-heading">Example .gitlab-ci.yml Structure</h3>


<pre class="wp-block-code"><span><code class="hljs language-php">stages:
  - build
  - test
  - deploy

build-job:
  stage: build
  script:
    - docker build -t my-app:$CI_COMMIT_SHA .

test-job:
  stage: test
  script:
    - docker run my-app:$CI_COMMIT_SHA ./run-tests.sh

deploy-job:
  stage: deploy
  script:
    - kubectl apply -f deployment.yaml
  only:
    - main</code></span></pre>


<p class="wp-block-paragraph">The YAML syntax enforces a sensible structure while still giving you enough flexibility to configure each stage independently. The tradeoff is that there is no built-in way to test or lint your pipeline scripts locally without committing and pushing changes to the repository. Teams should be aware of this limitation early on to avoid cluttering the commit history with purely experimental CI changes. (Third-party tools such as <code>gitlab-ci-local</code> have since emerged to help with local pipeline testing, though they were not part of this original migration.)</p>



<h2 class="wp-block-heading">Setting Up a GitLab Runner</h2>



<p class="wp-block-paragraph">A <code>.gitlab-ci.yml</code> file alone does nothing without a GitLab Runner — the agent that picks up jobs and executes them. Team Alfonzó registered a dedicated runner running inside a Docker container. This gave the team full control over the runner environment, though it comes with a resource cost compared to using shared runners provided by GitLab.</p>



<p class="wp-block-paragraph">If multiple teams share a codebase or similar build requirements, shared runners are worth considering as a more resource-efficient option. Dedicated runners make the most sense when you need a specific environment, custom tooling, or tighter security boundaries.</p>



<h2 class="wp-block-heading">Bypassing Docker-in-Docker Difficulties</h2>



<p class="wp-block-paragraph">A common challenge when running Docker-based CI pipelines is the need to build Docker images from <em>within</em> a Docker container — a pattern known as Docker-in-Docker (DinD). GitLab officially supports DinD using the <code>docker:dind</code> service image, but in Team Alfonzó&#8217;s environment this approach did not work reliably.</p>



<h3 class="wp-block-heading">The Unix Socket Workaround</h3>



<p class="wp-block-paragraph">To work around the DinD limitation, the team configured the Docker API to share the same Unix socket between the runner container and the stage container (the container that actually executes build steps). This is done by mounting the host Docker socket into the runner container:</p>


<pre class="wp-block-code"><span><code class="hljs language-php"><span class="hljs-comment"># When registering the GitLab Runner, pass the socket mount:</span>
docker run -d \
  --name gitlab-runner \
  -v /<span class="hljs-keyword">var</span>/run/docker.sock:/<span class="hljs-keyword">var</span>/run/docker.sock \
  -v /srv/gitlab-runner/config:/etc/gitlab-runner \
  gitlab/gitlab-runner:latest</code></span></pre>


<p class="wp-block-paragraph">By mounting <code>/var/run/docker.sock</code> from the host into the runner container, and then propagating that same socket mount into stage containers, both containers communicate with the same Docker daemon. This sidesteps the need to run a nested Docker daemon entirely.</p>




<p class="wp-block-paragraph"><strong>Security note:</strong> Mounting the Docker socket grants the container root-equivalent access to the host. This approach is acceptable in controlled, trusted CI environments but should be carefully evaluated before use in multi-tenant or public-facing setups.</p>




<h3 class="wp-block-heading">Data Volumes and Kubernetes Deployment</h3>



<p class="wp-block-paragraph">Even with the socket sharing workaround in place, the team found that Docker containers running build stages could not accept data volumes mounted from outside. This created a specific problem during Kubernetes deployments: the deployment manifest file could not be injected via a volume mount into the stage container.</p>



<p class="wp-block-paragraph">The solution was to use <code>kubectl</code>&#8216;s ability to read configuration from standard input rather than from a file path:</p>


<pre class="wp-block-code"><span><code class="hljs language-php"><span class="hljs-comment"># Pass a Kubernetes manifest via stdin instead of a file</span>
cat deployment.yaml | kubectl apply -f -</code></span></pre>


<p class="wp-block-paragraph">This pattern works reliably when volume mounts are unavailable and is a useful technique in any containerized CI environment where file system sharing between containers is restricted.</p>



<h2 class="wp-block-heading">Hosting Docker Images with the GitLab Container Registry</h2>



<p class="wp-block-paragraph">GitLab includes an integrated Container Registry that can host Docker images built from your projects. For Team Alfonzó, this proved more convenient than DockerHub for several reasons:</p>



<ul class="wp-block-list">
<li><strong>Granular access control:</strong> Registry permissions follow the existing GitLab project permissions model, meaning developers already have appropriately scoped access without a separate admin workflow.</li>
<li><strong>Reduced friction:</strong> No need to manage separate DockerHub credentials or request registry creation from a small group of administrators.</li>
<li><strong>Tighter integration:</strong> Images built and pushed during a CI pipeline are immediately visible and accessible within the same GitLab project.</li>
</ul>



<p class="wp-block-paragraph">A typical pipeline stage to build and push an image to the GitLab Registry looks like this:</p>


<pre class="wp-block-code"><span><code class="hljs language-php">build-<span class="hljs-keyword">and</span>-push:
  stage: build
  script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA</code></span></pre>


<p class="wp-block-paragraph">GitLab automatically provides the predefined CI variables <code>$CI_REGISTRY</code>, <code>$CI_REGISTRY_USER</code>, <code>$CI_REGISTRY_PASSWORD</code>, and <code>$CI_REGISTRY_IMAGE</code>, so no manual credential management is needed for standard project pipelines.</p>



<h3 class="wp-block-heading">Known Limitation: One Registry per Project</h3>



<p class="wp-block-paragraph">At the time of this migration, the team noted that GitLab&#8217;s registry did not support hosting multiple distinct images under a single project — a limitation that surfaced particularly for projects with external dependencies. This issue was reported to the GitLab team. GitLab&#8217;s registry has evolved significantly since 2017, so teams evaluating it today should consult the current GitLab documentation for the latest capabilities.</p>



<h2 class="wp-block-heading">Conclusion</h2>



<p class="wp-block-paragraph">GitLab CI offers a compelling alternative to Jenkins for teams already using GitLab for source control. The YAML-based pipeline configuration is readable and maintainable, the integrated Container Registry removes the need for a separate image hosting service, and the GitLab Runner architecture supports both shared and dedicated execution environments.</p>



<p class="wp-block-paragraph">The main challenges encountered — Docker-in-Docker limitations and restricted data volume access in nested containers — each have workable solutions. The Unix socket mount approach and the use of <code>kubectl</code> stdin input are practical patterns that apply well beyond this specific migration scenario.</p>



<p class="wp-block-paragraph">For teams experiencing high load on a shared Jenkins instance or looking to consolidate their toolchain, GitLab CI is a mature, well-integrated option worth evaluating.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/continuous-integration-with-gitlab/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>SQL Server Database Continuous Integration (CI): Best Practices for Testing, Processing, and Automation</title>
		<link>https://www.bestdevops.com/sql-server-database-continuous-integration-ci-best-practices-and-how-to-implement-them-testing-processing-and-automation/</link>
					<comments>https://www.bestdevops.com/sql-server-database-continuous-integration-ci-best-practices-and-how-to-implement-them-testing-processing-and-automation/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Mon, 13 Feb 2017 06:38:11 +0000</pubDate>
				<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[DevOps Best Practices]]></category>
		<category><![CDATA[DevOps Tools]]></category>
		<category><![CDATA[Automation]]></category>
		<category><![CDATA[Best practices]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Implementation]]></category>
		<category><![CDATA[Processing]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Testing]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=635</guid>

					<description><![CDATA[A practical guide to implementing SQL Server database CI pipelines — covering unit testing strategies, synthetic test data, pipeline failure handling, build frequency governance, and secure automation scripting.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Continuous Integration (CI) for SQL Server databases introduces challenges that application-code CI does not always share — schema migrations, referential integrity, test data management, and the inherent statefulness of a relational database. This article covers actionable best practices across three phases of a database CI pipeline: <strong>Testing</strong>, <strong>Processing</strong>, and <strong>Automation</strong>.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img decoding="async" src="https://www.bestdevops.com/wp-content/uploads/2017/02/test-databases.jpg" alt="Test databases and CI pipelines" /></figure>
</div>


<h2 class="wp-block-heading">Testing</h2>



<h3 class="wp-block-heading">Run Unit Tests Against a Reconstituted QA Database</h3>



<p class="wp-block-paragraph">A common approach for application code is to run unit tests at the point of each commit. For databases, a more reliable pattern is to run the full unit test suite sequentially against a fully reconstituted QA database as a dedicated <em>Test</em> step in the CI pipeline — rather than against an individual developer&#8217;s local environment.</p>



<p class="wp-block-paragraph">This introduces a small lag compared to per-commit testing, but frequent CI iterations largely close that gap. The key advantage is that unit tests execute against a known, reproducible database state rather than a developer&#8217;s potentially dirty working copy.</p>



<p class="wp-block-paragraph">Tools such as <a href="https://apexsql.com/">ApexSQL Unit Test</a> integrate with the <a href="https://tsqlt.org/">tSQLt framework</a> to author and execute SQL Server unit tests from the command line, making them suitable for inclusion in any automated pipeline.</p>



<h3 class="wp-block-heading">Keep Unit Tests and Test Scripts in Source Control</h3>



<p class="wp-block-paragraph">Test scripts are first-class artifacts and must be version-controlled alongside the database objects they test. Store them in a dedicated branch or folder (e.g., <code>/tests</code>) within your repository to prevent them from being accidentally deployed to production. The <em>Build</em> step should pull the correct revision of both the schema scripts and the test scripts before executing either.</p>



<p class="wp-block-paragraph">This approach guarantees that every change to a test is tracked, reviewable, and automatically included in the next build without manual intervention.</p>



<h3 class="wp-block-heading">Never Use Production Data for Testing</h3>



<p class="wp-block-paragraph">Pulling a copy of production data into a QA or CI environment is tempting as a shortcut, but it creates two significant problems:</p>



<ul class="wp-block-list">
<li><strong>Pipeline direction violation.</strong> A well-structured CI/CD pipeline flows in one direction — from a clean baseline toward production. Reading from production to seed a lower environment reverses this flow and introduces an uncontrolled dependency on production state.</li>
<li><strong>Privacy and compliance risk.</strong> Real customer or business data exposed to developers, contractors, or CI agents can violate data-protection regulations and internal security policies.</li>
</ul>



<p class="wp-block-paragraph">The correct approach is to generate <strong>synthetic test data</strong> programmatically. A data generation tool or script should be able to populate transactional tables with configurable volumes of randomized, realistic data on demand. Static reference data (lookup tables, enumeration tables) should be seeded from source control as part of the Build step. Tools such as ApexSQL Generate are purpose-built for this Populate step, but a well-crafted T-SQL or PowerShell script can serve the same role.</p>



<h3 class="wp-block-heading">Unit Tests Must Return a Machine-Readable Pass/Fail Result</h3>



<p class="wp-block-paragraph">A test run that produces a human-readable HTML summary is not useful in an automated pipeline. Every test execution must return a numeric exit/return code that the calling process can evaluate without string parsing. A non-zero return code on failure allows the pipeline orchestrator (Jenkins, Azure DevOps, TeamCity, a PowerShell script, etc.) to abort subsequent steps immediately.</p>



<p class="wp-block-paragraph">When selecting or writing a test runner, verify that it surfaces OS-level exit codes — not just log files or report files.</p>



<h3 class="wp-block-heading">Define a Failure Threshold, Not a 100% Pass Requirement</h3>



<p class="wp-block-paragraph">Requiring 100% of all tests to pass before a build is considered green may seem like a high standard, but in practice it forces manual review of results on every single test failure — defeating the purpose of automation. A more practical approach uses configurable thresholds:</p>



<ul class="wp-block-list">
<li>Fail the build if fewer than <em>X</em>% of tests pass (e.g., 80%).</li>
<li>Optionally, always fail on specific high-priority or smoke tests regardless of the overall pass rate.</li>
</ul>



<p class="wp-block-paragraph">This allows minor, known-flaky tests to be tolerated temporarily without blocking the pipeline, while still catching regressions that cross a meaningful threshold.</p>



<h2 class="wp-block-heading">Processing</h2>



<h3 class="wp-block-heading">Every Pipeline Step Must Return a Clear Success or Failure</h3>



<p class="wp-block-paragraph">This applies to every step in the pipeline — schema build, static analysis, data population, unit tests, integration tests. Each step must emit a machine-consumable result (typically an OS exit code) so the orchestrator can decide whether to proceed or abort. Steps that only log output and always exit with code 0 are pipeline liabilities.</p>



<p class="wp-block-paragraph">Audit each tool and script in your pipeline against this criterion before integrating it.</p>



<h3 class="wp-block-heading">Abort the Pipeline on Any Failure — Do Not Continue Past a Broken Step</h3>



<p class="wp-block-paragraph">Database CI pipelines can involve many sequential steps, and if parallel pipelines are spawned (e.g., one for unit tests, one for performance/load tests, one for policy compliance checks), total execution time can be substantial. Allowing a pipeline to continue past a known failure wastes compute resources and produces misleading results downstream.</p>



<p class="wp-block-paragraph">Configure your orchestrator to <strong>fail fast</strong>: abort and notify on the first step that returns a failure code. Immediate email or messaging notification to the team should be triggered at this point, including as much diagnostic detail as the failing step can provide.</p>



<h3 class="wp-block-heading">Implement a Circuit Breaker to Block Subsequent Builds After a Failure</h3>



<p class="wp-block-paragraph">A failed build that is not fixed before the next scheduled run will cause every subsequent run to fail as well, consuming resources and filling notification queues with noise. Implement a circuit-breaker pattern:</p>



<ol class="wp-block-list">
<li>On failure, set a flag (e.g., a value in a configuration table or a flag file) that prevents the CI job from starting.</li>
<li>A manual trigger can bypass the circuit breaker to allow a hotfix run.</li>
<li>A successful completion automatically resets the flag.</li>
</ol>



<p class="wp-block-paragraph">This is a lightweight but effective safeguard against runaway failures in unattended overnight pipelines.</p>



<h3 class="wp-block-heading">Send Targeted Notifications at Pipeline Start, Completion, and Failure</h3>



<p class="wp-block-paragraph">Notification strategy matters. Over-notifying desensitizes the team; under-notifying leaves failures unaddressed. A practical model:</p>



<ul class="wp-block-list">
<li><strong>Pipeline start:</strong> Notify QA only (so they know the current build may be temporarily unavailable or in flux).</li>
<li><strong>Successful completion:</strong> Notify QA only (so they can begin testing the new build).</li>
<li><strong>Failure:</strong> Notify the full team — developers, QA, and manager — with as much detail about the failing step as possible.</li>
</ul>



<p class="wp-block-paragraph">Where the pipeline environment supports it, build QA environments as a <em>new</em> environment rather than overwriting the existing one, so QA is never completely blocked during a build run.</p>



<h3 class="wp-block-heading">Build Frequency Should Not Exceed Build Duration</h3>



<p class="wp-block-paragraph">Do not trigger a new build more frequently than it takes for the previous build to complete. If a full pipeline run takes 45 minutes, the minimum build interval should be 45 minutes. Commits arriving during a build window should be queued and incorporated into the <em>next</em> build rather than triggering an overlapping run.</p>



<p class="wp-block-paragraph">This avoids pipeline collisions, prevents resource contention on the CI agent and database server, and eliminates arbitrary check-in blackout windows for developers.</p>



<h3 class="wp-block-heading">The CI Process Must Support Three Execution Modes</h3>



<ol class="wp-block-list">
<li><strong>Manual trigger</strong> — for hotfix validation, ad-hoc testing, or circuit-breaker bypass.</li>
<li><strong>Scheduled trigger</strong> — time-based (e.g., every hour, nightly) for low-commit-frequency environments.</li>
<li><strong>Commit trigger</strong> — initiated by a source-control webhook or polling, subject to the minimum-interval governor described above.</li>
</ol>



<h2 class="wp-block-heading">Automation</h2>



<h3 class="wp-block-heading">Never Store Plain-Text Passwords in Automation Scripts</h3>



<p class="wp-block-paragraph">Credentials embedded as plain text in PowerShell scripts, batch files, or YAML pipeline definitions are a serious security risk — particularly when scripts are stored in source control. Use one of the following approaches depending on your environment:</p>



<ol class="wp-block-list">
<li><strong>Windows Authentication / Integrated Security</strong> — the preferred option for SQL Server connections running under a domain service account. No password appears anywhere in the script.</li>
<li><strong>Encrypted credentials</strong> — use <code>ConvertTo-SecureString</code> / <code>ConvertFrom-SecureString</code> in PowerShell, or a secrets manager (Azure Key Vault, HashiCorp Vault, AWS Secrets Manager) to retrieve credentials at runtime.</li>
<li><strong>Interactive prompt for attended runs</strong> — use <code>Get-Credential</code> in PowerShell or equivalent for scripts that a human operator launches manually.</li>
</ol>



<p class="wp-block-paragraph">For unattended overnight jobs, option 1 or option 2 is required. Many CI tool project files (including those produced by ApexSQL tooling) store passwords in encrypted form, but always verify the encryption mechanism meets your organization&#8217;s security requirements.</p>



<h3 class="wp-block-heading">Putting It All Together: A Reference Pipeline Structure</h3>



<p class="wp-block-paragraph">A SQL Server database CI pipeline that follows these practices will typically look like this:</p>



<ol class="wp-block-list">
<li><strong>Trigger</strong> — commit webhook, schedule, or manual invocation.</li>
<li><strong>Circuit breaker check</strong> — abort if the previous build is still broken.</li>
<li><strong>Notify</strong> — alert QA that a build is starting.</li>
<li><strong>Source pull</strong> — check out schema scripts, static data scripts, and test scripts at the current revision.</li>
<li><strong>Build</strong> — deploy schema and static data to a clean QA database instance.</li>
<li><strong>Populate</strong> — generate synthetic transactional test data.</li>
<li><strong>Test</strong> — execute unit tests; abort and notify on failure or threshold breach.</li>
<li><strong>Static analysis</strong> (optional) — run policy/rules checks; abort on failure.</li>
<li><strong>Notify</strong> — alert QA on success, or alert full team with diagnostics on failure.</li>
<li><strong>Reset circuit breaker</strong> — clear the failure flag on success.</li>
</ol>



<p class="wp-block-paragraph">Each step emits an exit code. The orchestrator evaluates it and either proceeds or aborts. No step requires human interpretation to continue.</p>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">Implementing CI for SQL Server databases requires deliberate decisions about where tests run, what data they run against, how results are communicated, and how the pipeline behaves under failure. The key principles are: test against a reproducible QA environment, use synthetic data, make every step machine-readable, fail fast, protect subsequent builds with a circuit breaker, and never embed plain-text credentials. These practices apply regardless of the specific tooling your team chooses.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/sql-server-database-continuous-integration-ci-best-practices-and-how-to-implement-them-testing-processing-and-automation/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Java in the Cloud: Continuous Integration Setup Tutorial</title>
		<link>https://www.bestdevops.com/java-in-the-cloud-continuous-integration-setup-tutorial/</link>
					<comments>https://www.bestdevops.com/java-in-the-cloud-continuous-integration-setup-tutorial/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Thu, 09 Feb 2017 06:57:21 +0000</pubDate>
				<category><![CDATA[Cloud Computing]]></category>
		<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[DevOps Tools]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Jenkins]]></category>
		<category><![CDATA[Springboot]]></category>
		<category><![CDATA[tutorial]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=557</guid>

					<description><![CDATA[Source:- whatmatrix.com Year after year, we bear witness to the increasingly rapid evolution of the IT industry. It has now [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Source:- whatmatrix.com</p>
<p>Year after year, we bear witness to the increasingly rapid evolution of the IT industry. It has now been more than two decades since the groundbreaking slogan ”Write once, run anywhere“ set a whole new level of expectation for the software development community. And here we are today, with a resulting, ever-expanding set of tools that have collectively taken Java development in particular, and software development in general, to a whole new universe of possibility.</p>
<p>Methodologies such as Agile, <a href="http://www.scmgalaxy.com/courses/agenda/devops/devops-training-course-online.html">DevOps</a>, and Continuous Integration and Deployment – along with the evolution of microservices – have collectively boosted software development process productivity to a point where it is a pleasure to be developing software more than ever before.</p>
<p>Utilizing automation and setting up the correct set of tools can make the development and delivery of software products surprisingly painless.</p>
<p>This article will take a look at this new universe from the perspective of a Java developer who crosses into DevOps and searches to optimize product development and delivery to its maximum.</p>
<p>Today, terms such as Spring Boot, <a href="http://www.scmgalaxy.com/courses/agenda/virtulization-and-container-tools/docker-training.html">Docker</a>, <a href="http://www.scmgalaxy.com/courses/agenda/virtulization-and-container-tools/cloud-computing-essentials.html">Cloud</a>, <a href="http://www.scmgalaxy.com/courses/agenda/virtulization-and-container-tools/amazon-aws-training.html">Amazon Web Services</a>, Continuous Delivery are widely used but less widely understood. This article will take the easiest route possible to present all these technologies and explain these terms, and wrap it up in the form of a tutorial where we will develop a small piece of software and prepare it for production delivery using all the mentioned tools.</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-558" src="http://www.bestdevops.com/wp-content/uploads/2017/02/devops-tools-1-300x300.jpg" alt="" width="350" height="350" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/devops-tools-1-300x300.jpg 300w, https://www.bestdevops.com/wp-content/uploads/2017/02/devops-tools-1-150x150.jpg 150w, https://www.bestdevops.com/wp-content/uploads/2017/02/devops-tools-1.jpg 640w" sizes="auto, (max-width: 350px) 100vw, 350px" /></p>
<h5><strong>Why These Tools?</strong></h5>
<h5>
<strong>Simplify Deployments with Docker</strong></h5>
<p>”Write once, run anywhere“ was the conceptual breakthrough that yielded technologies like the Java Virtual Machine (JVM) which enabled your code to run anywhere. And now here we are, a couple of decades later, with something called Docker being presented to the IT community. Docker is a containment tool in which you can place your software and run it painlessly, almost anywhere you wish.</p>
<p>However, a Java developer may look at Docker and say “Why would we need that, we already have the JVM, which is well recognized as the master portable solution.” But is it?</p>
<p>”Write once, run anywhere“ sounds nice, and plays out well… at least most of the time. Until you encounter multiple JVM vendors, multiple Java versions, multiple operating systems, and various permutations and combinations of all the above. You then find yourself switching from the elegant ”Write once, run anywhere“ paradigm to the counter-productive ”Write once, debug everywhere“ pitfall.</p>
<p>And that’s where Docker comes in to help save the day.</p>
<p>Docker simplifies development, testing, and shipping of software. If you have the software you want to test, put it in the Docker container, and it will run and be painless to install for all the parties involved.</p>
<h5 id="speed-up-development-with-spring-boot">Speed Up Development with Spring Boot</h5>
<p>Less than a decade after the “run anywhere” slogan was introduced, the Spring framework appeared on the scene. Today, the Spring ecosystem continues to flourish, and has produced lots of valuable Spring-based projects, perhaps most notably Spring Boot. As stated on the Spring Boot website:</p>
<blockquote><p>Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”.</p></blockquote>
<p>Spring Boot enables you to bring the application up and running in a matter of minutes. Software developers can focus on software development and then can benefit from a tool that does all the configuration for them.</p>
<p>In this tutorial, we will use Spring Boot to develop our microservice.</p>
<h5><strong>Continuous Integration (CI) with <a href="http://www.scmgalaxy.com/courses/agenda/continous-integration-tools/jenkins-training.html">Jenkins</a></strong></h5>
<p>DevOps is a rapidly growing movement that is tightly integrating software development and systems administration teams, with the goal of making a software development and delivery lifecycle as painless, seamless, and productive as possible for all parties involved: developers, sysadmins, testers, and ultimately, end users.</p>
<p>Continuous integration (CI), is one of the cornerstones of the DevOps revolution. The idea is that whenever a developer commits code to the code repository, it is automatically tested and packaged for delivery (deployment) to production.</p>
<p>CI goes hand-in-hand with:</p>
<ul>
<li>Continuous Delivery – Automatic delivery of the package prepared for end user business testing with manual trigger to production deployment.</li>
<li>Continuous Deployment – Automatic deployment of the packaged product directly to production.</li>
</ul>
<p>More than a few tools exist which can be utilized for implementing the CI process. One of the most popular is Jenkins, an open source CI tool. With more than a thousand plugins and a huge community behind it, Jenkins is an easy choice when starting to think about implementing continuous integration, delivery, or deployment.</p>
<p>In our tutorial, Jenkins will be used to deliver our product to the cloud, more specifically, the Amazon (AWS) cloud.</p>
<h5><strong>Cloud Computing with AWS</strong></h5>
<p>If you have some sysadmin experience, imagine removing some of the worries of system administration from your shoulders. You have a few applications; you have an idea of how much resource they will require, but you don’t know exactly the hardware sizing you will need. You make the estimation, the resources are bought, and the system goes to production. If you are lucky, you will find that you overestimated and have more resources than you need. But given Murphy’s Law, you will more likely find that you underestimated resource requirements and end up scrambling to get a bit more memory or processing power under tremendous time pressure. In contrast, if you’re deploying to the cloud, you simply put your system out there and size it as needed, with the flexibility offered by the cloud providers. With the cloud, you neither need to worry about running out of system resources, nor do you need to worry about having 90 percent of your memory or CPU sitting idle.</p>
<p>Of course, there is the challenge of deciding which provider to choose. Cloud wars are still in progress. Clash of Microsoft, Amazon and Google for the future of computing is an example title you can find lately in tech-world news. For this blog, I have chosen Amazon Web Services (AWS), largely based on its current popularity and market share.</p>
<p>One of the advantages of AWS is that Amazon offers lots of services after you sign up</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-560" src="http://www.bestdevops.com/wp-content/uploads/2017/02/amazon-web-services-bestdevops-1-300x212.jpg" alt="" width="383" height="271" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/amazon-web-services-bestdevops-1-300x212.jpg 300w, https://www.bestdevops.com/wp-content/uploads/2017/02/amazon-web-services-bestdevops-1-100x70.jpg 100w, https://www.bestdevops.com/wp-content/uploads/2017/02/amazon-web-services-bestdevops-1.jpg 618w" sizes="auto, (max-width: 383px) 100vw, 383px" /></p>
<p>In this tutorial we will use the following two AWS services: Elastic Compute Cloud EC2 (more specifically, Amazon EC2 Container Registry, or Amazon ECR), and Amazon S3 (Simple Storage Services).</p>
<h5 id="amazon-ecr"><strong>Amazon ECR</strong></h5>
<p>We will need to store our Docker images somewhere. Amazon ECR is a managed AWS Docker registry service. As stated on the Amazon ECR web site:</p>
<blockquote><p>…makes it easy for developers to store, manage, and deploy Docker container images. Amazon ECR is integrated with Amazon EC2 Container Service (ECS), simplifying your development to production workflow. Amazon ECR eliminates the need to operate your own container repositories or worry about scaling the underlying infrastructure.</p></blockquote>
<h5 id="amazon-s3">Amazon S3</h5>
<p>As mentioned, the application we develop will be a Spring Boot microservice that will be uploading files to Amazon S3. As stated on the Amazon S3 web site:</p>
<blockquote><p>…provides developers and IT teams with secure, durable, highly-scalable cloud storage. Amazon S3 is easy to use object storage, with a simple web service interface to store and retrieve any amount of data from anywhere on the web.</p></blockquote>
<h5 id="a-practical-how-to-tutorial">A Practical “How To” Tutorial</h5>
<p>The goal is to prepare for deployment a Spring Boot microservice which will upload files to Amazon S3. Steps are the following:</p>
<ul>
<li>Develop the microservice</li>
<li>Define the build process in which the service will be dockerized</li>
<li>Use <a href="http://www.scmgalaxy.com/courses/agenda/source-code-management-tools/bitbucket-administrator-training.html">Bitbucket </a>for hosting the Git code repository</li>
<li>Integrate Bitbucket with Jenkins to package the application using Gradle</li>
<li>Push it to a remote Amazon ECR</li>
</ul>
<p>What follows is a tutorial for setting up all the needed components:</p>
<ul>
<li>Spring Boot example application – microservice packaged and dockerized using Gradle</li>
<li>Jenkins installation on a fresh Ubuntu server</li>
<li>Bitbucket integration with Jenkins via webhook</li>
<li>Jenkins job configuration</li>
<li>Amazon ECR to store the Docker images containing our application</li>
</ul>
<h5 id="prerequisites">Prerequisites</h5>
<p>To be able to use AWS cloud resources, we need to register at Amazon first. By registering, we will get an account with immediate Free Tier usage benefits, for purposes of enabling hands-on experience during the 12 months following registration.</p>
<p>As mentioned, in this tutorial we will use Amazon S3 and Amazon ECR. For both, we will need access keys to connect to the services.</p>
<p>After signing up with AWS, we go to our account <em>Security credentials</em>, where we choose <em>Access keys</em> and click on “Create New Access Key”. After clicking, a key is generated along with its ID. You need to store this somewhere safe, as we will use it later when configuring AWS Jenkins integration and developing our S3 file upload.</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-561" src="http://www.bestdevops.com/wp-content/uploads/2017/02/aws-security-credentials-300x261.jpg" alt="" width="408" height="355" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/aws-security-credentials-300x261.jpg 300w, https://www.bestdevops.com/wp-content/uploads/2017/02/aws-security-credentials.jpg 467w" sizes="auto, (max-width: 408px) 100vw, 408px" /></p>
<p>The next prerequisite is that we need an Amazon S3 bucket (storage container). Our Spring Boot Service will be uploading and downloading files to and from Amazon S3 storage. Bucket creation is simple enough and just requires few clicks. A full description of how to do it is provided in the Create a Bucket documentation.</p>
<p>We will also be using Bitbucket for hosting our code and triggering requests to Jenkins, so a Bitbucket account is needed as well. Bitbucket is a great option for developers, with one of its main benefits being the unlimited amount of private repositories you can create.</p>
<h5 id="application-development">Application Development</h5>
<p>Rather than getting into all the details of Spring annotations and how they work, I will instead focus, from a pure developer perspective, on the more challenging part of the whole setup; namely, installing and configuring Linux, Jenkins, and other tools needed for CI. All the code examples used in this tutorial, including the Spring Boot microservice application, are available on the Bickbucket repository for the project.</p>
<p>Our application composition is simple. We have a Spring Boot application entry point in our <code>StorageWebserviceApplication.java</code> file. The logic for uploading and downloading files is in <code>StorageService.java</code>. <code>StorageController.java</code> is a Rest controller, containing API endpoints used for file upload and download. Here is the project hierarchy:</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-562" src="http://www.bestdevops.com/wp-content/uploads/2017/02/storagewebservice-236x300.png" alt="" width="247" height="314" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/storagewebservice-236x300.png 236w, https://www.bestdevops.com/wp-content/uploads/2017/02/storagewebservice.png 300w" sizes="auto, (max-width: 247px) 100vw, 247px" /></p>
<p>We have chosen Gradle as a build tool, and it will package our application and compose the Docker image. So next, we will discuss the Gradle build file, service component, and the Dockerfile.</p>
<p>To be able to use AWS API, we need to include dependencies in our build file, as defined in the AWS documentation for using Gradle.</p>
<p>Summed up, the AWS dependency configuration part of our Gradle script will look like the following:</p>
<pre><code>buildscript {
   	   	...
   	repositories {
         	mavenCentral()
   	}
   	dependencies {
...
         	classpath("io.spring.gradle:dependency-management-plugin:0.5.4.RELEASE")
   	}
}
..
apply plugin: "io.spring.dependency-management"
 
dependencyManagement {
	imports {
    	mavenBom ('com.amazonaws:aws-java-sdk-bom:1.10.47')
	}
}
 
dependencies {
   	..
   	compile ('com.amazonaws:aws-java-sdk-s3')
}
</code></pre>
<p>As stated previously, when uploading files to Amazon S3, we do so by uploading files to an S3 <em>bucket</em>.</p>
<p>To connect to the bucket, our Amazon S3 client needs to have credentials provided. Credentials are the access keys we created earlier. We define the access key ID and value in the <code>application.properties</code> file; we have named our bucket <code>toptal-s3-example</code>.</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-563" src="http://www.bestdevops.com/wp-content/uploads/2017/02/amazon-s3-client-300x73.png" alt="" width="383" height="93" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/amazon-s3-client-300x73.png 300w, https://www.bestdevops.com/wp-content/uploads/2017/02/amazon-s3-client.png 425w" sizes="auto, (max-width: 383px) 100vw, 383px" /></p>
<p>Our main service component is now as follows:</p>
<pre><code class="language-java hljs"><span class="hljs-annotation">@Service</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StorageService</span> {</span>
 
  	<span class="hljs-annotation">@Value</span>(<span class="hljs-string">"${aws.accesKeyId}"</span>)
  	<span class="hljs-keyword">private</span> String awsAccessKeyId;
 
  	<span class="hljs-annotation">@Value</span>(<span class="hljs-string">"${aws.secretKey}"</span>)
  	<span class="hljs-keyword">private</span> String awsSecretKey;
 
  	<span class="hljs-annotation">@Value</span>(<span class="hljs-string">"${aws.bucketName}"</span>)
  	<span class="hljs-keyword">private</span> String awsBucketName;
  	
  	 <span class="hljs-keyword">private</span> AWSCredentials credentials;
  	 <span class="hljs-keyword">private</span> AmazonS3 s3client;;
 
  	<span class="hljs-annotation">@PostConstruct</span>
	<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">init</span>(){
        	 credentials = <span class="hljs-keyword">new</span> BasicAWSCredentials(awsAccessKeyId, awsSecretKey);
        	 s3client = <span class="hljs-keyword">new</span> AmazonS3Client(credentials);
	}
 
 
  	<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">uploadFile</span>(MultipartFile file) <span class="hljs-keyword">throws</span> IOException {
        	File fileForUpload = transformMultipartToFile(file);
        	s3client.putObject(<span class="hljs-keyword">new</span> PutObjectRequest(awsBucketName, file.getOriginalFilename(), fileForUpload));
  	}
  	
  	<span class="hljs-keyword">public</span> InputStream <span class="hljs-title">downloadFile</span>(String amazonFileKey) <span class="hljs-keyword">throws</span> IOException {
        	S3Object fetchFile = s3client.getObject(<span class="hljs-keyword">new</span> GetObjectRequest(awsBucketName, amazonFileKey));
        	InputStream objectData = fetchFile.getObjectContent();
        	<span class="hljs-keyword">return</span> objectData;
  	}
…
</code></pre>
<p><code>StorageService</code> reads the credentials from the <code>application.properties</code> file and uses them to instantiate <code>BasicAWSCredentials</code> object, and subsequently the <code>AmazonS3Client</code> object. What follows is a simple matter of invoking <code>putObject</code> for file upload and <code>getObject</code> for file download, on the Amazon S3 client object.</p>
<p>We will run the service inside a Docker container and, during the Gradle build process, we will build the Docker image. We will do this by additionally configuring the <code>build.gradle</code> file, as follows:</p>
<pre><code>buildscript {
   	...
   	dependencies {
         	...
         	classpath('se.transmode.gradle:gradle-docker:1.2')
   	}
}
 
.....
apply plugin: 'docker'
...
task buildDocker(type: Docker, dependsOn: build) {
 push = false
 applicationName = "storageservice"
 dockerfile = file('src/main/docker/Dockerfile')
 doFirst {
   	copy {
   	from jar
   	into stageDir
   	}
 }
}
</code></pre>
<p>The <code>Buildscript</code> part and <code>apply plugin</code> are pretty standard. We have also defined a <code>buildDocker</code> task which reads the Docker configuration stored in the <code>src/main/docker/Dockerfile</code>, and copies the JAR file to the Docker build.</p>
<p>Dockerfile contains a list of pure Docker commands with which we will prepare our image:</p>
<pre><code>FROM frolvlad/alpine-oraclejdk8
ADD storageWebService-0.0.1-SNAPSHOT.jar storageService.jar
EXPOSE 8080
CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/storageService.jar"]
</code></pre>
<p>A prerequisite for running our application is to have installed a Java Virtual Machine (JVM). Docker provides a list of images with Java installed, and we will choose one of the smallest, based on a minimal 5MB Alpine Linux. <code>frolvlad/alpine-oraclejdk8</code> image has all that we need and is quite small (just 170 MB).</p>
<p>The <code>FROM</code> command sets the mentioned image as the base on which our own will be built. We <code>ADD</code> the built JAR file to the container filesystem under the name <code>storageService.jar</code>. Next, we define for Docker container to listen on port <code>8080</code> at runtime with the <code>EXPOSE</code> command. This, however, will not enable communication to <code>8080</code> from the host. When the image is done, and we want to run it, we will also need to publish the port on the container with the following command <code>docker run -p 8080:8080 amazonRepository/storageservice</code>, where <code>amazonRepository</code> is a repository we will configure later in this tutorial. With <code>CMD</code>, we define which commands will be executed when we run the container. Values in the brackets of the <code>CMD</code> command simply mean the following will be executed when we run the container:</p>
<pre><code class="language-bash hljs">java -Djava.security.egd=file:/dev/./urandom -jar /storageService.jar
</code></pre>
<p>The option <code>-Djava.security.egd=file:/dev/./urandom</code> is needed to help mitigate JVM delays during startup. If omitted, it will make the application boot up extremely slow due to a random number generation process needed during the boot process.</p>
<p>This sums up the “Application development” part. With this done, the service we have created here will be automatically started when we run a Docker container later on. So, let’s start installation and configuration of the other tools needed to set up the continuous integration process.</p>
<h5 id="application-and-system-operations">Application and System Operations</h5>
<p>First off, we need a clean Linux server on which to set up the Jenkins CI tool. Note that the following instructions are specifically for Ubuntu 14.04. Keep in mind instructions may slightly differ for other Linux distributions. The Jenkins version used is 2.7.1 and screens and instructions may differ slightly depending on the version of Jenkins being used.</p>
<p>So, we go to our Linux server console and start installing the prerequisites.</p>
<h5 id="jdk-prerequisite">JDK Prerequisite</h5>
<p>We need to have a JDK installed. Following are instructions for installing JDK8.</p>
<pre><code class="language-bash hljs"><span class="hljs-built_in">sudo</span> add-apt-repository ppa:webupd8team/java
<span class="hljs-built_in">sudo</span> apt-get install python-software-properties
<span class="hljs-built_in">sudo</span> apt-get update
<span class="hljs-built_in">sudo</span> apt-get install oracle-java8-installer
java -version 
</code></pre>
<h5 id="install-docker">Install Docker</h5>
<p>For Jenkins to be able to trigger Docker builds, we need to install <code>docker-engine</code> as follows:</p>
<pre><code class="language-bash hljs"><span class="hljs-built_in">sudo</span> apt-get install apt-transport-https ca-certificates

<span class="hljs-built_in">sudo</span> apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:<span class="hljs-number">80</span> --recv-keys <span class="hljs-number">58118</span>E89F3A912897C070ADBF76221572C52609D

<span class="hljs-comment">#create a docker list file</span>
<span class="hljs-built_in">sudo</span> vi /etc/apt/sources.list.d/docker.list

<span class="hljs-comment">#add the following entry in the docker.list file (change trusty to #the release you are running on if you are running on different, ie. #xenial, precise...):</span>
deb https://apt.dockerproject.org/repo ubuntu-trusty main
<span class="hljs-comment">#save and exit the file</span>
 
<span class="hljs-built_in">sudo</span> apt-get update
apt-cache policy docker-engine
<span class="hljs-built_in">sudo</span> apt-get install docker-engine
</code></pre>
<p>As we have now installed the Docker engine, with the following command we will start a <code>hello-world</code> Docker image to confirm Docker works correctly.</p>
<pre><code class="language-bash hljs"><span class="hljs-built_in">sudo</span> docker run hello-world
</code></pre>
<p><code>Hello-world</code> image output will look as follows, and with this, we can confirm that the engine is working ok.</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-564" src="http://www.bestdevops.com/wp-content/uploads/2017/02/sudo-docker-300x186.png" alt="" width="389" height="241" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/sudo-docker-300x186.png 300w, https://www.bestdevops.com/wp-content/uploads/2017/02/sudo-docker.png 654w" sizes="auto, (max-width: 389px) 100vw, 389px" /></p>
<h5 id="install-aws-command-line-interface-cli">Install AWS Command Line Interface (CLI)</h5>
<p>Next, we will install the AWS CLI. Later on, in Jenkins job configuration, we will use the CLI to execute commands for AWS authentication and Docker image push to Amazon EC2 container registry.</p>
<p>To install the AWS CLI, we follow the guidelines described in details on the Amazon CLI documentation.</p>
<p>Of the two installation options, we will choose installation using Pip, a package management system used for installing and managing Python programs. We will install Pip and AWS CLI simply by running the following three commands:</p>
<pre><code class="language-bash hljs"><span class="hljs-comment">#install Python version 2.7 if it was not already installed during the JDK #prerequisite installation</span>
<span class="hljs-built_in">sudo</span> apt-get install python2.<span class="hljs-number">7</span>
<span class="hljs-comment">#install Pip package management for python</span>
<span class="hljs-built_in">sudo</span> apt-get install python-pip
<span class="hljs-comment">#install AWS CLI</span>
<span class="hljs-built_in">sudo</span> pip install awscli
</code></pre>
<h5 id="aws-ecr">AWS ECR</h5>
<p>As the last step of the build process, we will be pushing our Docker image to the Amazon container registry. In the Amazon web services console, we find the AWS EC2 Container Service.</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-565" src="http://www.bestdevops.com/wp-content/uploads/2017/02/aws-ecr-300x97.png" alt="" width="390" height="126" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/aws-ecr-300x97.png 300w, https://www.bestdevops.com/wp-content/uploads/2017/02/aws-ecr-768x250.png 768w, https://www.bestdevops.com/wp-content/uploads/2017/02/aws-ecr-1024x333.png 1024w, https://www.bestdevops.com/wp-content/uploads/2017/02/aws-ecr.png 1034w" sizes="auto, (max-width: 390px) 100vw, 390px" /></p>
<p>We select <em>Repositories</em> submenu on the left and click on <em>Get started</em>.</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-566" src="http://www.bestdevops.com/wp-content/uploads/2017/02/amazon-ec2-container-300x139.png" alt="" width="395" height="183" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/amazon-ec2-container-300x139.png 300w, https://www.bestdevops.com/wp-content/uploads/2017/02/amazon-ec2-container.png 720w" sizes="auto, (max-width: 395px) 100vw, 395px" /></p>
<p>We are then presented with the first screen for configuring the repository where we enter the repository name and click on the <em>Next Step</em> button.</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-567" src="http://www.bestdevops.com/wp-content/uploads/2017/02/ec2-container-registry-300x128.png" alt="" width="401" height="171" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/ec2-container-registry-300x128.png 300w, https://www.bestdevops.com/wp-content/uploads/2017/02/ec2-container-registry-768x328.png 768w, https://www.bestdevops.com/wp-content/uploads/2017/02/ec2-container-registry.png 963w" sizes="auto, (max-width: 401px) 100vw, 401px" /></p>
<p>Clicking on <em>Next Step</em> then shows us a screen with instructions on how to push images to the repository.</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-569" src="http://www.bestdevops.com/wp-content/uploads/2017/02/ec2-container-registry-2-300x198.png" alt="" width="400" height="264" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/ec2-container-registry-2-300x198.png 300w, https://www.bestdevops.com/wp-content/uploads/2017/02/ec2-container-registry-2-768x507.png 768w, https://www.bestdevops.com/wp-content/uploads/2017/02/ec2-container-registry-2.png 940w" sizes="auto, (max-width: 400px) 100vw, 400px" /></p>
<p>&nbsp;</p>
<p>We are presented with an example of how to build and push a Docker image to the registry, but we don’t need to concern ourselves with this now. With this, we have created a repository.</p>
<h5 id="install-and-configure-jenkins">Install and Configure Jenkins</h5>
<p>To install Jenkins, we enter the following commands in the shell:</p>
<pre><code class="language-bash hljs"><span class="hljs-comment">#Download Jenkins key and pipe it to apt-key tool, apt-key command #add will read from input stream, as defined by „–„. When added</span>
<span class="hljs-comment">#apt will be able to authenticate package to be installed.</span>
wget -q -O - https://jenkins-ci.org/debian/jenkins-ci.org.key | <span class="hljs-built_in">sudo</span> apt-key add -
<span class="hljs-comment">#create a sources list for jenkins</span>
<span class="hljs-built_in">sudo</span> sh -c <span class="hljs-string">'echo deb http://pkg.jenkins-ci.org/debian-stable binary/ &gt; /etc/apt/sources.list.d/jenkins.list'</span>

<span class="hljs-comment">#update your local package list</span>
<span class="hljs-built_in">sudo</span> apt-get update

<span class="hljs-comment">#install jenkins</span>
<span class="hljs-built_in">sudo</span> apt-get install jenkins
</code></pre>
<p>When the installation finishes, Jenkins starts automatically. Check the service status with the following command:</p>
<pre><code class="language-bash hljs"><span class="hljs-built_in">sudo</span> service jenkins status
</code></pre>
<p>Jenkins will be connecting to Bitbucket Git repository, and to do so, we need to install Git.</p>
<pre><code class="language-bash hljs"><span class="hljs-comment">#install Git</span>
<span class="hljs-built_in">sudo</span> apt-get install git
</code></pre>
<p>Jenkins will be triggering Gradle build process, during which a Docker image will be created. To be able to do this, the Jenkins user needs to be added to the <code>docker</code> user group:</p>
<pre><code class="language-bash hljs"><span class="hljs-comment">#add Jenkins user to docker user group</span>
<span class="hljs-built_in">sudo</span> usermod <span class="hljs-operator">-a</span>G docker jenkins
</code></pre>
<p>During the build process, Jenkins will be pushing Docker images to Amazon ECR. To enable this, we need to configure AWS for the Jenkins user.</p>
<p>First, we need to switch to the <code>jenkins</code> user. To do so, we need to set a password.</p>
<pre><code class="language-bash hljs"><span class="hljs-comment">#change Jenkins password</span>
<span class="hljs-built_in">sudo</span> passwd jenkins

<span class="hljs-comment">#switch to Jenkins user</span>
su – jenkins

<span class="hljs-comment">#configure AWS</span>
aws configure
</code></pre>
<p>After entering the <code>aws configure</code> command, we start inputting the generated secret access key and key ID (these are the credentials we generated earlier in the process). In my case, the account’s region is <code>us-west-2</code>, and so I input that. We also set the default output format for AWS commands to be JSON.</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-570" src="http://www.bestdevops.com/wp-content/uploads/2017/02/aws-commands-json-300x41.png" alt="" width="454" height="62" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/aws-commands-json-300x41.png 300w, https://www.bestdevops.com/wp-content/uploads/2017/02/aws-commands-json.png 570w" sizes="auto, (max-width: 454px) 100vw, 454px" /></p>
<p>We can now move on to configuring Jenkins through the web console accessible on port 8080.</p>
<p>When we access the URL, we are presented with the following <em>Getting started</em> screen.</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-571" src="http://www.bestdevops.com/wp-content/uploads/2017/02/unlock-jenkins-300x131.png" alt="" width="440" height="192" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/unlock-jenkins-300x131.png 300w, https://www.bestdevops.com/wp-content/uploads/2017/02/unlock-jenkins.png 662w" sizes="auto, (max-width: 440px) 100vw, 440px" /></p>
<p>As stated on the screen, we need to input the password. Having done this, the setup wizard prompts us to do the following:</p>
<ul>
<li>Choose which plugins to install – we will choose <em>Install suggested plugins</em>.</li>
<li>Create first admin user by inputting user credentials</li>
</ul>
<p>When done, click <em>Save and Finish</em>. With this, we have finished Jenkins setup configuration.</p>
<p>Before we start defining the build job, we need to add a few additional plugins. We will go to <em>Manage Jenkins</em> and click on <em>Manage plugins</em>. In the <em>Available</em> tab, we first find the <em>Bitbucket plugin</em>, check the box, and click on <em>Download and install after restart</em>.</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-572" src="http://www.bestdevops.com/wp-content/uploads/2017/02/jenkins-300x166.png" alt="" width="451" height="249" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/jenkins-300x166.png 300w, https://www.bestdevops.com/wp-content/uploads/2017/02/jenkins.png 605w" sizes="auto, (max-width: 451px) 100vw, 451px" /></p>
<p>You will then be presented with something like the following screen.</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-573" src="http://www.bestdevops.com/wp-content/uploads/2017/02/installing-plugins-296x300.png" alt="" width="337" height="342" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/installing-plugins-296x300.png 296w, https://www.bestdevops.com/wp-content/uploads/2017/02/installing-plugins.png 605w" sizes="auto, (max-width: 337px) 100vw, 337px" /></p>
<p>After plugin installs, we repeat the process for the following additional plugins that will be needed to set up the job:</p>
<ul>
<li>Gradle plugin</li>
<li>Docker build step plugin</li>
<li>Cloudbees Docker custom build environment plugin</li>
<li>Amazon ECR plugin</li>
</ul>
<p>The Docker build step plugin we use will send requests to the Docker daemon. For this purpose, we need to enable the TCP socket on port 2375. To do to so, we enter the Docker configuration file located at <code>etc/default/docker</code>.</p>
<pre><code class="language-bash hljs"><span class="hljs-built_in">sudo</span> vi /etc/default/docker
</code></pre>
<p>Here we add the following line in the configuration:</p>
<pre><code class="language-bash hljs">DOCKER_OPTS=<span class="hljs-string">'-H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock'</span>
</code></pre>
<p>We save and exit the file and restart both Docker and Jenkins service.</p>
<pre><code class="language-bash hljs"><span class="hljs-built_in">sudo</span> service docker restart
<span class="hljs-built_in">sudo</span> service jenkins restart
</code></pre>
<p>After Jenkins reboots, we go to the Jenkins console and, from <em>Manage Jenkins</em>, we choose <em>Configure System</em>.</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-574" src="http://www.bestdevops.com/wp-content/uploads/2017/02/manage-jenkins-300x120.png" alt="" width="373" height="149" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/manage-jenkins-300x120.png 300w, https://www.bestdevops.com/wp-content/uploads/2017/02/manage-jenkins-768x308.png 768w, https://www.bestdevops.com/wp-content/uploads/2017/02/manage-jenkins.png 882w" sizes="auto, (max-width: 373px) 100vw, 373px" /></p>
<p>We find the <em>Docker builder</em> section and enter <code>http://localhost:2375</code> for the REST API URL, click on <em>Apply</em> to confirm the change. We then click the <em>Test Connection</em> to hopefully confirm that everything is ok.</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-575" src="http://www.bestdevops.com/wp-content/uploads/2017/02/docker-builder-300x73.png" alt="" width="395" height="96" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/docker-builder-300x73.png 300w, https://www.bestdevops.com/wp-content/uploads/2017/02/docker-builder-768x188.png 768w, https://www.bestdevops.com/wp-content/uploads/2017/02/docker-builder.png 921w" sizes="auto, (max-width: 395px) 100vw, 395px" /></p>
<p>We save the configuration and proceed to Jenkins job configuration.</p>
<h6 id="job-configuration">Job Configuration</h6>
<p>We go to the Jenkins home page and create a <em>New Item</em>.</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-576" src="http://www.bestdevops.com/wp-content/uploads/2017/02/jenkins-homepage.png" alt="" width="144" height="174" /></p>
<p>We choose a <em>Freestyle project</em> and enter the project name as shown on the following screen:</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-577" src="http://www.bestdevops.com/wp-content/uploads/2017/02/freestyle-project--300x168.png" alt="" width="316" height="177" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/freestyle-project--300x168.png 300w, https://www.bestdevops.com/wp-content/uploads/2017/02/freestyle-project--768x429.png 768w, https://www.bestdevops.com/wp-content/uploads/2017/02/freestyle-project--1024x572.png 1024w, https://www.bestdevops.com/wp-content/uploads/2017/02/freestyle-project--375x210.png 375w, https://www.bestdevops.com/wp-content/uploads/2017/02/freestyle-project-.png 1485w" sizes="auto, (max-width: 316px) 100vw, 316px" /></p>
<p>Clicking on <em>OK</em>, we are presented with the job configuration page. We want the project to be built on each push to our Bitbucket Git repository. To achieve this, we first need to define the repository we are connecting to.</p>
<h5 id="step-1-source-code-management">Step 1: Source Code Management</h5>
<p>Under source code management, we choose Git and enter the URL of our Bitbucket repository. The URL has the form of <code>https://bitbucket.org/bitbucketUsername/repositoryName</code>.</p>
<p>After we enter the URL, Jenkins will automatically try to test the connection. Since we didn’t yet input credentials, it will show an error indicating it cannot connect.</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-578" src="http://www.bestdevops.com/wp-content/uploads/2017/02/source-code-management-300x55.png" alt="" width="424" height="78" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/source-code-management-300x55.png 300w, https://www.bestdevops.com/wp-content/uploads/2017/02/source-code-management.png 605w" sizes="auto, (max-width: 424px) 100vw, 424px" /></p>
<p>Open the drop down list <em>Add</em>, and click on <em>Credentials Jenkins</em> provider.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-579" src="http://www.bestdevops.com/wp-content/uploads/2017/02/credentials.png" alt="" width="279" height="65" /></p>
<p>We are presented with the following screen, where we enter the username and password for our Bitbucket account</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-580" src="http://www.bestdevops.com/wp-content/uploads/2017/02/jenkins-credentials-provider-290x300.png" alt="" width="300" height="310" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/jenkins-credentials-provider-290x300.png 290w, https://www.bestdevops.com/wp-content/uploads/2017/02/jenkins-credentials-provider.png 302w" sizes="auto, (max-width: 300px) 100vw, 300px" /></p>
<p>After adding the new credentials record, we make sure to select it in the credentials drop down, and this finishes the <em>Source code management</em> setup.</p>
<h5 id="step-2-build-triggers">Step 2: Build Triggers</h5>
<p>Check <em>Trigger builds remotely</em> and define an authentication token. Make sure to define a random and secure token.</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-581" src="http://www.bestdevops.com/wp-content/uploads/2017/02/build-triggers-300x92.png" alt="" width="349" height="107" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/build-triggers-300x92.png 300w, https://www.bestdevops.com/wp-content/uploads/2017/02/build-triggers.png 605w" sizes="auto, (max-width: 349px) 100vw, 349px" /></p>
<h5 id="step-3-bitbucket-webhook">Step 3: Bitbucket Webhook</h5>
<p>Jenkins already provided the URL for us which we will use on Bitbucket. We go to our Bitbucket repository page and, in the settings menu, click on <em>Web hooks</em>. Subsequently clicking on <em>Add webhook</em> presents us with the following screen, which we fill in as follows:</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-582" src="http://www.bestdevops.com/wp-content/uploads/2017/02/bitbucket-interfase-300x209.png" alt="" width="349" height="243" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/bitbucket-interfase-300x209.png 300w, https://www.bestdevops.com/wp-content/uploads/2017/02/bitbucket-interfase-100x70.png 100w, https://www.bestdevops.com/wp-content/uploads/2017/02/bitbucket-interfase.png 739w" sizes="auto, (max-width: 349px) 100vw, 349px" /></p>
<p>URL has the following structure: <code>http://JENKINS_URL _HOST:PORT/job/JOB_NAME/build?token=TOKEN</code>.</p>
<p>Enter the values above respectively with the Jenkins URL, port it is running on, the name of the job you have created, and token you have previously defined.</p>
<p>After saving the Webhook, you will be provided with the following screen, which you can edit if needed, or view requests generated each time we push new code.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-medium wp-image-583" src="http://www.bestdevops.com/wp-content/uploads/2017/02/webhooks-300x94.png" alt="" width="300" height="94" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/webhooks-300x94.png 300w, https://www.bestdevops.com/wp-content/uploads/2017/02/webhooks.png 605w" sizes="auto, (max-width: 300px) 100vw, 300px" /></p>
<p>With this configuration, the webhook is triggered on each repository push, regardless of the branch. On the Jenkins side, we can define which branch push will trigger the build.</p>
<p>For Bitbucket to be able to push code to Jenkins, we need to reconfigure Jenkins global security to allow anonymous read access. Additionally, for our setup, we have to disable the default Jenkins option which prevents cross-site request forgery. To do this, go to <em>Manage Jenkins</em> and choose <em>Configure global security</em>. Check <em>Allow anonymous read access</em> and check <em>Prevent cross-site forgery exploits</em>. Then save the configuration.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-medium wp-image-584" src="http://www.bestdevops.com/wp-content/uploads/2017/02/configure-global-security-231x300.png" alt="" width="231" height="300" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/configure-global-security-231x300.png 231w, https://www.bestdevops.com/wp-content/uploads/2017/02/configure-global-security.png 484w" sizes="auto, (max-width: 231px) 100vw, 231px" /></p>
<p>Please note that this is only done for simplicity reasons. Full setup surpasses the coverage of this tutorial, and it would include further securing Jenkins behind a reverse proxy, on TLS connection, and enabling CSRF prevention.</p>
<h5 id="step-4-gradle-build">Step 4: <a href="http://www.scmgalaxy.com/courses/agenda/build-management-tools/gradle-training.html">Gradle Build</a></h5>
<p>We can now return to the Jenkins job and continue configuring it. In the build section, we add a build step: <em>Invoke gradle script</em>.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-585" src="http://www.bestdevops.com/wp-content/uploads/2017/02/add-build-setup.png" alt="" width="239" height="184" /></p>
<p>On this form, we enter the following:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-medium wp-image-586" src="http://www.bestdevops.com/wp-content/uploads/2017/02/ivolve-gradle-script-300x179.png" alt="" width="300" height="179" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/ivolve-gradle-script-300x179.png 300w, https://www.bestdevops.com/wp-content/uploads/2017/02/ivolve-gradle-script-768x457.png 768w, https://www.bestdevops.com/wp-content/uploads/2017/02/ivolve-gradle-script.png 915w" sizes="auto, (max-width: 300px) 100vw, 300px" /></p>
<p>As shown on the screen, we will use the Gradle wrapper, a convenient Gradle feature that doesn’t require you to have Gradle installed on the host. Make sure to check the <em>Make gradlew executable</em> box.</p>
<p>In the tasks, we specify <code>build</code> and <code>buildDocker</code>.</p>
<h5 id="step-5-docker-tag-image">Step 5: Docker Tag Image</h5>
<p>This part of the build tags a Docker image previously prepared by Gradle’s <code>dockerBuild</code> task. For this, we add a new build step to the job: <em>Execute Docker command</em>. We choose the <em>Tag image</em> command and set the image name, target repository where we will push the image, and tag:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-medium wp-image-587" src="http://www.bestdevops.com/wp-content/uploads/2017/02/execute-docker-command-300x87.png" alt="" width="300" height="87" srcset="https://www.bestdevops.com/wp-content/uploads/2017/02/execute-docker-command-300x87.png 300w, https://www.bestdevops.com/wp-content/uploads/2017/02/execute-docker-command-768x223.png 768w, https://www.bestdevops.com/wp-content/uploads/2017/02/execute-docker-command.png 819w" sizes="auto, (max-width: 300px) 100vw, 300px" /></p>
<h4 id="step-6-docker-push-to-amazon-ecr"></h4>
<p>&nbsp;</p>
<h5 id="step-6-docker-push-to-amazon-ecr">Step 6: Docker Push to Amazon ECR</h5>
<p>Lastly, we need to define how to push our image to the Amazon ECR. For this, we add a new <em>Execute shell</em> build step and set the commands to authenticate to AWS and to push the image to Amazon ECR:</p>
<pre><code>#region for our account is us-west-2
aws ecr get-login --region us-west-2 | bash
#push the previously tagged image
docker push 058432294874.dkr.ecr.us-west-2.amazonaws.com/springbootdocker:${BUILD_NUMBER}
</code></pre>
<p><img decoding="async" src="https://uploads.toptal.io/blog/image/121104/toptal-blog-image-1472043675964-d4d406113219c18faca1e4f74bdc17aa.png" alt="Docker Push to Amazon ECR" /></p>
<p>With this, we have finished our build process. After pushing new code to the repo, this job will activate, and we will have a new Docker image uploaded to the Docker registry “auto-magically”.</p>
<p>The image can be then pulled to wherever we have <code>docker-engine</code> installed, and can be run with the following command:</p>
<pre><code>docker run -p 8080:8080 amazonRepository/springbootdocker
</code></pre>
<p>This command will start our Spring Boot microservice, with the following endpoints for uploading and downloading our files to the S3 bucket:</p>
<ul>
<li><code>http://hostnameURL:8080/api/storage/upload</code></li>
<li><code>http://hostnameURL:8080/api/storage/download?fileName=xyz</code></li>
</ul>
<h5 id="further-steps-with-java-and-continuous-integration">Further Steps with Java and Continuous Integration</h5>
<p>There are always more things to do. A lot of ground has been covered in this tutorial, but I would consider this only a starting point from which to learn further. Putting Jenkins behind a web proxy server, like Nginx, and establishing a TLS connection, are only two examples of what more could, and arguably should, be done.</p>
<p>Our Docker image is available on Amazon ECR and ready for deploying. We can now take it and deploy it manually. However, a finer solution would be to automate it further. CI is only the first step, and next step is Continuous Delivery. What about a high availability? Amazon AWS EC2 provides features for registering containers in the cloud on a clustered environment which is mandatory for production based service. A good working example of developing a continuous delivery process can be found on the following <a href="https://blogs.aws.amazon.com/application-management/post/Tx32RHFZHXY6ME1/Set-up-a-build-pipeline-with-Jenkins-and-Amazon-ECS" target="_blank" rel="noopener noreferrer">AWS blog post</a>.</p>
<h5 id="conclusion">Conclusion</h5>
<p>All in all, we have put in place a smooth and clean software development process. Utilizing the tools available, we have created an infrastructure that helps maximize our productivity. Now, we do not have to worry about the configuration of our Java service which is a simple web service with a REST endpoint. We let the Spring Boot convention take care of everything and focus only on the service logic. We utilize Jenkins to build a new Docker image each time we push our code to our Bitbucket Git repository, and in the end, we’ve set the cloud to be responsible for storing our Docker images and files. When we deploy our service contained within a Docker image, we will be care free of any restrictions of the operating system (as long as the operating system has a <code>docker-engine</code> installed).</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/java-in-the-cloud-continuous-integration-setup-tutorial/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
