diff --git a/.bazelignore b/.bazelignore index 5dc04a346072a..8b40e6384ed79 100644 --- a/.bazelignore +++ b/.bazelignore @@ -23,5 +23,5 @@ java/build/production java/client/build java/server/build javascript/grid-ui/node_modules -javascript/node/selenium-webdriver/node_modules +javascript/selenium-webdriver/node_modules node_modules diff --git a/.bazelrc b/.bazelrc index 281fcd02ad7d5..6c7bbee315a23 100644 --- a/.bazelrc +++ b/.bazelrc @@ -8,7 +8,11 @@ try-import %workspace%/.bazelrc.windows.local # https://github.com/bazelbuild/bazel/issues/20369 # https://github.com/bazelbuild/bazel/issues/21491 -common --enable_bzlmod --lockfile_mode=off +common --lockfile_mode=off + +# Prepare for Bazel 8. These become the default in 8.0.0 +common --incompatible_disallow_empty_glob +common --incompatible_use_plus_in_repo_names # Ensure Windows support is accurate. @@ -20,20 +24,22 @@ build --flag_alias=headless=//common:headless # Set the default java toolchain -build --java_language_version=17 -build --java_runtime_version=remotejdk_17 -build --tool_java_language_version=17 -build --tool_java_runtime_version=remotejdk_17 +build --java_language_version=21 +build --java_runtime_version=remotejdk_21 +build --tool_java_language_version=21 +build --tool_java_runtime_version=remotejdk_21 # We target java 11 by default build --javacopt="--release 11" # Require java dependencies to be used and first-order - build --experimental_strict_java_deps=strict build --explicit_java_test_deps +# Avoid ErrorProne getting annoyed about "impossible null checks" +build --javacopt="-Xep:ImpossibleNullComparison:OFF" + # Allow spaces in runfile paths build --nobuild_runfile_links @@ -55,6 +61,11 @@ query --@aspect_rules_ts//ts:default_to_tsc_transpiler build --incompatible_strict_action_env +# Required to get `protobuf` compiling, which is required for `rules_closure` +build --incompatible_enable_cc_toolchain_resolution +build --cxxopt=-std=c++14 +build --host_cxxopt=-std=c++14 + # For build stamping build --enable_platform_specific_config @@ -94,6 +105,7 @@ test --test_env=JRUBY_OPTS="--dev" test:windows --test_env=PATH test:windows --test_env=LOCALAPPDATA +test:windows --test_env=PROCESSOR_ARCHITECTURE test:windows --test_env=PROGRAMFILES="C:\\Program Files" test:windows --test_env=PROGRAMFILES(X86)="C:\\Program Files (x86)" @@ -102,8 +114,14 @@ test --test_timeout=1800 test:node_debug --test_output=streamed --test_strategy=exclusive --test_timeout=9999 --nocache_test_results test:ruby_debug --test_output=streamed --test_env=RUBY_DEBUG_FORK_MODE=parent --run_under="@bundle//bin:rdbg --nonstop --open --command" -build:release --config=remote + build:release --stamp +build:release --compilation_mode=opt + +# As regular `release` but all the build work happens on the RBE +build:rbe_release --config=release +build:rbe_release --config=rbe +build:rbe_release --remote_download_toplevel # RBE import %workspace%/.bazelrc.remote diff --git a/.bazelrc.remote b/.bazelrc.remote index db858bbfaf1f5..0a93b16902511 100644 --- a/.bazelrc.remote +++ b/.bazelrc.remote @@ -1,68 +1,68 @@ # The RBE to use -build:remote --bes_results_url=https://gypsum.cluster.engflow.com/invocation -build:remote --bes_backend=grpcs://gypsum.cluster.engflow.com -build:remote --remote_executor=grpcs://gypsum.cluster.engflow.com -build:remote --remote_cache=grpcs://gypsum.cluster.engflow.com +build:rbe --bes_results_url=https://gypsum.cluster.engflow.com/invocation +build:rbe --bes_backend=grpcs://gypsum.cluster.engflow.com +build:rbe --remote_executor=grpcs://gypsum.cluster.engflow.com +build:rbe --remote_cache=grpcs://gypsum.cluster.engflow.com # The number of cores available -build:remote -j 50 +build:rbe -j 50 -build:remote --define=EXECUTOR=remote -build:remote --experimental_inmemory_dotd_files -build:remote --experimental_inmemory_jdeps_files -build:remote --remote_timeout=3600 -build:remote --spawn_strategy=remote,local -#build:remote --nolegacy_important_outputs -build:remote --incompatible_strict_action_env=true +build:rbe --define=EXECUTOR=remote +build:rbe --experimental_inmemory_dotd_files +build:rbe --experimental_inmemory_jdeps_files +build:rbe --remote_timeout=3600 +build:rbe --spawn_strategy=remote,local +#build:rbe --nolegacy_important_outputs +build:rbe --incompatible_strict_action_env=true -build:remote --crosstool_top=//common/remote-build/cc:toolchain -build:remote --extra_execution_platforms=//common/remote-build:platform -build:remote --extra_toolchains=//common/remote-build:cc-toolchain -build:remote --host_platform=//common/remote-build:platform -build:remote --platforms=//common/remote-build:platform -build:remote --cxxopt=-std=c++14 +build:rbe --crosstool_top=//common/remote-build/cc:toolchain +build:rbe --extra_execution_platforms=//common/remote-build:platform +build:rbe --extra_toolchains=//common/remote-build:cc-toolchain +build:rbe --host_platform=//common/remote-build:platform +build:rbe --platforms=//common/remote-build:platform +build:rbe --cxxopt=-std=c++14 # The Docker images are running Linux -build:remote --cpu=k8 -build:remote --host_cpu=k8 +build:rbe --cpu=k8 +build:rbe --host_cpu=k8 -build:remote --disk_cache= +build:rbe --disk_cache= -build:remote --incompatible_enable_cc_toolchain_resolution -build:remote --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 -test:remote --test_env=DISPLAY=:99.0 -test:remote --test_tag_filters=-skip-remote,-remote +build:rbe --incompatible_enable_cc_toolchain_resolution +build:rbe --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 +test:rbe --test_env=DISPLAY=:99.0 +test:rbe --test_tag_filters=-skip-rbe,-remote # Env vars we can hard code -build:remote --action_env=HOME=/home/dev -build:remote --action_env=PATH=/bin:/usr/bin:/usr/local/bin -test:remote --test_env=PATH=/bin:/usr/bin:/usr/local/bin -test:remote --test_env=HOME=/home/dev +build:rbe --action_env=HOME=/home/dev +build:rbe --action_env=PATH=/bin:/usr/bin:/usr/local/bin +test:rbe --test_env=PATH=/bin:/usr/bin:/usr/local/bin +test:rbe --test_env=HOME=/home/dev # Make sure we sniff credentials properly -build:remote --credential_helper=gypsum.cluster.engflow.com=%workspace%/scripts/credential-helper.sh +build:rbe --credential_helper=gypsum.cluster.engflow.com=%workspace%/scripts/credential-helper.sh # Use pinned browsers when running remotely -build:remote --//common:pin_browsers +build:rbe --//common:pin_browsers # The remote build machines are pretty small, and 50 threads may leave them # thrashing, but our dev machines are a lot larger. Scale the workload so we # make reasonable usage of everything, everywhere, all at once. -build:remote --local_resources=cpu='HOST_CPUS*10' -build:remote --local_resources=memory='HOST_RAM*4.0' +build:rbe --local_resources=cpu='HOST_CPUS*10' +build:rbe --local_resources=memory='HOST_RAM*4.0' # A small hint that we're running our tests remotely -test:remote --test_env=REMOTE_BUILD=1 +test:rbe --test_env=REMOTE_BUILD=1 # Wait for up to 5 minutes for a test to pass -test:remote --test_timeout=600 +test:rbe --test_timeout=600 # Extend the remote config for CI -build:remote-ci --config=remote -build:remote-ci --curses=no --color=yes --show_timestamps --show_progress_rate_limit=5 -build:remote-ci --bes_upload_mode=wait_for_upload_complete -build:remote-ci --remote_download_minimal +build:rbe-ci --config=rbe +build:rbe-ci --curses=no --color=yes --show_timestamps --show_progress_rate_limit=5 +build:rbe-ci --bes_upload_mode=wait_for_upload_complete +build:rbe-ci --remote_download_minimal # Configuration changes suggested by EngFlow -build:remote --grpc_keepalive_time=30s -build:remote --nolegacy_important_outputs +build:rbe --grpc_keepalive_time=30s +build:rbe --nolegacy_important_outputs diff --git a/.bazelversion b/.bazelversion index 0ee843cc60466..815da58b7a9ed 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1 +1 @@ -7.2.0 +7.4.1 diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index 75cd9ceab450d..cb4556e52d4d4 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -1,94 +1,128 @@ name: šŸ› Bug Report description: File a bug report title: "[šŸ› Bug]: " -labels: [ I-defect, needs-triaging ] +labels: [ I-defect, A-needs-triaging ] body: - - type: markdown - attributes: - value: | - Thanks for taking the time to fill out this bug report! - type: textarea - id: what-happened + id: description attributes: - label: What happened? - description: | - Describe clearly and concisely the bug including instructions showing how to reproduce it. + label: Description placeholder: | - Please add as many details as possible to avoid assumptions from our side. How do you - trigger this bug? What did you expect to happen? Please walk us through it step by step. - Notes: - If the issue is with Google Chrome consider logging an issue with ChromeDriver instead: - https://bugs.chromium.org/p/chromedriver - If the issue is with Firefox GeckoDriver (aka Marionette) consider logging an issue with - Mozilla: https://bugzilla.mozilla.org/buglist.cgi?product=Testing&component=Marionette - If the issue is with Microsoft Edge consider logging an issue with Microsoft instead: - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/ - If the issue is with Safari, only Safari 10+ is supported. Please log any Safari issue - with Apple: https://bugreport.apple.com/ + Include details like: + - What you were trying to do + - What you expected to happen + - What actually happened + - Any relevant context or configuration + - Stacktrace or error message if applicable validations: required: true - type: textarea - id: repro-command + id: reproduction attributes: - label: How can we reproduce the issue? - description: | - Share with a code snippet or a GitHub repo to reproduce the issue. + label: Reproducible Code placeholder: | - Please share the code script to reproduce the issue. If more than one file is needed, - create a GitHub repository and share the link. - This will be automatically formatted into code, so no need for backticks. - Be sure to include an SSCCE (Short, Self Contained, Correct - [compilable] example) http://sscce.org/ - Issues without a reproduction script are likely to stall and eventually be closed. + (This section renders as code, no need for backticks) + + * We can't fix an issue we can't reproduce. + * If more than one file is needed, create a new GitHub repository and link it here. + * Reproduction should be SSCCE: Short, Self Contained, Correct (Compilable), Example. render: shell validations: required: true - type: textarea id: logs attributes: - label: Relevant log output - description: | - Please copy and paste any relevant log output. - Ideally, turn on more detailed logging: https://www.selenium.dev/documentation/webdriver/troubleshooting/logging/ - This will be automatically formatted, so no need for backticks. - render: shell - validations: - required: true + label: Debugging Logs + placeholder: | + Note: the stack trace should be in the explanation section above + Instructions for enabling and referencing logs can be found in the links below + render: logs + - type: markdown + id: link + attributes: + value: | + **Read our [logging documentation](https://www.selenium.dev/documentation/webdriver/troubleshooting/logging/)** + **Link to a [gist](https://gist.github.com/) if logs are too long** +   + + ## Help us Address Your Issue Faster! - type: input - id: operating-system + id: selenium-version attributes: - label: Operating System - description: What host operating system are you using to run Selenium? - placeholder: Windows 10? macOS BigSur? Ubuntu? + label: What version of Selenium are you currently using? + description: Important! The latest released version of Selenium is 4.35 and we can't fix old versions. + placeholder: e.g., 4.17.0 validations: required: true - - type: input - id: selenium-version + - type: checkboxes + id: prerequisites + attributes: + label: The following statements are true + options: + - label: This applies to the most recent version of Selenium (we can't fix old versions) + required: true + - label: This hasn't already been reported (I searched and didn't find it) + required: true + - label: All information necessary to reproduce the issue has been provided above + required: true + - type: dropdown + id: regression attributes: - label: Selenium version - description: What programming language release version of Selenium? - placeholder: Java 4.0.0? Ruby 4.0.3? (please use the full version number). + label: Did this work for you before? + options: + - Not sure, this is my first time trying it + - Yes this is a regression validations: required: true - type: input - id: browser-versions + id: last-good + attributes: + label: If yes, what version of Selenium did it work with? + placeholder: "e.g., 4.8.0" + validations: + required: false + - type: dropdown + id: operating-system attributes: - label: What are the browser(s) and version(s) where you see this issue? - description: What browser and versions are you using? - placeholder: Example - Chrome 90, Firefox 88, etc. + label: Operating System + options: + - "--" + - Windows + - macOS + - Linux (specify in the description) validations: required: true - - type: input - id: browser-driver-versions + - type: dropdown + id: bindings attributes: - label: What are the browser driver(s) and version(s) where you see this issue? - description: What browser driver(s) are you using? - placeholder: Example - ChromeDriver 94.0.4606.61, GeckoDriver 0.30.0, etc. + label: Selenium Language Binding + options: + - "--" + - Java + - Python + - C#/.NET + - JavaScript/Node.js + - Ruby validations: required: true - - type: input - id: selenium-grid-version + - type: dropdown + id: browsers + attributes: + label: Which browsers are you experiencing the issue with? + multiple: true + options: + - Chrome + - Firefox + - Edge + - Safari + - IE + - Other (please specify in the description) + - type: dropdown + id: grid attributes: label: Are you using Selenium Grid? - description: What version of Selenium Grid are you using? - placeholder: Example - 4.0.0 + options: + - "No" + - "Yes" + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/feature_proposal.yml b/.github/ISSUE_TEMPLATE/feature_proposal.yml index 04a8a21d7b541..e2005f52d2539 100644 --- a/.github/ISSUE_TEMPLATE/feature_proposal.yml +++ b/.github/ISSUE_TEMPLATE/feature_proposal.yml @@ -1,31 +1,53 @@ name: šŸš€ Feature Proposal -description: Propose a feature +description: Suggest a new feature or improvement to Selenium title: "[šŸš€ Feature]: " -labels: [ I-enhancement, needs-triaging ] +labels: [ I-enhancement, A-needs-triaging ] body: - - type: markdown - attributes: - value: | - Thanks for taking the time to propose a feature! - type: textarea - id: feature-description + id: description attributes: - label: Feature and motivation - description: | - Describe clearly and concisely the feature you are proposing, what is the motivation - behind it. + label: Description placeholder: | - Help us to understand your proposal by adding as many details as possible, we will look into - it and give you feedback as soon as possible. + What would you like Selenium to support or do differently? + Please include: + - The problem this would solve + - How you expect the feature would work + - Any relevant context or use cases + - Links to related issues, discussions, or external tools (if applicable) validations: required: true + - type: textarea - id: feature-example + id: alternatives attributes: - label: Usage example - description: | - How would you use this feature? + label: Have you considered any alternatives or workarounds? placeholder: | - A clear example showing how this feature is useful for you and the Selenium community. + If you've tried other ways to solve this problem, describe them here. + If not, you can leave this blank. validations: - required: true + required: false + + - type: dropdown + id: bindings + attributes: + label: Does this apply to specific language bindings? + multiple: true + options: + - Java + - Python + - C#/.NET + - JavaScript/Node.js + - Ruby + + - type: dropdown + id: components + attributes: + label: What part(s) of Selenium does this relate to? + multiple: true + options: + - Atoms + - Build (CI or Bazel) + - DevTools (CDP or BiDi) + - Documentation + - Grid + - Selenium Manager diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 7fcdfc28a62bd..9fa86b9c5fe64 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,30 +1,24 @@ -**Thanks for contributing to Selenium!** -**A PR well described will help maintainers to quickly review and merge it** + + -Before submitting your PR, please check our [contributing](https://github.com/SeleniumHQ/selenium/blob/trunk/CONTRIBUTING.md) guidelines. -Avoid large PRs, help reviewers by making them as simple and short as possible. +### šŸ”— Related Issues + + +### šŸ’„ What does this PR do? + - +### šŸ”§ Implementation Notes + + -### Description - +### šŸ’” Additional Considerations + + -### Motivation and Context - - -### Types of changes - -- [ ] Bug fix (non-breaking change which fixes an issue) -- [ ] New feature (non-breaking change which adds functionality) -- [ ] Breaking change (fix or feature that would cause existing functionality to change) - -### Checklist - - -- [ ] I have read the [contributing](https://github.com/SeleniumHQ/selenium/blob/trunk/CONTRIBUTING.md) document. -- [ ] My change requires a change to the documentation. -- [ ] I have updated the documentation accordingly. -- [ ] I have added tests to cover my changes. -- [ ] All new and existing tests passed. - +### šŸ”„ Types of changes + +- Cleanup (formatting, renaming) +- Bug fix (backwards compatible) +- New feature (non-breaking change which adds functionality *and tests!*) +- Breaking change (fix or feature that would cause existing functionality to change) diff --git a/.github/issue-labeler-config.yml b/.github/issue-labeler-config.yml new file mode 100644 index 0000000000000..4fc070272e611 --- /dev/null +++ b/.github/issue-labeler-config.yml @@ -0,0 +1,61 @@ +policy: + - section: + - id: [operating-system] + label: + - name: OS-windows + keys: [ Windows ] + - name: OS-mac + keys: [ macOS ] + - name: OS-linux + keys: [ Linux (specify in the description) ] + + - id: [bindings] + label: + - name: C-java + keys: [ Java ] + - name: C-py + keys: [ Python ] + - name: C-dotnet + keys: [ C#/.NET ] + - name: C-rb + keys: [ Ruby ] + - name: C-nodejs + keys: [ JavaScript/Node.js ] + + - id: [regression] + label: + - name: I-regression + keys: [ Yes this is a regression ] + + - id: [components] + label: + - name: B-grid + keys: [ Grid ] + - name: B-docs + keys: [ Documentation ] + - name: B-devtools + keys: [ DevTools (CDP or BiDi) ] + - name: B-manager + keys: [ Selenium Manager ] + - name: B-build + keys: [ Build (CI or Bazel) ] + - name: B-atoms + keys: [ Atoms ] + + - id: [browsers] + label: + - name: D-chrome + keys: [ Chrome ] + - name: D-firefox + keys: [ Firefox ] + - name: D-safari + keys: [ Safari ] + - name: D-edge + keys: [ Edge ] + - name: D-IE + keys: [ IE ] + + - id: [grid] + label: + - name: B-grid + keys: [ "Yes" ] diff --git a/.github/label-commenter-config.yml b/.github/label-commenter-config.yml index a4733b7d647b2..4932a6aa025dd 100644 --- a/.github/label-commenter-config.yml +++ b/.github/label-commenter-config.yml @@ -1,41 +1,12 @@ # Configuration for Label Commenter - https://github.com/peaceiris/actions-label-commenter labels: - - name: needs-triaging + - name: A-needs-triaging labeled: issue: body: | @{{ issue.user.login }}, thank you for creating this issue. We will troubleshoot it as soon as we can. - --- -
- Info for maintainers -
-
-

- Triage this issue by using labels. -

-

- If information is missing, add a helpful comment and then I-issue-template label. -

-

- If the issue is a question, add the I-question label. -

-

- If the issue is valid but there is no time to troubleshoot it, consider adding the help wanted label. -

-

- If the issue requires changes or fixes from an external project (e.g., ChromeDriver, GeckoDriver, MSEdgeDriver, W3C), - add the applicable G-* label, and it will provide the correct link and auto-close the - issue. -

-

- After troubleshooting the issue, please add the R-awaiting answer label. -

-

- Thank you! -

-
-
+ Selenium Triage Team: remember to follow the [Triage Guide](https://github.com/SeleniumHQ/selenium/wiki/How-to-Triage-Issues) - name: G-w3c labeled: issue: @@ -101,18 +72,18 @@ labels: Feel free to comment the issues that you raise back in this issue. Thank you. action: close - - name: I-issue-template + - name: J-issue-template labeled: issue: body: | Hi, @{{ issue.user.login }}. - Please follow the issue template, we need more information to reproduce the issue. + Please follow the issue template; we need more information to reproduce the issue. Either a complete code snippet and URL/HTML (if more than one file is needed, provide a GitHub repo and instructions to run the code), the specific versions used, or a more detailed description to help us understand the issue. Note: If you cannot share your code and URL/HTML, any complete code snippet and URL/HTML that reproduces the issue is good enough. - Reply to this issue when all information is provided, thank you. + Reply to this issue when all information is provided. Thank you. - name: I-question labeled: issue: @@ -122,14 +93,14 @@ labels: * šŸ“® [StackOverflow](https://stackoverflow.com/questions/tagged/selenium) * šŸ—£ Our [IRC/Slack/Matrix channels](https://www.selenium.dev/support/) where the community can help you as well action: close - - name: help wanted + - name: R-help wanted labeled: issue: body: | This issue is looking for contributors. Please comment below or reach out to us through our [IRC/Slack/Matrix channels](https://www.selenium.dev/support/) if you are interested. - - name: I-logging + - name: J-logging labeled: issue: body: | @@ -137,3 +108,29 @@ labels: Please turn on logging and re-run your code. Information on how to adjust logs for your language can be found in our [Troubleshooting documentation](https://www.selenium.dev/documentation/webdriver/troubleshooting/logging/). + - name: B-support + labeled: + issue: + body: | + Hi, @{{ issue.user.login }}. + + This is related to code in the Support packages. The support packages contain example code that + many users find helpful, but they do not necessarily represent the best practices for using Selenium, + and the Selenium team is not prioritizing work on them right now. + This doesn't mean that we won't ever work on them, but it is not on our roadmap as we push to release Selenium 5. + + We actively encourage people to create their own wrapper and helper code that makes sense for them. + If you have any questions, please [contact us](https://www.selenium.dev/support) + pr: + body: | + Thank you, @{{ pull_request.user.login }} for this code suggestion. + + The support packages contain example code that many users find helpful, but they do not necessarily represent + the best practices for using Selenium, and the Selenium team is not currently merging changes to them. + + We actively encourage people to add the wrapper and helper code that makes sense for them to their own frameworks. + If you have any questions, please [contact us](https://www.selenium.dev/support) + action: close + + + diff --git a/.github/pr-labeler-config.yml b/.github/pr-labeler-config.yml new file mode 100644 index 0000000000000..1ad4a3ab14e03 --- /dev/null +++ b/.github/pr-labeler-config.yml @@ -0,0 +1,74 @@ +C-java: + - changed-files: + - any-glob-to-any-file: + - 'java/**' + +C-py: + - changed-files: + - any-glob-to-any-file: + - 'py/**' + +C-dotnet: + - changed-files: + - any-glob-to-any-file: + - 'dotnet/**' + +C-rb: + - changed-files: + - any-glob-to-any-file: + - 'rb/**' + +C-nodejs: + - changed-files: + - any-glob-to-any-file: + - 'javascript/selenium-webdriver/**' + +C-cpp: + - changed-files: + - any-glob-to-any-file: + - 'cpp/**' + +C-rust: + - changed-files: + - any-glob-to-any-file: + - 'rust/**' + +B-atoms: + - changed-files: + - any-glob-to-any-file: + - 'javascript/atoms/**' + +B-grid: + - changed-files: + - any-glob-to-any-file: + - 'java/src/org/openqa/selenium/grid/**' + - 'javascript/grid-ui/**' + +B-manager: + - changed-files: + - any-glob-to-any-file: + - 'rust/**' + +B-devtools: + - changed-files: + - any-glob-to-any-file: + - 'common/devtools/**' + - '**/devtools/**' + - '**/bidi/**' + +B-build: + - changed-files: + - any-glob-to-any-file: + - '.github/**' + - 'scripts/**' + - 'rake_tasks/**' + - 'Rakefile' + - 'BUILD.bazel' + - '**/*.bazel' + - '**/*.bzl' + - '.bazel*' + +B-support: + - changed-files: + - any-glob-to-any-file: + - '**/support/**' diff --git a/.github/release.yml b/.github/release.yml index 8f13b55a4e290..4b0e5f9a11c83 100644 --- a/.github/release.yml +++ b/.github/release.yml @@ -1,6 +1,6 @@ changelog: exclude: labels: - -dependencies + - B-dependencies authors: - selenium-ci diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 0000000000000..818b30e75f3f7 --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,3 @@ +{ + "labels": ["B-dependencies"] +} diff --git a/.github/workflows/bazel.yml b/.github/workflows/bazel.yml index 41a100327c9db..017ab6fa92eea 100644 --- a/.github/workflows/bazel.yml +++ b/.github/workflows/bazel.yml @@ -70,7 +70,7 @@ on: jobs: bazel: name: ${{ inputs.name }} - runs-on: ${{ inputs.os == 'macos' && 'macos-13' || format('{0}-latest', inputs.os) }} + runs-on: ${{ contains(inputs.os, '-') && inputs.os || format('{0}-latest', inputs.os) }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SEL_M2_USER: ${{ secrets.SEL_M2_USER }} @@ -82,6 +82,12 @@ jobs: steps: - name: Checkout source tree uses: actions/checkout@v4 + - name: Pull latest changes from head ref for PRs + if: contains(github.head_ref, 'renovate/') + run: git pull origin ${{ github.head_ref }} + - name: Pull latest changes from ref for branch pushes + if: contains(github.ref, 'renovate/') + run: git pull origin ${{ github.ref }} - name: Free space if: inputs.os != 'windows' run: ./scripts/github-actions/free-disk-space.sh @@ -116,7 +122,7 @@ jobs: node-version: ${{ inputs.node-version }} - name: Setup Bazel with caching if: inputs.caching - uses: bazel-contrib/setup-bazel@0.8.5 + uses: bazel-contrib/setup-bazel@0.15.0 with: bazelisk-cache: true bazelrc: common --color=yes @@ -126,13 +132,16 @@ jobs: name: ${{ inputs.cache-key }} manifest: crates: rust/Cargo.Bazel.lock - rules_ruby~~ruby~ruby: ${{ inputs.os == 'windows' && 'false' || 'rb/.ruby-version' }} + rules_ruby++ruby+ruby: ${{ inputs.os == 'windows' && 'false' || 'rb/.ruby-version' }} repository-cache: true - name: Setup Bazel without caching if: inputs.caching == false - uses: bazel-contrib/setup-bazel@0.8.5 + uses: bazel-contrib/setup-bazel@0.15.0 with: bazelrc: common --color=yes + - name: Setup curl for Ubuntu + if: inputs.os == 'ubuntu' + run: sudo apt-get update && sudo apt-get install -y libcurl4-openssl-dev - name: Setup Fluxbox and Xvfb if: inputs.os == 'ubuntu' && inputs.browser != '' run: | diff --git a/.github/workflows/ci-dotnet.yml b/.github/workflows/ci-dotnet.yml index 65debef8c10e4..1e2a2c259382d 100644 --- a/.github/workflows/ci-dotnet.yml +++ b/.github/workflows/ci-dotnet.yml @@ -23,4 +23,5 @@ jobs: java-version: 17 os: windows run: | + fsutil 8dot3name set 0 bazel test //dotnet/test/common:ElementFindingTest-firefox //dotnet/test/common:ElementFindingTest-chrome --pin_browsers=true diff --git a/.github/workflows/ci-grid-ui.yml b/.github/workflows/ci-grid-ui.yml new file mode 100644 index 0000000000000..f9d1f145dbe76 --- /dev/null +++ b/.github/workflows/ci-grid-ui.yml @@ -0,0 +1,38 @@ +name: CI - Grid UI + +on: + pull_request: + paths: + - 'javascript/grid-ui/**' + push: + branches: + - trunk + paths: + - 'javascript/grid-ui/**' + workflow_dispatch: + workflow_call: + +jobs: + grid-ui-tests: + runs-on: ubuntu-latest + name: Grid UI Component Tests + steps: + - name: Checkout source tree + uses: actions/checkout@v4 + with: + fetch-depth: 50 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: 'javascript/grid-ui/package.json' + + - name: Install dependencies + working-directory: javascript/grid-ui + run: npm install + + - name: Run component tests + working-directory: javascript/grid-ui + run: npm test diff --git a/.github/workflows/ci-java.yml b/.github/workflows/ci-java.yml index 569d68d562440..63727764a0953 100644 --- a/.github/workflows/ci-java.yml +++ b/.github/workflows/ci-java.yml @@ -22,12 +22,14 @@ jobs: # https://github.com/bazelbuild/rules_jvm_external/issues/1046 java-version: 17 run: | - bazel test --flaky_test_attempts 3 //java/test/org/openqa/selenium/chrome:ChromeDriverFunctionalTest ` + fsutil 8dot3name set 0 + bazel test --flaky_test_attempts 3 --pin_browsers=true //java/test/org/openqa/selenium/chrome:ChromeDriverFunctionalTest ` //java/test/org/openqa/selenium/federatedcredentialmanagement:FederatedCredentialManagementTest ` //java/test/org/openqa/selenium/firefox:FirefoxDriverBuilderTest ` //java/test/org/openqa/selenium/grid/router:RemoteWebDriverDownloadTest ` //java/test/org/openqa/selenium/remote:RemoteWebDriverBuilderTest ` - //java/test/org/openqa/selenium/grid/router:RemoteWebDriverDownloadTest + //java/test/org/openqa/selenium/grid/router:RemoteWebDriverDownloadTest ` + //java/test/org/openqa/selenium/devtools:NetworkInterceptorRestTest browser-tests-macos: name: Browser Tests @@ -46,7 +48,7 @@ jobs: # https://github.com/bazelbuild/rules_jvm_external/issues/1046 java-version: 17 run: | - bazel test --flaky_test_attempts 3 //java/test/org/openqa/selenium/chrome:ChromeDriverFunctionalTest-remote \ + bazel test --flaky_test_attempts 3 --pin_browsers=true //java/test/org/openqa/selenium/chrome:ChromeDriverFunctionalTest-remote \ //java/test/org/openqa/selenium/federatedcredentialmanagement:FederatedCredentialManagementTest \ //java/test/org/openqa/selenium/firefox:FirefoxDriverBuilderTest \ //java/test/org/openqa/selenium/grid/router:RemoteWebDriverDownloadTest \ @@ -70,4 +72,4 @@ jobs: # https://github.com/bazelbuild/rules_jvm_external/issues/1046 java-version: 17 run: | - bazel test --flaky_test_attempts 3 //java/test/org/openqa/selenium/chrome:ChromeDriverFunctionalTest-remote + bazel test --flaky_test_attempts 3 --pin_browsers=true //java/test/org/openqa/selenium/chrome:ChromeDriverFunctionalTest-remote diff --git a/.github/workflows/ci-python.yml b/.github/workflows/ci-python.yml index 9749fd4e7ad82..96bdbfefddf18 100644 --- a/.github/workflows/ci-python.yml +++ b/.github/workflows/ci-python.yml @@ -16,64 +16,41 @@ jobs: docs: name: Documentation needs: build - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Checkout source tree uses: actions/checkout@v4 - - name: Set up Python 3.8 + - name: Set up Python 3.9 uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: 3.9 - name: Install dependencies run: | python -m pip install --upgrade pip - pip install tox==4.6.4 - - name: Test with tox + pip install tox==4.27.0 + - name: Generate docs run: tox -c py/tox.ini env: TOXENV: docs - lint: - name: Lint - needs: build - runs-on: ubuntu-20.04 - steps: - - name: Checkout source tree - uses: actions/checkout@v4 - - name: Set up Python 3.8 - uses: actions/setup-python@v4 - with: - python-version: 3.8 - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install tox==4.6.4 - - name: Test with tox - run: tox -c py/tox.ini - env: - # If this fails, it will exit. Local work should be using `tox -e linting` prior to committing. - # the linting-ci recipe exists solely for CI and will not attempt to rewrite any files in-place etc. - TOXENV: linting-ci - mypy: name: Mypy needs: build - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Checkout source tree uses: actions/checkout@v4 - - name: Set up Python 3.8 + - name: Set up Python 3.9 uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: 3.9 - name: Install dependencies run: | python -m pip install --upgrade pip - pip install tox==4.6.4 - - name: Test with tox + pip install tox==4.27.0 + - name: Run type checking run: | - tox -c py/tox.ini -- --cobertura-xml-report ci || true - bash <(curl -s https://codecov.io/bash) -f py/ci/cobertura.xml + tox -c py/tox.ini || true env: TOXENV: mypy @@ -81,8 +58,54 @@ jobs: name: Remote Tests needs: build uses: ./.github/workflows/bazel.yml + strategy: + fail-fast: false + matrix: + include: + - browser: firefox with: - name: Integration Tests (remote) - browser: firefox - cache-key: py-remote + name: Integration Tests (remote, ${{ matrix.browser }}) + browser: ${{ matrix.browser }} + cache-key: py-remote-${{ matrix.browser }} run: bazel test --local_test_jobs 1 --flaky_test_attempts 3 //py:test-remote + + browser-tests: + name: Browser Tests + needs: build + uses: ./.github/workflows/bazel.yml + strategy: + fail-fast: false + matrix: + include: + - browser: chrome + os: ubuntu + - browser: edge + os: ubuntu + - browser: firefox + os: ubuntu + with: + name: Integration Tests (${{ matrix.browser }}, ${{ matrix.os }}) + browser: ${{ matrix.browser }} + os: ${{ matrix.os }} + cache-key: py-browser-${{ matrix.browser }} + run: | + bazel test --local_test_jobs 1 --flaky_test_attempts 3 --pin_browsers=true //py:common-${{ matrix.browser }}-bidi + bazel test --local_test_jobs 1 --flaky_test_attempts 3 --pin_browsers=true //py:test-${{ matrix.browser }} + + safari-tests: + name: Browser Tests + needs: build + uses: ./.github/workflows/bazel.yml + strategy: + fail-fast: false + matrix: + include: + - browser: safari + os: macos + with: + name: Integration Tests (${{ matrix.browser }}, ${{ matrix.os }}) + browser: ${{ matrix.browser }} + os: ${{ matrix.os }} + cache-key: py-browser-${{ matrix.browser }} + run: | + bazel test --local_test_jobs 1 --flaky_test_attempts 3 --pin_browsers=true //py:test-${{ matrix.browser }} diff --git a/.github/workflows/ci-rbe.yml b/.github/workflows/ci-rbe.yml index 382aea6409f2a..405bffde2bad8 100644 --- a/.github/workflows/ci-rbe.yml +++ b/.github/workflows/ci-rbe.yml @@ -6,24 +6,30 @@ on: branches: - trunk workflow_dispatch: + inputs: + disable_test_cache: + description: 'Force re-run of tests (disable test cache)' + required: false + default: false + type: boolean jobs: format: name: Format - if: github.repository_owner == 'seleniumhq' + if: github.repository_owner == 'seleniumhq' && startsWith(github.head_ref, 'renovate/') != true uses: ./.github/workflows/bazel.yml with: name: Check format script run caching: false - ruby-version: jruby-9.4.5.0 + ruby-version: jruby-10.0.0.0 run: ./scripts/github-actions/check-format.sh test: name: Test - if: github.repository_owner == 'seleniumhq' + if: github.repository_owner == 'seleniumhq' && startsWith(github.head_ref, 'renovate/') != true uses: ./.github/workflows/bazel.yml with: name: All RBE tests caching: false - ruby-version: jruby-9.4.5.0 - run: ./scripts/github-actions/ci-build.sh + ruby-version: jruby-10.0.0.0 + run: ./scripts/github-actions/ci-build.sh ${{ github.event.inputs.disable_test_cache }} diff --git a/.github/workflows/ci-renovate-rbe.yml b/.github/workflows/ci-renovate-rbe.yml new file mode 100644 index 0000000000000..e0423839568d3 --- /dev/null +++ b/.github/workflows/ci-renovate-rbe.yml @@ -0,0 +1,68 @@ +name: CI - Renovate - RBE + +on: + push: + branches: + - renovate/* + workflow_dispatch: + +jobs: + pin: + runs-on: ubuntu-latest + if: github.repository_owner == 'seleniumhq' + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + - name: java - repin dependencies + if: contains(join(github.event.commits.*.message), '[java]') + run: RULES_JVM_EXTERNAL_REPIN=1 bazel run @maven//:pin + - name: rust - repin dependencies + if: contains(join(github.event.commits.*.message), '[rust]') + run: CARGO_BAZEL_REPIN=true bazel sync --only=crates + - name: js - repin dependencies + if: contains(join(github.event.commits.*.message), '[js]') + run: bazel run -- @pnpm//:pnpm install --dir $PWD --lockfile-only + - name: dotnet - repin dependencies + if: contains(join(github.event.commits.*.message), '[dotnet]') + run: ./dotnet/update-deps.sh + - name: py - repin dependencies + if: contains(join(github.event.commits.*.message), '[py]') + run: bazel run //py:requirements.update + - name: Commit files + run: | + export CHANGES=$(git status -s) + if [ -n "$CHANGES" ]; then + git config --local user.email "selenium-ci@users.noreply.github.com" + git config --local user.name "Selenium CI Bot" + git add . + git commit -m 'Repin dependencies' + git push + fi + + check-format: + needs: pin + name: Check format + if: github.repository_owner == 'seleniumhq' + uses: ./.github/workflows/bazel.yml + with: + name: Check format script run + caching: false + ruby-version: jruby-10.0.0.0 + run: ./scripts/github-actions/check-format.sh + + test: + name: Test + needs: pin + if: github.repository_owner == 'seleniumhq' + uses: ./.github/workflows/bazel.yml + with: + name: All RBE tests + caching: false + ruby-version: jruby-10.0.0.0 + run: ./scripts/github-actions/ci-build.sh + + ci-gh: + name: CI - GitHub + needs: pin + if: github.repository_owner == 'seleniumhq' + uses: ./.github/workflows/ci.yml diff --git a/.github/workflows/ci-ruby.yml b/.github/workflows/ci-ruby.yml index 419e17df5065c..91bfc322ab9b4 100644 --- a/.github/workflows/ci-ruby.yml +++ b/.github/workflows/ci-ruby.yml @@ -22,15 +22,6 @@ jobs: cache-key: rb-docs run: bazel run //rb:docs - lint: - name: Lint - needs: build - uses: ./.github/workflows/bazel.yml - with: - name: Lint - cache-key: rb-lint - run: bazel test //rb:lint - unit-tests: name: Unit Tests needs: build @@ -39,25 +30,26 @@ jobs: fail-fast: false matrix: include: - - ruby-version: 3.0.6 + - ruby-version: 3.2.8 os: ubuntu - - ruby-version: 3.0.6 + - ruby-version: 3.2.8 os: windows - - ruby-version: 3.0.6 + - ruby-version: 3.2.8 os: macos - - ruby-version: 3.3.0 + - ruby-version: 3.4.3 os: ubuntu - - ruby-version: jruby-9.4.5.0 + - ruby-version: jruby-10.0.0.0 os: ubuntu - - ruby-version: truffleruby-23.1.1 + - ruby-version: truffleruby-24.2.1 os: ubuntu with: name: Unit Tests (${{ matrix.ruby-version }}, ${{ matrix.os }}) - cache-key: rb-unit-test-${{ matrix.ruby-version }} + cache-key: rb-unit-test-${{ matrix.ruby-version }}-${{ matrix.os }} os: ${{ matrix.os }} ruby-version: ${{ matrix.ruby-version }} run: > bazel test + --keep_going --build_tests_only --test_size_filters small //rb/spec/... @@ -82,16 +74,17 @@ jobs: with: name: Local Tests (${{ matrix.browser }}, ${{ matrix.os }}) browser: ${{ matrix.browser }} - cache-key: rb-${{ matrix.browser }}-test + cache-key: rb-${{ matrix.browser }}-${{ matrix.os }}-test os: ${{ matrix.os }} run: > bazel test + --keep_going --build_tests_only --flaky_test_attempts 3 --local_test_jobs 1 --test_size_filters large --test_tag_filters ${{ matrix.browser }} - ${{ matrix.os != 'windows' && '--pin_browsers' || '' }} + --pin_browsers //rb/spec/... integration-tests-remote: @@ -107,15 +100,16 @@ jobs: with: name: Remote Tests (${{ matrix.browser }}, ${{ matrix.os }}) browser: ${{ matrix.browser }} - cache-key: rb-remote-${{ matrix.browser }}-test + cache-key: rb-remote-${{ matrix.browser }}-${{ matrix.os }}-test os: ${{ matrix.os }} - java-version: 11 + java-version: 17 run: > bazel test + --keep_going --build_tests_only --flaky_test_attempts 3 --local_test_jobs 1 --test_size_filters large --test_tag_filters ${{ matrix.browser }}-remote - ${{ matrix.os != 'windows' && '--pin_browsers' || '' }} + --pin_browsers //rb/spec/... diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2175fe47d3b96..00e7031f760d9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,10 +8,14 @@ on: schedule: - cron: "0 */12 * * *" workflow_dispatch: + workflow_call: jobs: check: name: Check + if: > + github.repository_owner == 'seleniumhq' && + (startsWith(github.head_ref, 'renovate/') != true || github.event_name == 'workflow_call') runs-on: ubuntu-latest outputs: targets: ${{ steps.check-targets.outputs.bazel-targets }} @@ -21,7 +25,7 @@ jobs: with: fetch-depth: 50 - name: Setup Bazel - uses: bazel-contrib/setup-bazel@0.8.5 + uses: bazel-contrib/setup-bazel@0.15.0 with: bazelisk-cache: true cache-version: 2 @@ -44,6 +48,7 @@ jobs: if: > github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || + github.event_name == 'workflow_call' || contains(needs.check.outputs.targets, '//dotnet') || contains(join(github.event.commits.*.message), '[dotnet]') || contains(github.event.pull_request.title, '[dotnet]') @@ -55,6 +60,7 @@ jobs: if: > github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || + github.event_name == 'workflow_call' || contains(needs.check.outputs.targets, '//java') || contains(join(github.event.commits.*.message), '[java]') || contains(github.event.pull_request.title, '[java]') @@ -66,6 +72,7 @@ jobs: if: > github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || + github.event_name == 'workflow_call' || contains(needs.check.outputs.targets, '//py') || contains(join(github.event.commits.*.message), '[py]') || contains(github.event.pull_request.title, '[py]') @@ -77,6 +84,7 @@ jobs: if: > github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || + github.event_name == 'workflow_call' || contains(needs.check.outputs.targets, '//rb') || contains(join(github.event.commits.*.message), '[rb]') || contains(github.event.pull_request.title, '[rb]') @@ -90,6 +98,7 @@ jobs: if: > github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || + github.event_name == 'workflow_call' || contains(needs.check.outputs.targets, '//rust') || contains(join(github.event.commits.*.message), '[rust]') || contains(github.event.pull_request.title, '[rust]') diff --git a/.github/workflows/delete-comments.yml b/.github/workflows/delete-comments.yml new file mode 100644 index 0000000000000..d766665ced333 --- /dev/null +++ b/.github/workflows/delete-comments.yml @@ -0,0 +1,44 @@ +name: Delete Comments + +on: + issue_comment: + types: [created] + +permissions: + issues: write + +jobs: + delete_comment: + runs-on: ubuntu-latest + steps: + - name: Check for specific strings in comment + id: check_comment + uses: actions/github-script@v7 + with: + script: | + const comment = context.payload.comment.body; + const triggerStrings = ['www.mediafire.com']; + return triggerStrings.some(triggerString => comment.includes(triggerString)); + + - name: Delete comment if it contains any of the specific strings + if: steps.check_comment.outputs.result == 'true' + uses: actions/github-script@v7 + with: + script: | + const commentId = context.payload.comment.id; + await github.rest.issues.deleteComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: commentId + }); + + - name: Block user from the org if their comment contained any of the banned strings + if: steps.check_comment.outputs.result == 'true' + uses: actions/github-script@v7 + with: + script: | + const username = context.payload.comment.user.login + await github.rest.orgs.blockUser({ + org: context.repo.owner, + username: username + }); diff --git a/.github/workflows/issue-labeler.yml b/.github/workflows/issue-labeler.yml new file mode 100644 index 0000000000000..d117fb09f6796 --- /dev/null +++ b/.github/workflows/issue-labeler.yml @@ -0,0 +1,188 @@ +name: Issue Form Labeler +on: + issues: + types: [ opened ] + +jobs: + label-issues: + runs-on: ubuntu-latest + permissions: + issues: write + steps: + - uses: actions/checkout@v3 + + - name: Parse bug report form + id: bug-parser + uses: stefanbuck/github-issue-parser@v3 + with: + template-path: .github/ISSUE_TEMPLATE/bug-report.yml + continue-on-error: true + + - name: Parse feature proposal form + id: feature-parser + uses: stefanbuck/github-issue-parser@v3 + with: + template-path: .github/ISSUE_TEMPLATE/feature_proposal.yml + continue-on-error: true + + - name: Apply labels from bug report + uses: redhat-plumbers-in-action/advanced-issue-labeler@v3 + with: + issue-form: ${{ steps.bug-parser.outputs.jsonString }} + token: ${{ secrets.GITHUB_TOKEN }} + config-path: .github/issue-labeler-config.yml + continue-on-error: true + + - name: Apply labels from feature proposal + uses: redhat-plumbers-in-action/advanced-issue-labeler@v3 + with: + issue-form: ${{ steps.feature-parser.outputs.jsonString }} + token: ${{ secrets.GITHUB_TOKEN }} + config-path: .github/issue-labeler-config.yml + continue-on-error: true + + - name: Clean up labeled sections + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const issueNumber = context.issue.number; + const originalBody = context.payload.issue.body; + const owner = context.repo.owner; + const repo = context.repo.repo; + + const headingsToRemove = [ + '### What version of Selenium are you currently using?', + '### The following statements are true', + '### Did this work for you before?', + '### If yes, what version of Selenium did it work with?', + '### Operating System', + '### Selenium Language Binding', + '### Which browsers are you experiencing the issue with?', + '### Are you using Selenium Grid?', + '### Does this apply to specific language bindings?', + '### What part(s) of Selenium does this relate to?' + ]; + + const form = JSON.parse(process.env.FORM_JSON || '{}'); + const lastGood = form?.["last-good"]?.trim(); + + // Conditionally remove Debugging Logs + const logs = form?.logs?.trim(); + const isLogsEmpty = !logs || logs === '```logs\n\n```' || logs === '```logs```'; + + if (isLogsEmpty) { + headingsToRemove.push('### Debugging Logs'); + } + + const lines = originalBody.split(/\r?\n/); + const cleanedLines = []; + + let skip = false; + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + const trimmed = line.trim(); + + if (headingsToRemove.includes(trimmed)) { + skip = true; + continue; + } + + if (skip) { + if (trimmed.startsWith('###')) { + skip = false; + i--; // Reprocess this heading + } + continue; + } + + cleanedLines.push(line); + } + + let finalBody = cleanedLines.join('\n').trim(); + + if (lastGood) { + finalBody += `\n\n---\nā„¹ļø **Last known working version:** \`${lastGood}\``; + } + + await github.rest.issues.update({ + owner, + repo, + issue_number: issueNumber, + body: finalBody + }); + env: + FORM_JSON: ${{ steps.bug-parser.outputs.jsonString }} + + - name: Get latest Selenium version + id: get-version + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { data: latestRelease } = await github.rest.repos.getLatestRelease({ + owner: 'SeleniumHQ', + repo: 'selenium' + }); + + const latestTag = latestRelease.tag_name; + const versionMatch = latestTag.match(/[vV]?(?:selenium-)?(\d+\.\d+(?:\.\d+)?)/); + + if (!versionMatch) { + core.setFailed(`Couldn't parse version from tag: ${latestTag}`); + return; + } + + const fullVersion = versionMatch[1]; + const [major, minor] = fullVersion.split('.'); + const latestVersion = `${major}.${minor}`; + + console.log(`Latest version: ${latestVersion}`); + core.setOutput('version', latestVersion); + + - name: Compare user version + id: version-check + uses: actions/github-script@v6 + with: + script: | + const form = JSON.parse(process.env.FORM_JSON || '{}'); + const userVersion = form?.["selenium-version"]?.trim() || ""; + const latest = process.env.LATEST_VERSION; + + const [umaj, umin] = userVersion.split('.').map(n => parseInt(n, 10)); + const [lmaj, lmin] = latest.split('.').map(n => parseInt(n, 10)); + + const isOutdated = umaj < lmaj || (umaj === lmaj && umin < lmin); + + core.setOutput("user-version", userVersion); + core.setOutput("latest-version", latest); + core.setOutput("is-outdated", isOutdated); + env: + FORM_JSON: ${{ steps.bug-parser.outputs.jsonString }} + LATEST_VERSION: ${{ steps.get-version.outputs.version }} + + - name: Comment if version is outdated + id: comment-version + if: steps.version-check.outputs.is-outdated == 'true' + uses: peter-evans/create-or-update-comment@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + issue-number: ${{ github.event.issue.number }} + body: | + āš ļø You reported using Selenium version `${{ steps.version-check.outputs.user-version }}`, but the latest release is `${{ steps.version-check.outputs.latest-version }}`. + + Please verify that this issue still occurs with the latest version. If it no longer applies, you can close this issue or update your comment. + + *This issue will be marked "awaiting answer" and may be closed automatically if no response is received.* + + - name: Add label + if: steps.version-check.outputs.is-outdated == 'true' + uses: actions-ecosystem/action-add-labels@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + labels: J-awaiting answer + - name: Remove label + if: steps.version-check.outputs.is-outdated == 'true' + uses: actions-ecosystem/action-remove-labels@v1 + with: + labels: A-needs-triaging diff --git a/.github/workflows/label-commenter.yml b/.github/workflows/label-commenter.yml index fddc487a797ef..6704de20c7fdf 100644 --- a/.github/workflows/label-commenter.yml +++ b/.github/workflows/label-commenter.yml @@ -1,9 +1,11 @@ -# Configuration for Label Commenter - https://github.com/peaceiris/actions-label-commenter +# Configuration for Label Commenter - ./.github/label-commenter-config.yml name: Label Commenter on: issues: types: [ labeled ] + pull_request_target: + types: [labeled] permissions: contents: read @@ -12,8 +14,15 @@ permissions: jobs: comment: if: github.repository_owner == 'seleniumhq' - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - name: Checkout base repo to get config file + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.base.ref }} + repository: seleniumhq/selenium - name: Label Commenter uses: peaceiris/actions-label-commenter@v1 + with: + github_token: ${{ secrets.SELENIUM_CI_TOKEN }} + config_file: .github/label-commenter-config.yml diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index eeea269c87f62..89de2e2fe06d7 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -21,10 +21,16 @@ on: - grid - dotnet - javascript + workflow_call: + inputs: + language: + required: false + type: string + default: "all" jobs: ruby: - if: (github.repository_owner == 'seleniumhq') && (inputs.language == 'ruby' || github.event_name == 'schedule') + if: (github.repository_owner == 'seleniumhq') && (inputs.language == 'ruby' || inputs.language == 'all' || github.event_name == 'schedule') name: Ruby uses: ./.github/workflows/bazel.yml strategy: @@ -57,7 +63,7 @@ jobs: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} python: - if: (github.repository_owner == 'seleniumhq') && (inputs.language == 'python' || github.event_name == 'schedule') + if: (github.repository_owner == 'seleniumhq') && (inputs.language == 'python' || inputs.language == 'all' || github.event_name == 'schedule') name: Python uses: ./.github/workflows/bazel.yml with: @@ -84,7 +90,7 @@ jobs: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} java: - if: (github.repository_owner == 'seleniumhq') && (inputs.language == 'java' || github.event_name == 'schedule') + if: (github.repository_owner == 'seleniumhq') && (inputs.language == 'java' || inputs.language == 'all' || github.event_name == 'schedule') name: Java uses: ./.github/workflows/bazel.yml with: @@ -111,7 +117,7 @@ jobs: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} dotnet: - if: (github.repository_owner == 'seleniumhq') && (inputs.language == 'dotnet' || github.event_name == 'schedule') + if: (github.repository_owner == 'seleniumhq') && (inputs.language == 'dotnet' || inputs.language == 'all' || github.event_name == 'schedule') name: DotNet uses: ./.github/workflows/bazel.yml with: @@ -139,7 +145,7 @@ jobs: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} grid: - if: (github.repository_owner == 'seleniumhq') && (inputs.language == 'grid' || github.event_name == 'schedule') + if: (github.repository_owner == 'seleniumhq') && (inputs.language == 'grid' || inputs.language == 'all' || github.event_name == 'schedule') name: Grid uses: ./.github/workflows/bazel.yml with: @@ -166,16 +172,16 @@ jobs: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} javascript: - if: (github.repository_owner == 'seleniumhq') && (inputs.language == 'javascript' || github.event_name == 'schedule') + if: (github.repository_owner == 'seleniumhq') && (inputs.language == 'javascript' || inputs.language == 'all' || github.event_name == 'schedule') name: JavaScript uses: ./.github/workflows/bazel.yml with: name: Nightly JavaScript Release cache-key: javascript-nightly - node-version: '18.x' + node-version: '22.x' run: | - sed -i 's|https://registry.npmjs.org/|https://npm.pkg.github.com|g' javascript/node/selenium-webdriver/package.json - sed -i 's|"name": "selenium-webdriver"|"name": "@seleniumhq/selenium-webdriver"|g' javascript/node/selenium-webdriver/package.json + sed -i 's|https://registry.npmjs.org/|https://npm.pkg.github.com|g' javascript/selenium-webdriver/package.json + sed -i 's|"name": "selenium-webdriver"|"name": "@seleniumhq/selenium-webdriver"|g' javascript/selenium-webdriver/package.json echo "//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}" >> ~/.npmrc echo "@seleniumhq:registry=https://npm.pkg.github.com" >> ~/.npmrc echo "always-auth=true" >> ~/.npmrc diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml new file mode 100644 index 0000000000000..467b28756dfb7 --- /dev/null +++ b/.github/workflows/pr-labeler.yml @@ -0,0 +1,25 @@ +# Configuration for Label Generation - ./.github/pr-labeler-config.yml +name: Label pull requests based on file paths + +on: + pull_request_target: + types: [opened] + +permissions: + contents: read + pull-requests: write + +jobs: + label: + runs-on: ubuntu-latest + steps: + - name: Checkout base repo to get config file + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.base.ref }} + repository: seleniumhq/selenium + - name: Auto label Pull Requests + uses: actions/labeler@v5 + with: + repo-token: ${{ secrets.SELENIUM_CI_TOKEN }} + configuration-path: .github/pr-labeler-config.yml diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index fb2d19a97a272..4417a12d9a839 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -25,24 +25,23 @@ jobs: with: persist-credentials: false fetch-depth: 0 - fetch-tags: true - name: "Prep git" run: | git config --local user.email "selenium-ci@users.noreply.github.com" git config --local user.name "Selenium CI Bot" - if git rev-parse --verify release-${{ github.event.inputs.version }} >/dev/null 2>&1; then - git branch -D release-${{ github.event.inputs.version }} + if git rev-parse --verify rust-release-${{ github.event.inputs.version }} >/dev/null 2>&1; then + git branch -D rust-release-${{ github.event.inputs.version }} fi - git checkout -b release-${{ github.event.inputs.version }} + git checkout -b rust-release-${{ github.event.inputs.version }} - name: Update Rust Version - run: | - ./go rust:version[${{ github.event.inputs.version }}] - ./go rust:version:commit + run: ./go rust:version ${{ github.event.inputs.version }} + - name: Commit Rust updates + run: git commit -m "update selenium manager version and rust changelog" - name: Push changes uses: ad-m/github-push-action@master with: github_token: ${{ secrets.SELENIUM_CI_TOKEN }} - branch: release-${{ github.event.inputs.version }} + branch: rust-release-${{ github.event.inputs.version }} force: true selenium-manager: @@ -51,10 +50,23 @@ jobs: uses: ./.github/workflows/ci-rust.yml with: release: true - branch: release-${{ github.event.inputs.version }} + branch: rust-release-${{ github.event.inputs.version }} secrets: SELENIUM_CI_TOKEN: ${{ secrets.SELENIUM_CI_TOKEN }} + cleanup-rust-branch: + name: Cleanup Rust Branch + needs: selenium-manager + runs-on: ubuntu-latest + steps: + - name: "Checkout repo" + uses: actions/checkout@v4 + with: + token: ${{ secrets.SELENIUM_CI_TOKEN }} + - name: "Delete rust release branch" + run: | + git push origin --delete rust-release-${{ github.event.inputs.version }} + update-files: name: Update Files runs-on: ubuntu-latest @@ -66,24 +78,50 @@ jobs: persist-credentials: false fetch-depth: 0 fetch-tags: true - ref: release-${{ github.event.inputs.version }} + ref: trunk - name: Install Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: '3.1' + ruby-version: '3.2' working-directory: 'rb' + - name: Setup curl for Ubuntu + run: sudo apt-get update && sudo apt-get install -y libcurl4-openssl-dev - name: "Prep git" run: | git config --local user.email "selenium-ci@users.noreply.github.com" git config --local user.name "Selenium CI Bot" - - name: Undo rust changelog commit - run: git reset HEAD~1 - - name: Update everything including early release CDP - if: ${{ github.event.inputs.chrome_channel == 'early-stable' }} - run: ./go all:prepare[${{ github.event.inputs.version }},Beta] - - name: Update everything including released CDP - if: ${{ github.event.inputs.chrome_channel == 'stable' }} - run: ./go "all:prepare[${{ github.event.inputs.version }},Stable]" + - name: Update browser versions + run: ./go update_browsers ${{ github.event.inputs.chrome_channel }} + - name: Commit browser updates + run: git commit -m "update pinned browser versions" || true + - name: Update devtools versions + run: ./go all:update_cdp ${{ github.event.inputs.chrome_channel }} + - name: Commit DevTools updates + run: git commit -m "update devtools versions" + - name: Update Selenium Manager versions + run: ./go update_manager + - name: Commit Selenium Manager updates + run: git commit -m "update selenium manager versions" + - name: Update Maven dependency versions + run: ./go java:update + - name: Commit Maven version updates + run: git commit -m "update maven dependency versions" + - name: Update Authors file + run: ./go authors + - name: Commit Authors updates + run: git commit -m "update authors file" + - name: Bump minor version + run: ./go all:version ${{ github.event.inputs.version }} + - name: Commit version updates + run: git commit -m "bump versions in preparation for release" + - name: Update changelog + run: ./go all:changelogs + - name: Commit changelog updates + run: git commit -m "WIP - rough auto-update of changelog, please edit" + - name: List untracked files + run: git status -u + - name: Clean working directory before PR + run: git clean -fd - name: Create Pull Request uses: peter-evans/create-pull-request@v6 with: @@ -97,7 +135,6 @@ jobs: **Warning: Manually update the changelogs before merging** This PR: - * Updates Rust version for Selenium Manager release * Updates Pinned browser version to coincide with new CDP release * Adds support for new CDP version and removes old CDP version * Selenium Manager references the new Selenium Manager release @@ -105,9 +142,12 @@ jobs: * Adds new authors to authors file * Updates all versions for all bindings * Generates *rough* change logs for each bindings (please tidy them up before merging this) + * Not all commits need to be in the change log — users do not need to see anything about building or testing Selenium + * Remove references to updating versions including nightly + * The code now outputs the complete body of the commit message; make sure the changelog message is complete and correct - - Auto-generated by [create-pull-request][1] + - This PR was auto-generated by workflow run: [release-preparation][1] - [1]: https://github.com/peter-evans/create-pull-request + [1]: https://github.com/SeleniumHQ/selenium/actions/runs/${{ github.run_id }} labels: C-build draft: true diff --git a/.github/workflows/stage-release.yml b/.github/workflows/stage-release.yml index 5f4eccb69d477..ec787db2e8fc3 100644 --- a/.github/workflows/stage-release.yml +++ b/.github/workflows/stage-release.yml @@ -2,7 +2,12 @@ name: Release Staging on: pull_request: - types: [closed] + types: [ closed ] + workflow_dispatch: + inputs: + version: + description: 'Selenium version to release' + required: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -10,56 +15,69 @@ env: jobs: github-release: if: > - github.event.pull_request.merged == true && + (github.event.pull_request.merged == true && github.repository_owner == 'seleniumhq' && - startsWith(github.event.pull_request.head.ref, 'release-preparation-') + startsWith(github.event.pull_request.head.ref, 'release-preparation-')) || + (github.event_name == 'workflow_dispatch' && + github.event.inputs.version != '' && + github.repository_owner == 'seleniumhq') runs-on: ubuntu-latest + permissions: write-all + outputs: + version: ${{ env.VERSION }} steps: - name: Checkout repo uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Extract version from branch name - id: extract_version + if: github.event.pull_request.merged == true + run: | + TEMP_BRANCH_NAME=${{ github.event.pull_request.head.ref }} + VERSION=$(echo $TEMP_BRANCH_NAME | grep -oE '[0-9]+\.[0-9]+\.[0-9]+') + echo "VERSION=$VERSION" >> $GITHUB_ENV + - name: Extract version from workflow input + if: github.event_name == 'workflow_dispatch' run: | - BRANCH_NAME="${{ github.event.pull_request.head.ref }}" - VERSION=$(echo $BRANCH_NAME | grep -oE '[0-9]+\.[0-9]+\.[0-9]+') + VERSION=${{ inputs.version }} echo "VERSION=$VERSION" >> $GITHUB_ENV - name: Prep git run: | git config --local user.email "selenium-ci@users.noreply.github.com" git config --local user.name "Selenium CI Bot" - - name: Tag Release - run: | - git tag selenium-${{ env.VERSION }} - git push origin selenium-${{ env.VERSION }} - - name: Update Nightly Tag to Remove pre-release - run: | - git fetch --tags - git tag -d nightly || echo "Nightly tag not found" - git tag nightly - git push origin refs/tags/nightly --force - name: Setup Java uses: actions/setup-java@v3 with: java-version: 17 distribution: 'temurin' + - name: Setup curl for Ubuntu + run: sudo apt-get update && sudo apt-get install -y libcurl4-openssl-dev + - name: Delete nightly tag + run: | + if git rev-parse --verify refs/tags/nightly >/dev/null 2>&1; then + echo "Deleting nightly tag" + git push origin --delete refs/tags/nightly + else + echo "No nightly tag found - nothing to delete" + fi - name: Build and Stage Packages run: ./go all:package[--config=release] - name: Generate Draft Release - uses: softprops/action-gh-release@v2 + uses: ncipollo/release-action@v1 with: - name: Selenium ${{ env.VERSION }} - body: | - ## Detailed Changelogs by Component - **[Java](https://github.com/SeleniumHQ/selenium/blob/trunk/java/CHANGELOG)**     |     **[Python](https://github.com/SeleniumHQ/selenium/blob/trunk/py/CHANGES)**     |     **[DotNet](https://github.com/SeleniumHQ/selenium/blob/trunk/dotnet/CHANGELOG)**     |     **[Ruby](https://github.com/SeleniumHQ/selenium/blob/trunk/rb/CHANGES)**     |     **[JavaScript](https://github.com/SeleniumHQ/selenium/blob/trunk/javascript/node/selenium-webdriver/CHANGES.md)**     |     **[IEDriver](https://github.com/SeleniumHQ/selenium/blob/trunk/cpp/iedriverserver/CHANGELOG)** -
- tag_name: selenium-${{ env.VERSION }} + artifacts: "build/dist/*.*" + bodyFile: "scripts/github-actions/release_header.md" draft: true - generate_release_notes: true + generateReleaseNotes: true + name: "Selenium ${{ env.VERSION }}" prerelease: false - files: build/dist/*.* + skipIfReleaseExists: true + tag: "selenium-${{ env.VERSION }}" + commit: "${{ github.sha }}" update-documentation: needs: github-release uses: ./.github/workflows/update-documentation.yml with: - tag: selenium-${{ needs.github-release.outputs.version }} + version: ${{ needs.github-release.outputs.version }} + sha: ${{ github.sha }} diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 987c0e6d171b8..0f888d9584b3f 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -18,16 +18,31 @@ jobs: steps: - uses: actions/stale@v9 with: - stale-issue-message: 'This issue is stale because it has been open 280 days with no activity. Remove stale label or comment or this will be closed in 14 days.' + stale-issue-message: 'This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 14 days.' close-issue-message: 'This issue was closed because it has been stalled for 14 days with no activity.' - stale-issue-label: 'I-stale' - days-before-stale: 280 + stale-issue-label: 'J-stale' + stale-pr-label: 'J-stale' + days-before-stale: 180 days-before-close: 14 + exempt-all-milestones: true - uses: actions/stale@v9 with: close-issue-message: 'This issue was closed because we did not receive any additional information after 14 days.' - stale-issue-label: 'R-awaiting answer' + stale-issue-label: 'J-awaiting answer' days-before-stale: -1 days-before-close: 14 - labels-to-add-when-unstale: 'needs-triaging' - + labels-to-add-when-unstale: 'A-needs-triaging' + - uses: actions/stale@v9 + with: + close-issue-message: 'This issue was closed because we did not receive any additional information after 14 days.' + stale-issue-label: 'J-logging' + days-before-stale: -1 + days-before-close: 14 + labels-to-add-when-unstale: 'A-needs-triaging' + - uses: actions/stale@v9 + with: + close-issue-message: 'This issue was closed because we did not receive any additional information after 14 days.' + stale-issue-label: 'J-issue-template' + days-before-stale: -1 + days-before-close: 14 + labels-to-add-when-unstale: 'A-needs-triaging' diff --git a/.github/workflows/update-docs-after-action.yml b/.github/workflows/update-docs-after-action.yml new file mode 100644 index 0000000000000..f839e37eb16e2 --- /dev/null +++ b/.github/workflows/update-docs-after-action.yml @@ -0,0 +1,30 @@ +name: Update Version After Docs Merge + +on: + pull_request: + types: [ closed ] + branches: + - gh-pages + paths: + - 'docs/api/**' + +jobs: + parse-pr-title: + runs-on: ubuntu-latest + if: github.event.pull_request.merged == true && contains(github.event.pull_request.title, 'Update documentation for Selenium') + outputs: + language: ${{ steps.extract-language.outputs.language }} + steps: + - name: Extract language from PR title + id: extract-language + run: | + PR_TITLE="${{ github.event.pull_request.title }}" + LANGUAGE=$(echo "$PR_TITLE" | grep -o '[^-]*$') + echo "language=$LANGUAGE" >> $GITHUB_OUTPUT + update-version: + needs: parse-pr-title + uses: ./.github/workflows/nightly.yml + with: + language: ${{ needs.parse-pr-title.outputs.language }} + secrets: inherit + diff --git a/.github/workflows/update-documentation.yml b/.github/workflows/update-documentation.yml index 7e2e5efee541f..fb8d579ea891f 100644 --- a/.github/workflows/update-documentation.yml +++ b/.github/workflows/update-documentation.yml @@ -3,252 +3,99 @@ name: Update Documentation on: workflow_dispatch: inputs: - tag: - description: Release tag (e.g. selenium-4.21.0) + version: + description: Release version (e.g., 4.21.0) required: true type: string + language: + description: language documentation + required: true + type: choice + default: "all" + options: + - java + - rb + - py + - dotnet + - node + - all workflow_call: inputs: - tag: + version: + required: true + type: string + sha: required: true type: string + language: + required: false + type: string + default: "all" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} jobs: - determine-language: - runs-on: ubuntu-latest - outputs: - language: ${{ steps.get-language.outputs.language }} - steps: - - name: Parse language from tag - id: get-language - run: | - tag=${{ inputs.tag }} - language=$(echo $tag | awk -F'-' '{print $NF}') - if [[ ! "$language" =~ ^(java|ruby|python|dotnet|node)$ ]]; then - language="all" - fi - echo "language=$language" > $GITHUB_OUTPUT - - java-docs: - runs-on: ubuntu-latest - needs: determine-language - steps: - - name: Checkout the tag - uses: actions/checkout@v4 - with: - ref: ${{ inputs.tag }} - - name: Prep git - run: | - git config --local user.email "selenium-ci@users.noreply.github.com" - git config --local user.name "Selenium CI Bot" - - name: Setup Java - uses: actions/setup-java@v3 - with: - java-version: 17 - distribution: 'temurin' - - name: Update Documentation - if: needs.determine-language.outputs.language == 'all' || needs.determine-language.outputs.language == 'java' - run: ./go java:docs - - name: Create patch for changes - run: | - git format-patch -1 HEAD --stdout > java-docs.patch - - name: Upload patch - if: needs.determine-language.outputs.language == 'all' || needs.determine-language.outputs.language == 'java' - uses: actions/upload-artifact@v2 - with: - name: java-docs-patch - path: java-docs.patch - - ruby-docs: + build-docs: runs-on: ubuntu-latest - needs: determine-language steps: - - name: Checkout the tag + - name: Checkout repository uses: actions/checkout@v4 with: - ref: ${{ inputs.tag }} - - name: Prep git + ref: ${{ github.event_name == 'workflow_dispatch' && github.ref || inputs.sha }} + - name: Fetch gh-pages branch + run: git fetch origin gh-pages + - name: Setup git run: | git config --local user.email "selenium-ci@users.noreply.github.com" git config --local user.name "Selenium CI Bot" + - name: Setup curl for Ubuntu + run: sudo apt-get update && sudo apt-get install -y libcurl4-openssl-dev - name: Setup Java - uses: actions/setup-java@v3 + if: ${{ inputs.language == 'java' || inputs.language == 'all' }} + uses: actions/setup-java@v4 with: java-version: 17 distribution: 'temurin' - - name: Update Documentation - if: needs.determine-language.outputs.language == 'all' || needs.determine-language.outputs.language == 'ruby' - run: ./go rb:docs - - name: Create patch for changes - run: | - git format-patch -1 HEAD --stdout > ruby-docs.patch - - name: Upload patch - if: needs.determine-language.outputs.language == 'all' || needs.determine-language.outputs.language == 'ruby' - uses: actions/upload-artifact@v2 - with: - name: ruby-docs-patch - path: ruby-docs.patch - - python-docs: - needs: determine-language - runs-on: ubuntu-latest - steps: - - name: Checkout the tag - uses: actions/checkout@v4 - with: - ref: ${{ inputs.tag }} - - name: Prep git - run: | - git config --local user.email "selenium-ci@users.noreply.github.com" - git config --local user.name "Selenium CI Bot" - - name: Set up Python 3.8 - uses: actions/setup-python@v4 + - name: Set up Python 3.9 + if: ${{ inputs.language == 'py' || inputs.language == 'all' }} + uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: 3.9 - name: Install dependencies + if: ${{ inputs.language == 'py' || inputs.language == 'all' }} run: | python -m pip install --upgrade pip pip install tox - - name: Update Documentation - if: needs.determine-language.outputs.language == 'all' || needs.determine-language.outputs.language == 'python' - run: ./go py:docs - - name: Create patch for changes - run: | - git format-patch -1 HEAD --stdout > python-docs.patch - - name: Upload patch - if: needs.determine-language.outputs.language == 'all' || needs.determine-language.outputs.language == 'python' - uses: actions/upload-artifact@v2 - with: - name: python-docs-patch - path: python-docs.patch - - dotnet-docs: - needs: determine-language - runs-on: ubuntu-latest - steps: - - name: Checkout the tag - uses: actions/checkout@v4 - with: - ref: ${{ inputs.tag }} - - name: Prep git - run: | - git config --local user.email "selenium-ci@users.noreply.github.com" - git config --local user.name "Selenium CI Bot" - - name: Install specific version of DocFX tool - # Pinning to 2.75.3 to avoid breaking changes in newer versions - # See https://github.com/dotnet/docfx/issues/9855 - run: dotnet tool install --global --version 2.75.3 docfx - - name: Update Documentation - if: needs.determine-language.outputs.language == 'all' || needs.determine-language.outputs.language == 'dotnet' - run: ./go dotnet:docs - - name: Create patch for changes - run: | - git format-patch -1 HEAD --stdout > dotnet-docs.patch - - name: Upload patch - if: needs.determine-language.outputs.language == 'all' || needs.determine-language.outputs.language == 'dotnet' - uses: actions/upload-artifact@v2 - with: - name: dotnet-docs-patch - path: dotnet-docs.patch - - node-docs: - needs: determine-language - runs-on: ubuntu-latest - steps: - - name: Checkout the tag - uses: actions/checkout@v4 - with: - ref: ${{ inputs.tag }} - - name: Prep git - run: | - git config --local user.email "selenium-ci@users.noreply.github.com" - git config --local user.name "Selenium CI Bot" - name: Install npm dependencies + if: ${{ inputs.language == 'node' || inputs.language == 'all' }} run: | npm install - npm install --prefix javascript/node/selenium-webdriver - - name: Update Documentation - if: needs.determine-language.outputs.language == 'all' || needs.determine-language.outputs.language == 'node' - run: ./go node:docs - - name: Create patch for changes - run: | - git format-patch -1 HEAD --stdout > node-docs.patch - - name: Upload patch - if: needs.determine-language.outputs.language == 'all' || needs.determine-language.outputs.language == 'node' - uses: actions/upload-artifact@v2 - with: - name: node-docs-patch - path: node-docs.patch - - merge-patches: - runs-on: ubuntu-latest - needs: [java-docs, ruby-docs, python-docs, dotnet-docs, node-docs] - steps: - - name: Checkout documentation branch - uses: actions/checkout@v4 - with: - ref: 'gh-pages' - - name: Create and checkout new branch - run: | - git config --local user.email "selenium-ci@users.noreply.github.com" - git config --local user.name "Selenium CI Bot" - git checkout -b api-docs-${{ inputs.tag }} - - name: Download Java patch - if: needs.determine-language.outputs.language == 'all' || needs.determine-language.outputs.language == 'java' - uses: actions/download-artifact@v2 - with: - name: java-docs-patch - path: patches/ - - name: Download Ruby patch - if: needs.determine-language.outputs.language == 'all' || needs.determine-language.outputs.language == 'ruby' - uses: actions/download-artifact@v2 - with: - name: ruby-docs-patch - path: patches/ - - name: Download Python patch - if: needs.determine-language.outputs.language == 'all' || needs.determine-language.outputs.language == 'python' - uses: actions/download-artifact@v2 - with: - name: python-docs-patch - path: patches/ - - name: Download .NET patch - if: needs.determine-language.outputs.language == 'all' || needs.determine-language.outputs.language == 'dotnet' - uses: actions/download-artifact@v2 - with: - name: dotnet-docs-patch - path: patches/ - - name: Download Node patch - if: needs.determine-language.outputs.language == 'all' || needs.determine-language.outputs.language == 'node' - uses: actions/download-artifact@v2 - with: - name: node-docs-patch - path: patches/ - - name: Apply patches - run: | - for patch in patches/*.patch; do - git am < "$patch" - done - - name: Push Branch - run: git push origin api-docs-${{ inputs.tag }} + npm install --prefix javascript/selenium-webdriver + - name: Generate Documentation for selected langauges + run: ./go ${{ inputs.language }}:docs - name: Documentation Pull Request + id: cpr uses: peter-evans/create-pull-request@v6 with: token: ${{ secrets.SELENIUM_CI_TOKEN }} author: Selenium CI Bot delete-branch: true - branch: api-docs-${{ inputs.tag }} + branch: api-docs-${{ inputs.version }} base: gh-pages - title: Update documentation for ${{ inputs.tag }} + add-paths: docs/api/** + title: Update documentation for Selenium ${{ inputs.version }}-${{ inputs.language }} body: | - This PR updates the API documentation for all bindings - based on the provided tag name. - - - Auto-generated by [create-pull-request][1] + This PR updates the API documentation for version **${{ inputs.version }}-${{ inputs.language }}**. - [1]: https://github.com/peter-evans/create-pull-request - labels: documentation + - Auto-generated by [workflow run #${{ github.run_id }}](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) + labels: B-docs draft: false + - name: Enable Pull Request Auto-merge + if: steps.cpr.outputs.pull-request-operation == 'created' + uses: peter-evans/enable-pull-request-automerge@v3 + with: + token: ${{ secrets.SELENIUM_CI_TOKEN }} + pull-request-number: ${{ steps.cpr.outputs.pull-request-number }} + merge-method: squash diff --git a/.gitignore b/.gitignore index 259551ffd4482..246f2c4bdaf7d 100644 --- a/.gitignore +++ b/.gitignore @@ -19,11 +19,11 @@ dotnet/packages/ java/client/src/org/openqa/selenium/ie/IeReturnTypes.java java/server/test/org/openqa/selenium/example javascript/deps.js -javascript/node/selenium-webdriver/node_modules/ -javascript/node/selenium-webdriver/lib/atoms/find-elements.js -javascript/node/selenium-webdriver/lib/atoms/get-attribute.js -javascript/node/selenium-webdriver/lib/atoms/is-displayed.js -javascript/node/selenium-webdriver/lib/atoms/mutation-listener.js +javascript/selenium-webdriver/node_modules/ +javascript/selenium-webdriver/lib/atoms/find-elements.js +javascript/selenium-webdriver/lib/atoms/get-attribute.js +javascript/selenium-webdriver/lib/atoms/is-displayed.js +javascript/selenium-webdriver/lib/atoms/mutation-listener.js javascript/safari-driver/node_modules/ javascript/webdriver/devtools/types/ .idea/vcs.xml @@ -75,9 +75,11 @@ py/selenium/webdriver/remote/getAttribute.js py/selenium/webdriver/remote/isDisplayed.js py/docs/build/ py/docs/source/**/* +!py/docs/source/conf.py +!py/docs/source/*.rst py/build/ -py/LICENSE py/pytestdebug.log +py/python.iml selenium.egg-info/ third_party/java/jetty/jetty-repacked.jar *.user @@ -136,7 +138,8 @@ MODULE.bazel.lock # Engflow *.crt *.key -javascript/node/selenium-webdriver/.vscode/settings.json +javascript/selenium-webdriver/.vscode/settings.json dotnet-bin .metadata/ +.npmrc diff --git a/.mailmap b/.mailmap index 92e57a7c9fb60..ebcf4b058538b 100644 --- a/.mailmap +++ b/.mailmap @@ -16,6 +16,7 @@ Brandon Walderman Brian Burg Chethana Paniyadi Craig Nishina +Corey Goldberg <1113081+cgoldberg@users.noreply.github.com> Dan Fabulich Daniel P. PurkhĆŗs diff --git a/.pr_agent.toml b/.pr_agent.toml new file mode 100644 index 0000000000000..0a9a3e330fbfc --- /dev/null +++ b/.pr_agent.toml @@ -0,0 +1,78 @@ +# Used by qodo-merge-pro bot + +[config] +enable_labeler = true +enable_custom_labels=true +labels_mode = "custom_only" + +[custom_labels."B-atoms"] +description = "Related to one or more of the JavaScript atoms Selenium compiles and uses" + +[custom_labels."B-build"] +description = "Related to any build script execution, bazel implementation or CI integrations" + +[custom_labels."B-devtools"] +description = "Related to anything BiDi or Chrome DevTools" + +[custom_labels."B-docs"] +description = "Related to API documentation such as Javadoc or code-level docs. Not for website updates, examples, or general comments." + +[custom_labels."B-grid"] +description = "Everything grid, server related, possibly including remote webdriver execution" + +[custom_labels."B-manager"] +description = "Focused on something related to Selenium Manager and Driver Finding, whether in Rust or in the bindings" + +[custom_labels."D-chrome"] +description = "Specific to Chrome" + +[custom_labels."D-firefox"] +description = "Specific to Firefox" + +[custom_labels."D-safari"] +description = "Specific to Safari" + +[custom_labels."D-IE"] +description = "Specific to Internet Explorer" + +[custom_labels."D-edge"] +description = "Specific to Microsoft Edge" + +[custom_labels."E-easy"] +description = "An easy PR to review" + +[custom_labels."E-less easy"] +description = "A somewhat difficult PR to review" + +[custom_labels."E-hard"] +description = "A hard or complex PR to review" + +[custom_labels."I-cleanup"] +description = "Internal tidy-up only, not user-facing. Applies to typo fixes, syntax tweaks, comment formatting, or dead code removal. Should not be used for bug fixes or behavior changes." + +[custom_labels."I-regression"] +description = "Fixes something that used to work and no longer does" + +[custom_labels."I-performance"] +description = "Improves performance" + +[custom_labels."I-security"] +description = "Addresses a security vulnerability" + +[custom_labels."OS-linux"] +description = "Specific to Linux" + +[custom_labels."OS-mac"] +description = "Specific to macOS" + +[custom_labels."OS-windows"] +description = "Specific to Windows" + +[custom_labels."P-bug fix"] +description = "Addresses a known issue in a backwards compatible way" + +[custom_labels."P-enhancement"] +description = "Creates a new feature in a backwards compatible way" + +[custom_labels."P-breaking change"] +description = "Introduces a non-backwards compatible change (a fix or feature that would cause existing functionality to change)" diff --git a/.readthedocs.yaml b/.readthedocs.yaml deleted file mode 100644 index ea69ba8052a4a..0000000000000 --- a/.readthedocs.yaml +++ /dev/null @@ -1,32 +0,0 @@ -# .readthedocs.yaml -# Read the Docs configuration file -# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details - -# Required -version: 2 - -# Set the OS, Python version and other tools you might need -build: - os: ubuntu-22.04 - tools: - python: "3.11" - # You can also specify other tool versions: - # nodejs: "19" - # rust: "1.64" - # golang: "1.19" - -# Build documentation in the "docs/" directory with Sphinx -sphinx: - configuration: py/docs/source/conf.py - -# Optionally build your docs in additional formats such as PDF and ePub -# formats: -# - pdf -# - epub - -# Optional but recommended, declare the Python requirements required -# to build your documentation -# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html -python: - install: - - requirements: py/docs/requirements.txt diff --git a/.skipped-tests b/.skipped-tests index 16f00c9b99235..88eb59305ca8b 100644 --- a/.skipped-tests +++ b/.skipped-tests @@ -1,10 +1,13 @@ -//dotnet/test/common:NetworkInterceptionTests-chrome -//dotnet/test/common:NetworkInterceptionTests-edge +-//dotnet/test/firefox:FirefoxDriverTest-firefox -//java/test/org/openqa/selenium/chrome:ChromeDriverFunctionalTest -//java/test/org/openqa/selenium/chrome:ChromeDriverFunctionalTest-remote -//java/test/org/openqa/selenium/edge:EdgeDriverFunctionalTest -//java/test/org/openqa/selenium/edge:EdgeDriverFunctionalTest-edge -//java/test/org/openqa/selenium/edge:EdgeDriverFunctionalTest-remote +-//java/test/org/openqa/selenium/devtools:NetworkInterceptorRestTest +-//java/test/org/openqa/selenium/devtools:NetworkInterceptorRestTest-remote -//java/test/org/openqa/selenium/federatedcredentialmanagement:FederatedCredentialManagementTest -//java/test/org/openqa/selenium/firefox:FirefoxDriverBuilderTest -//java/test/org/openqa/selenium/grid/gridui:OverallGridTest @@ -19,17 +22,10 @@ -//javascript/atoms:test-chrome -//javascript/atoms:test-edge -//javascript/atoms:test-firefox-beta --//javascript/node/selenium-webdriver:test-bidi-network-test.js-chrome --//javascript/node/selenium-webdriver:test-builder-test.js-chrome --//javascript/node/selenium-webdriver:test-builder-test.js-firefox --//javascript/node/selenium-webdriver:test-chrome-devtools-test.js-chrome --//javascript/node/selenium-webdriver:test-chrome-options-test.js-chrome --//javascript/node/selenium-webdriver:test-chrome-service-test.js-chrome --//javascript/node/selenium-webdriver:test-firefox-options-test.js-firefox --//javascript/node/selenium-webdriver:test-lib-capabilities-test.js-chrome --//py:test-chrome-test/selenium/webdriver/chrome/chrome_launcher_tests.py --//py:test-chrome-test/selenium/webdriver/chrome/chrome_service_tests.py --//py:test-chrome-test/selenium/webdriver/chrome/proxy_tests.py +-//javascript/chrome-driver/... +-//javascript/selenium-webdriver:test-builder-test.js-chrome +-//javascript/selenium-webdriver:test-chrome-devtools-test.js-chrome +-//javascript/selenium-webdriver:test-firefox-options-test.js-firefox -//rb/spec/integration/selenium/webdriver/chrome:service-chrome -//rb/spec/integration/selenium/webdriver/chrome:service-chrome-bidi -//rb/spec/integration/selenium/webdriver/chrome:service-chrome-remote @@ -51,6 +47,10 @@ -//rb/spec/integration/selenium/webdriver/remote:element-edge-remote -//rb/spec/integration/selenium/webdriver/remote:element-firefox-beta-remote -//rb/spec/integration/selenium/webdriver/remote:element-firefox-remote +-//rb/spec/integration/selenium/webdriver:action_builder-firefox-beta-remote -//rb/spec/integration/selenium/webdriver:element-chrome -//rb/spec/integration/selenium/webdriver:element-chrome-bidi -//rb/spec/integration/selenium/webdriver:element-chrome-remote +-//rb/spec/integration/selenium/webdriver:manager-firefox-beta +-//rb/spec/integration/selenium/webdriver:manager-firefox-beta-remote +-//rb:lint diff --git a/AUTHORS b/AUTHORS index 11a8283f1f12c..c2caea885e760 100644 --- a/AUTHORS +++ b/AUTHORS @@ -11,11 +11,13 @@ abidema <44252090+abidema@users.noreply.github.com> Adam Dangoor Adam Demuri Adam Goucher +Adam Halbrock Adam Smith AdamPDotty <81536237+AdamPDotty@users.noreply.github.com> Adi Roiban adiohana Aditya Pratap Singh +Adolfo Armas Adrian Dymorz Adrian Leonhard Agustin Pequeno <33221555+aguspe@users.noreply.github.com> @@ -34,8 +36,10 @@ albertor24 Aleksei Moskvin Alex <72409387+fergushev@users.noreply.github.com> Alex +Alex B <45384811+AB-xdev@users.noreply.github.com> Alex Eagle Alex Henrie +Alex Popov Alex Rodionov Alex Savchuk Alexander Bayandin @@ -68,9 +72,11 @@ Andrei Andrei Botalov Andrei Rusu Andrei Solntsev +Andrew Nesbitt Andrey Botalov Andrii Rohovets Andy Duncan +Angie Jones anonymous_sdet Anthony Sottile Anton Usmansky @@ -90,21 +96,27 @@ Ashley Trinh Aslak HellesĆøy asmundak Atsushi Tatsuma +Augustin Gottlieb <33221555+aguspe@users.noreply.github.com> Augustin Gottlieb Pequeno <33221555+aguspe@users.noreply.github.com> AurĆ©lien Pupier Austin Michael Wilkins <42476341+amwilkins@users.noreply.github.com> BaerMitUmlaut Baran Ozgul Bartek Florczak +Ben Beasley Ben Congleton Ben Kucera <14625260+Bkucera@users.noreply.github.com> Ben Lamm Ben Sedat +Benjamin Benjamin Forehand Jr +Benoit Pierre bgermann +bgermann bhecquet bhkwan Bill Agee +BlitzDestroyer <143762104+BlitzDestroyer@users.noreply.github.com> bob Bob Baron Bob Lubecker @@ -118,6 +130,7 @@ Boris Osipov Boris Petrov Boris Wrubel bozdemir84 +Bradley Latreille <47356514+Bradltr95@users.noreply.github.com> Branden Cash <203336+ammmze@users.noreply.github.com> Brandon Walderman Brandon Williams @@ -146,11 +159,13 @@ Chirag Jayswal chris Chris Block Chris Gamache +Chris Gossett <54162250+cgossett@users.noreply.github.com> Chris Martin Chris Mohr Chris Stringer Chris Ward Christian Ansel <36796016+ChrstnAnsl@users.noreply.github.com> +Christian Biesinger Christian Biesinger Christian Clauss Christopher Buttkus @@ -164,7 +179,7 @@ clubfest ColinF colons Connor Shea -Corey Goldberg +Corey Goldberg <1113081+cgoldberg@users.noreply.github.com> Corey Schooler Coty Rosenblath Craig Nishina @@ -197,6 +212,7 @@ Darrin Cherry Dave Hoover Dave Hunt daviande +David Bernhard David Burns David English David Fischer @@ -211,6 +227,7 @@ David Wang David Zhu Debanjan Choudhury deedy5 <65482418+deedy5@users.noreply.github.com> +DeflateAwning <11021263+DeflateAwning@users.noreply.github.com> Denis Demchenko Dennis Oelkers dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> @@ -222,12 +239,15 @@ Diego FernĆ”ndez Santos Diego Molina Dima Kovalenko Dima Veselov +Dinesh Kumar R A <37109896+DineshKumarRA@users.noreply.github.com> +Diogo Teles Sant'Anna Dmitriy Sintsov Dmitry Dubenets Dmitry Tokarev Dmytro Shpakovskyi dnknitro doctor-house <66467615+doctor-house@users.noreply.github.com> +Dominic Evans <8060970+dnwe@users.noreply.github.com> Dominik Dary Dominik Rauch Dominik Stadler @@ -255,6 +275,7 @@ elgatov Eli Flanagan Elias Faxƶ Ellis Percival +Emil Hemdal Enrique Daimiel eoff Eran Messeri @@ -267,8 +288,10 @@ Evan Sangaline Evgeniy Roldukhin EwaMarek Fan <1135611487@qq.com> +Federico Franco <81330093+FFederi@users.noreply.github.com> Felipe Knorr Kuhn Fenil Mehta <42742240+fenilgmehta@users.noreply.github.com> +FloKNetcare Florian Apolloner Florian LOPES Florian Mutter <32459530+florianmutter@users.noreply.github.com> @@ -327,6 +350,7 @@ Harshit Agrawal <94462364+harshit-bs@users.noreply.github.com> havja Haw-bin Chai hectorhon +HeeJun <64578367+syber911911@users.noreply.github.com> Heky helen3141 <54561656+helen3141@users.noreply.github.com> Henrik Skupin @@ -349,6 +373,7 @@ Ilyas Bayraktar Immanuel Hayden Indomitable Innokenty Shuvalov +Ioan Giurgiu Isaac A. Murchie Isaul Vargas Ish Abbi @@ -383,6 +408,7 @@ Jari Bakken Jason Jason Anderson Jason Carr +Jason Heflinger Jason Hu Jason Huggins Jason Juang @@ -439,6 +465,7 @@ John J. Barton John Pelly Johnny.H Johnson <20457146+j3soon@users.noreply.github.com> +Jolyon Pawlyn joma74 Jon Dufresne Jon Spalding @@ -451,6 +478,7 @@ Jonathan Lipps Jonathon Kereliuk Jongkuen Hong Jordan Mace +Jose D. Gomez R. <1josegomezr@gmail.com> josephg Josh Goldberg Joshua Bruning @@ -525,6 +553,7 @@ Lucas Diniz Lucas Tierney Luis Correia Luis Pflamminger +Luis Serna Luke Hill Luke Inman-Semerau lukec @@ -537,6 +566,7 @@ Maid <37146904+ParadiseWitch@users.noreply.github.com> Malcolm Rowe MandarJKulkarni <33712629+MandarJKulkarni@users.noreply.github.com> Maneesh MS +Manikanta Reddy <89578665+MRTamalampudi@users.noreply.github.com> Manoj Kumar Manuel Blanco Marc Fisher @@ -587,6 +617,7 @@ Michael Render Michael Tamm Michael Zhou Michal Čihař +Michał Górny Michał Herda Michele Sama MickaĆ«l Schoentgen @@ -607,6 +638,7 @@ ming Mirko Nasato mitchloudenbeck Miten Chauhan +mk868 mkvetko MMK-IBSEN <124664589+MMK-IBSEN@users.noreply.github.com> Mohab Mohie @@ -621,14 +653,19 @@ mpurland mtrea <32470080+mtrea@users.noreply.github.com> Mubariz Hajimuradov Muhammad Hammad <33136628+mhnaeem@users.noreply.github.com> +MustafaAgamy Muthu Kannan MWschutte <72599545+MWschutte@users.noreply.github.com> myslak71 +Natalia Pozhidaeva Nate Lowry Nathan Isom native-api Naveen <172697+naveensrinivasan@users.noreply.github.com> Naveen Singh <36371707+Naveen3Singh@users.noreply.github.com> +Navin Chandra <98466550+navin772@users.noreply.github.com> +Navin Chandra +Navin Chandra Neil Carvalho Nelson Sproul Nick Crews @@ -643,10 +680,12 @@ nir-tal-talkspace <71274151+nir-tal-talkspace@users.noreply.github.com> Nirantak Raghav Nitish Noel Gordon +Noritaka Kobayashi Nowell Strite Nozomi Ito no_author nvonop +nxs7 <69392661+nxs7@users.noreply.github.com> Oboleninov Anton Oleg Hƶfling Oleg Ridchenko <73664101+oleg-rd@users.noreply.github.com> @@ -662,6 +701,7 @@ orangeudav Oscar Devora <100381276+RevealOscar@users.noreply.github.com> Outsider Paladin Wang <49390614+eversoutheast@users.noreply.github.com> +Pallavi Palmer Bandy <37938675+palmermbandy@users.noreply.github.com> Pat Tullmann Patrice Jaton @@ -671,6 +711,7 @@ Patrick Lightbody Paul G Webster Paul Hammant Pavel Lobashov +Pavel Sobolev Perryn Fowler Pete Johns Peter Hedenskog @@ -688,6 +729,7 @@ PombaM Potapov Dmitriy Prakhar Rawat praveendvd <45095911+praveendvd@users.noreply.github.com> +Priyansh Garg Puja Jagani Pulkit Sharma Pydi Chandra @@ -711,13 +753,16 @@ richard.hines RichCrook richseviora Rishav Trivedi +Rob Brackett Rob Richardson Rob Wu Robert Elliot Robert Fletcher Roberto Rivera +Robin <167366979+allrob23@users.noreply.github.com> Robin Stocker Rod McNew +Romain TartiĆØre Roman Yurchak Roman Yurchak Roman Zoller @@ -741,6 +786,7 @@ Sam Uong Samit Badle Samuel BĆ©trisey Sandeep Suryaprasad <26169602+sandeepsuryaprasad@users.noreply.github.com> +Sandro Sankha Narayan Guria Santiago Suarez OrdoƱez Sarah Bird @@ -766,6 +812,7 @@ Seth Lemanek Seva Lotoshnikov Shan Shashank <42868640+snsten@users.noreply.github.com> +Shaurya Bisht <87357655+ShauryaDusht@users.noreply.github.com> Shay Dratler Shengfa <3363396+k7z45@users.noreply.github.com> shin @@ -774,6 +821,7 @@ Shishu Raj Pandey Shreyan Avigyan <74560907+shreyanavigyan@users.noreply.github.com> Shubham Singh <41840111+singh811@users.noreply.github.com> Shuhai Shen +Simon Benzer <69980130+shbenzer@users.noreply.github.com> Simon K Simon Perepelitsa Simon Stewart @@ -799,6 +847,7 @@ Stuart Knightly sufyanAbbasi sugama sunnyyukaige +Swastik Baranwal symonk Take take0x <89313929+take0x@users.noreply.github.com> @@ -827,6 +876,7 @@ Tobias Lidskog Tobias Smolka <37370256+tosmolka@users.noreply.github.com> Toda Hiroshi Toilal +Tom Hughes Tom Longhurst Tom Trumper tomaszn @@ -864,6 +914,7 @@ Vijendarn Selvarajah <11275608+vijay44@users.noreply.github.com> VijendraEAtech <39116868+VijendraEAtech@users.noreply.github.com> Vikas Goel VimalRaj Selvam +Vinaysimha Varma Yadavali Vincent Ladeuil vinoth959 Viren Negi <63040+meetme2meat@users.noreply.github.com> @@ -894,6 +945,7 @@ Zeki Mokhtarzada zhangwenqiang00 Zhuo Peng Ziyu +zodac Zoltar - Knower of All zsong Ɓkos LukĆ”cs diff --git a/BUILD.bazel b/BUILD.bazel index 43f9fae6400da..6a156f8f327bd 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -72,7 +72,7 @@ java_binary( npm_link_package( name = "node_modules/selenium-webdriver", - src = "//javascript/node/selenium-webdriver", + src = "//javascript/selenium-webdriver", ) platform( diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 80b6ecaf11662..3905abcb1d9e9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -62,11 +62,11 @@ on Github. This document will guide you through the contribution process. -### Step 1: Fork +### Step 1: Fork & Clone Fork the project [on Github](https://github.com/seleniumhq/selenium) -and check out your copy locally. Use `--depth 1` for a quick check out. -The repository is ~2GB and checking the whole history takes a while. +and clone the repository locally. Use `--depth 1` for a quick clone. +The repository is over 2GB and cloning the whole history takes a while. ```shell % git clone git@github.com:username/selenium.git --depth 1 @@ -76,7 +76,7 @@ The repository is ~2GB and checking the whole history takes a while. #### Dependencies -We bundle dependencies in the _third-party/_ directory that is not +We bundle dependencies in the _third-party/_ directory that are not part of the proper project. Any changes to files in this directory or its subdirectories should be sent upstream to the respective projects. Please don't send your patch to us as we cannot accept it. @@ -109,7 +109,7 @@ installed on your local machine, or by executing: ```shell # Example of adding a dep to the JS webdriver bindings -cd javascript/node/selenium-webdriver +cd javascript/selenium-webdriver bazel run javascript:pnpm -- install my-amazing-dep --dir $PWD ``` @@ -255,12 +255,12 @@ Build your code for the latest changes and run tests locally. Node Tests ```shell - % bazel test //javascript/node/selenium-webdriver:tests + % bazel test //javascript/selenium-webdriver:all ``` Firefox Atom Tests ```shell - % bazel test --test_tag_filters=firefox //javascript/atoms/... //javascript/selenium-atoms/... //javascript/webdriver/... + % bazel test --test_tag_filters=firefox //javascript/atoms/... //javascript/webdriver/... ``` Grid UI Unit Tests @@ -350,7 +350,7 @@ Issues are labelled to make them easier to categorise and find by: ## Communication Selenium contributors frequent the `#selenium` channel on -[`irc.freenode.org`](https://webchat.freenode.net/). You can also join +[`libera.chat`](https://web.libera.chat/). You can also join the [`selenium-developers@` mailing list](https://groups.google.com/forum/#!forum/selenium-developers). Check https://selenium.dev/support/ for a complete list of options to communicate. @@ -358,8 +358,8 @@ Check https://selenium.dev/support/ for a complete list of options to communicat To access the EngFlow RBE, a developer needs to be granted access to our project container repository. Once that has been done, then any bazel command can be run -remotely by using `--config=remote`. For example: `bazel build --config=remote -grid` or `bazel test --config=remote java/test/...` +remotely by using `--config=rbe`. For example: `bazel build --config=rbe +grid` or `bazel test --config=rbe java/test/...` When you run a remote build, one of the first lines of output from Bazel will include a link to the EngFlow UI so you can track the progress of the build and diff --git a/LICENSE b/LICENSE index 2cb588d8c7a84..75b9810f863a5 100644 --- a/LICENSE +++ b/LICENSE @@ -187,7 +187,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2024 Software Freedom Conservancy (SFC) + Copyright 2025 Software Freedom Conservancy (SFC) Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/MODULE.bazel b/MODULE.bazel index bde71eecb9491..f73c55bc41d7b 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -1,31 +1,45 @@ module(name = "selenium") -bazel_dep(name = "apple_rules_lint", version = "0.3.2") -bazel_dep(name = "aspect_bazel_lib", version = "2.7.7") -bazel_dep(name = "aspect_rules_esbuild", version = "0.20.1") -bazel_dep(name = "aspect_rules_js", version = "1.42.3") -bazel_dep(name = "aspect_rules_ts", version = "2.4.2") -bazel_dep(name = "bazel_features", version = "1.13.0") +bazel_dep(name = "apple_rules_lint", version = "0.4.0") +bazel_dep(name = "aspect_bazel_lib", version = "2.13.0") +bazel_dep(name = "aspect_rules_esbuild", version = "0.21.0") +bazel_dep(name = "aspect_rules_js", version = "2.3.7") +bazel_dep(name = "aspect_rules_ts", version = "3.6.0") +bazel_dep(name = "bazel_features", version = "1.23.0") bazel_dep(name = "bazel_skylib", version = "1.7.1") bazel_dep(name = "buildifier_prebuilt", version = "6.4.0") bazel_dep(name = "contrib_rules_jvm", version = "0.27.0") -bazel_dep(name = "platforms", version = "0.0.10") +bazel_dep(name = "platforms", version = "0.0.11") # Required for the closure rules -bazel_dep(name = "protobuf", version = "21.7", dev_dependency = True, repo_name = "com_google_protobuf") +bazel_dep(name = "protobuf", version = "29.2", dev_dependency = True, repo_name = "com_google_protobuf") # Required for rules_rust to import the crates properly -bazel_dep(name = "rules_cc", version = "0.0.9", dev_dependency = True) +bazel_dep(name = "rules_cc", version = "0.1.1", dev_dependency = True) -bazel_dep(name = "rules_dotnet", version = "0.15.1") -bazel_dep(name = "rules_java", version = "7.6.3") -bazel_dep(name = "rules_jvm_external", version = "6.1") -bazel_dep(name = "rules_nodejs", version = "6.2.0") -bazel_dep(name = "rules_oci", version = "1.7.6") -bazel_dep(name = "rules_pkg", version = "0.10.1") -bazel_dep(name = "rules_python", version = "0.33.0") -bazel_dep(name = "rules_proto", version = "6.0.0") -bazel_dep(name = "rules_ruby", version = "0.11.0") +bazel_dep(name = "rules_dotnet", version = "0.17.5") +bazel_dep(name = "rules_java", version = "8.7.1") +bazel_dep(name = "rules_jvm_external", version = "6.6") +bazel_dep(name = "rules_multitool", version = "1.3.0") +bazel_dep(name = "rules_nodejs", version = "6.3.2") +bazel_dep(name = "rules_oci", version = "1.8.0") +bazel_dep(name = "rules_pkg", version = "1.0.1") +bazel_dep(name = "rules_python", version = "1.5.0") +bazel_dep(name = "rules_proto", version = "7.0.2") +bazel_dep(name = "rules_ruby", version = "0.19.0") + +# Until `rules_jvm_external` 6.8 ships +git_override( + module_name = "rules_jvm_external", + commit = "aca619b117c1fe306ffdd20c5f47cc4dbd5effed", + patch_strip = 1, + patches = ["//java:rules_jvm_external_javadoc.patch"], + remote = "https://github.com/bazel-contrib/rules_jvm_external.git", +) + +multitool = use_extension("@rules_multitool//multitool:extension.bzl", "multitool") +multitool.hub(lockfile = "//:multitool.lock.json") +use_repo(multitool, "multitool") linter = use_extension("@apple_rules_lint//lint:extensions.bzl", "linter") linter.configure( @@ -41,7 +55,11 @@ linter.register(name = "rust-rustfmt") node = use_extension("@rules_nodejs//nodejs:extensions.bzl", "node") node.toolchain(node_version = "20.9.0") -pnpm = use_extension("@aspect_rules_js//npm:extensions.bzl", "pnpm", dev_dependency = True) +pnpm = use_extension( + "@aspect_rules_js//npm:extensions.bzl", + "pnpm", + dev_dependency = True, +) use_repo(pnpm, "pnpm") npm = use_extension("@aspect_rules_js//npm:extensions.bzl", "npm") @@ -51,7 +69,7 @@ npm.npm_translate_lock( "@//:package.json", "@//:pnpm-workspace.yaml", "@//javascript/grid-ui:package.json", - "@//javascript/node/selenium-webdriver:package.json", + "@//javascript/selenium-webdriver:package.json", ], generate_bzl_library_targets = True, npmrc = "//:.npmrc", @@ -72,13 +90,13 @@ rules_ts_ext.deps( use_repo(rules_ts_ext, "npm_typescript") esbuild = use_extension("@aspect_rules_esbuild//esbuild:extensions.bzl", "esbuild") -esbuild.toolchain(esbuild_version = "0.19.9") +esbuild.toolchain(esbuild_version = "0.23.0") use_repo(esbuild, "esbuild_toolchains") register_toolchains("@esbuild_toolchains//:all") dotnet = use_extension("@rules_dotnet//dotnet:extensions.bzl", "dotnet") -dotnet.toolchain(dotnet_version = "7.0.400") +dotnet.toolchain(dotnet_version = "8.0.203") use_repo(dotnet, "dotnet_toolchains") selenium_paket = use_extension("//dotnet:paket.nuget_extension.bzl", "nuget_extension") @@ -89,7 +107,7 @@ register_toolchains("@dotnet_toolchains//:all") oci = use_extension("@rules_oci//oci:extensions.bzl", "oci") oci.pull( name = "java_image_base", - digest = "sha256:161a1d97d592b3f1919801578c3a47c8e932071168a96267698f4b669c24c76d", + digest = "sha256:1df9f3e6a2de0544dd04f1840aa811d334045c9126f9e93d8da45448061ad51e", image = "gcr.io/distroless/java17", ) oci.pull( @@ -107,11 +125,12 @@ use_repo(oci, "chrome_standalone", "firefox_standalone", "java_image_base") python = use_extension("@rules_python//python/extensions:python.bzl", "python") python.toolchain( is_default = True, - python_version = "3.8", + python_version = "3.9", ) -python.toolchain(python_version = "3.9") python.toolchain(python_version = "3.10") python.toolchain(python_version = "3.11") +python.toolchain(python_version = "3.12") +python.toolchain(python_version = "3.13") use_repo(python, "pythons_hub") pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip") @@ -123,10 +142,11 @@ pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip") requirements_lock = "//py:requirements_lock.txt", ) for version in [ - "3.8", "3.9", "3.10", "3.11", + "3.12", + "3.13", ] ] @@ -134,16 +154,6 @@ use_repo(pip, "py_dev_requirements") register_toolchains("@pythons_hub//:all") -# https://github.com/bazelbuild/rules_jvm_external/pull/1079 -archive_override( - module_name = "rules_jvm_external", - integrity = "sha256-yS8Qes1PLbYbe10b1WSgl0Auqn/1Wlxg8O3wSr7a/Sg=", - patch_strip = 1, - patches = ["//java:rules_jvm_external_javadoc.patch"], - strip_prefix = "rules_jvm_external-f572a26116c7ef71d8842dd056c2605782f7be8d", - urls = ["https://github.com/bazelbuild/rules_jvm_external/archive/f572a26116c7ef71d8842dd056c2605782f7be8d.tar.gz"], -) - java_toolchains = use_extension("@rules_java//java:extensions.bzl", "toolchains") use_repo( java_toolchains, @@ -165,59 +175,67 @@ maven.install( name = "maven", artifacts = [ "com.beust:jcommander:1.82", - "com.github.javaparser:javaparser-core:3.26.1", - "com.github.spotbugs:spotbugs:4.8.6", + "com.github.javaparser:javaparser-core:3.27.0", + "com.github.spotbugs:spotbugs:4.9.4", "com.github.stephenc.jcip:jcip-annotations:1.0-1", - "com.google.code.gson:gson:2.11.0", - "com.google.guava:guava:33.2.1-jre", + "com.google.code.findbugs:jsr305:3.0.2", + "com.google.code.gson:gson:2.13.1", + "com.google.guava:guava:33.4.8-jre", + "com.github.ben-manes.caffeine:caffeine:3.2.2", "com.google.auto:auto-common:1.2.2", "com.google.auto.service:auto-service:1.1.1", "com.google.auto.service:auto-service-annotations:1.1.1", - "com.google.googlejavaformat:google-java-format:jar:1.22.0", - "com.graphql-java:graphql-java:20.2", - "com.graphql-java:java-dataloader:3.2.0", + "com.google.googlejavaformat:google-java-format:1.28.0", + "com.graphql-java:graphql-java:24.1", "dev.failsafe:failsafe:3.3.2", - "io.grpc:grpc-context:1.65.1", - "io.lettuce:lettuce-core:6.3.2.RELEASE", - "io.netty:netty-buffer:4.1.111.Final", - "io.netty:netty-codec-http:4.1.111.Final", - "io.netty:netty-codec-http2:4.1.111.Final", - "io.netty:netty-common:4.1.111.Final", - "io.netty:netty-handler:4.1.111.Final", - "io.netty:netty-handler-proxy:4.1.111.Final", - "io.netty:netty-transport:4.1.111.Final", - "io.opentelemetry:opentelemetry-api:1.40.0", - "io.opentelemetry:opentelemetry-context:1.40.0", - "io.opentelemetry:opentelemetry-exporter-logging:1.40.0", - "io.opentelemetry:opentelemetry-sdk:1.40.0", - "io.opentelemetry:opentelemetry-sdk-common:1.40.0", - "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.40.0", - "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.40.0", - "io.opentelemetry:opentelemetry-sdk-testing:1.40.0", - "io.opentelemetry:opentelemetry-sdk-trace:1.40.0", - "io.opentelemetry.semconv:opentelemetry-semconv:1.25.0-alpha", - "io.ous:jtoml:2.0.0", + "io.grpc:grpc-context:1.74.0", + "io.lettuce:lettuce-core:6.8.0.RELEASE", + "io.netty:netty-buffer", + "io.netty:netty-codec-http", + "io.netty:netty-codec-http2", + "io.netty:netty-common", + "io.netty:netty-handler", + "io.netty:netty-handler-proxy", + "io.netty:netty-transport", + "io.opentelemetry:opentelemetry-api", + "io.opentelemetry:opentelemetry-context", + "io.opentelemetry:opentelemetry-exporter-logging", + "io.opentelemetry:opentelemetry-sdk", + "io.opentelemetry:opentelemetry-sdk-common", + "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure", + "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi", + "io.opentelemetry:opentelemetry-sdk-testing", + "io.opentelemetry:opentelemetry-sdk-trace", "it.ozimov:embedded-redis:0.7.3", - "net.bytebuddy:byte-buddy:1.14.18", - "org.htmlunit:htmlunit-core-js:4.3.0", - "org.apache.commons:commons-exec:1.4.0", - "org.apache.logging.log4j:log4j-core:2.23.1", - "org.assertj:assertj-core:3.26.3", - "org.bouncycastle:bcpkix-jdk18on:1.78.1", + "net.bytebuddy:byte-buddy:1.17.6", + "org.htmlunit:htmlunit-core-js:4.14.0", + "org.apache.commons:commons-exec:1.5.0", + "org.apache.logging.log4j:log4j-core:2.25.1", + "org.assertj:assertj-core:3.27.4", + "org.bouncycastle:bcpkix-jdk18on:1.81", "org.eclipse.mylyn.github:org.eclipse.egit.github.core:2.1.5", - "org.hsqldb:hsqldb:2.7.3", - "org.junit.jupiter:junit-jupiter-api:5.10.3", - "org.junit.jupiter:junit-jupiter-engine:5.10.3", - "org.junit.jupiter:junit-jupiter-params:5.10.3", - "org.junit.platform:junit-platform-launcher:1.10.3", - "org.junit.platform:junit-platform-reporting:1.10.3", - "org.junit.platform:junit-platform-commons:1.10.3", - "org.junit.platform:junit-platform-engine:1.10.3", - "org.mockito:mockito-core:5.12.0", - "org.redisson:redisson:3.33.0", - "org.slf4j:slf4j-api:2.0.13", - "org.slf4j:slf4j-jdk14:2.0.13", + "org.hsqldb:hsqldb:2.7.4", + "org.jspecify:jspecify:1.0.0", + "org.junit.jupiter:junit-jupiter-api", + "org.junit.jupiter:junit-jupiter-engine", + "org.junit.jupiter:junit-jupiter-params", + "org.junit.platform:junit-platform-launcher", + "org.junit.platform:junit-platform-reporting", + "org.junit.platform:junit-platform-commons", + "org.junit.platform:junit-platform-engine", + "org.mockito:mockito-core:5.18.0", + "org.redisson:redisson:3.50.0", + "org.slf4j:slf4j-api:2.0.17", + "org.slf4j:slf4j-jdk14:2.0.17", + "org.tomlj:tomlj:1.1.1", "org.zeromq:jeromq:0.6.0", + "uk.org.webcompere:system-stubs-jupiter:2.1.8", + "uk.org.webcompere:system-stubs-core:2.1.8", + ], + boms = [ + "io.opentelemetry:opentelemetry-bom:1.53.0", + "io.netty:netty-bom:4.1.121.Final", + "org.junit:junit-bom:5.13.4", ], excluded_artifacts = [ "org.hamcrest:hamcrest-all", # Replaced by hamcrest 2 @@ -231,6 +249,7 @@ maven.install( repositories = [ "https://repo1.maven.org/maven2", ], + resolver = "maven", strict_visibility = True, ) use_repo(maven, "maven", "unpinned_maven") @@ -238,6 +257,10 @@ use_repo(maven, "maven", "unpinned_maven") ruby = use_extension("@rules_ruby//ruby:extensions.bzl", "ruby") ruby.toolchain( name = "ruby", + msys2_packages = [ + "curl", + "libyaml", + ], version_file = "//:rb/.ruby-version", ) ruby.bundle_fetch( @@ -249,82 +272,88 @@ ruby.bundle_fetch( "//:rb/selenium-webdriver.gemspec", ], gem_checksums = { - "abbrev-0.1.2": "ad1b4eaaaed4cb722d5684d63949e4bde1d34f2a95e20db93aecfe7cbac74242", - "activesupport-7.1.3.2": "ad8445b7ae4a6d3acc5f88c8c5f437eb0b54062032aaf44856c7b6d3855b8b2e", - "addressable-2.8.6": "798f6af3556641a7619bad1dce04cdb6eb44b0216a991b0396ea7339276f2b47", - "ast-2.4.2": "1e280232e6a33754cde542bc5ef85520b74db2aac73ec14acef453784447cc12", + "activesupport-7.2.2.1": "842bcbf8a92977f80fb4750661a237cf5dd4fdd442066b3c35e88afb488647f5", + "addressable-2.8.7": "462986537cf3735ab5f3c0f557f14155d778f4b43ea4f485a9deb9c8f7c58232", + "ast-2.4.3": "954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383", "base64-0.2.0": "0f25e9b21a02a0cc0cea8ef92b2041035d39350946e8789c562b2d1a3da01507", - "bigdecimal-3.1.7": "e799b369a0005fc6d62eed7ef19139ac9bc319cc51470c637b9dcdf593600133", - "bigdecimal-3.1.7-java": "955f5c7aa90136874b494655e42ed70d81382abb0f49f1b42f374a1660e33c63", - "concurrent-ruby-1.2.3": "82fdd3f8a0816e28d513e637bb2b90a45d7b982bdf4f3a0511722d2e495801e2", - "connection_pool-2.4.1": "0f40cf997091f1f04ff66da67eabd61a9fe0d4928b9a3645228532512fab62f4", + "benchmark-0.4.0": "0f12f8c495545e3710c3e4f0480f63f06b4c842cc94cec7f33a956f5180e874a", + "bigdecimal-3.1.9": "2ffc742031521ad69c2dfc815a98e426a230a3d22aeac1995826a75dabfad8cc", + "bigdecimal-3.1.9-java": "dd9b8f7c870664cd9538a1325ce385ba57a6627969177258c4f0e661a7be4456", + "concurrent-ruby-1.3.5": "813b3e37aca6df2a21a3b9f1d497f8cbab24a2b94cab325bffe65ee0f6cbebc6", + "connection_pool-2.5.3": "cfd74a82b9b094d1ce30c4f1a346da23ee19dc8a062a16a85f58eab1ced4305b", "crack-1.0.0": "c83aefdb428cdc7b66c7f287e488c796f055c0839e6e545fec2c7047743c4a49", - "csv-3.3.0": "0bbd1defdc31134abefed027a639b3723c2753862150f4c3ee61cab71b20d67d", - "debug-1.9.2": "48e026c0852c7a10c60263e2e527968308958e266231e36d64e3efcabec7e7fc", - "diff-lcs-1.5.1": "273223dfb40685548436d32b4733aa67351769c7dea621da7d9dd4813e63ddfe", + "csv-3.3.4": "e96ecd5a8c3494aa5b596282249daba5c6033203c199248e6146e36d2a78d8cd", + "curb-1.0.9": "07e5b74a4836103ce186827528f76a22d3991a9b7c45f5c10ee18ee7b03feb0d", + "date-3.4.1": "bf268e14ef7158009bfeaec40b5fa3c7271906e88b196d958a89d4b408abe64f", + "date-3.4.1-java": "74740d914c65a922a15657c25ff0e203c16f1d0f7aa910a9ebed712afe9819c4", + "debug-1.10.0": "11e28ca74875979e612444104f3972bd5ffb9e79179907d7ad46dba44bd2e7a4", + "diff-lcs-1.6.1": "12a5a83f3e37a8e2f4427268e305914d5f1879f22b4e73bb1a09f76a3dd86cd4", "drb-2.2.1": "e9d472bf785f558b96b25358bae115646da0dbfd45107ad858b0bc0d935cb340", - "ffi-1.16.3": "6d3242ff10c87271b0675c58d68d3f10148fabc2ad6da52a18123f06078871fb", - "ffi-1.16.3-java": "6f107fcd7c96f9c96f7e57db749b99502cc2f65665f7b2241d087a8f8c01d42c", - "ffi-1.16.3-x64-mingw32": "6ec709011e3955e97033fa77907a8ab89a9150137d4c45c82c77399b909c9259", - "fileutils-1.7.2": "36a0fb324218263e52b486ad7408e9a295378fe8edc9fd343709e523c0980631", + "ffi-1.17.2": "297235842e5947cc3036ebe64077584bff583cd7a4e94e9a02fdec399ef46da6", + "ffi-1.17.2-java": "94c8516d7c97b21915497b994e41f69e7e8e21d5fc085c498b68e52044e191ec", + "ffi-1.17.2-x64-mingw-ucrt": "15d2da54ee578657a333a6059ed16eaba1cbd794ceecd15944825b65c8381ac0", + "ffi-1.17.2-x86_64-darwin": "981f2d4e32ea03712beb26e55e972797c2c5a7b0257955d8667ba58f2da6440e", + "ffi-1.17.2-x86_64-linux-gnu": "05d2026fc9dbb7cfd21a5934559f16293815b7ce0314846fee2ac8efbdb823ea", + "fileutils-1.7.3": "57271e854b694a87755d76f836f5c57b2c9538ebbaf4b2154bb66addf15eb5da", "git-1.19.1": "b0a422d9f6517353c48a330d6114de4db9e0c82dbe7202964a1d9f1fbc827d70", - "hashdiff-1.1.0": "b5465f0e7375f1ee883f53a766ece4dbc764b7674a7c5ffd76e79b2f5f6fc9c9", - "i18n-1.14.4": "c7deedead0866ea9102975a4eab7968f53de50793a0c211a37808f75dd187551", - "io-console-0.7.2": "f0dccff252f877a4f60d04a4dc6b442b185ebffb4b320ab69212a92b48a7a221", - "io-console-0.7.2-java": "73aa382f8832b116613ceaf57b8ff5bf73dfedcaf39f0aa5420e10f63a4543ed", - "irb-1.12.0": "07634937fbb7d28d07e46da50d0aa43b4d2f7258174d08de4e32dfb57c10539d", - "jar-dependencies-0.4.1": "b2df2f1ecbff15334ce20ea7fdd5b8d8161faab67761ff72c7647d728e40d387", - "json-2.7.2": "1898b5cbc81cd36c0fd4d0b7ad2682c39fb07c5ff682fc6265f678f550d4982c", - "json-2.7.2-java": "138e3038b5361b3d06ee2e8aa2be00bed0d0de4ef5f1553fc5935e5b93aca7ee", - "language_server-protocol-3.17.0.3": "3d5c58c02f44a20d972957a9febe386d7e7468ab3900ce6bd2b563dd910c6b3f", + "hashdiff-1.1.2": "2c30eeded6ed3dce8401d2b5b99e6963fe5f14ed85e60dd9e33c545a44b71a77", + "i18n-1.14.7": "ceba573f8138ff2c0915427f1fc5bdf4aa3ab8ae88c8ce255eb3ecf0a11a5d0f", + "io-console-0.8.0": "cd6a9facbc69871d69b2cb8b926fc6ea7ef06f06e505e81a64f14a470fddefa2", + "io-console-0.8.0-java": "3cc6fd5c66e587145c1fdf8dc40c2e3d851e90722a5d0cc3f38da352f06fe1bd", + "irb-1.15.2": "222f32952e278da34b58ffe45e8634bf4afc2dc7aa9da23fed67e581aa50fdba", + "jar-dependencies-0.5.5": "2972b9fcba4b014e6446a84b5c09674a3e8648b95b71768e729f0e8e40568059", + "json-2.11.3": "9a10f658a2de67c0eb837eb795dd48132ce797c403e52b5ebef87dcdc7f9ccc1", + "json-2.11.3-java": "cfe8db24e49073c5bcd93699d106a1c1c9e5bc301fcc0de05965e72fad999a34", + "language_server-protocol-3.17.0.4": "c484626478664fd13482d8180947c50a8590484b1258b99b7aedb3b69df89669", + "lint_roller-1.1.0": "2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87", "listen-3.9.0": "db9e4424e0e5834480385197c139cb6b0ae0ef28cc13310cfd1ca78377d59c67", - "logger-1.6.0": "0ab7c120262dd8de2a18cb8d377f1f318cbe98535160a508af9e7710ff43ef3e", - "minitest-5.22.3": "ea84676290cb5e2b4f31f25751af6050aa90d3e43e4337141c3e3e839611981e", - "mutex_m-0.2.0": "b6ef0c6c842ede846f2ec0ade9e266b1a9dac0bc151682b04835e8ebd54840d5", - "parallel-1.24.0": "5bf38efb9b37865f8e93d7a762727f8c5fc5deb19949f4040c76481d5eee9397", - "parser-3.3.0.5": "7748313e505ca87045dc0465c776c802043f777581796eb79b1654c5d19d2687", - "psych-5.1.2": "337322f58fc2bf24827d2b9bd5ab595f6a72971867d151bb39980060ea40a368", - "psych-5.1.2-java": "1dd68dc609eddbc884e6892e11da942e16f7256bd30ebde9d35449d43043a6fe", - "public_suffix-5.0.5": "72c340218bb384610536919988705cc29e09749c0021fd7005f715c7e5dfc493", - "racc-1.7.3": "b785ab8a30ec43bce073c51dbbe791fd27000f68d1c996c95da98bf685316905", - "racc-1.7.3-java": "b2ad737e788cfa083263ce7c9290644bb0f2c691908249eb4f6eb48ed2815dbf", - "rack-2.2.9": "fd6301a97a1c1e955e68f85c861fcb1cde6145a32c532e1ea321a72ff8cc4042", + "logger-1.7.0": "196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203", + "minitest-5.25.5": "391b6c6cb43a4802bfb7c93af1ebe2ac66a210293f4a3fb7db36f2fc7dc2c756", + "parallel-1.27.0": "4ac151e1806b755fb4e2dc2332cbf0e54f2e24ba821ff2d3dcf86bf6dc4ae130", + "parser-3.3.8.0": "2476364142b307fa5a1b1ece44f260728be23858a9c71078e956131a75453c45", + "pp-0.6.2": "947ec3120c6f92195f8ee8aa25a7b2c5297bb106d83b41baa02983686577b6ff", + "prettyprint-0.2.0": "2bc9e15581a94742064a3cc8b0fb9d45aae3d03a1baa6ef80922627a0766f193", + "prism-1.4.0": "dc0e3e00e93160213dc2a65519d9002a4a1e7b962db57d444cf1a71565bb703e", + "psych-5.2.4": "f2d9810f7f383a6b0fbc705202851e1a55b236bcb8e168ab5dfa5741842ec7c5", + "psych-5.2.4-java": "a3ae584e85e11fd069f17a563ef18f204d3df0fde0c093d35ae494fd64164664", + "public_suffix-6.0.2": "bfa7cd5108066f8c9602e0d6d4114999a5df5839a63149d3e8b0f9c1d3558394", + "racc-1.8.1": "4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f", + "racc-1.8.1-java": "54f2e6d1e1b91c154013277d986f52a90e5ececbe91465d29172e49342732b98", + "rack-2.2.13": "ccee101719696a5da12ee9da6fb3b1d20cb329939e089e0e458be6e93667f0fb", "rainbow-3.1.1": "039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a", "rake-13.2.1": "46cb38dae65d7d74b6020a4ac9d48afed8eb8149c040eccf0523bec91907059d", "rb-fsevent-0.11.2": "43900b972e7301d6570f64b850a5aa67833ee7d87b458ee92805d56b7318aefe", - "rb-inotify-0.10.1": "050062d4f31d307cca52c3f6a7f4b946df8de25fc4bd373e1a5142e41034a7ca", - "rbs-3.4.4": "1376d2604a00832641bb47521595e63a1c0d1cc241ded383ba48ddb4396de5a8", - "rchardet-1.8.0": "693acd5253d5ade81a51940697955f6dd4bb2f0d245bda76a8e23deec70a52c7", - "rdoc-6.6.3.1": "39f7b749229ab5ad9d21c81586151c1dd7a549fa8be4070ee09b524f9c656345", - "regexp_parser-2.9.0": "81a00ba141cec0d4b4bf58cb80cd9193e5180836d3fa6ef623f7886d3ba8bdd9", - "reline-0.5.3": "2c46747a1dfd03e100f0666d8a374cf2930c3e734298af9b39e5fe8d35b42035", - "rexml-3.2.6": "e0669a2d4e9f109951cb1fde723d8acd285425d81594a2ea929304af50282816", + "rb-inotify-0.11.1": "a0a700441239b0ff18eb65e3866236cd78613d6b9f78fea1f9ac47a85e47be6e", + "rbs-3.9.2": "873b5d01a11f3dc15a7cc3bd66d9d50c3d05fad4fbb73b47704eb96f0ba6faf2", + "rchardet-1.9.0": "26889486cdd83b378652baf7603f71d93e431bb11bc237b4cd8c65151af4a590", + "rdoc-6.13.1": "62a0dac99493c94e8eb7a3fb44e55aefcb4cecb119f7991f25bddc5ed8d472f7", + "regexp_parser-2.10.0": "cb6f0ddde88772cd64bff1dbbf68df66d376043fe2e66a9ef77fcb1b0c548c61", + "reline-0.6.1": "1afcc9d7cb1029cdbe780d72f2f09251ce46d3780050f3ec39c3ccc6b60675fb", + "rexml-3.4.1": "c74527a9a0a04b4ec31dbe0dc4ed6004b960af943d8db42e539edde3a871abca", "rspec-3.13.0": "d490914ac1d5a5a64a0e1400c1d54ddd2a501324d703b8cfe83f458337bab993", - "rspec-core-3.13.0": "557792b4e88da883d580342b263d9652b6a10a12d5bda9ef967b01a48f15454c", - "rspec-expectations-3.13.0": "621d48c62262f955421eaa418130744760802cad47e781df70dba4d9f897102e", - "rspec-mocks-3.13.0": "735a891215758d77cdb5f4721fffc21078793959d1f0ee4a961874311d9b7f66", - "rspec-support-3.13.1": "48877d4f15b772b7538f3693c22225f2eda490ba65a0515c4e7cf6f2f17de70f", - "rubocop-1.63.3": "17a31f16658f2fbb20bc7bcb4a841a06f7368da4f3be8a50365ad61e658d5f44", - "rubocop-ast-1.31.2": "7c206fb094553779923eca862aceece3913ce384f1bf85730208228e884578ec", - "rubocop-capybara-2.20.0": "2a6844b942921f230ee3ab8c94fe77f41a9406096a140245270c0e11624bb938", - "rubocop-factory_bot-2.25.1": "62751bde7af789878b8a31cbd2a82e69515ce7b23a2ad1820cb0fcc3e0150134", - "rubocop-performance-1.21.0": "ec54fa8991c2d538af7bc958361d63bdb3df2e53032da393e9903ea5e4f74a9a", - "rubocop-rspec-2.29.1": "534ee81a3006e7379ec6203687ef7c06ca1d137b7d6d67c2777b680b1ce82e13", - "rubocop-rspec_rails-2.28.3": "9769f2077cca8af2269193ba0450e0317ae1827a132c19149fdbeecaaca32818", + "rspec-core-3.13.3": "25136507f4f9cf2e8977a2851e64e438b4331646054e345998714108745cdfe4", + "rspec-expectations-3.13.4": "4e43459765dfee900b25aa1361e106ab0799895ede65fc57872069feb559ecd8", + "rspec-mocks-3.13.3": "be08abadfe28e932d03b8e70215cd5972bd7693e0f1a45c7479b11e9a773c3c2", + "rspec-support-3.13.3": "2a61e393f6e18b7228726e0c6869c5d5a1419d37206116c4d917d145276b3f43", + "rubocop-1.75.4": "e0656af44d0811bb40f6d0bd4ed6c8d80c0f05f3444f0e8f0839833dd46d18c6", + "rubocop-ast-1.44.1": "e3cc04203b2ef04f6d6cf5f85fe6d643f442b18cc3b23e3ada0ce5b6521b8e92", + "rubocop-performance-1.25.0": "6f7d03568a770054117a78d0a8e191cefeffb703b382871ca7743831b1a52ec1", + "rubocop-rake-0.7.1": "3797f2b6810c3e9df7376c26d5f44f3475eda59eb1adc38e6f62ecf027cbae4d", + "rubocop-rspec-3.6.0": "c0e4205871776727e54dee9cc91af5fd74578001551ba40e1fe1a1ab4b404479", "ruby-progressbar-1.13.0": "80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33", - "rubyzip-2.3.2": "3f57e3935dc2255c414484fbf8d673b4909d8a6a57007ed754dde39342d2373f", - "securerandom-0.3.1": "98f0450c0ea46d2f9a4b6db4f391dbd83dc08049592eada155739f40e0341bde", + "rubyzip-2.4.1": "8577c88edc1fde8935eb91064c5cb1aef9ad5494b940cf19c775ee833e075615", + "securerandom-0.4.1": "cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1", "steep-1.5.3": "7c6302a4d5932d0a46176ebc79766e52b853c223a85525aa2f8911e345123b85", - "stringio-3.1.0": "c1f6263ae03a15025e51194ab19b06b15e06adcaaedb7f5f6c06ab60f5d67718", - "strscan-3.1.0": "01b8a81d214fbf7b5308c6fb51b5972bbfc4a6aa1f166fd3618ba97e0fcd5555", - "strscan-3.1.0-java": "8645aa76e017e21764c6df572d2d79fcc1672284014f5bdbd806278cdbcd11b0", + "stringio-3.1.7": "5b78b7cb242a315fb4fca61a8255d62ec438f58da2b90be66048546ade4507fa", + "strscan-3.1.4": "8e130a503aa6c79352c6ac02a9819507c8b8720c174ce8335e3eb2c8cc2ae042", + "strscan-3.1.4-java": "5551e01d215ba8ac7dadb6dab46b9fb4c33303ba63eaf3e1b0496c078b8d3fb8", "terminal-table-3.0.2": "f951b6af5f3e00203fb290a669e0a85c5dd5b051b3b023392ccfd67ba5abae91", "tzinfo-2.0.6": "8daf828cc77bcf7d63b0e3bdb6caa47e2272dcfaf4fbfe46f8c3a9df087a829b", - "unicode-display_width-2.5.0": "7e7681dcade1add70cb9fda20dd77f300b8587c81ebbd165d14fd93144ff0ab4", - "webmock-3.23.0": "100787435c1f556129a238c11cc7cbee38cb9c2864709c6a0dcdcf822545f31f", - "webrick-1.8.1": "19411ec6912911fd3df13559110127ea2badd0c035f7762873f58afc803e158f", - "websocket-1.2.10": "2cc1a4a79b6e63637b326b4273e46adcddf7871caa5dc5711f2ca4061a629fa8", - "yard-0.9.36": "5505736c1b00c926f71053a606ab75f02070c5960d0778b901fe9d8b0a470be4", + "unicode-display_width-2.6.0": "12279874bba6d5e4d2728cef814b19197dbb10d7a7837a869bab65da943b7f5a", + "webmock-3.25.1": "ab9d5d9353bcbe6322c83e1c60a7103988efc7b67cd72ffb9012629c3d396323", + "webrick-1.9.1": "b42d3c94f166f3fb73d87e9b359def9b5836c426fc8beacf38f2184a21b2a989", + "websocket-1.2.11": "b7e7a74e2410b5e85c25858b26b3322f29161e300935f70a0e0d3c35e0462737", + "yard-0.9.37": "a6e910399e78e613f80ba9add9ba7c394b1a935f083cccbef82903a3d2a26992", }, gemfile = "//:rb/Gemfile", gemfile_lock = "//:rb/Gemfile.lock", @@ -344,6 +373,8 @@ use_repo( pin_browsers_extension = use_extension("//common:repositories.bzl", "pin_browsers_extension") use_repo( pin_browsers_extension, + "linux_beta_chrome", + "linux_beta_chromedriver", "linux_beta_firefox", "linux_chrome", "linux_chromedriver", @@ -351,6 +382,8 @@ use_repo( "linux_edgedriver", "linux_firefox", "linux_geckodriver", + "mac_beta_chrome", + "mac_beta_chromedriver", "mac_beta_firefox", "mac_chrome", "mac_chromedriver", diff --git a/NOTICE b/NOTICE index 42b02391b4142..146d948e632bc 100644 --- a/NOTICE +++ b/NOTICE @@ -1,2 +1,2 @@ -Copyright 2011-2024 Software Freedom Conservancy +Copyright 2011-2025 Software Freedom Conservancy Copyright 2004-2011 Selenium committers diff --git a/README.md b/README.md index e5ef14de8c4f4..268539467320d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,24 @@ -# Selenium - -[![CI](https://github.com/SeleniumHQ/selenium/actions/workflows/ci.yml/badge.svg?branch=trunk&event=schedule)](https://github.com/SeleniumHQ/selenium/actions/workflows/ci.yml) - -Selenium Logo +

+
+ Selenium +
+ Selenium +
+

+ +

Automates browsers. That's it!

+ +

+ Contributing • + Installing • + Building • + Developing • + Testing • + Documenting • + Releasing +

+ +
Selenium is an umbrella project encapsulating a variety of tools and libraries enabling web browser automation. Selenium specifically @@ -13,13 +29,15 @@ major web browsers. The project is made possible by volunteer contributors who've generously donated thousands of hours in code development and upkeep. -Selenium's source code is made available under the [Apache 2.0 license](https://github.com/SeleniumHQ/selenium/blob/trunk/LICENSE). - This README is for developers interested in contributing to the project. For people looking to get started using Selenium, please check out our [User Manual](https://selenium.dev/documentation/) for detailed examples and descriptions, and if you get stuck, there are several ways to [Get Help](https://www.selenium.dev/support/). +[![CI](https://github.com/SeleniumHQ/selenium/actions/workflows/ci.yml/badge.svg)](https://github.com/SeleniumHQ/selenium/actions/workflows/ci.yml) +[![CI - RBE](https://github.com/SeleniumHQ/selenium/actions/workflows/ci-rbe.yml/badge.svg)](https://github.com/SeleniumHQ/selenium/actions/workflows/ci-rbe.yml) +[![Releases downloads](https://img.shields.io/github/downloads/SeleniumHQ/selenium/total.svg)](https://github.com/SeleniumHQ/selenium/releases) + ## Contributing Please read [CONTRIBUTING.md](https://github.com/SeleniumHQ/selenium/blob/trunk/CONTRIBUTING.md) @@ -182,7 +200,14 @@ for Maven to use locally by deploying to your local maven repository (`~/.m2/rep #### Updating Dependencies -Dependencies are defined in the file [maven_deps.bzl](https://github.com/SeleniumHQ/selenium/blob/trunk/java/maven_deps.bzl). +Dependencies are defined in the file [MODULE.bazel](https://github.com/SeleniumHQ/selenium/blob/trunk/MODULE.bazel). + +To update a dependency, modify the version in the `MODULE.bazel` file and run: + +```shell +RULES_JVM_EXTERNAL_REPIN=1 bazel run @maven//:pin +``` + To automatically update and pin new dependencies, run: ```shell @@ -191,16 +216,37 @@ To automatically update and pin new dependencies, run: ### Python -You can run Python code locally by updating generated files in the python directory using: +#### Linting and Formatting + +We follow the [PEP8 Style Guide for Python Code](https://peps.python.org/pep-0008) (except we use a 120 character line length). +This is checked and enforced with [ruff](https://docs.astral.sh/ruff/), a linting/formatting tool. +There is also an auto-formatting script that can be run: `./scripts/format.sh` + +#### Local Installation + +To run Python code locally without building/installing the package, you must first install the dependencies: +```shell +pip install -r py/requirements.txt +``` + +Then, build the generated files and copy them into your local source tree: ```shell -./go py:update +./go py:local_dev ``` -To install Selenium locally based on a specific commit, you can use: +After that, you can import the selenium package directly from source from the `py` directory. + +Instead of running from source, you can build and install the selenium package (wheel) locally: ```shell ./go py:install ``` +This will attempt to install into the global Python `site-packages` directory, +which might not be writable. To avoid this, you should create and activate a +[virtual environment](https://packaging.python.org/en/latest/tutorials/installing-packages/#creating-virtual-environments) +before installing. + + ### Ruby Instead of using `irb`, you can create an interactive REPL with all gems loaded using: `bazel run //rb:console` @@ -220,7 +266,7 @@ you can configure it use Bazel artifacts: 1. Open `rb/` as a main project directory. 2. Run `bundle exec rake update` as necessary to create up-to-date artifacts. If this does not work, run `./go rb:update` from the `selenium` (parent) directory. 3. In Settings / Languages & Frameworks / Ruby SDK and Gems add new Interpreter pointing to `../bazel-selenium/external/rules_ruby_dist/dist/bin/ruby`. -4. You should now be able to run and debug any spec. It uses Chrome by default, but you can alter it using environment variables secified in [Ruby Testing](#ruby-2) section below. +4. You should now be able to run and debug any spec. It uses Chrome by default, but you can alter it using environment variables specified in [Ruby Testing](#ruby-2) section below. ### Rust @@ -264,6 +310,9 @@ Tests can also be filtered by tag like: bazel test ///... --test_tag_filters=this,-not-this ``` +If there are multiple `--test_tag_filters`, only the last one is considered, +so be careful if also using an inherited config + ### Java
@@ -296,13 +345,13 @@ bazel test //java/test/org/openqa/selenium/chrome:ChromeDriverFunctionalTest To run the tests run: ```sh -bazel test //javascript/node/selenium-webdriver:tests +bazel test //javascript/selenium-webdriver:all ``` You can use `--test_env` to pass in the browser name as `SELENIUM_BROWSER`. ```sh -bazel test //javascript/node/selenium-webdriver:tests --test_env=SELENIUM_BROWSER=firefox +bazel test //javascript/selenium-webdriver:all --test_env=SELENIUM_BROWSER=firefox ```
@@ -316,6 +365,18 @@ Run unit tests with: bazel test //py:unit ``` +To run common tests with a specific browser: + +```sh +bazel test //py:common- +``` + +To run common tests with a specific browser (include BiDi tests): + +```sh +bazel test //py:common--bidi +``` + To run tests with a specific browser: ```sh @@ -467,8 +528,6 @@ To update API documentation for a specific language: `./go :docs` To update all documentation: `./go all:docs` -Note that JavaScript generation is [currently broken](https://github.com/SeleniumHQ/selenium/issues/10185). - ## Releasing diff --git a/Rakefile b/Rakefile index 0dc22a2ebeba1..833ec94917f68 100644 --- a/Rakefile +++ b/Rakefile @@ -92,15 +92,13 @@ task '//java/test/org/openqa/selenium/environment/webserver:webserver:uber' => [ '//java/test/org/openqa/selenium/environment:webserver' ] -# Java targets required for release. These should all be java_export targets. -# Generated from: bazel query 'kind(maven_publish, set(//java/... //third_party/...))' | sort +# use #java_release_targets to access this list JAVA_RELEASE_TARGETS = %w[ //java/src/org/openqa/selenium/chrome:chrome.publish //java/src/org/openqa/selenium/chromium:chromium.publish - //java/src/org/openqa/selenium/devtools/v125:v125.publish - //java/src/org/openqa/selenium/devtools/v126:v126.publish - //java/src/org/openqa/selenium/devtools/v127:v127.publish - //java/src/org/openqa/selenium/devtools/v85:v85.publish + //java/src/org/openqa/selenium/devtools/v137:v137.publish + //java/src/org/openqa/selenium/devtools/v138:v138.publish + //java/src/org/openqa/selenium/devtools/v139:v139.publish //java/src/org/openqa/selenium/edge:edge.publish //java/src/org/openqa/selenium/firefox:firefox.publish //java/src/org/openqa/selenium/grid/sessionmap/jdbc:jdbc.publish @@ -120,10 +118,59 @@ JAVA_RELEASE_TARGETS = %w[ //java/src/org/openqa/selenium:core.publish ].freeze +def java_release_targets + @targets_verified ||= verify_java_release_targets + + JAVA_RELEASE_TARGETS +end + +def verify_java_release_targets + query = 'kind(maven_publish, set(//java/... //third_party/...))' + current_targets = [] + + Bazel.execute('query', [], query) do |output| + current_targets = output.lines.map(&:strip).reject(&:empty?).select { |line| line.start_with?('//') } + end + + missing_targets = current_targets - JAVA_RELEASE_TARGETS + extra_targets = JAVA_RELEASE_TARGETS - current_targets + + return if missing_targets.empty? && extra_targets.empty? + + error_message = 'Java release targets are out of sync with Bazel query results.' + + error_message += "\nMissing targets: #{missing_targets.join(', ')}" unless missing_targets.empty? + + error_message += "\nObsolete targets: #{extra_targets.join(', ')}" unless extra_targets.empty? + + raise error_message +end + # Notice that because we're using rake, anything you can do in a normal rake # build can also be done here. For example, here we set the default task task default: [:grid] +# ./go update_browser stable +# ./go update_browser beta +desc 'Update pinned browser versions' +task :update_browsers, [:channel] do |_task, arguments| + chrome_channel = arguments[:channel] || 'Stable' + chrome_channel = 'beta' if chrome_channel == 'early-stable' + args = Array(chrome_channel) ? ['--', "--chrome_channel=#{chrome_channel.capitalize}"] : [] + + puts 'pinning updated browsers and drivers' + Bazel.execute('run', args, '//scripts:pinned_browsers') + @git.add('common/repositories.bzl') +end + +desc 'Update Selenium Manager to latest release' +task :update_manager do |_task, _arguments| + puts 'Updating Selenium Manager references' + Bazel.execute('run', [], '//scripts:selenium_manager') + + @git.add('common/selenium_manager.bzl') +end + task all: [ :'selenium-java', '//java/test/org/openqa/selenium/environment:webserver' @@ -331,7 +378,7 @@ task ios_driver: [ # ./go java:package['--config=release'] desc 'Create stamped zipped assets for Java for uploading to GitHub' task :'java-release-zip' do - Rake::Task['java:package'].invoke('--stamp') + Rake::Task['java:package'].invoke('--config=rbe_release') end task 'release-java': %i[java-release-zip publish-maven] @@ -364,7 +411,7 @@ end desc 'Install jars to local m2 directory' task :'maven-install' do - JAVA_RELEASE_TARGETS.each do |p| + java_release_targets.each do |p| Bazel.execute('run', ['--stamp', '--define', @@ -380,7 +427,9 @@ task 'selenium-java' => '//java/src/org/openqa/selenium:client-combined' desc 'Update AUTHORS file' task :authors do + puts 'Updating AUTHORS file' sh "(git log --use-mailmap --format='%aN <%aE>' ; cat .OLD_AUTHORS) | sort -uf > AUTHORS" + @git.add('AUTHORS') end namespace :side do @@ -404,7 +453,7 @@ namespace :side do end def node_version - File.foreach('javascript/node/selenium-webdriver/package.json') do |line| + File.foreach('javascript/selenium-webdriver/package.json') do |line| return line.split(':').last.strip.tr('",', '') if line.include?('version') end end @@ -416,7 +465,7 @@ namespace :node do ] task atoms: atom_list do - base_dir = 'javascript/node/selenium-webdriver/lib/atoms' + base_dir = 'javascript/selenium-webdriver/lib/atoms' mkdir_p base_dir ['bazel-bin/javascript/atoms/fragments/is-displayed.js', @@ -436,44 +485,54 @@ namespace :node do desc 'Build Node npm package' task :build do |_task, arguments| args = arguments.to_a.compact - Bazel.execute('build', args, '//javascript/node/selenium-webdriver') + Bazel.execute('build', args, '//javascript/selenium-webdriver') end task :'dry-run' do Bazel.execute('run', ['--stamp'], - '//javascript/node/selenium-webdriver:selenium-webdriver.publish -- --dry-run=true') + '//javascript/selenium-webdriver:selenium-webdriver.publish -- --dry-run=true') end desc 'Release Node npm package' task :release do |_task, arguments| - args = arguments.to_a.compact - nightly = args.delete('nightly') - Rake::Task['node:version'].invoke('nightly') if nightly + nightly = arguments.to_a.include?('nightly') + if nightly + puts 'Updating Node version to nightly...' + Rake::Task['node:version'].invoke('nightly') if nightly + end - Bazel.execute('run', ['--stamp'], '//javascript/node/selenium-webdriver:selenium-webdriver.publish') + puts 'Running Node package release...' + Bazel.execute('run', ['--config=release'], '//javascript/selenium-webdriver:selenium-webdriver.publish') end desc 'Release Node npm package' task deploy: :release desc 'Generate Node documentation' - task :docs, [:skip_update] do |_task, arguments| + task :docs do |_task, arguments| + if node_version.include?('nightly') && !arguments.to_a.include?('force') + abort('Aborting documentation update: nightly versions should not update docs.') + end + + puts 'Generating Node documentation' FileUtils.rm_rf('build/docs/api/javascript/') begin - sh 'npm run generate-docs --prefix javascript/node/selenium-webdriver || true', verbose: true - rescue StandardError - puts 'Ensure that npm is installed on your system' - raise + Dir.chdir('javascript/selenium-webdriver') do + sh 'pnpm install', verbose: true + sh 'pnpm run generate-docs', verbose: true + end + rescue StandardError => e + puts "Node documentation generation contains errors; continuing... #{e.message}" end - update_gh_pages unless arguments[:skip_update] + update_gh_pages unless arguments.to_a.include?('skip_update') end desc 'Update JavaScript changelog' task :changelog do - header = "## #{node_version}" - update_changelog(node_version, 'javascript', 'javascript/node/selenium-webdriver/', - 'javascript/node/selenium-webdriver/CHANGES.md', header) + header = "## #{node_version}\n" + update_changelog(node_version, 'javascript', 'javascript/selenium-webdriver/', + 'javascript/selenium-webdriver/CHANGES.md', header) end desc 'Update Node version' @@ -482,14 +541,11 @@ namespace :node do nightly = "-nightly#{Time.now.strftime('%Y%m%d%H%M')}" new_version = updated_version(old_version, arguments[:version], nightly) - ['javascript/node/selenium-webdriver/package.json', - 'package-lock.json', - 'javascript/node/selenium-webdriver/BUILD.bazel'].each do |file| + %w[javascript/selenium-webdriver/package.json javascript/selenium-webdriver/BUILD.bazel].each do |file| text = File.read(file).gsub(old_version, new_version) File.open(file, 'w') { |f| f.puts text } + @git.add(file) end - - Rake::Task['node:changelog'].invoke unless new_version.include?(nightly) end end @@ -508,12 +564,15 @@ namespace :py do desc 'Release Python wheel and sdist to pypi' task :release do |_task, arguments| - args = arguments.to_a.compact - nightly = args.delete('nightly') - Rake::Task['py:version'].invoke('nightly') if nightly + nightly = arguments.to_a.include?('nightly') + if nightly + puts 'Updating Python version to nightly...' + Rake::Task['py:version'].invoke('nightly') + end command = nightly ? '//py:selenium-release-nightly' : '//py:selenium-release' - Bazel.execute('run', ['--stamp'], command) + puts "Running Python release command: #{command}" + Bazel.execute('run', ['--config=release'], command) end desc 'generate and copy files required for local development' @@ -550,7 +609,12 @@ namespace :py do end desc 'Generate Python documentation' - task :docs, [:skip_update] do |_task, arguments| + task :docs do |_task, arguments| + if python_version.match?(/^\d+\.\d+\.\d+\.\d+$/) && !arguments.to_a.include?('force') + abort('Aborting documentation update: nightly versions should not update docs.') + end + puts 'Generating Python documentation' + FileUtils.rm_rf('build/docs/api/py/') FileUtils.rm_rf('build/docs/doctrees/') begin @@ -560,7 +624,7 @@ namespace :py do raise end - update_gh_pages unless arguments[:skip_update] + update_gh_pages unless arguments.to_a.include?('skip_update') end desc 'Install Python wheel locally' @@ -583,30 +647,26 @@ namespace :py do desc 'Update Python version' task :version, [:version] do |_task, arguments| old_version = python_version - nightly = ".dev#{Time.now.strftime('%Y%m%d%H%M')}" + nightly = ".#{Time.now.strftime('%Y%m%d%H%M')}" new_version = updated_version(old_version, arguments[:version], nightly) - ['py/setup.py', + ['py/pyproject.toml', 'py/BUILD.bazel', 'py/selenium/__init__.py', 'py/selenium/webdriver/__init__.py', 'py/docs/source/conf.py'].each do |file| text = File.read(file).gsub(old_version, new_version) File.open(file, 'w') { |f| f.puts text } + @git.add(file) end old_short_version = old_version.split('.')[0..1].join('.') new_short_version = new_version.split('.')[0..1].join('.') - text = File.read('py/docs/source/conf.py').gsub(old_short_version, new_short_version) - File.open('py/docs/source/conf.py', 'w') { |f| f.puts text } - - Rake::Task['py:changelog'].invoke unless new_version.include?(nightly) - end - - desc 'Update Python Syntax' - task :lint do - sh 'tox -c py/tox.ini -e linting' + conf = 'py/docs/source/conf.py' + text = File.read(conf).gsub(old_short_version, new_short_version) + File.open(conf, 'w') { |f| f.puts text } + @git.add(conf) end namespace :test do @@ -666,6 +726,25 @@ namespace :rb do Bazel.execute('build', args, '//rb:selenium-devtools') if devtools || !webdriver end + task :atoms do + base_dir = 'rb/lib/selenium/webdriver/atoms' + mkdir_p base_dir + + { + '//javascript/atoms/fragments:find-elements': 'findElements.js', + '//javascript/atoms/fragments:is-displayed': 'isDisplayed.js', + '//javascript/webdriver/atoms:get-attribute': 'getAttribute.js' + }.each do |target, name| + puts "Generating #{target} as #{name}" + + atom = Bazel.execute('build', [], target.to_s) + + File.open(File.join(base_dir, name), 'w') do |f| + f << File.read(atom).strip + end + end + end + desc 'Update generated Ruby files for local development' task :local_dev do Bazel.execute('build', [], '@bundle//:bundle') @@ -675,26 +754,36 @@ namespace :rb do desc 'Push Ruby gems to rubygems' task :release do |_task, arguments| - args = arguments.to_a.compact - nightly = args.delete('nightly') + nightly = arguments.to_a.include?('nightly') if nightly + puts 'Bumping Ruby nightly version...' Bazel.execute('run', [], '//rb:selenium-webdriver-bump-nightly-version') - Bazel.execute('run', ['--stamp'], '//rb:selenium-webdriver-release-nightly') + + puts 'Releasing nightly WebDriver gem...' + Bazel.execute('run', ['--config=release'], '//rb:selenium-webdriver-release-nightly') else - Bazel.execute('run', ['--stamp'], '//rb:selenium-webdriver-release') - Bazel.execute('run', ['--stamp'], '//rb:selenium-devtools-release') + patch_release = ruby_version.split('.').fetch(2, '0').to_i.positive? + + puts 'Releasing Ruby gems...' + Bazel.execute('run', ['--config=release'], '//rb:selenium-webdriver-release') + Bazel.execute('run', ['--config=release'], '//rb:selenium-devtools-release') unless patch_release end end desc 'Generate Ruby documentation' - task :docs, [:skip_update] do |_task, arguments| + task :docs do |_task, arguments| + if ruby_version.include?('nightly') && !arguments.to_a.include?('force') + abort('Aborting documentation update: nightly versions should not update docs.') + end + puts 'Generating Ruby documentation' + FileUtils.rm_rf('build/docs/api/rb/') Bazel.execute('run', [], '//rb:docs') FileUtils.mkdir_p('build/docs/api') FileUtils.cp_r('bazel-bin/rb/docs.sh.runfiles/_main/docs/api/rb/.', 'build/docs/api/rb') - update_gh_pages unless arguments[:skip_update] + update_gh_pages unless arguments.to_a.include?('skip_update') end desc 'Update Ruby changelog' @@ -711,9 +800,10 @@ namespace :rb do file = 'rb/lib/selenium/webdriver/version.rb' text = File.read(file).gsub(old_version, new_version) File.open(file, 'w') { |f| f.puts text } + @git.add(file) - Rake::Task['rb:changelog'].invoke unless new_version.include?('.nightly') sh 'cd rb && bundle --version && bundle update' + @git.add('rb/Gemfile.lock') end desc 'Update Ruby Syntax' @@ -750,16 +840,20 @@ namespace :dotnet do desc 'Upload nupkg files to Nuget' task :release do |_task, arguments| - args = arguments.to_a.compact - nightly = args.delete('nightly') - Rake::Task['dotnet:version'].invoke('nightly') if nightly - Rake::Task['dotnet:package'].invoke('--stamp') + nightly = arguments.to_a.include?('nightly') + if nightly + puts 'Updating .NET version to nightly...' + Rake::Task['dotnet:version'].invoke('nightly') + end + + puts 'Packaging .NET release artifacts...' + Rake::Task['dotnet:package'].invoke('--config=release') api_key = ENV.fetch('NUGET_API_KEY', nil) push_destination = 'https://api.nuget.org/v3/index.json' + if nightly - # Nightly builds are pushed to GitHub NuGet repository - # This commands will run in GitHub Actions + puts 'Setting up NuGet GitHub source for nightly release...' api_key = ENV.fetch('GITHUB_TOKEN', nil) github_push_url = 'https://nuget.pkg.github.com/seleniumhq/index.json' push_destination = 'github' @@ -768,6 +862,7 @@ namespace :dotnet do sh "dotnet nuget add source #{flags.join(' ')}" end + puts 'Pushing packages to NuGet' ["./bazel-bin/dotnet/src/webdriver/Selenium.WebDriver.#{dotnet_version}.nupkg", "./bazel-bin/dotnet/src/support/Selenium.Support.#{dotnet_version}.nupkg"].each do |asset| sh "dotnet nuget push #{asset} --api-key #{api_key} --source #{push_destination}" @@ -775,13 +870,17 @@ namespace :dotnet do end desc 'Generate .NET documentation' - task :docs, [:skip_update] do |_task, arguments| + task :docs do |_task, arguments| + if dotnet_version.include?('nightly') && !arguments.to_a.include?('force') + abort('Aborting documentation update: nightly versions should not update docs.') + end + + puts 'Generating .NET documentation' FileUtils.rm_rf('build/docs/api/dotnet/') begin - # Pinning to 2.75.3 to avoid breaking changes in newer versions - # See https://github.com/dotnet/docfx/issues/9855 + # Pinning to 2.78.2 to avoid breaking changes in newer versions sh 'dotnet tool uninstall --global docfx || true' - sh 'dotnet tool install --global --version 2.75.3 docfx' + sh 'dotnet tool install --global --version 2.78.2 docfx' # sh 'dotnet tool update -g docfx' rescue StandardError puts 'Please ensure that .NET SDK is installed.' @@ -792,7 +891,7 @@ namespace :dotnet do sh 'docfx dotnet/docs/docfx.json' rescue StandardError case $CHILD_STATUS.exitstatus - when 127 + when 133 raise 'Ensure the dotnet/tools directory is added to your PATH environment variable (e.g., `~/.dotnet/tools`)' when 255 puts '.NET documentation build failed, likely because of DevTools namespacing. This is ok; continuing' @@ -801,7 +900,7 @@ namespace :dotnet do end end - update_gh_pages unless arguments[:skip_update] + update_gh_pages unless arguments.to_a.include?('skip_update') end desc 'Update .NET changelog' @@ -819,8 +918,7 @@ namespace :dotnet do file = 'dotnet/selenium-dotnet-version.bzl' text = File.read(file).gsub(old_version, new_version) File.open(file, 'w') { |f| f.puts text } - - Rake::Task['dotnet:changelog'].invoke unless new_version.include?(nightly) + @git.add(file) end end @@ -828,7 +926,7 @@ namespace :java do desc 'Build Java Client Jars' task :build do |_task, arguments| args = arguments.to_a.compact - JAVA_RELEASE_TARGETS.each { |target| Bazel.execute('build', args, target) } + java_release_targets.each { |target| Bazel.execute('build', args, target) } end desc 'Build Grid Server' @@ -839,7 +937,7 @@ namespace :java do desc 'Package Java bindings and grid into releasable packages and stage for release' task :package do |_task, arguments| - args = arguments.to_a.compact.empty? ? ['--stamp'] : arguments.to_a.compact + args = arguments.to_a.compact.empty? ? ['--config=release'] : arguments.to_a.compact Bazel.execute('build', args, '//java/src/org/openqa/selenium:client-zip') Bazel.execute('build', args, '//java/src/org/openqa/selenium/grid:server-zip') Bazel.execute('build', args, '//java/src/org/openqa/selenium/grid:executable-grid') @@ -860,62 +958,72 @@ namespace :java do desc 'Deploy all jars to Maven' task :release do |_task, arguments| - args = arguments.to_a.compact - nightly = args.delete('nightly') + nightly = arguments.to_a.include?('nightly') ENV['MAVEN_USER'] ||= ENV.fetch('SEL_M2_USER', nil) ENV['MAVEN_PASSWORD'] ||= ENV.fetch('SEL_M2_PASS', nil) read_m2_user_pass unless ENV['MAVEN_PASSWORD'] && ENV['MAVEN_USER'] - - repo = nightly ? 'content/repositories/snapshots' : 'service/local/staging/deploy/maven2' - ENV['MAVEN_REPO'] = "https://oss.sonatype.org/#{repo}" + repo_domain = 'central.sonatype.com' + repo = nightly ? "#{repo_domain}/repository/maven-snapshots" : "ossrh-staging-api.#{repo_domain}/service/local/staging/deploy/maven2/" + ENV['MAVEN_REPO'] = "https://#{repo}" ENV['GPG_SIGN'] = (!nightly).to_s - Rake::Task['java:version'].invoke if nightly - Rake::Task['java:package'].invoke('--stamp') - Rake::Task['java:build'].invoke('--stamp') - JAVA_RELEASE_TARGETS.each { |target| Bazel.execute('run', ['--stamp'], target) } + if nightly + puts 'Updating Java version to nightly...' + Rake::Task['java:version'].invoke('nightly') + end + + puts 'Packaging Java artifacts...' + Rake::Task['java:package'].invoke('--config=release') + Rake::Task['java:build'].invoke('--config=release') + + puts "Releasing Java artifacts to Maven repository at '#{ENV.fetch('MAVEN_REPO', nil)}'" + java_release_targets.each { |target| Bazel.execute('run', ['--config=release'], target) } end desc 'Install jars to local m2 directory' task install: :'maven-install' desc 'Generate Java documentation' - task :docs, [:skip_update] do |_task, arguments| + task :docs do |_task, arguments| + if java_version.include?('SNAPSHOT') && !arguments.to_a.include?('force') + abort('Aborting documentation update: snapshot versions should not update docs.') + end + + puts 'Generating Java documentation' Rake::Task['javadocs'].invoke - update_gh_pages unless arguments[:skip_update] + update_gh_pages unless arguments.to_a.include?('skip_update') end desc 'Update Maven dependencies' task :update do # Make sure things are in a good state to start with args = ['--action_env=RULES_JVM_EXTERNAL_REPIN=1'] - Bazel.execute('run', args, '@unpinned_maven//:pin') + Bazel.execute('run', args, '@maven//:pin') file_path = 'MODULE.bazel' content = File.read(file_path) - # For some reason ./go wrapper is not outputting from Open3, so cannot use Bazel class directly - output = `bazel run @maven//:outdated` - - output.scan(/\S+ \[\S+-alpha\]/).each do |match| - puts "WARNING — Cannot automatically update alpha version of: #{match}" + output = nil + Bazel.execute('run', [], '@maven//:outdated') do |out| + output = out end versions = output.scan(/(\S+) \[\S+ -> (\S+)\]/).to_h versions.each do |artifact, version| if artifact.match?('graphql') + # https://github.com/graphql-java/graphql-java/discussions/3187 puts 'WARNING — Cannot automatically update graphql' next end - - replacement = artifact.include?('googlejavaformat') ? "#{artifact}:jar:#{version}" : "#{artifact}:#{version}" - content.gsub!(/#{artifact}:(jar:)?\d+\.\d+[^\\"]+/, replacement) + content.sub!(/#{Regexp.escape(artifact)}:([\d.-]+(?:[-.]?[A-Za-z0-9]+)*)/, "#{artifact}:#{version}") end File.write(file_path, content) args = ['--action_env=RULES_JVM_EXTERNAL_REPIN=1'] - Bazel.execute('run', args, '@unpinned_maven//:pin') + Bazel.execute('run', args, '@maven//:pin') + + %w[MODULE.bazel java/maven_install.json].each { |file| @git.add(file) } end desc 'Update Java changelog' @@ -932,7 +1040,7 @@ namespace :java do file = 'java/version.bzl' text = File.read(file).gsub(old_version, new_version) File.open(file, 'w') { |f| f.puts text } - Rake::Task['java:changelog'].invoke unless new_version.include?('-SNAPSHOT') + @git.add(file) end end @@ -976,33 +1084,46 @@ namespace :rust do ['rust/Cargo.toml', 'rust/BUILD.bazel'].each do |file| text = File.read(file).gsub(old_version, new_version) File.open(file, 'w') { |f| f.puts text } + @git.add(file) end - Rake::Task['rust:changelog'].invoke unless new_version.include?('-nightly') Rake::Task['rust:update'].invoke - end - - # Creating a special task for this because Rust version needs to be managed at a different place than - # everything else; want to use changelog updates later in process - namespace :version do - desc 'Commits updates from Rust version changes' - task :commit do - @git.reset - commit!("update Rust version to #{rust_version}", - ['rust/BUILD.bazel', 'rust/Cargo.Bazel.lock', 'rust/Cargo.lock', 'rust/Cargo.toml']) - commit!('Rust Changelog', ['rust/CHANGELOG.md']) - end + @git.add('rust/Cargo.Bazel.lock') + @git.add('rust/Cargo.lock') end end namespace :all do + desc 'Update Chrome DevTools support' + task :update_cdp, [:channel] do |_task, arguments| + chrome_channel = arguments[:channel] || 'stable' + chrome_channel = 'beta' if chrome_channel == 'early-stable' + args = Array(chrome_channel) ? ['--', "--chrome_channel=#{chrome_channel.capitalize}"] : [] + + puts "Updating Chrome DevTools references to include latest from #{chrome_channel} channel" + Bazel.execute('run', args, '//scripts:update_cdp') + + ['common/devtools/', + 'dotnet/src/webdriver/DevTools/', + 'dotnet/src/webdriver/Selenium.WebDriver.csproj', + 'dotnet/test/common/DevTools/', + 'dotnet/test/common/CustomDriverConfigs/', + 'dotnet/selenium-dotnet-version.bzl', + 'java/src/org/openqa/selenium/devtools/', + 'javascript/selenium-webdriver/BUILD.bazel', + 'py/BUILD.bazel', + 'rb/lib/selenium/devtools/', + 'rb/Gemfile.lock', + 'Rakefile'].each { |file| @git.add(file) } + end + desc 'Update all API Documentation' task :docs do - Rake::Task['java:docs'].invoke(true) - Rake::Task['py:docs'].invoke(true) - Rake::Task['rb:docs'].invoke(true) - Rake::Task['dotnet:docs'].invoke(true) - Rake::Task['node:docs'].invoke(true) + Rake::Task['java:docs'].invoke('skip_update') + Rake::Task['py:docs'].invoke('skip_update') + Rake::Task['rb:docs'].invoke('skip_update') + Rake::Task['dotnet:docs'].invoke('skip_update') + Rake::Task['node:docs'].invoke('skip_update') update_gh_pages end @@ -1028,94 +1149,31 @@ namespace :all do task :release do |_task, arguments| Rake::Task['clean'].invoke - args = arguments.to_a.compact.empty? ? ['--stamp'] : arguments.to_a.compact + args = arguments.to_a.include?('nightly') ? ['nightly'] : [] Rake::Task['java:release'].invoke(*args) Rake::Task['py:release'].invoke(*args) Rake::Task['rb:release'].invoke(*args) Rake::Task['dotnet:release'].invoke(*args) Rake::Task['node:release'].invoke(*args) - - # TODO: Update this so it happens in each language, but does not commit - Rake::Task['all:version'].invoke('nightly') - - puts 'Committing nightly version updates' - commit!('update versions to nightly', ['dotnet/selenium-dotnet-version.bzl', - 'java/version.bzl', - 'javascript/node/selenium-webdriver/BUILD.bazel', - 'javascript/node/selenium-webdriver/package.json', - 'py/docs/source/conf.py', - 'py/selenium/webdriver/__init__.py', - 'py/selenium/__init__.py', - 'py/BUILD.bazel', - 'py/setup.py', - 'rb/lib/selenium/webdriver/version.rb', - 'rb/Gemfile.lock', - 'package-lock.json']) - - print 'Do you want to push the committed changes? (Y/n): ' - response = $stdin.gets.chomp.downcase - @git.push if %w[y yes].include?(response) end task :lint do ext = /mswin|msys|mingw|cygwin|bccwin|wince|emc/.match?(RbConfig::CONFIG['host_os']) ? 'ps1' : 'sh' sh "./scripts/format.#{ext}", verbose: true - Rake::Task['py:lint'].invoke end + # Example: `./go all:prepare 4.31.0 early-stable` desc 'Update everything in preparation for a release' task :prepare, [:version, :channel] do |_task, arguments| - chrome_channel = arguments[:channel] || 'Stable' version = arguments[:version] - args = Array(chrome_channel) ? ['--', "--chrome_channel=#{chrome_channel.capitalize}"] : [] - Bazel.execute('run', args, '//scripts:pinned_browsers') - commit!('Update pinned browser versions', ['common/repositories.bzl']) - - Bazel.execute('run', args, '//scripts:update_cdp') - commit!('Update supported versions for Chrome DevTools', - ['common/devtools/', - 'dotnet/src/webdriver/DevTools/', - 'dotnet/src/webdriver/WebDriver.csproj', - 'dotnet/test/common/DevTools/', - 'dotnet/test/common/CustomDriverConfigs/', - 'dotnet/selenium-dotnet-version.bzl', - 'java/src/org/openqa/selenium/devtools/', - 'javascript/node/selenium-webdriver/BUILD.bazel', - 'py/BUILD.bazel', - 'rb/lib/selenium/devtools/', - 'rb/Gemfile.lock', - 'Rakefile']) - - Bazel.execute('run', args, '//scripts:selenium_manager') - commit!('Update selenium manager version', ['common/selenium_manager.bzl']) + Rake::Task['update_browsers'].invoke(arguments[:channel]) + Rake::Task['all:update_cdp'].invoke(arguments[:channel]) + Rake::Task['update_manager'].invoke Rake::Task['java:update'].invoke - commit!('Update Maven Dependencies', ['java/maven_deps.bzl', 'java/maven_install.json']) - Rake::Task['authors'].invoke - commit!('Update authors file', ['AUTHORS']) - - # Note that this does not include Rust version changes that are handled in separate rake:version task - # TODO: These files are all defined in other tasks; remove duplication Rake::Task['all:version'].invoke(version) - commit!("FIX CHANGELOGS BEFORE MERGING!\n\nUpdate versions and change logs to release Selenium #{java_version}", - ['dotnet/CHANGELOG', - 'dotnet/selenium-dotnet-version.bzl', - 'java/CHANGELOG', - 'java/version.bzl', - 'javascript/node/selenium-webdriver/CHANGES.md', - 'javascript/node/selenium-webdriver/package.json', - 'package-lock.json', - 'py/docs/source/conf.py', - 'py/selenium/__init__.py', - 'py/selenium/webdriver/__init__.py', - 'py/BUILD.bazel', - 'py/CHANGES', - 'py/setup.py', - 'rb/lib/selenium/webdriver/version.rb', - 'rb/CHANGES', - 'rb/Gemfile.lock', - 'rust/CHANGELOG.md']) + Rake::Task['all:changelogs'] end desc 'Update all versions' @@ -1127,11 +1185,34 @@ namespace :all do Rake::Task['node:version'].invoke(version) Rake::Task['py:version'].invoke(version) Rake::Task['dotnet:version'].invoke(version) + Rake::Task['rust:version'].invoke(version) + + unless version == 'nightly' + major_minor = arguments[:version][/^\d+\.\d+/] + file = '.github/ISSUE_TEMPLATE/bug-report.yml' + old_version_pattern = /The latest released version of Selenium is (\d+\.\d+)/ + + text = File.read(file).gsub(old_version_pattern, "The latest released version of Selenium is #{major_minor}") + File.write(file, text) + @git.add(file) + end + end + + desc 'Update all changelogs' + task :changelogs do |_task, _arguments| + Rake::Task['java:changelog'].invoke + Rake::Task['rb:changelog'].invoke + Rake::Task['node:changelog'].invoke + Rake::Task['py:changelog'].invoke + Rake::Task['dotnet:changelog'].invoke + Rake::Task['rust:changelog'].invoke end end at_exit do - system 'sh', '.git-fixfiles' if File.exist?('.git') && !SeleniumRake::Checks.windows? + system 'sh', '.git-fixfiles' if File.exist?('.git') && SeleniumRake::Checks.linux? +rescue StandardError => e + puts "Do not exit execution when this errors... #{e.inspect}" end def updated_version(current, desired = nil, nightly = nil) @@ -1140,7 +1221,7 @@ def updated_version(current, desired = nil, nightly = nil) desired.split('.').tap { |v| v << 0 while v.size < 3 }.join('.') elsif current.split(/\.|-/).size > 3 # if current version is already nightly, just need to bump it; this will be noop for some languages - pattern = /-?\.?(nightly|SNAPSHOT|dev)\d*$/ + pattern = /-?\.?(nightly|SNAPSHOT|dev|\d{12})\d*$/ current.gsub(pattern, nightly) elsif current.split(/\.|-/).size == 3 # if current version is not nightly, need to bump the version and make nightly @@ -1148,26 +1229,34 @@ def updated_version(current, desired = nil, nightly = nil) end end -def update_gh_pages - @git.fetch('origin', {ref: 'gh-pages'}) - @git.checkout('gh-pages', force: true) +def update_gh_pages(force: true) + puts 'Switching to gh-pages branch...' + @git.fetch('https://github.com/seleniumhq/selenium.git', {ref: 'gh-pages'}) + + unless force + puts 'Stash changes that are not docs...' + @git.lib.send(:command, 'stash', ['push', '-m', 'stash wip', '--', ':(exclude)build/docs/api/']) + end + + @git.checkout('gh-pages', force: force) + + updated = false %w[java rb py dotnet javascript].each do |language| - next unless Dir.exist?("build/docs/api/#{language}") && !Dir.empty?("build/docs/api/#{language}") + source = "build/docs/api/#{language}" + destination = "docs/api/#{language}" - FileUtils.rm_rf("docs/api/#{language}") - FileUtils.mv("build/docs/api/#{language}", "docs/api/#{language}") + next unless Dir.exist?(source) && !Dir.empty?(source) - commit!("updating #{language} API docs", ["docs/api/#{language}/"]) + puts "Updating documentation for #{language}..." + FileUtils.rm_rf(destination) + FileUtils.mv(source, destination) + + @git.add(destination) + updated = true end -end -def restore_git(origin_reference) - puts 'Stashing docs changes for gh-pages' - Git::Stash.new(@git, 'docs changes for gh-pages') - puts "Checking out originating branch/tag — #{origin_reference}" - @git.checkout(origin_reference) - false + puts(updated ? 'Documentation staged. Ready for commit.' : 'No documentation changes found.') end def previous_tag(current_version, language = nil) @@ -1191,27 +1280,27 @@ end def update_changelog(version, language, path, changelog, header) tag = previous_tag(version, language) - log = `git --no-pager log #{tag}...HEAD --pretty=format:"--> %B" --reverse #{path}` - commits = log.split('>>>').map { |entry| - lines = entry.split("\n") - lines.reject! { |line| line.match?(/^(----|Co-authored|Signed-off)/) || line.empty? } - lines.join("\n") - }.join("\n>>>") - - File.open(changelog, 'r+') do |file| - new_content = "#{header}\n#{commits}\n\n#{file.read}" - file.rewind - file.write(new_content) - file.truncate(file.pos) - end -end + bullet = language == 'javascript' ? '- ' : '* ' + commit_delimiter = '===DELIM===' + tags_to_remove = /\[(dotnet|rb|py|java|js|rust)\]:?\s?/ -def commit!(message, files = [], all: false) - files.each do |file| - puts "adding: #{file}" - @git.add(file) - end - all ? @git.commit_all(message) : @git.commit(message) -rescue Git::FailedError => e - puts e.message + command = "git --no-pager log #{tag}...HEAD --pretty=format:\"%s%n%b#{commit_delimiter}\" --reverse #{path}" + puts "Executing git command: #{command}" + + log = `#{command}` + + commits = log.split(commit_delimiter).map { |commit| + lines = commit.gsub(tags_to_remove, '').strip.lines.map(&:chomp) + subject = "#{bullet}#{lines[0]}" + + body = lines[1..] + .reject { |line| line.match?(/^(----|Co-authored|Signed-off)/) || line.empty? } + .map { |line| " > #{line}" } + .join("\n") + body.empty? ? subject : "#{subject}\n#{body}" + }.join("\n") + + content = File.read(changelog) + File.write(changelog, "#{header}\n#{commits}\n\n#{content}") + @git.add(changelog) end diff --git a/WORKSPACE b/WORKSPACE index eb09ccc8726e0..e82b52f11fa56 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -6,17 +6,9 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "io_bazel_rules_closure", - patch_args = [ - "-p1", - ], - patches = [ - "//javascript:rules_closure_shell.patch", - ], - sha256 = "d66deed38a0bb20581c15664f0ab62270af5940786855c7adc3087b27168b529", - strip_prefix = "rules_closure-0.11.0", - urls = [ - "https://github.com/bazelbuild/rules_closure/archive/0.11.0.tar.gz", - ], + integrity = "sha256-lJjlc2jvuCuYXbHtQmp2fL8boDmP167WMvw5CGVOGx4=", + strip_prefix = "rules_closure-0.12.0", + url = "https://github.com/bazelbuild/rules_closure/archive/refs/tags/0.12.0.tar.gz", ) load("@io_bazel_rules_closure//closure:repositories.bzl", "rules_closure_dependencies", "rules_closure_toolchains") @@ -34,8 +26,8 @@ rules_closure_toolchains() http_archive( name = "rules_rust", - integrity = "sha256-JLN47ZcAbx9wEr5Jiib4HduZATGLiDgK7oUi/fvotzU=", - urls = ["https://github.com/bazelbuild/rules_rust/releases/download/0.42.1/rules_rust-v0.42.1.tar.gz"], + integrity = "sha256-eEXiHXSGUH6qD1bdI5KXZ/B04m0wIUeoyM7pmujzbbQ=", + urls = ["https://github.com/bazelbuild/rules_rust/releases/download/0.55.5/rules_rust-0.55.5.tar.gz"], ) load("@rules_rust//rust:repositories.bzl", "rules_rust_dependencies", "rust_register_toolchains") diff --git a/common/browsers.bzl b/common/browsers.bzl index 7be9d79fbf267..0617a80c934d4 100644 --- a/common/browsers.bzl +++ b/common/browsers.bzl @@ -83,3 +83,25 @@ firefox_beta_data = select({ ], "//conditions:default": [], }) + geckodriver_data + +chromedriver_beta_data = select({ + "@selenium//common:use_pinned_linux_chrome": [ + "@linux_beta_chromedriver//:chromedriver", + ], + "@selenium//common:use_pinned_macos_chrome": [ + "@mac_beta_chromedriver//:chromedriver", + ], + "@selenium//common:use_local_chromedriver": ["@selenium//common:chromedriver"], + "//conditions:default": [], +}) + +chrome_beta_data = select({ + "@selenium//common:use_pinned_linux_chrome": [ + "@linux_beta_chrome//:files", + "@linux_beta_chrome//:chrome-linux64/chrome", + ], + "@selenium//common:use_pinned_macos_chrome": [ + "@mac_beta_chrome//:Chrome.app", + ], + "//conditions:default": [], +}) + chromedriver_beta_data diff --git a/common/devtools/BUILD.bazel b/common/devtools/BUILD.bazel index 3372453b49d0b..4039709859906 100644 --- a/common/devtools/BUILD.bazel +++ b/common/devtools/BUILD.bazel @@ -6,7 +6,7 @@ exports_files( "js_protocol.json", ], visibility = [ - "//javascript/node/selenium-webdriver:__pkg__", + "//javascript/selenium-webdriver:__pkg__", "//py:__pkg__", "//rb/lib/selenium/devtools:__pkg__", ], diff --git a/common/devtools/chromium/v125/BUILD.bazel b/common/devtools/chromium/v125/BUILD.bazel deleted file mode 100644 index 6b4a4fe5c3f4a..0000000000000 --- a/common/devtools/chromium/v125/BUILD.bazel +++ /dev/null @@ -1,37 +0,0 @@ -package( - default_visibility = [ - "//dotnet/src/webdriver:__subpackages__", - "//java/src/org/openqa/selenium/devtools:__subpackages__", - "//javascript/node/selenium-webdriver:__pkg__", - "//py:__pkg__", - "//rb/lib/selenium/devtools:__pkg__", - ], -) - -genrule( - name = "browser_protocol", - srcs = [ - "browser_protocol.pdl", - ], - outs = [ - "browser_protocol.json", - ], - cmd = "$(location //common/devtools:pdl_to_json) $(location :browser_protocol.pdl) --map_binary_to_string=true $@", - tools = [ - "//common/devtools:pdl_to_json", - ], -) - -genrule( - name = "js_protocol", - srcs = [ - "js_protocol.pdl", - ], - outs = [ - "js_protocol.json", - ], - cmd = "$(location //common/devtools:pdl_to_json) $(location :js_protocol.pdl) --map_binary_to_string=true $@", - tools = [ - "//common/devtools:pdl_to_json", - ], -) diff --git a/common/devtools/chromium/v125/browser_protocol.pdl b/common/devtools/chromium/v125/browser_protocol.pdl deleted file mode 100644 index 162eeacc25478..0000000000000 --- a/common/devtools/chromium/v125/browser_protocol.pdl +++ /dev/null @@ -1,12282 +0,0 @@ -# Copyright 2017 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Contributing to Chrome DevTools Protocol: https://goo.gle/devtools-contribution-guide-cdp - -version - major 1 - minor 3 - -experimental domain Accessibility - depends on DOM - - # Unique accessibility node identifier. - type AXNodeId extends string - - # Enum of possible property types. - type AXValueType extends string - enum - boolean - tristate - booleanOrUndefined - idref - idrefList - integer - node - nodeList - number - string - computedString - token - tokenList - domRelation - role - internalRole - valueUndefined - - # Enum of possible property sources. - type AXValueSourceType extends string - enum - attribute - implicit - style - contents - placeholder - relatedElement - - # Enum of possible native property sources (as a subtype of a particular AXValueSourceType). - type AXValueNativeSourceType extends string - enum - description - figcaption - label - labelfor - labelwrapped - legend - rubyannotation - tablecaption - title - other - - # A single source for a computed AX property. - type AXValueSource extends object - properties - # What type of source this is. - AXValueSourceType type - # The value of this property source. - optional AXValue value - # The name of the relevant attribute, if any. - optional string attribute - # The value of the relevant attribute, if any. - optional AXValue attributeValue - # Whether this source is superseded by a higher priority source. - optional boolean superseded - # The native markup source for this value, e.g. a `