Merge pull request #83 from rtyler/developer-dashboard

Refactor a bit to prepare for the Jenkins Developer Dashboard
This commit is contained in:
R. Tyler Croy 2018-01-02 15:19:08 -08:00 committed by GitHub
commit 6ed480ba24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 233 additions and 21 deletions

View File

@ -33,7 +33,10 @@ ENV BUNDLE_DISABLE_SHARED_GEMS=true
ADD app.rb ${APP_DIR}/
ADD monkeys.txt ${APP_DIR}/
ADD config.ru ${APP_DIR}/
ADD views ${APP_DIR}/views/
ADD assets ${APP_DIR}/assets/
ADD lib ${APP_DIR}/lib
ADD views ${APP_DIR}/views
ADD assets ${APP_DIR}/assets
ADD plugins.yaml ${APP_DIR}/
CMD bundle exec puma

View File

@ -9,6 +9,9 @@ gem 'puma'
# For rendering all the views
gem 'haml'
# For dotted references to Hashes
gem 'hashie'
# Provides some semblance of github-based authentication and authorization
# within the rack app
gem 'warden-github'

View File

@ -16,6 +16,7 @@ GEM
haml (5.0.1)
temple (>= 0.8.0)
tilt
hashie (3.5.7)
i18n (0.8.6)
kramdown (1.14.0)
minitest (5.10.3)
@ -71,6 +72,7 @@ PLATFORMS
DEPENDENCIES
dalli
haml
hashie
kramdown
puma
rack-cache
@ -80,4 +82,4 @@ DEPENDENCIES
warden-github
BUNDLED WITH
1.16.0
1.16.1

View File

@ -7,14 +7,14 @@ check: spec check-container
depends: Gemfile
./scripts/ruby bundle install
spec: depends
spec: depends monkeys.txt
./scripts/ruby bundle exec rspec -c
run: depends monkeys.txt
./scripts/ruby bundle exec puma
check-container: container
docker run --rm $(IMAGE_NAME):latest bundle exec puma --version
IMAGE_NAME=$(IMAGE_NAME) ./scripts/container-check
container: depends Dockerfile monkeys.txt
docker build -t $(IMAGE_NAME) .

View File

@ -9,24 +9,19 @@ require 'rack/session/dalli'
require 'sinatra/base'
require 'warden/github'
require 'codevalet/webapp/authfailure'
require 'codevalet/webapp/monkeys'
require 'codevalet/webapp/plugins'
Haml::TempleEngine.disable_option_validator!
module CodeValet
class AuthFailre < Sinatra::Base
get '/unauthenticated' do
status 403
<<-EOS
<h2>Unable to authenticate, sorry bud.</h2>
<p>#{env['warden'].message}</p>
<p>#{ENV['REDIRECT_URI']}</p>
<p>#{ENV['GITHUB_CLIENT_ID']}</p>
EOS
end
end
# Primary web application for CodeValet.io
class App < Sinatra::Base
include Warden::GitHub::SSO
ADMINISTRATORS = %w(rtyler).freeze
enable :sessions
set :session_secret, ENV.fetch('SESSION_SECRET') { SecureRandom.hex(64) }
@ -47,7 +42,7 @@ module CodeValet
end
use Warden::Manager do |config|
config.failure_app = AuthFailre
config.failure_app = CodeValet::WebApp::AuthFailure
config.default_strategies :github
config.scope_defaults :default, :config => {
:scope => 'read:public_repo,user:email',
@ -66,13 +61,12 @@ module CodeValet
end
def masters
file_path = File.expand_path(File.dirname(__FILE__) + '/monkeys.txt')
@monkeys ||= File.open(file_path, 'r').readlines.map(&:chomp).sort
return CodeValet::WebApp::Monkeys.data
end
def admin?
return false unless env['warden'].user
return env['warden'].user.login == 'rtyler'
return ADMINISTRATORS.include? env['warden'].user.login
end
end

View File

@ -1,6 +1,7 @@
ENV['RACK_ENV'] ||= 'development'
$LOAD_PATH << File.dirname(__FILE__)
$LOAD_PATH << File.expand_path(File.dirname(__FILE__) + '/lib/')
require 'app'
require 'raven'

View File

@ -0,0 +1,19 @@
require 'sinatra/base'
module CodeValet
module WebApp
# Simple Sinatra application for enumerating a complete authentication
# failure with Warden
class AuthFailure < Sinatra::Base
get '/unauthenticated' do
status 403
<<-EOS
<h2>Unable to authenticate, sorry bud.</h2>
<p>#{env['warden'].message}</p>
<p>#{ENV['REDIRECT_URI']}</p>
<p>#{ENV['GITHUB_CLIENT_ID']}</p>
EOS
end
end
end
end

View File

@ -0,0 +1,21 @@
require 'yaml'
require 'hashie'
module CodeValet
module WebApp
# Simple object wrapping the monkeys.txt for exposure within the web app
class Monkeys
MONKEYS_FILE = File.expand_path(File.dirname(__FILE__) + '/../../../monkeys.txt')
def self.data
@@monkeys_data ||= File.readlines(MONKEYS_FILE).map(&:chomp).sort
end
# Delete the singleton's internal state.
def self.clear!
@@monkeys_data = nil
end
end
end
end

View File

@ -0,0 +1,32 @@
require 'yaml'
require 'hashie'
module CodeValet
module WebApp
# Simple object wrapping the plugins.yaml for exposure within the web app
class Plugins
PLUGINS_FILE = File.expand_path(File.dirname(__FILE__) + '/../../../plugins.yaml')
# Load and return the raw plugin data from +plugins.yaml+
#
# @return [Hash] deserialized representation of +plugins.yaml+
def self.data
@@plugin_data ||= YAML.load(File.read(PLUGINS_FILE))
end
# Load and return the essential list of plugins and their repositories
#
# @return [Hash]
def self.essential
return self.data['essential']
end
# Delete the singleton's internal state.
def self.clear!
@@plugin_data = nil
end
end
end
end

42
webapp/plugins.yaml Normal file
View File

@ -0,0 +1,42 @@
---
# List of plugins which should be considered for the Jenkins Developer
# Dashbaord, see https://github.com/CodeValet/codevalet/milestone/3
essential:
azure-vm-agents:
repo: 'https://github.com/jenkinsci/azure-vm-agents-plugin'
ref: 'master'
blueocean:
repo: 'https://github.com/jenkinsci/blueocean-plugin'
ref: 'master'
datadog:
repo: 'https://github.com/datadog/jenkins-datadog-plugin.git'
ref: 'master'
declarative:
repo: 'https://github.com/jenkinsci/pipeline-model-definition-plugin'
ref: 'master'
embeddable-status:
repo: 'https://github.com/jenkinsci/embeddable-build-status-plugin'
ref: 'master'
git:
repo: 'https://github.com/jenkinsci/git-plugin'
ref: 'master'
git-client:
repo: 'https://github.com/jenkinsci/git-client-plugin'
ref: 'master'
github-oauth:
repo: 'https://github.com/jenkinsci/github-oauth-plugin'
ref: 'master'
matrix-auth:
repo: 'https://github.com/jenkinsci/matrix-auth-plugin'
ref: 'master'
pipeline:
repo: 'https://github.com/jenkinsci/workflow-aggregator-plugin'
ref: 'master'
restricted-declarative:
repo: 'https://github.com/abayer/restricted-declarative-plugin'
ref: 'master'
sentry:
repo: 'https://github.com/jenkinsci/sentry-plugin'
ref: 'master'
inessential:

42
webapp/scripts/container-check Executable file
View File

@ -0,0 +1,42 @@
#!/usr/bin/env bash
NAME=codevalet-webapp-container-check
PORT=9292
URL=http://127.0.0.1:${PORT}/
function terminate {
echo ">> Terminating ${NAME}"
docker stop ${NAME}
docker rm ${NAME}
}
trap terminate EXIT
docker run --detach -e RACK_ENV=production \
-p ${PORT}:${PORT} \
--name ${NAME} \
${IMAGE_NAME}:latest \
for i in $(seq 1 10); do
echo ">> Attempt #${i} to reach ${URL}"
curl --silent --fail ${URL} 2>&1 > /dev/null
STATUS=$?
if [ $STATUS -eq 22 ]; then
echo "----> :( Container returned a bad response"
break;
elif [ $STATUS -ne 0 ]; then
sleep 1;
else
echo '----> :) The app returned a 200'
exit 0;
fi;
sleep 1
done;
echo "----> :( Failed to reach the container"
docker logs ${NAME}
docker ps
# If we get to here without having bailed out, something is wrong
exit 1

View File

@ -0,0 +1,20 @@
require 'spec_helper'
require 'codevalet/webapp/monkeys'
describe CodeValet::WebApp::Monkeys do
subject(:klass) { described_class }
before(:each) { klass.clear! }
it { should respond_to :data }
describe '.data' do
subject(:data) { klass.data }
it { should be_kind_of Array }
it 'should only read the file once' do
expect(File).to receive(:readlines).and_call_original.once
1..3.times { klass.data }
end
end
end

View File

@ -0,0 +1,26 @@
require 'spec_helper'
require 'codevalet/webapp/plugins'
describe CodeValet::WebApp::Plugins do
subject(:klass) { described_class }
before(:each) { klass.clear! }
it { should respond_to :data }
describe '.data' do
subject(:data) { klass.data }
it { should be_kind_of Hash }
it 'should only read the file once' do
expect(File).to receive(:read).and_call_original.once
1..3.times { klass.data }
end
end
it { should respond_to :essential }
describe '.essential' do
subject(:essential) { klass.essential}
it { should be_kind_of Hash }
end
end

View File

@ -0,0 +1,7 @@
require 'rspec'
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
RSpec.configure do |c|
c.order = :random
end