-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: sebastien.heurtematte <sebastien.heurtematte@eclipse-foundation.org>
- Loading branch information
1 parent
c25c678
commit fa353cb
Showing
4 changed files
with
378 additions
and
352 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,96 +1,104 @@ | ||
import os, subprocess | ||
from playwright.sync_api import sync_playwright, Page, Error, expect | ||
import os | ||
import subprocess | ||
|
||
|
||
def get_pass_2fa_otp(project_name): | ||
#TODO: extract pass path to properties file | ||
# TODO: extract pass path to properties file | ||
# this method requires the pass otp extension to be installed | ||
return os.popen("pass otp cbi-pass/bots/" + project_name + "/github.com/2FA-seed").read() | ||
|
||
|
||
def get_pass_creds(project_name, item): | ||
return os.popen("pass cbi-pass/bots/"+ project_name + "/github.com/" + item).read() | ||
return os.popen("pass cbi-pass/bots/" + project_name + "/github.com/" + item).read() | ||
|
||
|
||
def add_to_pass(project_name, item, item_name): | ||
subprocess.check_output("echo \"" + item +"\" | pass insert -m cbi-pass/bots/"+ project_name + "/github.com/" + item_name, shell=True) | ||
subprocess.check_output("echo \"" + item + "\" | pass insert -m cbi-pass/bots/"+ project_name + "/github.com/" + item_name, shell=True) | ||
|
||
|
||
def get_project_shortname(project_name): | ||
# TODO: can this be simplified? | ||
if project_name.find("."): | ||
short_name = "".join(project_name.split(".")[-1:]) | ||
else: | ||
short_name = "".join(project_name) | ||
return short_name | ||
# TODO: can this be simplified? | ||
if project_name.find("."): | ||
short_name = "".join(project_name.split(".")[-1:]) | ||
else: | ||
short_name = "".join(project_name) | ||
return short_name | ||
|
||
# Playwright commons | ||
|
||
## Playwright commons | ||
|
||
def open_nav_menu(page): | ||
page.get_by_label("Open user navigation menu").click() | ||
page.get_by_label("Open user navigation menu").click() | ||
|
||
|
||
def open_settings(page): | ||
#FIXME this is not perfect since it seems to be true even on the Settings/Developer Settings page | ||
#if not page.get_by_role("link", name="Settings", exact=True).is_visible(): | ||
if not page.get_by_text("Your personal account").is_visible(): | ||
open_nav_menu(page) | ||
page.get_by_label("Settings", exact=True).click() | ||
# FIXME this is not perfect since it seems to be true even on the Settings/Developer Settings page | ||
# if not page.get_by_role("link", name="Settings", exact=True).is_visible(): | ||
if not page.get_by_text("Your personal account").is_visible(): | ||
open_nav_menu(page) | ||
page.get_by_label("Settings", exact=True).click() | ||
|
||
|
||
def nav_to_token_settings(page): | ||
open_settings(page) | ||
# navigate to token settings | ||
page.get_by_role("link", name="Developer settings").click() | ||
page.get_by_role("button", name="Personal access tokens").click() | ||
page.get_by_role("link", name="Tokens (classic)").click() | ||
open_settings(page) | ||
# navigate to token settings | ||
page.get_by_role("link", name="Developer settings").click() | ||
page.get_by_role("button", name="Personal access tokens").click() | ||
page.get_by_role("link", name="Tokens (classic)").click() | ||
|
||
|
||
def signout(page): | ||
open_nav_menu(page) | ||
page.get_by_role("link", name="Sign out").click() | ||
page.get_by_role("button", name="Sign out", exact=True).click() | ||
open_nav_menu(page) | ||
page.get_by_role("link", name="Sign out").click() | ||
page.get_by_role("button", name="Sign out", exact=True).click() | ||
|
||
def login(page, project_name, username, password): | ||
response = page.goto("https://github.com/login") | ||
|
||
assert response is not None | ||
if not response.ok: | ||
raise RuntimeError(f"unable to load GitHub login page: {response.status}") | ||
|
||
# login | ||
page.get_by_label("Username or email address").click() | ||
page.get_by_label("Username or email address").fill(username) | ||
|
||
page.get_by_label("Password").click() | ||
page.get_by_label("Password").fill(password) | ||
|
||
page.get_by_role("button", name="Sign in", exact=True).click() | ||
|
||
if (page.get_by_role("heading", name="Device verification").is_visible()): | ||
print ("Found device verification page.") | ||
# manual task | ||
print ("Waiting for verification code...") | ||
#input('Press any key to continue\n') | ||
#TODO: wait for page element instead | ||
elif (page.get_by_role("heading", name="Two-factor authentication").is_visible()): | ||
print ("Found token verification page.") | ||
twofa_token_pass = get_pass_2fa_otp(project_name) | ||
page.get_by_placeholder("XXXXXX").click() | ||
page.get_by_placeholder("XXXXXX").fill(twofa_token_pass) | ||
else: | ||
print("Device verification page not found or skipped.") | ||
|
||
if (page.get_by_role("heading", name="Verify your two-factor authentication (2FA) settings").is_visible()): | ||
print ("Found Verify 2FA page.") | ||
page.get_by_role("button", name="Verify 2FA now").click() | ||
|
||
# deal with confirm account settings page | ||
if (page.get_by_text("Confirm your account recovery settings").is_visible()): | ||
print ("Found account confirmation page.") | ||
page.get_by_role("button", name="Confirm").click() | ||
|
||
if (page.get_by_role("heading", name="Two-factor authentication").is_visible()): | ||
print ("Found 2nd token verification page.") | ||
print ("Waiting for next 2FA token for 35 seconds...") | ||
page.wait_for_timeout(35000) | ||
twofa_token_pass = get_pass_2fa_otp(project_name) | ||
page.get_by_placeholder("XXXXXX").click() | ||
page.get_by_placeholder("XXXXXX").fill(twofa_token_pass) | ||
|
||
if (page.get_by_role("heading", name="2FA verification successful!").is_visible()): | ||
page.get_by_role("link", name="Done").click() | ||
|
||
def login(page, project_name, username, password): | ||
response = page.goto("https://github.com/login") | ||
|
||
assert response is not None | ||
if not response.ok: | ||
raise RuntimeError(f"unable to load GitHub login page: {response.status}") | ||
|
||
# login | ||
page.get_by_label("Username or email address").click() | ||
page.get_by_label("Username or email address").fill(username) | ||
|
||
page.get_by_label("Password").click() | ||
page.get_by_label("Password").fill(password) | ||
|
||
page.get_by_role("button", name="Sign in", exact=True).click() | ||
|
||
if (page.get_by_role("heading", name="Device verification").is_visible()): | ||
print("Found device verification page.") | ||
# manual task | ||
print("Waiting for verification code...") | ||
# input('Press any key to continue\n') | ||
# TODO: wait for page element instead | ||
elif (page.get_by_role("heading", name="Two-factor authentication").is_visible()): | ||
print("Found token verification page.") | ||
twofa_token_pass = get_pass_2fa_otp(project_name) | ||
page.get_by_placeholder("XXXXXX").click() | ||
page.get_by_placeholder("XXXXXX").fill(twofa_token_pass) | ||
else: | ||
print("Device verification page not found or skipped.") | ||
|
||
if (page.get_by_role("heading", name="Verify your two-factor authentication (2FA) settings").is_visible()): | ||
print("Found Verify 2FA page.") | ||
page.get_by_role("button", name="Verify 2FA now").click() | ||
|
||
# deal with confirm account settings page | ||
if (page.get_by_text("Confirm your account recovery settings").is_visible()): | ||
print("Found account confirmation page.") | ||
page.get_by_role("button", name="Confirm").click() | ||
|
||
if (page.get_by_role("heading", name="Two-factor authentication").is_visible()): | ||
print("Found 2nd token verification page.") | ||
print("Waiting for next 2FA token for 35 seconds...") | ||
page.wait_for_timeout(35000) | ||
twofa_token_pass = get_pass_2fa_otp(project_name) | ||
page.get_by_placeholder("XXXXXX").click() | ||
page.get_by_placeholder("XXXXXX").fill(twofa_token_pass) | ||
|
||
if (page.get_by_role("heading", name="2FA verification successful!").is_visible()): | ||
page.get_by_role("link", name="Done").click() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,72 +1,74 @@ | ||
import sys, common | ||
import sys | ||
import common | ||
import pyperclip | ||
from playwright.sync_api import sync_playwright, Page, Error, expect | ||
from playwright.sync_api import sync_playwright, expect | ||
|
||
|
||
def setup_token(page, project_name): | ||
common.nav_to_token_settings(page) | ||
|
||
# Check if token has already been added | ||
page.get_by_role("heading", name="Personal access tokens (classic)").click() # This click is required, otherwise the next elements are not found!? | ||
if page.get_by_role("link", name="otterdog").is_visible(): | ||
print ("Otterdog token has been added already. Skipping.") | ||
return | ||
|
||
#Create Otterdog token | ||
page.get_by_role("button", name="Generate new token").click() | ||
page.get_by_role("menuitem", name="Generate new token (classic) For general use").click() | ||
page.get_by_label("Note").fill("otterdog") | ||
page.get_by_role("combobox", name="Expiration*").select_option("none") | ||
page.get_by_label("repo\n \n\n \n \n Full control of private repositories").check() | ||
page.get_by_label("workflow\n \n\n \n \n Update GitHub Action workflows").check() | ||
page.get_by_label("admin:org\n \n\n \n \n Full control of orgs and teams, read and write org projects").check() | ||
page.get_by_label("admin:org_hook\n \n\n \n \n Full control of organization hooks").check() | ||
page.get_by_label("delete_repo\n \n\n \n \n Delete repositories").check() | ||
page.get_by_role("button", name="Generate token").click() | ||
page.get_by_role("button", name="Copy token").click() | ||
|
||
# get token from clipboard | ||
otterdog_token = pyperclip.paste() | ||
print ("otterdog_token: " + otterdog_token) | ||
# TODO: check that otterdog_token is not empty | ||
|
||
# add token to pass | ||
common.add_to_pass(project_name, otterdog_token, "otterdog-token") | ||
|
||
|
||
### MAIN | ||
common.nav_to_token_settings(page) | ||
|
||
# Check if token has already been added | ||
page.get_by_role("heading", name="Personal access tokens (classic)").click() # This click is required, otherwise the next elements are not found!? | ||
if page.get_by_role("link", name="otterdog").is_visible(): | ||
print("Otterdog token has been added already. Skipping.") | ||
return | ||
|
||
# Create Otterdog token | ||
page.get_by_role("button", name="Generate new token").click() | ||
page.get_by_role("menuitem", name="Generate new token (classic) For general use").click() | ||
page.get_by_label("Note").fill("otterdog") | ||
page.get_by_role("combobox", name="Expiration*").select_option("none") | ||
page.get_by_label("repo\n \n\n \n \n Full control of private repositories").check() | ||
page.get_by_label("workflow\n \n\n \n \n Update GitHub Action workflows").check() | ||
page.get_by_label("admin:org\n \n\n \n \n Full control of orgs and teams, read and write org projects").check() | ||
page.get_by_label("admin:org_hook\n \n\n \n \n Full control of organization hooks").check() | ||
page.get_by_label("delete_repo\n \n\n \n \n Delete repositories").check() | ||
page.get_by_role("button", name="Generate token").click() | ||
page.get_by_role("button", name="Copy token").click() | ||
|
||
# get token from clipboard | ||
otterdog_token = pyperclip.paste() | ||
print("otterdog_token: " + otterdog_token) | ||
# TODO: check that otterdog_token is not empty | ||
|
||
# add token to pass | ||
common.add_to_pass(project_name, otterdog_token, "otterdog-token") | ||
|
||
|
||
def main(): | ||
_DEFAULT_TIMEOUT = 10000 | ||
_DEFAULT_TIMEOUT = 10000 | ||
|
||
if len(sys.argv) < 2: | ||
print("ERROR: project name must be set") | ||
sys.exit(1) | ||
else: | ||
project_name = sys.argv[1] | ||
print("Project name: " + project_name) | ||
|
||
if len(sys.argv) < 2: | ||
print ("ERROR: project name must be set") | ||
sys.exit(1) | ||
else: | ||
project_name=sys.argv[1] | ||
print ("Project name: " + project_name) | ||
print("opening browser window") | ||
with sync_playwright() as playwright: | ||
browser = playwright.firefox.launch(headless=False) | ||
context = browser.new_context(no_viewport=True) | ||
|
||
print("opening browser window") | ||
with sync_playwright() as playwright: | ||
browser = playwright.firefox.launch(headless=False) | ||
context = browser.new_context(no_viewport=True) | ||
page = context.new_page() | ||
page.set_default_timeout(_DEFAULT_TIMEOUT) | ||
|
||
page = context.new_page() | ||
page.set_default_timeout(_DEFAULT_TIMEOUT) | ||
username = common.get_pass_creds(project_name, "username") | ||
password = common.get_pass_creds(project_name, "password") | ||
|
||
username = common.get_pass_creds(project_name, "username") | ||
password = common.get_pass_creds(project_name, "password") | ||
common.login(page, project_name, username, password) | ||
|
||
common.login(page, project_name, username, password) | ||
expect(page.get_by_role("heading", name="Home", exact=True)).to_be_visible(timeout=30000) | ||
|
||
expect(page.get_by_role("heading", name="Home", exact=True)).to_be_visible(timeout=30000) | ||
setup_token(page, project_name) | ||
|
||
setup_token(page, project_name) | ||
# input('Press any key to continue\n') | ||
common.signout(page) | ||
|
||
#input('Press any key to continue\n') | ||
common.signout(page) | ||
page.close() | ||
context.close() | ||
browser.close() | ||
|
||
page.close() | ||
context.close() | ||
browser.close() | ||
|
||
if __name__ == "__main__": | ||
main() | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,41 @@ | ||
import sys, common | ||
from playwright.sync_api import sync_playwright, Page, Error, expect | ||
import sys | ||
import common | ||
|
||
from playwright.sync_api import sync_playwright, expect | ||
|
||
|
||
### MAIN | ||
def main(): | ||
_DEFAULT_TIMEOUT = 10000 | ||
_DEFAULT_TIMEOUT = 10000 | ||
|
||
if len(sys.argv) < 2: | ||
print("ERROR: project name must be set") | ||
sys.exit(1) | ||
else: | ||
project_name = sys.argv[1] | ||
print("Project name: " + project_name) | ||
|
||
if len(sys.argv) < 2: | ||
print ("ERROR: project name must be set") | ||
sys.exit(1) | ||
else: | ||
project_name=sys.argv[1] | ||
print ("Project name: " + project_name) | ||
print("opening browser window") | ||
with sync_playwright() as playwright: | ||
browser = playwright.firefox.launch(headless=False) | ||
context = browser.new_context(no_viewport=True) | ||
|
||
print("opening browser window") | ||
with sync_playwright() as playwright: | ||
browser = playwright.firefox.launch(headless=False) | ||
context = browser.new_context(no_viewport=True) | ||
page = context.new_page() | ||
page.set_default_timeout(_DEFAULT_TIMEOUT) | ||
|
||
page = context.new_page() | ||
page.set_default_timeout(_DEFAULT_TIMEOUT) | ||
username = common.get_pass_creds(project_name, "username") | ||
password = common.get_pass_creds(project_name, "password") | ||
|
||
username = common.get_pass_creds(project_name, "username") | ||
password = common.get_pass_creds(project_name, "password") | ||
common.login(page, project_name, username, password) | ||
|
||
common.login(page, project_name, username, password) | ||
expect(page.get_by_role("heading", name="Home", exact=True)).to_be_visible(timeout=30000) | ||
|
||
expect(page.get_by_role("heading", name="Home", exact=True)).to_be_visible(timeout=30000) | ||
input('Press any key to continue\n') | ||
common.signout(page) | ||
|
||
input('Press any key to continue\n') | ||
common.signout(page) | ||
page.close() | ||
context.close() | ||
browser.close() | ||
|
||
page.close() | ||
context.close() | ||
browser.close() | ||
|
||
if __name__ == "__main__": | ||
main() |
Oops, something went wrong.