2024-11-01T16:19:15.0609714Z Current runner version: '2.320.0' 2024-11-01T16:19:15.0633199Z ##[group]Operating System 2024-11-01T16:19:15.0633935Z Ubuntu 2024-11-01T16:19:15.0634289Z 22.04.5 2024-11-01T16:19:15.0634641Z LTS 2024-11-01T16:19:15.0635057Z ##[endgroup] 2024-11-01T16:19:15.0635445Z ##[group]Runner Image 2024-11-01T16:19:15.0635889Z Image: ubuntu-22.04 2024-11-01T16:19:15.0636513Z Version: 20241015.1.0 2024-11-01T16:19:15.0637531Z Included Software: https://github.com/actions/runner-images/blob/ubuntu22/20241015.1/images/ubuntu/Ubuntu2204-Readme.md 2024-11-01T16:19:15.0638988Z Image Release: https://github.com/actions/runner-images/releases/tag/ubuntu22%2F20241015.1 2024-11-01T16:19:15.0639889Z ##[endgroup] 2024-11-01T16:19:15.0640296Z ##[group]Runner Image Provisioner 2024-11-01T16:19:15.0640801Z 2.0.384.1 2024-11-01T16:19:15.0641171Z ##[endgroup] 2024-11-01T16:19:15.0656850Z ##[group]GITHUB_TOKEN Permissions 2024-11-01T16:19:15.0658680Z Contents: read 2024-11-01T16:19:15.0659162Z Metadata: read 2024-11-01T16:19:15.0659839Z ##[endgroup] 2024-11-01T16:19:15.0663029Z Secret source: Actions 2024-11-01T16:19:15.0663722Z Prepare workflow directory 2024-11-01T16:19:15.1871386Z Prepare all required actions 2024-11-01T16:19:15.2080078Z Uses: pytorch/pytorch/.github/workflows/_runner-determinator.yml@refs/heads/main (33dce10ece5b38aa0ab76739b658cd980a6e3d8f) 2024-11-01T16:19:15.2086133Z ##[group] Inputs 2024-11-01T16:19:15.2086619Z check_experiments: 2024-11-01T16:19:15.2087107Z triggering_actor: pytorch-bot[bot] 2024-11-01T16:19:15.2087775Z issue_owner: 2024-11-01T16:19:15.2088176Z curr_branch: ciflow/trunk/138766 2024-11-01T16:19:15.2088680Z curr_ref_type: tag 2024-11-01T16:19:15.2089173Z issue_number: 5132 2024-11-01T16:19:15.2089564Z ##[endgroup] 2024-11-01T16:19:15.2090455Z Complete job name: before-test / get-label-type / runner-determinator 2024-11-01T16:19:15.9386796Z ##[group]Run cat < runner_determinator.py 2024-11-01T16:19:15.9388741Z cat < runner_determinator.py 2024-11-01T16:19:15.9389259Z # flake8: noqa: G004 2024-11-01T16:19:15.9389627Z  2024-11-01T16:19:15.9390278Z # Note: Copies of this script in runner_determinator.py and _runner-determinator.yml 2024-11-01T16:19:15.9391167Z # must be kept in sync. You can do it easily by running the following command: 2024-11-01T16:19:15.9391903Z # python .github/scripts/update_runner_determinator.py 2024-11-01T16:19:15.9392535Z  2024-11-01T16:19:15.9392854Z """ 2024-11-01T16:19:15.9393375Z This runner determinator is used to determine which set of runners to run a 2024-11-01T16:19:15.9394198Z GitHub job on. It uses the first comment of a GitHub issue (by default 2024-11-01T16:19:15.9395145Z https://github.com/pytorch/test-infra/issues/5132) to define the configuration 2024-11-01T16:19:15.9395925Z of which runners should be used to run which job. 2024-11-01T16:19:15.9396450Z  2024-11-01T16:19:15.9396972Z The configuration has two parts, the settings and a list of opted-in users, 2024-11-01T16:19:15.9397873Z separated by a line containing "---". If the line is not present, the 2024-11-01T16:19:15.9398623Z settings are considered to be empty with only the second part, the user 2024-11-01T16:19:15.9399216Z list, defined. 2024-11-01T16:19:15.9399646Z  2024-11-01T16:19:15.9400159Z The first part is a YAML block that defines the rollout settings. This can be 2024-11-01T16:19:15.9400982Z used to define any settings that are needed to determine which runners to use. 2024-11-01T16:19:15.9401824Z It's fields are defined by the RolloutSettings class below. 2024-11-01T16:19:15.9402727Z  2024-11-01T16:19:15.9403269Z The second part is a list of users who are explicitly opted in to the LF fleet. 2024-11-01T16:19:15.9404166Z The user list is also a comma separated list of additional features or 2024-11-01T16:19:15.9405178Z experiments which the user could be opted in to. 2024-11-01T16:19:15.9405617Z  2024-11-01T16:19:15.9406068Z The user list has the following rules: 2024-11-01T16:19:15.9406499Z  2024-11-01T16:19:15.9406955Z - Users are GitHub usernames, which must start with the @ prefix 2024-11-01T16:19:15.9407850Z - Each user is also a comma-separated list of features/experiments to enable 2024-11-01T16:19:15.9408548Z - A "#" prefix opts the user out of all experiments 2024-11-01T16:19:15.9409011Z  2024-11-01T16:19:15.9409554Z Example config: 2024-11-01T16:19:15.9410012Z  # A list of experiments that can be opted into. 2024-11-01T16:19:15.9410648Z  # This defines the behavior they'll induce when opted into. 2024-11-01T16:19:15.9411242Z  # Expected syntax is: 2024-11-01T16:19:15.9411846Z  # [experiment_name]: # Name of the experiment. Also used for the label prefix. 2024-11-01T16:19:15.9412734Z  # rollout_perc: [int] # % of workflows to run with this experiment when users are not opted in. 2024-11-01T16:19:15.9413415Z  2024-11-01T16:19:15.9413720Z  experiments: 2024-11-01T16:19:15.9414095Z  lf: 2024-11-01T16:19:15.9414481Z  rollout_percent: 25 2024-11-01T16:19:15.9414911Z  all_branches: false 2024-11-01T16:19:15.9415311Z  default: true 2024-11-01T16:19:15.9415711Z  --- 2024-11-01T16:19:15.9416035Z  2024-11-01T16:19:15.9416333Z  # Opt-ins: 2024-11-01T16:19:15.9416957Z  # Users can opt into the LF fleet by adding their GitHub username to this list 2024-11-01T16:19:15.9417917Z  # and specifying experiments to enable in a comma-separated list. 2024-11-01T16:19:15.9418575Z  # Experiments should be from the above list. 2024-11-01T16:19:15.9419131Z  2024-11-01T16:19:15.9419418Z  @User1,lf,split_build 2024-11-01T16:19:15.9419820Z  @User2,lf 2024-11-01T16:19:15.9420254Z  @User3,split_build 2024-11-01T16:19:15.9420602Z """ 2024-11-01T16:19:15.9420904Z  2024-11-01T16:19:15.9421289Z import logging 2024-11-01T16:19:15.9421606Z import os 2024-11-01T16:19:15.9421937Z import random 2024-11-01T16:19:15.9422408Z from argparse import ArgumentParser 2024-11-01T16:19:15.9422840Z from logging import LogRecord 2024-11-01T16:19:15.9423441Z from typing import Any, Dict, FrozenSet, Iterable, List, NamedTuple, Tuple 2024-11-01T16:19:15.9424165Z  2024-11-01T16:19:15.9424431Z import yaml 2024-11-01T16:19:15.9424827Z from github import Auth, Github 2024-11-01T16:19:15.9425349Z from github.Issue import Issue 2024-11-01T16:19:15.9425720Z  2024-11-01T16:19:15.9426023Z  2024-11-01T16:19:15.9426469Z DEFAULT_LABEL_PREFIX = "" # use meta runners 2024-11-01T16:19:15.9427061Z WORKFLOW_LABEL_LF = "lf." # use runners from the linux foundation 2024-11-01T16:19:15.9427840Z WORKFLOW_LABEL_LF_CANARY = "lf.c." # use canary runners from the linux foundation 2024-11-01T16:19:15.9428518Z  2024-11-01T16:19:15.9428897Z GITHUB_OUTPUT = os.getenv("GITHUB_OUTPUT", "") 2024-11-01T16:19:15.9429375Z GH_OUTPUT_KEY_AMI = "runner-ami" 2024-11-01T16:19:15.9429907Z GH_OUTPUT_KEY_LABEL_TYPE = "label-type" 2024-11-01T16:19:15.9430360Z  2024-11-01T16:19:15.9430613Z  2024-11-01T16:19:15.9431021Z SETTING_EXPERIMENTS = "experiments" 2024-11-01T16:19:15.9431451Z  2024-11-01T16:19:15.9431729Z LF_FLEET_EXPERIMENT = "lf" 2024-11-01T16:19:15.9432219Z CANARY_FLEET_SUFFIX = ".c" 2024-11-01T16:19:15.9432612Z  2024-11-01T16:19:15.9432863Z  2024-11-01T16:19:15.9433248Z class Experiment(NamedTuple): 2024-11-01T16:19:15.9433930Z  rollout_perc: float = ( 2024-11-01T16:19:15.9434496Z  0 # Percentage of workflows to experiment on when user is not opted-in. 2024-11-01T16:19:15.9435178Z  ) 2024-11-01T16:19:15.9435520Z  all_branches: bool = ( 2024-11-01T16:19:15.9436081Z  False # If True, the experiment is also enabled on the exception branches 2024-11-01T16:19:15.9436748Z  ) 2024-11-01T16:19:15.9437074Z  default: bool = ( 2024-11-01T16:19:15.9437588Z  True # If True, the experiment is enabled by default for all queries 2024-11-01T16:19:15.9438233Z  ) 2024-11-01T16:19:15.9438534Z  2024-11-01T16:19:15.9438830Z  # Add more fields as needed 2024-11-01T16:19:15.9439321Z  2024-11-01T16:19:15.9439662Z  2024-11-01T16:19:15.9440069Z class Settings(NamedTuple): 2024-11-01T16:19:15.9440445Z  """ 2024-11-01T16:19:15.9440889Z  Settings for the experiments that can be opted into. 2024-11-01T16:19:15.9441476Z  """ 2024-11-01T16:19:15.9441749Z  2024-11-01T16:19:15.9442110Z  experiments: Dict[str, Experiment] = {} 2024-11-01T16:19:15.9443053Z  2024-11-01T16:19:15.9443322Z  2024-11-01T16:19:15.9443683Z class ColorFormatter(logging.Formatter): 2024-11-01T16:19:15.9444355Z  """Color codes the log messages based on the log level""" 2024-11-01T16:19:15.9444836Z  2024-11-01T16:19:15.9445136Z  COLORS = { 2024-11-01T16:19:15.9445607Z  "WARNING": "\033[33m", # Yellow 2024-11-01T16:19:15.9446055Z  "ERROR": "\033[31m", # Red 2024-11-01T16:19:15.9446729Z  "CRITICAL": "\033[31m", # Red 2024-11-01T16:19:15.9447284Z  "INFO": "\033[0m", # Reset 2024-11-01T16:19:15.9447740Z  "DEBUG": "\033[0m", # Reset 2024-11-01T16:19:15.9448144Z  } 2024-11-01T16:19:15.9448522Z  2024-11-01T16:19:15.9448902Z  def format(self, record: LogRecord) -> str: 2024-11-01T16:19:15.9449572Z  log_color = self.COLORS.get(record.levelname, "\033[0m") # Default to reset 2024-11-01T16:19:15.9450335Z  record.msg = f"{log_color}{record.msg}\033[0m" 2024-11-01T16:19:15.9450879Z  return super().format(record) 2024-11-01T16:19:15.9451268Z  2024-11-01T16:19:15.9451630Z  2024-11-01T16:19:15.9451995Z handler = logging.StreamHandler() 2024-11-01T16:19:15.9452629Z handler.setFormatter(ColorFormatter(fmt="%(levelname)-8s: %(message)s")) 2024-11-01T16:19:15.9453267Z  2024-11-01T16:19:15.9453696Z log = logging.getLogger(os.path.basename(__file__)) 2024-11-01T16:19:15.9454175Z log.addHandler(handler) 2024-11-01T16:19:15.9454658Z log.setLevel(logging.INFO) 2024-11-01T16:19:15.9455071Z  2024-11-01T16:19:15.9455323Z  2024-11-01T16:19:15.9455788Z def set_github_output(key: str, value: str) -> None: 2024-11-01T16:19:15.9456293Z  """ 2024-11-01T16:19:15.9456735Z  Defines outputs of the github action that invokes this script 2024-11-01T16:19:15.9457348Z  """ 2024-11-01T16:19:15.9457705Z  if not GITHUB_OUTPUT: 2024-11-01T16:19:15.9458656Z  # See https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/ for deprecation notice 2024-11-01T16:19:15.9459653Z  log.warning( 2024-11-01T16:19:15.9460433Z  "No env var found for GITHUB_OUTPUT, you must be running this code locally. Falling back to the deprecated print method." 2024-11-01T16:19:15.9461209Z  ) 2024-11-01T16:19:15.9461661Z  print(f"::set-output name={key}::{value}") 2024-11-01T16:19:15.9462137Z  return 2024-11-01T16:19:15.9462662Z  2024-11-01T16:19:15.9463052Z  with open(GITHUB_OUTPUT, "a") as f: 2024-11-01T16:19:15.9463585Z  log.info(f"Setting output: {key}='{value}'") 2024-11-01T16:19:15.9464117Z  f.write(f"{key}={value}\n") 2024-11-01T16:19:15.9464603Z  2024-11-01T16:19:15.9464862Z  2024-11-01T16:19:15.9465315Z def _str_comma_separated_to_set(value: str) -> FrozenSet[str]: 2024-11-01T16:19:15.9465920Z  return frozenset( 2024-11-01T16:19:15.9466464Z  filter(lambda itm: itm != "", map(str.strip, value.strip(" \n\t").split(","))) 2024-11-01T16:19:15.9467063Z  ) 2024-11-01T16:19:15.9467433Z  2024-11-01T16:19:15.9467687Z  2024-11-01T16:19:15.9468019Z def parse_args() -> Any: 2024-11-01T16:19:15.9468606Z  parser = ArgumentParser("Get dynamic rollout settings") 2024-11-01T16:19:15.9469323Z  parser.add_argument("--github-token", type=str, required=True, help="GitHub token") 2024-11-01T16:19:15.9469997Z  parser.add_argument( 2024-11-01T16:19:15.9470502Z  "--github-issue-repo", 2024-11-01T16:19:15.9470898Z  type=str, 2024-11-01T16:19:15.9471266Z  required=False, 2024-11-01T16:19:15.9471898Z  default="pytorch/test-infra", 2024-11-01T16:19:15.9472381Z  help="GitHub repo to get the issue", 2024-11-01T16:19:15.9472826Z  ) 2024-11-01T16:19:15.9473219Z  parser.add_argument( 2024-11-01T16:19:15.9473602Z  "--github-repo", 2024-11-01T16:19:15.9473989Z  type=str, 2024-11-01T16:19:15.9474447Z  required=True, 2024-11-01T16:19:15.9475030Z  help="GitHub repo where CI is running", 2024-11-01T16:19:15.9475470Z  ) 2024-11-01T16:19:15.9475900Z  parser.add_argument( 2024-11-01T16:19:15.9476475Z  "--github-issue", type=int, required=True, help="GitHub issue number" 2024-11-01T16:19:15.9477005Z  ) 2024-11-01T16:19:15.9477421Z  parser.add_argument( 2024-11-01T16:19:15.9478001Z  "--github-actor", type=str, required=True, help="GitHub triggering_actor" 2024-11-01T16:19:15.9478542Z  ) 2024-11-01T16:19:15.9478960Z  parser.add_argument( 2024-11-01T16:19:15.9479540Z  "--github-issue-owner", type=str, required=True, help="GitHub issue owner" 2024-11-01T16:19:15.9480104Z  ) 2024-11-01T16:19:15.9480493Z  parser.add_argument( 2024-11-01T16:19:15.9481101Z  "--github-branch", type=str, required=True, help="Current GitHub branch or tag" 2024-11-01T16:19:15.9481682Z  ) 2024-11-01T16:19:15.9482078Z  parser.add_argument( 2024-11-01T16:19:15.9482838Z  "--github-ref-type", 2024-11-01T16:19:15.9483229Z  type=str, 2024-11-01T16:19:15.9483684Z  required=True, 2024-11-01T16:19:15.9484152Z  help="Current GitHub ref type, branch or tag", 2024-11-01T16:19:15.9484650Z  ) 2024-11-01T16:19:15.9485003Z  parser.add_argument( 2024-11-01T16:19:15.9485448Z  "--eligible-experiments", 2024-11-01T16:19:15.9485923Z  type=_str_comma_separated_to_set, 2024-11-01T16:19:15.9486397Z  required=False, 2024-11-01T16:19:15.9486803Z  default="", 2024-11-01T16:19:15.9487553Z  help="comma separated list of experiments to check, if omitted all experiments marked with default=True are checked", 2024-11-01T16:19:15.9488345Z  ) 2024-11-01T16:19:15.9488667Z  2024-11-01T16:19:15.9489004Z  return parser.parse_args() 2024-11-01T16:19:15.9489437Z  2024-11-01T16:19:15.9489743Z  2024-11-01T16:19:15.9490127Z def get_gh_client(github_token: str) -> Github: 2024-11-01T16:19:15.9490869Z  auth = Auth.Token(github_token) 2024-11-01T16:19:15.9491313Z  return Github(auth=auth) 2024-11-01T16:19:15.9491700Z  2024-11-01T16:19:15.9492037Z  2024-11-01T16:19:15.9492479Z def get_issue(gh: Github, repo: str, issue_num: int) -> Issue: 2024-11-01T16:19:15.9493034Z  repo = gh.get_repo(repo) 2024-11-01T16:19:15.9493546Z  return repo.get_issue(number=issue_num) 2024-11-01T16:19:15.9493988Z  2024-11-01T16:19:15.9494278Z  2024-11-01T16:19:15.9494644Z def get_potential_pr_author( 2024-11-01T16:19:15.9495235Z  github_token: str, repo: str, username: str, ref_type: str, ref_name: str 2024-11-01T16:19:15.9495823Z ) -> str: 2024-11-01T16:19:15.9496401Z  # If the trigger was a new tag added by a bot, this is a ciflow case 2024-11-01T16:19:15.9497106Z  # Fetch the actual username from the original PR. The PR number is 2024-11-01T16:19:15.9497805Z  # embedded in the tag name: ciflow// 2024-11-01T16:19:15.9498369Z  2024-11-01T16:19:15.9498673Z  gh = get_gh_client(github_token) 2024-11-01T16:19:15.9499107Z  2024-11-01T16:19:15.9499579Z  if username == "pytorch-bot[bot]" and ref_type == "tag": 2024-11-01T16:19:15.9500105Z  split_tag = ref_name.split("/") 2024-11-01T16:19:15.9500557Z  if ( 2024-11-01T16:19:15.9500981Z  len(split_tag) == 3 2024-11-01T16:19:15.9501399Z  and split_tag[0] == "ciflow" 2024-11-01T16:19:15.9501899Z  and split_tag[2].isnumeric() 2024-11-01T16:19:15.9502391Z  ): 2024-11-01T16:19:15.9502929Z  pr_number = split_tag[2] 2024-11-01T16:19:15.9503441Z  try: 2024-11-01T16:19:15.9503823Z  repository = gh.get_repo(repo) 2024-11-01T16:19:15.9504412Z  pull = repository.get_pull(number=int(pr_number)) 2024-11-01T16:19:15.9505029Z  except Exception as e: 2024-11-01T16:19:15.9505483Z  raise Exception( # noqa: TRY002 2024-11-01T16:19:15.9506113Z  f"issue with pull request {pr_number} from repo {repository}" 2024-11-01T16:19:15.9506736Z  ) from e 2024-11-01T16:19:15.9507170Z  return pull.user.login 2024-11-01T16:19:15.9507675Z  # In all other cases, return the original input username 2024-11-01T16:19:15.9508255Z  return username 2024-11-01T16:19:15.9508629Z  2024-11-01T16:19:15.9508884Z  2024-11-01T16:19:15.9509337Z def is_exception_branch(branch: str) -> bool: 2024-11-01T16:19:15.9509816Z  """ 2024-11-01T16:19:15.9510365Z  Branches that get opted out of experiments by default, until they're explicitly enabled. 2024-11-01T16:19:15.9511087Z  """ 2024-11-01T16:19:15.9511608Z  return branch.split("/")[0] in {"main", "nightly", "release", "landchecks"} 2024-11-01T16:19:15.9512144Z  2024-11-01T16:19:15.9512512Z  2024-11-01T16:19:15.9512855Z def load_yaml(yaml_text: str) -> Any: 2024-11-01T16:19:15.9513248Z  try: 2024-11-01T16:19:15.9513697Z  data = yaml.safe_load(yaml_text) 2024-11-01T16:19:15.9514141Z  return data 2024-11-01T16:19:15.9514516Z  except yaml.YAMLError as exc: 2024-11-01T16:19:15.9515094Z  log.exception("Error loading YAML") 2024-11-01T16:19:15.9515543Z  raise 2024-11-01T16:19:15.9515874Z  2024-11-01T16:19:15.9516200Z  2024-11-01T16:19:15.9516718Z def extract_settings_user_opt_in_from_text(rollout_state: str) -> Tuple[str, str]: 2024-11-01T16:19:15.9517337Z  """ 2024-11-01T16:19:15.9518084Z  Extracts the text with settings, if any, and the opted in users from the rollout state. 2024-11-01T16:19:15.9518721Z  2024-11-01T16:19:15.9519225Z  If the issue body contains "---" then the text above that is the settings 2024-11-01T16:19:15.9519938Z  and the text below is the list of opted in users. 2024-11-01T16:19:15.9520420Z  2024-11-01T16:19:15.9520963Z  If it doesn't contain "---" then the settings are empty and the rest is the users. 2024-11-01T16:19:15.9521640Z  """ 2024-11-01T16:19:15.9522057Z  rollout_state_parts = rollout_state.split("---") 2024-11-01T16:19:15.9522939Z  if len(rollout_state_parts) >= 2: 2024-11-01T16:19:15.9523626Z  return rollout_state_parts[0], rollout_state_parts[1] 2024-11-01T16:19:15.9524135Z  else: 2024-11-01T16:19:15.9524495Z  return "", rollout_state 2024-11-01T16:19:15.9524968Z  2024-11-01T16:19:15.9525246Z  2024-11-01T16:19:15.9525604Z class UserOptins(Dict[str, List[str]]): 2024-11-01T16:19:15.9526117Z  """ 2024-11-01T16:19:15.9526586Z  Dictionary of users with a list of features they have opted into 2024-11-01T16:19:15.9527147Z  """ 2024-11-01T16:19:15.9527509Z  2024-11-01T16:19:15.9527780Z  2024-11-01T16:19:15.9528239Z def parse_user_opt_in_from_text(user_optin_text: str) -> UserOptins: 2024-11-01T16:19:15.9528866Z  """ 2024-11-01T16:19:15.9529496Z  Parse the user opt-in text into a key value pair of username and the list of features they have opted into 2024-11-01T16:19:15.9530217Z  2024-11-01T16:19:15.9531168Z  Users are GitHub usernames with the @ prefix. Each user is also a comma-separated list of features/experiments to enable. 2024-11-01T16:19:15.9532021Z  - Example line: "@User1,lf,split_build" 2024-11-01T16:19:15.9532639Z  - A "#" prefix indicates the user is opted out of all experiments 2024-11-01T16:19:15.9533272Z  2024-11-01T16:19:15.9533566Z  2024-11-01T16:19:15.9533820Z  """ 2024-11-01T16:19:15.9534239Z  optins = UserOptins() 2024-11-01T16:19:15.9534703Z  for user in user_optin_text.split("\n"): 2024-11-01T16:19:15.9535181Z  user = user.strip("\r\n\t -") 2024-11-01T16:19:15.9535744Z  if not user or not user.startswith("@"): 2024-11-01T16:19:15.9536244Z  # Not a valid user. Skip 2024-11-01T16:19:15.9536655Z  continue 2024-11-01T16:19:15.9537072Z  2024-11-01T16:19:15.9537370Z  if user: 2024-11-01T16:19:15.9537777Z  usr_name = user.split(",")[0].strip("@") 2024-11-01T16:19:15.9538467Z  optins[usr_name] = [exp.strip(" ") for exp in user.split(",")[1:]] 2024-11-01T16:19:15.9539023Z  2024-11-01T16:19:15.9539315Z  return optins 2024-11-01T16:19:15.9539726Z  2024-11-01T16:19:15.9540028Z  2024-11-01T16:19:15.9540425Z def parse_settings_from_text(settings_text: str) -> Settings: 2024-11-01T16:19:15.9541007Z  """ 2024-11-01T16:19:15.9541556Z  Parse the experiments from the issue body into a list of ExperimentSettings 2024-11-01T16:19:15.9542117Z  """ 2024-11-01T16:19:15.9542505Z  try: 2024-11-01T16:19:15.9542858Z  if settings_text: 2024-11-01T16:19:15.9543535Z  # Escape the backtick as well so that we can have the settings in a code block on the GH issue 2024-11-01T16:19:15.9544255Z  # for easy reading 2024-11-01T16:19:15.9545016Z  # Note: Using ascii for the backtick so that the cat step in _runner-determinator.yml doesn't choke on 2024-11-01T16:19:15.9545822Z  # the backtick character in shell commands. 2024-11-01T16:19:15.9546622Z  backtick = chr(96) # backtick character 2024-11-01T16:19:15.9547228Z  settings_text = settings_text.strip(f"\r\n\t{backtick} ") 2024-11-01T16:19:15.9547826Z  settings = load_yaml(settings_text) 2024-11-01T16:19:15.9548328Z  2024-11-01T16:19:15.9548868Z  # For now we just load experiments. We can expand this if/when we add more settings 2024-11-01T16:19:15.9549514Z  experiments = {} 2024-11-01T16:19:15.9549983Z  2024-11-01T16:19:15.9550444Z  for exp_name, exp_settings in settings.get(SETTING_EXPERIMENTS).items(): 2024-11-01T16:19:15.9551062Z  valid_settings = {} 2024-11-01T16:19:15.9551634Z  for setting in exp_settings: 2024-11-01T16:19:15.9552127Z  if setting not in Experiment._fields: 2024-11-01T16:19:15.9552647Z  log.warning( 2024-11-01T16:19:15.9553341Z  f"Unexpected setting in experiment: {setting} = {exp_settings[setting]}" 2024-11-01T16:19:15.9553942Z  ) 2024-11-01T16:19:15.9554307Z  else: 2024-11-01T16:19:15.9554901Z  valid_settings[setting] = exp_settings[setting] 2024-11-01T16:19:15.9555396Z  2024-11-01T16:19:15.9555792Z  experiments[exp_name] = Experiment(**valid_settings) 2024-11-01T16:19:15.9556413Z  return Settings(experiments) 2024-11-01T16:19:15.9556840Z  2024-11-01T16:19:15.9557133Z  except Exception: 2024-11-01T16:19:15.9557797Z  log.exception("Failed to parse settings") 2024-11-01T16:19:15.9558289Z  2024-11-01T16:19:15.9558562Z  return Settings() 2024-11-01T16:19:15.9559005Z  2024-11-01T16:19:15.9559317Z  2024-11-01T16:19:15.9559679Z def parse_settings(rollout_state: str) -> Settings: 2024-11-01T16:19:15.9560226Z  """ 2024-11-01T16:19:15.9560658Z  Parse settings, if any, from the rollout state. 2024-11-01T16:19:15.9561092Z  2024-11-01T16:19:15.9561639Z  If the issue body contains "---" then the text above that is the settings 2024-11-01T16:19:15.9562916Z  and the text below is the list of opted in users. 2024-11-01T16:19:15.9563399Z  2024-11-01T16:19:15.9564047Z  If it doesn't contain "---" then the settings are empty and the default values are used. 2024-11-01T16:19:15.9564672Z  """ 2024-11-01T16:19:15.9565224Z  settings_text, _ = extract_settings_user_opt_in_from_text(rollout_state) 2024-11-01T16:19:15.9565873Z  return parse_settings_from_text(settings_text) 2024-11-01T16:19:15.9566336Z  2024-11-01T16:19:15.9566683Z  2024-11-01T16:19:15.9567062Z def parse_users(rollout_state: str) -> UserOptins: 2024-11-01T16:19:15.9567542Z  """ 2024-11-01T16:19:15.9567975Z  Parse users from the rollout state. 2024-11-01T16:19:15.9568395Z  2024-11-01T16:19:15.9568683Z  """ 2024-11-01T16:19:15.9569247Z  _, users_text = extract_settings_user_opt_in_from_text(rollout_state) 2024-11-01T16:19:15.9569855Z  return parse_user_opt_in_from_text(users_text) 2024-11-01T16:19:15.9570316Z  2024-11-01T16:19:15.9570695Z  2024-11-01T16:19:15.9571199Z def is_user_opted_in(user: str, user_optins: UserOptins, experiment_name: str) -> bool: 2024-11-01T16:19:15.9571817Z  """ 2024-11-01T16:19:15.9572302Z  Check if a user is opted into an experiment 2024-11-01T16:19:15.9572737Z  """ 2024-11-01T16:19:15.9573156Z  return experiment_name in user_optins.get(user, []) 2024-11-01T16:19:15.9573720Z  2024-11-01T16:19:15.9574149Z  2024-11-01T16:19:15.9574484Z def get_runner_prefix( 2024-11-01T16:19:15.9574949Z  rollout_state: str, 2024-11-01T16:19:15.9575379Z  workflow_requestors: Iterable[str], 2024-11-01T16:19:15.9575805Z  branch: str, 2024-11-01T16:19:15.9576329Z  eligible_experiments: FrozenSet[str] = frozenset(), 2024-11-01T16:19:15.9576848Z  is_canary: bool = False, 2024-11-01T16:19:15.9577226Z ) -> str: 2024-11-01T16:19:15.9577682Z  settings = parse_settings(rollout_state) 2024-11-01T16:19:15.9578198Z  user_optins = parse_users(rollout_state) 2024-11-01T16:19:15.9578624Z  2024-11-01T16:19:15.9578996Z  fleet_prefix = "" 2024-11-01T16:19:15.9579400Z  prefixes = [] 2024-11-01T16:19:15.9579936Z  for experiment_name, experiment_settings in settings.experiments.items(): 2024-11-01T16:19:15.9580783Z  if not experiment_settings.all_branches and is_exception_branch(branch): 2024-11-01T16:19:15.9581398Z  log.info( 2024-11-01T16:19:15.9581989Z  f"Branch {branch} is an exception branch. Not enabling experiment {experiment_name}." 2024-11-01T16:19:15.9582696Z  ) 2024-11-01T16:19:15.9583062Z  continue 2024-11-01T16:19:15.9583420Z  2024-11-01T16:19:15.9583788Z  if eligible_experiments: 2024-11-01T16:19:15.9584330Z  if experiment_name not in eligible_experiments: 2024-11-01T16:19:15.9584905Z  exp_list = ", ".join(eligible_experiments) 2024-11-01T16:19:15.9585417Z  log.info( 2024-11-01T16:19:15.9586889Z  f"Skipping experiment '{experiment_name}', as it is not in the eligible_experiments list: {exp_list}" 2024-11-01T16:19:15.9587638Z  ) 2024-11-01T16:19:15.9588063Z  continue 2024-11-01T16:19:15.9588523Z  elif not experiment_settings.default: 2024-11-01T16:19:15.9588984Z  log.info( 2024-11-01T16:19:15.9589612Z  f"Skipping experiment '{experiment_name}', as it is not a default experiment" 2024-11-01T16:19:15.9590222Z  ) 2024-11-01T16:19:15.9590565Z  continue 2024-11-01T16:19:15.9590995Z  2024-11-01T16:19:15.9591385Z  # Is any workflow_requestor opted in to this experiment? 2024-11-01T16:19:15.9591936Z  opted_in_users = [ 2024-11-01T16:19:15.9592393Z  requestor 2024-11-01T16:19:15.9592808Z  for requestor in workflow_requestors 2024-11-01T16:19:15.9593431Z  if is_user_opted_in(requestor, user_optins, experiment_name) 2024-11-01T16:19:15.9594024Z  ] 2024-11-01T16:19:15.9594308Z  2024-11-01T16:19:15.9594634Z  enabled = False 2024-11-01T16:19:15.9595097Z  if opted_in_users: 2024-11-01T16:19:15.9595458Z  log.info( 2024-11-01T16:19:15.9596035Z  f"{', '.join(opted_in_users)} have opted into experiment {experiment_name}." 2024-11-01T16:19:15.9596679Z  ) 2024-11-01T16:19:15.9596995Z  enabled = True 2024-11-01T16:19:15.9597386Z  2024-11-01T16:19:15.9597828Z  elif experiment_settings.rollout_perc: 2024-11-01T16:19:15.9598548Z  # If no user is opted in, then we randomly enable the experiment based on the rollout percentage 2024-11-01T16:19:15.9599397Z  if random.uniform(0, 100) <= experiment_settings.rollout_perc: 2024-11-01T16:19:15.9600022Z  log.info( 2024-11-01T16:19:15.9600777Z  f"Based on rollout percentage of {experiment_settings.rollout_perc}%, enabling experiment {experiment_name}." 2024-11-01T16:19:15.9601616Z  ) 2024-11-01T16:19:15.9602066Z  enabled = True 2024-11-01T16:19:15.9602801Z  2024-11-01T16:19:15.9603083Z  if enabled: 2024-11-01T16:19:15.9603596Z  label = experiment_name 2024-11-01T16:19:15.9604113Z  if experiment_name == LF_FLEET_EXPERIMENT: 2024-11-01T16:19:15.9604823Z  # We give some special treatment to the "lf" experiment since determines the fleet we use 2024-11-01T16:19:15.9605717Z  # - If it's enabled, then we always list it's prefix first 2024-11-01T16:19:15.9606431Z  # - If we're in the canary branch, then we append ".c" to the lf prefix 2024-11-01T16:19:15.9607078Z  if is_canary: 2024-11-01T16:19:15.9607584Z  label += CANARY_FLEET_SUFFIX 2024-11-01T16:19:15.9608074Z  fleet_prefix = label 2024-11-01T16:19:15.9608500Z  else: 2024-11-01T16:19:15.9608944Z  prefixes.append(label) 2024-11-01T16:19:15.9609366Z  2024-11-01T16:19:15.9609697Z  if len(prefixes) > 1: 2024-11-01T16:19:15.9610123Z  log.error( 2024-11-01T16:19:15.9611031Z  f"Only a fleet and one other experiment can be enabled for a job at any time. Enabling {prefixes[0]} and ignoring the rest, which are {', '.join(prefixes[1:])}" 2024-11-01T16:19:15.9611968Z  ) 2024-11-01T16:19:15.9612387Z  prefixes = prefixes[:1] 2024-11-01T16:19:15.9612758Z  2024-11-01T16:19:15.9613096Z  # Fleet always comes first 2024-11-01T16:19:15.9613575Z  if fleet_prefix: 2024-11-01T16:19:15.9614145Z  prefixes.insert(0, fleet_prefix) 2024-11-01T16:19:15.9614613Z  2024-11-01T16:19:15.9615094Z  return ".".join(prefixes) + "." if prefixes else "" 2024-11-01T16:19:15.9615568Z  2024-11-01T16:19:15.9615853Z  2024-11-01T16:19:15.9616439Z def get_rollout_state_from_issue(github_token: str, repo: str, issue_num: int) -> str: 2024-11-01T16:19:15.9617043Z  """ 2024-11-01T16:19:15.9617593Z  Gets the first comment of the issue, which contains the desired rollout state. 2024-11-01T16:19:15.9618256Z  2024-11-01T16:19:15.9618757Z  The default issue we use - https://github.com/pytorch/test-infra/issues/5132 2024-11-01T16:19:15.9619348Z  """ 2024-11-01T16:19:15.9619786Z  gh = get_gh_client(github_token) 2024-11-01T16:19:15.9620296Z  issue = get_issue(gh, repo, issue_num) 2024-11-01T16:19:15.9620835Z  return str(issue.get_comments()[0].body.strip("\n\t ")) 2024-11-01T16:19:15.9621425Z  2024-11-01T16:19:15.9621714Z  2024-11-01T16:19:15.9621984Z def main() -> None: 2024-11-01T16:19:15.9622452Z  args = parse_args() 2024-11-01T16:19:15.9622832Z  2024-11-01T16:19:15.9623165Z  runner_label_prefix = DEFAULT_LABEL_PREFIX 2024-11-01T16:19:15.9623744Z  2024-11-01T16:19:15.9624036Z  try: 2024-11-01T16:19:15.9624409Z  rollout_state = get_rollout_state_from_issue( 2024-11-01T16:19:15.9625126Z  args.github_token, args.github_issue_repo, args.github_issue 2024-11-01T16:19:15.9625668Z  ) 2024-11-01T16:19:15.9625954Z  2024-11-01T16:19:15.9626392Z  username = get_potential_pr_author( 2024-11-01T16:19:15.9626862Z  args.github_token, 2024-11-01T16:19:15.9627247Z  args.github_repo, 2024-11-01T16:19:15.9627760Z  args.github_actor, 2024-11-01T16:19:15.9628209Z  args.github_ref_type, 2024-11-01T16:19:15.9628629Z  args.github_branch, 2024-11-01T16:19:15.9629323Z  ) 2024-11-01T16:19:15.9629640Z  2024-11-01T16:19:15.9630054Z  is_canary = args.github_repo == "pytorch/pytorch-canary" 2024-11-01T16:19:15.9630644Z  2024-11-01T16:19:15.9631035Z  runner_label_prefix = get_runner_prefix( 2024-11-01T16:19:15.9631472Z  rollout_state, 2024-11-01T16:19:15.9631994Z  (args.github_issue_owner, username), 2024-11-01T16:19:15.9632486Z  args.github_branch, 2024-11-01T16:19:15.9633003Z  args.eligible_experiments, 2024-11-01T16:19:15.9633410Z  is_canary, 2024-11-01T16:19:15.9633870Z  ) 2024-11-01T16:19:15.9634241Z  2024-11-01T16:19:15.9634543Z  except Exception as e: 2024-11-01T16:19:15.9634960Z  log.error( 2024-11-01T16:19:15.9635646Z  f"Failed to get issue. Defaulting to Meta runners and no experiments. Exception: {e}" 2024-11-01T16:19:15.9636274Z  ) 2024-11-01T16:19:15.9636585Z  2024-11-01T16:19:15.9637113Z  set_github_output(GH_OUTPUT_KEY_LABEL_TYPE, runner_label_prefix) 2024-11-01T16:19:15.9637639Z  2024-11-01T16:19:15.9637927Z  2024-11-01T16:19:15.9638307Z if __name__ == "__main__": 2024-11-01T16:19:15.9638695Z  main() 2024-11-01T16:19:15.9639018Z  2024-11-01T16:19:15.9639409Z EOF 2024-11-01T16:19:15.9639697Z  2024-11-01T16:19:15.9640013Z cat runner_determinator.py 2024-11-01T16:19:16.0291137Z shell: /usr/bin/bash -e {0} 2024-11-01T16:19:16.0292087Z env: 2024-11-01T16:19:16.0292982Z GITHUB_TOKEN: *** 2024-11-01T16:19:16.0293439Z ISSUE_NUMBER: 5132 2024-11-01T16:19:16.0294266Z TRIGGERING_ACTOR: pytorch-bot[bot] 2024-11-01T16:19:16.0294776Z ISSUE_OWNER: 2024-11-01T16:19:16.0295160Z CHECK_EXPERIMENTS: 2024-11-01T16:19:16.0295659Z ##[endgroup] 2024-11-01T16:19:16.0840016Z # flake8: noqa: G004 2024-11-01T16:19:16.0840382Z 2024-11-01T16:19:16.0841861Z # Note: Copies of this script in runner_determinator.py and _runner-determinator.yml 2024-11-01T16:19:16.0843422Z # must be kept in sync. You can do it easily by running the following command: 2024-11-01T16:19:16.0844181Z # python .github/scripts/update_runner_determinator.py 2024-11-01T16:19:16.0844540Z 2024-11-01T16:19:16.0844680Z """ 2024-11-01T16:19:16.0845207Z This runner determinator is used to determine which set of runners to run a 2024-11-01T16:19:16.0845972Z GitHub job on. It uses the first comment of a GitHub issue (by default 2024-11-01T16:19:16.0846852Z https://github.com/pytorch/test-infra/issues/5132) to define the configuration 2024-11-01T16:19:16.0847571Z of which runners should be used to run which job. 2024-11-01T16:19:16.0847936Z 2024-11-01T16:19:16.0848294Z The configuration has two parts, the settings and a list of opted-in users, 2024-11-01T16:19:16.0849058Z separated by a line containing "---". If the line is not present, the 2024-11-01T16:19:16.0849852Z settings are considered to be empty with only the second part, the user 2024-11-01T16:19:16.0850387Z list, defined. 2024-11-01T16:19:16.0850590Z 2024-11-01T16:19:16.0850887Z The first part is a YAML block that defines the rollout settings. This can be 2024-11-01T16:19:16.0851987Z used to define any settings that are needed to determine which runners to use. 2024-11-01T16:19:16.0852895Z It's fields are defined by the RolloutSettings class below. 2024-11-01T16:19:16.0853282Z 2024-11-01T16:19:16.0853586Z The second part is a list of users who are explicitly opted in to the LF fleet. 2024-11-01T16:19:16.0854416Z The user list is also a comma separated list of additional features or 2024-11-01T16:19:16.0855006Z experiments which the user could be opted in to. 2024-11-01T16:19:16.0855350Z 2024-11-01T16:19:16.0855495Z The user list has the following rules: 2024-11-01T16:19:16.0855879Z 2024-11-01T16:19:16.0856181Z - Users are GitHub usernames, which must start with the @ prefix 2024-11-01T16:19:16.0857217Z - Each user is also a comma-separated list of features/experiments to enable 2024-11-01T16:19:16.0857856Z - A "#" prefix opts the user out of all experiments 2024-11-01T16:19:16.0858305Z 2024-11-01T16:19:16.0858427Z Example config: 2024-11-01T16:19:16.0858817Z # A list of experiments that can be opted into. 2024-11-01T16:19:16.0859406Z # This defines the behavior they'll induce when opted into. 2024-11-01T16:19:16.0860048Z # Expected syntax is: 2024-11-01T16:19:16.0860576Z # [experiment_name]: # Name of the experiment. Also used for the label prefix. 2024-11-01T16:19:16.0861356Z # rollout_perc: [int] # % of workflows to run with this experiment when users are not opted in. 2024-11-01T16:19:16.0861939Z 2024-11-01T16:19:16.0862067Z experiments: 2024-11-01T16:19:16.0862382Z lf: 2024-11-01T16:19:16.0862670Z rollout_percent: 25 2024-11-01T16:19:16.0863107Z all_branches: false 2024-11-01T16:19:16.0863466Z default: true 2024-11-01T16:19:16.0863803Z --- 2024-11-01T16:19:16.0864094Z 2024-11-01T16:19:16.0864260Z # Opt-ins: 2024-11-01T16:19:16.0864780Z # Users can opt into the LF fleet by adding their GitHub username to this list 2024-11-01T16:19:16.0865665Z # and specifying experiments to enable in a comma-separated list. 2024-11-01T16:19:16.0866217Z # Experiments should be from the above list. 2024-11-01T16:19:16.0866543Z 2024-11-01T16:19:16.0866687Z @User1,lf,split_build 2024-11-01T16:19:16.0867101Z @User2,lf 2024-11-01T16:19:16.0867383Z @User3,split_build 2024-11-01T16:19:16.0867723Z """ 2024-11-01T16:19:16.0867864Z 2024-11-01T16:19:16.0868076Z import logging 2024-11-01T16:19:16.0868349Z import os 2024-11-01T16:19:16.0868659Z import random 2024-11-01T16:19:16.0869259Z from argparse import ArgumentParser 2024-11-01T16:19:16.0869707Z from logging import LogRecord 2024-11-01T16:19:16.0870258Z from typing import Any, Dict, FrozenSet, Iterable, List, NamedTuple, Tuple 2024-11-01T16:19:16.0870701Z 2024-11-01T16:19:16.0870934Z import yaml 2024-11-01T16:19:16.0871246Z from github import Auth, Github 2024-11-01T16:19:16.0871647Z from github.Issue import Issue 2024-11-01T16:19:16.0871875Z 2024-11-01T16:19:16.0871881Z 2024-11-01T16:19:16.0872151Z DEFAULT_LABEL_PREFIX = "" # use meta runners 2024-11-01T16:19:16.0872700Z WORKFLOW_LABEL_LF = "lf." # use runners from the linux foundation 2024-11-01T16:19:16.0873411Z WORKFLOW_LABEL_LF_CANARY = "lf.c." # use canary runners from the linux foundation 2024-11-01T16:19:16.0873838Z 2024-11-01T16:19:16.0874113Z GITHUB_OUTPUT = os.getenv("GITHUB_OUTPUT", "") 2024-11-01T16:19:16.0874635Z GH_OUTPUT_KEY_AMI = "runner-ami" 2024-11-01T16:19:16.0875097Z GH_OUTPUT_KEY_LABEL_TYPE = "label-type" 2024-11-01T16:19:16.0875411Z 2024-11-01T16:19:16.0875432Z 2024-11-01T16:19:16.0875678Z SETTING_EXPERIMENTS = "experiments" 2024-11-01T16:19:16.0875951Z 2024-11-01T16:19:16.0876116Z LF_FLEET_EXPERIMENT = "lf" 2024-11-01T16:19:16.0876469Z CANARY_FLEET_SUFFIX = ".c" 2024-11-01T16:19:16.0876709Z 2024-11-01T16:19:16.0876714Z 2024-11-01T16:19:16.0876952Z class Experiment(NamedTuple): 2024-11-01T16:19:16.0877349Z rollout_perc: float = ( 2024-11-01T16:19:16.0877934Z 0 # Percentage of workflows to experiment on when user is not opted-in. 2024-11-01T16:19:16.0878575Z ) 2024-11-01T16:19:16.0878883Z all_branches: bool = ( 2024-11-01T16:19:16.0879371Z False # If True, the experiment is also enabled on the exception branches 2024-11-01T16:19:16.0880019Z ) 2024-11-01T16:19:16.0880319Z default: bool = ( 2024-11-01T16:19:16.0880763Z True # If True, the experiment is enabled by default for all queries 2024-11-01T16:19:16.0881397Z ) 2024-11-01T16:19:16.0881547Z 2024-11-01T16:19:16.0881730Z # Add more fields as needed 2024-11-01T16:19:16.0881971Z 2024-11-01T16:19:16.0881975Z 2024-11-01T16:19:16.0882124Z class Settings(NamedTuple): 2024-11-01T16:19:16.0883314Z """ 2024-11-01T16:19:16.0884127Z Settings for the experiments that can be opted into. 2024-11-01T16:19:16.0884606Z """ 2024-11-01T16:19:16.0884791Z 2024-11-01T16:19:16.0885055Z experiments: Dict[str, Experiment] = {} 2024-11-01T16:19:16.0885386Z 2024-11-01T16:19:16.0885390Z 2024-11-01T16:19:16.0885549Z class ColorFormatter(logging.Formatter): 2024-11-01T16:19:16.0886111Z """Color codes the log messages based on the log level""" 2024-11-01T16:19:16.0886442Z 2024-11-01T16:19:16.0886634Z COLORS = { 2024-11-01T16:19:16.0887001Z "WARNING": "\033[33m", # Yellow 2024-11-01T16:19:16.0887429Z "ERROR": "\033[31m", # Red 2024-11-01T16:19:16.0887869Z "CRITICAL": "\033[31m", # Red 2024-11-01T16:19:16.0888311Z "INFO": "\033[0m", # Reset 2024-11-01T16:19:16.0888700Z "DEBUG": "\033[0m", # Reset 2024-11-01T16:19:16.0889132Z } 2024-11-01T16:19:16.0889336Z 2024-11-01T16:19:16.0889740Z def format(self, record: LogRecord) -> str: 2024-11-01T16:19:16.0890443Z log_color = self.COLORS.get(record.levelname, "\033[0m") # Default to reset 2024-11-01T16:19:16.0891124Z record.msg = f"{log_color}{record.msg}\033[0m" 2024-11-01T16:19:16.0891617Z return super().format(record) 2024-11-01T16:19:16.0891866Z 2024-11-01T16:19:16.0891871Z 2024-11-01T16:19:16.0892054Z handler = logging.StreamHandler() 2024-11-01T16:19:16.0892778Z handler.setFormatter(ColorFormatter(fmt="%(levelname)-8s: %(message)s")) 2024-11-01T16:19:16.0893191Z 2024-11-01T16:19:16.0893385Z log = logging.getLogger(os.path.basename(__file__)) 2024-11-01T16:19:16.0893854Z log.addHandler(handler) 2024-11-01T16:19:16.0894295Z log.setLevel(logging.INFO) 2024-11-01T16:19:16.0894510Z 2024-11-01T16:19:16.0894515Z 2024-11-01T16:19:16.0894773Z def set_github_output(key: str, value: str) -> None: 2024-11-01T16:19:16.0895220Z """ 2024-11-01T16:19:16.0895900Z Defines outputs of the github action that invokes this script 2024-11-01T16:19:16.0896390Z """ 2024-11-01T16:19:16.0896691Z if not GITHUB_OUTPUT: 2024-11-01T16:19:16.0897805Z # See https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/ for deprecation notice 2024-11-01T16:19:16.0898683Z log.warning( 2024-11-01T16:19:16.0899407Z "No env var found for GITHUB_OUTPUT, you must be running this code locally. Falling back to the deprecated print method." 2024-11-01T16:19:16.0900244Z ) 2024-11-01T16:19:16.0926665Z print(f"::set-output name={key}::{value}") 2024-11-01T16:19:16.0927216Z return 2024-11-01T16:19:16.0927541Z 2024-11-01T16:19:16.0927711Z with open(GITHUB_OUTPUT, "a") as f: 2024-11-01T16:19:16.0928258Z log.info(f"Setting output: {key}='{value}'") 2024-11-01T16:19:16.0928739Z f.write(f"{key}={value}\n") 2024-11-01T16:19:16.0929066Z 2024-11-01T16:19:16.0929090Z 2024-11-01T16:19:16.0929380Z def _str_comma_separated_to_set(value: str) -> FrozenSet[str]: 2024-11-01T16:19:16.0929908Z return frozenset( 2024-11-01T16:19:16.0930440Z filter(lambda itm: itm != "", map(str.strip, value.strip(" \n\t").split(","))) 2024-11-01T16:19:16.0931033Z ) 2024-11-01T16:19:16.0931216Z 2024-11-01T16:19:16.0931221Z 2024-11-01T16:19:16.0931404Z def parse_args() -> Any: 2024-11-01T16:19:16.0931867Z parser = ArgumentParser("Get dynamic rollout settings") 2024-11-01T16:19:16.0932700Z parser.add_argument("--github-token", type=str, required=True, help="GitHub token") 2024-11-01T16:19:16.0933338Z parser.add_argument( 2024-11-01T16:19:16.0933756Z "--github-issue-repo", 2024-11-01T16:19:16.0934199Z type=str, 2024-11-01T16:19:16.0934549Z required=False, 2024-11-01T16:19:16.0934965Z default="pytorch/test-infra", 2024-11-01T16:19:16.0935456Z help="GitHub repo to get the issue", 2024-11-01T16:19:16.0935890Z ) 2024-11-01T16:19:16.0936200Z parser.add_argument( 2024-11-01T16:19:16.0936625Z "--github-repo", 2024-11-01T16:19:16.0936991Z type=str, 2024-11-01T16:19:16.0937317Z required=True, 2024-11-01T16:19:16.0938081Z help="GitHub repo where CI is running", 2024-11-01T16:19:16.0938578Z ) 2024-11-01T16:19:16.0938891Z parser.add_argument( 2024-11-01T16:19:16.0939533Z "--github-issue", type=int, required=True, help="GitHub issue number" 2024-11-01T16:19:16.0940071Z ) 2024-11-01T16:19:16.0940392Z parser.add_argument( 2024-11-01T16:19:16.0941025Z "--github-actor", type=str, required=True, help="GitHub triggering_actor" 2024-11-01T16:19:16.0941586Z ) 2024-11-01T16:19:16.0941901Z parser.add_argument( 2024-11-01T16:19:16.0942525Z "--github-issue-owner", type=str, required=True, help="GitHub issue owner" 2024-11-01T16:19:16.0943083Z ) 2024-11-01T16:19:16.0943397Z parser.add_argument( 2024-11-01T16:19:16.0944050Z "--github-branch", type=str, required=True, help="Current GitHub branch or tag" 2024-11-01T16:19:16.0944628Z ) 2024-11-01T16:19:16.0944958Z parser.add_argument( 2024-11-01T16:19:16.0945418Z "--github-ref-type", 2024-11-01T16:19:16.0945795Z type=str, 2024-11-01T16:19:16.0946135Z required=True, 2024-11-01T16:19:16.0946579Z help="Current GitHub ref type, branch or tag", 2024-11-01T16:19:16.0947025Z ) 2024-11-01T16:19:16.0947341Z parser.add_argument( 2024-11-01T16:19:16.0947777Z "--eligible-experiments", 2024-11-01T16:19:16.0948217Z type=_str_comma_separated_to_set, 2024-11-01T16:19:16.0948634Z required=False, 2024-11-01T16:19:16.0949014Z default="", 2024-11-01T16:19:16.0949729Z help="comma separated list of experiments to check, if omitted all experiments marked with default=True are checked", 2024-11-01T16:19:16.0950462Z ) 2024-11-01T16:19:16.0950685Z 2024-11-01T16:19:16.0950822Z return parser.parse_args() 2024-11-01T16:19:16.0951104Z 2024-11-01T16:19:16.0951294Z 2024-11-01T16:19:16.0951533Z def get_gh_client(github_token: str) -> Github: 2024-11-01T16:19:16.0952004Z auth = Auth.Token(github_token) 2024-11-01T16:19:16.0952517Z return Github(auth=auth) 2024-11-01T16:19:16.0952740Z 2024-11-01T16:19:16.0952745Z 2024-11-01T16:19:16.0953037Z def get_issue(gh: Github, repo: str, issue_num: int) -> Issue: 2024-11-01T16:19:16.0953555Z repo = gh.get_repo(repo) 2024-11-01T16:19:16.0954053Z return repo.get_issue(number=issue_num) 2024-11-01T16:19:16.0954332Z 2024-11-01T16:19:16.0954337Z 2024-11-01T16:19:16.0954466Z def get_potential_pr_author( 2024-11-01T16:19:16.0954992Z github_token: str, repo: str, username: str, ref_type: str, ref_name: str 2024-11-01T16:19:16.0955641Z ) -> str: 2024-11-01T16:19:16.0956082Z # If the trigger was a new tag added by a bot, this is a ciflow case 2024-11-01T16:19:16.0956774Z # Fetch the actual username from the original PR. The PR number is 2024-11-01T16:19:16.0957559Z # embedded in the tag name: ciflow// 2024-11-01T16:19:16.0957899Z 2024-11-01T16:19:16.0958077Z gh = get_gh_client(github_token) 2024-11-01T16:19:16.0958333Z 2024-11-01T16:19:16.0958605Z if username == "pytorch-bot[bot]" and ref_type == "tag": 2024-11-01T16:19:16.0959225Z split_tag = ref_name.split("/") 2024-11-01T16:19:16.0959630Z if ( 2024-11-01T16:19:16.0959931Z len(split_tag) == 3 2024-11-01T16:19:16.0960398Z and split_tag[0] == "ciflow" 2024-11-01T16:19:16.0960824Z and split_tag[2].isnumeric() 2024-11-01T16:19:16.0961193Z ): 2024-11-01T16:19:16.0961578Z pr_number = split_tag[2] 2024-11-01T16:19:16.0961980Z try: 2024-11-01T16:19:16.0962690Z repository = gh.get_repo(repo) 2024-11-01T16:19:16.0963596Z pull = repository.get_pull(number=int(pr_number)) 2024-11-01T16:19:16.0964104Z except Exception as e: 2024-11-01T16:19:16.0964531Z raise Exception( # noqa: TRY002 2024-11-01T16:19:16.0965183Z f"issue with pull request {pr_number} from repo {repository}" 2024-11-01T16:19:16.0965726Z ) from e 2024-11-01T16:19:16.0966275Z return pull.user.login 2024-11-01T16:19:16.0966838Z # In all other cases, return the original input username 2024-11-01T16:19:16.0967339Z return username 2024-11-01T16:19:16.0967525Z 2024-11-01T16:19:16.0967530Z 2024-11-01T16:19:16.0967769Z def is_exception_branch(branch: str) -> bool: 2024-11-01T16:19:16.0968282Z """ 2024-11-01T16:19:16.0968906Z Branches that get opted out of experiments by default, until they're explicitly enabled. 2024-11-01T16:19:16.0969486Z """ 2024-11-01T16:19:16.0970014Z return branch.split("/")[0] in {"main", "nightly", "release", "landchecks"} 2024-11-01T16:19:16.0970446Z 2024-11-01T16:19:16.0970488Z 2024-11-01T16:19:16.0970670Z def load_yaml(yaml_text: str) -> Any: 2024-11-01T16:19:16.0971129Z try: 2024-11-01T16:19:16.0971442Z data = yaml.safe_load(yaml_text) 2024-11-01T16:19:16.0971846Z return data 2024-11-01T16:19:16.0972259Z except yaml.YAMLError as exc: 2024-11-01T16:19:16.0972683Z log.exception("Error loading YAML") 2024-11-01T16:19:16.0973109Z raise 2024-11-01T16:19:16.0973272Z 2024-11-01T16:19:16.0973277Z 2024-11-01T16:19:16.0973753Z def extract_settings_user_opt_in_from_text(rollout_state: str) -> Tuple[str, str]: 2024-11-01T16:19:16.0974317Z """ 2024-11-01T16:19:16.0974834Z Extracts the text with settings, if any, and the opted in users from the rollout state. 2024-11-01T16:19:16.0975301Z 2024-11-01T16:19:16.0975746Z If the issue body contains "---" then the text above that is the settings 2024-11-01T16:19:16.0976361Z and the text below is the list of opted in users. 2024-11-01T16:19:16.0976713Z 2024-11-01T16:19:16.0977086Z If it doesn't contain "---" then the settings are empty and the rest is the users. 2024-11-01T16:19:16.0977739Z """ 2024-11-01T16:19:16.0978281Z rollout_state_parts = rollout_state.split("---") 2024-11-01T16:19:16.0978772Z if len(rollout_state_parts) >= 2: 2024-11-01T16:19:16.0979348Z return rollout_state_parts[0], rollout_state_parts[1] 2024-11-01T16:19:16.0979822Z else: 2024-11-01T16:19:16.0980099Z return "", rollout_state 2024-11-01T16:19:16.0980381Z 2024-11-01T16:19:16.0980387Z 2024-11-01T16:19:16.0980615Z class UserOptins(Dict[str, List[str]]): 2024-11-01T16:19:16.0981026Z """ 2024-11-01T16:19:16.0981420Z Dictionary of users with a list of features they have opted into 2024-11-01T16:19:16.0982015Z """ 2024-11-01T16:19:16.0982161Z 2024-11-01T16:19:16.0982166Z 2024-11-01T16:19:16.0982514Z def parse_user_opt_in_from_text(user_optin_text: str) -> UserOptins: 2024-11-01T16:19:16.0983007Z """ 2024-11-01T16:19:16.0983748Z Parse the user opt-in text into a key value pair of username and the list of features they have opted into 2024-11-01T16:19:16.0984297Z 2024-11-01T16:19:16.0984907Z Users are GitHub usernames with the @ prefix. Each user is also a comma-separated list of features/experiments to enable. 2024-11-01T16:19:16.0985742Z - Example line: "@User1,lf,split_build" 2024-11-01T16:19:16.0986427Z - A "#" prefix indicates the user is opted out of all experiments 2024-11-01T16:19:16.0986835Z 2024-11-01T16:19:16.0986840Z 2024-11-01T16:19:16.0986947Z """ 2024-11-01T16:19:16.0987265Z optins = UserOptins() 2024-11-01T16:19:16.0987720Z for user in user_optin_text.split("\n"): 2024-11-01T16:19:16.0988216Z user = user.strip("\r\n\t -") 2024-11-01T16:19:16.0988699Z if not user or not user.startswith("@"): 2024-11-01T16:19:16.0989204Z # Not a valid user. Skip 2024-11-01T16:19:16.0989620Z continue 2024-11-01T16:19:16.0989806Z 2024-11-01T16:19:16.0989952Z if user: 2024-11-01T16:19:16.0990347Z usr_name = user.split(",")[0].strip("@") 2024-11-01T16:19:16.0990961Z optins[usr_name] = [exp.strip(" ") for exp in user.split(",")[1:]] 2024-11-01T16:19:16.0991348Z 2024-11-01T16:19:16.0991503Z return optins 2024-11-01T16:19:16.0991681Z 2024-11-01T16:19:16.0991686Z 2024-11-01T16:19:16.0992031Z def parse_settings_from_text(settings_text: str) -> Settings: 2024-11-01T16:19:16.0992707Z """ 2024-11-01T16:19:16.0993202Z Parse the experiments from the issue body into a list of ExperimentSettings 2024-11-01T16:19:16.0993809Z """ 2024-11-01T16:19:16.0994162Z try: 2024-11-01T16:19:16.0994467Z if settings_text: 2024-11-01T16:19:16.0995143Z # Escape the backtick as well so that we can have the settings in a code block on the GH issue 2024-11-01T16:19:16.0995796Z # for easy reading 2024-11-01T16:19:16.0996537Z # Note: Using ascii for the backtick so that the cat step in _runner-determinator.yml doesn't choke on 2024-11-01T16:19:16.0997365Z # the backtick character in shell commands. 2024-11-01T16:19:16.0997847Z backtick = chr(96) # backtick character 2024-11-01T16:19:16.0998392Z settings_text = settings_text.strip(f"\r\n\t{backtick} ") 2024-11-01T16:19:16.0999011Z settings = load_yaml(settings_text) 2024-11-01T16:19:16.0999297Z 2024-11-01T16:19:16.0999627Z # For now we just load experiments. We can expand this if/when we add more settings 2024-11-01T16:19:16.1000245Z experiments = {} 2024-11-01T16:19:16.1000482Z 2024-11-01T16:19:16.1000865Z for exp_name, exp_settings in settings.get(SETTING_EXPERIMENTS).items(): 2024-11-01T16:19:16.1001402Z valid_settings = {} 2024-11-01T16:19:16.1001843Z for setting in exp_settings: 2024-11-01T16:19:16.1002667Z if setting not in Experiment._fields: 2024-11-01T16:19:16.1003116Z log.warning( 2024-11-01T16:19:16.1003711Z f"Unexpected setting in experiment: {setting} = {exp_settings[setting]}" 2024-11-01T16:19:16.1004359Z ) 2024-11-01T16:19:16.1004898Z else: 2024-11-01T16:19:16.1005319Z valid_settings[setting] = exp_settings[setting] 2024-11-01T16:19:16.1005755Z 2024-11-01T16:19:16.1005979Z experiments[exp_name] = Experiment(**valid_settings) 2024-11-01T16:19:16.1006514Z return Settings(experiments) 2024-11-01T16:19:16.1006783Z 2024-11-01T16:19:16.1006906Z except Exception: 2024-11-01T16:19:16.1007394Z log.exception("Failed to parse settings") 2024-11-01T16:19:16.1007697Z 2024-11-01T16:19:16.1007869Z return Settings() 2024-11-01T16:19:16.1008060Z 2024-11-01T16:19:16.1008065Z 2024-11-01T16:19:16.1008318Z def parse_settings(rollout_state: str) -> Settings: 2024-11-01T16:19:16.1008858Z """ 2024-11-01T16:19:16.1009233Z Parse settings, if any, from the rollout state. 2024-11-01T16:19:16.1009536Z 2024-11-01T16:19:16.1009908Z If the issue body contains "---" then the text above that is the settings 2024-11-01T16:19:16.1010580Z and the text below is the list of opted in users. 2024-11-01T16:19:16.1010946Z 2024-11-01T16:19:16.1011346Z If it doesn't contain "---" then the settings are empty and the default values are used. 2024-11-01T16:19:16.1011942Z """ 2024-11-01T16:19:16.1012418Z settings_text, _ = extract_settings_user_opt_in_from_text(rollout_state) 2024-11-01T16:19:16.1013039Z return parse_settings_from_text(settings_text) 2024-11-01T16:19:16.1013339Z 2024-11-01T16:19:16.1013344Z 2024-11-01T16:19:16.1013606Z def parse_users(rollout_state: str) -> UserOptins: 2024-11-01T16:19:16.1014109Z """ 2024-11-01T16:19:16.1014429Z Parse users from the rollout state. 2024-11-01T16:19:16.1014690Z 2024-11-01T16:19:16.1014833Z """ 2024-11-01T16:19:16.1015302Z _, users_text = extract_settings_user_opt_in_from_text(rollout_state) 2024-11-01T16:19:16.1015883Z return parse_user_opt_in_from_text(users_text) 2024-11-01T16:19:16.1016209Z 2024-11-01T16:19:16.1016215Z 2024-11-01T16:19:16.1016616Z def is_user_opted_in(user: str, user_optins: UserOptins, experiment_name: str) -> bool: 2024-11-01T16:19:16.1017287Z """ 2024-11-01T16:19:16.1017596Z Check if a user is opted into an experiment 2024-11-01T16:19:16.1018204Z """ 2024-11-01T16:19:16.1018660Z return experiment_name in user_optins.get(user, []) 2024-11-01T16:19:16.1018986Z 2024-11-01T16:19:16.1018991Z 2024-11-01T16:19:16.1019113Z def get_runner_prefix( 2024-11-01T16:19:16.1019483Z rollout_state: str, 2024-11-01T16:19:16.1019920Z workflow_requestors: Iterable[str], 2024-11-01T16:19:16.1020293Z branch: str, 2024-11-01T16:19:16.1020705Z eligible_experiments: FrozenSet[str] = frozenset(), 2024-11-01T16:19:16.1021244Z is_canary: bool = False, 2024-11-01T16:19:16.1021596Z ) -> str: 2024-11-01T16:19:16.1021958Z settings = parse_settings(rollout_state) 2024-11-01T16:19:16.1022493Z user_optins = parse_users(rollout_state) 2024-11-01T16:19:16.1022772Z 2024-11-01T16:19:16.1022893Z fleet_prefix = "" 2024-11-01T16:19:16.1023257Z prefixes = [] 2024-11-01T16:19:16.1023837Z for experiment_name, experiment_settings in settings.experiments.items(): 2024-11-01T16:19:16.1024542Z if not experiment_settings.all_branches and is_exception_branch(branch): 2024-11-01T16:19:16.1025103Z log.info( 2024-11-01T16:19:16.1025742Z f"Branch {branch} is an exception branch. Not enabling experiment {experiment_name}." 2024-11-01T16:19:16.1026328Z ) 2024-11-01T16:19:16.1026629Z continue 2024-11-01T16:19:16.1026877Z 2024-11-01T16:19:16.1027051Z if eligible_experiments: 2024-11-01T16:19:16.1027500Z if experiment_name not in eligible_experiments: 2024-11-01T16:19:16.1028029Z exp_list = ", ".join(eligible_experiments) 2024-11-01T16:19:16.1028576Z log.info( 2024-11-01T16:19:16.1029309Z f"Skipping experiment '{experiment_name}', as it is not in the eligible_experiments list: {exp_list}" 2024-11-01T16:19:16.1029928Z ) 2024-11-01T16:19:16.1030469Z continue 2024-11-01T16:19:16.1030883Z elif not experiment_settings.default: 2024-11-01T16:19:16.1031282Z log.info( 2024-11-01T16:19:16.1031976Z f"Skipping experiment '{experiment_name}', as it is not a default experiment" 2024-11-01T16:19:16.1032544Z ) 2024-11-01T16:19:16.1032812Z continue 2024-11-01T16:19:16.1033114Z 2024-11-01T16:19:16.1033332Z # Is any workflow_requestor opted in to this experiment? 2024-11-01T16:19:16.1033831Z opted_in_users = [ 2024-11-01T16:19:16.1034147Z requestor 2024-11-01T16:19:16.1034602Z for requestor in workflow_requestors 2024-11-01T16:19:16.1035143Z if is_user_opted_in(requestor, user_optins, experiment_name) 2024-11-01T16:19:16.1035620Z ] 2024-11-01T16:19:16.1035877Z 2024-11-01T16:19:16.1035999Z enabled = False 2024-11-01T16:19:16.1036352Z if opted_in_users: 2024-11-01T16:19:16.1036691Z log.info( 2024-11-01T16:19:16.1037327Z f"{', '.join(opted_in_users)} have opted into experiment {experiment_name}." 2024-11-01T16:19:16.1037871Z ) 2024-11-01T16:19:16.1038171Z enabled = True 2024-11-01T16:19:16.1038471Z 2024-11-01T16:19:16.1038684Z elif experiment_settings.rollout_perc: 2024-11-01T16:19:16.1039389Z # If no user is opted in, then we randomly enable the experiment based on the rollout percentage 2024-11-01T16:19:16.1040148Z if random.uniform(0, 100) <= experiment_settings.rollout_perc: 2024-11-01T16:19:16.1040751Z log.info( 2024-11-01T16:19:16.1041447Z f"Based on rollout percentage of {experiment_settings.rollout_perc}%, enabling experiment {experiment_name}." 2024-11-01T16:19:16.1042799Z ) 2024-11-01T16:19:16.1043150Z enabled = True 2024-11-01T16:19:16.1043413Z 2024-11-01T16:19:16.1043551Z if enabled: 2024-11-01T16:19:16.1043992Z label = experiment_name 2024-11-01T16:19:16.1044422Z if experiment_name == LF_FLEET_EXPERIMENT: 2024-11-01T16:19:16.1045129Z # We give some special treatment to the "lf" experiment since determines the fleet we use 2024-11-01T16:19:16.1046265Z # - If it's enabled, then we always list it's prefix first 2024-11-01T16:19:16.1046981Z # - If we're in the canary branch, then we append ".c" to the lf prefix 2024-11-01T16:19:16.1047568Z if is_canary: 2024-11-01T16:19:16.1048039Z label += CANARY_FLEET_SUFFIX 2024-11-01T16:19:16.1048466Z fleet_prefix = label 2024-11-01T16:19:16.1048858Z else: 2024-11-01T16:19:16.1049285Z prefixes.append(label) 2024-11-01T16:19:16.1049546Z 2024-11-01T16:19:16.1049693Z if len(prefixes) > 1: 2024-11-01T16:19:16.1050055Z log.error( 2024-11-01T16:19:16.1051114Z f"Only a fleet and one other experiment can be enabled for a job at any time. Enabling {prefixes[0]} and ignoring the rest, which are {', '.join(prefixes[1:])}" 2024-11-01T16:19:16.1052000Z ) 2024-11-01T16:19:16.1052318Z prefixes = prefixes[:1] 2024-11-01T16:19:16.1052594Z 2024-11-01T16:19:16.1052799Z # Fleet always comes first 2024-11-01T16:19:16.1053201Z if fleet_prefix: 2024-11-01T16:19:16.1053535Z prefixes.insert(0, fleet_prefix) 2024-11-01T16:19:16.1053838Z 2024-11-01T16:19:16.1054114Z return ".".join(prefixes) + "." if prefixes else "" 2024-11-01T16:19:16.1054431Z 2024-11-01T16:19:16.1054436Z 2024-11-01T16:19:16.1054855Z def get_rollout_state_from_issue(github_token: str, repo: str, issue_num: int) -> str: 2024-11-01T16:19:16.1055420Z """ 2024-11-01T16:19:16.1056130Z Gets the first comment of the issue, which contains the desired rollout state. 2024-11-01T16:19:16.1056565Z 2024-11-01T16:19:16.1056998Z The default issue we use - https://github.com/pytorch/test-infra/issues/5132 2024-11-01T16:19:16.1057530Z """ 2024-11-01T16:19:16.1058369Z gh = get_gh_client(github_token) 2024-11-01T16:19:16.1058845Z issue = get_issue(gh, repo, issue_num) 2024-11-01T16:19:16.1059348Z return str(issue.get_comments()[0].body.strip("\n\t ")) 2024-11-01T16:19:16.1059723Z 2024-11-01T16:19:16.1059727Z 2024-11-01T16:19:16.1060246Z def main() -> None: 2024-11-01T16:19:16.1060648Z args = parse_args() 2024-11-01T16:19:16.1060859Z 2024-11-01T16:19:16.1061080Z runner_label_prefix = DEFAULT_LABEL_PREFIX 2024-11-01T16:19:16.1061368Z 2024-11-01T16:19:16.1061553Z try: 2024-11-01T16:19:16.1061931Z rollout_state = get_rollout_state_from_issue( 2024-11-01T16:19:16.1062522Z args.github_token, args.github_issue_repo, args.github_issue 2024-11-01T16:19:16.1063056Z ) 2024-11-01T16:19:16.1063252Z 2024-11-01T16:19:16.1063406Z username = get_potential_pr_author( 2024-11-01T16:19:16.1063858Z args.github_token, 2024-11-01T16:19:16.1064267Z args.github_repo, 2024-11-01T16:19:16.1064670Z args.github_actor, 2024-11-01T16:19:16.1065048Z args.github_ref_type, 2024-11-01T16:19:16.1065472Z args.github_branch, 2024-11-01T16:19:16.1065863Z ) 2024-11-01T16:19:16.1066015Z 2024-11-01T16:19:16.1066355Z is_canary = args.github_repo == "pytorch/pytorch-canary" 2024-11-01T16:19:16.1066698Z 2024-11-01T16:19:16.1066935Z runner_label_prefix = get_runner_prefix( 2024-11-01T16:19:16.1067404Z rollout_state, 2024-11-01T16:19:16.1067801Z (args.github_issue_owner, username), 2024-11-01T16:19:16.1068280Z args.github_branch, 2024-11-01T16:19:16.1068701Z args.eligible_experiments, 2024-11-01T16:19:16.1069109Z is_canary, 2024-11-01T16:19:16.1069480Z ) 2024-11-01T16:19:16.1069686Z 2024-11-01T16:19:16.1069819Z except Exception as e: 2024-11-01T16:19:16.1070184Z log.error( 2024-11-01T16:19:16.1070805Z f"Failed to get issue. Defaulting to Meta runners and no experiments. Exception: {e}" 2024-11-01T16:19:16.1071451Z ) 2024-11-01T16:19:16.1071640Z 2024-11-01T16:19:16.1071886Z set_github_output(GH_OUTPUT_KEY_LABEL_TYPE, runner_label_prefix) 2024-11-01T16:19:16.1072456Z 2024-11-01T16:19:16.1072461Z 2024-11-01T16:19:16.1072728Z if __name__ == "__main__": 2024-11-01T16:19:16.1073057Z main() 2024-11-01T16:19:16.1073248Z 2024-11-01T16:19:16.1257957Z ##[group]Run python3 -m pip install urllib3==1.26.18 PyGithub==2.3.0 2024-11-01T16:19:16.1258831Z python3 -m pip install urllib3==1.26.18 PyGithub==2.3.0 2024-11-01T16:19:16.1317516Z shell: /usr/bin/bash -e {0} 2024-11-01T16:19:16.1318069Z env: 2024-11-01T16:19:16.1318660Z GITHUB_TOKEN: *** 2024-11-01T16:19:16.1319319Z ISSUE_NUMBER: 5132 2024-11-01T16:19:16.1319906Z TRIGGERING_ACTOR: pytorch-bot[bot] 2024-11-01T16:19:16.1320530Z ISSUE_OWNER: 2024-11-01T16:19:16.1321079Z CHECK_EXPERIMENTS: 2024-11-01T16:19:16.1321443Z ##[endgroup] 2024-11-01T16:19:16.6100372Z Defaulting to user installation because normal site-packages is not writeable 2024-11-01T16:19:17.0563191Z Collecting urllib3==1.26.18 2024-11-01T16:19:17.1307736Z Downloading urllib3-1.26.18-py2.py3-none-any.whl (143 kB) 2024-11-01T16:19:17.1628450Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 143.8/143.8 KB 4.6 MB/s eta 0:00:00 2024-11-01T16:19:17.1959126Z Collecting PyGithub==2.3.0 2024-11-01T16:19:17.2108131Z Downloading PyGithub-2.3.0-py3-none-any.whl (354 kB) 2024-11-01T16:19:17.2293892Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 354.4/354.4 KB 21.4 MB/s eta 0:00:00 2024-11-01T16:19:17.2785192Z Collecting typing-extensions>=4.0.0 2024-11-01T16:19:17.2932672Z Downloading typing_extensions-4.12.2-py3-none-any.whl (37 kB) 2024-11-01T16:19:17.3303633Z Collecting pynacl>=1.4.0 2024-11-01T16:19:17.3455172Z Downloading PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl (856 kB) 2024-11-01T16:19:17.3682995Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 856.7/856.7 KB 41.7 MB/s eta 0:00:00 2024-11-01T16:19:17.3714121Z Requirement already satisfied: requests>=2.14.0 in /usr/lib/python3/dist-packages (from PyGithub==2.3.0) (2.25.1) 2024-11-01T16:19:17.3988379Z Collecting Deprecated 2024-11-01T16:19:17.4132575Z Downloading Deprecated-1.2.14-py2.py3-none-any.whl (9.6 kB) 2024-11-01T16:19:17.4411428Z Collecting pyjwt[crypto]>=2.4.0 2024-11-01T16:19:17.4555982Z Downloading PyJWT-2.9.0-py3-none-any.whl (22 kB) 2024-11-01T16:19:17.4703575Z Requirement already satisfied: cryptography>=3.4.0 in /usr/lib/python3/dist-packages (from pyjwt[crypto]>=2.4.0->PyGithub==2.3.0) (3.4.8) 2024-11-01T16:19:17.7256175Z Collecting cffi>=1.4.1 2024-11-01T16:19:17.7404552Z Downloading cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (446 kB) 2024-11-01T16:19:17.7489970Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 446.2/446.2 KB 75.5 MB/s eta 0:00:00 2024-11-01T16:19:17.9471727Z Collecting wrapt<2,>=1.10 2024-11-01T16:19:17.9617810Z Downloading wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (80 kB) 2024-11-01T16:19:17.9666535Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 80.3/80.3 KB 26.5 MB/s eta 0:00:00 2024-11-01T16:19:17.9836460Z Collecting pycparser 2024-11-01T16:19:17.9982772Z Downloading pycparser-2.22-py3-none-any.whl (117 kB) 2024-11-01T16:19:18.0032068Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 117.6/117.6 KB 39.9 MB/s eta 0:00:00 2024-11-01T16:19:18.1859225Z Installing collected packages: wrapt, urllib3, typing-extensions, pyjwt, pycparser, Deprecated, cffi, pynacl, PyGithub 2024-11-01T16:19:18.6675415Z Successfully installed Deprecated-1.2.14 PyGithub-2.3.0 cffi-1.17.1 pycparser-2.22 pyjwt-2.9.0 pynacl-1.5.0 typing-extensions-4.12.2 urllib3-1.26.18 wrapt-1.16.0 2024-11-01T16:19:18.7764989Z ##[group]Run curr_branch="ciflow/trunk/138766" 2024-11-01T16:19:18.7765589Z curr_branch="ciflow/trunk/138766" 2024-11-01T16:19:18.7766144Z curr_ref_type="tag" 2024-11-01T16:19:18.7766574Z echo "Current branch is '$curr_branch'" 2024-11-01T16:19:18.7767029Z  2024-11-01T16:19:18.7767448Z python3 runner_determinator.py \ 2024-11-01T16:19:18.7767932Z  --github-token "$GITHUB_TOKEN" \ 2024-11-01T16:19:18.7768677Z  --github-issue "$ISSUE_NUMBER" \ 2024-11-01T16:19:18.7769246Z  --github-branch "$curr_branch" \ 2024-11-01T16:19:18.7769693Z  --github-actor "$TRIGGERING_ACTOR" \ 2024-11-01T16:19:18.7770205Z  --github-issue-owner "$ISSUE_OWNER" \ 2024-11-01T16:19:18.7770865Z  --github-ref-type "$curr_ref_type" \ 2024-11-01T16:19:18.7771325Z  --github-repo "$GITHUB_REPOSITORY" \ 2024-11-01T16:19:18.7772081Z  --eligible-experiments "$CHECK_EXPERIMENTS" \ 2024-11-01T16:19:18.7832170Z shell: /usr/bin/bash -e {0} 2024-11-01T16:19:18.7832523Z env: 2024-11-01T16:19:18.7833232Z GITHUB_TOKEN: *** 2024-11-01T16:19:18.7833598Z ISSUE_NUMBER: 5132 2024-11-01T16:19:18.7833942Z TRIGGERING_ACTOR: pytorch-bot[bot] 2024-11-01T16:19:18.7834508Z ISSUE_OWNER: 2024-11-01T16:19:18.7834855Z CHECK_EXPERIMENTS: 2024-11-01T16:19:18.7835184Z ##[endgroup] 2024-11-01T16:19:18.7923314Z Current branch is 'ciflow/trunk/138766' 2024-11-01T16:19:20.6475891Z INFO : Based on rollout percentage of 25%, enabling experiment lf. 2024-11-01T16:19:20.6477780Z INFO : Skipping experiment 'awsa100', as it is not a default experiment 2024-11-01T16:19:20.6478909Z INFO : Setting output: label-type='lf.' 2024-11-01T16:19:20.6931566Z Evaluate and set job outputs 2024-11-01T16:19:20.6943278Z Set output 'label-type' 2024-11-01T16:19:20.6944660Z Cleaning up orphan processes