...
 
Commits (54)
......@@ -17,8 +17,11 @@
/tmp
config/secrets.yml
config/database.yml
config/settings.local.yml
config/settings/*.local.yml
config/environments/*.local.yml
.env
.bash_profile
#!/bin/bash
set -e
echo "Starting app-config.sh @ `date`"
echo "Running rake db:migrate @ `date`"
bundle exec rake db:migrate
# Sometimes something gets left over
echo "Removing server.pid @ `date`"
rm -f /var/www/current/tmp/pids/server.pid
# Symlink in settings.local.yml
ln -s /conf/settings.local.yml /var/www/current/config/settings.local.yml
rm -rf /var/www/current/public/system
ln -s /public/system /var/www/current/public/system
echo "Finished app-config.sh @ `date`"
......@@ -2,10 +2,10 @@ source 'https://rubygems.org'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.2.4'
gem 'rails'
# Use sqlite3 as the database for Active Record
gem 'sqlite3', group: [:development, :test]
gem 'mysql2', '~> 0.3.18', group: :production
gem 'sqlite3', '~> 1.3.13', group: [:development, :test]
gem 'mysql2', '~> 0.4.10', group: :production
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
......@@ -57,6 +57,14 @@ group :development do
gem 'spring'
end
group :assets do
gem 'ejs'
gem "activerecord-nulldb-adapter"
end
# delayed job - as opposed to redis
gem 'delayed_job_active_record'
# use config to store API secrets, etc.
gem "config", "~> 1.0.0"
......@@ -66,8 +74,10 @@ gem 'simple_form'
# authentication
# gem 'devise', "~> 3.5.2"
gem 'net-ssh', '~> 3.1.0'
gem 'net-ssh', '~> 5.0.0'
gem 'net-scp', '~> 1.2.1'
gem 'ed25519', '>= 1.2', '< 2.0'
gem 'bcrypt_pbkdf', '>= 1.0', '< 2.0'
# authorization
gem "pundit"
......@@ -88,3 +98,5 @@ gem 'bootstrap-sass', '~> 3.3.5'
# post to Slack
gem 'slack-notifier', '~> 1.5.1'
gem 'nokogiri', '~> 1.6', '>= 1.6.8.1'
This diff is collapsed.
pipeline {
agent {
node {
label 'atomic'
}
}
stages {
stage ('Generate Dockerfile') {
steps {
sh '''
source /build/pipeline_vars
repackage_upstream_image stevedore-repo.oit.duke.edu/el7-rails
'''
}
}
stage ('Build Image') {
steps {
sh '''
source /build/pipeline_vars
build
'''
}
}
stage ('Save Build Artifact') {
steps {
sh '''
source /build/pipeline_vars
docker tag ${BUILD_IMAGE_TAG} ${REMOTE_IMAGE_TAG}
docker push ${REMOTE_IMAGE_TAG}
'''
}
}
stage('Test') {
steps {
parallel (
Integrity: {
sh '''
source /build/pipeline_vars
test
'''
},
SysSecurity: {
sh '''
source /build/pipeline_vars
check_cves 7.0
'''
}
)
}
}
stage('Push Image Latest') {
steps {
sh '''
source /build/pipeline_vars
tag
'''
}
}
}
post {
always {
sh '''
source /build/pipeline_vars
cleanup_images
'''
}
failure {
mail(from: "doozer@build.docker.oit.duke.edu",
to: "christopher.collins@duke.edu, ml354@duke.edu",
subject: "${JOB_NAME} Image Build Failed",
body: "Something failed with the ${JOB_NAME} image build: ${RUN_DISPLAY_URL}")
}
}
}
......@@ -80,8 +80,8 @@ class AppFilesController < ApplicationController
format.html { redirect_to @app_file.app, notice: 'App file has been uploaded.' }
format.json { render :show, status: :created, location: @app_file }
SendSlackUpdateJob.perform_later "[!!] %s uploaded [%s](%s) (ver. %s for %s) <!channel>" \
% [if current_user.nil? then 'Guest' else current_user.display_name end, @app_file.app.name, app_url(@app_file.app), @app_file.version, @app_file.platform].map { |s| SlackNotifier.escape(s.to_s) }
# SendSlackUpdateJob.perform_later "[!!] %s uploaded [%s](%s) (ver. %s for %s) <!channel>" \
# % [if current_user.nil? then 'Guest' else current_user.display_name end, @app_file.app.name, app_url(@app_file.app), @app_file.version, @app_file.platform].map { |s| SlackNotifier.escape(s.to_s) }
else
format.html { render :new }
format.json { render json: @app_file.errors, status: :unprocessable_entity }
......@@ -129,11 +129,11 @@ class AppFilesController < ApplicationController
return
end
end
@app_file.increment!(:download_count)
SendSlackUpdateJob.perform_later "%s (IP: %s) downloaded [%s](%s) (ver. %s for %s)" \
% [if current_user.nil? then 'Guest' else current_user.display_name end, request.remote_ip, @app_file.app.name, app_url(@app_file.app), @app_file.version, @app_file.platform].map { |s| SlackNotifier.escape(s.to_s) }
# SendSlackUpdateJob.perform_later "%s (IP: %s) downloaded [%s](%s) (ver. %s for %s)" \
# % [if current_user.nil? then 'Guest' else current_user.display_name end, request.remote_ip, @app_file.app.name, app_url(@app_file.app), @app_file.version, @app_file.platform].map { |s| SlackNotifier.escape(s.to_s) }
end
# Use callbacks to share common setup or constraints between actions.
......
......@@ -44,8 +44,8 @@ class AppsController < ApplicationController
format.html { redirect_to @app, notice: 'App was successfully created.' }
format.json { render :show, status: :created, location: @app }
SendSlackUpdateJob.perform_later "[!!!] %s created a new app [%s](%s) <!channel>" \
% [if current_user.nil? then 'Guest' else current_user.display_name end, @app.name, app_url(@app)].map { |s| SlackNotifier.escape(s.to_s) }
# SendSlackUpdateJob.perform_later "[!!!] %s created a new app [%s](%s) <!channel>" \
# % [if current_user.nil? then 'Guest' else current_user.display_name end, @app.name, app_url(@app)].map { |s| SlackNotifier.escape(s.to_s) }
else
format.html { render :new }
format.json { render json: @app.errors, status: :unprocessable_entity }
......@@ -62,8 +62,8 @@ class AppsController < ApplicationController
format.html { redirect_to @app, notice: 'App was successfully updated.' }
format.json { render :show, status: :ok, location: @app }
SendSlackUpdateJob.perform_later "[!!!] %s updated information of app [%s](%s) <!channel>" \
% [if current_user.nil? then 'Guest' else current_user.display_name end, @app.name, app_url(@app)].map { |s| SlackNotifier.escape(s.to_s) }
# SendSlackUpdateJob.perform_later "[!!!] %s updated information of app [%s](%s) <!channel>" \
# % [if current_user.nil? then 'Guest' else current_user.display_name end, @app.name, app_url(@app)].map { |s| SlackNotifier.escape(s.to_s) }
else
format.html { render :edit }
format.json { render json: @app.errors, status: :unprocessable_entity }
......
......@@ -76,7 +76,7 @@ class BuildIpaJob < ActiveJob::Base
'iPhone Distribution: Duke University', # cert name in Keychain
'-e', File.join(tmpdir, 'entitlements.plist'),
# TODO: allow for multiple provisioning profiles and App IDs
'-p', Rails.root.join('resources', 'ios_provisioning_profiles', 'CoLab_Member_Apps_Nov_2017.mobileprovision').to_s,
'-p', Rails.root.join('resources', 'ios_provisioning_profiles', 'CoLab_Member_Apps_Nov_2018.mobileprovision').to_s,
'-b', app_file.app.ios_application_identifier,
'-t', File.join(tmpdir, 'floatsign_tmp'),
app_file.signed_ipa_path_on_signing_server
......
......@@ -13,14 +13,33 @@ class FetchedSignedIpaJob < ActiveJob::Base
# get file to app_file.signed_ipa_location
log << "scp from #{Settings.signing_worker.user}@#{Settings.signing_worker.host}:#{app_file.signed_ipa_path_on_signing_server} to #{app_file.signed_ipa_location}\n"
Net::SCP.download!(Settings.signing_worker.host, Settings.signing_worker.user,
app_file.signed_ipa_path_on_signing_server, app_file.signed_ipa_location)
Net::SCP.download!(
Settings.signing_worker.host,
Settings.signing_worker.user,
app_file.signed_ipa_path_on_signing_server,
app_file.signed_ipa_location,
{
:ssh => {
:verify_host_key => :never,
:user_known_hosts_file => '/dev/null',
:keys => ['/conf/my.key'],
:keys_only => true
}
})
# remove remote tmpdir and file
log << "removing sign:#{File.dirname(app_file.signed_ipa_path_on_signing_server)}\n"
Net::SSH.start(Settings.signing_worker.host, Settings.signing_worker.user) do |ssh|
ssh.exec "rm -rf \"#{File.dirname(app_file.signed_ipa_path_on_signing_server)}\""
end
# log << "removing sign:#{File.dirname(app_file.signed_ipa_path_on_signing_server)}\n"
# Net::SSH.start(
# Settings.signing_worker.host,
# Settings.signing_worker.user,
# {
# :verify_host_key => :never,
# :user_known_hosts_file => '/dev/null',
# :keys => ['/conf/my.key'],
# :keys_only => true
# }) do |ssh|
# ssh.exec "rm -rf \"#{File.dirname(app_file.signed_ipa_path_on_signing_server)}\""
# end
# remove user uploaded unsigned package to save space
log << "removing local, unsigned copy\n"
......
......@@ -6,7 +6,7 @@
</div>
</div>
<div class="row app-list">
<% @apps.each do |app| %>
<% @apps.reverse_each do |app| %>
<div class="col-sm-6 app-details">
<div class="row">
<div class="col-xs-3 app-icon">
......
#!/usr/bin/env ruby
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment'))
require 'delayed/command'
Delayed::Command.new(ARGV).daemonize
......@@ -27,7 +27,8 @@ module Appstore
# Be sure to have the adapter's gem in your Gemfile and follow
# the adapter's specific installation and deployment instructions.
config.active_job.queue_adapter = :resque
# config.active_job.queue_adapter = :resque
config.active_job.queue_adapter = :delayed_job
# Since many clients are from Duke private network,
# we need to customize the definition of trusted proxies to get their real
......
production:
adapter: nulldb
Delayed::Worker.destroy_failed_jobs = false
Delayed::Worker.sleep_delay = 60
Delayed::Worker.max_attempts = 3
Delayed::Worker.max_run_time = 5.minutes
Delayed::Worker.read_ahead = 10
Delayed::Worker.default_queue_name = 'default'
Delayed::Worker.delay_jobs = !Rails.env.test?
Delayed::Worker.raise_signal_exceptions = :term
Delayed::Worker.logger = Logger.new(File.join(Rails.root, 'log', 'delayed_job.log'))
\ No newline at end of file
Hashie.logger = Logger.new(nil)
Rails.application.config.middleware.use OmniAuth::Builder do
provider :duke_oauth2, Settings.duke_oauth2.client_id, Settings.duke_oauth2.client_secret
unless Settings.duke_oauth2.nil?
provider :duke_oauth2, Settings.duke_oauth2.client_id, Settings.duke_oauth2.client_secret
end
end
require 'paperclip/media_type_spoof_detector'
module Paperclip
class MediaTypeSpoofDetector
def spoofed?
false
end
end
end
Paperclip.options[:content_type_mappings] = {
ipa: 'application/zip'
}
# Paperclip.options[:command_path] = '/usr/bin/file'
::SlackNotifier = Slack::Notifier.new Settings.slack.webhook_url
# ::SlackNotifier = Slack::Notifier.new Settings.slack.webhook_url
......@@ -2,5 +2,5 @@ web:
host: appstore.colab.duke.edu
user: appstore
signing_worker:
host: appstore-mac.colab.managed.jiehan.org
host: 152.3.125.2
user: appstore
class CreateDelayedJobs < ActiveRecord::Migration
def self.up
create_table :delayed_jobs, force: true do |table|
table.integer :priority, default: 0, null: false # Allows some jobs to jump to the front of the queue
table.integer :attempts, default: 0, null: false # Provides for retries, but still fail eventually.
table.text :handler, null: false # YAML-encoded string of the object that will do work
table.text :last_error # reason for last failure (See Note below)
table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future.
table.datetime :locked_at # Set when a client is working on this object
table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
table.string :locked_by # Who is working on this object (if locked)
table.string :queue # The name of the queue this job is in
table.timestamps null: true
end
add_index :delayed_jobs, [:priority, :run_at], name: "delayed_jobs_priority"
end
def self.down
drop_table :delayed_jobs
end
end