The developers push the code on CodeCommit, a trigger is set off, and CodePipeline takes the code and feeds it into CodeBuild, which carries out the build and the tests and creates the artifact, ready for the deploy. At this point, CodePipeline passes the packet to CodeDeploy which releases it on a pool of EC2 instances. At every step, S3 is used as supporting storage for the artifacts.<\/figcaption><\/figure>\nUsing only AWS services, which are compatible and specifically designed to cooperate with each other, has the advantage of putting specific triggers and extremely simplified setups at our disposal. Everything scales automatically and without the need for any particular technical operations<\/strong>; the team is, therefore relieved of the burden of sizing the Continuous Delivery infrastructure in advance.<\/p>\nIt is also possible to manage security and permissions at a granular level by using IAM role and IAM policy. Unlike what happens when using other tools, it is possible to remain confined within the sandbox of a single Amazon account, without having to externally present an endpoint to start the build process.<\/p>\n
We have found that CodeBuild takes care of the build and test phases by using provisioning of the containers; these start up only when needed, thus optimising performance and eliminating the need for dedicated instances, as happens when using Jenkins, for example.<\/p>\n
Another key feature of CodeBuild is isolation, which allows for\u00a0each build to be segregated at both the application and release levels.<\/strong><\/p>\nAWS Costs
\n<\/strong>Before we begin with the tutorial, let\u2019s have a look at the AWS costs incurred by this solution:<\/p>\nThe price of each CodePipeline pipeline is $1\/month, whilst for the first 5 users (50GB and 10000 git requests), the CodeCommit service is totally free. For the sixth user onwards, the cost is $1\/month per user.<\/p>\n
The cost of the CodeBuild service is calculated according to the minutes of the actual use of the containers carried out by the builds, a model that allows for significant cost savings compared to traditional runners based on EC2 instances, which are charged on an hourly basis.<\/p>\n
CodeDeploy is free, with no limits on traffic or time.<\/p>\n
The additional costs to be considered are the storage and bandwidth costs generated by S3, which is used as supporting storage for the artifacts between one step and the next of each pipeline.<\/p>\n
Obviously, costs can vary widely depending on the context and organisation of every team, but we would like to say that in most cases, this stack works out to be\u00a0one of the cheapest solutions around.<\/strong><\/p>\nNow let us enter into the heart of the implementation.<\/p>\n
CodeCommit
\n<\/strong>The first service to be configured is CodeCommit.<\/p>\nWe create the repository by logging into the AWS console or, in the case of programming access, to the CLI.<\/p>\n
<\/p>\n
Now we create an IAM user that will allow us to proceed with the main git actions on the repository that has just been created.<\/p>\n
<\/p>\n
To get the necessary permissions to access the repo, you must authenticate as an IAM user. Here are the possible methods:<\/p>\n
\n- Git credential helper<\/em>, which uses the CLI. In which case, a key pair is needed for access:<\/li>\n
- an\u00a0SSH key<\/em>\u00a0that can be generated by IAM user management;<\/li>\n
- a\u00a0username and password<\/em>, also generated by the IAM management console (using HTTPS).<\/li>\n<\/ul>\n
With each push of the app\u2019s source code, this is taken over by CodeBuild, which deals with the provisioning of a temporary, isolated environment (container) inside which the build and test phases will take place.<\/p>\n
CodeBuild
\n<\/strong>Before proceeding to the test and build phases, we must configure CodeBuild, specifying the container size, the type of image desired (for example, a Linux container with a preinstalled framework from the ones available or a custom image) and specifying the steps we want CodeBuild to take to carry out the test and build of the app. This last step means a choice between two methodologies: declaring the inline commands or using a file called buildspec.yml that will invoke the hooks of the build cycle.<\/p>\nWe chose to use the latter method because, in this way, the YAML buildspec file can be versioned along with the application code, giving us the opportunity to change the test and build procedures just before the build phase itself.<\/p>\n
<\/p>\n
So, within each hook, we have specified the commands that CodeBuild will perform, moment by moment.<\/p>\n
Below is a generic example of the structure of a buildspec.yml file located in the root directory of the repository:<\/p>\n
version: <\/strong>0.1\r\n\r\nenvironment_variables:\r\nplaintext:\r\nJAVA_HOME: <\/strong>\"\/usr\/lib\/jvm\/java-8-openjdk-amd64\"\r\n\r\nphases:\r\ninstall:\r\ncommands:\r\n<\/strong>- apt-get update -y\r\n- apt-get install -y maven\r\npre_build:\r\ncommands:\r\n<\/strong>- echo Nothing to do in the pre_build phase...\r\nbuild:\r\ncommands:\r\n<\/strong>- echo Build started on `date`\r\n- mvn install\r\npost_build:\r\ncommands:\r\n<\/strong>- echo Build completed on `date`\r\nartifacts:\r\nfiles:\r\n<\/strong>- target\/messageUtil-1.0.jar\r\ndiscard-paths: yes<\/strong><\/pre>\nSince the last phase of the buildspec.yml, we made sure to get a bundle that was compatible with CodeDeploy, the service used in the next phase; the package obtained from the last build phase contains both the application, ready for implementation, and the scripts to run to install it and configure it on the deploy instance.<\/p>\n
CodeDeploy
\n<\/strong>For CodeDeploy to function, its scripts must be executed from within the instance; for this to happen, the AWS CLI and the CodeDeploy agent must be installed in each instance of the process\u2019 target infrastructure.<\/p>\nWe create a file containing the declaration of the hooks, this time called appspec.yml. After having created the necessary scripts from scratch, we decided which and how many of them to call for each hook.<\/p>\n
<\/p>\n
The YAML appspec file, in this specific case, requires two folders to be created in the bundle: one (App<\/em>) dedicated to the application and another (Scripts<\/em>) dedicated to the scripts.<\/p>\nBelow is a generic example of the structure of an appspec.yml file located in the root directory of the bundle:<\/p>\n
version: <\/strong>0.0\r\nos: <\/strong>linux\r\nfiles:\r\n- source: <\/strong>App\/\r\ndestination: <\/strong>\/var\/www\/html\/\r\n- source: <\/strong>nginx.conf\r\ndestination: <\/strong>\/etc\/nginx\/\r\nhooks:\r\nBeforeInstall:\r\n- location: <\/strong>Scripts\/UnzipResourceBundle.sh\r\ntimeout: <\/strong>300\r\nrunas: <\/strong>root\r\n- location: <\/strong>Scripts\/InstallDependencies.sh\r\ntimeout: <\/strong>300\r\nrunas: <\/strong>ubuntu\r\nAfterInstall:\r\n- location: <\/strong>Scripts\/FixPermissions.sh\r\ntimeout: <\/strong>300\r\nrunas: <\/strong>root\r\nApplicationStart:\r\n- location: <\/strong>Scripts\/WebServerStart.sh\r\ntimeout: <\/strong>300\r\nrunas: <\/strong>root\r\nValidateService:\r\n- location: <\/strong>Scripts\/ValidateService.sh\r\ntimeout: <\/strong>300\r\nrunas: <\/strong>ubuntu<\/pre>\nCodePipeline
\n<\/strong>Working in parallel with the three tools that we have just described is CodePipeline, the service orchestrator that deals with passing the outputs generated by each phase to the next service, which will use them as the inputs needed to perform its task. Each phase of the Continuous Integration process uses the S3 platform as supporting storage.<\/p>\nFor CodePipeline to function, you need to create a pipeline; to do this, we access the AWS console and perform the following steps:<\/p>\n
\n- choose a name for the pipeline;<\/li>\n<\/ul>\n
<\/p>\n
\n- choose the source, in our case CodeCommit;<\/li>\n<\/ul>\n
<\/p>\n
\n- configure the build step, in our case CodeBuild;<\/li>\n<\/ul>\n
<\/p>\n
\n- choose the deploy provider, in our case CodeDeploy;<\/li>\n<\/ul>\n
<\/p>\n
The Pipeline has been successfully created.<\/p>\n
<\/p>\n
When CodeCommit is linked to CodePipeline, it automatically creates a trigger that means that every\u00a0git push<\/em>\u00a0causes the process described in the pipeline created to initiate.<\/p>\nThe source code that results from this phase is delivered in the form of an input to CodeBuild, which generates a bundle that will, in turn, be the input for CodeDeploy. CodeDeploy will then install the app on the target infrastructure.<\/p>\n
N.B. it is important to verify that the code generated at the end of each phase by each tool is correct; as each result is the starting point for the next phase, if an output were to be wrong, the whole deploy process would be compromised.<\/em><\/p>\nWe have been using this solution for the past few weeks now, and we are delighted indeed with it: we deleted all the management efforts of our previous Continuous Delivery infrastructure, increasing the number of builds that we can manage in parallel, and we are also spending significantly less. This stack has turned out to be excellent in terms of efficiency, reliability, and cost efficiency.<\/p>\n
What do you think of it?<\/p>\n
If our solution has intrigued you and you like the idea of implementing it in your workflow, leave us a comment or\u00a0contact us<\/strong><\/a>! We\u2019d be happy to answer all your questions, read your thoughts, and help you get the most out of this application.<\/p>\n","protected":false},"excerpt":{"rendered":"AWS DevOps With the launch of\u00a0CodeBuild\u00a0last November\u00a0on the stage of re:Invent, AWS added the missing puzzle piece to the suite […]<\/p>\n","protected":false},"author":3,"featured_media":473,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[242],"tags":[365,369],"yoast_head":"\n
Full stack Continuous Delivery on AWS - Proud2beCloud Blog<\/title>\n\n\n\n\n\n\n\n\n\n\n\n\n\t\n\t\n\t\n\n\n\n\n\n\n\t\n\t\n\t\n