Skip to content

Commit

Permalink
[frontend] Add OBS Factory files
Browse files Browse the repository at this point in the history
We wanted to add the OBS Factory engine in this project to be part of
the code of OBS. This commit only move OBS Factory Engine files into
OBS.
  • Loading branch information
Moises Deniz Aleman authored and David Kang committed Jun 21, 2018
1 parent a36785b commit a2b7c83
Show file tree
Hide file tree
Showing 40 changed files with 2,722 additions and 0 deletions.
425 changes: 425 additions & 0 deletions src/api/app/assets/stylesheets/webui/obs_factory/application.css

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module ObsFactory
class ApplicationController < ::Webui::WebuiController
layout 'obs_factory/application'

rescue_from ObsFactory::OpenqaApi::OpenqaFailure do |ex|
render text: "failure in openQA"
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
module ObsFactory
class DistributionsController < ApplicationController
respond_to :html

before_action :require_distribution, :require_dashboard

def require_distribution
@distribution = Distribution.find(params[:project])
unless @distribution
redirect_to main_app.root_path, flash: { error: "#{params[:project]} is not a valid openSUSE distribution, can't offer dashboard" }
end
end

def require_dashboard
if @distribution.staging_projects.empty?
redirect_to main_app.root_path, flash: { error: "#{params[:project]} does not offer a dashboard" }
end
end

def show
@staging_projects = StagingProjectPresenter.sort(@distribution.staging_projects)
@versions = { source: @distribution.source_version,
totest: @distribution.totest_version,
published: @distribution.published_version }
@ring_prjs = ObsProjectPresenter.wrap(@distribution.ring_projects)
@standard = ObsProjectPresenter.new(@distribution.standard_project)
@live = @distribution.live_project
@live = ObsProjectPresenter.new(@live) unless @live.nil?
@images = ObsProjectPresenter.new(@distribution.images_project)
@openqa_jobs = @distribution.openqa_jobs_for(:totest)
calculate_reviews
# For the breadcrumbs
@project = @distribution.project
end

protected

def calculate_reviews
@reviews = {}
@reviews[:review_team] = @distribution.requests_with_reviews_for_group('opensuse-review-team').size
@reviews[:factory_auto] = @distribution.requests_with_reviews_for_group('factory-auto').size
@reviews[:legal_auto] = @distribution.requests_with_reviews_for_group('legal-auto').size
@reviews[:legal_team] = @distribution.requests_with_reviews_for_group('legal-team').size
@reviews[:repo_checker] = @distribution.requests_with_reviews_for_user('repo-checker').size
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module ObsFactory
class OpenqaJobsController < ApplicationController
respond_to :json, :html

def index
@q = params[:q] || {}
@cache = params[:cache]
openqa_jobs = OpenqaJob.find_all_by(@q, cache: @cache)
respond_to do |format|
format.html { @openqa_jobs = OpenqaJobPresenter.wrap(openqa_jobs) }
format.json { render json: openqa_jobs }
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
module ObsFactory
class StagingProjectsController < ApplicationController
respond_to :json, :html

before_action :require_distribution

def require_distribution
@distribution = Distribution.find(params[:project])
unless @distribution
redirect_to main_app.root_path, flash: { error: "#{params[:project]} is not a valid openSUSE distribution, can't offer dashboard" }
end
end

def index
respond_to do |format|
format.html do
@staging_projects = StagingProjectPresenter.sort(@distribution.staging_projects_all)
@backlog_requests = Request.with_open_reviews_for(by_group: @distribution.staging_manager, target_project: @distribution.name)
@requests_state_new = Request.in_state_new(by_group: @distribution.staging_manager, target_project: @distribution.name)
file = PackageFile.new(
project_name: "#{params[:project]}:Staging",
package_name: "dashboard",
name: "ignored_requests")
unless file.to_s.nil?
@ignored_requests = YAML.load(file.to_s)
end
if !@ignored_requests.nil? and @ignored_requests
@backlog_requests_ignored = @backlog_requests.select { |req| @ignored_requests.key?(req.number) }
@backlog_requests = @backlog_requests.select { |req| !@ignored_requests.key?(req.number) }
@requests_state_new = @requests_state_new.select { |req| !@ignored_requests.key?(req.number) }
@backlog_requests_ignored.sort! { |x,y| x.package <=> y.package }
else
@backlog_requests_ignored = []
end
@backlog_requests.sort! { |x,y| x.package <=> y.package }
@requests_state_new.sort! { |x,y| x.package <=> y.package }
# For the breadcrumbs
@project = @distribution.project
end
format.json { render json: @distribution.staging_projects_all }
end
end

before_action :require_id, only: [:show]

def require_id
@staging_project = StagingProject.find(@distribution, params[:id])
unless @staging_project
redirect_to main_app.root_path, flash: { error: "#{params[:id]} is not a valid staging project" }
end
end

def show
respond_to do |format|
format.html do
@staging_project = StagingProjectPresenter.new(@staging_project)
# For the breadcrumbs
@project = @distribution.project
end
format.json { render json: @staging_project }
end
end
end
end
20 changes: 20 additions & 0 deletions src/api/app/helpers/webui/obs_factory/application_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module ObsFactory
module ApplicationHelper

# Catch some url helpers used in the OBS layout and forward them to
# the main application
%w(home_path user_tasks_path root_path project_show_path search_path user_show_url user_show_path
user_register_user_path news_feed_path project_toggle_watch_path
project_list_public_path monitor_path projects_path new_project_path
user_rss_notifications_url session_new_path session_create_path session_destroy_path).each do |m|
define_method(m) do |*args|
main_app.send(m, *args)
end
end

def openqa_links_helper
OpenqaJob.openqa_links_url
end

end
end
235 changes: 235 additions & 0 deletions src/api/app/models/obs_factory/distribution.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
require 'open-uri'

module ObsFactory

class UnknownDistribution < Exception
end

# A Distribution. Contains a reference to the corresponding Project object.
class Distribution
include ActiveModel::Model
extend ActiveModel::Naming
extend Forwardable

SOURCE_VERSION_FILE = "000product/openSUSE.product"
RINGS_PREFIX = ":Rings"

attr_accessor :project, :strategy

def distribution_strategy_for_project(project)
s = case project.name
when 'openSUSE:Factory' then DistributionStrategyFactory.new
when 'openSUSE:Factory:PowerPC' then DistributionStrategyFactoryPPC.new
when /^openSUSE:.*/ then DistributionStrategyOpenSUSE.new
when /^SUSE:SLE-12-SP\d:GA/ then DistributionStrategySLE12SP1.new
when /^SUSE:SLE-15:GA/ then DistributionStrategySLE15.new
when /^SUSE:SLE-12-SP.*CASP\d*/ then DistributionStrategyCasp.new
else raise UnknownDistribution
end
s.project = project
s
end

def initialize(project = nil)
self.project = project
self.strategy = distribution_strategy_for_project(project)
end

def self.attributes
%w(name description staging_projects openqa_version openqa_group
source_version totest_version published_version staging_manager
standard_project live_project images_project ring_projects)
end

def attributes
Hash[self.class.attributes.map { |a| [a, nil] }]
end

def_delegators :@strategy, :root_project_name, :url_suffix, :openqa_version,
:openqa_iso, :arch, :openqa_group, :staging_manager

# Find a distribution by id
#
# @return [Distribution] the distribution
def self.find(id)
project = ::Project.find_by_name(id)
if project
begin
Distribution.new(project)
rescue UnknownDistribution
nil
end
else
nil
end
end

# Name of the associated project
#
# @return [String] name of the Project object
def name
project.name
end

# Id of the distribution
#
# @return [String] name
def id
name
end

# Description of the associated project
#
# @return [String] description of the Project object
def description
project.description
end

# Version of the distribution used as ToTest
#
# @return [String] version string
def totest_version
Rails.cache.fetch("totest_version_for_#{name}", expires_in: 10.minutes) do
strategy.totest_version
end
end

# Version of the published distribution
#
# @return [String] version string
def published_version
Rails.cache.fetch("published_version_for_#{name}", expires_in: 10.minutes) do
strategy.published_version
end
end

# Staging projects associated to the distribution
#
# @return [Array] array of StagingProject objects
def staging_projects
@staging_projects ||= StagingProject.for(self)
end

# Staging projects associated to the distribution, including non-letter
#
# @return [Array] array of StagingProject objects
def staging_projects_all
@staging_projects ||= StagingProject.for(self, false)
end

# Staging project associated to the distribution and with the given id
#
# @param [String] id of the staging project
# @return [StagingProject] the associated project or nil
def staging_project(id)
if @staging_projects
@staging_projects.select {|p| p.id == id }
else
StagingProject.find(self, id)
end
end

# Version of the distribution used as source
#
# @return [String] version string
def source_version
Rails.cache.fetch("source_version_for_#{name}", expires_in: 10.minutes) do
begin
p = Xmlhash.parse(ActiveXML::backend.direct_http "/source/#{name}/#{SOURCE_VERSION_FILE}?expand=1")
p.get('products').get('product').get('version')
rescue ActiveXML::Transport::NotFoundError
nil
end
end
end

# openQA jobs related with a given version of the distribution
#
# @param [#to_s] version must be :source, :totest or :published
# @return [Array] list of OpenqaJob objects
def openqa_jobs_for(version)
filter = {distri: 'opensuse', version: strategy.openqa_version, build: send(:"#{version}_version"), group: strategy.openqa_group}
OpenqaJob.find_all_by(filter, exclude_modules: true)
end

# Requests with some open review targeting the distribution, filtered by
# the group in charge of the open reviews
#
# @param [String] group name of the group
# @return [Array] list of Request objects
def requests_with_reviews_for_group(group)
Request.with_open_reviews_for(by_group: group, target_project: root_project_name)
end

# Requests with some open review targeting the distribution, filtered by
# the user in charge of the open reviews
#
# @param [String] user name of the user
# @return [Array] list of Request objects
def requests_with_reviews_for_user(user)
Request.with_open_reviews_for(by_user: user, target_project: root_project_name)
end

# Standard project
#
# @return [ObsProject] standard
def standard_project
if @standard_project.nil?
@standard_project = ObsProject.new(name, 'standard')
@standard_project.exclusive_repository = 'standard'
end
@standard_project
end

# Live project
#
# @return [ObsProject] live
def live_project
if @live_project.nil?
@live_project = ObsProject.new("#{name}:Live", 'live')
if @live_project.project.nil?
@live_project = nil
else
@live_project.exclusive_repository = 'images'
end
end
@live_project
end

# Images project
#
# @return [ObsProject] images
def images_project
if @images_project.nil?
@images_project = ObsProject.new(name, 'images')
@images_project.exclusive_repository = 'images'
end
@images_project
end

# Projects defining the distribution rings
#
# @return [Array] list of ObsProject objects nicknamed with numbers
def ring_projects
@ring_projects ||= strategy.rings.each_with_index.map do |r,idx|
ObsProject.new("#{rings_project_name}:#{idx}-#{r}", "#{idx}-#{r}")
end
end

# Name of the project used as top-level for the ring projects
#
# @return [String] project name
def rings_project_name
"#{root_project_name}#{RINGS_PREFIX}"
end

# URL parameter for openqa's /test route to be opened in view
# for given project
#
# @return [String] URL part (e.g. match=A)
def openqa_filter(project)
return strategy.openqa_filter(project)
end

end
end
Loading

0 comments on commit a2b7c83

Please sign in to comment.