{"id":13682790,"url":"https://github.com/Hallian/codedeploy-example","last_synced_at":"2025-04-30T09:34:23.287Z","repository":{"id":45795117,"uuid":"102130253","full_name":"Hallian/codedeploy-example","owner":"Hallian","description":"This is a project demonstrating AWS CodeDeploy. A CloudFormation template is included for setting up a simple Auto Scaling Group, Load Balancer and Deployment Group. Also includes a Packer template for provisioning a Ubuntu based AMI with NodeJS, AWS CLI and the CodeDeploy agent.","archived":false,"fork":false,"pushed_at":"2017-09-08T20:40:33.000Z","size":140,"stargazers_count":30,"open_issues_count":0,"forks_count":11,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-08-02T13:34:32.912Z","etag":null,"topics":["aws","cloudformation","codedeploy","packer"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Hallian.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-09-01T16:04:03.000Z","updated_at":"2024-07-22T15:45:56.000Z","dependencies_parsed_at":"2022-07-16T16:00:51.755Z","dependency_job_id":null,"html_url":"https://github.com/Hallian/codedeploy-example","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hallian%2Fcodedeploy-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hallian%2Fcodedeploy-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hallian%2Fcodedeploy-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hallian%2Fcodedeploy-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Hallian","download_url":"https://codeload.github.com/Hallian/codedeploy-example/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224206214,"owners_count":17273409,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","cloudformation","codedeploy","packer"],"created_at":"2024-08-02T13:01:53.218Z","updated_at":"2024-11-12T02:31:49.366Z","avatar_url":"https://github.com/Hallian.png","language":"Shell","funding_links":[],"categories":["Shell"],"sub_categories":[],"readme":"# AWS CodeDeploy Example\n\nThis project will demonstrate the basics of deploying an application to an Auto Scaled EC2 instance with CodeDeploy. The infrastructure\nis setup is automated with CloudFormation. A NodeJS Express application will serve as a dummy application. Dependencies are preinstalled\ninto the AMI with Packer.\n\n# Prerequisites\n\nYou should have the [aws cli](http://docs.aws.amazon.com/cli/latest/userguide/awscli-install-bundle.html) installed and [configured with your\nAWS credentials](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html). [NodeJS and npm](https://nodejs.org/en/) are also\nrequired to run the example app.\n\nYou should also change the default values for the CloudFormation template. You could do this during the stack creation command but that's\ntedious, so I find it easied to just modify the `Parameters` section in `webapp.cloudformation.yml`. See *CloudFormation* section for more info.\n\n# Getting started\n\nWell start off by creating a stack of AWS resources that we're going to use to serve our application. Use the AWS CLI to create a CloudFormation\nstack from `webapp.cloudformation.yml`.\n\n```\naws cloudformation create-stack \\\n\t--stack-name webapp-example \\\n\t--template-body=file://webapp.cloudformation.yml \\\n\t--capabilities CAPABILITY_IAM\n```\n\nNext we'll deploy our sample `webapp`. It's a simple Express application written in NodeJS so you'll need to install it's dependencies with npm.\n\n```\ncd webapp\nnpm install\n```\n\nTo deploy our application we'll use aws cli to create a zip file of our sources and push it to S3.\n\n```\n# in project root\naws deploy push --application-name $APPLICATION_NAME \\\n\t--s3-location s3://$DEPLOYMENT_BUCKET/$REVISION \\\n\t--source webapp\n```\n\nReplace `$APPLICATION_NAME`, `$DEPLOYMENT_BUCKET` and `$REVISION` with your values. Revision can be anything but it should include an incrementing\nversion number, e.g. `webapp-1, webapp-2, webapp-3...`.\nYou can obtain the application name and deployment bucket from the example webapp stack's outputs with the following command.\n\n```\naws cloudformation describe-stacks --stack-name webapp-example\n```\n\nOnce you've pushed your new revision package to S3, the command will output a command that you can use to deploy the application to a deployment group.\nIt will look something like this:\n\n```\naws deploy create-deployment --application-name $APPLICATION_NAME \\\n\t--s3-location bucket=\"$DEPLOYMENT_BUCKET\",key=\"$REVISION\",bundleType=zip \\\n\t--deployment-group-name $DEPLOYMENT_GROUP\n```\n\nThat command will create a new deployment in CodeDeploy. The CodeDeploy agent on your instances will notice this and download the new revision.\nSee *CodeDeploy* section for more info.\n\n## Scripting\n\nSince it's somewhat tedious to be writing all of that all the time, it pays to have a script do it for you. The `scripts` folder contains a script\nthat will do all of the above in one step.\n\n```\n../scripts/deploy-webapp.sh webapp-1\n```\n\nAlternatively, you can use the convenient npm scripts registered in the scripts section of `package.json`:\n\n```\nnpm run create-stack\n...\nnpm run deploy-webapp -- webapp-1\n```\n\nnpm scripts like these can be configured in the scripts section of `package.json`.\n\n# CodeDeploy\n\nBelow is a simplified chart of a deployment workflow. \n\n![deployment](images/deployment.png)\n\n## Appspec\n\n`appspec.yml` is a file used to tell CodeDeploy how to install your application. You can find this in the root of `webapp` folder which will be packaged\nas a zip archive and uploaded to S3.\n\n### Files\n\nThe files section is used to copy files from your package to where ever you need to copy them in order for your application to function.\nIn this example we'll copy the contents of `src` folder to `/opt/webapp`. Since NodeJS applications need their libraries to run, we'll copy\n`node_modules` to the same location as well.\n\n```\nfiles:\n  - source: src\n    destination: /opt/webapp\n  - source: node_modules\n    destination: /opt/webapp/node_modules\n```\n\n[See AWS Documentation on files](http://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file-structure-files.html)\n\n### Hooks\n\nHooks are used to run scripts during various stages of the deployment. Here we'll use the `AfterInstall` hook to install our application as a `systemd`\nservice and `ApplicationStart` and `ApplicationStop` hooks to start and stop our application with `systemctl`.\n\n```\nhooks:\n  ApplicationStop:\n    - location: deployment_scripts/stop.sh\n  AfterInstall:\n    - location: deployment_scripts/deploy.sh\n  ApplicationStart:\n    - location: deployment_scripts/start.sh\n```\n\nThese scripts are located in the `webapp/deployment_scripts` folder.\n\n[AWS Docs on hooks](http://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file-structure-hooks.html)\n\n## Deploy\n\nAs described in the *Getting started* section we can use the `aws` cli tool to create a zip package of our applications\nsource code and push it to S3.\n\n```\naws deploy push --application-name $APPLICATION_NAME \\\n\t--s3-location s3://$DEPLOYMENT_BUCKET/$REVISION \\\n\t--source webapp\n```\n\nHowever, you don't need to use `aws` cli for this. You can use any method to create a zip or tar.gz archive. `tar` is especially useful\nwhen you source code is not all in one convenient folder that you can zip up. The `--transform` flag on `tar` can be used to rename\nfiles inside the archive. For example say you have your appspec.yml in a folder called `codedeploy` instead of project root where CodeDeploy\nwill look for it, you could use the `--transform` to move it in the package, e.g.\n\n```\ntar -czf package.tar.gz --transform=\"s|webapp/codedeploy/appspec.yml|appspec.yml|\" webapp\n```\n\nThe command above will output a gzipped tar archive called `package.tar.gz` with the appspec moved to the root:\n\n```\nwebapp/\nwebapp/codedeploy/\nappspec.yml\nwebapp/deployment_scripts/\nwebapp/deployment_scripts/deploy.sh\n...\n```\n\nNote that this repository actually has the appspec.yml in the `webapp` folder so the above isn't necessary here.\n\nYou can use `aws` cli to upload your package to S3.\n\n```\naws s3 cp package.tar.gz s3://$DEPLOYMENT_BUCKET/$REVISION\n```\n\nTo deploy your application you can either go to the AWS CodeDeploy console or use the `aws` cli. Using the command line\ntool is highly recommended since it can easily be scripted thus easing development.\n\n```\naws deploy create-deployment --application-name $APPLICATION_NAME \\\n\t--s3-location bucket=\"$DEPLOYMENT_BUCKET\",key=\"$REVISION\",bundleType=zip \\\n\t--deployment-group-name $DEPLOYMENT_GROUP\n```\n\nDepending on your package type change the `bundleType` parameter to one of `tar`, `tgz` or `zip`.\n\n### Scripting\n\nAs described in *Getting started* section, it's convenient to automated all of this with a script. The `scripts` folder\ncontains a script called `deploy-webapp.sh` that will fetch the required details from your CloudFormation stack, create\nthe package, upload it to S3 and create a deployment with CodeDeploy.\n\nIf you're using npm or a similar system with configurable scripts you should add your scripts there as well. This will further\nease development. With package.json for example you could configure the scripts section as follows.\n\n```\n  \"scripts\": {\n    \"deploy-webapp\": \"bash scripts/deploy-webapp.sh\"\n  },\n```\n\nNow you can run `npm run deploy-webapp -- revision-1` to deploy your application. The `--` denotes that all arguments after that\nwill be passed to the script.\n\nYou can easily use this to create a Continuous Deployment setup. For example, you could run a bash scripts something like this\non a some CI.\n\n```\ncd webapp\nnpm install\nnpm run test\n\nif [ $BRANCH == \"master\" ]; then\n\tnpm run deploy-webapp -- webapp-$BUILD_NUMBER $PROD_DEPLOYMENT_GROUP\nelif [ $BRANCH == \"develop\" ]; then\n\tnpm run deploy-webapp -- webapp-$BUILD_NUMBER $TEST_DEPLOYMENT_GROUP\nfi\n```\n\nYou should run tests for all of your branches.\n\nWe could extend `deploy-webapp.sh` script to accept a deployment group as a parameter and use an `if` statement to conditionally\ndeploy to different environments based on branch.\n\n# CloudFormation\n\nManaging AWS resources is easy with CloudFormation. We describe the resources we want as an YAML file and CloudFormation will\ncreate them for us with a single command. Updating and removing them is as simple. This is called infrastructure as code and\nthe benefit is having your infrastructure versioned just like your code.\n\n![stack](images/stack.png)\n\n## Default parameters\n\nYou should change the default parameters for the CloudFormation stack. You can do this during stack creation but that's tedious.\nThe default parameters are an easy way of storing your AWS details. This template however will have mine which wont work for you.\nSo edit the `Parameters` section of `webapp.cloudformation.yml` with your AWS details and all of the commands described here will\nwork without modifition.\n\nYou should at least change `KeyName`, `WebappSubnets`, `ALBSubnets`, `VPC` and `AMIID`. You can register an SSH key at AWS EC2 console.\nThe default VPC and subnets found under the AWS VPC console will do just fine. The AMI id can be obtained by building the Amazon Machine\nimage with Packer. See *EC2* section for more info on building the AMI.\n\n## Create stack\n\nWe'll use the `aws` cli tool to create the stack.\n\n```\naws cloudformation create-stack \\\n\t--stack-name webapp-example \\\n\t--template-body=file://webapp.cloudformation.yml \\\n\t--capabilities CAPABILITY_IAM\n```\n\nHowever that's a bit cumbersome to type out every time so `package.json` contains a bunch of handful scripts, e.g.\n\n```\nnpm run create-stack\n```\n\n## Remove stack\n\nTo remove the stack you'll first need to clean up the S3 deployment bucket. CloudFormation will refuse to delete buckets\nthat are not empty.\n\n```\nnpm run cleanup-s3\nnpm run remove-stack\n```\n\n## Useful npm scripts\n\nTyping out those `aws` cli commands can be a chore sometimes so the `package.json` contains a set of scripts for dealing\nwith various lifycycle events. They should be pretty self explanatory so here's a listing of them.\n\n```\nnpm run create-stack\nnpm run update-stack\nnpm run delete-stack\nnpm run remove-stack\nnpm run describe-stack\nnpm run describe-stack-events\nnpm run wait-stack-delete\nnpm run wait-stack-remove\nnpm run wait-stack-create\nnpm run wait-stack-update\nnpm run wait-stack-exists\n```\n\nThe commands called `wait-stack-*` can be used to wait for a certain stack event to complete. For example, wait for your\nstack to be created before pushing deployment. This is very useful in scripts. e.g.\n\n```\nnpm run create-stack \u0026\u0026 npm run wait-stack-create \u0026\u0026 npm run deploy-webapp -- webapp-1\n```\n\n# EC2\n\nWe'll run our Webapp on an Auto Scaling Group with EC2 instances. For this we're going to need an Amazon Machine Image\n(AMI) with our dependencies installed. Things like the CodeDeploy agent and NodeJS. We could simply install these during\nthe application deployment but that would increase the deployment time. It would also be error prone due to the possibility\nof OS vendors package repositories being offline for example.\n\n## Build AMI with Packer\n\nPacker is perfect for creating AMIs with software preinstalled in a repeatable fashion.\n\n```\npacker build webapp.packer.json\n```\n\n# License\n\nCopyright 2017 Nikolas Lahtinen\n\nPermission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FHallian%2Fcodedeploy-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FHallian%2Fcodedeploy-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FHallian%2Fcodedeploy-example/lists"}