Skip to content

Commit

Permalink
Add #new and #create actions for StagingWorkflowController
Browse files Browse the repository at this point in the history
Now the user will be able to create a StagingWorkflow. By default it
creates/uses two subprojects of the main project (:Staging:A and
:Staging:B)
  • Loading branch information
Moises Deniz Aleman authored and dmarcoux committed Nov 5, 2018
1 parent ebb64db commit 8e497cc
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 6 deletions.
48 changes: 48 additions & 0 deletions src/api/app/controllers/webui/staging_workflows_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
class Webui::StagingWorkflowsController < Webui::WebuiController
layout 'webui2/webui'

before_action :require_login, except: [:show]
before_action :set_bootstrap_views
before_action :set_project, only: [:new, :create]
after_action :verify_authorized, except: [:show, :new]

def new
if @project.staging
redirect_to staging_workflow_path(@project.staging)
return
end

@staging_workflow = @project.build_staging
end

def create
staging_workflow = @project.build_staging

authorize staging_workflow

if staging_workflow.save
flash[:success] = "Staging Workflow for #{@project.name} was successfully created"
redirect_to staging_workflow_path(staging_workflow)
else
flash[:error] = "Staging Workflow for #{@project.name} couldn't be created"
render :new
end
end

def show
@staging_workflow = StagingWorkflow.find_by(id: params[:id])
unless @staging_workflow
redirect_back(fallback_location: root_path)
flash[:error] = "StagingWorkflow with id = #{params[:id]} doesn't exist"
return
end

@project = @staging_workflow.project
end

private

def set_bootstrap_views
prepend_view_path('app/views/webui2')
end
end
4 changes: 2 additions & 2 deletions src/api/app/helpers/webui/webui_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -400,9 +400,9 @@ def toggle_sliced_text(text, slice_length = 50, id = "toggle_sliced_text_#{Time.
short + long
end

def tab_link(label, path)
def tab_link(label, path, active = false)
html_class = 'nav-link text-nowrap'
html_class << ' active' if request.path.include?(path)
html_class << ' active' if active || request.path.include?(path)

link_to(label, path, class: html_class)
end
Expand Down
13 changes: 12 additions & 1 deletion src/api/app/models/staging_workflow.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,26 @@ def without_staged_requests
includes(:staged_requests).where(bs_requests: { id: nil })
end
end

has_many :staging_projects, class_name: 'Project', inverse_of: :staging_workflow, dependent: :nullify, autosave: true
has_many :target_of_bs_requests, through: :project
has_many :staged_requests, class_name: 'BsRequest', through: :staging_projects

after_initialize :init_staging_projects

def unassigned_requests
target_of_bs_requests.in_states(['new', 'review']) - staged_requests - ignored_requests
end

def ignored_requests
BsRequest.none # TODO: define this method
end

private

def init_staging_projects
return unless new_record?
['A', 'B'].each do |letter|
staging_projects << Project.find_or_initialize_by(name: "#{project.name}:Staging:#{letter}")
end
end
end
11 changes: 11 additions & 0 deletions src/api/app/policies/staging_workflow_policy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class StagingWorkflowPolicy < ApplicationPolicy
def initialize(user, record)
raise Pundit::NotAuthorizedError, 'staging workflow does not exist' unless record
@user = user
@record = record
end

def create?
ProjectPolicy.new(@user, @record.project).create?
end
end
7 changes: 6 additions & 1 deletion src/api/app/views/webui2/webui/project/_tabs.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@
= tab_link('Requests', project_requests_path)
- unless project.defines_remote_instance?
%li.nav-item
= tab_link('Users', project_users_path)
= tab_link('Users', project_users_path(project))
// This link is intentionally hidden, only users that access to the staging workflow show will see it
// TODO: show it if the project have a staging_workflow attached when this feature will be released
- if controller_name == 'staging_workflows'
%li.nav-item
= tab_link('Staging', request.url, controller_name == 'staging_workflows')
- unless project.defines_remote_instance? || project.is_maintenance?
%li.nav-item
= tab_link('Subprojects', project_subprojects_path(project))
Expand Down
13 changes: 13 additions & 0 deletions src/api/app/views/webui2/webui/staging_workflows/new.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
- @pagetitle = "Staging Projects for #{@project}"

.card.mb-3
= render(partial: 'webui2/webui/project/tabs', locals: { project: @project })
.card-body
%h3= @pagetitle
.mb-3
Adding the staging capability to this project will enable you to group
requests into staging projects and being able to see how they build together.
.text-center
= form_for @staging_workflow, method: :post do |f|
= hidden_field_tag :project_name, @project
= f.submit 'Create Staging Projects', class: 'btn btn-primary'
2 changes: 2 additions & 0 deletions src/api/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,8 @@ def self.public_or_about_path?(request)
get 'published/:project(/:repository(/:arch(/:binary)))' => 'published#index', constraints: cons
get 'published/' => 'source#index', via: :get

resources :staging_workflows, except: [:index, :edit, :update, :destroy], controller: 'webui/staging_workflows', constraints: cons

constraints(APIMatcher) do
get '/' => 'main#index'

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
require 'rails_helper'

RSpec.describe Webui::StagingWorkflowsController do
let(:user) { create(:confirmed_user, login: 'tom') }
let(:project) { user.home_project }

before do
login(user)
end

describe 'GET #new' do
context 'non existent staging_workflow for project' do
before do
get :new, params: { project: project.name }
end

it { expect(StagingWorkflow.count).to eq(0) }
it { expect(assigns[:staging_workflow].class).to be(StagingWorkflow) }
it { expect(response).to render_template(:new) }
end

context 'with an existent staging_workflow for project' do
before do
project.create_staging
get :new, params: { project: project.name }
end

it { expect(StagingWorkflow.count).to eq(1) }
it { expect(response).to redirect_to(staging_workflow_path(project.staging)) }
end
end

describe 'POST #create' do
context 'a staging_workflow and staging_projects' do
before do
post :create, params: { project: project.name }
end

subject { project.staging }

it { expect(StagingWorkflow.count).to eq(1) }
it { expect(subject.staging_projects.map(&:name)).to match_array(['home:tom:Staging:A', 'home:tom:Staging:B']) }
it { expect(response).to redirect_to(staging_workflow_path(project.staging)) }
it { expect(flash[:success]).not_to be_nil }
end

context 'with existent stagings projects' do
let!(:staging_a) { create(:project, name: "#{project}:Staging:A") }
let!(:staging_b) { create(:project, name: "#{project}:Staging:B") }

before do
post :create, params: { project: project.name }
end

subject { project.staging }

it { expect(StagingWorkflow.count).to eq(1) }
it { expect(subject.staging_projects.map(&:name)).to match_array(['home:tom:Staging:A', 'home:tom:Staging:B']) }
it { expect(response).to redirect_to(staging_workflow_path(project.staging)) }
it { expect(flash[:success]).not_to be_nil }
end

context 'when it fails to save' do
before do
allow_any_instance_of(StagingWorkflow).to receive(:save).and_return(false)
post :create, params: { project: project.name }
end

it { expect(StagingWorkflow.count).to eq(0) }
it { expect(response).to render_template(:new) }
it { expect(flash[:error]).not_to be_nil }
end
end

describe 'GET #show' do
context 'non existent staging_workflow for project' do
before do
get :show, params: { id: 5 }
end

it { expect(assigns[:staging_workflow]).to be_nil }
it { expect(response).to redirect_to(root_path) }
it { expect(flash[:error]).not_to be_nil }
end

context 'with an existent staging_workflow for project' do
before do
project.create_staging
get :show, params: { id: project.staging }
end

it { expect(assigns[:staging_workflow]).to eq(project.staging) }
it { expect(assigns[:project]).to eq(project) }
it { expect(response).to render_template(:show) }
end
end
end
10 changes: 8 additions & 2 deletions src/api/spec/factories/staging_workflow.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
FactoryBot.define do
factory :staging_workflow do
factory :staging_workflow_with_staging_projects do
initialize_with { new(attributes) }

transient do
staging_project_count { 2 }
end

after(:create) do |staging_workflow, evaluator|
evaluator.staging_project_count.times do
staging_workflow.staging_projects << create(:staging_project, workflow_project_name: staging_workflow.project.name)
# StagingWorkflow have some staging projects already after initialize
new_staging_projects_count = evaluator.staging_project_count - staging_workflow.staging_projects.count
letters = [*'A'..'Z']
new_staging_projects_count.times do |index|
letter = letters[index + staging_workflow.staging_projects.count]
staging_workflow.staging_projects << create(:staging_project, name: "#{project.name}:Staging:#{letter}")
end
end
end
Expand Down

0 comments on commit 8e497cc

Please sign in to comment.