At work, we use Amazon’s Elastic Beanstalk to deploy and host micro sites for our clients. I would explain what Elastic Beanstalk is, but if you’re here, you probably already know. We have a team of three and have a post-commit set up to push back up to GitHub and also push over to Elastic Beanstalk (I’ll do a write up of how we do that later) and it was working quite well for a few months… until we started getting this error the other day when doing an aws.push:
remote: error: Unable to create application version: null remote: To https://(AWSAccessToken):(AWSSecretToken)@git.elasticbeanstalk.us-east-1.amazonaws.com/repos/6465762e626c6f6766726f677369746573/(NameOfBeanstalkApp) ! [remote rejected] HEAD -> master (hook declined) error: failed to push some refs to 'https://(AWSAccessToken):(AWSSecretToken)@git.elasticbeanstalk.us-east-1.amazonaws.com/repos/6465762e626c6f6766726f677369746573/(NameOfBeanstalkApp)'
After doing some quick research, I found that we were hitting some sort of invisible limit of application versions. My initial fix was to go in a manually remove old versions through the management console, but this was proven less than ideal when I realized that there isn’t a select all button and if you stray away from clicking right in the middle of the check box, it deselects the whole list. Not only was this very frustrating, but I would have to do this each time the error came up. There must be a way to automate this.
The AWS SDK for PHP library includes a class for working with Elastic Beanstalk applications, specifically, methods for listing and deleting application versions. The function below is triggered after we do a push to Beanstalk. We opted to have no more than 5 old versions, as that should be plenty to roll back to in an emergency situation. The code and the comments should be pretty self explanatory, but if you have any questions or ways to improve it, please feel free to drop a note in the comments.
function removeOldAppVersionsFromBeanstalk($aws_app){ require_once(getcwd().'/lib/aws-sdk/sdk.class.php'); //Whatever the path is to the AWS SDK $bean = new AmazonElasticBeanstalk(); $response = $bean->describe_application_versions(array( 'ApplicationName' => $aws_app )); // Beanstalk returns the versions newest to oldest if($response->isOK()){ $app_versions = array(); foreach($response->body->DescribeApplicationVersionsResult->ApplicationVersions->member as $app){ $app_versions[] = "$app->VersionLabel"; //Put all of the app version labels (IDs) into an array } $versions_to_keep = 5; if(count($app_versions) > $versions_to_keep){ $app_versions = array_slice($app_versions, $versions_to_keep-1); echo "\nRemoving ".count($app_versions)." old version(s) from AWS\n"; foreach($app_versions as $app_version_id){ $response = $bean->delete_application_version($aws_app, $app_version_id, array( 'DeleteSourceBundle' => 'true' // true will remove the zip files from S3 too )); } } } }
February 4, 2013 — 2:00 pm
Thanks for posting this code, I ran into this same issue.
I have just one comment:
for($i=0; $i < $versions_to_keep; $i++){
$app_versions = array_shift($app_versions); //Remove the first X app versions from the array
}
can be replaced with:
$app_versions = array_slice($app_versions, $versions_to_keep-1);
February 4, 2013 — 2:20 pm
Oh, awesome, thanks! I always like learning new tricks. I’ll update the code.
November 15, 2013 — 9:17 am
Thanks much for this! We just ran into the same problem.
September 29, 2014 — 2:31 pm
Nice hack :), there is a way to ask for an increase for the versions limit for an elastic beanstalk application, in the strange scenario that someone needs to keep track of more than 500 versions — http://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html#limits_elastic_beanstalk
Btw, how did you automate the aws.push ?, i am a little noob with git hehe.
September 29, 2014 — 2:36 pm
In short, you can either alias git commands or post-commit hooks to run BASH commands. In our case, (which in hindsight is wrong) we had a post-commit hook that would push the repo to origin, the also do a git aws.push. You can edit the .git/hooks/post-commit file within the repo to start playing with that functionality.
September 29, 2014 — 3:22 pm
Thanks, i will try that :D.