groundskeeper-bitcore 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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