Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat: Video recording with dynamic file name based on metadata in tests #2249

Merged
merged 2 commits into from
May 5, 2024

Conversation

VietND96
Copy link
Member

@VietND96 VietND96 commented May 5, 2024

User description

Thanks for contributing to the Docker-Selenium project!
A PR well described will help maintainers to quickly review and merge it

Before submitting your PR, please check our contributing guidelines, applied for this repository.
Avoid large PRs, help reviewers by making them as simple and short as possible.

Description

feat: Video recording with dynamic file name based on metadata in tests

Motivation and Context

Video recording with dynamic file name based on metadata in tests

Based on the support of Metadata in tests. When the video recorder is sidecar deployed with the browser node with enabling SE_VIDEO_FILE_NAME=auto and adding metadata to your tests, video file name will extract value of capability se:name and use it as the video file name.

For example in Python binding:

from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium import webdriver

options = ChromeOptions()
options.set_capability('se:name', 'test_visit_basic_auth_secured_page (ChromeTests)')
driver = webdriver.Remote(options=options, command_executor="http://localhost:4444")
driver.get("https://selenium.dev")
driver.quit()

The output video file name will be test_visit_basic_auth_secured_page_ChromeTests_<sessionId>.mp4.

If your test name is handled by the test framework, and it is unique for sure, you also can disable the session id appends to the video file name by setting SE_VIDEO_FILE_NAME_SUFFIX=false.

File name will be trimmed to 255 characters to avoid long file names. Moreover, space character will be replaced by _ and only characters alphabets, numbers, - (hyphen), _ (underscore) are retained in the file name.

The trim regex is able to be customized by setting SE_VIDEO_FILE_NAME_TRIM_REGEX environment variable. The default value is [:alnum:]-_. The regex should be compatible with the tr command in bash.

At deployment level, the recorder container is up always. In addition, you can disable video recording process via session capability se:recordVideo. For example in Python binding:

options.set_capability('se:recordVideo', False)

In recorder container will perform query GraphQL in Hub based on Node SessionId and extract the value of se:recordVideo in capabilities before deciding to start video recording process or not.

Notes: To reach the GraphQL endpoint, the recorder container needs to know the Hub URL. The Hub URL can be passed via environment variable SE_NODE_GRID_URL. For example SE_NODE_GRID_URL is http://selenium-hub:4444.

For example, docker-compose-v3-video.yml


Dynamic Grid

From language bindings, you can set the se:name capability to change output video file name dynamically. For example, in Python binding:

from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium import webdriver

options = ChromeOptions()
options.set_capability('se:recordVideo', True)
options.set_capability('se:screenResolution', '1920x1080')
options.set_capability('se:name', 'test_visit_basic_auth_secured_page (ChromeTests)')
driver = webdriver.Remote(options=options, command_executor="http://localhost:4444")
driver.get("https://selenium.dev")
driver.quit()

After test executed, under (${PWD}/assets) you can see the video file name in path /<sessionId>/test_visit_basic_auth_secured_page_ChromeTests.mp4

The file name will be trimmed to 255 characters to avoid long file names. Moreover, the space character will be replaced by _, and only the characters alphabets, numbers, - (hyphen), and _ (underscore) are retained in the file name. (This feat is available once this SeleniumHQ/selenium#13907 merged)

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 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.

PR Type

enhancement, bug_fix


Description

  • Enhanced video upload and recording scripts with better cleanup, signal handling, and logging.
  • Introduced dynamic video file naming based on test metadata, improving traceability of test artifacts.
  • Updated Helm chart testing scripts to handle new configurations and improved cleanup logic.
  • Added new GitHub Actions workflows for video integrity checks and artifact uploads.
  • Updated documentation to reflect new features and usage examples.

Changes walkthrough 📝

Relevant files
Enhancement
8 files
upload.sh
Enhance upload script with improved cleanup and signal handling

Video/upload.sh

  • Added removal of UPLOAD_PIPE_FILE upon graceful exit.
  • Modified signal trapping to include SIGTERM and SIGINT along with
    EXIT.
  • +2/-1     
    video.sh
    Refactor video recording script with improved logging and process
    handling

    Video/video.sh

  • Introduced a variable process_name to tag log entries.
  • Enhanced logging with timestamps and process name.
  • Changed pkill to kill using pgrep for stopping ffmpeg to improve
    reliability.
  • Added removal of UPLOAD_PIPE_FILE in the graceful exit function.
  • +36/-30 
    video_graphQLQuery.sh
    Support dynamic video file naming based on session metadata

    Video/video_graphQLQuery.sh

  • Added handling for dynamic video file naming based on test metadata.
  • Implemented conditional logic for appending session ID based on
    SE_VIDEO_FILE_NAME_SUFFIX.
  • Enhanced output to return both recording flag and video file name.
  • +18/-2   
    chart_test.sh
    Update Helm chart testing scripts with additional configurations and
    cleanup

    tests/charts/make/chart_test.sh

  • Added handling for persistent volume claims and resource limits in
    Helm chart tests.
  • Improved environment variable management and conditional logic for
    test setups.
  • +33/-5   
    __init__.py
    Enhance Selenium tests with video naming and post-test delay

    tests/SeleniumTests/init.py

  • Added capabilities for dynamic video file naming and screen resolution
    in Selenium tests.
  • Implemented a delay after tests based on an environment variable.
  • +13/-4   
    helm-chart-test.yml
    Enhance GitHub Actions for Helm chart tests with video checks

    .github/workflows/helm-chart-test.yml

  • Added steps for video integrity checks and uploading video artifacts
    in GitHub Actions.
  • +17/-1   
    test-video.yml
    Refactor GitHub Actions workflow for video upload consolidation

    .github/workflows/test-video.yml

    • Consolidated video upload steps in GitHub Actions workflow.
    +13/-17 
    Makefile
    Add new make targets for dynamic video testing and integrity checks

    Makefile

  • Added a new make target for testing video with dynamic names.
  • Implemented video integrity checks in the makefile.
  • +44/-21 
    Bug_fix
    1 files
    _helpers.tpl
    Fix uploader conditional checks in Helm chart templates   

    charts/selenium-grid/templates/_helpers.tpl

  • Fixed conditional checks for uploader configuration in Helm templates.

  • +2/-2     
    Documentation
    1 files
    README.md
    Update README with dynamic video file naming documentation

    README.md

  • Updated documentation to include details on dynamic video file naming
    based on test metadata.
  • +55/-0   

    💡 PR-Agent usage:
    Comment /help on the PR to get a list of all available PR-Agent tools and their descriptions

    Copy link

    PR Description updated to latest commit (d4caf9d)

    Copy link

    PR Review 🔍

    ⏱️ Estimated effort to review [1-5]

    4, because the PR involves multiple complex changes across various scripts, configurations, and test setups. It requires a thorough understanding of the video recording feature, environment variable configurations, and potential impacts on existing functionalities.

    🧪 Relevant tests

    Yes

    ⚡ Possible issues

    Possible Bug: The use of pgrep ffmpeg in stop_recording function might not reliably capture the correct process ID if multiple ffmpeg processes are running. Consider using a more specific method to track and kill the ffmpeg process started by this script.

    Performance Concern: The addition of logging with timestamps in multiple places might introduce slight delays. While generally minimal, this could affect performance in high-load scenarios or when precise timing is critical.

    🔒 Security concerns

    No

    Copy link

    PR Code Suggestions ✨

    CategorySuggestions                                                                                                                                                       
    Enhancement
    Improve the reliability of stopping ffmpeg processes.

    Replace the kill -INT $(pgrep ffmpeg) command with pkill -INT ffmpeg to ensure that all
    ffmpeg processes are targeted more reliably without needing to spawn a subshell for pgrep.

    Video/video.sh [84]

    -kill -INT $(pgrep ffmpeg)
    +pkill -INT ffmpeg
     
    Add error handling for FIFO file creation to enhance robustness.

    Consider adding error handling for the mkfifo command to manage cases where the FIFO file
    could not be created, which would prevent silent failures.

    Video/video.sh [38]

    -mkfifo ${UPLOAD_PIPE_FILE}
    +if ! mkfifo ${UPLOAD_PIPE_FILE}; then
    +  echo "Failed to create FIFO file: ${UPLOAD_PIPE_FILE}"
    +  exit 1
    +fi
     
    Improve filename sanitization by using a more explicit character set.

    Replace the use of tr -dc "${VIDEO_FILE_NAME_TRIM}" with a more explicit and controlled
    regex pattern or set of characters to ensure that the filename sanitization is robust and
    predictable.

    Video/video_graphQLQuery.sh [36]

    -TEST_NAME="$(echo "${TEST_NAME}" | tr ' ' '_' | tr -dc "${VIDEO_FILE_NAME_TRIM}" | cut -c 1-251)"
    +TEST_NAME="$(echo "${TEST_NAME}" | tr ' ' '_' | tr -dc '[:alnum:]_-' | cut -c 1-251)"
     
    Add error handling for environment variable integer conversion.

    Add error handling for the integer conversion of the environment variable to prevent
    crashes due to invalid inputs.

    tests/SeleniumTests/init.py [23]

    -TEST_DELAY_AFTER_TEST = int(os.environ.get('TEST_DELAY_AFTER_TEST', 0))
    +try:
    +  TEST_DELAY_AFTER_TEST = int(os.environ.get('TEST_DELAY_AFTER_TEST', 0))
    +except ValueError:
    +  TEST_DELAY_AFTER_TEST = 0
     
    Conditionally execute the video integrity check based on the presence of video files.

    To ensure that the make test_video_integrity command only runs when necessary, consider
    adding a condition to check if video files exist before executing the command.

    Makefile [485]

    -make test_video_integrity
    +if [ -n "$$(find ./tests/videos -type f -name '*.mp4')" ]; then make test_video_integrity; fi
     
    Allow dynamic configuration of the video file name suffix to enhance flexibility.

    Instead of hardcoding the video file name suffix as "true" or "false", consider using a
    more flexible approach that allows configuration through an environment variable or a
    configuration file.

    Makefile [471]

    -echo VIDEO_FILE_NAME_SUFFIX=$${VIDEO_FILE_NAME_SUFFIX:-"true"} >> .env ;
    +echo VIDEO_FILE_NAME_SUFFIX=$${VIDEO_FILE_NAME_SUFFIX:-$${DEFAULT_VIDEO_SUFFIX}} >> .env ;
     
    Add detailed logging and error handling to the video file integrity check process.

    To improve the robustness of the video file integrity check, consider adding logging for
    each step and more detailed error messages to help in troubleshooting.

    Makefile [549]

    -docker run -u $$(id -u) -v $$(pwd):$$(pwd) -w $$(pwd) --entrypoint="" $(FFMPEG_BASED_NAME)/ffmpeg:$(FFMPEG_BASED_TAG) ffmpeg -v error -i "$$file" -f null - ;
    +echo "Starting integrity check for $$file"; \
    +docker run -u $$(id -u) -v $$(pwd):$$(pwd) -w $$(pwd) --entrypoint="" $(FFMPEG_BASED_NAME)/ffmpeg:$(FFMPEG_BASED_TAG) ffmpeg -v error -i "$$file" -f null - ; \
    +if [ $$? -ne 0 ]; then echo "Error: Integrity check failed for $$file"; else echo "$$file passed integrity check"; fi
     
    Document or comment on the logic behind dynamic video file naming for better maintainability and clarity.

    Since SE_VIDEO_FILE_NAME is set to 'auto' for dynamic naming, it's crucial to document or
    provide inline comments on how the naming convention is derived (e.g., based on timestamp,
    session ID, etc.) to aid in maintainability and understanding for new developers or during
    debugging sessions.

    docker-compose-v3-video.yml [46-70]

    -- SE_VIDEO_FILE_NAME=auto
    +- SE_VIDEO_FILE_NAME=auto  # Naming based on timestamp and session ID
     
    Security
    Enhance security by preventing potential command injection and ensuring proper variable quoting.

    To avoid potential command injection vulnerabilities, consider using array variables for
    commands and ensure that variables in command contexts are properly quoted.

    Video/video.sh [129]

    -exec ffmpeg -hide_banner -loglevel warning -flags low_delay -threads 1 -fflags nobuffer+genpts -strict experimental -y -f x11grab \
    -  -video_size ${VIDEO_SIZE} -r ${FRAME_RATE} -i ${DISPLAY_CONTAINER_NAME}:${DISPLAY_NUM}.0 -codec:v ${CODEC} ${PRESET} -pix_fmt yuv420p "$VIDEO_FOLDER/$VIDEO_FILE_NAME"
    +ffmpeg_cmd=(ffmpeg -hide_banner -loglevel warning -flags low_delay -threads 1 -fflags nobuffer+genpts -strict experimental -y -f x11grab \
    +  -video_size "${VIDEO_SIZE}" -r "${FRAME_RATE}" -i "${DISPLAY_CONTAINER_NAME}:${DISPLAY_NUM}.0" -codec:v "${CODEC}" "${PRESET}" -pix_fmt yuv420p "${VIDEO_FOLDER}/${VIDEO_FILE_NAME}")
    +exec "${ffmpeg_cmd[@]}"
     
    Best practice
    Improve safety by adding checks before deleting files.

    Instead of using rm -rf which can be risky, especially when combined with variables, use a
    more controlled deletion method with checks.

    Video/video.sh [109]

    -rm -rf ${UPLOAD_PIPE_FILE} || true
    +if [ -e "${UPLOAD_PIPE_FILE}" ]; then
    +  rm -f "${UPLOAD_PIPE_FILE}" || { echo "Failed to delete ${UPLOAD_PIPE_FILE}"; exit 1; }
    +fi
     
    Use improved test command for conditionals in bash scripts.

    Use [[ instead of [ for conditional expressions to take advantage of bash's improved test
    mechanism which offers more features and reliability.

    Video/video.sh [164]

    -if [ $(($attempts % 60)) -eq 0 ];
    +if [[ $(($attempts % 60)) -eq 0 ]];
     
    Use a case statement for more robust boolean string handling.

    Use a more robust method to handle boolean string comparisons by using a case statement or
    a function to avoid potential issues with different case inputs.

    Video/video_graphQLQuery.sh [26-30]

    -if [ "${RECORD_VIDEO,,}" = "false" ]; then
    -  RECORD_VIDEO=false
    -else
    -  RECORD_VIDEO=true
    -fi
    +case "${RECORD_VIDEO,,}" in
    +  "false") RECORD_VIDEO=false ;;
    +  *) RECORD_VIDEO=true ;;
    +esac
     
    Check file existence before removal for safer file operations.

    Ensure that the removal of ${UPLOAD_PIPE_FILE} is handled safely by checking if the file
    exists before attempting to remove it.

    Video/upload.sh [51]

    -rm -rf ${UPLOAD_PIPE_FILE} || true
    +[ -f "${UPLOAD_PIPE_FILE}" ] && rm -rf ${UPLOAD_PIPE_FILE}
     
    Improve environment variable naming for clarity and to avoid potential conflicts.

    It's recommended to use more descriptive variable names for environment variables to avoid
    conflicts and increase clarity. For example, VIDEO_FILE_NAME could be more specific to its
    usage context.

    Makefile [470]

    -VIDEO_FILE_NAME=$${VIDEO_FILE_NAME:-"chrome_video.mp4"} >> .env ;
    +TEST_VIDEO_FILE_NAME=$${TEST_VIDEO_FILE_NAME:-"chrome_video.mp4"} >> .env ;
     
    Ensure compatibility and clarity by verifying dynamic file naming support and removing deprecated environment variables.

    It appears that the commented-out environment variable FILE_NAME is replaced by
    SE_VIDEO_FILE_NAME with a value of 'auto'. If the intention is to dynamically generate
    file names based on metadata, ensure that the system or application using these variables
    supports the 'auto' setting and behaves as expected. If FILE_NAME is no longer needed, it
    should be removed entirely to avoid confusion.

    docker-compose-v3-video.yml [45-46]

    -- FILE_NAME=chrome_video.mp4
    +- SE_VIDEO_FILE_NAME=auto
     
    Maintainability
    Use a more descriptive variable name for clarity.

    Consider using a more descriptive variable name than TEST_DELAY_AFTER_TEST to clarify its
    purpose, such as DELAY_SECONDS_AFTER_TEST.

    tests/SeleniumTests/init.py [23]

    -TEST_DELAY_AFTER_TEST = int(os.environ.get('TEST_DELAY_AFTER_TEST', 0))
    +DELAY_SECONDS_AFTER_TEST = int(os.environ.get('DELAY_SECONDS_AFTER_TEST', 0))
     
    Use a variable for the video directory path to enhance maintainability and flexibility.

    To avoid potential issues with hardcoded paths, consider using a variable for the video
    directory path, which can be set at the top of the Makefile or passed as an environment
    variable.

    Makefile [540]

    -list_files=$$(find ./tests/videos -type f -name "*.mp4");
    +VIDEO_DIR=./tests/videos; \
    +list_files=$$(find $$VIDEO_DIR -type f -name "*.mp4");
     
    Reduce redundancy and potential for errors by defining shared environment variables globally.

    The addition of SE_NODE_GRID_URL to each service's environment suggests a centralized
    Selenium Grid URL. To avoid redundancy and potential errors in URL updates, consider
    defining SE_NODE_GRID_URL globally for all services if the URL is the same across them.

    docker-compose-v3-video.yml [44-68]

    -- SE_NODE_GRID_URL=http://selenium-hub:4444
    +environment:
    +  SE_NODE_GRID_URL: http://selenium-hub:4444
     
    Remove deprecated and unused configuration lines to clean up the environment settings.

    The commented-out FILE_NAME variables are still present in the file. If these are no
    longer used due to the new SE_VIDEO_FILE_NAME setting, it would be cleaner and less
    confusing to remove these commented lines entirely.

    docker-compose-v3-video.yml [45-69]

    -# - FILE_NAME=chrome_video.mp4
    +# (Remove this line if no longer needed)
     
    Possible issue
    Verify that the 'auto' setting for video file names generates unique and meaningful names to prevent file clashes.

    The use of the auto value for SE_VIDEO_FILE_NAME across different services suggests a
    feature for automatic file naming. Confirm that the underlying system correctly interprets
    'auto' to generate meaningful and unique file names, especially in a concurrent testing
    environment where file name clashes can occur.

    docker-compose-v3-video.yml [46-70]

    -- SE_VIDEO_FILE_NAME=auto
    +- SE_VIDEO_FILE_NAME=auto  # Ensure unique naming to avoid clashes
     

    Signed-off-by: Viet Nguyen Duc <nguyenducviet4496@gmail.com>
    @VietND96 VietND96 merged commit 6d3a8a7 into SeleniumHQ:trunk May 5, 2024
    14 checks passed
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    1 participant