Repository URL to install this package:
|
Version:
3.6.0 ▾
|
# frozen_string_literal: true
require 'English'
require 'rake/tasklib'
require_relative 'helpers'
module Faculty
module Rake
# Functions for deploying to AWS from the local machine
class Deploy < ::Rake::TaskLib # rubocop:disable Metrics/ClassLength
include Helpers
def initialize(stack_name: nil, tag_name: nil, parameter_overrides: {}, &block)
super()
@stack_name = stack_name || repository_name_from_git_origin
@tag_name = tag_name || repository_name_from_git_origin
@extra_task = block if block
@app_specific_parameter_overrides = parameter_overrides
initialize_task
end
def initialize_task # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
namespace :deploy do
desc 'Deploy to AWS'
task :to, [:environment, :deployed_by, :deploy_role] do |_, args|
@environment = args.fetch(:environment, 'dev').to_sym
@deployed_by = args.fetch(:deployed_by, 'manual')
@deploy_role = args.fetch(:deploy_role, 'CloudformationDeploymentRole')
@account_id = ACCOUNT_IDS.fetch(@environment)
@parameter_overrides = cloudformation_parameter_overrides.merge @app_specific_parameter_overrides
abort bold 'You have uncommitted changes; please commit before deploying' if uncommitted_changes?
update_aws_cli
check_aws_credentials
abort bold 'Stack does not exist. Please deploy through github first.' unless stack_exists?
begin
Dir.chdir tmp_dir do
install_gems
@extra_task&.call
cloudformation_deploy
end
ensure
tidy_up
end
end
end
end
ACCOUNT_IDS = {
dev: '496883770698',
staging: '423014805995',
prod: '542159367156'
}.freeze
AWS_CREDENTIAL_VARS = %w[
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_SESSION_TOKEN
AWS_SECURITY_TOKEN
AWS_DEFAULT_REGION
AWS_REGION
].freeze
environment_aws_credentials = ENV.keys.intersection(AWS_CREDENTIAL_VARS).map { |var| "--env #{var}" }.join(' ')
AWS_CLI_IMAGE = 'amazon/aws-cli'
AWS_CLI = 'docker run --rm -v ~/.aws:/home/.aws -v $(pwd):/aws ' \
"--user #{Process.uid}:#{Process.gid} --env HOME=/home " \
"#{environment_aws_credentials} #{AWS_CLI_IMAGE}"
OUTPUT_TEMPLATE_FILE = 'rake-deploy-template.yaml'
S3_BUCKET = 'uk-ac-york-global-artifactstore'
TEMPLATE_FILE = 'cloudformation.yaml'
private
def check_aws_credentials
puts bold 'Checking AWS credentials...'
until current_credentials == @account_id
puts bold "Please login using saml2aws to the #{@environment} account"
system 'saml2aws login --force'
end
end
def cloudformation_deploy
puts bold 'Deploying to cloudformation...'
system "#{AWS_CLI} cloudformation package --output-template-file #{OUTPUT_TEMPLATE_FILE} " \
"--template-file #{TEMPLATE_FILE} --s3-bucket #{S3_BUCKET}"
system "#{AWS_CLI} cloudformation deploy " \
"#{cloudformation_deploy_parameters.map { |k, v| "--#{k} #{v}" }.join(' ')} " \
"--tags #{cloudformation_deploy_tags.map { |k, v| "\"#{k}=#{v}\"" }.join(' ')}" \
"--parameter-overrides #{@parameter_overrides.map { |k, v| "\"#{k}=#{v}\"" }.join(' ')}"
end
def cloudformation_deploy_parameters
{
capabilities: 'CAPABILITY_IAM',
'no-fail-on-empty-changeset': nil,
'role-arn': "arn:aws:iam::#{@account_id}:role/#{@deploy_role}",
'stack-name': @stack_name,
'template-file': OUTPUT_TEMPLATE_FILE
}
end
def cloudformation_parameter_overrides
{
AppName: @stack_name,
Deployment: @environment
}
end
def cloudformation_deploy_tags
{
'york/defined_in' => 'cloudformation',
'york/group' => 'FACULTY-DEV',
'york/name' => "Faculty Dev #{@tag_name}",
'york/project' => repository_name_from_git_origin,
'york/pushed_by' => @deployed_by,
'york/status' => @environment,
'york/policy_version' => 2,
'york/repo_name' => repository_name_from_git_origin
}
end
def current_credentials
`#{AWS_CLI} sts get-caller-identity --query Account --output text`.strip
end
def install_gems
puts bold 'Installing gems...'
system "docker compose run --rm -u #{Process.uid}:#{Process.gid} builder " \
'bundle install --deployment --path vendor/bundle --without test development'
end
def repository_name_from_git_origin
repository_name_from_remote `git config --get remote.origin.url`.strip
end
def stack_exists?
`#{AWS_CLI} cloudformation describe-stacks --stack-name #{@stack_name}`
$CHILD_STATUS.success?
end
def tidy_up
puts bold 'Tidying up...'
Dir.chdir tmp_dir do
system 'docker compose down'
end
system "rm -rf #{tmp_dir}"
end
def tmp_dir
@tmp_dir ||= begin
tmp_dir = `mktemp -d -t aws-deploy-XXXXX`.strip
system "git clone --depth=1 file://#{Dir.pwd} #{tmp_dir}"
tmp_dir
end
end
def uncommitted_changes?
!system 'git diff HEAD --quiet'
end
def update_aws_cli
puts bold 'Updating aws cli...'
system "docker pull #{AWS_CLI_IMAGE}"
end
end
end
end