Skip to content

Conversation

@bonigarcia
Copy link
Member

@bonigarcia bonigarcia commented Nov 17, 2025

User description

🔗 Related Issues

The latest IEDriverServer was done a long time ago (Selenium 4.14), and so, it is currently excluded from the default GitHub API response used for the mirror workflow (due to result pagination). As a result, the support of IEDriverServer in Selenium Manager was started to fail:

> selenium-manager.exe --browser iexplorer --debug
[2025-11-17T09:04:19.669Z DEBUG] IEDriverServer not found in PATH
[2025-11-17T09:04:19.670Z DEBUG] iexplorer detected at C:\Program Files\Internet Explorer\iexplore.exe
[2025-11-17T09:04:19.671Z DEBUG] Detected browser: iexplorer 11.00.26100.1
[2025-11-17T09:04:19.723Z ERROR] IEDriverServer release not available

It is currently failing in CI:

https://github.com/SeleniumHQ/selenium/actions/runs/19414639574/job/55541217140

💥 What does this PR do?

This PR changes the mirror workflow to get all pages in the GitHub API responses. This way, even old releases (e.g., Selenium 4.14) are kept in the mirror file, and Selenium Manager should be able to find IEDriverServer, as usual.

🔧 Implementation Notes

💡 Additional Considerations

🔄 Types of changes

  • Bug fix (backwards compatible)

PR Type

Bug fix


Description

  • Implements pagination in mirror workflow to fetch all GitHub releases

  • Fixes IEDriverServer availability by retrieving old Selenium releases

  • Adds error handling and improved shell script robustness

  • Processes paginated API responses into consolidated mirror file


Diagram Walkthrough

flowchart LR
  A["GitHub API<br/>Releases Endpoint"] -->|"Paginated<br/>per_page=100"| B["Fetch Loop<br/>All Pages"]
  B -->|"Filter & Transform"| C["JQ Processing"]
  C -->|"Aggregate"| D["selenium<br/>Mirror File"]
Loading

File Walkthrough

Relevant files
Bug fix
mirror-selenium-releases.yml
Add pagination logic to GitHub releases API calls               

.github/workflows/mirror-selenium-releases.yml

  • Replaces single API call with paginated loop to fetch all releases
    (100 per page)
  • Adds error handling with set -euo pipefail for shell script robustness
  • Implements temporary file accumulation and final aggregation with jq
    -s 'add'
  • Improves authorization header format and adds debug logging for
    pagination progress
+19/-2   

@selenium-ci selenium-ci added the B-build Includes scripting, bazel and CI integrations label Nov 17, 2025
@bonigarcia bonigarcia added B-manager Selenium Manager ci and removed B-build Includes scripting, bazel and CI integrations labels Nov 17, 2025
@qodo-merge-pro
Copy link
Contributor

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
🟡
🎫 #5678
🔴 Investigate and resolve repeated "Error: ConnectFailure (Connection refused)" when
instantiating multiple ChromeDriver sessions on Ubuntu 16.04 with Chrome 65 and
chromedriver 2.35 using Selenium 3.9.0.
Ensure subsequent ChromeDriver instantiations after the first do not produce connection
errors.
Provide a fix or guidance that addresses environment-specific causes (networking, driver
lifecycle) leading to ConnectFailure.
🟡
🎫 #1234
🔴 Ensure WebDriver 2.48 triggers javascript in link hrefs on click() as it did in 2.47.1 for
Firefox 42.
Provide a regression fix or workaround for click() not executing javascript: href.
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
Missing audit logs: The new script performs multiple external API reads and file writes without emitting
structured audit logs that capture actor, action, and outcome details.

Referred Code
set -euo pipefail
cd common/mirror
TOKEN="${{ secrets.GITHUB_TOKEN }}"
JQ_FILTER='[.[] | {tag_name: .tag_name, assets: [.assets[] | {browser_download_url: .browser_download_url} ] } ]'
page=1
tmpfile="$(mktemp)"
: > "$tmpfile"
while :; do
  echo "Fetching SeleniumHQ/selenium releases page $page..."
  resp=$(curl -fsSL \
    -H "Authorization: token $TOKEN" \
    "https://api.github.com/repos/SeleniumHQ/selenium/releases?per_page=100&page=${page}")
  if [ "$(echo "$resp" | jq 'length')" -eq 0 ]; then
    break
  fi
  echo "$resp" | jq "$JQ_FILTER" >> "$tmpfile"
  page=$((page+1))
done
jq -s 'add' "$tmpfile" > selenium
rm "$tmpfile"

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Partial error handling: While set -euo pipefail and curl -f are used, the script lacks explicit handling/logging
for HTTP rate limits, API errors, or jq failures beyond abrupt exit.

Referred Code
set -euo pipefail
cd common/mirror
TOKEN="${{ secrets.GITHUB_TOKEN }}"
JQ_FILTER='[.[] | {tag_name: .tag_name, assets: [.assets[] | {browser_download_url: .browser_download_url} ] } ]'
page=1
tmpfile="$(mktemp)"
: > "$tmpfile"
while :; do
  echo "Fetching SeleniumHQ/selenium releases page $page..."
  resp=$(curl -fsSL \
    -H "Authorization: token $TOKEN" \
    "https://api.github.com/repos/SeleniumHQ/selenium/releases?per_page=100&page=${page}")
  if [ "$(echo "$resp" | jq 'length')" -eq 0 ]; then
    break
  fi
  echo "$resp" | jq "$JQ_FILTER" >> "$tmpfile"
  page=$((page+1))
done
jq -s 'add' "$tmpfile" > selenium
rm "$tmpfile"

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
External input trust: The script ingests unvalidated JSON from the GitHub API and assumes expected structure
without guarding against unexpected fields or jq parsing errors.

Referred Code
  resp=$(curl -fsSL \
    -H "Authorization: token $TOKEN" \
    "https://api.github.com/repos/SeleniumHQ/selenium/releases?per_page=100&page=${page}")
  if [ "$(echo "$resp" | jq 'length')" -eq 0 ]; then
    break
  fi
  echo "$resp" | jq "$JQ_FILTER" >> "$tmpfile"
  page=$((page+1))
done
jq -s 'add' "$tmpfile" > selenium

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-merge-pro
Copy link
Contributor

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Use GitHub CLI for simpler pagination

Instead of a manual shell loop with curl for GitHub API pagination, use the
pre-installed gh CLI with the gh api --paginate command. This simplifies the
workflow, making it more concise and robust.

Examples:

.github/workflows/mirror-selenium-releases.yml [19-38]
        set -euo pipefail
        cd common/mirror
        TOKEN="${{ secrets.GITHUB_TOKEN }}"
        JQ_FILTER='[.[] | {tag_name: .tag_name, assets: [.assets[] | {browser_download_url: .browser_download_url} ] } ]'
        page=1
        tmpfile="$(mktemp)"
        : > "$tmpfile"
        while :; do
          echo "Fetching SeleniumHQ/selenium releases page $page..."
          resp=$(curl -fsSL \

 ... (clipped 10 lines)

Solution Walkthrough:

Before:

# .github/workflows/mirror-selenium-releases.yml
page=1
tmpfile="$(mktemp)"
while :; do
  resp=$(curl -fsSL \
    -H "Authorization: token $TOKEN" \
    "https://api.github.com/repos/SeleniumHQ/selenium/releases?per_page=100&page=${page}")
  if [ "$(echo "$resp" | jq 'length')" -eq 0 ]; then
    break
  fi
  echo "$resp" | jq "$JQ_FILTER" >> "$tmpfile"
  page=$((page+1))
done
jq -s 'add' "$tmpfile" > selenium
rm "$tmpfile"

After:

# .github/workflows/mirror-selenium-releases.yml
JQ_FILTER='[.[] | {tag_name: .tag_name, assets: [.assets[] | {browser_download_url: .browser_download_url} ] } ]'

gh api --paginate 'repos/SeleniumHQ/selenium/releases?per_page=100' \
  | jq -s 'add' \
  | jq "$JQ_FILTER" > selenium
Suggestion importance[1-10]: 9

__

Why: The suggestion provides a significantly simpler and more robust solution using the idiomatic gh api --paginate command, replacing a complex manual curl loop and improving the workflow's maintainability.

High
General
Ensure temporary file is always cleaned

Add a trap command to ensure the temporary file is always removed on script
exit, even in case of an error.

.github/workflows/mirror-selenium-releases.yml [24-38]

 tmpfile="$(mktemp)"
-: > "$tmpfile"
+trap 'rm -f "$tmpfile"' EXIT
 while :; do
   echo "Fetching SeleniumHQ/selenium releases page $page..."
   resp=$(curl -fsSL \
     -H "Authorization: token $TOKEN" \
     "https://api.github.com/repos/SeleniumHQ/selenium/releases?per_page=100&page=${page}")
   if [ "$(echo "$resp" | jq 'length')" -eq 0 ]; then
     break
   fi
   echo "$resp" | jq "$JQ_FILTER" >> "$tmpfile"
   page=$((page+1))
 done
 jq -s 'add' "$tmpfile" > selenium
-rm "$tmpfile"
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why: The suggestion correctly identifies that the temporary file is not cleaned up if the script fails, and proposes using trap which is a robust, standard practice for ensuring resource cleanup.

Low
Remove redundant file truncation command

Remove the redundant : > "$tmpfile" command because mktemp already creates a
new, empty file.

.github/workflows/mirror-selenium-releases.yml [25]

-: > "$tmpfile"
 
+
  • Apply / Chat
Suggestion importance[1-10]: 3

__

Why: The suggestion correctly identifies a redundant line of code, as mktemp already creates an empty file, and removing it is a minor code cleanup.

Low
Learned
best practice
Validate token and response

Validate that the token is non-empty and fail fast with a clear message; also
check jq output is valid JSON before proceeding.

.github/workflows/mirror-selenium-releases.yml [21-30]

 TOKEN="${{ secrets.GITHUB_TOKEN }}"
-...
+if [ -z "${TOKEN:-}" ]; then
+  echo "GITHUB_TOKEN is missing; cannot query GitHub API." >&2
+  exit 1
+fi
 resp=$(curl -fsSL \
   -H "Authorization: token $TOKEN" \
   "https://api.github.com/repos/SeleniumHQ/selenium/releases?per_page=100&page=${page}")
+echo "$resp" | jq -e . >/dev/null

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 6

__

Why:
Relevant best practice - Guard external API calls with validation and clear error messages.

Low
  • More

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants