Skip to content

Commit

Permalink
Merge pull request #5140 from DavidKang/feature/obs-factory-without-test
Browse files Browse the repository at this point in the history
Integrate obs factory
  • Loading branch information
bgeuken committed Jun 22, 2018
2 parents a36785b + 97645f1 commit c32e16a
Show file tree
Hide file tree
Showing 40 changed files with 3,032 additions and 58 deletions.
416 changes: 359 additions & 57 deletions .rubocop_todo.yml

Large diffs are not rendered by default.

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 Webui::ObsFactory
class ApplicationController < ::Webui::WebuiController
layout 'webui/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,49 @@
module Webui::ObsFactory
class DistributionsController < ApplicationController
respond_to :html

before_action :require_distribution, :require_dashboard

def show
@staging_projects = ::ObsFactory::StagingProjectPresenter.sort(@distribution.staging_projects)
@versions = { source: @distribution.source_version,
totest: @distribution.totest_version,
published: @distribution.published_version }
@ring_prjs = ::ObsFactory::ObsProjectPresenter.wrap(@distribution.ring_projects)
@standard = ::ObsFactory::ObsProjectPresenter.new(@distribution.standard_project)
@live = @distribution.live_project
@live = ::ObsFactory::ObsProjectPresenter.new(@live) unless @live.nil?
@images = ::ObsFactory::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

private

def require_distribution
@distribution = ::ObsFactory::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
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
module Webui::ObsFactory
class StagingProjectsController < ApplicationController
respond_to :json, :html

before_action :require_distribution
before_action :require_project_name, only: [:show]

def index
respond_to do |format|
format.html do
@staging_projects = ::ObsFactory::StagingProjectPresenter.sort(@distribution.staging_projects_all)
@backlog_requests = ::ObsFactory::Request.with_open_reviews_for(by_group: @distribution.staging_manager, target_project: @distribution.name)
@requests_state_new = ::ObsFactory::Request.in_state_new(by_group: @distribution.staging_manager, target_project: @distribution.name)

staging_project = Project.find_by_name("#{@distribution.project}:Staging")
dashboard_package = Package.find_by_project_and_name(staging_project.name, 'dashboard')

if dashboard_package && dashboard_package.file_exists?('ignored_requests')
file = ::Backend::Api::Sources::Package.file(staging_project.name, dashboard_package.name, 'ignored_requests')
@ignored_requests = YAML.load(file)
end

if @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

def show
respond_to do |format|
format.html do
@staging_project = ::ObsFactory::StagingProjectPresenter.new(@staging_project)
# For the breadcrumbs
@project = @distribution.project
end
format.json { render json: @staging_project }
end
end

private

def require_distribution
@distribution = ::ObsFactory::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_project_name
@staging_project = ::ObsFactory::StagingProject.find(@distribution, params[:project_name])
unless @staging_project
redirect_to main_app.root_path, flash: { error: "#{params[:project_name]} is not a valid staging project" }
end
end
end
end
5 changes: 5 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,5 @@
module Webui::ObsFactory::ApplicationHelper
def openqa_links_helper
ObsFactory::OpenqaJob.openqa_links_url
end
end
224 changes: 224 additions & 0 deletions src/api/app/models/obs_factory/distribution.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
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 = { package_name: '000product', filename: 'openSUSE.product' }
RINGS_PREFIX = ":Rings"

attr_accessor :project, :strategy

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

# 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(Backend::Api::Sources::Package.file(name, SOURCE_VERSION_FILE[:package_name], SOURCE_VERSION_FILE[:filename]))
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

private

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
end
end
Loading

0 comments on commit c32e16a

Please sign in to comment.