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 )); } } } }