diff --git a/setup-container.sh b/setup-container.sh index c0f991d35c4..46a983d2824 100755 --- a/setup-container.sh +++ b/setup-container.sh @@ -38,6 +38,7 @@ declare -r VERBOSE_MIN="${VERBOSE_ERROR}" # Arguments ----------------------------------------------------------------------------------------------------------- # +ENV_VARS="" CONTAINER_NAME="" IMAGE_ID="" LINK_DIR="" @@ -96,6 +97,7 @@ function show_help_and_exit() { echo " -n set the name of the Docker container" echo echo "Other options:" + echo " -e set environment variable inside the container (can be used multiple times)" echo " -i specify Docker image to use. This can be an image ID (hashed value) or an image name." echo " If no value is provided, defaults to the following images in the specified order:" echo " 1. The local image named \"docker-sonic-mgmt\"" @@ -298,7 +300,7 @@ EOF function start_local_container() { log_info "creating a container: ${CONTAINER_NAME} ..." - eval "docker run -d -t ${PUBLISH_PORTS} -h ${CONTAINER_NAME} \ + eval "docker run -d -t ${PUBLISH_PORTS} ${ENV_VARS} -h ${CONTAINER_NAME} \ -v \"$(dirname "${SCRIPT_DIR}"):${LINK_DIR}:rslave\" ${MOUNT_POINTS} \ --name \"${CONTAINER_NAME}\" \"${LOCAL_IMAGE}\" /bin/bash ${SILENT_HOOK}" || \ exit_failure "failed to start a container: ${CONTAINER_NAME}" @@ -345,11 +347,14 @@ if [[ $# -eq 0 ]]; then show_help_and_exit "${EXIT_SUCCESS}" fi -while getopts "n:i:d:m:p:fvxh" opt; do +while getopts "e:n:i:d:m:p:fvxh" opt; do case "${opt}" in n ) CONTAINER_NAME="${OPTARG}" ;; + e ) + ENV_VARS+=" -e ${OPTARG}" + ;; i ) IMAGE_ID="${OPTARG}" ;; diff --git a/tests/common/plugins/conditional_mark/issue.py b/tests/common/plugins/conditional_mark/issue.py index 44f0fd3482c..f6efdac2cec 100644 --- a/tests/common/plugins/conditional_mark/issue.py +++ b/tests/common/plugins/conditional_mark/issue.py @@ -2,11 +2,13 @@ """ import logging import multiprocessing +import os import re -import six -import requests - from abc import ABCMeta, abstractmethod +from urllib.parse import urlencode + +import requests +import six logger = logging.getLogger(__name__) @@ -38,28 +40,58 @@ def __init__(self, url, proxies): self.proxies = proxies def is_active(self): - """Check if the issue is still active. + """Check if the GitHub issue is still active. - If unable to get issue state, always consider it as active. + Attempt to fetch issue details via proxy if configured. If proxy fails, retry with direct GitHub API URL. + If unable to retrieve issue state, assume the issue is active (safe default). Returns: bool: False if the issue is closed else True. """ - try: - response = requests.get(self.api_url, proxies=self.proxies, timeout=10) + + def fetch_issue(url): + response = requests.get(url, proxies=self.proxies, timeout=10) response.raise_for_status() - issue_data = response.json() - if issue_data.get('state', '') == 'closed': - logger.debug('Issue {} is closed'.format(self.url)) - labels = issue_data.get('labels', []) - if any(['name' in label and 'duplicate' in label['name'].lower() for label in labels]): - logger.warning('GitHub issue: {} looks like duplicate and was closed. Please re-check and ignore' - 'the test on the parent issue'.format(self.url)) - return False - except Exception as e: - logger.error('Get details for {} failed with: {}'.format(self.url, repr(e))) - - logger.debug('Issue {} is active. Or getting issue state failed, consider it as active anyway'.format(self.url)) + return response.json() + + direct_url = self.api_url + proxy_url = os.getenv("SONIC_AUTOMATION_PROXY_GITHUB_ISSUES_URL") + + issue_data = None + + # Attempt to access via proxy first (if configured) + # The proxy is used to work around GitHub's unauthenticated rate limit (60 requests/hour per IP). + # For details, refer to GitHub API rate limits documentation: + # https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api?apiVersion=2022-11-28#primary-rate-limit-for-unauthenticated-users + if proxy_url: + try: + proxy_endpoint = f"{proxy_url.rstrip('/')}/?{urlencode({'github_issue_url': direct_url})}" + logger.info("Attempting to access GitHub API via proxy.") + issue_data = fetch_issue(proxy_endpoint) + except Exception as proxy_err: + logger.warning(f"Proxy access failed: {proxy_err}. Falling back to direct API.") + + # Fallback to direct URL if proxy is not set or fails + if issue_data is None: + try: + logger.info(f"Accessing GitHub API directly: {direct_url}") + issue_data = fetch_issue(direct_url) + except Exception as direct_err: + logger.error(f"Access GitHub API directly failed for {direct_url}: {direct_err}") + logger.debug(f"Issue {direct_url} is considered active due to API access failure.") + return True + + # Check issue state + if issue_data.get('state') == 'closed': + logger.debug(f"Issue {direct_url} is closed.") + labels = issue_data.get('labels', []) + if any('name' in label and 'duplicate' in label['name'].lower() for label in labels): + logger.warning( + f"GitHub issue {direct_url} appears to be a duplicate and was closed. " + f"Consider ignoring related test failures.") + return False + + logger.debug(f"Issue {direct_url} is active.") return True