Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
uoy-faculty-rake / lib / faculty / rake / deploy.rb
Size: Mime:
# 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, &block)
        super()
        @stack_name = stack_name || repository_name_from_git_origin
        @extra_task = block if block
        initialize_task
      end

      def initialize_task # rubocop:disable Metrics/MethodLength
        desc 'Deploy to AWS'
        task :deploy do
          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

      private

      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"\
                " #{AWS_CLI_IMAGE}"
      DEV_ACCOUNT_ID = '496883770698'
      OUTPUT_TEMPLATE_FILE = 'rake-deploy-template.yaml'
      S3_BUCKET = 'uk-ac-york-global-artifactstore'
      TEMPLATE_FILE = 'cloudformation.yaml'

      def check_aws_credentials
        puts bold 'Checking AWS credentials...'
        until current_credentials == DEV_ACCOUNT_ID
          puts bold 'Please login using saml2aws to the dev 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(' ')}"
      end

      def cloudformation_deploy_parameters
        {
          capabilities: 'CAPABILITY_IAM',
          'no-fail-on-empty-changeset': nil,
          'role-arn': "arn:aws:iam::#{DEV_ACCOUNT_ID}:role/CloudformationDeploymentRole",
          'stack-name': @stack_name,
          'template-file': OUTPUT_TEMPLATE_FILE
        }
      end

      def cloudformation_deploy_tags
        {
          defined_in: 'cloudformation',
          group: 'FACULTY-DEV',
          name: 'Faculty Dev APP_FULL_NAME',
          project: repository_name_from_git_origin,
          pushed_by: 'manual',
          status: 'dev'
        }
      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