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

Tag changes #13

Draft
wants to merge 65 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 64 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
e67c05f
Always use tags for indicating stages
WilliamWFLee Sep 30, 2024
d6a5d9e
Add deprecation warning to use_tags_for_deploy option
WilliamWFLee Sep 30, 2024
6aeed3e
Add test for GitWrapper.update_tag_commit
WilliamWFLee Sep 30, 2024
23e9467
Clean up comment
WilliamWFLee Sep 30, 2024
71e8492
Simplify deploy feature specs setup
WilliamWFLee Sep 30, 2024
0eb0432
Add test for release to call update_tag_commit when deploying
WilliamWFLee Sep 30, 2024
de14ff3
Require 'byebug' for tests
WilliamWFLee Sep 30, 2024
3aa3483
Add method to delete branches both locally and remotely
WilliamWFLee Sep 30, 2024
0c6a246
Add method on git wrapper to delete branches both locally and remotely
WilliamWFLee Sep 30, 2024
8207b14
Change GitWrapper#delete_branches to accept an array of branch names
WilliamWFLee Sep 30, 2024
7779af7
Add #environments method to stages extractor to get a list of all dep…
WilliamWFLee Sep 30, 2024
9d52173
Delete legacy environment branches locally and on remote when deploying
WilliamWFLee Sep 30, 2024
b703fad
Improve use_tags_for_deploy option deprecation warnng
WilliamWFLee Sep 30, 2024
2a3b593
Add Ruby 3.1, 3.2 and 3.3 to test workflow
WilliamWFLee Sep 30, 2024
1d80515
Rename method for creating/updating tags and update implementation to…
WilliamWFLee Oct 1, 2024
8fe2721
Add StagesExtractor#stages_for_environment to get deployable stages f…
WilliamWFLee Oct 1, 2024
9708588
Update stages extractor so that either a valid stage or environment c…
WilliamWFLee Oct 1, 2024
946d757
Update Release.deploy! so that each deployment to a stage is done wit…
WilliamWFLee Oct 1, 2024
d05f7c5
Stub output helper methods instead of IO.puts to avoid silencing test…
WilliamWFLee Oct 2, 2024
3235f88
Move creation of deployment tags so that a tag for each stage is only…
WilliamWFLee Oct 2, 2024
d83601b
Add use_timestamped_deploy_tags option for configuring use of new tag…
WilliamWFLee Oct 2, 2024
21576b3
Fix position of rescue clause
WilliamWFLee Oct 2, 2024
e9ba734
Refactor release deployment logic to a deployer class
WilliamWFLee Oct 2, 2024
3d9455e
Add back method to create or update branch
WilliamWFLee Oct 2, 2024
dfd4268
Replace GitWrapper#tag with create_or_update_tag
WilliamWFLee Oct 2, 2024
b008c32
Add old branch-style deployment behaviour back, using the use_timesta…
WilliamWFLee Oct 2, 2024
2e7762e
Add git wrapper method for fetching a list of tags for a given object…
WilliamWFLee Oct 2, 2024
714670b
Update Release.create! so that it does not create a new release and t…
WilliamWFLee Oct 2, 2024
b324aad
Fix specs for Release class
WilliamWFLee Oct 2, 2024
c5703bc
Remove incorrect parameter for method
WilliamWFLee Oct 2, 2024
2bca50f
Fix test for fetching tags that point to an object
WilliamWFLee Oct 2, 2024
56f3194
Only symlink the customer settings if the file exists
WilliamWFLee Oct 3, 2024
fdb8cbc
Extract file contents in executables to Cli class
WilliamWFLee Oct 3, 2024
7b863f6
Clean up unused variable
WilliamWFLee Oct 3, 2024
5405694
Update authors in gemspec
WilliamWFLee Oct 3, 2024
e445ed8
Remove unused test import
WilliamWFLee Oct 3, 2024
e6a8f17
Avoid duplicate updates to the same deployment branch when deploying …
WilliamWFLee Oct 3, 2024
a5d35cb
Fix deployment branches deduplication
WilliamWFLee Oct 3, 2024
fea5e50
Fix typo in release message
WilliamWFLee Oct 3, 2024
a16341f
Remove unused method
WilliamWFLee Oct 3, 2024
6a7d003
Use fully qualified ref names to avoid ambiguity between branches and…
WilliamWFLee Oct 3, 2024
76bc8ae
Fix tests
WilliamWFLee Oct 3, 2024
d6b6587
Remove unused parameter
WilliamWFLee Oct 3, 2024
54ed3d0
Use filter instead of find for finding local branches
WilliamWFLee Oct 3, 2024
f9baca3
Update README with deployment tags information
WilliamWFLee Oct 3, 2024
c174c8c
Add epi_deploy:set_branch task for manually set the Capistrano :branc…
WilliamWFLee Oct 3, 2024
7cdc07e
Update deployer to pass the branch reference as an environment variab…
WilliamWFLee Oct 3, 2024
ab67eeb
Use require instead of require_relative in epi_deploy:set_branch task
WilliamWFLee Oct 3, 2024
2224f1b
Use absolute path for requiring version.rb
WilliamWFLee Oct 3, 2024
969c106
Dereference tags to commit if a tag name is used as the reference
WilliamWFLee Oct 3, 2024
e79b3e4
Remove setup class, and add latest_release_tag to AppVersion
WilliamWFLee Oct 3, 2024
6f2a014
Make the default tag the latest release tag, rather than any tag
WilliamWFLee Oct 3, 2024
de6b423
Add AppVersion.open method
WilliamWFLee Oct 7, 2024
00afe71
Fix AppVersion#initialize method
WilliamWFLee Oct 7, 2024
0dcb970
Rename bump! method to bump
WilliamWFLee Oct 7, 2024
4fa3205
Fix saving of app version file
WilliamWFLee Oct 7, 2024
c6a0b08
Fix release creation to create app version save file before creating …
WilliamWFLee Oct 7, 2024
1f5a902
Fix tests
WilliamWFLee Oct 7, 2024
df6112c
Update README to add instructions to include Capistrano tasks in Capf…
WilliamWFLee Oct 7, 2024
5944114
Add tests for the release setting the latest release tag in the versi…
WilliamWFLee Oct 16, 2024
16d82d4
Add tests for app version
WilliamWFLee Oct 16, 2024
d5bfc54
Make regexes for version.rb more resilient to whitespace differences
WilliamWFLee Oct 16, 2024
b19bdaf
Do not define set_branch cap task if using default deployment behaviour
WilliamWFLee Oct 21, 2024
2a48c38
Fix creation of branches for default behaviour
WilliamWFLee Oct 21, 2024
789e954
Add deploy- prefix to deployment tags to avoid conflict with tags tha…
WilliamWFLee Oct 31, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
ruby-version: ['2.6', '2.7', '3.0']
ruby-version: ['2.6', '2.7', '3.0', '3.1', '3.2', '3.3']

steps:
- uses: actions/checkout@v2
Expand Down
58 changes: 49 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,23 @@ This gem provides a convenient interface for creating releases and deploying usi

## Installation

At the top of your application's `Gemfile` add this line if it does not already exist:

```sh
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
```

Add this line to your application's Gemfile:

gem 'epi_deploy', github: 'epigenesys/epi_deploy'
```rb
gem 'epi_deploy', github: 'epigenesys/epi_deploy'
```

And then execute:

$ bundle install

```sh
$ bundle install
```

## Usage

Expand Down Expand Up @@ -101,10 +110,41 @@ You can also deploy to all customers for a given environment by running e.g. `ca

Using branches for stages, i.e. demo and production branches, can clutter up your branches screen. This can be particularly awkward when running CI and keeping track of multiple active branches. To resolve this you can optionally configure epi_deploy to use tags for this instead of branches.

1. Update to epi_deploy 2.2.0 or greater.
2. Add config/epi_deploy.rb to your application.
3. Add `EpiDeploy.use_tags_for_deploy = true` to the newly created config file.
4. Delete your stage branches on gitlab (likely `production`, `demo`, `qa`).
5. Push your changes and deploy to a demo site to test it is working correctly.
Tags will be automatically created for each successful deployment with the format `environment.stage-timestamp`, for example `production.epigenesys-2024_10_03-12_20_09`, and pushed to the remote.
WilliamWFLee marked this conversation as resolved.
Show resolved Hide resolved

1. Change the line in your Gemfile to this, to ensure that you have version 2.3 or greater.

```rb
gem 'epi_deploy', '>= 2.3', github: 'epigenesys/epi_deploy'
```

1. Update epi_deploy in your application's gems

```sh
bundle update epi_deploy
```

1. Create a file called `config/epi_deploy.rb` if it does not already exist, with this configuration option:

```rb
EpiDeploy.use_timestamped_deploy_tags = true
```

1. If it hasn't be added already, add this line to `Capfile`

```rb
require 'capistrano/epi_deploy'
```

1. Commit and push your changes, then deploy to a demo site to test it is working correctly.

If you've previously used the `use_tags_for_deploy` configuration option, then this has now been removed since v2.3. If you upgrade to v2.3, then you should remove the old deployment tags manually from your local repo and remotely by doing, e.g.

```sh
git tag --delete production demo
git push origin --delete production demo
```

and remove the old `EpiDeploy.use_tags_for_deploy` from your application's `config/epi_deploy.rb` file.

Note: In the future we intend to change this configuration option to default to true.
You can then use the deployment branches (the default behaviour) or the new tags for deployment.
44 changes: 2 additions & 42 deletions bin/ed
Original file line number Diff line number Diff line change
@@ -1,45 +1,5 @@
#!/usr/bin/env ruby

require 'slop'
require_relative '../lib/epi_deploy/command'
require_relative '../lib/epi_deploy/cli'

config_path = File.join(Dir.pwd, 'config/epi_deploy.rb')
if File.exist?(config_path)
require config_path
end

begin
opts = Slop.parse strict: true do

banner 'Usage: bundle exec epi_deploy <command>'

command 'release' do
description 'Create a new release with optional deploy'

on :d=, :deploy=, 'Deploy to specified environment(s)', argument: :optional, as: Array, delimiter: ':'

run do |options, args|
command = EpiDeploy::Command.new(options, args)
command.release
end
end

command 'deploy' do
description 'Deploys an existing release'

on :r=, :ref=, 'Git reference to deploy', argument: :optional

run do |options, args|
command = EpiDeploy::Command.new(options, args)
command.deploy
end
end

run do |options, args|
Kernel.abort "\x1B[31mValid commands are 'release' and 'deploy'.\x1B[0m"
end

end
rescue Slop::InvalidOptionError, Slop::InvalidArgumentError, RuntimeError => e
Kernel.abort "\x1B[31m#{e.message}\x1B[0m"
end
EpiDeploy::Cli.new.run!
44 changes: 2 additions & 42 deletions bin/epi_deploy
Original file line number Diff line number Diff line change
@@ -1,45 +1,5 @@
#!/usr/bin/env ruby

require 'slop'
require_relative '../lib/epi_deploy/command'
require_relative '../lib/epi_deploy/cli'

config_path = File.join(Dir.pwd, 'config/epi_deploy.rb')
if File.exist?(config_path)
require config_path
end

begin
opts = Slop.parse strict: true do

banner 'Usage: bundle exec epi_deploy <command>'

command 'release' do
description 'Create a new release with optional deploy'

on :d=, :deploy=, 'Deploy to specified environment(s)', argument: :optional, as: Array, delimiter: ':'

run do |options, args|
command = EpiDeploy::Command.new(options, args)
command.release
end
end

command 'deploy' do
description 'Deploys an existing release'

on :r=, :ref=, 'Git reference to deploy', argument: :optional

run do |options, args|
command = EpiDeploy::Command.new(options, args)
command.deploy
end
end

run do |options, args|
Kernel.abort "\x1B[31mValid commands are 'release' and 'deploy'.\x1B[0m"
end

end
rescue Slop::InvalidOptionError, Slop::InvalidArgumentError, RuntimeError => e
Kernel.abort "\x1B[31m#{e.message}\x1B[0m"
end
EpiDeploy::Cli.new.run!
4 changes: 2 additions & 2 deletions epi_deploy.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ require 'epi_deploy/version'
Gem::Specification.new do |gem|
gem.name = "epi_deploy"
gem.version = EpiDeploy::VERSION
gem.authors = ["Anthony Nettleship", "Shuo Chen", "Chris Hunt", "James Gregory"]
gem.email = ["[email protected]", "[email protected]", "[email protected]", "[email protected]"]
gem.authors = ["Anthony Nettleship", "Shuo Chen", "Chris Hunt", "James Gregory", "William Lee"]
gem.email = ["[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]"]
gem.description = "A gem to facilitate deployment across multiple git branches and evironments"
gem.summary = "eD"
gem.homepage = "https://www.epigenesys.org.uk"
Expand Down
2 changes: 1 addition & 1 deletion lib/capistrano/epi_deploy.rb
Original file line number Diff line number Diff line change
@@ -1 +1 @@
load File.join(File.dirname(__FILE__), 'tasks', 'multi_customers.rb')
Dir.glob(File.join(File.dirname(__FILE__), 'tasks', '*.rb')).each { |f| require f }
25 changes: 25 additions & 0 deletions lib/capistrano/tasks/branches.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require_relative '../../epi_deploy/config'

Dir["config/initializers/version.rb", "config/epi_deploy.rb"].each do |file|
require File.join(Dir.pwd, file)
end

if EpiDeploy.use_timestamped_deploy_tags
namespace :epi_deploy do
task :set_branch do
branch = if ENV['BRANCH']
ENV['BRANCH']
elsif Object.const_defined?('LATEST_RELEASE_TAG')
LATEST_RELEASE_TAG
end

if branch.nil?
raise 'Cannot determine commit to deploy as BRANCH environment variable is not set and LATEST_RELEASE_TAG constant in version.rb could not be found'
end

set :branch, branch
end
end

before 'deploy:starting', 'epi_deploy:set_branch'
end
5 changes: 4 additions & 1 deletion lib/capistrano/tasks/multi_customers.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
namespace :epi_deploy do
task :symlink_customer_configs do
on release_roles :all do
execute :ln, '-s', release_path.join("config/customers/customer_settings/#{fetch(:current_customer)}.yml"), release_path.join("config/customer_settings.yml")
customer_settings_path = release_path.join("config/customers/customer_settings/#{fetch(:current_customer)}.yml")
if test("[ -f #{customer_settings_path}]")
execute :ln, '-s', customer_settings_path, release_path.join("config/customer_settings.yml")
end
end
end
end
Expand Down
60 changes: 39 additions & 21 deletions lib/epi_deploy/app_version.rb
Original file line number Diff line number Diff line change
@@ -1,38 +1,56 @@
module EpiDeploy
class AppVersion
attr_reader :version_file_path
attr_accessor :version_file_path, :version, :latest_release_tag

def initialize(current_dir = Dir.pwd)
@version_file_path = File.join(current_dir, 'config/initializers/version.rb')
self.version_file_path = File.join(current_dir, 'config/initializers/version.rb')
end

def initial_version_file_if_required
self.version = 0 unless version_file_exists?
end

def bump!
self.version = version + 1
end

def version
@version ||= extract_version_number

def load
if version_file_exists?
File.open(version_file_path) do |f|
contents = f.read
self.version = extract_version_number(contents)
self.latest_release_tag = extract_latest_release_tag(contents)
end
else
self.version = 0
self.latest_release_tag = ''
end
end
def version=(new_version)

def save!
File.open version_file_path, 'w' do |f|
f.write "APP_VERSION = '#{new_version}'"
f.write "APP_VERSION = '#{version}'\n"
f.write "LATEST_RELEASE_TAG = '#{latest_release_tag}'\n"
end
@version = extract_version_number
end


def bump
self.version += 1
end

def self.open(current_dir = Dir.pwd)
app_version = self.new(current_dir)
app_version.load
app_version
end

private
def version_file_exists?
File.exist? version_file_path
end

def extract_version_number
return 0 unless version_file_exists?
File.read(version_file_path).match(/APP_VERSION = '(?<version>\d+).*'/)[:version].to_i
def extract_version_number(contents)
contents.match(/APP_VERSION\s*=\s*'(?<version>\d+).*'/)[:version].to_i
end

def extract_latest_release_tag(contents)
if (match = contents.match(/LATEST_RELEASE_TAG\s*=\s*'(?<tag>[A-Za-z0-9_-]+)'/))
match[:tag]
else
''
end
end

end
Expand Down
54 changes: 54 additions & 0 deletions lib/epi_deploy/cli.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
require 'slop'

require_relative 'command'

module EpiDeploy
class Cli
def run!
load_config

Slop.parse strict: true do

banner 'Usage: bundle exec epi_deploy <command>'

command 'release' do
description 'Create a new release with optional deploy'

on :d=, :deploy=, 'Deploy to specified environment(s)', argument: :optional, as: Array, delimiter: ':'

run do |options, args|
command = EpiDeploy::Command.new(options, args)
command.release
end
end

command 'deploy' do
description 'Deploys an existing release'

on :r=, :ref=, 'Git reference to deploy', argument: :optional

run do |options, args|
command = EpiDeploy::Command.new(options, args)
command.deploy
end
end

run do |options, args|
Kernel.abort "\x1B[31mValid commands are 'release' and 'deploy'.\x1B[0m"
end

end
rescue Slop::InvalidOptionError, Slop::InvalidArgumentError, RuntimeError => e
Kernel.abort "\x1B[31m#{e.message}\x1B[0m"
end

private

def load_config
config_path = File.join(Dir.pwd, 'config/epi_deploy.rb')
if File.exist?(config_path)
require config_path
end
end
end
end
Loading
Loading