Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(bugfix) option to use codedeploy deployment id in release directory name #21

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# frozen_string_literal: true

source 'https://rubygems.org'
gemspec

group :development do
gem 'pry'
gem 'aws-sdk-codedeploy'
gem 'guard'
gem 'guard-minitest'
gem 'pry'
end
1 change: 1 addition & 0 deletions egads.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Gem::Specification.new do |s|
s.extra_rdoc_files = ["README.md"]
s.rdoc_options = ["--charset=UTF-8"]

s.add_dependency "aws-sdk-codedeploy", '~> 1.0'
s.add_dependency "aws-sdk-s3", '~> 1.0'
s.add_dependency "rexml", ">= 3.3.4" # required for Ruby 3+
s.add_dependency "thor"
Expand Down
1 change: 1 addition & 0 deletions lib/egads.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require 'fileutils'
require 'yaml'
require 'aws-sdk-codedeploy'
require 'aws-sdk-s3'
require 'thor'
require 'benchmark'
Expand Down
4 changes: 3 additions & 1 deletion lib/egads/command/extract.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ class Extract < Group

desc "[remote, plumbing] Downloads tarball for SHA from S3 and extracts it to the filesystem"
class_option :force, type: :boolean, aliases: '-f', default: false, banner: "Overwrite existing files"
class_option :deployment_id, type: :string, default: nil, banner: 'Append suffix to release directory'
argument :sha, type: :string, required: true, desc: 'git SHA to download and extract'

attr_accessor :seed_sha, :seed_path
Expand Down Expand Up @@ -89,7 +90,8 @@ def do_extract(path)

# Directory created upon successful extraction
def release_dir
RemoteConfig.release_dir(sha)
suffix = options[:deployment_id] ? "_#{options[:deployment_id]}" : ''
dir(sha) + suffix
end

# Directory where in-progress extraction occurs
Expand Down
21 changes: 18 additions & 3 deletions lib/egads/command/release.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
# rubocop:disable Style/Documentation, Style/RaiseArgs, Style/RescueModifier
# frozen_string_literal: true

require 'aws-sdk-codedeploy'

module Egads
class Release < Group
include Egads::LocalHelpers
include Thor::Actions

desc "[remote] Symlinks SHA to current and restarts services. If needed, stages SHA"
class_option :force, type: :boolean, default: false, banner: "Overwrite existing release"
desc '[remote] Symlinks SHA to current and restarts services. If needed, stages SHA'
class_option :force, type: :boolean, default: false, banner: 'Overwrite existing release'
class_option :deployment_id, type: :string, default: nil, banner: 'Append suffix to release directory'
argument :sha, type: :string, required: true, desc: 'git SHA to stage'

def setup_environment
RemoteConfig.setup_environment
end
Expand All @@ -15,11 +23,13 @@ def stage

def run_before_release_hooks
return unless should_release?

inside(dir) { run_hooks_for(:release, :before) }
end

def symlink_release
return unless should_release?

atomic_symlink(dir, release_to)
end

Expand All @@ -44,8 +54,10 @@ def trim
end

protected

def dir
RemoteConfig.release_dir(sha)
suffix = options[:deployment_id] ? "_#{options[:deployment_id]}" : ''
RemoteConfig.release_dir(sha) + suffix
end

def release_to
Expand All @@ -66,6 +78,7 @@ def should_release?
# Use an extra temporary symlink for atomicity (equivalent to `mv -T`)
def atomic_symlink(src, dest)
raise ArgumentError.new("#{src} is not a directory") unless File.directory?(src)

say_status :symlink, "from #{src} to #{dest}"
tmp = "#{dest}-new-#{rand(2**32)}"
# Make a temporary symlink
Expand All @@ -75,3 +88,5 @@ def atomic_symlink(src, dest)
end
end
end

# rubocop:enable Style/Documentation, Style/RaiseArgs, Style/RescueModifier
25 changes: 19 additions & 6 deletions lib/egads/command/stage.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
# rubocop:disable Style/Documentation, Style/GuardClause
# frozen_string_literal: true

require 'aws-sdk-codedeploy'

module Egads
class Stage < Group
include Egads::LocalHelpers
include Thor::Actions


desc "[remote] Readies SHA for release. If needed, generates URL for SHA and extracts"
class_option :force, type: :boolean, default: false, banner: "Overwrite existing files"
desc '[remote] Readies SHA for release. If needed, generates URL for SHA and extracts'
class_option :force, type: :boolean, default: false, banner: 'Overwrite existing files'
class_option :deployment_id, type: :string, default: nil, banner: 'Append suffix to release directory'
argument :sha, type: :string, required: true, desc: 'git SHA to stage'

def setup_environment
Expand All @@ -17,19 +23,21 @@ def extract

def run_before_hooks
return unless should_stage?
inside(dir){ run_hooks_for(:stage, :before) }

inside(dir) { run_hooks_for(:stage, :before) }
end

def bundle
return unless should_stage?

inside(dir) do
run_with_code("bundle install #{RemoteConfig.bundler_options}", stream: true) if File.readable?("Gemfile")
run_with_code("bundle install #{RemoteConfig.bundler_options}", stream: true) if File.readable?('Gemfile')
end
end

def symlink_system_paths
return unless should_stage? && shared_path

symlink_directory File.join(shared_path, 'system'), File.join(dir, 'public', 'system')
symlink_directory File.join(shared_path, 'log'), File.join(dir, 'log')
end
Expand All @@ -49,6 +57,7 @@ def symlink_config_files

def run_after_stage_hooks
return unless should_stage?

inside(dir) { run_hooks_for(:stage, :after) }
end

Expand All @@ -57,8 +66,10 @@ def mark_as_staged
end

protected

def dir
RemoteConfig.release_dir(sha)
suffix = options[:deployment_id] ? "_#{options[:deployment_id]}" : ''
RemoteConfig.release_dir(sha) + suffix
end

def stage_flag_path
Expand All @@ -74,3 +85,5 @@ def shared_path
end
end
end

# rubocop:enable Style/Documentation, Style/GuardClause
29 changes: 28 additions & 1 deletion lib/egads/local_helpers.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# frozen_string_literal: true

# rubocop:disable Metrics/MethodLength

require 'aws-sdk-codedeploy'

module Egads
# Some helper methods for all local commands
module LocalHelpers
Expand All @@ -6,12 +12,33 @@ def sha
end

def short_sha
sha[0,7]
sha[0, 7]
end

def tarball
@tarball ||= S3Tarball.new(sha, seed: options[:seed])
end

def deployment_id
environment = ENV['EC2_ENVIRONMENT'] || ''
application = ENV['EC2_SERVICE'] || ''

return unless environment && application

deployment = CodeDeploy::Client.new.list_deployments(
application_name: application,
deployment_group_name: environment,
include_only_statuses: %w[InProgress Created Queued]
).deployments.first

return nil if deployment.empty?

deployment
rescue Aws::CodeDeploy::Errors::ServiceError => e
puts "Error fetching deployment: #{e.message}"
nil
end
end
end

# rubocop:enable Metrics/MethodLength
2 changes: 1 addition & 1 deletion lib/egads/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Egads
VERSION = '5.1.2'
VERSION = '5.2.0'
end
16 changes: 14 additions & 2 deletions spec/egads_release_spec.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
# frozen_string_literal: true

require_relative 'spec_helper'

describe "Egads::Release" do
describe 'Egads::Release' do
subject { Egads::Release }

it 'should run the correct tasks' do
_(subject.commands.keys).must_equal %w(setup_environment stage run_before_release_hooks symlink_release restart run_after_release_hooks trim)
_(subject.commands.keys).must_equal %w[setup_environment stage run_before_release_hooks symlink_release restart run_after_release_hooks trim]
end

# it 'should have the correct class options' do
# expected_options = {
# force: { type: :boolean, default: false, banner: 'Overwrite existing release' },
# deployment_id: { type: :boolean, default: false, banner: 'Include deployment ID in release directory' }
# }

# actual_options = subject.class_options.transform_values { |opt| { type: opt.type, default: opt.default, banner: opt.banner }}
# _(actual_options).must_equal expected_options
# end
end
16 changes: 14 additions & 2 deletions spec/egads_stage_spec.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
# frozen_string_literal: true

require_relative 'spec_helper'

describe "Egads::Stage" do
describe 'Egads::Stage' do
subject { Egads::Stage }

it 'should run the correct tasks' do
_(subject.commands.keys).must_equal %w(setup_environment extract run_before_hooks bundle symlink_system_paths symlink_config_files run_after_stage_hooks mark_as_staged)
_(subject.commands.keys).must_equal %w[setup_environment extract run_before_hooks bundle symlink_system_paths symlink_config_files run_after_stage_hooks mark_as_staged]
end

# it 'should have the correct class options' do
# expected_options = {
# force: { type: :boolean, default: false, banner: 'Overwrite existing files' },
# deployment_id: { type: :boolean, default: false, banner: 'Include deployment ID in release directory'}
# }

# actual_options = subject.class_options.transform_values { |opt| { type: opt.type, default: opt.default, banner: opt.banner }}
# _(actual_options).must_equal expected_options
# end
end
Loading