2024-11-01T16:19:21.9688268Z Current runner version: '2.320.0' 2024-11-01T16:19:21.9713340Z ##[group]Operating System 2024-11-01T16:19:21.9714108Z Ubuntu 2024-11-01T16:19:21.9714488Z 22.04.5 2024-11-01T16:19:21.9714840Z LTS 2024-11-01T16:19:21.9715216Z ##[endgroup] 2024-11-01T16:19:21.9715600Z ##[group]Runner Image 2024-11-01T16:19:21.9716049Z Image: ubuntu-22.04 2024-11-01T16:19:21.9716483Z Version: 20241015.1.0 2024-11-01T16:19:21.9717481Z Included Software: https://github.com/actions/runner-images/blob/ubuntu22/20241015.1/images/ubuntu/Ubuntu2204-Readme.md 2024-11-01T16:19:21.9718879Z Image Release: https://github.com/actions/runner-images/releases/tag/ubuntu22%2F20241015.1 2024-11-01T16:19:21.9719757Z ##[endgroup] 2024-11-01T16:19:21.9720169Z ##[group]Runner Image Provisioner 2024-11-01T16:19:21.9720665Z 2.0.384.1 2024-11-01T16:19:21.9721053Z ##[endgroup] 2024-11-01T16:19:21.9736753Z ##[group]GITHUB_TOKEN Permissions 2024-11-01T16:19:21.9738602Z Contents: read 2024-11-01T16:19:21.9739054Z Metadata: read 2024-11-01T16:19:21.9739777Z ##[endgroup] 2024-11-01T16:19:21.9742921Z Secret source: Actions 2024-11-01T16:19:21.9743660Z Prepare workflow directory 2024-11-01T16:19:22.0662668Z Prepare all required actions 2024-11-01T16:19:22.0835491Z Uses: pytorch/pytorch/.github/workflows/_runner-determinator.yml@refs/heads/main (33dce10ece5b38aa0ab76739b658cd980a6e3d8f) 2024-11-01T16:19:22.0841192Z ##[group] Inputs 2024-11-01T16:19:22.0841804Z check_experiments: 2024-11-01T16:19:22.0842401Z triggering_actor: c00w 2024-11-01T16:19:22.0842875Z issue_owner: c00w 2024-11-01T16:19:22.0843259Z curr_branch: gh/c00w/2/head 2024-11-01T16:19:22.0843830Z curr_ref_type: branch 2024-11-01T16:19:22.0844280Z issue_number: 5132 2024-11-01T16:19:22.0844669Z ##[endgroup] 2024-11-01T16:19:22.0845657Z Complete job name: before-test / get-label-type / runner-determinator 2024-11-01T16:19:22.8358421Z ##[group]Run cat < runner_determinator.py 2024-11-01T16:19:22.8360169Z cat < runner_determinator.py 2024-11-01T16:19:22.8360653Z # flake8: noqa: G004 2024-11-01T16:19:22.8361138Z  2024-11-01T16:19:22.8361700Z # Note: Copies of this script in runner_determinator.py and _runner-determinator.yml 2024-11-01T16:19:22.8362549Z # must be kept in sync. You can do it easily by running the following command: 2024-11-01T16:19:22.8363330Z # python .github/scripts/update_runner_determinator.py 2024-11-01T16:19:22.8363862Z  2024-11-01T16:19:22.8364172Z """ 2024-11-01T16:19:22.8364714Z This runner determinator is used to determine which set of runners to run a 2024-11-01T16:19:22.8365490Z GitHub job on. It uses the first comment of a GitHub issue (by default 2024-11-01T16:19:22.8366477Z https://github.com/pytorch/test-infra/issues/5132) to define the configuration 2024-11-01T16:19:22.8367603Z of which runners should be used to run which job. 2024-11-01T16:19:22.8368109Z  2024-11-01T16:19:22.8368690Z The configuration has two parts, the settings and a list of opted-in users, 2024-11-01T16:19:22.8369439Z separated by a line containing "---". If the line is not present, the 2024-11-01T16:19:22.8370208Z settings are considered to be empty with only the second part, the user 2024-11-01T16:19:22.8370864Z list, defined. 2024-11-01T16:19:22.8371218Z  2024-11-01T16:19:22.8371705Z The first part is a YAML block that defines the rollout settings. This can be 2024-11-01T16:19:22.8372577Z used to define any settings that are needed to determine which runners to use. 2024-11-01T16:19:22.8373322Z It's fields are defined by the RolloutSettings class below. 2024-11-01T16:19:22.8373828Z  2024-11-01T16:19:22.8374413Z The second part is a list of users who are explicitly opted in to the LF fleet. 2024-11-01T16:19:22.8375209Z The user list is also a comma separated list of additional features or 2024-11-01T16:19:22.8376141Z experiments which the user could be opted in to. 2024-11-01T16:19:22.8376776Z  2024-11-01T16:19:22.8377183Z The user list has the following rules: 2024-11-01T16:19:22.8377613Z  2024-11-01T16:19:22.8378137Z - Users are GitHub usernames, which must start with the @ prefix 2024-11-01T16:19:22.8378950Z - Each user is also a comma-separated list of features/experiments to enable 2024-11-01T16:19:22.8379640Z - A "#" prefix opts the user out of all experiments 2024-11-01T16:19:22.8380169Z  2024-11-01T16:19:22.8380602Z Example config: 2024-11-01T16:19:22.8381051Z  # A list of experiments that can be opted into. 2024-11-01T16:19:22.8381755Z  # This defines the behavior they'll induce when opted into. 2024-11-01T16:19:22.8382270Z  # Expected syntax is: 2024-11-01T16:19:22.8382860Z  # [experiment_name]: # Name of the experiment. Also used for the label prefix. 2024-11-01T16:19:22.8383806Z  # rollout_perc: [int] # % of workflows to run with this experiment when users are not opted in. 2024-11-01T16:19:22.8384412Z  2024-11-01T16:19:22.8384714Z  experiments: 2024-11-01T16:19:22.8385158Z  lf: 2024-11-01T16:19:22.8385465Z  rollout_percent: 25 2024-11-01T16:19:22.8385884Z  all_branches: false 2024-11-01T16:19:22.8386350Z  default: true 2024-11-01T16:19:22.8386680Z  --- 2024-11-01T16:19:22.8387002Z  2024-11-01T16:19:22.8387362Z  # Opt-ins: 2024-11-01T16:19:22.8387886Z  # Users can opt into the LF fleet by adding their GitHub username to this list 2024-11-01T16:19:22.8388861Z  # and specifying experiments to enable in a comma-separated list. 2024-11-01T16:19:22.8389592Z  # Experiments should be from the above list. 2024-11-01T16:19:22.8390073Z  2024-11-01T16:19:22.8390364Z  @User1,lf,split_build 2024-11-01T16:19:22.8390831Z  @User2,lf 2024-11-01T16:19:22.8391203Z  @User3,split_build 2024-11-01T16:19:22.8391535Z """ 2024-11-01T16:19:22.8391895Z  2024-11-01T16:19:22.8392214Z import logging 2024-11-01T16:19:22.8392524Z import os 2024-11-01T16:19:22.8392918Z import random 2024-11-01T16:19:22.8393322Z from argparse import ArgumentParser 2024-11-01T16:19:22.8393742Z from logging import LogRecord 2024-11-01T16:19:22.8394399Z from typing import Any, Dict, FrozenSet, Iterable, List, NamedTuple, Tuple 2024-11-01T16:19:22.8394992Z  2024-11-01T16:19:22.8395262Z import yaml 2024-11-01T16:19:22.8395709Z from github import Auth, Github 2024-11-01T16:19:22.8396159Z from github.Issue import Issue 2024-11-01T16:19:22.8396522Z  2024-11-01T16:19:22.8396891Z  2024-11-01T16:19:22.8397260Z DEFAULT_LABEL_PREFIX = "" # use meta runners 2024-11-01T16:19:22.8397843Z WORKFLOW_LABEL_LF = "lf." # use runners from the linux foundation 2024-11-01T16:19:22.8398676Z WORKFLOW_LABEL_LF_CANARY = "lf.c." # use canary runners from the linux foundation 2024-11-01T16:19:22.8399262Z  2024-11-01T16:19:22.8399603Z GITHUB_OUTPUT = os.getenv("GITHUB_OUTPUT", "") 2024-11-01T16:19:22.8400176Z GH_OUTPUT_KEY_AMI = "runner-ami" 2024-11-01T16:19:22.8400643Z GH_OUTPUT_KEY_LABEL_TYPE = "label-type" 2024-11-01T16:19:22.8401047Z  2024-11-01T16:19:22.8401418Z  2024-11-01T16:19:22.8401756Z SETTING_EXPERIMENTS = "experiments" 2024-11-01T16:19:22.8402134Z  2024-11-01T16:19:22.8402535Z LF_FLEET_EXPERIMENT = "lf" 2024-11-01T16:19:22.8402950Z CANARY_FLEET_SUFFIX = ".c" 2024-11-01T16:19:22.8403305Z  2024-11-01T16:19:22.8403646Z  2024-11-01T16:19:22.8403964Z class Experiment(NamedTuple): 2024-11-01T16:19:22.8404624Z  rollout_perc: float = ( 2024-11-01T16:19:22.8405183Z  0 # Percentage of workflows to experiment on when user is not opted-in. 2024-11-01T16:19:22.8405787Z  ) 2024-11-01T16:19:22.8406177Z  all_branches: bool = ( 2024-11-01T16:19:22.8407020Z  False # If True, the experiment is also enabled on the exception branches 2024-11-01T16:19:22.8407642Z  ) 2024-11-01T16:19:22.8408057Z  default: bool = ( 2024-11-01T16:19:22.8408569Z  True # If True, the experiment is enabled by default for all queries 2024-11-01T16:19:22.8409142Z  ) 2024-11-01T16:19:22.8409509Z  2024-11-01T16:19:22.8409797Z  # Add more fields as needed 2024-11-01T16:19:22.8410220Z  2024-11-01T16:19:22.8410625Z  2024-11-01T16:19:22.8410960Z class Settings(NamedTuple): 2024-11-01T16:19:22.8411333Z  """ 2024-11-01T16:19:22.8411835Z  Settings for the experiments that can be opted into. 2024-11-01T16:19:22.8412352Z  """ 2024-11-01T16:19:22.8412619Z  2024-11-01T16:19:22.8413035Z  experiments: Dict[str, Experiment] = {} 2024-11-01T16:19:22.8413490Z  2024-11-01T16:19:22.8413739Z  2024-11-01T16:19:22.8414155Z class ColorFormatter(logging.Formatter): 2024-11-01T16:19:22.8414746Z  """Color codes the log messages based on the log level""" 2024-11-01T16:19:22.8415216Z  2024-11-01T16:19:22.8415574Z  COLORS = { 2024-11-01T16:19:22.8415991Z  "WARNING": "\033[33m", # Yellow 2024-11-01T16:19:22.8416415Z  "ERROR": "\033[31m", # Red 2024-11-01T16:19:22.8417120Z  "CRITICAL": "\033[31m", # Red 2024-11-01T16:19:22.8417591Z  "INFO": "\033[0m", # Reset 2024-11-01T16:19:22.8417997Z  "DEBUG": "\033[0m", # Reset 2024-11-01T16:19:22.8418498Z  } 2024-11-01T16:19:22.8418805Z  2024-11-01T16:19:22.8419141Z  def format(self, record: LogRecord) -> str: 2024-11-01T16:19:22.8419890Z  log_color = self.COLORS.get(record.levelname, "\033[0m") # Default to reset 2024-11-01T16:19:22.8420580Z  record.msg = f"{log_color}{record.msg}\033[0m" 2024-11-01T16:19:22.8421109Z  return super().format(record) 2024-11-01T16:19:22.8421550Z  2024-11-01T16:19:22.8421841Z  2024-11-01T16:19:22.8422195Z handler = logging.StreamHandler() 2024-11-01T16:19:22.8422836Z handler.setFormatter(ColorFormatter(fmt="%(levelname)-8s: %(message)s")) 2024-11-01T16:19:22.8423407Z  2024-11-01T16:19:22.8423824Z log = logging.getLogger(os.path.basename(__file__)) 2024-11-01T16:19:22.8424379Z log.addHandler(handler) 2024-11-01T16:19:22.8424784Z log.setLevel(logging.INFO) 2024-11-01T16:19:22.8425188Z  2024-11-01T16:19:22.8425521Z  2024-11-01T16:19:22.8425916Z def set_github_output(key: str, value: str) -> None: 2024-11-01T16:19:22.8426410Z  """ 2024-11-01T16:19:22.8426901Z  Defines outputs of the github action that invokes this script 2024-11-01T16:19:22.8427441Z  """ 2024-11-01T16:19:22.8427787Z  if not GITHUB_OUTPUT: 2024-11-01T16:19:22.8428789Z  # See https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/ for deprecation notice 2024-11-01T16:19:22.8429702Z  log.warning( 2024-11-01T16:19:22.8430464Z  "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:22.8431292Z  ) 2024-11-01T16:19:22.8431673Z  print(f"::set-output name={key}::{value}") 2024-11-01T16:19:22.8432134Z  return 2024-11-01T16:19:22.8432708Z  2024-11-01T16:19:22.8433025Z  with open(GITHUB_OUTPUT, "a") as f: 2024-11-01T16:19:22.8433542Z  log.info(f"Setting output: {key}='{value}'") 2024-11-01T16:19:22.8434135Z  f.write(f"{key}={value}\n") 2024-11-01T16:19:22.8434506Z  2024-11-01T16:19:22.8434791Z  2024-11-01T16:19:22.8435298Z def _str_comma_separated_to_set(value: str) -> FrozenSet[str]: 2024-11-01T16:19:22.8435802Z  return frozenset( 2024-11-01T16:19:22.8436374Z  filter(lambda itm: itm != "", map(str.strip, value.strip(" \n\t").split(","))) 2024-11-01T16:19:22.8437029Z  ) 2024-11-01T16:19:22.8437329Z  2024-11-01T16:19:22.8437576Z  2024-11-01T16:19:22.8437977Z def parse_args() -> Any: 2024-11-01T16:19:22.8438490Z  parser = ArgumentParser("Get dynamic rollout settings") 2024-11-01T16:19:22.8439203Z  parser.add_argument("--github-token", type=str, required=True, help="GitHub token") 2024-11-01T16:19:22.8439933Z  parser.add_argument( 2024-11-01T16:19:22.8440346Z  "--github-issue-repo", 2024-11-01T16:19:22.8440734Z  type=str, 2024-11-01T16:19:22.8441157Z  required=False, 2024-11-01T16:19:22.8441577Z  default="pytorch/test-infra", 2024-11-01T16:19:22.8442046Z  help="GitHub repo to get the issue", 2024-11-01T16:19:22.8442543Z  ) 2024-11-01T16:19:22.8442865Z  parser.add_argument( 2024-11-01T16:19:22.8443241Z  "--github-repo", 2024-11-01T16:19:22.8443679Z  type=str, 2024-11-01T16:19:22.8444037Z  required=True, 2024-11-01T16:19:22.8444594Z  help="GitHub repo where CI is running", 2024-11-01T16:19:22.8445123Z  ) 2024-11-01T16:19:22.8445464Z  parser.add_argument( 2024-11-01T16:19:22.8445982Z  "--github-issue", type=int, required=True, help="GitHub issue number" 2024-11-01T16:19:22.8446880Z  ) 2024-11-01T16:19:22.8447235Z  parser.add_argument( 2024-11-01T16:19:22.8447800Z  "--github-actor", type=str, required=True, help="GitHub triggering_actor" 2024-11-01T16:19:22.8448398Z  ) 2024-11-01T16:19:22.8448736Z  parser.add_argument( 2024-11-01T16:19:22.8449310Z  "--github-issue-owner", type=str, required=True, help="GitHub issue owner" 2024-11-01T16:19:22.8449911Z  ) 2024-11-01T16:19:22.8450249Z  parser.add_argument( 2024-11-01T16:19:22.8450847Z  "--github-branch", type=str, required=True, help="Current GitHub branch or tag" 2024-11-01T16:19:22.8451476Z  ) 2024-11-01T16:19:22.8451803Z  parser.add_argument( 2024-11-01T16:19:22.8452198Z  "--github-ref-type", 2024-11-01T16:19:22.8452636Z  type=str, 2024-11-01T16:19:22.8453001Z  required=True, 2024-11-01T16:19:22.8453464Z  help="Current GitHub ref type, branch or tag", 2024-11-01T16:19:22.8453978Z  ) 2024-11-01T16:19:22.8454299Z  parser.add_argument( 2024-11-01T16:19:22.8454716Z  "--eligible-experiments", 2024-11-01T16:19:22.8455226Z  type=_str_comma_separated_to_set, 2024-11-01T16:19:22.8455674Z  required=False, 2024-11-01T16:19:22.8456074Z  default="", 2024-11-01T16:19:22.8456872Z  help="comma separated list of experiments to check, if omitted all experiments marked with default=True are checked", 2024-11-01T16:19:22.8457599Z  ) 2024-11-01T16:19:22.8457914Z  2024-11-01T16:19:22.8458307Z  return parser.parse_args() 2024-11-01T16:19:22.8458675Z  2024-11-01T16:19:22.8458975Z  2024-11-01T16:19:22.8459406Z def get_gh_client(github_token: str) -> Github: 2024-11-01T16:19:22.8460039Z  auth = Auth.Token(github_token) 2024-11-01T16:19:22.8460493Z  return Github(auth=auth) 2024-11-01T16:19:22.8460956Z  2024-11-01T16:19:22.8461229Z  2024-11-01T16:19:22.8461665Z def get_issue(gh: Github, repo: str, issue_num: int) -> Issue: 2024-11-01T16:19:22.8462276Z  repo = gh.get_repo(repo) 2024-11-01T16:19:22.8462720Z  return repo.get_issue(number=issue_num) 2024-11-01T16:19:22.8463154Z  2024-11-01T16:19:22.8463504Z  2024-11-01T16:19:22.8463799Z def get_potential_pr_author( 2024-11-01T16:19:22.8464377Z  github_token: str, repo: str, username: str, ref_type: str, ref_name: str 2024-11-01T16:19:22.8465003Z ) -> str: 2024-11-01T16:19:22.8465485Z  # If the trigger was a new tag added by a bot, this is a ciflow case 2024-11-01T16:19:22.8466208Z  # Fetch the actual username from the original PR. The PR number is 2024-11-01T16:19:22.8466964Z  # embedded in the tag name: ciflow// 2024-11-01T16:19:22.8467454Z  2024-11-01T16:19:22.8467753Z  gh = get_gh_client(github_token) 2024-11-01T16:19:22.8468243Z  2024-11-01T16:19:22.8468655Z  if username == "pytorch-bot[bot]" and ref_type == "tag": 2024-11-01T16:19:22.8469171Z  split_tag = ref_name.split("/") 2024-11-01T16:19:22.8469681Z  if ( 2024-11-01T16:19:22.8470039Z  len(split_tag) == 3 2024-11-01T16:19:22.8470450Z  and split_tag[0] == "ciflow" 2024-11-01T16:19:22.8471010Z  and split_tag[2].isnumeric() 2024-11-01T16:19:22.8471437Z  ): 2024-11-01T16:19:22.8472053Z  pr_number = split_tag[2] 2024-11-01T16:19:22.8472498Z  try: 2024-11-01T16:19:22.8472877Z  repository = gh.get_repo(repo) 2024-11-01T16:19:22.8473528Z  pull = repository.get_pull(number=int(pr_number)) 2024-11-01T16:19:22.8474065Z  except Exception as e: 2024-11-01T16:19:22.8474506Z  raise Exception( # noqa: TRY002 2024-11-01T16:19:22.8475191Z  f"issue with pull request {pr_number} from repo {repository}" 2024-11-01T16:19:22.8475751Z  ) from e 2024-11-01T16:19:22.8476180Z  return pull.user.login 2024-11-01T16:19:22.8476743Z  # In all other cases, return the original input username 2024-11-01T16:19:22.8477308Z  return username 2024-11-01T16:19:22.8477675Z  2024-11-01T16:19:22.8477988Z  2024-11-01T16:19:22.8478371Z def is_exception_branch(branch: str) -> bool: 2024-11-01T16:19:22.8478841Z  """ 2024-11-01T16:19:22.8479451Z  Branches that get opted out of experiments by default, until they're explicitly enabled. 2024-11-01T16:19:22.8480098Z  """ 2024-11-01T16:19:22.8480608Z  return branch.split("/")[0] in {"main", "nightly", "release", "landchecks"} 2024-11-01T16:19:22.8481201Z  2024-11-01T16:19:22.8481488Z  2024-11-01T16:19:22.8481841Z def load_yaml(yaml_text: str) -> Any: 2024-11-01T16:19:22.8482287Z  try: 2024-11-01T16:19:22.8482665Z  data = yaml.safe_load(yaml_text) 2024-11-01T16:19:22.8483105Z  return data 2024-11-01T16:19:22.8483551Z  except yaml.YAMLError as exc: 2024-11-01T16:19:22.8484046Z  log.exception("Error loading YAML") 2024-11-01T16:19:22.8484486Z  raise 2024-11-01T16:19:22.8484838Z  2024-11-01T16:19:22.8485140Z  2024-11-01T16:19:22.8485648Z def extract_settings_user_opt_in_from_text(rollout_state: str) -> Tuple[str, str]: 2024-11-01T16:19:22.8486268Z  """ 2024-11-01T16:19:22.8487162Z  Extracts the text with settings, if any, and the opted in users from the rollout state. 2024-11-01T16:19:22.8487992Z  2024-11-01T16:19:22.8488582Z  If the issue body contains "---" then the text above that is the settings 2024-11-01T16:19:22.8489232Z  and the text below is the list of opted in users. 2024-11-01T16:19:22.8489706Z  2024-11-01T16:19:22.8490308Z  If it doesn't contain "---" then the settings are empty and the rest is the users. 2024-11-01T16:19:22.8490881Z  """ 2024-11-01T16:19:22.8491287Z  rollout_state_parts = rollout_state.split("---") 2024-11-01T16:19:22.8491886Z  if len(rollout_state_parts) >= 2: 2024-11-01T16:19:22.8492394Z  return rollout_state_parts[0], rollout_state_parts[1] 2024-11-01T16:19:22.8492890Z  else: 2024-11-01T16:19:22.8493312Z  return "", rollout_state 2024-11-01T16:19:22.8493675Z  2024-11-01T16:19:22.8493979Z  2024-11-01T16:19:22.8494386Z class UserOptins(Dict[str, List[str]]): 2024-11-01T16:19:22.8494786Z  """ 2024-11-01T16:19:22.8495288Z  Dictionary of users with a list of features they have opted into 2024-11-01T16:19:22.8495899Z  """ 2024-11-01T16:19:22.8496199Z  2024-11-01T16:19:22.8496462Z  2024-11-01T16:19:22.8496977Z def parse_user_opt_in_from_text(user_optin_text: str) -> UserOptins: 2024-11-01T16:19:22.8497515Z  """ 2024-11-01T16:19:22.8498147Z  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:22.8498915Z  2024-11-01T16:19:22.8499765Z  Users are GitHub usernames with the @ prefix. Each user is also a comma-separated list of features/experiments to enable. 2024-11-01T16:19:22.8500593Z  - Example line: "@User1,lf,split_build" 2024-11-01T16:19:22.8501272Z  - A "#" prefix indicates the user is opted out of all experiments 2024-11-01T16:19:22.8501829Z  2024-11-01T16:19:22.8502086Z  2024-11-01T16:19:22.8502433Z  """ 2024-11-01T16:19:22.8502778Z  optins = UserOptins() 2024-11-01T16:19:22.8503200Z  for user in user_optin_text.split("\n"): 2024-11-01T16:19:22.8503752Z  user = user.strip("\r\n\t -") 2024-11-01T16:19:22.8504268Z  if not user or not user.startswith("@"): 2024-11-01T16:19:22.8504760Z  # Not a valid user. Skip 2024-11-01T16:19:22.8505231Z  continue 2024-11-01T16:19:22.8505584Z  2024-11-01T16:19:22.8505877Z  if user: 2024-11-01T16:19:22.8506338Z  usr_name = user.split(",")[0].strip("@") 2024-11-01T16:19:22.8506959Z  optins[usr_name] = [exp.strip(" ") for exp in user.split(",")[1:]] 2024-11-01T16:19:22.8507498Z  2024-11-01T16:19:22.8507849Z  return optins 2024-11-01T16:19:22.8508194Z  2024-11-01T16:19:22.8508477Z  2024-11-01T16:19:22.8508947Z def parse_settings_from_text(settings_text: str) -> Settings: 2024-11-01T16:19:22.8509464Z  """ 2024-11-01T16:19:22.8510000Z  Parse the experiments from the issue body into a list of ExperimentSettings 2024-11-01T16:19:22.8510621Z  """ 2024-11-01T16:19:22.8510933Z  try: 2024-11-01T16:19:22.8511277Z  if settings_text: 2024-11-01T16:19:22.8511969Z  # Escape the backtick as well so that we can have the settings in a code block on the GH issue 2024-11-01T16:19:22.8512667Z  # for easy reading 2024-11-01T16:19:22.8513398Z  # Note: Using ascii for the backtick so that the cat step in _runner-determinator.yml doesn't choke on 2024-11-01T16:19:22.8514262Z  # the backtick character in shell commands. 2024-11-01T16:19:22.8515214Z  backtick = chr(96) # backtick character 2024-11-01T16:19:22.8515823Z  settings_text = settings_text.strip(f"\r\n\t{backtick} ") 2024-11-01T16:19:22.8516495Z  settings = load_yaml(settings_text) 2024-11-01T16:19:22.8516917Z  2024-11-01T16:19:22.8517450Z  # For now we just load experiments. We can expand this if/when we add more settings 2024-11-01T16:19:22.8518150Z  experiments = {} 2024-11-01T16:19:22.8518552Z  2024-11-01T16:19:22.8519005Z  for exp_name, exp_settings in settings.get(SETTING_EXPERIMENTS).items(): 2024-11-01T16:19:22.8519697Z  valid_settings = {} 2024-11-01T16:19:22.8520187Z  for setting in exp_settings: 2024-11-01T16:19:22.8520672Z  if setting not in Experiment._fields: 2024-11-01T16:19:22.8521246Z  log.warning( 2024-11-01T16:19:22.8521889Z  f"Unexpected setting in experiment: {setting} = {exp_settings[setting]}" 2024-11-01T16:19:22.8522448Z  ) 2024-11-01T16:19:22.8522905Z  else: 2024-11-01T16:19:22.8523387Z  valid_settings[setting] = exp_settings[setting] 2024-11-01T16:19:22.8523930Z  2024-11-01T16:19:22.8524322Z  experiments[exp_name] = Experiment(**valid_settings) 2024-11-01T16:19:22.8524873Z  return Settings(experiments) 2024-11-01T16:19:22.8525359Z  2024-11-01T16:19:22.8525657Z  except Exception: 2024-11-01T16:19:22.8526232Z  log.exception("Failed to parse settings") 2024-11-01T16:19:22.8527234Z  2024-11-01T16:19:22.8527547Z  return Settings() 2024-11-01T16:19:22.8527920Z  2024-11-01T16:19:22.8528284Z  2024-11-01T16:19:22.8528661Z def parse_settings(rollout_state: str) -> Settings: 2024-11-01T16:19:22.8529145Z  """ 2024-11-01T16:19:22.8529656Z  Parse settings, if any, from the rollout state. 2024-11-01T16:19:22.8530089Z  2024-11-01T16:19:22.8530569Z  If the issue body contains "---" then the text above that is the settings 2024-11-01T16:19:22.8531336Z  and the text below is the list of opted in users. 2024-11-01T16:19:22.8531782Z  2024-11-01T16:19:22.8532317Z  If it doesn't contain "---" then the settings are empty and the default values are used. 2024-11-01T16:19:22.8533016Z  """ 2024-11-01T16:19:22.8533469Z  settings_text, _ = extract_settings_user_opt_in_from_text(rollout_state) 2024-11-01T16:19:22.8534144Z  return parse_settings_from_text(settings_text) 2024-11-01T16:19:22.8534667Z  2024-11-01T16:19:22.8534951Z  2024-11-01T16:19:22.8535354Z def parse_users(rollout_state: str) -> UserOptins: 2024-11-01T16:19:22.8535893Z  """ 2024-11-01T16:19:22.8536263Z  Parse users from the rollout state. 2024-11-01T16:19:22.8536673Z  2024-11-01T16:19:22.8537028Z  """ 2024-11-01T16:19:22.8537500Z  _, users_text = extract_settings_user_opt_in_from_text(rollout_state) 2024-11-01T16:19:22.8538120Z  return parse_user_opt_in_from_text(users_text) 2024-11-01T16:19:22.8538638Z  2024-11-01T16:19:22.8538943Z  2024-11-01T16:19:22.8539433Z def is_user_opted_in(user: str, user_optins: UserOptins, experiment_name: str) -> bool: 2024-11-01T16:19:22.8540105Z  """ 2024-11-01T16:19:22.8540522Z  Check if a user is opted into an experiment 2024-11-01T16:19:22.8540946Z  """ 2024-11-01T16:19:22.8541426Z  return experiment_name in user_optins.get(user, []) 2024-11-01T16:19:22.8541927Z  2024-11-01T16:19:22.8542338Z  2024-11-01T16:19:22.8542724Z def get_runner_prefix( 2024-11-01T16:19:22.8543134Z  rollout_state: str, 2024-11-01T16:19:22.8543527Z  workflow_requestors: Iterable[str], 2024-11-01T16:19:22.8544047Z  branch: str, 2024-11-01T16:19:22.8544505Z  eligible_experiments: FrozenSet[str] = frozenset(), 2024-11-01T16:19:22.8544979Z  is_canary: bool = False, 2024-11-01T16:19:22.8545450Z ) -> str: 2024-11-01T16:19:22.8545839Z  settings = parse_settings(rollout_state) 2024-11-01T16:19:22.8546346Z  user_optins = parse_users(rollout_state) 2024-11-01T16:19:22.8546822Z  2024-11-01T16:19:22.8547126Z  fleet_prefix = "" 2024-11-01T16:19:22.8547518Z  prefixes = [] 2024-11-01T16:19:22.8548124Z  for experiment_name, experiment_settings in settings.experiments.items(): 2024-11-01T16:19:22.8548900Z  if not experiment_settings.all_branches and is_exception_branch(branch): 2024-11-01T16:19:22.8549507Z  log.info( 2024-11-01T16:19:22.8550149Z  f"Branch {branch} is an exception branch. Not enabling experiment {experiment_name}." 2024-11-01T16:19:22.8550787Z  ) 2024-11-01T16:19:22.8551145Z  continue 2024-11-01T16:19:22.8551523Z  2024-11-01T16:19:22.8551850Z  if eligible_experiments: 2024-11-01T16:19:22.8552375Z  if experiment_name not in eligible_experiments: 2024-11-01T16:19:22.8553016Z  exp_list = ", ".join(eligible_experiments) 2024-11-01T16:19:22.8553463Z  log.info( 2024-11-01T16:19:22.8554309Z  f"Skipping experiment '{experiment_name}', as it is not in the eligible_experiments list: {exp_list}" 2024-11-01T16:19:22.8555068Z  ) 2024-11-01T16:19:22.8555407Z  continue 2024-11-01T16:19:22.8555858Z  elif not experiment_settings.default: 2024-11-01T16:19:22.8556378Z  log.info( 2024-11-01T16:19:22.8556937Z  f"Skipping experiment '{experiment_name}', as it is not a default experiment" 2024-11-01T16:19:22.8557530Z  ) 2024-11-01T16:19:22.8557930Z  continue 2024-11-01T16:19:22.8558265Z  2024-11-01T16:19:22.8558684Z  # Is any workflow_requestor opted in to this experiment? 2024-11-01T16:19:22.8559274Z  opted_in_users = [ 2024-11-01T16:19:22.8559649Z  requestor 2024-11-01T16:19:22.8560095Z  for requestor in workflow_requestors 2024-11-01T16:19:22.8560775Z  if is_user_opted_in(requestor, user_optins, experiment_name) 2024-11-01T16:19:22.8561295Z  ] 2024-11-01T16:19:22.8561572Z  2024-11-01T16:19:22.8561958Z  enabled = False 2024-11-01T16:19:22.8562357Z  if opted_in_users: 2024-11-01T16:19:22.8562709Z  log.info( 2024-11-01T16:19:22.8563466Z  f"{', '.join(opted_in_users)} have opted into experiment {experiment_name}." 2024-11-01T16:19:22.8564069Z  ) 2024-11-01T16:19:22.8564380Z  enabled = True 2024-11-01T16:19:22.8564831Z  2024-11-01T16:19:22.8565206Z  elif experiment_settings.rollout_perc: 2024-11-01T16:19:22.8565910Z  # If no user is opted in, then we randomly enable the experiment based on the rollout percentage 2024-11-01T16:19:22.8567106Z  if random.uniform(0, 100) <= experiment_settings.rollout_perc: 2024-11-01T16:19:22.8567680Z  log.info( 2024-11-01T16:19:22.8568428Z  f"Based on rollout percentage of {experiment_settings.rollout_perc}%, enabling experiment {experiment_name}." 2024-11-01T16:19:22.8569392Z  ) 2024-11-01T16:19:22.8569762Z  enabled = True 2024-11-01T16:19:22.8570167Z  2024-11-01T16:19:22.8570499Z  if enabled: 2024-11-01T16:19:22.8570913Z  label = experiment_name 2024-11-01T16:19:22.8571413Z  if experiment_name == LF_FLEET_EXPERIMENT: 2024-11-01T16:19:22.8572187Z  # We give some special treatment to the "lf" experiment since determines the fleet we use 2024-11-01T16:19:22.8572980Z  # - If it's enabled, then we always list it's prefix first 2024-11-01T16:19:22.8573683Z  # - If we're in the canary branch, then we append ".c" to the lf prefix 2024-11-01T16:19:22.8574335Z  if is_canary: 2024-11-01T16:19:22.8574772Z  label += CANARY_FLEET_SUFFIX 2024-11-01T16:19:22.8575253Z  fleet_prefix = label 2024-11-01T16:19:22.8575736Z  else: 2024-11-01T16:19:22.8576109Z  prefixes.append(label) 2024-11-01T16:19:22.8576522Z  2024-11-01T16:19:22.8576912Z  if len(prefixes) > 1: 2024-11-01T16:19:22.8577314Z  log.error( 2024-11-01T16:19:22.8578218Z  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:22.8579224Z  ) 2024-11-01T16:19:22.8579575Z  prefixes = prefixes[:1] 2024-11-01T16:19:22.8579941Z  2024-11-01T16:19:22.8580341Z  # Fleet always comes first 2024-11-01T16:19:22.8580751Z  if fleet_prefix: 2024-11-01T16:19:22.8581279Z  prefixes.insert(0, fleet_prefix) 2024-11-01T16:19:22.8581810Z  2024-11-01T16:19:22.8582205Z  return ".".join(prefixes) + "." if prefixes else "" 2024-11-01T16:19:22.8582667Z  2024-11-01T16:19:22.8583012Z  2024-11-01T16:19:22.8583530Z def get_rollout_state_from_issue(github_token: str, repo: str, issue_num: int) -> str: 2024-11-01T16:19:22.8584141Z  """ 2024-11-01T16:19:22.8584731Z  Gets the first comment of the issue, which contains the desired rollout state. 2024-11-01T16:19:22.8585323Z  2024-11-01T16:19:22.8585808Z  The default issue we use - https://github.com/pytorch/test-infra/issues/5132 2024-11-01T16:19:22.8586463Z  """ 2024-11-01T16:19:22.8586821Z  gh = get_gh_client(github_token) 2024-11-01T16:19:22.8587284Z  issue = get_issue(gh, repo, issue_num) 2024-11-01T16:19:22.8587923Z  return str(issue.get_comments()[0].body.strip("\n\t ")) 2024-11-01T16:19:22.8588435Z  2024-11-01T16:19:22.8588682Z  2024-11-01T16:19:22.8589048Z def main() -> None: 2024-11-01T16:19:22.8589442Z  args = parse_args() 2024-11-01T16:19:22.8589784Z  2024-11-01T16:19:22.8590222Z  runner_label_prefix = DEFAULT_LABEL_PREFIX 2024-11-01T16:19:22.8590682Z  2024-11-01T16:19:22.8591046Z  try: 2024-11-01T16:19:22.8591421Z  rollout_state = get_rollout_state_from_issue( 2024-11-01T16:19:22.8592058Z  args.github_token, args.github_issue_repo, args.github_issue 2024-11-01T16:19:22.8592651Z  ) 2024-11-01T16:19:22.8592931Z  2024-11-01T16:19:22.8593297Z  username = get_potential_pr_author( 2024-11-01T16:19:22.8593839Z  args.github_token, 2024-11-01T16:19:22.8594225Z  args.github_repo, 2024-11-01T16:19:22.8594660Z  args.github_actor, 2024-11-01T16:19:22.8595154Z  args.github_ref_type, 2024-11-01T16:19:22.8595569Z  args.github_branch, 2024-11-01T16:19:22.8596087Z  ) 2024-11-01T16:19:22.8596468Z  2024-11-01T16:19:22.8596874Z  is_canary = args.github_repo == "pytorch/pytorch-canary" 2024-11-01T16:19:22.8597389Z  2024-11-01T16:19:22.8597853Z  runner_label_prefix = get_runner_prefix( 2024-11-01T16:19:22.8598287Z  rollout_state, 2024-11-01T16:19:22.8598736Z  (args.github_issue_owner, username), 2024-11-01T16:19:22.8599293Z  args.github_branch, 2024-11-01T16:19:22.8599710Z  args.eligible_experiments, 2024-11-01T16:19:22.8600151Z  is_canary, 2024-11-01T16:19:22.8600651Z  ) 2024-11-01T16:19:22.8600966Z  2024-11-01T16:19:22.8601269Z  except Exception as e: 2024-11-01T16:19:22.8601715Z  log.error( 2024-11-01T16:19:22.8602326Z  f"Failed to get issue. Defaulting to Meta runners and no experiments. Exception: {e}" 2024-11-01T16:19:22.8602947Z  ) 2024-11-01T16:19:22.8603327Z  2024-11-01T16:19:22.8603770Z  set_github_output(GH_OUTPUT_KEY_LABEL_TYPE, runner_label_prefix) 2024-11-01T16:19:22.8604283Z  2024-11-01T16:19:22.8604625Z  2024-11-01T16:19:22.8604939Z if __name__ == "__main__": 2024-11-01T16:19:22.8605304Z  main() 2024-11-01T16:19:22.8605682Z  2024-11-01T16:19:22.8605967Z EOF 2024-11-01T16:19:22.8606246Z  2024-11-01T16:19:22.8607141Z cat runner_determinator.py 2024-11-01T16:19:22.8988528Z shell: /usr/bin/bash -e {0} 2024-11-01T16:19:22.8989174Z env: 2024-11-01T16:19:22.8989906Z GITHUB_TOKEN: *** 2024-11-01T16:19:22.8990396Z ISSUE_NUMBER: 5132 2024-11-01T16:19:22.8990968Z TRIGGERING_ACTOR: c00w 2024-11-01T16:19:22.8991357Z ISSUE_OWNER: c00w 2024-11-01T16:19:22.8991804Z CHECK_EXPERIMENTS: 2024-11-01T16:19:22.8992143Z ##[endgroup] 2024-11-01T16:19:22.9457067Z # flake8: noqa: G004 2024-11-01T16:19:22.9457347Z 2024-11-01T16:19:22.9458760Z # Note: Copies of this script in runner_determinator.py and _runner-determinator.yml 2024-11-01T16:19:22.9459692Z # must be kept in sync. You can do it easily by running the following command: 2024-11-01T16:19:22.9460372Z # python .github/scripts/update_runner_determinator.py 2024-11-01T16:19:22.9460723Z 2024-11-01T16:19:22.9460864Z """ 2024-11-01T16:19:22.9461407Z This runner determinator is used to determine which set of runners to run a 2024-11-01T16:19:22.9462117Z GitHub job on. It uses the first comment of a GitHub issue (by default 2024-11-01T16:19:22.9462976Z https://github.com/pytorch/test-infra/issues/5132) to define the configuration 2024-11-01T16:19:22.9463682Z of which runners should be used to run which job. 2024-11-01T16:19:22.9464050Z 2024-11-01T16:19:22.9464413Z The configuration has two parts, the settings and a list of opted-in users, 2024-11-01T16:19:22.9465197Z separated by a line containing "---". If the line is not present, the 2024-11-01T16:19:22.9465975Z settings are considered to be empty with only the second part, the user 2024-11-01T16:19:22.9466481Z list, defined. 2024-11-01T16:19:22.9466708Z 2024-11-01T16:19:22.9467002Z The first part is a YAML block that defines the rollout settings. This can be 2024-11-01T16:19:22.9467827Z used to define any settings that are needed to determine which runners to use. 2024-11-01T16:19:22.9468510Z It's fields are defined by the RolloutSettings class below. 2024-11-01T16:19:22.9468905Z 2024-11-01T16:19:22.9469203Z The second part is a list of users who are explicitly opted in to the LF fleet. 2024-11-01T16:19:22.9469989Z The user list is also a comma separated list of additional features or 2024-11-01T16:19:22.9470552Z experiments which the user could be opted in to. 2024-11-01T16:19:22.9470904Z 2024-11-01T16:19:22.9471051Z The user list has the following rules: 2024-11-01T16:19:22.9471410Z 2024-11-01T16:19:22.9471702Z - Users are GitHub usernames, which must start with the @ prefix 2024-11-01T16:19:22.9472709Z - Each user is also a comma-separated list of features/experiments to enable 2024-11-01T16:19:22.9473335Z - A "#" prefix opts the user out of all experiments 2024-11-01T16:19:22.9473749Z 2024-11-01T16:19:22.9473866Z Example config: 2024-11-01T16:19:22.9474270Z # A list of experiments that can be opted into. 2024-11-01T16:19:22.9474837Z # This defines the behavior they'll induce when opted into. 2024-11-01T16:19:22.9475402Z # Expected syntax is: 2024-11-01T16:19:22.9475934Z # [experiment_name]: # Name of the experiment. Also used for the label prefix. 2024-11-01T16:19:22.9476679Z # rollout_perc: [int] # % of workflows to run with this experiment when users are not opted in. 2024-11-01T16:19:22.9477243Z 2024-11-01T16:19:22.9477381Z experiments: 2024-11-01T16:19:22.9477692Z lf: 2024-11-01T16:19:22.9477958Z rollout_percent: 25 2024-11-01T16:19:22.9478404Z all_branches: false 2024-11-01T16:19:22.9478767Z default: true 2024-11-01T16:19:22.9479079Z --- 2024-11-01T16:19:22.9479338Z 2024-11-01T16:19:22.9479477Z # Opt-ins: 2024-11-01T16:19:22.9479971Z # Users can opt into the LF fleet by adding their GitHub username to this list 2024-11-01T16:19:22.9480690Z # and specifying experiments to enable in a comma-separated list. 2024-11-01T16:19:22.9481338Z # Experiments should be from the above list. 2024-11-01T16:19:22.9481658Z 2024-11-01T16:19:22.9481782Z @User1,lf,split_build 2024-11-01T16:19:22.9482207Z @User2,lf 2024-11-01T16:19:22.9482483Z @User3,split_build 2024-11-01T16:19:22.9482809Z """ 2024-11-01T16:19:22.9482948Z 2024-11-01T16:19:22.9483193Z import logging 2024-11-01T16:19:22.9483467Z import os 2024-11-01T16:19:22.9483755Z import random 2024-11-01T16:19:22.9484331Z from argparse import ArgumentParser 2024-11-01T16:19:22.9484738Z from logging import LogRecord 2024-11-01T16:19:22.9485281Z from typing import Any, Dict, FrozenSet, Iterable, List, NamedTuple, Tuple 2024-11-01T16:19:22.9485713Z 2024-11-01T16:19:22.9485928Z import yaml 2024-11-01T16:19:22.9486212Z from github import Auth, Github 2024-11-01T16:19:22.9486836Z from github.Issue import Issue 2024-11-01T16:19:22.9487090Z 2024-11-01T16:19:22.9487095Z 2024-11-01T16:19:22.9487377Z DEFAULT_LABEL_PREFIX = "" # use meta runners 2024-11-01T16:19:22.9487902Z WORKFLOW_LABEL_LF = "lf." # use runners from the linux foundation 2024-11-01T16:19:22.9488606Z WORKFLOW_LABEL_LF_CANARY = "lf.c." # use canary runners from the linux foundation 2024-11-01T16:19:22.9489028Z 2024-11-01T16:19:22.9489299Z GITHUB_OUTPUT = os.getenv("GITHUB_OUTPUT", "") 2024-11-01T16:19:22.9489779Z GH_OUTPUT_KEY_AMI = "runner-ami" 2024-11-01T16:19:22.9490237Z GH_OUTPUT_KEY_LABEL_TYPE = "label-type" 2024-11-01T16:19:22.9490497Z 2024-11-01T16:19:22.9490547Z 2024-11-01T16:19:22.9490755Z SETTING_EXPERIMENTS = "experiments" 2024-11-01T16:19:22.9491003Z 2024-11-01T16:19:22.9491173Z LF_FLEET_EXPERIMENT = "lf" 2024-11-01T16:19:22.9491515Z CANARY_FLEET_SUFFIX = ".c" 2024-11-01T16:19:22.9491755Z 2024-11-01T16:19:22.9491759Z 2024-11-01T16:19:22.9491955Z class Experiment(NamedTuple): 2024-11-01T16:19:22.9492352Z rollout_perc: float = ( 2024-11-01T16:19:22.9492911Z 0 # Percentage of workflows to experiment on when user is not opted-in. 2024-11-01T16:19:22.9493515Z ) 2024-11-01T16:19:22.9493827Z all_branches: bool = ( 2024-11-01T16:19:22.9494305Z False # If True, the experiment is also enabled on the exception branches 2024-11-01T16:19:22.9494908Z ) 2024-11-01T16:19:22.9495211Z default: bool = ( 2024-11-01T16:19:22.9495649Z True # If True, the experiment is enabled by default for all queries 2024-11-01T16:19:22.9496229Z ) 2024-11-01T16:19:22.9496371Z 2024-11-01T16:19:22.9496567Z # Add more fields as needed 2024-11-01T16:19:22.9496800Z 2024-11-01T16:19:22.9496804Z 2024-11-01T16:19:22.9496933Z class Settings(NamedTuple): 2024-11-01T16:19:22.9497345Z """ 2024-11-01T16:19:22.9497731Z Settings for the experiments that can be opted into. 2024-11-01T16:19:22.9498458Z """ 2024-11-01T16:19:22.9498635Z 2024-11-01T16:19:22.9498881Z experiments: Dict[str, Experiment] = {} 2024-11-01T16:19:22.9499194Z 2024-11-01T16:19:22.9499198Z 2024-11-01T16:19:22.9499352Z class ColorFormatter(logging.Formatter): 2024-11-01T16:19:22.9499857Z """Color codes the log messages based on the log level""" 2024-11-01T16:19:22.9500199Z 2024-11-01T16:19:22.9500382Z COLORS = { 2024-11-01T16:19:22.9500713Z "WARNING": "\033[33m", # Yellow 2024-11-01T16:19:22.9501117Z "ERROR": "\033[31m", # Red 2024-11-01T16:19:22.9501565Z "CRITICAL": "\033[31m", # Red 2024-11-01T16:19:22.9501961Z "INFO": "\033[0m", # Reset 2024-11-01T16:19:22.9502359Z "DEBUG": "\033[0m", # Reset 2024-11-01T16:19:22.9502758Z } 2024-11-01T16:19:22.9502933Z 2024-11-01T16:19:22.9503153Z def format(self, record: LogRecord) -> str: 2024-11-01T16:19:22.9503772Z log_color = self.COLORS.get(record.levelname, "\033[0m") # Default to reset 2024-11-01T16:19:22.9504433Z record.msg = f"{log_color}{record.msg}\033[0m" 2024-11-01T16:19:22.9504899Z return super().format(record) 2024-11-01T16:19:22.9505145Z 2024-11-01T16:19:22.9505150Z 2024-11-01T16:19:22.9505339Z handler = logging.StreamHandler() 2024-11-01T16:19:22.9505971Z handler.setFormatter(ColorFormatter(fmt="%(levelname)-8s: %(message)s")) 2024-11-01T16:19:22.9506409Z 2024-11-01T16:19:22.9506600Z log = logging.getLogger(os.path.basename(__file__)) 2024-11-01T16:19:22.9507077Z log.addHandler(handler) 2024-11-01T16:19:22.9507509Z log.setLevel(logging.INFO) 2024-11-01T16:19:22.9507721Z 2024-11-01T16:19:22.9507726Z 2024-11-01T16:19:22.9507959Z def set_github_output(key: str, value: str) -> None: 2024-11-01T16:19:22.9508418Z """ 2024-11-01T16:19:22.9509041Z Defines outputs of the github action that invokes this script 2024-11-01T16:19:22.9509536Z """ 2024-11-01T16:19:22.9509835Z if not GITHUB_OUTPUT: 2024-11-01T16:19:22.9510887Z # See https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/ for deprecation notice 2024-11-01T16:19:22.9511759Z log.warning( 2024-11-01T16:19:22.9512451Z "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:22.9513248Z ) 2024-11-01T16:19:22.9536071Z print(f"::set-output name={key}::{value}") 2024-11-01T16:19:22.9536553Z return 2024-11-01T16:19:22.9536914Z 2024-11-01T16:19:22.9537093Z with open(GITHUB_OUTPUT, "a") as f: 2024-11-01T16:19:22.9537641Z log.info(f"Setting output: {key}='{value}'") 2024-11-01T16:19:22.9538069Z f.write(f"{key}={value}\n") 2024-11-01T16:19:22.9538429Z 2024-11-01T16:19:22.9538447Z 2024-11-01T16:19:22.9538746Z def _str_comma_separated_to_set(value: str) -> FrozenSet[str]: 2024-11-01T16:19:22.9539247Z return frozenset( 2024-11-01T16:19:22.9539761Z filter(lambda itm: itm != "", map(str.strip, value.strip(" \n\t").split(","))) 2024-11-01T16:19:22.9540379Z ) 2024-11-01T16:19:22.9540557Z 2024-11-01T16:19:22.9540562Z 2024-11-01T16:19:22.9540723Z def parse_args() -> Any: 2024-11-01T16:19:22.9541174Z parser = ArgumentParser("Get dynamic rollout settings") 2024-11-01T16:19:22.9541972Z parser.add_argument("--github-token", type=str, required=True, help="GitHub token") 2024-11-01T16:19:22.9542567Z parser.add_argument( 2024-11-01T16:19:22.9542983Z "--github-issue-repo", 2024-11-01T16:19:22.9543385Z type=str, 2024-11-01T16:19:22.9543704Z required=False, 2024-11-01T16:19:22.9544117Z default="pytorch/test-infra", 2024-11-01T16:19:22.9544587Z help="GitHub repo to get the issue", 2024-11-01T16:19:22.9544994Z ) 2024-11-01T16:19:22.9545306Z parser.add_argument( 2024-11-01T16:19:22.9545718Z "--github-repo", 2024-11-01T16:19:22.9546054Z type=str, 2024-11-01T16:19:22.9546384Z required=True, 2024-11-01T16:19:22.9547042Z help="GitHub repo where CI is running", 2024-11-01T16:19:22.9547486Z ) 2024-11-01T16:19:22.9547780Z parser.add_argument( 2024-11-01T16:19:22.9548377Z "--github-issue", type=int, required=True, help="GitHub issue number" 2024-11-01T16:19:22.9548919Z ) 2024-11-01T16:19:22.9549211Z parser.add_argument( 2024-11-01T16:19:22.9549800Z "--github-actor", type=str, required=True, help="GitHub triggering_actor" 2024-11-01T16:19:22.9550349Z ) 2024-11-01T16:19:22.9550637Z parser.add_argument( 2024-11-01T16:19:22.9551233Z "--github-issue-owner", type=str, required=True, help="GitHub issue owner" 2024-11-01T16:19:22.9551790Z ) 2024-11-01T16:19:22.9552080Z parser.add_argument( 2024-11-01T16:19:22.9552717Z "--github-branch", type=str, required=True, help="Current GitHub branch or tag" 2024-11-01T16:19:22.9553313Z ) 2024-11-01T16:19:22.9553602Z parser.add_argument( 2024-11-01T16:19:22.9554027Z "--github-ref-type", 2024-11-01T16:19:22.9554406Z type=str, 2024-11-01T16:19:22.9554720Z required=True, 2024-11-01T16:19:22.9555163Z help="Current GitHub ref type, branch or tag", 2024-11-01T16:19:22.9555600Z ) 2024-11-01T16:19:22.9555888Z parser.add_argument( 2024-11-01T16:19:22.9556330Z "--eligible-experiments", 2024-11-01T16:19:22.9556740Z type=_str_comma_separated_to_set, 2024-11-01T16:19:22.9557145Z required=False, 2024-11-01T16:19:22.9557524Z default="", 2024-11-01T16:19:22.9558209Z help="comma separated list of experiments to check, if omitted all experiments marked with default=True are checked", 2024-11-01T16:19:22.9558922Z ) 2024-11-01T16:19:22.9559138Z 2024-11-01T16:19:22.9559276Z return parser.parse_args() 2024-11-01T16:19:22.9559537Z 2024-11-01T16:19:22.9559697Z 2024-11-01T16:19:22.9559930Z def get_gh_client(github_token: str) -> Github: 2024-11-01T16:19:22.9560400Z auth = Auth.Token(github_token) 2024-11-01T16:19:22.9560849Z return Github(auth=auth) 2024-11-01T16:19:22.9561109Z 2024-11-01T16:19:22.9561114Z 2024-11-01T16:19:22.9561395Z def get_issue(gh: Github, repo: str, issue_num: int) -> Issue: 2024-11-01T16:19:22.9561921Z repo = gh.get_repo(repo) 2024-11-01T16:19:22.9562402Z return repo.get_issue(number=issue_num) 2024-11-01T16:19:22.9562677Z 2024-11-01T16:19:22.9562681Z 2024-11-01T16:19:22.9562811Z def get_potential_pr_author( 2024-11-01T16:19:22.9563337Z github_token: str, repo: str, username: str, ref_type: str, ref_name: str 2024-11-01T16:19:22.9563967Z ) -> str: 2024-11-01T16:19:22.9564374Z # If the trigger was a new tag added by a bot, this is a ciflow case 2024-11-01T16:19:22.9565055Z # Fetch the actual username from the original PR. The PR number is 2024-11-01T16:19:22.9565771Z # embedded in the tag name: ciflow// 2024-11-01T16:19:22.9566088Z 2024-11-01T16:19:22.9566244Z gh = get_gh_client(github_token) 2024-11-01T16:19:22.9566529Z 2024-11-01T16:19:22.9567200Z if username == "pytorch-bot[bot]" and ref_type == "tag": 2024-11-01T16:19:22.9567850Z split_tag = ref_name.split("/") 2024-11-01T16:19:22.9568234Z if ( 2024-11-01T16:19:22.9568551Z len(split_tag) == 3 2024-11-01T16:19:22.9569005Z and split_tag[0] == "ciflow" 2024-11-01T16:19:22.9569404Z and split_tag[2].isnumeric() 2024-11-01T16:19:22.9569789Z ): 2024-11-01T16:19:22.9570180Z pr_number = split_tag[2] 2024-11-01T16:19:22.9570551Z try: 2024-11-01T16:19:22.9570904Z repository = gh.get_repo(repo) 2024-11-01T16:19:22.9571481Z pull = repository.get_pull(number=int(pr_number)) 2024-11-01T16:19:22.9571927Z except Exception as e: 2024-11-01T16:19:22.9572349Z raise Exception( # noqa: TRY002 2024-11-01T16:19:22.9572990Z f"issue with pull request {pr_number} from repo {repository}" 2024-11-01T16:19:22.9573500Z ) from e 2024-11-01T16:19:22.9573821Z return pull.user.login 2024-11-01T16:19:22.9574562Z # In all other cases, return the original input username 2024-11-01T16:19:22.9575035Z return username 2024-11-01T16:19:22.9575212Z 2024-11-01T16:19:22.9575216Z 2024-11-01T16:19:22.9575443Z def is_exception_branch(branch: str) -> bool: 2024-11-01T16:19:22.9575956Z """ 2024-11-01T16:19:22.9576544Z Branches that get opted out of experiments by default, until they're explicitly enabled. 2024-11-01T16:19:22.9577132Z """ 2024-11-01T16:19:22.9577649Z return branch.split("/")[0] in {"main", "nightly", "release", "landchecks"} 2024-11-01T16:19:22.9578044Z 2024-11-01T16:19:22.9578048Z 2024-11-01T16:19:22.9578261Z def load_yaml(yaml_text: str) -> Any: 2024-11-01T16:19:22.9578631Z try: 2024-11-01T16:19:22.9579019Z data = yaml.safe_load(yaml_text) 2024-11-01T16:19:22.9579418Z return data 2024-11-01T16:19:22.9579744Z except yaml.YAMLError as exc: 2024-11-01T16:19:22.9580226Z log.exception("Error loading YAML") 2024-11-01T16:19:22.9580641Z raise 2024-11-01T16:19:22.9580816Z 2024-11-01T16:19:22.9580821Z 2024-11-01T16:19:22.9581195Z def extract_settings_user_opt_in_from_text(rollout_state: str) -> Tuple[str, str]: 2024-11-01T16:19:22.9581829Z """ 2024-11-01T16:19:22.9582351Z Extracts the text with settings, if any, and the opted in users from the rollout state. 2024-11-01T16:19:22.9582807Z 2024-11-01T16:19:22.9583231Z If the issue body contains "---" then the text above that is the settings 2024-11-01T16:19:22.9583808Z and the text below is the list of opted in users. 2024-11-01T16:19:22.9584150Z 2024-11-01T16:19:22.9584529Z If it doesn't contain "---" then the settings are empty and the rest is the users. 2024-11-01T16:19:22.9585148Z """ 2024-11-01T16:19:22.9585658Z rollout_state_parts = rollout_state.split("---") 2024-11-01T16:19:22.9586159Z if len(rollout_state_parts) >= 2: 2024-11-01T16:19:22.9586708Z return rollout_state_parts[0], rollout_state_parts[1] 2024-11-01T16:19:22.9587140Z else: 2024-11-01T16:19:22.9587460Z return "", rollout_state 2024-11-01T16:19:22.9587696Z 2024-11-01T16:19:22.9587701Z 2024-11-01T16:19:22.9587947Z class UserOptins(Dict[str, List[str]]): 2024-11-01T16:19:22.9588325Z """ 2024-11-01T16:19:22.9588739Z Dictionary of users with a list of features they have opted into 2024-11-01T16:19:22.9589311Z """ 2024-11-01T16:19:22.9589455Z 2024-11-01T16:19:22.9589459Z 2024-11-01T16:19:22.9589822Z def parse_user_opt_in_from_text(user_optin_text: str) -> UserOptins: 2024-11-01T16:19:22.9590291Z """ 2024-11-01T16:19:22.9591014Z 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:22.9591579Z 2024-11-01T16:19:22.9592184Z Users are GitHub usernames with the @ prefix. Each user is also a comma-separated list of features/experiments to enable. 2024-11-01T16:19:22.9592983Z - Example line: "@User1,lf,split_build" 2024-11-01T16:19:22.9593649Z - A "#" prefix indicates the user is opted out of all experiments 2024-11-01T16:19:22.9594027Z 2024-11-01T16:19:22.9594032Z 2024-11-01T16:19:22.9594173Z """ 2024-11-01T16:19:22.9594443Z optins = UserOptins() 2024-11-01T16:19:22.9594917Z for user in user_optin_text.split("\n"): 2024-11-01T16:19:22.9595402Z user = user.strip("\r\n\t -") 2024-11-01T16:19:22.9595803Z if not user or not user.startswith("@"): 2024-11-01T16:19:22.9596336Z # Not a valid user. Skip 2024-11-01T16:19:22.9596721Z continue 2024-11-01T16:19:22.9596899Z 2024-11-01T16:19:22.9597042Z if user: 2024-11-01T16:19:22.9597578Z usr_name = user.split(",")[0].strip("@") 2024-11-01T16:19:22.9598145Z optins[usr_name] = [exp.strip(" ") for exp in user.split(",")[1:]] 2024-11-01T16:19:22.9598523Z 2024-11-01T16:19:22.9598690Z return optins 2024-11-01T16:19:22.9598864Z 2024-11-01T16:19:22.9598868Z 2024-11-01T16:19:22.9599214Z def parse_settings_from_text(settings_text: str) -> Settings: 2024-11-01T16:19:22.9599879Z """ 2024-11-01T16:19:22.9600364Z Parse the experiments from the issue body into a list of ExperimentSettings 2024-11-01T16:19:22.9600967Z """ 2024-11-01T16:19:22.9601251Z try: 2024-11-01T16:19:22.9601562Z if settings_text: 2024-11-01T16:19:22.9602187Z # Escape the backtick as well so that we can have the settings in a code block on the GH issue 2024-11-01T16:19:22.9602826Z # for easy reading 2024-11-01T16:19:22.9603569Z # Note: Using ascii for the backtick so that the cat step in _runner-determinator.yml doesn't choke on 2024-11-01T16:19:22.9604340Z # the backtick character in shell commands. 2024-11-01T16:19:22.9604855Z backtick = chr(96) # backtick character 2024-11-01T16:19:22.9605389Z settings_text = settings_text.strip(f"\r\n\t{backtick} ") 2024-11-01T16:19:22.9605940Z settings = load_yaml(settings_text) 2024-11-01T16:19:22.9606257Z 2024-11-01T16:19:22.9606827Z # For now we just load experiments. We can expand this if/when we add more settings 2024-11-01T16:19:22.9607453Z experiments = {} 2024-11-01T16:19:22.9607667Z 2024-11-01T16:19:22.9608065Z for exp_name, exp_settings in settings.get(SETTING_EXPERIMENTS).items(): 2024-11-01T16:19:22.9608610Z valid_settings = {} 2024-11-01T16:19:22.9609026Z for setting in exp_settings: 2024-11-01T16:19:22.9609565Z if setting not in Experiment._fields: 2024-11-01T16:19:22.9609994Z log.warning( 2024-11-01T16:19:22.9610572Z f"Unexpected setting in experiment: {setting} = {exp_settings[setting]}" 2024-11-01T16:19:22.9611204Z ) 2024-11-01T16:19:22.9611665Z else: 2024-11-01T16:19:22.9612093Z valid_settings[setting] = exp_settings[setting] 2024-11-01T16:19:22.9612410Z 2024-11-01T16:19:22.9612749Z experiments[exp_name] = Experiment(**valid_settings) 2024-11-01T16:19:22.9613220Z return Settings(experiments) 2024-11-01T16:19:22.9613509Z 2024-11-01T16:19:22.9613627Z except Exception: 2024-11-01T16:19:22.9614093Z log.exception("Failed to parse settings") 2024-11-01T16:19:22.9614383Z 2024-11-01T16:19:22.9614534Z return Settings() 2024-11-01T16:19:22.9614719Z 2024-11-01T16:19:22.9614723Z 2024-11-01T16:19:22.9614968Z def parse_settings(rollout_state: str) -> Settings: 2024-11-01T16:19:22.9615494Z """ 2024-11-01T16:19:22.9615844Z Parse settings, if any, from the rollout state. 2024-11-01T16:19:22.9616144Z 2024-11-01T16:19:22.9616490Z If the issue body contains "---" then the text above that is the settings 2024-11-01T16:19:22.9617229Z and the text below is the list of opted in users. 2024-11-01T16:19:22.9617541Z 2024-11-01T16:19:22.9617969Z If it doesn't contain "---" then the settings are empty and the default values are used. 2024-11-01T16:19:22.9618579Z """ 2024-11-01T16:19:22.9619055Z settings_text, _ = extract_settings_user_opt_in_from_text(rollout_state) 2024-11-01T16:19:22.9619647Z return parse_settings_from_text(settings_text) 2024-11-01T16:19:22.9619970Z 2024-11-01T16:19:22.9619975Z 2024-11-01T16:19:22.9620239Z def parse_users(rollout_state: str) -> UserOptins: 2024-11-01T16:19:22.9620746Z """ 2024-11-01T16:19:22.9621066Z Parse users from the rollout state. 2024-11-01T16:19:22.9621344Z 2024-11-01T16:19:22.9621482Z """ 2024-11-01T16:19:22.9621933Z _, users_text = extract_settings_user_opt_in_from_text(rollout_state) 2024-11-01T16:19:22.9622522Z return parse_user_opt_in_from_text(users_text) 2024-11-01T16:19:22.9622812Z 2024-11-01T16:19:22.9622816Z 2024-11-01T16:19:22.9623244Z def is_user_opted_in(user: str, user_optins: UserOptins, experiment_name: str) -> bool: 2024-11-01T16:19:22.9623859Z """ 2024-11-01T16:19:22.9624219Z Check if a user is opted into an experiment 2024-11-01T16:19:22.9624809Z """ 2024-11-01T16:19:22.9625207Z return experiment_name in user_optins.get(user, []) 2024-11-01T16:19:22.9625572Z 2024-11-01T16:19:22.9625576Z 2024-11-01T16:19:22.9625698Z def get_runner_prefix( 2024-11-01T16:19:22.9626038Z rollout_state: str, 2024-11-01T16:19:22.9626482Z workflow_requestors: Iterable[str], 2024-11-01T16:19:22.9626847Z branch: str, 2024-11-01T16:19:22.9627232Z eligible_experiments: FrozenSet[str] = frozenset(), 2024-11-01T16:19:22.9627778Z is_canary: bool = False, 2024-11-01T16:19:22.9628125Z ) -> str: 2024-11-01T16:19:22.9628461Z settings = parse_settings(rollout_state) 2024-11-01T16:19:22.9629002Z user_optins = parse_users(rollout_state) 2024-11-01T16:19:22.9629279Z 2024-11-01T16:19:22.9629398Z fleet_prefix = "" 2024-11-01T16:19:22.9629742Z prefixes = [] 2024-11-01T16:19:22.9630337Z for experiment_name, experiment_settings in settings.experiments.items(): 2024-11-01T16:19:22.9631276Z if not experiment_settings.all_branches and is_exception_branch(branch): 2024-11-01T16:19:22.9631834Z log.info( 2024-11-01T16:19:22.9632488Z f"Branch {branch} is an exception branch. Not enabling experiment {experiment_name}." 2024-11-01T16:19:22.9633047Z ) 2024-11-01T16:19:22.9633359Z continue 2024-11-01T16:19:22.9633605Z 2024-11-01T16:19:22.9633771Z if eligible_experiments: 2024-11-01T16:19:22.9634184Z if experiment_name not in eligible_experiments: 2024-11-01T16:19:22.9634715Z exp_list = ", ".join(eligible_experiments) 2024-11-01T16:19:22.9635225Z log.info( 2024-11-01T16:19:22.9635905Z f"Skipping experiment '{experiment_name}', as it is not in the eligible_experiments list: {exp_list}" 2024-11-01T16:19:22.9636574Z ) 2024-11-01T16:19:22.9637129Z continue 2024-11-01T16:19:22.9637493Z elif not experiment_settings.default: 2024-11-01T16:19:22.9637928Z log.info( 2024-11-01T16:19:22.9638597Z f"Skipping experiment '{experiment_name}', as it is not a default experiment" 2024-11-01T16:19:22.9639140Z ) 2024-11-01T16:19:22.9639440Z continue 2024-11-01T16:19:22.9639683Z 2024-11-01T16:19:22.9639928Z # Is any workflow_requestor opted in to this experiment? 2024-11-01T16:19:22.9640429Z opted_in_users = [ 2024-11-01T16:19:22.9640737Z requestor 2024-11-01T16:19:22.9641163Z for requestor in workflow_requestors 2024-11-01T16:19:22.9641723Z if is_user_opted_in(requestor, user_optins, experiment_name) 2024-11-01T16:19:22.9642178Z ] 2024-11-01T16:19:22.9642426Z 2024-11-01T16:19:22.9642545Z enabled = False 2024-11-01T16:19:22.9642911Z if opted_in_users: 2024-11-01T16:19:22.9643229Z log.info( 2024-11-01T16:19:22.9643872Z f"{', '.join(opted_in_users)} have opted into experiment {experiment_name}." 2024-11-01T16:19:22.9644411Z ) 2024-11-01T16:19:22.9644689Z enabled = True 2024-11-01T16:19:22.9644986Z 2024-11-01T16:19:22.9645169Z elif experiment_settings.rollout_perc: 2024-11-01T16:19:22.9645852Z # If no user is opted in, then we randomly enable the experiment based on the rollout percentage 2024-11-01T16:19:22.9646576Z if random.uniform(0, 100) <= experiment_settings.rollout_perc: 2024-11-01T16:19:22.9647486Z log.info( 2024-11-01T16:19:22.9648163Z f"Based on rollout percentage of {experiment_settings.rollout_perc}%, enabling experiment {experiment_name}." 2024-11-01T16:19:22.9648817Z ) 2024-11-01T16:19:22.9649223Z enabled = True 2024-11-01T16:19:22.9649439Z 2024-11-01T16:19:22.9649586Z if enabled: 2024-11-01T16:19:22.9649894Z label = experiment_name 2024-11-01T16:19:22.9650435Z if experiment_name == LF_FLEET_EXPERIMENT: 2024-11-01T16:19:22.9651103Z # We give some special treatment to the "lf" experiment since determines the fleet we use 2024-11-01T16:19:22.9652175Z # - If it's enabled, then we always list it's prefix first 2024-11-01T16:19:22.9652857Z # - If we're in the canary branch, then we append ".c" to the lf prefix 2024-11-01T16:19:22.9653406Z if is_canary: 2024-11-01T16:19:22.9653878Z label += CANARY_FLEET_SUFFIX 2024-11-01T16:19:22.9654285Z fleet_prefix = label 2024-11-01T16:19:22.9654677Z else: 2024-11-01T16:19:22.9655091Z prefixes.append(label) 2024-11-01T16:19:22.9655347Z 2024-11-01T16:19:22.9655478Z if len(prefixes) > 1: 2024-11-01T16:19:22.9655836Z log.error( 2024-11-01T16:19:22.9656864Z 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:22.9657720Z ) 2024-11-01T16:19:22.9658045Z prefixes = prefixes[:1] 2024-11-01T16:19:22.9658278Z 2024-11-01T16:19:22.9658503Z # Fleet always comes first 2024-11-01T16:19:22.9658834Z if fleet_prefix: 2024-11-01T16:19:22.9659208Z prefixes.insert(0, fleet_prefix) 2024-11-01T16:19:22.9659465Z 2024-11-01T16:19:22.9659753Z return ".".join(prefixes) + "." if prefixes else "" 2024-11-01T16:19:22.9660063Z 2024-11-01T16:19:22.9660067Z 2024-11-01T16:19:22.9660491Z def get_rollout_state_from_issue(github_token: str, repo: str, issue_num: int) -> str: 2024-11-01T16:19:22.9661052Z """ 2024-11-01T16:19:22.9661601Z Gets the first comment of the issue, which contains the desired rollout state. 2024-11-01T16:19:22.9662027Z 2024-11-01T16:19:22.9662446Z The default issue we use - https://github.com/pytorch/test-infra/issues/5132 2024-11-01T16:19:22.9662966Z """ 2024-11-01T16:19:22.9663499Z gh = get_gh_client(github_token) 2024-11-01T16:19:22.9663960Z issue = get_issue(gh, repo, issue_num) 2024-11-01T16:19:22.9664428Z return str(issue.get_comments()[0].body.strip("\n\t ")) 2024-11-01T16:19:22.9664792Z 2024-11-01T16:19:22.9664796Z 2024-11-01T16:19:22.9665019Z def main() -> None: 2024-11-01T16:19:22.9665369Z args = parse_args() 2024-11-01T16:19:22.9665566Z 2024-11-01T16:19:22.9665728Z runner_label_prefix = DEFAULT_LABEL_PREFIX 2024-11-01T16:19:22.9666039Z 2024-11-01T16:19:22.9666209Z try: 2024-11-01T16:19:22.9666588Z rollout_state = get_rollout_state_from_issue( 2024-11-01T16:19:22.9667147Z args.github_token, args.github_issue_repo, args.github_issue 2024-11-01T16:19:22.9667684Z ) 2024-11-01T16:19:22.9667869Z 2024-11-01T16:19:22.9668018Z username = get_potential_pr_author( 2024-11-01T16:19:22.9668435Z args.github_token, 2024-11-01T16:19:22.9668853Z args.github_repo, 2024-11-01T16:19:22.9669221Z args.github_actor, 2024-11-01T16:19:22.9669584Z args.github_ref_type, 2024-11-01T16:19:22.9670025Z args.github_branch, 2024-11-01T16:19:22.9670379Z ) 2024-11-01T16:19:22.9670529Z 2024-11-01T16:19:22.9670831Z is_canary = args.github_repo == "pytorch/pytorch-canary" 2024-11-01T16:19:22.9671185Z 2024-11-01T16:19:22.9671421Z runner_label_prefix = get_runner_prefix( 2024-11-01T16:19:22.9671851Z rollout_state, 2024-11-01T16:19:22.9672251Z (args.github_issue_owner, username), 2024-11-01T16:19:22.9672713Z args.github_branch, 2024-11-01T16:19:22.9673102Z args.eligible_experiments, 2024-11-01T16:19:22.9673506Z is_canary, 2024-11-01T16:19:22.9673849Z ) 2024-11-01T16:19:22.9674031Z 2024-11-01T16:19:22.9674157Z except Exception as e: 2024-11-01T16:19:22.9674519Z log.error( 2024-11-01T16:19:22.9675089Z f"Failed to get issue. Defaulting to Meta runners and no experiments. Exception: {e}" 2024-11-01T16:19:22.9675685Z ) 2024-11-01T16:19:22.9675830Z 2024-11-01T16:19:22.9676119Z set_github_output(GH_OUTPUT_KEY_LABEL_TYPE, runner_label_prefix) 2024-11-01T16:19:22.9676694Z 2024-11-01T16:19:22.9676700Z 2024-11-01T16:19:22.9677068Z if __name__ == "__main__": 2024-11-01T16:19:22.9677479Z main() 2024-11-01T16:19:22.9677765Z 2024-11-01T16:19:23.0208098Z ##[group]Run python3 -m pip install urllib3==1.26.18 PyGithub==2.3.0 2024-11-01T16:19:23.0210344Z python3 -m pip install urllib3==1.26.18 PyGithub==2.3.0 2024-11-01T16:19:23.0295410Z shell: /usr/bin/bash -e {0} 2024-11-01T16:19:23.0296087Z env: 2024-11-01T16:19:23.0297023Z GITHUB_TOKEN: *** 2024-11-01T16:19:23.0297852Z ISSUE_NUMBER: 5132 2024-11-01T16:19:23.0298441Z TRIGGERING_ACTOR: c00w 2024-11-01T16:19:23.0299099Z ISSUE_OWNER: c00w 2024-11-01T16:19:23.0299862Z CHECK_EXPERIMENTS: 2024-11-01T16:19:23.0300460Z ##[endgroup] 2024-11-01T16:19:23.4287418Z Defaulting to user installation because normal site-packages is not writeable 2024-11-01T16:19:23.8167753Z Collecting urllib3==1.26.18 2024-11-01T16:19:23.8724067Z Downloading urllib3-1.26.18-py2.py3-none-any.whl (143 kB) 2024-11-01T16:19:23.8989598Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 143.8/143.8 KB 5.6 MB/s eta 0:00:00 2024-11-01T16:19:23.9392992Z Collecting PyGithub==2.3.0 2024-11-01T16:19:23.9495021Z Downloading PyGithub-2.3.0-py3-none-any.whl (354 kB) 2024-11-01T16:19:23.9841380Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 354.4/354.4 KB 10.7 MB/s eta 0:00:00 2024-11-01T16:19:24.0358043Z Collecting Deprecated 2024-11-01T16:19:24.0454284Z Downloading Deprecated-1.2.14-py2.py3-none-any.whl (9.6 kB) 2024-11-01T16:19:24.0541019Z 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:24.0874674Z Collecting typing-extensions>=4.0.0 2024-11-01T16:19:24.0976266Z Downloading typing_extensions-4.12.2-py3-none-any.whl (37 kB) 2024-11-01T16:19:24.1423227Z Collecting pynacl>=1.4.0 2024-11-01T16:19:24.1525263Z 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:24.2169844Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 856.7/856.7 KB 13.6 MB/s eta 0:00:00 2024-11-01T16:19:24.2490384Z Collecting pyjwt[crypto]>=2.4.0 2024-11-01T16:19:24.2585476Z Downloading PyJWT-2.9.0-py3-none-any.whl (22 kB) 2024-11-01T16:19:24.2724326Z 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:24.5087763Z Collecting cffi>=1.4.1 2024-11-01T16:19:24.5188426Z Downloading cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (446 kB) 2024-11-01T16:19:24.5489479Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 446.2/446.2 KB 15.6 MB/s eta 0:00:00 2024-11-01T16:19:24.7341175Z Collecting wrapt<2,>=1.10 2024-11-01T16:19:24.7443277Z 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:24.7488540Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 80.3/80.3 KB 26.7 MB/s eta 0:00:00 2024-11-01T16:19:24.7712273Z Collecting pycparser 2024-11-01T16:19:24.7807660Z Downloading pycparser-2.22-py3-none-any.whl (117 kB) 2024-11-01T16:19:24.7877268Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 117.6/117.6 KB 21.4 MB/s eta 0:00:00 2024-11-01T16:19:24.9831236Z Installing collected packages: wrapt, urllib3, typing-extensions, pyjwt, pycparser, Deprecated, cffi, pynacl, PyGithub 2024-11-01T16:19:25.4842063Z 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:25.5600626Z ##[group]Run curr_branch="gh/c00w/2/head" 2024-11-01T16:19:25.5601175Z curr_branch="gh/c00w/2/head" 2024-11-01T16:19:25.5601624Z curr_ref_type="branch" 2024-11-01T16:19:25.5602158Z echo "Current branch is '$curr_branch'" 2024-11-01T16:19:25.5602567Z  2024-11-01T16:19:25.5602932Z python3 runner_determinator.py \ 2024-11-01T16:19:25.5603476Z  --github-token "$GITHUB_TOKEN" \ 2024-11-01T16:19:25.5604142Z  --github-issue "$ISSUE_NUMBER" \ 2024-11-01T16:19:25.5604611Z  --github-branch "$curr_branch" \ 2024-11-01T16:19:25.5605143Z  --github-actor "$TRIGGERING_ACTOR" \ 2024-11-01T16:19:25.5605604Z  --github-issue-owner "$ISSUE_OWNER" \ 2024-11-01T16:19:25.5606112Z  --github-ref-type "$curr_ref_type" \ 2024-11-01T16:19:25.5606950Z  --github-repo "$GITHUB_REPOSITORY" \ 2024-11-01T16:19:25.5607587Z  --eligible-experiments "$CHECK_EXPERIMENTS" \ 2024-11-01T16:19:25.5664755Z shell: /usr/bin/bash -e {0} 2024-11-01T16:19:25.5665106Z env: 2024-11-01T16:19:25.5665907Z GITHUB_TOKEN: *** 2024-11-01T16:19:25.5666240Z ISSUE_NUMBER: 5132 2024-11-01T16:19:25.5666594Z TRIGGERING_ACTOR: c00w 2024-11-01T16:19:25.5667047Z ISSUE_OWNER: c00w 2024-11-01T16:19:25.5667348Z CHECK_EXPERIMENTS: 2024-11-01T16:19:25.5667701Z ##[endgroup] 2024-11-01T16:19:25.5743584Z Current branch is 'gh/c00w/2/head' 2024-11-01T16:19:26.9026298Z INFO : Skipping experiment 'awsa100', as it is not a default experiment 2024-11-01T16:19:26.9027241Z INFO : Setting output: label-type='' 2024-11-01T16:19:26.9431958Z Evaluate and set job outputs 2024-11-01T16:19:26.9442894Z Cleaning up orphan processes