This is an automated email from the ASF dual-hosted git repository.
sbp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-release.git
The following commit(s) were added to refs/heads/main by this push:
new 08471cf Update browser tests and fix key display problems
08471cf is described below
commit 08471cf344a5720b8ae6346c90d6135fa7f34b04
Author: Sean B. Palmer <[email protected]>
AuthorDate: Wed Jun 18 17:10:53 2025 +0100
Update browser tests and fix key display problems
---
atr/db/interaction.py | 4 ++-
atr/routes/keys.py | 3 ++
atr/tasks/checks/signature.py | 3 ++
atr/templates/keys-details.html | 2 +-
atr/templates/keys-review.html | 2 +-
playwright/test.py | 74 ++++++++++++-----------------------------
6 files changed, 33 insertions(+), 55 deletions(-)
diff --git a/atr/db/interaction.py b/atr/db/interaction.py
index e4cbf77..3e935ea 100644
--- a/atr/db/interaction.py
+++ b/atr/db/interaction.py
@@ -158,7 +158,9 @@ async def key_user_session_add(
existing.primary_declared_uid = uids[0] if uids else None
existing.secondary_declared_uids = uids[1:]
existing.apache_uid = asf_uid
- existing.ascii_armored_key = public_key
+ existing.ascii_armored_key = (
+ public_key.decode("utf-8", errors="replace") if
isinstance(public_key, bytes) else public_key
+ )
logging.info(f"Found existing key {fingerprint.upper()},
updating associations")
else:
logging.info(f"Found existing key {fingerprint.upper()}, no
update needed")
diff --git a/atr/routes/keys.py b/atr/routes/keys.py
index 4d7b6f4..246ae7f 100644
--- a/atr/routes/keys.py
+++ b/atr/routes/keys.py
@@ -313,6 +313,9 @@ async def details(session: routes.CommitterSession,
fingerprint: str) -> str | r
await quart.flash("Key committee associations updated
successfully.", "success")
return await session.redirect(details, fingerprint=fingerprint)
+ if isinstance(key.ascii_armored_key, bytes):
+ key.ascii_armored_key = key.ascii_armored_key.decode("utf-8",
errors="replace")
+
return await template.render(
"keys-details.html",
key=key,
diff --git a/atr/tasks/checks/signature.py b/atr/tasks/checks/signature.py
index 51766ea..3ee9963 100644
--- a/atr/tasks/checks/signature.py
+++ b/atr/tasks/checks/signature.py
@@ -105,6 +105,9 @@ async def _check_core_logic(committee_name: str,
artifact_path: str, signature_p
apache_uid_map[key.fingerprint.lower()] = True
public_keys = [key.ascii_armored_key for key in db_public_keys]
+ for i, key in enumerate(public_keys):
+ if isinstance(key, bytes):
+ public_keys[i] = key.decode("utf-8", errors="replace")
return await asyncio.to_thread(
_check_core_logic_verify_signature,
diff --git a/atr/templates/keys-details.html b/atr/templates/keys-details.html
index f7840d9..08bce30 100644
--- a/atr/templates/keys-details.html
+++ b/atr/templates/keys-details.html
@@ -103,6 +103,6 @@
</tbody>
</table>
<h2>ASCII armored key</h2>
- <pre class="mt-3 border border-2 p-3">{{ key.ascii_armored_key if
isinstance(key.ascii_armored_key, str) else
key.ascii_armored_key.decode('utf-8') }}</pre>
+ <pre class="mt-3 border border-2 p-3">{{ key.ascii_armored_key }}</pre>
{# TODO: Add download button for the ASCII armored key #}
{% endblock content %}
diff --git a/atr/templates/keys-review.html b/atr/templates/keys-review.html
index f3698c9..ed70c86 100644
--- a/atr/templates/keys-review.html
+++ b/atr/templates/keys-review.html
@@ -39,7 +39,7 @@
</thead>
<tbody>
{% for key in user_keys %}
- <tr>
+ <tr class="page-user-openpgp-key">
<td class="text-break px-2 align-middle">
<a href="{{ as_url(routes.keys.details,
fingerprint=key.fingerprint) }}">{{ key.fingerprint[-16:]|upper }}</a>
</td>
diff --git a/playwright/test.py b/playwright/test.py
index d9d00bc..c8a2952 100644
--- a/playwright/test.py
+++ b/playwright/test.py
@@ -745,8 +745,8 @@ def test_openpgp_01_upload(page: sync_api.Page,
credentials: Credentials) -> Non
go_to_path(page, "/keys")
logging.info(f"Verifying OpenPGP key with fingerprint
{key_fingerprint_upper} is visible")
- key_card_locator =
page.locator(f'div.card:has(td:has-text("{key_fingerprint_upper}"))')
- sync_api.expect(key_card_locator).to_be_visible()
+ key_row_locator =
page.locator(f'tr.page-user-openpgp-key:has(a[href="/keys/details/{key_fingerprint_lower}"])')
+ sync_api.expect(key_row_locator).to_be_visible()
logging.info("OpenPGP key fingerprint verified successfully on /keys page")
@@ -1075,63 +1075,33 @@ def test_tidy_up_openpgp_keys(page: sync_api.Page) ->
None:
logging.info("Navigated to /keys page for OpenPGP key cleanup")
openpgp_key_section_locator = page.locator("h3:has-text('OpenPGP keys')")
- key_cards_container_locator = openpgp_key_section_locator.locator(
- "xpath=following-sibling::div[contains(@class,
'mb-5')]//div[contains(@class, 'd-grid')]"
- )
- key_cards_locator = key_cards_container_locator.locator("> div.card")
+ table_locator =
openpgp_key_section_locator.locator("xpath=following-sibling::div//table")
+ key_rows_locator = table_locator.locator("tbody tr.page-user-openpgp-key")
- key_cards = key_cards_locator.all()
- logging.info(f"Found {len(key_cards)} potential OpenPGP key cards to
check")
+ key_rows = key_rows_locator.all()
+ logging.info(f"Found {len(key_rows)} OpenPGP key rows to check")
fingerprints_to_delete = []
- for card in key_cards:
- details_element = card.locator("details").first
- summary_element = details_element.locator("summary").first
-
- if not details_element.is_visible(timeout=500):
- logging.warning("OpenPGP key card: <details> element not found or
not visible, skipping")
- continue
- if not summary_element.is_visible(timeout=500):
- logging.warning("OpenPGP key card: <summary> element not found or
not visible, skipping")
+ for row in key_rows:
+ link_locator = row.locator('a[href^="/keys/details/"]')
+ href = link_locator.get_attribute("href")
+ if not href:
+ logging.warning("Could not find href for key details link in a
row, skipping")
continue
+ fingerprint = href.split("/")[-1]
- is_already_open = details_element.evaluate("el =>
el.hasAttribute('open')")
+ go_to_path(page, href, wait=False)
- if not is_already_open:
- logging.info("OpenPGP key card: details is not open, clicking
summary to open")
- summary_element.click()
- try:
- sync_api.expect(details_element).to_have_attribute("open", "",
timeout=2000)
- logging.info("OpenPGP key card: details successfully opened")
- except Exception as e:
- logging.warning(
- f"OpenPGP key card: failed to confirm details opened after
clicking summary: {e}, skipping card"
- )
- continue
- else:
- logging.info("OpenPGP key card: Details already open.")
+ pre_locator = page.locator("pre")
+ sync_api.expect(pre_locator).to_be_visible()
+ key_content = pre_locator.inner_text()
- details_pre_locator = details_element.locator("pre").first
- try:
- sync_api.expect(details_pre_locator).to_be_visible(timeout=1000)
- except Exception as e:
- logging.warning(
- f"OpenPGP key card: <pre> tag not visible even after
attempting to open details: {e}, skipping card"
- )
- continue
-
- key_content = details_pre_locator.inner_text()
if _OPENPGP_TEST_UID in key_content:
- fingerprint_locator =
card.locator('tr:has(th:has-text("Fingerprint")) > td').first
- fingerprint = fingerprint_locator.inner_text().strip()
- if fingerprint:
- logging.info(f"Found test OpenPGP key with fingerprint
{fingerprint} for deletion")
- fingerprints_to_delete.append(fingerprint)
- else:
- logging.warning("Found test OpenPGP key card but could not
extract fingerprint")
- else:
- logging.debug(f"OpenPGP key card: test UID '{_OPENPGP_TEST_UID}'
not found in key content")
+ logging.info(f"Found test OpenPGP key with fingerprint
{fingerprint} for deletion")
+ fingerprints_to_delete.append(fingerprint)
+
+ go_to_path(page, "/keys")
# For the complexity linter only
test_tidy_up_openpgp_keys_continued(page, fingerprints_to_delete)
@@ -1147,8 +1117,8 @@ def test_tidy_up_openpgp_keys_continued(page:
sync_api.Page, fingerprints_to_del
for fingerprint in fingerprints_to_delete:
logging.info(f"Locating delete form for fingerprint: {fingerprint}")
# Locate again by fingerprint for robustness
- card_to_delete_locator =
page.locator(f'div.card:has(td:has-text("{fingerprint}"))')
- delete_button_locator = card_to_delete_locator.locator(
+ row_to_delete_locator =
page.locator(f'tr:has(a[href="/keys/details/{fingerprint}"])')
+ delete_button_locator = row_to_delete_locator.locator(
'form[action="/keys/delete"] input[type="submit"][value="Delete
key"]'
)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]