Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[6.11.z] Cherry-picking Ansible UI fixes #818

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
f43c0e2
fix tasks pagination
Aug 2, 2022
96c288a
AutoCherrypick GHAs
jyejare Aug 2, 2022
d410b75
Fixing PF4ConfirmationDialog
Griffin-Sullivan Jul 14, 2022
6b60ed2
Fix locator for column_value in PopOverWidget (#736)
jameerpathan111 Aug 17, 2022
79ef1ff
use new host UI by default (#735)
peterdragun Aug 17, 2022
09cd65b
Fixing locator for login page footer (#738)
adarshdubey-star Aug 19, 2022
704cfbc
Add content tab to new host UI (#720)
peterdragun Aug 23, 2022
e26931e
add rex related views and entities (#742)
peterdragun Sep 5, 2022
b28dfd4
replace find_element_by_xpath with find_element (#744)
peterdragun Sep 6, 2022
1a3e0c3
Add support for container repo discovery (#745)
jameerpathan111 Sep 6, 2022
c740635
Ensure cockpit page is safe before locating elements (#743)
peterdragun Sep 12, 2022
9c23616
updating the airgun autocherrypick n-1 version as robottelo
omkarkhatavkar Sep 8, 2022
f1c54d8
recent audits and jobs as table
Sep 15, 2022
e824619
Rename column in puppet class table. (#758)
vsedmik Sep 20, 2022
e55b132
fixing the locator for logout page rhsso (#757)
omkarkhatavkar Sep 20, 2022
c9f456e
add static OUIA id for close button (#755)
peterdragun Sep 20, 2022
e736ecd
Locator fix for errata (#754)
adarshdubey-star Sep 20, 2022
9035bfd
Fixing new Webhook button (#761)
Griffin-Sullivan Sep 22, 2022
526bb47
Remove publish via http field since it's not longer valid (#762)
latran Sep 22, 2022
d86d62e
Create cv and search for new CV UI (#749)
latran Sep 22, 2022
a143737
Missing delete confirmation function (#763)
latran Sep 23, 2022
038fc7d
Updated locator for Text field in Settings (#767)
shweta83 Sep 30, 2022
dac0e20
fix OUIA IDs (#766)
peterdragun Oct 3, 2022
b37f029
Remove environment locator
shubhamsg199 Oct 21, 2022
0417116
added the support for the clone hostgroup (#773)
omkarkhatavkar Oct 26, 2022
9142746
Uncommenting select_all_hits (#771)
adarshdubey-star Oct 28, 2022
7e44222
Fix typo (#778)
shubhamsg199 Oct 28, 2022
007fe8b
Only search search bar in the active element, not from DOM root (#772)
lhellebr Nov 3, 2022
5e52906
change status id to static one (#781)
peterdragun Nov 14, 2022
84ecce4
Alligning ACP GHA with Robottelo (#780)
jyejare Nov 14, 2022
8012321
Switch classifiers from a tuple to a list (#784)
JacobCallahan Nov 24, 2022
da13431
Fixes for Robottelo Role/Variable UI tests (#775)
sambible Nov 29, 2022
68debea
add repository sets entities (#770)
peterdragun Nov 29, 2022
6a2e121
Cherrypicking based on branch labels added to the parent PR (#788)
jyejare Dec 15, 2022
dc169b9
Ansible UI fixes (#790)
adarshdubey-star Dec 19, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/auto_assign.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
addAssignees: author
21 changes: 21 additions & 0 deletions .github/workflows/auto_assignment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: 'Auto Assign'

on:
pull_request_target:
types:
- opened
- ready_for_review
- reopened
- synchronize


jobs:
add-assignees: # This needed to create the gh issue in case of failed auto-cherry-pick
name: Add author to assignee
if: "!contains(github.event.pull_request.labels.*.name, 'Auto_Cherry_Picked')"
runs-on: ubuntu-latest
steps:
- uses: kentaro-m/[email protected]
with:
repo-token: "${{ secrets.CHERRYPICK_PAT || github.token }}"
configuration-path: ".github/auto_assign.yml"
70 changes: 70 additions & 0 deletions .github/workflows/auto_cherry_pick.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# CI stages to execute against all branches on PR merge
name: auto_cherry_pick_commits

on:
pull_request_target:
types:
- closed

# Github & Parent PR Env vars
env:
assignee: ${{ github.event.pull_request.assignee.login }}
title: ${{ github.event.pull_request.title }}
number: ${{ github.event.number }}

jobs:

# Auto CherryPicking and Failure Recording
auto-cherry-pick:
if: github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'CherryPick')
name: Auto Cherry Pick to labeled branches
runs-on: ubuntu-latest
strategy:
matrix:
label: ${{ github.event.pull_request.labels.*.name }}

steps:
## Nailgun Repo Checkout
- uses: actions/checkout@v3
if: ${{ startsWith(matrix.label, '6.') && matrix.label != github.base_ref }}
with:
fetch-depth: 0

## CherryPicking and AutoMerging
- name: Cherrypicking to zStream branch
id: cherrypick
if: ${{ startsWith(matrix.label, '6.') && matrix.label != github.base_ref }}
uses: jyejare/github-cherry-pick-action@main
with:
token: ${{ secrets.CHERRYPICK_PAT }}
branch: ${{ matrix.label }}
labels: |
Auto_Cherry_Picked
${{ matrix.label }}
assignees: ${{ env.assignee }}

## Failure Logging to issues and GChat Group
- name: Create Github issue on cherrypick failure
id: create-issue
if: ${{ always() && steps.cherrypick.outcome == 'failure' }}
uses: dacbd/create-issue-action@main
with:
token: ${{ secrets.CHERRYPICK_PAT }}
title: "[Failed-AutoCherryPick] - ${{ env.title }}"
body: |
#### Auto-Cherry-Pick WorkFlow Failure:
- To Branch: ${{ matrix.label }}
- [Failed Cherrypick Action](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
- [Parent Pull Request](https://github.com/${{ github.repository }}/pull/${{ env.number }})
labels: Failed_AutoCherryPick,${{ matrix.label }}
assignees: ${{ env.assignee }}
- name: Send Google Chat notification on cherrypick failure
id: google-chat-notification
if: ${{ always() && steps.cherrypick.outcome == 'failure' }}
uses: omkarkhatavkar/google-chat-notification@master
with:
name: ${{ env.title }}
url: ${{ secrets.GCHAT_REVIEWERS_WEBHOOK }}
issue_url: ${{ steps.create-issue.outputs.html_url }}
author: ${{ env.assignee }}
status: failure
17 changes: 17 additions & 0 deletions .github/workflows/required_labels.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# CI jobs to check specific labels present / absent
name: required_labels

on:
pull_request:
types: [opened, labeled, unlabeled, synchronize]

jobs:
cherrypick_label:
name: Enforcing cherrypick labels
runs-on: ubuntu-latest
steps:
- uses: mheap/github-action-required-labels@v2
with:
mode: exactly
count: 1
labels: "CherryPick, No-CherryPick"
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ repos:
rev: 22.3.0
hooks:
- id: black
- repo: https://gitlab.com/pycqa/flake8
- repo: https://github.com/pycqa/flake8
rev: 3.9.2
hooks:
- id: flake8
Expand Down
7 changes: 3 additions & 4 deletions airgun/entities/ansible_role.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,9 @@ def imported_roles_count(self):
view = self.navigate_to(self, 'All')
# Before any roles have been imported, no table or pagination widget are
# present on the page
if not view.pagination.is_displayed:
return 0
else:
return int(view.total_imported_roles.read())
# Applying wait_displayed for the page to get rendered
view.wait_displayed()
return int(view.total_imported_roles.read())

def import_all_roles(self):
"""Import all available roles and return the number of roles
Expand Down
2 changes: 1 addition & 1 deletion airgun/entities/cloud_insights.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def remediate(self, entity_name):
view = self.navigate_to(self, 'All')
view.search(entity_name)
view.select_all.fill(True)
# view.select_all_hits.click() skip till BZ#1975321 is fixed.
view.select_all_hits.click()
view.remediate.click()
view.remediation_window.remediate.click()
self.run_job()
Expand Down
46 changes: 46 additions & 0 deletions airgun/entities/contentview_new.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from navmazing import NavigateToSibling

from airgun.entities.base import BaseEntity
from airgun.navigation import NavigateStep
from airgun.navigation import navigator
from airgun.utils import retry_navigation
from airgun.views.contentview_new import NewContentViewCreateView
from airgun.views.contentview_new import NewContentViewTableView


class NewContentViewEntity(BaseEntity):
endpoint_path = '/content_views'

def create(self, values):
"""Create a new content view"""
view = self.navigate_to(self, 'New')
view.fill(values)
view.submit.click()

def search(self, value):
"""Search for content view"""
view = self.navigate_to(self, 'All')
return view.search(value)


@navigator.register(NewContentViewEntity, 'All')
class ShowAllContentViewsScreen(NavigateStep):
"""Navigate to All Content Views screen."""

VIEW = NewContentViewTableView

@retry_navigation
def step(self, *args, **kwargs):
self.view.menu.select('Content', 'Content Views')


@navigator.register(NewContentViewEntity, 'New')
class CreateContentView(NavigateStep):
"""Navigate to Create content view."""

VIEW = NewContentViewCreateView

prerequisite = NavigateToSibling('All')

def step(self, *args, **kwargs):
self.parent.create_content_view.click()
12 changes: 9 additions & 3 deletions airgun/entities/host.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from airgun.views.host import HostsUnassignCompliancePolicy
from airgun.views.host import HostsView
from airgun.views.host import RecommendationListView
from airgun.views.host_new import NewHostDetailsView


class HostEntity(BaseEntity):
Expand All @@ -39,7 +40,7 @@ def create(self, values):
view.fill(values)
self.browser.click(view.submit, ignore_ajax=True)
self.browser.plugin.ensure_page_safe(timeout='600s')
host_view = HostDetailsView(self.browser)
host_view = NewHostDetailsView(self.browser)
host_view.wait_displayed()
host_view.flash.assert_no_error()
host_view.flash.dismiss()
Expand Down Expand Up @@ -258,15 +259,16 @@ def get_webconsole_content(self, entity_name, rhel_version=7):

# switch to the last opened tab,
self.browser.switch_to_window(self.browser.window_handles[-1])
self.browser.plugin.ensure_page_safe()
self.browser.wait_for_element(locator='//div[@id="content"]/iframe', exception=True)
# the remote host content is loaded in an iframe, let's switch to it
self.browser.switch_to_frame(locator='//div[@id="content"]/iframe')

self.browser.wait_for_element(
locator=f'//{hostname_element}[@id="{hostname_id}"]', exception=True, visible=True
)
hostname_button_view = self.browser.selenium.find_elements_by_id(hostname_id)
hostname = hostname_button_view[0].text
hostname_button = self.browser.selenium.find_elements("id", hostname_id)
hostname = hostname_button[0].text
self.browser.switch_to_main_frame()
self.browser.switch_to_window(self.browser.window_handles[0])
self.browser.close_window(self.browser.window_handles[-1])
Expand Down Expand Up @@ -327,6 +329,10 @@ def step(self, *args, **kwargs):
entity_name = kwargs.get('entity_name')
self.parent.search(entity_name)
self.parent.table.row(name=entity_name)['Name'].widget.click()
host_view = NewHostDetailsView(self.parent.browser)
host_view.wait_displayed()
host_view.dropdown.wait_displayed()
host_view.dropdown.item_select('Legacy UI')


@navigator.register(HostEntity, 'Edit')
Expand Down
117 changes: 117 additions & 0 deletions airgun/entities/host_new.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from airgun.entities.host import HostEntity
from airgun.navigation import NavigateStep
from airgun.navigation import navigator
from airgun.views.host_new import InstallPackagesView
from airgun.views.host_new import ModuleStreamDialog
from airgun.views.host_new import NewHostDetailsView
from airgun.views.job_invocation import JobInvocationCreateView


class NewHostEntity(HostEntity):
Expand All @@ -21,8 +24,122 @@ def get_details(self, entity_name, widget_names=None):
will be read.
"""
view = self.navigate_to(self, 'NewDetails', entity_name=entity_name)
self.browser.plugin.ensure_page_safe()
return view.read(widget_names=widget_names)

def schedule_job(self, entity_name, values):
"""Schedule a remote execution on selected host"""
view = self.navigate_to(self, 'NewDetails', entity_name=entity_name)
view.wait_displayed()
view.schedule_job.fill('Schedule a job')
view = JobInvocationCreateView(self.browser)
self.browser.plugin.ensure_page_safe()
view.wait_displayed()
view.fill(values)
view.submit.click()

def get_packages(self, entity_name, search=""):
"""Filter installed packages on host"""
view = self.navigate_to(self, 'NewDetails', entity_name=entity_name)
view.content.packages.select()
view.content.packages.searchbar.fill(search)
# wait for filter to apply
self.browser.plugin.ensure_page_safe()
view.content.packages.table.wait_displayed()
return view.content.packages.read()

def install_package(self, entity_name, package):
"""Installs package on host using the installation modal"""
view = self.navigate_to(self, 'NewDetails', entity_name=entity_name)
view.wait_displayed()
view.content.packages.select()
view.content.packages.dropdown.wait_displayed()
view.content.packages.dropdown.item_select('Install packages')
view = InstallPackagesView(self.browser)
view.wait_displayed()
view.searchbar.fill(package)
# wait for filter to apply
self.browser.plugin.ensure_page_safe()
view.select_all.click()
view.install.click()

def apply_package_action(self, entity_name, package_name, action):
"""Apply `action` to selected package based on the `package_name`"""
view = self.navigate_to(self, 'NewDetails', entity_name=entity_name)
view.wait_displayed()
view.content.packages.searchbar.fill(package_name)
# wait for filter to apply
self.browser.plugin.ensure_page_safe()
view.content.packages.table.wait_displayed()
view.content.packages.table[0][5].widget.item_select(action)
view.flash.assert_no_error()
view.flash.dismiss()

def get_errata_by_type(self, entity_name, type):
"""List errata based on type and return table"""
view = self.navigate_to(self, 'NewDetails', entity_name=entity_name)
view.wait_displayed()
view.content.errata.select()
view.content.errata.type_filter.fill(type)
self.browser.plugin.ensure_page_safe()
view.content.errata.table.wait_displayed()
return view.read(widget_names="content.errata.table")

def apply_erratas(self, entity_name, search):
"""Apply errata on selected host based on errata_id"""
view = self.navigate_to(self, 'NewDetails', entity_name=entity_name)
view.wait_displayed()
view.content.errata.searchbar.fill(search)
# wait for filter to apply
self.browser.plugin.ensure_page_safe()
view.content.errata.select_all.click()
view.content.errata.apply.fill('Apply')
view.flash.assert_no_error()
view.flash.dismiss()

def get_module_streams(self, entity_name, search):
"""Filter module streams"""
view = self.navigate_to(self, 'NewDetails', entity_name=entity_name)
view.wait_displayed()
view.content.module_streams.select()
view.content.module_streams.searchbar.fill(search)
# wait for filter to apply
self.browser.wait_for_element(locator='//h4[text()="Loading"]', exception=False)
view.content.module_streams.table.wait_displayed()
return view.content.module_streams.table.read()

def apply_module_streams_action(self, entity_name, module_stream, action):
"""Apply `action` to selected Module stream based on the `module_stream`"""
view = self.navigate_to(self, 'NewDetails', entity_name=entity_name)
view.wait_displayed()
view.content.module_streams.searchbar.fill(module_stream)
# wait for filter to apply
self.browser.plugin.ensure_page_safe()
view.content.module_streams.table[0][5].widget.item_select(action)
modal = ModuleStreamDialog(self.browser)
if modal.is_displayed:
modal.confirm()
view.flash.assert_no_error()
view.flash.dismiss()

def get_repo_sets(self, entity_name, search):
"""Get all repository sets available for host"""
view = self.navigate_to(self, 'NewDetails', entity_name=entity_name)
view.wait_displayed()
view.content.repository_sets.searchbar.fill(search)
self.browser.plugin.ensure_page_safe()
return view.content.repository_sets.table.read()

def override_repo_sets(self, entity_name, repo_set, action):
"""Change override for repository set"""
view = self.navigate_to(self, 'NewDetails', entity_name=entity_name)
view.wait_displayed()
view.content.repository_sets.searchbar.fill(repo_set)
self.browser.plugin.ensure_page_safe()
view.content.repository_sets.table[0][5].widget.item_select(action)
view.flash.assert_no_error()
view.flash.dismiss()


@navigator.register(NewHostEntity, 'NewDetails')
class ShowNewHostDetails(NavigateStep):
Expand Down
11 changes: 11 additions & 0 deletions airgun/entities/hostgroup.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@ def create(self, values):
view.flash.assert_no_error()
view.flash.dismiss()

def clone(self, entity_name, values):
"""Clone an existing host group entity"""
view = self.navigate_to(self, 'All')
view.search(entity_name)
view.table.row(name=entity_name)['Actions'].widget.fill('Clone')
view = HostGroupCreateView(self.browser)
view.fill(values)
view.submit.click()
view.flash.assert_no_error()
view.flash.dismiss()

def search(self, value):
"""Search for existing host group entity"""
view = self.navigate_to(self, 'All')
Expand Down
1 change: 1 addition & 0 deletions airgun/entities/lifecycleenvironment.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ def delete(self, entity_name):
"""Deletes existing lifecycle environment entity"""
view = self.navigate_to(self, 'Edit', entity_name=entity_name)
view.remove.click()
self.browser.handle_alert()
view.flash.assert_no_error()
view.flash.dismiss()

Expand Down
Loading