groundskeeper-bitcore 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +15 -15
- data/config/db_config.yml.erb +10 -0
- data/config/deploy.rb +112 -0
- data/config/git_config.rb +42 -0
- data/config/predeploy.rb +104 -0
- data/config/rails_config.rb.erb +88 -0
- data/config/secrets_config.yml.erb +3 -0
- data/config/tasks.rb +40 -0
- data/config/vhost_config.conf.erb +49 -0
- data/groundskeeper.gemspec +2 -5
- data/lib/groundskeeper.rb +1 -0
- data/lib/groundskeeper/application.rb +15 -0
- data/lib/groundskeeper/commands.rb +85 -1
- data/lib/groundskeeper/jira.rb +49 -3
- data/lib/groundskeeper/project.rb +79 -3
- data/lib/groundskeeper/version.rb +1 -1
- data/lib/groundskeeper/website.rb +20 -0
- data/servers.yml +35 -0
- metadata +28 -24
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -2
- metadata.gz.sig +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2a59a195b265d2acb9f80f92047a932b9d383774
|
4
|
+
data.tar.gz: cc30dafde4d041ded80022417a6aab76f91505c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a6e194b5cb47ff597fe0088a77b2d9767f949bc748c51813a65a01e4e6460c54b6c62526e02eac519ff2f8d9693a390fe5620d2e80272366169cfcbd4ff35d3
|
7
|
+
data.tar.gz: 0be07658c32a457a974e6b7809b5e8c021e00acf632d3b33f032513d0c3d1a69e1e3a04c0ec9865a73a6b5ca4adf1202dcb08e8b0b34948b78086f1604e81cf0
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.2.0 - 2017-11-29
|
4
|
+
|
5
|
+
* IN-8 Fixes #47 transition Jira issues upon deployment (#48)
|
6
|
+
* update script and instructions for predeployment (#46)
|
7
|
+
* Fixes #27 warn user if Jira env variables aren't set (#45)
|
8
|
+
* ensure RAILS_ENV gets set remotely during deployment (#44)
|
9
|
+
* enable production deployment (#43)
|
10
|
+
* IN-7 Merge rails_deployment functionality into groundskeeper (#40)
|
11
|
+
|
3
12
|
## 0.1.1 - 2017-09-14
|
4
13
|
|
5
14
|
* sign gem and update installation instructions (#37)
|
data/README.md
CHANGED
@@ -5,30 +5,17 @@ deploying Rails applications.
|
|
5
5
|
|
6
6
|
## Installation
|
7
7
|
|
8
|
-
Groundskeeper is cryptographically signed. To be sure this gem hasn't been
|
9
|
-
tampered with, add the following public key if you have not already:
|
10
|
-
|
11
|
-
```bash
|
12
|
-
gem cert --add <(curl -Ls https://raw.github.com/NU-CBITS/groundskeeper/master/certs/ericcf.pem)
|
13
|
-
```
|
14
|
-
|
15
8
|
Install this gem globally via:
|
16
9
|
|
17
10
|
```bash
|
18
|
-
gem install groundskeeper -P HighSecurity
|
11
|
+
gem install groundskeeper-bitcore -P HighSecurity
|
19
12
|
```
|
20
13
|
|
21
14
|
The HighSecurity trust profile will verify signed gems and require that all
|
22
15
|
dependencies are signed.
|
23
16
|
|
24
17
|
Note: if you have multiple versions of Ruby installed (via RVM e.g.), you will
|
25
|
-
need to install this gem for each of them.
|
26
|
-
application directory and the groundskeeper source are in the same parent
|
27
|
-
directory:
|
28
|
-
|
29
|
-
```bash
|
30
|
-
gem install ../groundskeeper/groundskeeper-<version>.gem
|
31
|
-
```
|
18
|
+
need to install this gem for each of them.
|
32
19
|
|
33
20
|
Additionally, to integrate with Jira you will need to set some environment
|
34
21
|
variables. One standard place to do this is in the `~/.bash_profile`:
|
@@ -62,6 +49,19 @@ application directory:
|
|
62
49
|
ground release
|
63
50
|
```
|
64
51
|
|
52
|
+
To prepare the server (only required the first time) for deployment:
|
53
|
+
|
54
|
+
```bash
|
55
|
+
tag=0.0.0 stage=production ground predeploy
|
56
|
+
```
|
57
|
+
|
58
|
+
To deploy the release (note that `stage` is optional and will be set to staging
|
59
|
+
by default):
|
60
|
+
|
61
|
+
```bash
|
62
|
+
tag=0.0.0 stage=production ground deploy
|
63
|
+
```
|
64
|
+
|
65
65
|
## Development
|
66
66
|
|
67
67
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<% project = fetch :project %>
|
2
|
+
<% db_env_variables = project.db_env_variables(fetch :stage) %>
|
3
|
+
<%= (fetch :stage).to_s %>:
|
4
|
+
adapter: postgresql
|
5
|
+
encoding: unicode
|
6
|
+
pool: 5
|
7
|
+
host: <%= db_env_variables["host"] %>
|
8
|
+
database: <%= db_env_variables["database"] %>
|
9
|
+
username: <%%= ENV['<%= db_env_variables["username"] %>'] %>
|
10
|
+
password: <%%= ENV['<%= db_env_variables["password"] %>'] %>
|
data/config/deploy.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "mina/rails"
|
4
|
+
require "mina/git"
|
5
|
+
require "mina/rvm" # for rvm support. (https://rvm.io)
|
6
|
+
|
7
|
+
require_relative "./git_config.rb"
|
8
|
+
require_relative "./predeploy.rb"
|
9
|
+
require_relative "./tasks.rb"
|
10
|
+
|
11
|
+
def load_project
|
12
|
+
invoke :before_run unless fetch(:project)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Basic settings:
|
16
|
+
# domain - The hostname to SSH to.
|
17
|
+
# deploy_to - Path to deploy into.
|
18
|
+
# repository - Git repo to clone from. (needed by mina/git)
|
19
|
+
# branch - Branch name to deploy. (needed by mina/git)
|
20
|
+
|
21
|
+
# set :application_name, 'foobar'
|
22
|
+
# set :domain, 'foobar.com'
|
23
|
+
# set :deploy_to, '/var/www/foobar.com'
|
24
|
+
# set :repository, 'git://...'
|
25
|
+
# set :branch, 'master'
|
26
|
+
|
27
|
+
# Optional settings:
|
28
|
+
# set :user, 'foobar' # Username in the server to SSH to.
|
29
|
+
# set :port, '30000' # SSH port number.
|
30
|
+
# set :forward_agent, true # SSH forward_agent.
|
31
|
+
|
32
|
+
# Shared dirs and files will be symlinked into the app-folder by the
|
33
|
+
# 'deploy:link_shared_paths' step. Some plugins already add folders to
|
34
|
+
# shared_dirs like `mina/rails` add `public/assets`, `vendor/bundle` and many
|
35
|
+
# more run `mina -d` to see all folders and files already included in
|
36
|
+
# `shared_dirs` and `shared_files`
|
37
|
+
set :shared_dirs, fetch(:shared_dirs, []).push(
|
38
|
+
"log",
|
39
|
+
"tmp/pids",
|
40
|
+
"tmp/cache",
|
41
|
+
"tmp/sockets",
|
42
|
+
"bundle",
|
43
|
+
"public/system"
|
44
|
+
)
|
45
|
+
|
46
|
+
set :shared_files, fetch(:shared_files, []).push(
|
47
|
+
"config/database.yml",
|
48
|
+
"config/secrets.yml"
|
49
|
+
)
|
50
|
+
|
51
|
+
# This task is the environment that is loaded for all remote run commands, such
|
52
|
+
# as `mina deploy` or `mina rake`.
|
53
|
+
task :environment do
|
54
|
+
# Be sure to commit your .ruby-version to your repository.
|
55
|
+
# For those using RVM, use this to load an RVM version@gemset.
|
56
|
+
# invoke :'rvm:use', 'ruby-1.9.3-p125@default'
|
57
|
+
end
|
58
|
+
|
59
|
+
# Put any custom commands you need to run at setup
|
60
|
+
# All paths in `shared_dirs` and `shared_paths` will be created on their own.
|
61
|
+
task :setup do
|
62
|
+
end
|
63
|
+
|
64
|
+
task :staging do
|
65
|
+
set :stage, :staging
|
66
|
+
set :rails_env, "staging"
|
67
|
+
end
|
68
|
+
|
69
|
+
task :production do
|
70
|
+
set :stage, :production
|
71
|
+
set :rails_env, "production"
|
72
|
+
end
|
73
|
+
|
74
|
+
if ENV["stage"] == "production"
|
75
|
+
invoke :production
|
76
|
+
else
|
77
|
+
invoke :staging
|
78
|
+
end
|
79
|
+
|
80
|
+
desc "Run predeployment tasks."
|
81
|
+
task predeploy: :remote_environment do
|
82
|
+
load_project
|
83
|
+
run :remote do
|
84
|
+
invoke :setup
|
85
|
+
end
|
86
|
+
invoke :'deploy_configure:create_configs'
|
87
|
+
invoke :'deploy_prepare:create_vhost'
|
88
|
+
invoke :'deploy_prepare:configure_pg'
|
89
|
+
invoke :'deploy_prepare:set_owner'
|
90
|
+
end
|
91
|
+
|
92
|
+
desc "Deploys the current version to the server."
|
93
|
+
task deploy: :remote_environment do
|
94
|
+
load_project
|
95
|
+
deploy do
|
96
|
+
# Put things that will set up an empty directory into a fully set-up
|
97
|
+
# instance of your project.
|
98
|
+
invoke :rvm_use
|
99
|
+
invoke :checkout_release
|
100
|
+
invoke :link_shared_dirs
|
101
|
+
invoke :'bundle:install'
|
102
|
+
invoke :'rails:db_migrate'
|
103
|
+
invoke :'rails:assets_precompile'
|
104
|
+
invoke :'deploy:cleanup'
|
105
|
+
|
106
|
+
on :launch do
|
107
|
+
invoke :restart
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
invoke :open_browser
|
112
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
require "json"
|
5
|
+
require "groundskeeper"
|
6
|
+
|
7
|
+
desc "Sets up project details."
|
8
|
+
# rubocop:disable Metrics/BlockLength
|
9
|
+
task :before_run do
|
10
|
+
application = %x(basename `git rev-parse --show-toplevel`).strip!
|
11
|
+
unless Groundskeeper::Project.available_applications.include? application
|
12
|
+
raise "must be inside application repo (currently in #{application}). " \
|
13
|
+
"available applications: " +
|
14
|
+
Groundskeeper::Project.available_applications
|
15
|
+
end
|
16
|
+
|
17
|
+
project = Groundskeeper::Project.build(application)
|
18
|
+
set :project, project
|
19
|
+
|
20
|
+
set :application_name, application
|
21
|
+
set :domain, project.full_dns(fetch(:stage))
|
22
|
+
set :user, "deploy"
|
23
|
+
set :repository, project.repo_url
|
24
|
+
set :deploy_to, project.deploy_to
|
25
|
+
set :forward_agent, true
|
26
|
+
set :bundle_path, "bundle"
|
27
|
+
|
28
|
+
set :rvm_ruby_version, project.rvm_ruby_version
|
29
|
+
set :rvm_type, :system
|
30
|
+
|
31
|
+
# On each deploy, prompt for the tag
|
32
|
+
puts "Looking up tags for project #{application}... (#{project.repo_url})"
|
33
|
+
tags = project.tags
|
34
|
+
raise "There must be a tagged release prior to deploying." if tags.count.zero?
|
35
|
+
tag = ENV["tag"]
|
36
|
+
unless tags.include? tag
|
37
|
+
raise "Tag \"#{tag}\" not found. Available tags:\n #{tags.join("\n")}"
|
38
|
+
end
|
39
|
+
set :branch, "master"
|
40
|
+
set :tag, "tags/#{tag}"
|
41
|
+
end
|
42
|
+
# rubocop:enable Metrics/BlockLength
|
data/config/predeploy.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
PG_CONFIG = "/usr/pgsql-9.3/bin/pg_config"
|
4
|
+
|
5
|
+
def load_template(name)
|
6
|
+
template_str = File.binread(File.join(File.dirname(__FILE__), name))
|
7
|
+
template = ERB.new(template_str, nil, "-")
|
8
|
+
template.result
|
9
|
+
end
|
10
|
+
|
11
|
+
def environments_dir
|
12
|
+
"#{fetch :deploy_to}/shared/config/environments"
|
13
|
+
end
|
14
|
+
|
15
|
+
def secrets_config_file
|
16
|
+
"#{fetch :deploy_to}/shared/config/secrets.yml"
|
17
|
+
end
|
18
|
+
|
19
|
+
def database_config_file
|
20
|
+
"#{fetch :deploy_to}/shared/config/database.yml"
|
21
|
+
end
|
22
|
+
|
23
|
+
def rails_config_file
|
24
|
+
"#{environments_dir}/#{fetch :stage}.rb"
|
25
|
+
end
|
26
|
+
|
27
|
+
def vhost_config_file
|
28
|
+
"/etc/httpd/conf.d/#{fetch :application_name}.conf"
|
29
|
+
end
|
30
|
+
|
31
|
+
def remote_shared_path(path)
|
32
|
+
"#{fetch(:user)}@#{fetch(:domain)}:#{fetch(:shared_path)}/#{path}"
|
33
|
+
end
|
34
|
+
|
35
|
+
# rubocop:disable Metrics/BlockLength
|
36
|
+
namespace :deploy_configure do
|
37
|
+
desc "Create database and secrets"
|
38
|
+
task create_configs: :remote_environment do
|
39
|
+
load_project
|
40
|
+
|
41
|
+
secrets_config = load_template("secrets_config.yml.erb")
|
42
|
+
db_config = load_template("db_config.yml.erb")
|
43
|
+
# TODO: Move environment variables to env.yml
|
44
|
+
rails_config = load_template("rails_config.rb.erb")
|
45
|
+
|
46
|
+
run :remote do
|
47
|
+
command "mkdir -p #{environments_dir}"
|
48
|
+
end
|
49
|
+
|
50
|
+
if File.exist? "./config/secrets.yml"
|
51
|
+
invoke :'deploy_configure:copy_secrets'
|
52
|
+
end
|
53
|
+
|
54
|
+
comment "Writing staging secrets to #{secrets_config_file}"
|
55
|
+
comment "touch #{secrets_config_file}"
|
56
|
+
run :remote do
|
57
|
+
command "echo \"#{secrets_config}\" >> #{secrets_config_file}"
|
58
|
+
end
|
59
|
+
|
60
|
+
comment "Writing database config to #{database_config_file}"
|
61
|
+
run :remote do
|
62
|
+
command "echo \"#{db_config}\" > #{database_config_file}"
|
63
|
+
end
|
64
|
+
|
65
|
+
comment "Writing Rails config to #{rails_config_file}"
|
66
|
+
run :remote do
|
67
|
+
command "echo \"#{rails_config}\" > #{rails_config_file}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
desc "Copy secrets,"
|
72
|
+
task :copy_secrets do
|
73
|
+
path = remote_shared_path("config/secrets.yml")
|
74
|
+
comment "Copying secrets.yml to #{path}."
|
75
|
+
run :local do
|
76
|
+
command = "scp ./config/secrets.yml #{path}"
|
77
|
+
puts `#{command}`
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
# rubocop:enable Metrics/BlockLength
|
82
|
+
|
83
|
+
namespace :deploy_prepare do
|
84
|
+
desc "Write the virtual host config file. May require an Apache restart."
|
85
|
+
task :create_vhost do
|
86
|
+
load_project
|
87
|
+
vhost_config = load_template("vhost_config.conf.erb")
|
88
|
+
|
89
|
+
comment "Writing virtual host config to #{vhost_config_file}"
|
90
|
+
command "echo \"#{vhost_config}\" > #{vhost_config_file}"
|
91
|
+
end
|
92
|
+
|
93
|
+
desc "Configure Postgres."
|
94
|
+
task :configure_pg do
|
95
|
+
comment "Configuring Postgres with config #{PG_CONFIG}"
|
96
|
+
command "bundle config build.pg -- --with-pg-config=#{PG_CONFIG}"
|
97
|
+
end
|
98
|
+
|
99
|
+
desc "Set owner."
|
100
|
+
task :set_owner do
|
101
|
+
comment "Setting owner of #{fetch :deploy_to} apache"
|
102
|
+
command "sudo chgrp -R apache #{fetch :deploy_to}"
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
<% project = fetch :project %>
|
2
|
+
Rails.application.configure do
|
3
|
+
# For catching exceptions
|
4
|
+
config.sentry_dsn = '<%= project.sentry_dsn %>'
|
5
|
+
config.sentry_public_dsn = '<%= project.sentry_public_dsn %>'
|
6
|
+
|
7
|
+
# Settings specified here will take precedence over those in config/application.rb.
|
8
|
+
|
9
|
+
# Code is not reloaded between requests.
|
10
|
+
config.cache_classes = true
|
11
|
+
|
12
|
+
# Eager load code on boot. This eager loads most of Rails and
|
13
|
+
# your application in memory, allowing both thread web servers
|
14
|
+
# and those relying on copy on write to perform better.
|
15
|
+
# Rake tasks automatically ignore this option for performance.
|
16
|
+
config.eager_load = true
|
17
|
+
|
18
|
+
# Full error reports are disabled and caching is turned on.
|
19
|
+
config.consider_all_requests_local = false
|
20
|
+
config.action_controller.perform_caching = true
|
21
|
+
|
22
|
+
# Disable serving static files from the `/public` folder by default since
|
23
|
+
# Apache or NGINX already handles this.
|
24
|
+
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
|
25
|
+
|
26
|
+
# Compress JavaScripts and CSS.
|
27
|
+
config.assets.js_compressor = :uglifier
|
28
|
+
# config.assets.css_compressor = :sass
|
29
|
+
|
30
|
+
# Do not fallback to assets pipeline if a precompiled asset is missed.
|
31
|
+
config.assets.compile = false
|
32
|
+
|
33
|
+
# Specifies the header that your server uses for sending files.
|
34
|
+
config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for apache
|
35
|
+
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
|
36
|
+
|
37
|
+
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
|
38
|
+
config.force_ssl = true
|
39
|
+
|
40
|
+
# Set to :debug to see everything in the log.
|
41
|
+
config.log_level = :info
|
42
|
+
|
43
|
+
# Prepend all log lines with the following tags.
|
44
|
+
config.log_tags = [ :request_id ]
|
45
|
+
|
46
|
+
# Use a different logger for distributed setups.
|
47
|
+
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
|
48
|
+
|
49
|
+
# Use a different cache store in production.
|
50
|
+
# config.cache_store = :mem_cache_store
|
51
|
+
|
52
|
+
config.action_mailer.perform_caching = false
|
53
|
+
|
54
|
+
# Precompile additional assets.
|
55
|
+
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
|
56
|
+
# config.assets.precompile += %w( search.js )
|
57
|
+
|
58
|
+
# Ignore bad email addresses and do not raise email delivery errors.
|
59
|
+
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
|
60
|
+
config.action_mailer.default_url_options = { host: '<%= fetch :domain %>' }
|
61
|
+
config.action_mailer.delivery_method = :smtp
|
62
|
+
config.action_mailer.raise_delivery_errors = false
|
63
|
+
config.action_mailer.perform_deliveries = true
|
64
|
+
config.action_mailer.smtp_settings = {
|
65
|
+
authentication: :plain,
|
66
|
+
address: 'smtp.mailgun.org',
|
67
|
+
port: 587,
|
68
|
+
domain: 'cbits.northwestern.edu',
|
69
|
+
user_name: ENV['mailgun_db_username'],
|
70
|
+
password: ENV['mailgun_db_password']
|
71
|
+
}
|
72
|
+
|
73
|
+
Rails.application.routes.default_url_options[:host] = '<%= fetch :domain %>'
|
74
|
+
Rails.application.routes.default_url_options[:protocol] = 'https'
|
75
|
+
|
76
|
+
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
|
77
|
+
# the I18n.default_locale when a translation can not be found).
|
78
|
+
config.i18n.fallbacks = true
|
79
|
+
|
80
|
+
# Send deprecation notices to registered listeners.
|
81
|
+
config.active_support.deprecation = :notify
|
82
|
+
|
83
|
+
# Disable automatic flushing of the log to improve performance.
|
84
|
+
# config.autoflush_log = false
|
85
|
+
|
86
|
+
# Use default logging formatter so that PID and timestamp are not suppressed.
|
87
|
+
config.log_formatter = ::Logger::Formatter.new
|
88
|
+
end
|
data/config/tasks.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
desc "Restart application"
|
4
|
+
task :restart do
|
5
|
+
in_path(fetch(:current_path)) do
|
6
|
+
command %(mkdir -p tmp/)
|
7
|
+
command %(touch tmp/restart.txt)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "Checks out the selected release tag"
|
12
|
+
task :checkout_release do
|
13
|
+
comment "Checking out release \"#{fetch :tag}\""
|
14
|
+
command %(git clone -b "#{fetch :branch}" "#{fetch :repository}" .)
|
15
|
+
command "git fetch"
|
16
|
+
command %(git checkout "#{fetch :tag}")
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "Uses an RVM envionment"
|
20
|
+
task :rvm_use do
|
21
|
+
command "rvm use \"ruby-#{fetch :rvm_ruby_version}\""
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "Link shared directories."
|
25
|
+
task :link_shared_dirs do
|
26
|
+
# Must be set after :stage is set
|
27
|
+
set :shared_files, fetch(:shared_files, []).push(
|
28
|
+
"config/environments/#{fetch :stage}.rb"
|
29
|
+
)
|
30
|
+
|
31
|
+
comment "Shared directories: #{(fetch :shared_dirs).join("\n")}"
|
32
|
+
invoke :'deploy:link_shared_paths'
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "Open the newly deployed server in the browser (for macOS)."
|
36
|
+
task :open_browser do
|
37
|
+
run(:local) do
|
38
|
+
command "open https://#{fetch :domain}"
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
<% project = fetch :project -%>
|
2
|
+
<VirtualHost *:80>
|
3
|
+
ServerName <%= fetch :domain %>
|
4
|
+
Redirect permanent / https://<%= fetch :domain -%>/
|
5
|
+
</VirtualHost>
|
6
|
+
|
7
|
+
<VirtualHost *:443>
|
8
|
+
PassengerFriendlyErrorPages off
|
9
|
+
PassengerAppEnv <%= fetch :stage %>
|
10
|
+
PassengerRuby /usr/local/rvm/wrappers/ruby-<%= fetch :rvm_ruby_version -%>/ruby
|
11
|
+
# Always have at least 1 process in existence for the application
|
12
|
+
PassengerMinInstances 1
|
13
|
+
|
14
|
+
ServerName <%= fetch :domain %>
|
15
|
+
|
16
|
+
SSLEngine On
|
17
|
+
SSLCertificateFile <%= project.ssl_certificate_file(fetch(:stage).to_sym) %>
|
18
|
+
SSLCertificateChainFile <%= project.ssl_certificate_chain_file(fetch(:stage).to_sym) %>
|
19
|
+
SSLCertificateKeyFile <%= project.ssl_certificate_key_file(fetch(:stage).to_sym) %>
|
20
|
+
|
21
|
+
DocumentRoot <%= fetch :deploy_to -%>/current/public
|
22
|
+
RailsBaseURI /
|
23
|
+
PassengerDebugLogFile /var/log/httpd/passenger.log
|
24
|
+
|
25
|
+
<Directory <%= fetch :deploy_to -%>/current/public >
|
26
|
+
Allow from all
|
27
|
+
Options -MultiViews
|
28
|
+
</Directory>
|
29
|
+
|
30
|
+
AddOutputFilterByType DEFLATE text/html text/css application/javascript
|
31
|
+
|
32
|
+
RewriteEngine On
|
33
|
+
|
34
|
+
# Show maintenance page if it exists
|
35
|
+
ErrorDocument 503 /system/maintenance.html
|
36
|
+
RewriteCond %{REQUEST_URI} !\.(css|gif|jpg|png)$
|
37
|
+
RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
|
38
|
+
RewriteCond %{SCRIPT_FILENAME} !maintenance.html
|
39
|
+
RewriteRule ^.*$ - [redirect=503,last]
|
40
|
+
|
41
|
+
<Location /assets/>
|
42
|
+
# RFC says only cache for 1 year
|
43
|
+
ExpiresActive On
|
44
|
+
ExpiresDefault \"access plus 1 year\"
|
45
|
+
</Location>
|
46
|
+
</VirtualHost>
|
47
|
+
|
48
|
+
# Start the application before the first access
|
49
|
+
PassengerPreStart https://<%= fetch :domain -%>:443/
|
data/groundskeeper.gemspec
CHANGED
@@ -15,10 +15,6 @@ Gem::Specification.new do |spec|
|
|
15
15
|
spec.homepage = "https://github.com/NU-CBITS/groundskeeper.git"
|
16
16
|
spec.license = "MIT"
|
17
17
|
spec.cert_chain = ["certs/ericcf.pem"]
|
18
|
-
if $PROGRAM_NAME.end_with?("gem")
|
19
|
-
spec.signing_key = File.expand_path("~/.ssh/gem-private_key.pem")
|
20
|
-
end
|
21
|
-
|
22
18
|
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the
|
23
19
|
# 'allowed_push_host' to allow pushing to a single host or delete this
|
24
20
|
# section to allow pushing to any host.
|
@@ -34,10 +30,11 @@ Gem::Specification.new do |spec|
|
|
34
30
|
end
|
35
31
|
spec.bindir = "bin"
|
36
32
|
spec.executables = "ground"
|
37
|
-
spec.require_paths = [
|
33
|
+
spec.require_paths = %w[lib config]
|
38
34
|
|
39
35
|
spec.add_dependency "jira-ruby", "~> 1.3"
|
40
36
|
spec.add_dependency "thor", "~> 0.19"
|
37
|
+
spec.add_dependency "mina", "~> 1.2"
|
41
38
|
|
42
39
|
spec.add_development_dependency "bundler", "~> 1.15"
|
43
40
|
spec.add_development_dependency "minitest", "~> 5.0"
|
data/lib/groundskeeper.rb
CHANGED
@@ -7,6 +7,9 @@ module Groundskeeper
|
|
7
7
|
class Application < Thor
|
8
8
|
attr_reader :commands
|
9
9
|
|
10
|
+
class_option :simulate, desc: "Simulate mina"
|
11
|
+
class_option :verbose, desc: "Run mina verbosely"
|
12
|
+
|
10
13
|
def initialize(args = [], local_options = {}, config = {})
|
11
14
|
@commands = Commands.build(self)
|
12
15
|
super
|
@@ -22,5 +25,17 @@ module Groundskeeper
|
|
22
25
|
commands.info
|
23
26
|
commands.release
|
24
27
|
end
|
28
|
+
|
29
|
+
desc "predeploy", "create configuration files for the project"
|
30
|
+
def predeploy
|
31
|
+
commands.info
|
32
|
+
commands.predeploy options
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "deploy", "deploy the latest release"
|
36
|
+
def deploy
|
37
|
+
commands.info
|
38
|
+
commands.deploy options
|
39
|
+
end
|
25
40
|
end
|
26
41
|
end
|
@@ -1,9 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "rake"
|
4
|
+
require "mina"
|
5
|
+
require "pp"
|
6
|
+
require "open3"
|
7
|
+
|
3
8
|
module Groundskeeper
|
4
|
-
# Formulas for managing releases.
|
9
|
+
# Formulas for managing releases and deployments.
|
5
10
|
# rubocop:disable Metrics/ClassLength
|
6
11
|
class Commands
|
12
|
+
RAKEFILE = File.join(
|
13
|
+
File.dirname(__FILE__), "..", "..", "config", "deploy.rb"
|
14
|
+
)
|
15
|
+
STAGE = "stage"
|
16
|
+
STAGING = "staging"
|
17
|
+
PRODUCTION = "production"
|
18
|
+
DEFAULT_STAGE = STAGING
|
19
|
+
TAG = "tag"
|
20
|
+
|
7
21
|
# rubocop:disable Metrics/MethodLength
|
8
22
|
def self.build(console)
|
9
23
|
repository = Repository.new
|
@@ -67,8 +81,10 @@ module Groundskeeper
|
|
67
81
|
)
|
68
82
|
end
|
69
83
|
|
84
|
+
# rubocop:disable Metrics/AbcSize
|
70
85
|
def release
|
71
86
|
return unrecognized_version unless version_file.exists?
|
87
|
+
return missing_jira_credentials unless jira.credentials?
|
72
88
|
|
73
89
|
summarize_recent_commits
|
74
90
|
ask_next_version
|
@@ -81,8 +97,21 @@ module Groundskeeper
|
|
81
97
|
ask_add_version_to_jira_issues
|
82
98
|
open_pull_request_page
|
83
99
|
end
|
100
|
+
# rubocop:enable Metrics/AbcSize
|
84
101
|
# rubocop:enable Metrics/MethodLength
|
85
102
|
|
103
|
+
def predeploy(options)
|
104
|
+
return unrecognized_version unless version_file.exists?
|
105
|
+
|
106
|
+
mina "predeploy", options
|
107
|
+
end
|
108
|
+
|
109
|
+
def deploy(options)
|
110
|
+
return unrecognized_version unless version_file.exists?
|
111
|
+
|
112
|
+
mina "deploy", options
|
113
|
+
end
|
114
|
+
|
86
115
|
private
|
87
116
|
|
88
117
|
# collaborators
|
@@ -92,6 +121,15 @@ module Groundskeeper
|
|
92
121
|
attr_reader :next_version, :recent_commits, :did_checkout_branch,
|
93
122
|
:did_push_to_remote
|
94
123
|
|
124
|
+
def mina(command, options)
|
125
|
+
cmd = String.new command
|
126
|
+
cmd << " -s" if options[:simulate]
|
127
|
+
cmd << " -v" if options[:verbose]
|
128
|
+
run_mina cmd
|
129
|
+
console.say("waiting for deployed application to restart...", :yellow)
|
130
|
+
update_deployed_issues
|
131
|
+
end
|
132
|
+
|
95
133
|
def announce_version
|
96
134
|
console.say("Groundskeeper version #{Groundskeeper::VERSION}\n\n", :bold)
|
97
135
|
end
|
@@ -185,6 +223,13 @@ module Groundskeeper
|
|
185
223
|
)
|
186
224
|
end
|
187
225
|
|
226
|
+
def missing_jira_credentials
|
227
|
+
console.say(
|
228
|
+
"Please configure your Jira environment variables.",
|
229
|
+
:red
|
230
|
+
)
|
231
|
+
end
|
232
|
+
|
188
233
|
def open_pull_request_page
|
189
234
|
return unless did_checkout_branch && did_push_to_remote
|
190
235
|
|
@@ -194,6 +239,45 @@ module Groundskeeper
|
|
194
239
|
def new_branch_name
|
195
240
|
"v#{next_version}"
|
196
241
|
end
|
242
|
+
|
243
|
+
def run_mina(arguments)
|
244
|
+
command = "mina #{arguments} -f #{RAKEFILE}"
|
245
|
+
Open3.popen3(command) do |_stdout, stderr, _status, _thread|
|
246
|
+
# rubocop:disable Lint/AssignmentInCondition
|
247
|
+
while line = stderr.gets
|
248
|
+
puts line
|
249
|
+
end
|
250
|
+
# rubocop:enable Lint/AssignmentInCondition
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
def update_deployed_issues
|
255
|
+
deployed_url = "https://#{project.full_dns(stage)}"
|
256
|
+
deployed_version = Website.new(deployed_url).version
|
257
|
+
|
258
|
+
if deployed_version == ENV[TAG]
|
259
|
+
console.say("# deployment successful", :green)
|
260
|
+
transition_remote_issues deployed_version
|
261
|
+
else
|
262
|
+
console.say("something went wrong", :red)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
def stage
|
267
|
+
ENV[STAGE] == PRODUCTION ? PRODUCTION : DEFAULT_STAGE
|
268
|
+
end
|
269
|
+
|
270
|
+
def transition_remote_issues(version)
|
271
|
+
version_name = "#{repository.name} #{version}"
|
272
|
+
deployed_issues = jira.fetch_issues_by_fix_version(version_name)
|
273
|
+
action = stage == PRODUCTION ? Jira::DELIVER : Jira::DEPLOY_TO_STAGING
|
274
|
+
console.say(
|
275
|
+
"transitioning deployed issues in Jira: " \
|
276
|
+
"#{action} #{deployed_issues.join(', ')}",
|
277
|
+
:yellow
|
278
|
+
)
|
279
|
+
jira.transition_remote_issues(action, deployed_issues)
|
280
|
+
end
|
197
281
|
end
|
198
282
|
# rubocop:enable Metrics/ClassLength
|
199
283
|
end
|
data/lib/groundskeeper/jira.rb
CHANGED
@@ -6,6 +6,16 @@ require "jira-ruby"
|
|
6
6
|
module Groundskeeper
|
7
7
|
# Wraps an interface to Jira.
|
8
8
|
class Jira
|
9
|
+
JIRA_USERNAME_KEY = "JIRA_USERNAME"
|
10
|
+
JIRA_PASSWORD_KEY = "JIRA_PASSWORD"
|
11
|
+
JIRA_SITE_KEY = "JIRA_SITE"
|
12
|
+
DEPLOY_TO_STAGING = "Deploy to Staging"
|
13
|
+
DELIVER = "Deliver"
|
14
|
+
TRANSITION_IDS = {
|
15
|
+
DEPLOY_TO_STAGING => 231,
|
16
|
+
DELIVER => 201
|
17
|
+
}.freeze
|
18
|
+
|
9
19
|
attr_reader :client, :prefix
|
10
20
|
|
11
21
|
ISSUE_PATTERN = "%s-\\d+"
|
@@ -16,9 +26,9 @@ module Groundskeeper
|
|
16
26
|
|
17
27
|
def initialize
|
18
28
|
@client = JIRA::Client.new(
|
19
|
-
username: ENV[
|
20
|
-
password: ENV[
|
21
|
-
site: ENV[
|
29
|
+
username: ENV[JIRA_USERNAME_KEY],
|
30
|
+
password: ENV[JIRA_PASSWORD_KEY],
|
31
|
+
site: ENV[JIRA_SITE_KEY],
|
22
32
|
context_path: "",
|
23
33
|
auth_type: :basic,
|
24
34
|
read_timeout: 120
|
@@ -36,6 +46,23 @@ module Groundskeeper
|
|
36
46
|
.find(issue_id)
|
37
47
|
.save(update: { fixVersions: [{ add: { name: version_name } }] })
|
38
48
|
end
|
49
|
+
|
50
|
+
def transition_issue(issue_id:, transition_id:)
|
51
|
+
client.Issue
|
52
|
+
.find(issue_id)
|
53
|
+
.transitions
|
54
|
+
.build
|
55
|
+
.save(transition: { id: transition_id })
|
56
|
+
end
|
57
|
+
|
58
|
+
def fetch_issues_by_fix_version(version:)
|
59
|
+
search_path = "/rest/api/2/search"
|
60
|
+
query = "fixVersion = \"#{version}\""
|
61
|
+
response =
|
62
|
+
client.get("#{search_path}?fields=key&jql=#{URI.escape(query)}").body
|
63
|
+
|
64
|
+
JSON.parse(response)["issues"].map { |issue| issue["key"] }
|
65
|
+
end
|
39
66
|
end
|
40
67
|
|
41
68
|
def self.build(prefix)
|
@@ -50,6 +77,12 @@ module Groundskeeper
|
|
50
77
|
@client = client
|
51
78
|
end
|
52
79
|
|
80
|
+
def credentials?
|
81
|
+
ENV[JIRA_USERNAME_KEY].present? &&
|
82
|
+
ENV[JIRA_PASSWORD_KEY].present? &&
|
83
|
+
ENV[JIRA_SITE_KEY].present?
|
84
|
+
end
|
85
|
+
|
53
86
|
# Returns the list of Jira issues found in a set of commit messages.
|
54
87
|
def included_issues(changes)
|
55
88
|
issue_expression = /#{format(ISSUE_PATTERN, prefix)}/
|
@@ -66,5 +99,18 @@ module Groundskeeper
|
|
66
99
|
client.add_version_to_issue(issue_id: issue_id, version_name: name)
|
67
100
|
end
|
68
101
|
end
|
102
|
+
|
103
|
+
def transition_remote_issues(transition_type, issue_ids)
|
104
|
+
issue_ids.each do |issue_id|
|
105
|
+
client.transition_issue(
|
106
|
+
issue_id: issue_id,
|
107
|
+
transition_id: TRANSITION_IDS[transition_type]
|
108
|
+
)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def fetch_issues_by_fix_version(version)
|
113
|
+
client.fetch_issues_by_fix_version(version: version)
|
114
|
+
end
|
69
115
|
end
|
70
116
|
end
|
@@ -1,27 +1,46 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "yaml"
|
4
|
+
require "json"
|
4
5
|
|
5
6
|
module Groundskeeper
|
6
7
|
# Accesses project details stored in the home directory.
|
7
8
|
class Project
|
8
|
-
attr_reader :details
|
9
|
+
attr_reader :details, :servers, :repo_name
|
9
10
|
|
10
11
|
DETAILS_PATH = "~/.project_details/projects.yml"
|
12
|
+
SERVERS_PATH = "../../servers.yml"
|
11
13
|
JIRA_PREFIX_KEY = "jira_prefix"
|
12
14
|
PROJECT_NAME_KEY = "name"
|
13
15
|
SOURCE_CONTROL_USERNAME_KEY = "scm_username"
|
16
|
+
FULL_DNS_KEY = "full_dns"
|
17
|
+
RVM_RUBY_VERSION_KEY = "ruby_version"
|
18
|
+
DB_ENV_VARIABLES_KEY = "db_env_variables"
|
19
|
+
SENTRY_DSN_KEY = "sentry_dsn"
|
20
|
+
SENTRY_PUBLIC_DSN_KEY = "sentry_public_dsn"
|
21
|
+
SSL_CERTIFICATE_FILE_KEY = "SSLCertificateFile"
|
22
|
+
SSL_CERTIFICATE_CHAIN_FILE_KEY = "SSLCertificateChainFile"
|
23
|
+
SSL_CERTIFICATE_KEY_FILE_KEY = "SSLCertificateKeyFile"
|
14
24
|
|
15
25
|
def self.build(repository_name)
|
16
26
|
new(
|
17
|
-
|
27
|
+
projects_yaml: Document.new(DETAILS_PATH).read,
|
28
|
+
servers_yaml: Document.new(SERVERS_PATH).read,
|
18
29
|
repository_name: repository_name
|
19
30
|
)
|
20
31
|
end
|
21
32
|
|
22
|
-
def
|
33
|
+
def self.available_applications
|
34
|
+
yaml = Document.new(DETAILS_PATH).read
|
23
35
|
projects = YAML.safe_load(yaml) || {}
|
36
|
+
projects.keys.join(", ")
|
37
|
+
end
|
38
|
+
|
39
|
+
def initialize(projects_yaml:, servers_yaml:, repository_name:)
|
40
|
+
projects = YAML.safe_load(projects_yaml) || {}
|
24
41
|
@details = projects[repository_name] || {}
|
42
|
+
@servers = YAML.safe_load(servers_yaml) || {}
|
43
|
+
@repo_name = repository_name
|
25
44
|
end
|
26
45
|
|
27
46
|
def project_name
|
@@ -35,5 +54,62 @@ module Groundskeeper
|
|
35
54
|
def source_control_username
|
36
55
|
details[SOURCE_CONTROL_USERNAME_KEY] || ""
|
37
56
|
end
|
57
|
+
|
58
|
+
def full_dns(stage)
|
59
|
+
details.dig(FULL_DNS_KEY, stage.to_s) || ""
|
60
|
+
end
|
61
|
+
|
62
|
+
def db_env_variables(stage)
|
63
|
+
details.dig(DB_ENV_VARIABLES_KEY, stage.to_s) || ""
|
64
|
+
end
|
65
|
+
|
66
|
+
def rvm_ruby_version
|
67
|
+
details[RVM_RUBY_VERSION_KEY] || ""
|
68
|
+
end
|
69
|
+
|
70
|
+
def sentry_dsn
|
71
|
+
details[SENTRY_DSN_KEY] || ""
|
72
|
+
end
|
73
|
+
|
74
|
+
def sentry_public_dsn
|
75
|
+
details[SENTRY_PUBLIC_DSN_KEY] || ""
|
76
|
+
end
|
77
|
+
|
78
|
+
def ssl_certificate_file(stage)
|
79
|
+
details.dig(SSL_CERTIFICATE_FILE_KEY, stage.to_s) || ""
|
80
|
+
end
|
81
|
+
|
82
|
+
def ssl_certificate_chain_file(stage)
|
83
|
+
details.dig(SSL_CERTIFICATE_CHAIN_FILE_KEY, stage.to_s) || ""
|
84
|
+
end
|
85
|
+
|
86
|
+
def ssl_certificate_key_file(stage)
|
87
|
+
details.dig(SSL_CERTIFICATE_KEY_FILE_KEY, stage.to_s) || ""
|
88
|
+
end
|
89
|
+
|
90
|
+
def server_config(stage)
|
91
|
+
servers[full_dns(stage)]
|
92
|
+
end
|
93
|
+
|
94
|
+
def repo_url
|
95
|
+
"git@github.com:#{source_control_username}/#{repo_name}.git"
|
96
|
+
end
|
97
|
+
|
98
|
+
def deploy_to
|
99
|
+
"/var/www/apps/#{repo_name}"
|
100
|
+
end
|
101
|
+
|
102
|
+
def tags
|
103
|
+
api_url = "https://api.github.com/repos/" \
|
104
|
+
"#{source_control_username}/#{repo_name}/tags"
|
105
|
+
authorization_header = "Authorization: token #{ENV['GITHUB_API_TOKEN']}"
|
106
|
+
response = JSON.parse(`curl -s -H "#{authorization_header}" #{api_url}`)
|
107
|
+
unless response.is_a?(Array)
|
108
|
+
message = response["message"]
|
109
|
+
puts "Failed to obtain response: #{message}"
|
110
|
+
return []
|
111
|
+
end
|
112
|
+
response.map { |h| h["name"] }
|
113
|
+
end
|
38
114
|
end
|
39
115
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "open-uri"
|
4
|
+
|
5
|
+
module Groundskeeper
|
6
|
+
# A deployed website/application.
|
7
|
+
class Website
|
8
|
+
VERSION_PATH = "version.txt"
|
9
|
+
|
10
|
+
attr_reader :uri
|
11
|
+
|
12
|
+
def initialize(uri)
|
13
|
+
@uri = uri
|
14
|
+
end
|
15
|
+
|
16
|
+
def version
|
17
|
+
URI.parse("#{uri}/#{VERSION_PATH}").read
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/servers.yml
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
cbits-railsapps-staging:
|
2
|
+
domain: cbits-railsapps-staging.nubic.northwestern.edu
|
3
|
+
SSLCertificateFile: /etc/pki/tls/certs/cbits.northwestern.edu.crt
|
4
|
+
SSLCertificateChainFile: /etc/pki/tls/certs/cbits.northwestern.edu_intermediate.crt
|
5
|
+
SSLCertificateKeyFile: /etc/pki/tls/private/cbits.northwestern.edu.key
|
6
|
+
cbits-railsapps:
|
7
|
+
domain: cbits-railsapps.nubic.northwestern.edu
|
8
|
+
SSLCertificateFile: /etc/pki/tls/certs/cbits-railsapps.nubic.northwestern.edu.crt
|
9
|
+
SSLCertificateChainFile: /etc/pki/tls/certs/komodo_intermediate_ca.crt
|
10
|
+
SSLCertificateKeyFile: /etc/pki/tls/private/cbits-railsapps.nubic.northwestern.edu.key
|
11
|
+
vtfsmcbitsapps01:
|
12
|
+
domain: vtfsmcbitsapps01.fsm.northwestern.edu
|
13
|
+
SSLCertificateFile: /etc/pki/tls/certs/cbits.northwestern.edu.crt
|
14
|
+
SSLCertificateChainFile: /etc/pki/tls/certs/cbits.northwestern.edu_intermediate.crt
|
15
|
+
SSLCertificateKeyFile: /etc/pki/tls/private/cbits.northwestern.edu.key
|
16
|
+
vfsmcbitsapps10:
|
17
|
+
domain: vfsmcbitsapps10.fsm.northwestern.edu
|
18
|
+
SSLCertificateFile: /etc/pki/tls/certs/vfsmcbitsapps10_nubic_northwestern_edu_cert.cer
|
19
|
+
SSLCertificateChainFile: /etc/pki/tls/certs/vfsmcbitsapps10_nubic_northwestern_edu_interm.cer
|
20
|
+
SSLCertificateKeyFile: /etc/pki/tls/private/cbits-railsapps.nubic.northwestern.edu.key
|
21
|
+
vfsmcbitsapps11:
|
22
|
+
domain: vfsmcbitsapps11.fsm.northwestern.edu
|
23
|
+
SSLCertificateFile: /etc/pki/tls/certs/vfsmcbitsapps11_nubic_northwestern_edu_cert.cer
|
24
|
+
SSLCertificateChainFile: /etc/pki/tls/certs/vfsmcbitsapps11_nubic_northwestern_edu_interm.cer
|
25
|
+
SSLCertificateKeyFile: /etc/pki/tls/private/cbits-railsapps.nubic.northwestern.edu.key
|
26
|
+
vfsmcbitsapps12:
|
27
|
+
domain: vfsmcbitsapps12.fsm.northwestern.edu
|
28
|
+
SSLCertificateFile: /etc/pki/tls/certs/vfsmcbitsapps12.fsm.northwestern.edu.crt
|
29
|
+
SSLCertificateChainFile: /etc/pki/tls/certs/vfsmcbitsapps12.fsm.northwestern.edu_intermediate.crt
|
30
|
+
SSLCertificateKeyFile: /etc/pki/tls/private/cbits-railsapps.nubic.northwestern.edu.key
|
31
|
+
vfsmcbitsapps13:
|
32
|
+
domain: vfsmcbitsapps13.fsm.northwestern.edu
|
33
|
+
SSLCertificateFile: /etc/pki/tls/certs/vfsmcbitsapps13.fsm.northwestern.edu.crt
|
34
|
+
SSLCertificateChainFile: /etc/pki/tls/certs/vfsmcbitsapps13.fsm.northwestern.edu_intermediate.crt
|
35
|
+
SSLCertificateKeyFile: /etc/pki/tls/private/cbits-railsapps.nubic.northwestern.edu.key
|
metadata
CHANGED
@@ -1,36 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: groundskeeper-bitcore
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- BIT Core
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain:
|
11
|
-
-
|
12
|
-
|
13
|
-
MIIDhTCCAm2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQ8wDQYDVQQDDAZlcmlj
|
14
|
-
Y2YxHDAaBgoJkiaJk/IsZAEZFgxub3J0aHdlc3Rlcm4xEzARBgoJkiaJk/IsZAEZ
|
15
|
-
FgNlZHUwHhcNMTcwOTEyMjAwODQzWhcNMTgwOTEyMjAwODQzWjBEMQ8wDQYDVQQD
|
16
|
-
DAZlcmljY2YxHDAaBgoJkiaJk/IsZAEZFgxub3J0aHdlc3Rlcm4xEzARBgoJkiaJ
|
17
|
-
k/IsZAEZFgNlZHUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDk8FgP
|
18
|
-
SIrleTjIXJT/yu+W9nujkvcIMRPbLqKq60KQy/2LANMZ7DiLZRBkg2oSK0D9p8GR
|
19
|
-
be30F2DGAOSBZiBTLPDNAQZBpRVGeFpAAOEpREZ8ahaZVTfc8+IYSfxpnW2gaUte
|
20
|
-
SfbG5xNcpHkRpwkbZGoq9yFOoaucxfwoz+9QunEFDiCAumn7uRMKHJdqSEpQnFkQ
|
21
|
-
56GKuUvUuq7J+J4M+kwOK6a/4/Y8Bs/qUYH3GHa/0WJwfFLfp3gqhagLcZu40JFe
|
22
|
-
mQpX3bAkmojuxyAi7JjXKqFv1LZgxAGca5SC6sECXiTkw9eXInBKzvBN33gOv+Vj
|
23
|
-
9bot70L0EihaqJrnAgMBAAGjgYEwfzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAd
|
24
|
-
BgNVHQ4EFgQUsMK40utpv6yRQ3i0R7avJn3LQ/YwIgYDVR0RBBswGYEXZXJpY2Nm
|
25
|
-
QG5vcnRod2VzdGVybi5lZHUwIgYDVR0SBBswGYEXZXJpY2NmQG5vcnRod2VzdGVy
|
26
|
-
bi5lZHUwDQYJKoZIhvcNAQEFBQADggEBACvUVV3V8EYqV9DanJS3ywMVnQB5ByP1
|
27
|
-
7TV70+Amnnu196Jp2JGJ27sjeE79VJeBbGyE0rCRUQXlaD2Zh8X6Yy04oWR0YFa8
|
28
|
-
DQ3rqVmKTodTJ0K/rmpIMCbwrsyg7QRxfB6cUE+sgPX5ygDmj2gYY+fcw3MoVOif
|
29
|
-
QY1i1gFSjcXvx0qnvQLnbD+gbr7D3wpfgFHRbBEDOuNdpFthggUO6eFraVYcsz9u
|
30
|
-
1v/mC2s7Cj+Jv053bCKPjSk2wLLZpHRs40jXgy/NudtouDy2yYlJHxBFfdeRNEk2
|
31
|
-
fo8I5WeWdUoEzUI6WlkTjMw3nWezlF0LCGz781P4qvtz0BICgaS41qw=
|
32
|
-
-----END CERTIFICATE-----
|
33
|
-
date: 2017-09-15 00:00:00.000000000 Z
|
11
|
+
- certs/ericcf.pem
|
12
|
+
date: 2017-11-29 00:00:00.000000000 Z
|
34
13
|
dependencies:
|
35
14
|
- !ruby/object:Gem::Dependency
|
36
15
|
name: jira-ruby
|
@@ -60,6 +39,20 @@ dependencies:
|
|
60
39
|
- - "~>"
|
61
40
|
- !ruby/object:Gem::Version
|
62
41
|
version: '0.19'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: mina
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '1.2'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '1.2'
|
63
56
|
- !ruby/object:Gem::Dependency
|
64
57
|
name: bundler
|
65
58
|
requirement: !ruby/object:Gem::Requirement
|
@@ -138,6 +131,14 @@ files:
|
|
138
131
|
- bin/ground
|
139
132
|
- bin/setup
|
140
133
|
- certs/ericcf.pem
|
134
|
+
- config/db_config.yml.erb
|
135
|
+
- config/deploy.rb
|
136
|
+
- config/git_config.rb
|
137
|
+
- config/predeploy.rb
|
138
|
+
- config/rails_config.rb.erb
|
139
|
+
- config/secrets_config.yml.erb
|
140
|
+
- config/tasks.rb
|
141
|
+
- config/vhost_config.conf.erb
|
141
142
|
- groundskeeper.gemspec
|
142
143
|
- lib/groundskeeper.rb
|
143
144
|
- lib/groundskeeper/application.rb
|
@@ -151,6 +152,8 @@ files:
|
|
151
152
|
- lib/groundskeeper/rails_version.rb
|
152
153
|
- lib/groundskeeper/repository.rb
|
153
154
|
- lib/groundskeeper/version.rb
|
155
|
+
- lib/groundskeeper/website.rb
|
156
|
+
- servers.yml
|
154
157
|
homepage: https://github.com/NU-CBITS/groundskeeper.git
|
155
158
|
licenses:
|
156
159
|
- MIT
|
@@ -160,6 +163,7 @@ post_install_message:
|
|
160
163
|
rdoc_options: []
|
161
164
|
require_paths:
|
162
165
|
- lib
|
166
|
+
- config
|
163
167
|
required_ruby_version: !ruby/object:Gem::Requirement
|
164
168
|
requirements:
|
165
169
|
- - ">="
|
checksums.yaml.gz.sig
DELETED
Binary file
|
data.tar.gz.sig
DELETED
metadata.gz.sig
DELETED