diff --git a/Capfile b/Capfile new file mode 100644 index 0000000..42dd3a4 --- /dev/null +++ b/Capfile @@ -0,0 +1,38 @@ +# Load DSL and set up stages +require "capistrano/setup" + +# Include default deployment tasks +require "capistrano/deploy" + +# Load the SCM plugin appropriate to your project: +# +# require "capistrano/scm/hg" +# install_plugin Capistrano::SCM::Hg +# or +# require "capistrano/scm/svn" +# install_plugin Capistrano::SCM::Svn +# or +require "capistrano/scm/git" +install_plugin Capistrano::SCM::Git + +# Include tasks from other gems included in your Gemfile +# +# For documentation on these, see for example: +# +# https://github.com/capistrano/rvm +# https://github.com/capistrano/rbenv +# https://github.com/capistrano/chruby +# https://github.com/capistrano/bundler +# https://github.com/capistrano/rails +# https://github.com/capistrano/passenger +# +# require "capistrano/rvm" +# require "capistrano/rbenv" +# require "capistrano/chruby" +# require "capistrano/bundler" +# require "capistrano/rails/assets" +# require "capistrano/rails/migrations" +# require "capistrano/passenger" + +# Load custom tasks from `lib/capistrano/tasks` if you have any defined +Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r } diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..8e3bf0a --- /dev/null +++ b/Gemfile @@ -0,0 +1,6 @@ +source "https://rubygems.org" + +group :development do + # Use Capistrano for deployment + gem 'capistrano' +end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..84822b2 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,29 @@ +GEM + remote: https://rubygems.org/ + specs: + airbrussh (1.3.0) + sshkit (>= 1.6.1, != 1.7.0) + capistrano (3.10.1) + airbrussh (>= 1.0.0) + i18n + rake (>= 10.0.0) + sshkit (>= 1.9.0) + concurrent-ruby (1.0.5) + i18n (1.0.0) + concurrent-ruby (~> 1.0) + net-scp (1.2.1) + net-ssh (>= 2.6.5) + net-ssh (4.2.0) + rake (12.3.1) + sshkit (1.16.0) + net-scp (>= 1.1.2) + net-ssh (>= 2.8.0) + +PLATFORMS + ruby + +DEPENDENCIES + capistrano + +BUNDLED WITH + 1.16.1 diff --git a/config/deploy.rb b/config/deploy.rb new file mode 100644 index 0000000..693f4b1 --- /dev/null +++ b/config/deploy.rb @@ -0,0 +1,9 @@ +# config valid for current version and patch releases of Capistrano +lock "~> 3.10.1" + +set :application, "todolist-backend" +set :repo_url, "git@github.com:guillaumebriday/todolist-backend-laravel.git" +set :branch, :master +set :deploy_to, '/var/www/todolist-backend' +set :docker_compose, "#{fetch(:deploy_to)}/docker-compose.yml" +set :env, "#{fetch(:deploy_to)}/.env" diff --git a/config/deploy/production.rb b/config/deploy/production.rb new file mode 100644 index 0000000..03951e5 --- /dev/null +++ b/config/deploy/production.rb @@ -0,0 +1,14 @@ +server '192.168.50.4', user: 'vagrant', roles: %w{app db web} + +after 'deploy:updated', 'docker:build' +after 'deploy:updated', 'template:compose' +after 'deploy:updated', 'template:env' + +after 'deploy:updated', 'composer:install' + +after 'deploy:updated', 'docker:stop' + +after 'deploy:updated', 'artisan:migrate' +after 'deploy:updated', 'artisan:seed' + +after 'deploy:published', 'docker:up' diff --git a/config/deploy/staging.rb b/config/deploy/staging.rb new file mode 100644 index 0000000..4bb7a71 --- /dev/null +++ b/config/deploy/staging.rb @@ -0,0 +1,61 @@ +# server-based syntax +# ====================== +# Defines a single server with a list of roles and multiple properties. +# You can define all roles on a single server, or split them: + +# server "example.com", user: "deploy", roles: %w{app db web}, my_property: :my_value +# server "example.com", user: "deploy", roles: %w{app web}, other_property: :other_value +# server "db.example.com", user: "deploy", roles: %w{db} + + + +# role-based syntax +# ================== + +# Defines a role with one or multiple servers. The primary server in each +# group is considered to be the first unless any hosts have the primary +# property set. Specify the username and a domain or IP for the server. +# Don't use `:all`, it's a meta role. + +# role :app, %w{deploy@example.com}, my_property: :my_value +# role :web, %w{user1@primary.com user2@additional.com}, other_property: :other_value +# role :db, %w{deploy@example.com} + + + +# Configuration +# ============= +# You can set any configuration variable like in config/deploy.rb +# These variables are then only loaded and set in this stage. +# For available Capistrano configuration variables see the documentation page. +# http://capistranorb.com/documentation/getting-started/configuration/ +# Feel free to add new variables to customise your setup. + + + +# Custom SSH Options +# ================== +# You may pass any option but keep in mind that net/ssh understands a +# limited set of options, consult the Net::SSH documentation. +# http://net-ssh.github.io/net-ssh/classes/Net/SSH.html#method-c-start +# +# Global options +# -------------- +# set :ssh_options, { +# keys: %w(/home/rlisowski/.ssh/id_rsa), +# forward_agent: false, +# auth_methods: %w(password) +# } +# +# The server-based syntax can be used to override options: +# ------------------------------------ +# server "example.com", +# user: "user_name", +# roles: %w{web app}, +# ssh_options: { +# user: "user_name", # overrides user setting above +# keys: %w(/home/user_name/.ssh/id_rsa), +# forward_agent: false, +# auth_methods: %w(publickey password) +# # password: "please use keys" +# } diff --git a/lib/capistrano/tasks/artisan.rake b/lib/capistrano/tasks/artisan.rake new file mode 100644 index 0000000..f296075 --- /dev/null +++ b/lib/capistrano/tasks/artisan.rake @@ -0,0 +1,19 @@ +namespace :artisan do + desc 'Running migrations' + task :migrate do + on roles(:app) do + within release_path do + execute 'docker-compose' , :run, '--rm', 'todolist-server', :php, :artisan, :migrate, '--force' + end + end + end + + desc 'Running seed' + task :seed do + on roles(:app) do + within release_path do + execute 'docker-compose' , :run, '--rm', 'todolist-server', :php, :artisan, 'db:seed', '--force' + end + end + end +end diff --git a/lib/capistrano/tasks/composer.rake b/lib/capistrano/tasks/composer.rake new file mode 100644 index 0000000..b1c2e52 --- /dev/null +++ b/lib/capistrano/tasks/composer.rake @@ -0,0 +1,10 @@ +namespace :composer do + desc 'Install dependencies' + task :install do + on roles(:app) do + within release_path do + execute 'docker-compose' , :run, '--no-deps', '--rm', '-u www-data', 'todolist-server', :composer, :install, '--no-dev', '--quiet' + end + end + end +end diff --git a/lib/capistrano/tasks/docker.rake b/lib/capistrano/tasks/docker.rake new file mode 100644 index 0000000..7092e7d --- /dev/null +++ b/lib/capistrano/tasks/docker.rake @@ -0,0 +1,45 @@ +namespace :docker do + desc 'Build images' + task :build do + on roles(:app) do + set :previous_release_path, previous_release + within release_path do + execute :docker, :build, '-t', fetch(:application), "#{release_path}/provisioning" + end + end + end + + desc 'Stopping old containers' + task :stop do + on roles(:app) do + if fetch(:previous_release_path, false) + within fetch(:previous_release_path) do + containers = capture :'docker-compose', 'ps', '-q' + unless containers.empty? + info "Purging containers of previous release at #{fetch(:previous_release_path)}" + execute :'docker-compose', 'down', '--remove-orphans' + end + end + end + end + end + + desc 'Run app containers' + task :up do + on roles(:app) do + within release_path do + execute "docker-compose", :up, "-d" + end + end + end + + def previous_release + path = "#{fetch(:deploy_to)}/current" + + if test("[ -L #{path} ]") + return capture("readlink -f #{path}") + end + + return nil + end +end diff --git a/lib/capistrano/tasks/template.rake b/lib/capistrano/tasks/template.rake new file mode 100644 index 0000000..0b2e991 --- /dev/null +++ b/lib/capistrano/tasks/template.rake @@ -0,0 +1,19 @@ +namespace :template do + desc 'Copying the docker-compose file' + task :compose do + on roles(:app) do + within release_path do + execute :cp, fetch(:docker_compose), 'docker-compose.yml' + end + end + end + + desc 'Copying the .env file' + task :env do + on roles(:app) do + within release_path do + execute :cp, fetch(:env), '.env' + end + end + end +end