2024-12-17T23:28:39.1643256Z Current runner version: '2.321.0' 2024-12-17T23:28:39.1666773Z ##[group]Operating System 2024-12-17T23:28:39.1667716Z Ubuntu 2024-12-17T23:28:39.1668248Z 22.04.5 2024-12-17T23:28:39.1668754Z LTS 2024-12-17T23:28:39.1669244Z ##[endgroup] 2024-12-17T23:28:39.1670054Z ##[group]Runner Image 2024-12-17T23:28:39.1670663Z Image: ubuntu-22.04 2024-12-17T23:28:39.1671173Z Version: 20241211.1.0 2024-12-17T23:28:39.1672198Z Included Software: https://github.com/actions/runner-images/blob/ubuntu22/20241211.1/images/ubuntu/Ubuntu2204-Readme.md 2024-12-17T23:28:39.1673593Z Image Release: https://github.com/actions/runner-images/releases/tag/ubuntu22%2F20241211.1 2024-12-17T23:28:39.1674477Z ##[endgroup] 2024-12-17T23:28:39.1675002Z ##[group]Runner Image Provisioner 2024-12-17T23:28:39.1675616Z 2.0.404.1 2024-12-17T23:28:39.1676079Z ##[endgroup] 2024-12-17T23:28:39.1677124Z ##[group]GITHUB_TOKEN Permissions 2024-12-17T23:28:39.1679118Z Contents: read 2024-12-17T23:28:39.1679611Z Metadata: read 2024-12-17T23:28:39.1680411Z ##[endgroup] 2024-12-17T23:28:39.1683592Z Secret source: Actions 2024-12-17T23:28:39.1684631Z Prepare workflow directory 2024-12-17T23:28:39.2166282Z Prepare all required actions 2024-12-17T23:28:39.2219800Z Uses: pytorch/pytorch/.github/workflows/_runner-determinator.yml@refs/heads/release/2.6 (0cdf8b1d09254cfda66191d1bd01e3041c3c76f7) 2024-12-17T23:28:39.2224628Z ##[group] Inputs 2024-12-17T23:28:39.2225321Z check_experiments: 2024-12-17T23:28:39.2225908Z triggering_actor: malfet 2024-12-17T23:28:39.2226446Z issue_owner: 2024-12-17T23:28:39.2227022Z curr_branch: release/2.6 2024-12-17T23:28:39.2227599Z curr_ref_type: branch 2024-12-17T23:28:39.2228118Z issue_number: 5132 2024-12-17T23:28:39.2228701Z ##[endgroup] 2024-12-17T23:28:39.2229798Z Complete job name: before-test / get-label-type / runner-determinator 2024-12-17T23:28:39.8807992Z ##[group]Run cat < runner_determinator.py 2024-12-17T23:28:39.8810425Z cat < runner_determinator.py 2024-12-17T23:28:39.8811090Z # flake8: noqa: G004 2024-12-17T23:28:39.8811720Z  2024-12-17T23:28:39.8812494Z # Note: Copies of this script in runner_determinator.py and _runner-determinator.yml 2024-12-17T23:28:39.8813551Z # must be kept in sync. You can do it easily by running the following command: 2024-12-17T23:28:39.8814501Z # python .github/scripts/update_runner_determinator.py 2024-12-17T23:28:39.8815215Z  2024-12-17T23:28:39.8815684Z """ 2024-12-17T23:28:39.8816394Z This runner determinator is used to determine which set of runners to run a 2024-12-17T23:28:39.8817393Z GitHub job on. It uses the first comment of a GitHub issue (by default 2024-12-17T23:28:39.8818582Z https://github.com/pytorch/test-infra/issues/5132) to define the configuration 2024-12-17T23:28:39.8819504Z of which runners should be used to run which job. 2024-12-17T23:28:39.8820178Z  2024-12-17T23:28:39.8820916Z The configuration has two parts, the settings and a list of opted-in users, 2024-12-17T23:28:39.8821916Z separated by a line containing "---". If the line is not present, the 2024-12-17T23:28:39.8822915Z settings are considered to be empty with only the second part, the user 2024-12-17T23:28:39.8823762Z list, defined. 2024-12-17T23:28:39.8824280Z  2024-12-17T23:28:39.8824945Z The first part is a YAML block that defines the rollout settings. This can be 2024-12-17T23:28:39.8826011Z used to define any settings that are needed to determine which runners to use. 2024-12-17T23:28:39.8826983Z It's fields are defined by the RolloutSettings class below. 2024-12-17T23:28:39.8827734Z  2024-12-17T23:28:39.8828499Z The second part is a list of users who are explicitly opted in to the LF fleet. 2024-12-17T23:28:39.8829874Z The user list is also a comma separated list of additional features or 2024-12-17T23:28:39.8831218Z experiments which the user could be opted in to. 2024-12-17T23:28:39.8831963Z  2024-12-17T23:28:39.8832499Z The user list has the following rules: 2024-12-17T23:28:39.8833076Z  2024-12-17T23:28:39.8833739Z - Users are GitHub usernames, which must start with the @ prefix 2024-12-17T23:28:39.8834743Z - Each user is also a comma-separated list of features/experiments to enable 2024-12-17T23:28:39.8835634Z - A "#" prefix opts the user out of all experiments 2024-12-17T23:28:39.8836290Z  2024-12-17T23:28:39.8836910Z Example config: 2024-12-17T23:28:39.8837547Z  # A list of experiments that can be opted into. 2024-12-17T23:28:39.8838807Z  # This defines the behavior they'll induce when opted into. 2024-12-17T23:28:39.8839524Z  # Expected syntax is: 2024-12-17T23:28:39.8840352Z  # [experiment_name]: # Name of the experiment. Also used for the label prefix. 2024-12-17T23:28:39.8841513Z  # rollout_perc: [int] # % of workflows to run with this experiment when users are not opted in. 2024-12-17T23:28:39.8842335Z  2024-12-17T23:28:39.8842814Z  experiments: 2024-12-17T23:28:39.8843401Z  lf: 2024-12-17T23:28:39.8843911Z  rollout_percent: 25 2024-12-17T23:28:39.8844534Z  all_branches: false 2024-12-17T23:28:39.8845178Z  default: true 2024-12-17T23:28:39.8845688Z  --- 2024-12-17T23:28:39.8846171Z  2024-12-17T23:28:39.8846690Z  # Opt-ins: 2024-12-17T23:28:39.8847384Z  # Users can opt into the LF fleet by adding their GitHub username to this list 2024-12-17T23:28:39.8848586Z  # and specifying experiments to enable in a comma-separated list. 2024-12-17T23:28:39.8849585Z  # To always opt out of an experiment, prefix it with a "-". 2024-12-17T23:28:39.8850405Z  # Experiments should be from the above list. 2024-12-17T23:28:39.8851021Z  2024-12-17T23:28:39.8851587Z  @User1,-lf,split_build 2024-12-17T23:28:39.8852177Z  @User2,lf 2024-12-17T23:28:39.8852656Z  @User3,split_build 2024-12-17T23:28:39.8853290Z """ 2024-12-17T23:28:39.8853737Z  2024-12-17T23:28:39.8854147Z import json 2024-12-17T23:28:39.8854717Z import logging 2024-12-17T23:28:39.8855230Z import os 2024-12-17T23:28:39.8855683Z import random 2024-12-17T23:28:39.8856268Z import re 2024-12-17T23:28:39.8856752Z import sys 2024-12-17T23:28:39.8857251Z from argparse import ArgumentParser 2024-12-17T23:28:39.8857981Z from functools import lru_cache 2024-12-17T23:28:39.8858602Z from logging import LogRecord 2024-12-17T23:28:39.8859397Z from typing import Any, Dict, FrozenSet, Iterable, List, NamedTuple, Set, Tuple 2024-12-17T23:28:39.8860378Z from urllib.request import Request, urlopen 2024-12-17T23:28:39.8861014Z  2024-12-17T23:28:39.8861422Z import yaml 2024-12-17T23:28:39.8862022Z from github import Auth, Github 2024-12-17T23:28:39.8862641Z from github.Issue import Issue 2024-12-17T23:28:39.8863198Z  2024-12-17T23:28:39.8863682Z  2024-12-17T23:28:39.8864204Z DEFAULT_LABEL_PREFIX = "" # use meta runners 2024-12-17T23:28:39.8864992Z WORKFLOW_LABEL_LF = "lf." # use runners from the linux foundation 2024-12-17T23:28:39.8866047Z WORKFLOW_LABEL_LF_CANARY = "lf.c." # use canary runners from the linux foundation 2024-12-17T23:28:39.8866850Z  2024-12-17T23:28:39.8867367Z GITHUB_OUTPUT = os.getenv("GITHUB_OUTPUT", "") 2024-12-17T23:28:39.8868113Z GH_OUTPUT_KEY_AMI = "runner-ami" 2024-12-17T23:28:39.8868756Z GH_OUTPUT_KEY_LABEL_TYPE = "label-type" 2024-12-17T23:28:39.8869593Z OPT_OUT_LABEL = "no-runner-experiments" 2024-12-17T23:28:39.8870476Z  2024-12-17T23:28:39.8870979Z SETTING_EXPERIMENTS = "experiments" 2024-12-17T23:28:39.8871557Z  2024-12-17T23:28:39.8872064Z LF_FLEET_EXPERIMENT = "lf" 2024-12-17T23:28:39.8872659Z CANARY_FLEET_SUFFIX = ".c" 2024-12-17T23:28:39.8873212Z  2024-12-17T23:28:39.8873698Z  2024-12-17T23:28:39.8874190Z class Experiment(NamedTuple): 2024-12-17T23:28:39.8874785Z  rollout_perc: float = ( 2024-12-17T23:28:39.8875612Z  0 # Percentage of workflows to experiment on when user is not opted-in. 2024-12-17T23:28:39.8876414Z  ) 2024-12-17T23:28:39.8876880Z  all_branches: bool = ( 2024-12-17T23:28:39.8877721Z  False # If True, the experiment is also enabled on the exception branches 2024-12-17T23:28:39.8878487Z  ) 2024-12-17T23:28:39.8878995Z  default: bool = ( 2024-12-17T23:28:39.8879816Z  True # If True, the experiment is enabled by default for all queries 2024-12-17T23:28:39.8880522Z  ) 2024-12-17T23:28:39.8880974Z  2024-12-17T23:28:39.8881547Z  # Add more fields as needed 2024-12-17T23:28:39.8882090Z  2024-12-17T23:28:39.8882511Z  2024-12-17T23:28:39.8883082Z class Settings(NamedTuple): 2024-12-17T23:28:39.8883664Z  """ 2024-12-17T23:28:39.8884263Z  Settings for the experiments that can be opted into. 2024-12-17T23:28:39.8885041Z  """ 2024-12-17T23:28:39.8885465Z  2024-12-17T23:28:39.8885965Z  experiments: Dict[str, Experiment] = {} 2024-12-17T23:28:39.8886656Z  2024-12-17T23:28:39.8887051Z  2024-12-17T23:28:39.8887740Z class ColorFormatter(logging.Formatter): 2024-12-17T23:28:39.8888601Z  """Color codes the log messages based on the log level""" 2024-12-17T23:28:39.8889255Z  2024-12-17T23:28:39.8889718Z  COLORS = { 2024-12-17T23:28:39.8890345Z  "WARNING": "\033[33m", # Yellow 2024-12-17T23:28:39.8890992Z  "ERROR": "\033[31m", # Red 2024-12-17T23:28:39.8891568Z  "CRITICAL": "\033[31m", # Red 2024-12-17T23:28:39.8892260Z  "INFO": "\033[0m", # Reset 2024-12-17T23:28:39.8892889Z  "DEBUG": "\033[0m", # Reset 2024-12-17T23:28:39.8893422Z  } 2024-12-17T23:28:39.8893957Z  2024-12-17T23:28:39.8894506Z  def format(self, record: LogRecord) -> str: 2024-12-17T23:28:39.8895323Z  log_color = self.COLORS.get(record.levelname, "\033[0m") # Default to reset 2024-12-17T23:28:39.8896302Z  record.msg = f"{log_color}{record.msg}\033[0m" 2024-12-17T23:28:39.8897017Z  return super().format(record) 2024-12-17T23:28:39.8897563Z  2024-12-17T23:28:39.8898106Z  2024-12-17T23:28:39.8898603Z handler = logging.StreamHandler() 2024-12-17T23:28:39.8899413Z handler.setFormatter(ColorFormatter(fmt="%(levelname)-8s: %(message)s")) 2024-12-17T23:28:39.8900330Z  2024-12-17T23:28:39.8900883Z log = logging.getLogger(os.path.basename(__file__)) 2024-12-17T23:28:39.8901531Z log.addHandler(handler) 2024-12-17T23:28:39.8902220Z log.setLevel(logging.INFO) 2024-12-17T23:28:39.8902797Z  2024-12-17T23:28:39.8903192Z  2024-12-17T23:28:39.8903851Z def set_github_output(key: str, value: str) -> None: 2024-12-17T23:28:39.8904574Z  """ 2024-12-17T23:28:39.8905272Z  Defines outputs of the github action that invokes this script 2024-12-17T23:28:39.8906001Z  """ 2024-12-17T23:28:39.8906491Z  if not GITHUB_OUTPUT: 2024-12-17T23:28:39.8907729Z  # See https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/ for deprecation notice 2024-12-17T23:28:39.8909065Z  log.warning( 2024-12-17T23:28:39.8910618Z  "No env var found for GITHUB_OUTPUT, you must be running this code locally. Falling back to the deprecated print method." 2024-12-17T23:28:39.8911736Z  ) 2024-12-17T23:28:39.8912298Z  print(f"::set-output name={key}::{value}") 2024-12-17T23:28:39.8912951Z  return 2024-12-17T23:28:39.8913526Z  2024-12-17T23:28:39.8914040Z  with open(GITHUB_OUTPUT, "a") as f: 2024-12-17T23:28:39.8914707Z  log.info(f"Setting output: {key}='{value}'") 2024-12-17T23:28:39.8915428Z  f.write(f"{key}={value}\n") 2024-12-17T23:28:39.8916036Z  2024-12-17T23:28:39.8916465Z  2024-12-17T23:28:39.8917127Z def _str_comma_separated_to_set(value: str) -> FrozenSet[str]: 2024-12-17T23:28:39.8917897Z  return frozenset( 2024-12-17T23:28:39.8918629Z  filter(lambda itm: itm != "", map(str.strip, value.strip(" \n\t").split(","))) 2024-12-17T23:28:39.8919455Z  ) 2024-12-17T23:28:39.8919940Z  2024-12-17T23:28:39.8920360Z  2024-12-17T23:28:39.8920880Z def parse_args() -> Any: 2024-12-17T23:28:39.8921618Z  parser = ArgumentParser("Get dynamic rollout settings") 2024-12-17T23:28:39.8922559Z  parser.add_argument("--github-token", type=str, required=True, help="GitHub token") 2024-12-17T23:28:39.8923470Z  parser.add_argument( 2024-12-17T23:28:39.8924091Z  "--github-issue-repo", 2024-12-17T23:28:39.8924637Z  type=str, 2024-12-17T23:28:39.8925240Z  required=False, 2024-12-17T23:28:39.8926052Z  default="pytorch/test-infra", 2024-12-17T23:28:39.8926719Z  help="GitHub repo to get the issue", 2024-12-17T23:28:39.8927406Z  ) 2024-12-17T23:28:39.8927939Z  parser.add_argument( 2024-12-17T23:28:39.8928512Z  "--github-repo", 2024-12-17T23:28:39.8929084Z  type=str, 2024-12-17T23:28:39.8929648Z  required=True, 2024-12-17T23:28:39.8930244Z  help="GitHub repo where CI is running", 2024-12-17T23:28:39.8930889Z  ) 2024-12-17T23:28:39.8931382Z  parser.add_argument( 2024-12-17T23:28:39.8932130Z  "--github-issue", type=int, required=True, help="GitHub issue number" 2024-12-17T23:28:39.8933030Z  ) 2024-12-17T23:28:39.8933653Z  parser.add_argument( 2024-12-17T23:28:39.8934466Z  "--github-actor", type=str, required=True, help="GitHub triggering_actor" 2024-12-17T23:28:39.8935311Z  ) 2024-12-17T23:28:39.8935816Z  parser.add_argument( 2024-12-17T23:28:39.8936608Z  "--github-issue-owner", type=str, required=True, help="GitHub issue owner" 2024-12-17T23:28:39.8937411Z  ) 2024-12-17T23:28:39.8937909Z  parser.add_argument( 2024-12-17T23:28:39.8938715Z  "--github-branch", type=str, required=True, help="Current GitHub branch or tag" 2024-12-17T23:28:39.8939572Z  ) 2024-12-17T23:28:39.8940014Z  parser.add_argument( 2024-12-17T23:28:39.8940597Z  "--github-ref-type", 2024-12-17T23:28:39.8941234Z  type=str, 2024-12-17T23:28:39.8941734Z  required=True, 2024-12-17T23:28:39.8942379Z  help="Current GitHub ref type, branch or tag", 2024-12-17T23:28:39.8943105Z  ) 2024-12-17T23:28:39.8943552Z  parser.add_argument( 2024-12-17T23:28:39.8944170Z  "--eligible-experiments", 2024-12-17T23:28:39.8944886Z  type=_str_comma_separated_to_set, 2024-12-17T23:28:39.8945477Z  required=False, 2024-12-17T23:28:39.8946042Z  default="", 2024-12-17T23:28:39.8947281Z  help="comma separated list of experiments to check, if omitted all experiments marked with default=True are checked", 2024-12-17T23:28:39.8948268Z  ) 2024-12-17T23:28:39.8948747Z  parser.add_argument( 2024-12-17T23:28:39.8949531Z  "--pr-number", 2024-12-17T23:28:39.8950080Z  type=str, 2024-12-17T23:28:39.8950626Z  required=False, 2024-12-17T23:28:39.8951268Z  default="", 2024-12-17T23:28:39.8951851Z  help="the optional PR number where this is run", 2024-12-17T23:28:39.8952513Z  ) 2024-12-17T23:28:39.8953055Z  2024-12-17T23:28:39.8953499Z  return parser.parse_args() 2024-12-17T23:28:39.8954352Z  2024-12-17T23:28:39.8955079Z  2024-12-17T23:28:39.8955596Z def get_gh_client(github_token: str) -> Github: 2024-12-17T23:28:39.8956537Z  auth = Auth.Token(github_token) 2024-12-17T23:28:39.8957186Z  return Github(auth=auth) 2024-12-17T23:28:39.8957735Z  2024-12-17T23:28:39.8958221Z  2024-12-17T23:28:39.8958878Z def get_issue(gh: Github, repo: str, issue_num: int) -> Issue: 2024-12-17T23:28:39.8959656Z  repo = gh.get_repo(repo) 2024-12-17T23:28:39.8960335Z  return repo.get_issue(number=issue_num) 2024-12-17T23:28:39.8960920Z  2024-12-17T23:28:39.8961465Z  2024-12-17T23:28:39.8962292Z def get_potential_pr_author( 2024-12-17T23:28:39.8963196Z  github_token: str, repo: str, username: str, ref_type: str, ref_name: str 2024-12-17T23:28:39.8964015Z ) -> str: 2024-12-17T23:28:39.8964631Z  # If the trigger was a new tag added by a bot, this is a ciflow case 2024-12-17T23:28:39.8965741Z  # Fetch the actual username from the original PR. The PR number is 2024-12-17T23:28:39.8966669Z  # embedded in the tag name: ciflow// 2024-12-17T23:28:39.8967438Z  2024-12-17T23:28:39.8967908Z  gh = get_gh_client(github_token) 2024-12-17T23:28:39.8968563Z  2024-12-17T23:28:39.8969221Z  if username == "pytorch-bot[bot]" and ref_type == "tag": 2024-12-17T23:28:39.8970206Z  split_tag = ref_name.split("/") 2024-12-17T23:28:39.8970767Z  if ( 2024-12-17T23:28:39.8971369Z  len(split_tag) == 3 2024-12-17T23:28:39.8972001Z  and split_tag[0] == "ciflow" 2024-12-17T23:28:39.8972588Z  and split_tag[2].isnumeric() 2024-12-17T23:28:39.8973260Z  ): 2024-12-17T23:28:39.8973812Z  pr_number = split_tag[2] 2024-12-17T23:28:39.8974354Z  try: 2024-12-17T23:28:39.8975019Z  repository = gh.get_repo(repo) 2024-12-17T23:28:39.8975776Z  pull = repository.get_pull(number=int(pr_number)) 2024-12-17T23:28:39.8976444Z  except Exception as e: 2024-12-17T23:28:39.8977184Z  raise Exception( # noqa: TRY002 2024-12-17T23:28:39.8977965Z  f"issue with pull request {pr_number} from repo {repository}" 2024-12-17T23:28:39.8978752Z  ) from e 2024-12-17T23:28:39.8979325Z  return pull.user.login 2024-12-17T23:28:39.8980039Z  # In all other cases, return the original input username 2024-12-17T23:28:39.8980784Z  return username 2024-12-17T23:28:39.8981300Z  2024-12-17T23:28:39.8981751Z  2024-12-17T23:28:39.8982317Z def is_exception_branch(branch: str) -> bool: 2024-12-17T23:28:39.8982943Z  """ 2024-12-17T23:28:39.8983735Z  Branches that get opted out of experiments by default, until they're explicitly enabled. 2024-12-17T23:28:39.8984650Z  """ 2024-12-17T23:28:39.8985330Z  return branch.split("/")[0] in {"main", "nightly", "release", "landchecks"} 2024-12-17T23:28:39.8986291Z  2024-12-17T23:28:39.8986792Z  2024-12-17T23:28:39.8987254Z def load_yaml(yaml_text: str) -> Any: 2024-12-17T23:28:39.8987890Z  try: 2024-12-17T23:28:39.8988460Z  data = yaml.safe_load(yaml_text) 2024-12-17T23:28:39.8989051Z  return data 2024-12-17T23:28:39.8990146Z  except yaml.YAMLError: 2024-12-17T23:28:39.8990855Z  log.exception("Error loading YAML") 2024-12-17T23:28:39.8991489Z  raise 2024-12-17T23:28:39.8991957Z  2024-12-17T23:28:39.8992430Z  2024-12-17T23:28:39.8993153Z def extract_settings_user_opt_in_from_text(rollout_state: str) -> Tuple[str, str]: 2024-12-17T23:28:39.8993976Z  """ 2024-12-17T23:28:39.8994756Z  Extracts the text with settings, if any, and the opted in users from the rollout state. 2024-12-17T23:28:39.8995608Z  2024-12-17T23:28:39.8996228Z  If the issue body contains "---" then the text above that is the settings 2024-12-17T23:28:39.8997128Z  and the text below is the list of opted in users. 2024-12-17T23:28:39.8997807Z  2024-12-17T23:28:39.8998451Z  If it doesn't contain "---" then the settings are empty and the rest is the users. 2024-12-17T23:28:39.8999275Z  """ 2024-12-17T23:28:39.8999868Z  rollout_state_parts = rollout_state.split("---") 2024-12-17T23:28:39.9000522Z  if len(rollout_state_parts) >= 2: 2024-12-17T23:28:39.9001287Z  return rollout_state_parts[0], rollout_state_parts[1] 2024-12-17T23:28:39.9002001Z  else: 2024-12-17T23:28:39.9002655Z  return "", rollout_state 2024-12-17T23:28:39.9003257Z  2024-12-17T23:28:39.9003724Z  2024-12-17T23:28:39.9004262Z class UserOptins(Dict[str, List[str]]): 2024-12-17T23:28:39.9004889Z  """ 2024-12-17T23:28:39.9005560Z  Dictionary of users with a list of features they have opted into 2024-12-17T23:28:39.9006293Z  """ 2024-12-17T23:28:39.9006749Z  2024-12-17T23:28:39.9007206Z  2024-12-17T23:28:39.9007822Z def parse_user_opt_in_from_text(user_optin_text: str) -> UserOptins: 2024-12-17T23:28:39.9008590Z  """ 2024-12-17T23:28:39.9009422Z  Parse the user opt-in text into a key value pair of username and the list of features they have opted into 2024-12-17T23:28:39.9010334Z  2024-12-17T23:28:39.9011250Z  Users are GitHub usernames with the @ prefix. Each user is also a comma-separated list of features/experiments to enable. 2024-12-17T23:28:39.9012350Z  - Example line: "@User1,lf,split_build" 2024-12-17T23:28:39.9013131Z  - A "#" prefix indicates the user is opted out of all experiments 2024-12-17T23:28:39.9013934Z  2024-12-17T23:28:39.9014326Z  2024-12-17T23:28:39.9014763Z  """ 2024-12-17T23:28:39.9015302Z  optins = UserOptins() 2024-12-17T23:28:39.9015885Z  for user in user_optin_text.split("\n"): 2024-12-17T23:28:39.9016561Z  user = user.strip("\r\n\t -") 2024-12-17T23:28:39.9017280Z  if not user or not user.startswith("@"): 2024-12-17T23:28:39.9017909Z  # Not a valid user. Skip 2024-12-17T23:28:39.9018515Z  continue 2024-12-17T23:28:39.9019081Z  2024-12-17T23:28:39.9019482Z  if user: 2024-12-17T23:28:39.9020066Z  usr_name = user.split(",")[0].strip("@") 2024-12-17T23:28:39.9020931Z  optins[usr_name] = [exp.strip(" ") for exp in user.split(",")[1:]] 2024-12-17T23:28:39.9021620Z  2024-12-17T23:28:39.9022081Z  return optins 2024-12-17T23:28:39.9022668Z  2024-12-17T23:28:39.9023244Z  2024-12-17T23:28:39.9023837Z def is_valid_experiment_name(experiment_name: str) -> bool: 2024-12-17T23:28:39.9024637Z  """ 2024-12-17T23:28:39.9025150Z  Check if the experiment name is valid. 2024-12-17T23:28:39.9025765Z  A valid name: 2024-12-17T23:28:39.9026599Z  - Contains only alphanumeric characters and the special characters "_" & "-" 2024-12-17T23:28:39.9027640Z  - The special characters "_" & "-" shouldn't be the first or last characters 2024-12-17T23:28:39.9028402Z  - Cannot contain spaces 2024-12-17T23:28:39.9029068Z  """ 2024-12-17T23:28:39.9029655Z  2024-12-17T23:28:39.9030170Z  valid_char_regex = r"^[a-zA-Z0-9]([\w-]*[a-zA-Z0-9])?$" 2024-12-17T23:28:39.9031092Z  valid = bool(re.match(valid_char_regex, experiment_name)) 2024-12-17T23:28:39.9031786Z  2024-12-17T23:28:39.9032189Z  if valid: 2024-12-17T23:28:39.9032771Z  return True 2024-12-17T23:28:39.9033286Z  2024-12-17T23:28:39.9033690Z  log.error( 2024-12-17T23:28:39.9035286Z  f"Invalid experiment name: {experiment_name}. Experiment names should only contain alphanumeric characters, '_', and '-'. They cannot contain spaces, and the special characters '_' and '-' cannot be the first or last characters." 2024-12-17T23:28:39.9036841Z  ) 2024-12-17T23:28:39.9037285Z  return False 2024-12-17T23:28:39.9037869Z  2024-12-17T23:28:39.9038293Z  2024-12-17T23:28:39.9038856Z def parse_settings_from_text(settings_text: str) -> Settings: 2024-12-17T23:28:39.9039654Z  """ 2024-12-17T23:28:39.9040500Z  Parse the experiments from the issue body into a list of ExperimentSettings 2024-12-17T23:28:39.9041317Z  """ 2024-12-17T23:28:39.9041819Z  try: 2024-12-17T23:28:39.9042290Z  if settings_text: 2024-12-17T23:28:39.9043137Z  # Escape the backtick as well so that we can have the settings in a code block on the GH issue 2024-12-17T23:28:39.9044099Z  # for easy reading 2024-12-17T23:28:39.9045051Z  # Note: Using ascii for the backtick so that the cat step in _runner-determinator.yml doesn't choke on 2024-12-17T23:28:39.9045979Z  # the backtick character in shell commands. 2024-12-17T23:28:39.9046774Z  backtick = chr(96) # backtick character 2024-12-17T23:28:39.9047560Z  settings_text = settings_text.strip(f"\r\n\t{backtick} ") 2024-12-17T23:28:39.9048272Z  settings = load_yaml(settings_text) 2024-12-17T23:28:39.9048950Z  2024-12-17T23:28:39.9049651Z  # For now we just load experiments. We can expand this if/when we add more settings 2024-12-17T23:28:39.9050522Z  experiments = {} 2024-12-17T23:28:39.9051064Z  2024-12-17T23:28:39.9051723Z  for exp_name, exp_settings in settings.get(SETTING_EXPERIMENTS).items(): 2024-12-17T23:28:39.9052628Z  if not is_valid_experiment_name(exp_name): 2024-12-17T23:28:39.9053818Z  # Exclude invalid experiments from the list. We log an error, but don't raise an exception so that other experiments can still be processed. 2024-12-17T23:28:39.9054927Z  continue 2024-12-17T23:28:39.9055527Z  2024-12-17T23:28:39.9055988Z  valid_settings = {} 2024-12-17T23:28:39.9056624Z  for setting in exp_settings: 2024-12-17T23:28:39.9057348Z  if setting not in Experiment._fields: 2024-12-17T23:28:39.9058034Z  log.warning( 2024-12-17T23:28:39.9058811Z  f"Unexpected setting in experiment: {setting} = {exp_settings[setting]}" 2024-12-17T23:28:39.9059847Z  ) 2024-12-17T23:28:39.9060411Z  else: 2024-12-17T23:28:39.9061017Z  valid_settings[setting] = exp_settings[setting] 2024-12-17T23:28:39.9061738Z  2024-12-17T23:28:39.9062333Z  experiments[exp_name] = Experiment(**valid_settings) 2024-12-17T23:28:39.9063039Z  return Settings(experiments) 2024-12-17T23:28:39.9063692Z  2024-12-17T23:28:39.9064155Z  except Exception: 2024-12-17T23:28:39.9064734Z  log.exception("Failed to parse settings") 2024-12-17T23:28:39.9065429Z  2024-12-17T23:28:39.9065891Z  return Settings() 2024-12-17T23:28:39.9066386Z  2024-12-17T23:28:39.9066872Z  2024-12-17T23:28:39.9067431Z def parse_settings(rollout_state: str) -> Settings: 2024-12-17T23:28:39.9068109Z  """ 2024-12-17T23:28:39.9068682Z  Parse settings, if any, from the rollout state. 2024-12-17T23:28:39.9069828Z  2024-12-17T23:28:39.9070499Z  If the issue body contains "---" then the text above that is the settings 2024-12-17T23:28:39.9071380Z  and the text below is the list of opted in users. 2024-12-17T23:28:39.9072039Z  2024-12-17T23:28:39.9072739Z  If it doesn't contain "---" then the settings are empty and the default values are used. 2024-12-17T23:28:39.9073559Z  """ 2024-12-17T23:28:39.9074243Z  settings_text, _ = extract_settings_user_opt_in_from_text(rollout_state) 2024-12-17T23:28:39.9075121Z  return parse_settings_from_text(settings_text) 2024-12-17T23:28:39.9075760Z  2024-12-17T23:28:39.9076380Z  2024-12-17T23:28:39.9076945Z def parse_users(rollout_state: str) -> UserOptins: 2024-12-17T23:28:39.9077626Z  """ 2024-12-17T23:28:39.9078191Z  Parse users from the rollout state. 2024-12-17T23:28:39.9078775Z  2024-12-17T23:28:39.9079209Z  """ 2024-12-17T23:28:39.9079885Z  _, users_text = extract_settings_user_opt_in_from_text(rollout_state) 2024-12-17T23:28:39.9080720Z  return parse_user_opt_in_from_text(users_text) 2024-12-17T23:28:39.9081427Z  2024-12-17T23:28:39.9081819Z  2024-12-17T23:28:39.9082519Z def is_user_opted_in(user: str, user_optins: UserOptins, experiment_name: str) -> bool: 2024-12-17T23:28:39.9083421Z  """ 2024-12-17T23:28:39.9083928Z  Check if a user is opted into an experiment 2024-12-17T23:28:39.9084550Z  """ 2024-12-17T23:28:39.9085214Z  return experiment_name in user_optins.get(user, []) 2024-12-17T23:28:39.9085853Z  2024-12-17T23:28:39.9086275Z  2024-12-17T23:28:39.9087064Z def is_user_opted_out(user: str, user_optins: UserOptins, experiment_name: str) -> bool: 2024-12-17T23:28:39.9087866Z  """ 2024-12-17T23:28:39.9088439Z  Check if a user explicitly opted out of an experiment 2024-12-17T23:28:39.9089188Z  """ 2024-12-17T23:28:39.9089806Z  # if the experiment is prefixed with a "-", then it's an opt-out 2024-12-17T23:28:39.9090609Z  experiment_optout = "-" + experiment_name 2024-12-17T23:28:39.9091534Z  if experiment_optout not in user_optins.get(user, []): 2024-12-17T23:28:39.9092225Z  return False 2024-12-17T23:28:39.9092722Z  2024-12-17T23:28:39.9093345Z  if is_user_opted_in(user, user_optins, experiment_name): 2024-12-17T23:28:39.9094033Z  log.warning( 2024-12-17T23:28:39.9094916Z  f"User {user} is opted into experiment {experiment_name}, but also opted out of it. Defaulting to opting out" 2024-12-17T23:28:39.9095914Z  ) 2024-12-17T23:28:39.9096380Z  2024-12-17T23:28:39.9096968Z  return True 2024-12-17T23:28:39.9097534Z  2024-12-17T23:28:39.9097976Z  2024-12-17T23:28:39.9098386Z def get_runner_prefix( 2024-12-17T23:28:39.9099006Z  rollout_state: str, 2024-12-17T23:28:39.9099618Z  workflow_requestors: Iterable[str], 2024-12-17T23:28:39.9100210Z  branch: str, 2024-12-17T23:28:39.9100898Z  eligible_experiments: FrozenSet[str] = frozenset(), 2024-12-17T23:28:39.9101608Z  is_canary: bool = False, 2024-12-17T23:28:39.9102133Z ) -> str: 2024-12-17T23:28:39.9102743Z  settings = parse_settings(rollout_state) 2024-12-17T23:28:39.9103444Z  user_optins = parse_users(rollout_state) 2024-12-17T23:28:39.9104022Z  2024-12-17T23:28:39.9104614Z  fleet_prefix = "" 2024-12-17T23:28:39.9105160Z  prefixes = [] 2024-12-17T23:28:39.9105881Z  for experiment_name, experiment_settings in settings.experiments.items(): 2024-12-17T23:28:39.9107011Z  if not experiment_settings.all_branches and is_exception_branch(branch): 2024-12-17T23:28:39.9107916Z  log.info( 2024-12-17T23:28:39.9108727Z  f"Branch {branch} is an exception branch. Not enabling experiment {experiment_name}." 2024-12-17T23:28:39.9109768Z  ) 2024-12-17T23:28:39.9110266Z  continue 2024-12-17T23:28:39.9110755Z  2024-12-17T23:28:39.9111283Z  if eligible_experiments: 2024-12-17T23:28:39.9111969Z  if experiment_name not in eligible_experiments: 2024-12-17T23:28:39.9112693Z  exp_list = ", ".join(eligible_experiments) 2024-12-17T23:28:39.9113552Z  log.info( 2024-12-17T23:28:39.9114457Z  f"Skipping experiment '{experiment_name}', as it is not in the eligible_experiments list: {exp_list}" 2024-12-17T23:28:39.9115363Z  ) 2024-12-17T23:28:39.9115961Z  continue 2024-12-17T23:28:39.9116552Z  elif not experiment_settings.default: 2024-12-17T23:28:39.9117170Z  log.info( 2024-12-17T23:28:39.9118028Z  f"Skipping experiment '{experiment_name}', as it is not a default experiment" 2024-12-17T23:28:39.9118797Z  ) 2024-12-17T23:28:39.9119296Z  continue 2024-12-17T23:28:39.9120130Z  2024-12-17T23:28:39.9120819Z  # Is any workflow_requestor opted out to this experiment? 2024-12-17T23:28:39.9121522Z  opted_out_users = [ 2024-12-17T23:28:39.9122190Z  requestor 2024-12-17T23:28:39.9122778Z  for requestor in workflow_requestors 2024-12-17T23:28:39.9123681Z  if is_user_opted_out(requestor, user_optins, experiment_name) 2024-12-17T23:28:39.9124519Z  ] 2024-12-17T23:28:39.9124973Z  2024-12-17T23:28:39.9125416Z  if opted_out_users: 2024-12-17T23:28:39.9126072Z  log.info( 2024-12-17T23:28:39.9126826Z  f"{', '.join(opted_out_users)} have opted out of experiment {experiment_name}." 2024-12-17T23:28:39.9127546Z  ) 2024-12-17T23:28:39.9128141Z  continue 2024-12-17T23:28:39.9128645Z  2024-12-17T23:28:39.9129145Z  # Is any workflow_requestor opted in to this experiment? 2024-12-17T23:28:39.9129941Z  opted_in_users = [ 2024-12-17T23:28:39.9130496Z  requestor 2024-12-17T23:28:39.9131033Z  for requestor in workflow_requestors 2024-12-17T23:28:39.9131895Z  if is_user_opted_in(requestor, user_optins, experiment_name) 2024-12-17T23:28:39.9132635Z  ] 2024-12-17T23:28:39.9133050Z  2024-12-17T23:28:39.9133778Z  enabled = False 2024-12-17T23:28:39.9134325Z  if opted_in_users: 2024-12-17T23:28:39.9134832Z  log.info( 2024-12-17T23:28:39.9135672Z  f"{', '.join(opted_in_users)} have opted into experiment {experiment_name}." 2024-12-17T23:28:39.9136427Z  ) 2024-12-17T23:28:39.9136986Z  enabled = True 2024-12-17T23:28:39.9137505Z  2024-12-17T23:28:39.9137998Z  elif experiment_settings.rollout_perc: 2024-12-17T23:28:39.9138975Z  # If no user is opted in, then we randomly enable the experiment based on the rollout percentage 2024-12-17T23:28:39.9139989Z  if random.uniform(0, 100) <= experiment_settings.rollout_perc: 2024-12-17T23:28:39.9140770Z  log.info( 2024-12-17T23:28:39.9141847Z  f"Based on rollout percentage of {experiment_settings.rollout_perc}%, enabling experiment {experiment_name}." 2024-12-17T23:28:39.9142813Z  ) 2024-12-17T23:28:39.9143352Z  enabled = True 2024-12-17T23:28:39.9143965Z  2024-12-17T23:28:39.9144385Z  if enabled: 2024-12-17T23:28:39.9144956Z  label = experiment_name 2024-12-17T23:28:39.9145663Z  if experiment_name == LF_FLEET_EXPERIMENT: 2024-12-17T23:28:39.9146593Z  # We give some special treatment to the "lf" experiment since determines the fleet we use 2024-12-17T23:28:39.9147528Z  # - If it's enabled, then we always list it's prefix first 2024-12-17T23:28:39.9148580Z  # - If we're in the canary branch, then we append ".c" to the lf prefix 2024-12-17T23:28:39.9149699Z  if is_canary: 2024-12-17T23:28:39.9150299Z  label += CANARY_FLEET_SUFFIX 2024-12-17T23:28:39.9151005Z  fleet_prefix = label 2024-12-17T23:28:39.9151622Z  else: 2024-12-17T23:28:39.9152179Z  prefixes.append(label) 2024-12-17T23:28:39.9152782Z  2024-12-17T23:28:39.9153267Z  if len(prefixes) > 1: 2024-12-17T23:28:39.9153826Z  log.error( 2024-12-17T23:28:39.9154977Z  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-12-17T23:28:39.9156179Z  ) 2024-12-17T23:28:39.9156680Z  prefixes = prefixes[:1] 2024-12-17T23:28:39.9157277Z  2024-12-17T23:28:39.9157769Z  # Fleet always comes first 2024-12-17T23:28:39.9158350Z  if fleet_prefix: 2024-12-17T23:28:39.9158946Z  prefixes.insert(0, fleet_prefix) 2024-12-17T23:28:39.9159569Z  2024-12-17T23:28:39.9160106Z  return ".".join(prefixes) + "." if prefixes else "" 2024-12-17T23:28:39.9160793Z  2024-12-17T23:28:39.9161234Z  2024-12-17T23:28:39.9161953Z def get_rollout_state_from_issue(github_token: str, repo: str, issue_num: int) -> str: 2024-12-17T23:28:39.9162823Z  """ 2024-12-17T23:28:39.9163527Z  Gets the first comment of the issue, which contains the desired rollout state. 2024-12-17T23:28:39.9164305Z  2024-12-17T23:28:39.9165048Z  The default issue we use - https://github.com/pytorch/test-infra/issues/5132 2024-12-17T23:28:39.9165798Z  """ 2024-12-17T23:28:39.9166317Z  gh = get_gh_client(github_token) 2024-12-17T23:28:39.9167023Z  issue = get_issue(gh, repo, issue_num) 2024-12-17T23:28:39.9167738Z  return str(issue.get_comments()[0].body.strip("\n\t ")) 2024-12-17T23:28:39.9168427Z  2024-12-17T23:28:39.9168911Z  2024-12-17T23:28:39.9169551Z def download_json(url: str, headers: Dict[str, str], num_retries: int = 3) -> Any: 2024-12-17T23:28:39.9170576Z  for _ in range(num_retries): 2024-12-17T23:28:39.9171232Z  try: 2024-12-17T23:28:39.9171741Z  req = Request(url=url, headers=headers) 2024-12-17T23:28:39.9172531Z  content = urlopen(req, timeout=5).read().decode("utf-8") 2024-12-17T23:28:39.9173328Z  return json.loads(content) 2024-12-17T23:28:39.9173972Z  except Exception as e: 2024-12-17T23:28:39.9174595Z  log.warning(f"Could not download {url}: {e}") 2024-12-17T23:28:39.9175312Z  2024-12-17T23:28:39.9175990Z  log.warning(f"All {num_retries} retries exhausted, downloading {url} failed") 2024-12-17T23:28:39.9176758Z  return {} 2024-12-17T23:28:39.9177297Z  2024-12-17T23:28:39.9177733Z  2024-12-17T23:28:39.9178147Z @lru_cache(maxsize=None) 2024-12-17T23:28:39.9179041Z def get_pr_info(github_repo: str, github_token: str, pr_number: int) -> Dict[str, Any]: 2024-12-17T23:28:39.9179886Z  """ 2024-12-17T23:28:39.9180353Z  Dynamically get PR information 2024-12-17T23:28:39.9181015Z  """ 2024-12-17T23:28:39.9181625Z  github_api = f"https://api.github.com/repos/{github_repo}" 2024-12-17T23:28:39.9182303Z  headers = { 2024-12-17T23:28:39.9182977Z  "Accept": "application/vnd.github.v3+json", 2024-12-17T23:28:39.9183681Z  "Authorization": f"token {github_token}", 2024-12-17T23:28:39.9184259Z  } 2024-12-17T23:28:39.9184887Z  json_response: Dict[str, Any] = download_json( 2024-12-17T23:28:39.9185732Z  url=f"{github_api}/issues/{pr_number}", 2024-12-17T23:28:39.9186383Z  headers=headers, 2024-12-17T23:28:39.9186965Z  ) 2024-12-17T23:28:39.9187414Z  2024-12-17T23:28:39.9187865Z  if not json_response: 2024-12-17T23:28:39.9188604Z  log.warning(f"Failed to get the labels for #{pr_number}") 2024-12-17T23:28:39.9189438Z  return {} 2024-12-17T23:28:39.9189954Z  2024-12-17T23:28:39.9190449Z  return json_response 2024-12-17T23:28:39.9190993Z  2024-12-17T23:28:39.9191412Z  2024-12-17T23:28:39.9192129Z def get_labels(github_repo: str, github_token: str, pr_number: int) -> Set[str]: 2024-12-17T23:28:39.9192933Z  """ 2024-12-17T23:28:39.9193563Z  Dynamically get the latest list of labels from the pull request 2024-12-17T23:28:39.9194333Z  """ 2024-12-17T23:28:39.9194956Z  pr_info = get_pr_info(github_repo, github_token, pr_number) 2024-12-17T23:28:39.9195630Z  return { 2024-12-17T23:28:39.9196364Z  label.get("name") for label in pr_info.get("labels", []) if label.get("name") 2024-12-17T23:28:39.9197144Z  } 2024-12-17T23:28:39.9197568Z  2024-12-17T23:28:39.9198029Z  2024-12-17T23:28:39.9198482Z def main() -> None: 2024-12-17T23:28:39.9199001Z  args = parse_args() 2024-12-17T23:28:39.9199580Z  2024-12-17T23:28:39.9200103Z  runner_label_prefix = DEFAULT_LABEL_PREFIX 2024-12-17T23:28:39.9200714Z  2024-12-17T23:28:39.9201208Z  # Check if the PR is opt-out 2024-12-17T23:28:39.9201821Z  if args.pr_number: 2024-12-17T23:28:39.9202573Z  labels = get_labels(args.github_repo, args.github_token, int(args.pr_number)) 2024-12-17T23:28:39.9203496Z  if OPT_OUT_LABEL in labels: 2024-12-17T23:28:39.9204049Z  log.info( 2024-12-17T23:28:39.9204874Z  f"Opt-out runner determinator because #{args.pr_number} has {OPT_OUT_LABEL} label" 2024-12-17T23:28:39.9205795Z  ) 2024-12-17T23:28:39.9206601Z  set_github_output(GH_OUTPUT_KEY_LABEL_TYPE, runner_label_prefix) 2024-12-17T23:28:39.9207347Z  sys.exit() 2024-12-17T23:28:39.9207969Z  2024-12-17T23:28:39.9208356Z  try: 2024-12-17T23:28:39.9208880Z  rollout_state = get_rollout_state_from_issue( 2024-12-17T23:28:39.9209799Z  args.github_token, args.github_issue_repo, args.github_issue 2024-12-17T23:28:39.9210482Z  ) 2024-12-17T23:28:39.9210942Z  2024-12-17T23:28:39.9211498Z  username = get_potential_pr_author( 2024-12-17T23:28:39.9212089Z  args.github_token, 2024-12-17T23:28:39.9212674Z  args.github_repo, 2024-12-17T23:28:39.9213342Z  args.github_actor, 2024-12-17T23:28:39.9213902Z  args.github_ref_type, 2024-12-17T23:28:39.9214496Z  args.github_branch, 2024-12-17T23:28:39.9215152Z  ) 2024-12-17T23:28:39.9215633Z  2024-12-17T23:28:39.9216153Z  is_canary = args.github_repo == "pytorch/pytorch-canary" 2024-12-17T23:28:39.9216966Z  2024-12-17T23:28:39.9217488Z  runner_label_prefix = get_runner_prefix( 2024-12-17T23:28:39.9218258Z  rollout_state, 2024-12-17T23:28:39.9218887Z  (args.github_issue_owner, username), 2024-12-17T23:28:39.9219537Z  args.github_branch, 2024-12-17T23:28:39.9220161Z  args.eligible_experiments, 2024-12-17T23:28:39.9220798Z  is_canary, 2024-12-17T23:28:39.9221324Z  ) 2024-12-17T23:28:39.9221785Z  2024-12-17T23:28:39.9222275Z  except Exception as e: 2024-12-17T23:28:39.9222978Z  log.error( 2024-12-17T23:28:39.9223831Z  f"Failed to get issue. Defaulting to Meta runners and no experiments. Exception: {e}" 2024-12-17T23:28:39.9224698Z  ) 2024-12-17T23:28:39.9225153Z  2024-12-17T23:28:39.9225775Z  set_github_output(GH_OUTPUT_KEY_LABEL_TYPE, runner_label_prefix) 2024-12-17T23:28:39.9226543Z  2024-12-17T23:28:39.9226967Z  2024-12-17T23:28:39.9227414Z if __name__ == "__main__": 2024-12-17T23:28:39.9227996Z  main() 2024-12-17T23:28:39.9228456Z  2024-12-17T23:28:39.9228902Z EOF 2024-12-17T23:28:39.9229487Z  2024-12-17T23:28:39.9229962Z cat runner_determinator.py 2024-12-17T23:28:39.9572156Z shell: /usr/bin/bash -e {0} 2024-12-17T23:28:39.9573133Z env: 2024-12-17T23:28:39.9574081Z GITHUB_TOKEN: *** 2024-12-17T23:28:39.9574628Z ISSUE_NUMBER: 5132 2024-12-17T23:28:39.9575182Z TRIGGERING_ACTOR: malfet 2024-12-17T23:28:39.9575823Z ISSUE_OWNER: 2024-12-17T23:28:39.9576335Z CHECK_EXPERIMENTS: 2024-12-17T23:28:39.9576867Z PR_NUMBER: 2024-12-17T23:28:39.9577411Z ##[endgroup] 2024-12-17T23:28:39.9809404Z # flake8: noqa: G004 2024-12-17T23:28:39.9809932Z 2024-12-17T23:28:39.9810390Z # Note: Copies of this script in runner_determinator.py and _runner-determinator.yml 2024-12-17T23:28:39.9811402Z # must be kept in sync. You can do it easily by running the following command: 2024-12-17T23:28:39.9812189Z # python .github/scripts/update_runner_determinator.py 2024-12-17T23:28:39.9812769Z 2024-12-17T23:28:39.9812948Z """ 2024-12-17T23:28:39.9813587Z This runner determinator is used to determine which set of runners to run a 2024-12-17T23:28:39.9814559Z GitHub job on. It uses the first comment of a GitHub issue (by default 2024-12-17T23:28:39.9815489Z https://github.com/pytorch/test-infra/issues/5132) to define the configuration 2024-12-17T23:28:39.9816384Z of which runners should be used to run which job. 2024-12-17T23:28:39.9816794Z 2024-12-17T23:28:39.9817269Z The configuration has two parts, the settings and a list of opted-in users, 2024-12-17T23:28:39.9818190Z separated by a line containing "---". If the line is not present, the 2024-12-17T23:28:39.9819363Z settings are considered to be empty with only the second part, the user 2024-12-17T23:28:39.9820172Z list, defined. 2024-12-17T23:28:39.9820434Z 2024-12-17T23:28:39.9820822Z The first part is a YAML block that defines the rollout settings. This can be 2024-12-17T23:28:39.9821783Z used to define any settings that are needed to determine which runners to use. 2024-12-17T23:28:39.9822707Z It's fields are defined by the RolloutSettings class below. 2024-12-17T23:28:39.9823190Z 2024-12-17T23:28:39.9823603Z The second part is a list of users who are explicitly opted in to the LF fleet. 2024-12-17T23:28:39.9824471Z The user list is also a comma separated list of additional features or 2024-12-17T23:28:39.9825307Z experiments which the user could be opted in to. 2024-12-17T23:28:39.9825761Z 2024-12-17T23:28:39.9826013Z The user list has the following rules: 2024-12-17T23:28:39.9826389Z 2024-12-17T23:28:39.9826713Z - Users are GitHub usernames, which must start with the @ prefix 2024-12-17T23:28:39.9827682Z - Each user is also a comma-separated list of features/experiments to enable 2024-12-17T23:28:39.9828546Z - A "#" prefix opts the user out of all experiments 2024-12-17T23:28:39.9828954Z 2024-12-17T23:28:39.9829144Z Example config: 2024-12-17T23:28:39.9830108Z # A list of experiments that can be opted into. 2024-12-17T23:28:39.9830879Z # This defines the behavior they'll induce when opted into. 2024-12-17T23:28:39.9831524Z # Expected syntax is: 2024-12-17T23:28:39.9832294Z # [experiment_name]: # Name of the experiment. Also used for the label prefix. 2024-12-17T23:28:39.9833321Z # rollout_perc: [int] # % of workflows to run with this experiment when users are not opted in. 2024-12-17T23:28:39.9833928Z 2024-12-17T23:28:39.9834354Z experiments: 2024-12-17T23:28:39.9834878Z lf: 2024-12-17T23:28:39.9835357Z rollout_percent: 25 2024-12-17T23:28:39.9835906Z all_branches: false 2024-12-17T23:28:39.9836443Z default: true 2024-12-17T23:28:39.9836938Z --- 2024-12-17T23:28:39.9837153Z 2024-12-17T23:28:39.9837392Z # Opt-ins: 2024-12-17T23:28:39.9838048Z # Users can opt into the LF fleet by adding their GitHub username to this list 2024-12-17T23:28:39.9838978Z # and specifying experiments to enable in a comma-separated list. 2024-12-17T23:28:39.9839810Z # To always opt out of an experiment, prefix it with a "-". 2024-12-17T23:28:39.9840557Z # Experiments should be from the above list. 2024-12-17T23:28:39.9841003Z 2024-12-17T23:28:39.9841208Z @User1,-lf,split_build 2024-12-17T23:28:39.9841731Z @User2,lf 2024-12-17T23:28:39.9842202Z @User3,split_build 2024-12-17T23:28:39.9842721Z """ 2024-12-17T23:28:39.9842925Z 2024-12-17T23:28:39.9843149Z import json 2024-12-17T23:28:39.9843597Z import logging 2024-12-17T23:28:39.9844077Z import os 2024-12-17T23:28:39.9844508Z import random 2024-12-17T23:28:39.9844961Z import re 2024-12-17T23:28:39.9845426Z import sys 2024-12-17T23:28:39.9845884Z from argparse import ArgumentParser 2024-12-17T23:28:39.9846475Z from functools import lru_cache 2024-12-17T23:28:39.9847058Z from logging import LogRecord 2024-12-17T23:28:39.9847791Z from typing import Any, Dict, FrozenSet, Iterable, List, NamedTuple, Set, Tuple 2024-12-17T23:28:39.9848619Z from urllib.request import Request, urlopen 2024-12-17T23:28:39.9849076Z 2024-12-17T23:28:39.9849259Z import yaml 2024-12-17T23:28:39.9849706Z from github import Auth, Github 2024-12-17T23:28:39.9850271Z from github.Issue import Issue 2024-12-17T23:28:39.9850657Z 2024-12-17T23:28:39.9850664Z 2024-12-17T23:28:39.9850898Z DEFAULT_LABEL_PREFIX = "" # use meta runners 2024-12-17T23:28:39.9851637Z WORKFLOW_LABEL_LF = "lf." # use runners from the linux foundation 2024-12-17T23:28:39.9852548Z WORKFLOW_LABEL_LF_CANARY = "lf.c." # use canary runners from the linux foundation 2024-12-17T23:28:39.9853172Z 2024-12-17T23:28:39.9853414Z GITHUB_OUTPUT = os.getenv("GITHUB_OUTPUT", "") 2024-12-17T23:28:39.9854215Z GH_OUTPUT_KEY_AMI = "runner-ami" 2024-12-17T23:28:39.9854875Z GH_OUTPUT_KEY_LABEL_TYPE = "label-type" 2024-12-17T23:28:39.9855457Z OPT_OUT_LABEL = "no-runner-experiments" 2024-12-17T23:28:39.9855851Z 2024-12-17T23:28:39.9856082Z SETTING_EXPERIMENTS = "experiments" 2024-12-17T23:28:39.9856406Z 2024-12-17T23:28:39.9856738Z LF_FLEET_EXPERIMENT = "lf" 2024-12-17T23:28:39.9857222Z CANARY_FLEET_SUFFIX = ".c" 2024-12-17T23:28:39.9857552Z 2024-12-17T23:28:39.9857559Z 2024-12-17T23:28:39.9857781Z class Experiment(NamedTuple): 2024-12-17T23:28:39.9858397Z rollout_perc: float = ( 2024-12-17T23:28:39.9859056Z 0 # Percentage of workflows to experiment on when user is not opted-in. 2024-12-17T23:28:39.9859803Z ) 2024-12-17T23:28:39.9860300Z all_branches: bool = ( 2024-12-17T23:28:39.9860953Z False # If True, the experiment is also enabled on the exception branches 2024-12-17T23:28:39.9861693Z ) 2024-12-17T23:28:39.9862189Z default: bool = ( 2024-12-17T23:28:39.9862792Z True # If True, the experiment is enabled by default for all queries 2024-12-17T23:28:39.9863509Z ) 2024-12-17T23:28:39.9863702Z 2024-12-17T23:28:39.9864025Z # Add more fields as needed 2024-12-17T23:28:39.9864340Z 2024-12-17T23:28:39.9864346Z 2024-12-17T23:28:39.9864599Z class Settings(NamedTuple): 2024-12-17T23:28:39.9865067Z """ 2024-12-17T23:28:39.9865640Z Settings for the experiments that can be opted into. 2024-12-17T23:28:39.9866285Z """ 2024-12-17T23:28:39.9866494Z 2024-12-17T23:28:39.9866718Z experiments: Dict[str, Experiment] = {} 2024-12-17T23:28:39.9867173Z 2024-12-17T23:28:39.9867180Z 2024-12-17T23:28:39.9867420Z class ColorFormatter(logging.Formatter): 2024-12-17T23:28:39.9868116Z """Color codes the log messages based on the log level""" 2024-12-17T23:28:39.9868675Z 2024-12-17T23:28:39.9868872Z COLORS = { 2024-12-17T23:28:39.9869713Z "WARNING": "\033[33m", # Yellow 2024-12-17T23:28:39.9870313Z "ERROR": "\033[31m", # Red 2024-12-17T23:28:39.9870857Z "CRITICAL": "\033[31m", # Red 2024-12-17T23:28:39.9871515Z "INFO": "\033[0m", # Reset 2024-12-17T23:28:39.9872060Z "DEBUG": "\033[0m", # Reset 2024-12-17T23:28:39.9872555Z } 2024-12-17T23:28:39.9872850Z 2024-12-17T23:28:39.9873120Z def format(self, record: LogRecord) -> str: 2024-12-17T23:28:39.9873913Z log_color = self.COLORS.get(record.levelname, "\033[0m") # Default to reset 2024-12-17T23:28:39.9874691Z record.msg = f"{log_color}{record.msg}\033[0m" 2024-12-17T23:28:39.9875402Z return super().format(record) 2024-12-17T23:28:39.9875779Z 2024-12-17T23:28:39.9875787Z 2024-12-17T23:28:39.9876000Z handler = logging.StreamHandler() 2024-12-17T23:28:39.9876741Z handler.setFormatter(ColorFormatter(fmt="%(levelname)-8s: %(message)s")) 2024-12-17T23:28:39.9877372Z 2024-12-17T23:28:39.9877652Z log = logging.getLogger(os.path.basename(__file__)) 2024-12-17T23:28:39.9878294Z log.addHandler(handler) 2024-12-17T23:28:39.9878823Z log.setLevel(logging.INFO) 2024-12-17T23:28:39.9879189Z 2024-12-17T23:28:39.9879196Z 2024-12-17T23:28:39.9879473Z def set_github_output(key: str, value: str) -> None: 2024-12-17T23:28:39.9880082Z """ 2024-12-17T23:28:39.9880644Z Defines outputs of the github action that invokes this script 2024-12-17T23:28:39.9881374Z """ 2024-12-17T23:28:39.9881809Z if not GITHUB_OUTPUT: 2024-12-17T23:28:39.9882919Z # See https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/ for deprecation notice 2024-12-17T23:28:39.9884108Z log.warning( 2024-12-17T23:28:39.9884995Z "No env var found for GITHUB_OUTPUT, you must be running this code locally. Falling back to the deprecated print method." 2024-12-17T23:28:39.9885954Z ) 2024-12-17T23:28:39.9895788Z print(f"::set-output name={key}::{value}") 2024-12-17T23:28:39.9896442Z return 2024-12-17T23:28:39.9896727Z 2024-12-17T23:28:39.9896950Z with open(GITHUB_OUTPUT, "a") as f: 2024-12-17T23:28:39.9897953Z log.info(f"Setting output: {key}='{value}'") 2024-12-17T23:28:39.9898561Z f.write(f"{key}={value}\n") 2024-12-17T23:28:39.9898951Z 2024-12-17T23:28:39.9898960Z 2024-12-17T23:28:39.9899264Z def _str_comma_separated_to_set(value: str) -> FrozenSet[str]: 2024-12-17T23:28:39.9900047Z return frozenset( 2024-12-17T23:28:39.9900684Z filter(lambda itm: itm != "", map(str.strip, value.strip(" \n\t").split(","))) 2024-12-17T23:28:39.9901422Z ) 2024-12-17T23:28:39.9901697Z 2024-12-17T23:28:39.9901704Z 2024-12-17T23:28:39.9901957Z def parse_args() -> Any: 2024-12-17T23:28:39.9902552Z parser = ArgumentParser("Get dynamic rollout settings") 2024-12-17T23:28:39.9903450Z parser.add_argument("--github-token", type=str, required=True, help="GitHub token") 2024-12-17T23:28:39.9904344Z parser.add_argument( 2024-12-17T23:28:39.9904851Z "--github-issue-repo", 2024-12-17T23:28:39.9905361Z type=str, 2024-12-17T23:28:39.9905911Z required=False, 2024-12-17T23:28:39.9906400Z default="pytorch/test-infra", 2024-12-17T23:28:39.9906986Z help="GitHub repo to get the issue", 2024-12-17T23:28:39.9907637Z ) 2024-12-17T23:28:39.9908051Z parser.add_argument( 2024-12-17T23:28:39.9908540Z "--github-repo", 2024-12-17T23:28:39.9909127Z type=str, 2024-12-17T23:28:39.9909862Z required=True, 2024-12-17T23:28:39.9910759Z help="GitHub repo where CI is running", 2024-12-17T23:28:39.9911478Z ) 2024-12-17T23:28:39.9911878Z parser.add_argument( 2024-12-17T23:28:39.9912544Z "--github-issue", type=int, required=True, help="GitHub issue number" 2024-12-17T23:28:39.9913338Z ) 2024-12-17T23:28:39.9913730Z parser.add_argument( 2024-12-17T23:28:39.9914587Z "--github-actor", type=str, required=True, help="GitHub triggering_actor" 2024-12-17T23:28:39.9915438Z ) 2024-12-17T23:28:39.9915855Z parser.add_argument( 2024-12-17T23:28:39.9916534Z "--github-issue-owner", type=str, required=True, help="GitHub issue owner" 2024-12-17T23:28:39.9917356Z ) 2024-12-17T23:28:39.9917761Z parser.add_argument( 2024-12-17T23:28:39.9918453Z "--github-branch", type=str, required=True, help="Current GitHub branch or tag" 2024-12-17T23:28:39.9919299Z ) 2024-12-17T23:28:39.9919706Z parser.add_argument( 2024-12-17T23:28:39.9920205Z "--github-ref-type", 2024-12-17T23:28:39.9920817Z type=str, 2024-12-17T23:28:39.9921237Z required=True, 2024-12-17T23:28:39.9921767Z help="Current GitHub ref type, branch or tag", 2024-12-17T23:28:39.9922480Z ) 2024-12-17T23:28:39.9922895Z parser.add_argument( 2024-12-17T23:28:39.9923444Z "--eligible-experiments", 2024-12-17T23:28:39.9924112Z type=_str_comma_separated_to_set, 2024-12-17T23:28:39.9924665Z required=False, 2024-12-17T23:28:39.9925135Z default="", 2024-12-17T23:28:39.9926123Z help="comma separated list of experiments to check, if omitted all experiments marked with default=True are checked", 2024-12-17T23:28:39.9927048Z ) 2024-12-17T23:28:39.9927466Z parser.add_argument( 2024-12-17T23:28:39.9928057Z "--pr-number", 2024-12-17T23:28:39.9928502Z type=str, 2024-12-17T23:28:39.9928949Z required=False, 2024-12-17T23:28:39.9929533Z default="", 2024-12-17T23:28:39.9930029Z help="the optional PR number where this is run", 2024-12-17T23:28:39.9930623Z ) 2024-12-17T23:28:39.9930911Z 2024-12-17T23:28:39.9931169Z return parser.parse_args() 2024-12-17T23:28:39.9931493Z 2024-12-17T23:28:39.9931500Z 2024-12-17T23:28:39.9931779Z def get_gh_client(github_token: str) -> Github: 2024-12-17T23:28:39.9932368Z auth = Auth.Token(github_token) 2024-12-17T23:28:39.9933029Z return Github(auth=auth) 2024-12-17T23:28:39.9933337Z 2024-12-17T23:28:39.9933345Z 2024-12-17T23:28:39.9933687Z def get_issue(gh: Github, repo: str, issue_num: int) -> Issue: 2024-12-17T23:28:39.9934336Z repo = gh.get_repo(repo) 2024-12-17T23:28:39.9935151Z return repo.get_issue(number=issue_num) 2024-12-17T23:28:39.9935523Z 2024-12-17T23:28:39.9935529Z 2024-12-17T23:28:39.9935785Z def get_potential_pr_author( 2024-12-17T23:28:39.9936422Z github_token: str, repo: str, username: str, ref_type: str, ref_name: str 2024-12-17T23:28:39.9937226Z ) -> str: 2024-12-17T23:28:39.9937815Z # If the trigger was a new tag added by a bot, this is a ciflow case 2024-12-17T23:28:39.9938613Z # Fetch the actual username from the original PR. The PR number is 2024-12-17T23:28:39.9939488Z # embedded in the tag name: ciflow// 2024-12-17T23:28:39.9939962Z 2024-12-17T23:28:39.9940167Z gh = get_gh_client(github_token) 2024-12-17T23:28:39.9940537Z 2024-12-17T23:28:39.9940909Z if username == "pytorch-bot[bot]" and ref_type == "tag": 2024-12-17T23:28:39.9941586Z split_tag = ref_name.split("/") 2024-12-17T23:28:39.9942162Z if ( 2024-12-17T23:28:39.9942656Z len(split_tag) == 3 2024-12-17T23:28:39.9943178Z and split_tag[0] == "ciflow" 2024-12-17T23:28:39.9943780Z and split_tag[2].isnumeric() 2024-12-17T23:28:39.9944386Z ): 2024-12-17T23:28:39.9944841Z pr_number = split_tag[2] 2024-12-17T23:28:39.9945429Z try: 2024-12-17T23:28:39.9945988Z repository = gh.get_repo(repo) 2024-12-17T23:28:39.9946672Z pull = repository.get_pull(number=int(pr_number)) 2024-12-17T23:28:39.9947323Z except Exception as e: 2024-12-17T23:28:39.9947954Z raise Exception( # noqa: TRY002 2024-12-17T23:28:39.9948693Z f"issue with pull request {pr_number} from repo {repository}" 2024-12-17T23:28:39.9949685Z ) from e 2024-12-17T23:28:39.9950308Z return pull.user.login 2024-12-17T23:28:39.9951123Z # In all other cases, return the original input username 2024-12-17T23:28:39.9951789Z return username 2024-12-17T23:28:39.9952050Z 2024-12-17T23:28:39.9952062Z 2024-12-17T23:28:39.9952415Z def is_exception_branch(branch: str) -> bool: 2024-12-17T23:28:39.9953001Z """ 2024-12-17T23:28:39.9953688Z Branches that get opted out of experiments by default, until they're explicitly enabled. 2024-12-17T23:28:39.9954566Z """ 2024-12-17T23:28:39.9955148Z return branch.split("/")[0] in {"main", "nightly", "release", "landchecks"} 2024-12-17T23:28:39.9955720Z 2024-12-17T23:28:39.9955727Z 2024-12-17T23:28:39.9955941Z def load_yaml(yaml_text: str) -> Any: 2024-12-17T23:28:39.9956556Z try: 2024-12-17T23:28:39.9956989Z data = yaml.safe_load(yaml_text) 2024-12-17T23:28:39.9957555Z return data 2024-12-17T23:28:39.9958094Z except yaml.YAMLError: 2024-12-17T23:28:39.9958613Z log.exception("Error loading YAML") 2024-12-17T23:28:39.9959204Z raise 2024-12-17T23:28:39.9959435Z 2024-12-17T23:28:39.9959463Z 2024-12-17T23:28:39.9959939Z def extract_settings_user_opt_in_from_text(rollout_state: str) -> Tuple[str, str]: 2024-12-17T23:28:39.9960735Z """ 2024-12-17T23:28:39.9961380Z Extracts the text with settings, if any, and the opted in users from the rollout state. 2024-12-17T23:28:39.9961989Z 2024-12-17T23:28:39.9962403Z If the issue body contains "---" then the text above that is the settings 2024-12-17T23:28:39.9963221Z and the text below is the list of opted in users. 2024-12-17T23:28:39.9963653Z 2024-12-17T23:28:39.9964026Z If it doesn't contain "---" then the settings are empty and the rest is the users. 2024-12-17T23:28:39.9964818Z """ 2024-12-17T23:28:39.9965331Z rollout_state_parts = rollout_state.split("---") 2024-12-17T23:28:39.9965957Z if len(rollout_state_parts) >= 2: 2024-12-17T23:28:39.9966667Z return rollout_state_parts[0], rollout_state_parts[1] 2024-12-17T23:28:39.9967333Z else: 2024-12-17T23:28:39.9967743Z return "", rollout_state 2024-12-17T23:28:39.9968081Z 2024-12-17T23:28:39.9968087Z 2024-12-17T23:28:39.9968358Z class UserOptins(Dict[str, List[str]]): 2024-12-17T23:28:39.9969133Z """ 2024-12-17T23:28:39.9969708Z Dictionary of users with a list of features they have opted into 2024-12-17T23:28:39.9970423Z """ 2024-12-17T23:28:39.9970725Z 2024-12-17T23:28:39.9970731Z 2024-12-17T23:28:39.9971077Z def parse_user_opt_in_from_text(user_optin_text: str) -> UserOptins: 2024-12-17T23:28:39.9971774Z """ 2024-12-17T23:28:39.9972542Z Parse the user opt-in text into a key value pair of username and the list of features they have opted into 2024-12-17T23:28:39.9973279Z 2024-12-17T23:28:39.9973881Z Users are GitHub usernames with the @ prefix. Each user is also a comma-separated list of features/experiments to enable. 2024-12-17T23:28:39.9974893Z - Example line: "@User1,lf,split_build" 2024-12-17T23:28:39.9975636Z - A "#" prefix indicates the user is opted out of all experiments 2024-12-17T23:28:39.9976189Z 2024-12-17T23:28:39.9976195Z 2024-12-17T23:28:39.9976368Z """ 2024-12-17T23:28:39.9976793Z optins = UserOptins() 2024-12-17T23:28:39.9977415Z for user in user_optin_text.split("\n"): 2024-12-17T23:28:39.9977979Z user = user.strip("\r\n\t -") 2024-12-17T23:28:39.9978581Z if not user or not user.startswith("@"): 2024-12-17T23:28:39.9979268Z # Not a valid user. Skip 2024-12-17T23:28:39.9979790Z continue 2024-12-17T23:28:39.9980079Z 2024-12-17T23:28:39.9980258Z if user: 2024-12-17T23:28:39.9980827Z usr_name = user.split(",")[0].strip("@") 2024-12-17T23:28:39.9981543Z optins[usr_name] = [exp.strip(" ") for exp in user.split(",")[1:]] 2024-12-17T23:28:39.9982073Z 2024-12-17T23:28:39.9982272Z return optins 2024-12-17T23:28:39.9982505Z 2024-12-17T23:28:39.9982511Z 2024-12-17T23:28:39.9982918Z def is_valid_experiment_name(experiment_name: str) -> bool: 2024-12-17T23:28:39.9983675Z """ 2024-12-17T23:28:39.9984167Z Check if the experiment name is valid. 2024-12-17T23:28:39.9984815Z A valid name: 2024-12-17T23:28:39.9985460Z - Contains only alphanumeric characters and the special characters "_" & "-" 2024-12-17T23:28:39.9986443Z - The special characters "_" & "-" shouldn't be the first or last characters 2024-12-17T23:28:39.9987342Z - Cannot contain spaces 2024-12-17T23:28:39.9987846Z """ 2024-12-17T23:28:39.9988110Z 2024-12-17T23:28:39.9988381Z valid_char_regex = r"^[a-zA-Z0-9]([\w-]*[a-zA-Z0-9])?$" 2024-12-17T23:28:39.9989200Z valid = bool(re.match(valid_char_regex, experiment_name)) 2024-12-17T23:28:39.9989927Z 2024-12-17T23:28:39.9990173Z if valid: 2024-12-17T23:28:39.9990583Z return True 2024-12-17T23:28:39.9990930Z 2024-12-17T23:28:39.9991128Z log.error( 2024-12-17T23:28:39.9992600Z f"Invalid experiment name: {experiment_name}. Experiment names should only contain alphanumeric characters, '_', and '-'. They cannot contain spaces, and the special characters '_' and '-' cannot be the first or last characters." 2024-12-17T23:28:39.9994089Z ) 2024-12-17T23:28:39.9994577Z return False 2024-12-17T23:28:39.9994847Z 2024-12-17T23:28:39.9994853Z 2024-12-17T23:28:39.9995204Z def parse_settings_from_text(settings_text: str) -> Settings: 2024-12-17T23:28:39.9995844Z """ 2024-12-17T23:28:39.9996557Z Parse the experiments from the issue body into a list of ExperimentSettings 2024-12-17T23:28:39.9997337Z """ 2024-12-17T23:28:39.9997712Z try: 2024-12-17T23:28:39.9998222Z if settings_text: 2024-12-17T23:28:39.9998990Z # Escape the backtick as well so that we can have the settings in a code block on the GH issue 2024-12-17T23:28:39.9999777Z # for easy reading 2024-12-17T23:28:40.0000674Z # Note: Using ascii for the backtick so that the cat step in _runner-determinator.yml doesn't choke on 2024-12-17T23:28:40.0001590Z # the backtick character in shell commands. 2024-12-17T23:28:40.0002232Z backtick = chr(96) # backtick character 2024-12-17T23:28:40.0003002Z settings_text = settings_text.strip(f"\r\n\t{backtick} ") 2024-12-17T23:28:40.0003903Z settings = load_yaml(settings_text) 2024-12-17T23:28:40.0004280Z 2024-12-17T23:28:40.0004742Z # For now we just load experiments. We can expand this if/when we add more settings 2024-12-17T23:28:40.0005578Z experiments = {} 2024-12-17T23:28:40.0005917Z 2024-12-17T23:28:40.0006282Z for exp_name, exp_settings in settings.get(SETTING_EXPERIMENTS).items(): 2024-12-17T23:28:40.0007082Z if not is_valid_experiment_name(exp_name): 2024-12-17T23:28:40.0008279Z # Exclude invalid experiments from the list. We log an error, but don't raise an exception so that other experiments can still be processed. 2024-12-17T23:28:40.0009302Z continue 2024-12-17T23:28:40.0009647Z 2024-12-17T23:28:40.0009837Z valid_settings = {} 2024-12-17T23:28:40.0010482Z for setting in exp_settings: 2024-12-17T23:28:40.0011064Z if setting not in Experiment._fields: 2024-12-17T23:28:40.0011677Z log.warning( 2024-12-17T23:28:40.0012500Z f"Unexpected setting in experiment: {setting} = {exp_settings[setting]}" 2024-12-17T23:28:40.0013232Z ) 2024-12-17T23:28:40.0013725Z else: 2024-12-17T23:28:40.0014375Z valid_settings[setting] = exp_settings[setting] 2024-12-17T23:28:40.0014801Z 2024-12-17T23:28:40.0015096Z experiments[exp_name] = Experiment(**valid_settings) 2024-12-17T23:28:40.0015755Z return Settings(experiments) 2024-12-17T23:28:40.0016182Z 2024-12-17T23:28:40.0016424Z except Exception: 2024-12-17T23:28:40.0016937Z log.exception("Failed to parse settings") 2024-12-17T23:28:40.0017366Z 2024-12-17T23:28:40.0017682Z return Settings() 2024-12-17T23:28:40.0018082Z 2024-12-17T23:28:40.0018088Z 2024-12-17T23:28:40.0018376Z def parse_settings(rollout_state: str) -> Settings: 2024-12-17T23:28:40.0018999Z """ 2024-12-17T23:28:40.0019441Z Parse settings, if any, from the rollout state. 2024-12-17T23:28:40.0019949Z 2024-12-17T23:28:40.0020323Z If the issue body contains "---" then the text above that is the settings 2024-12-17T23:28:40.0021131Z and the text below is the list of opted in users. 2024-12-17T23:28:40.0021533Z 2024-12-17T23:28:40.0021923Z If it doesn't contain "---" then the settings are empty and the default values are used. 2024-12-17T23:28:40.0022796Z """ 2024-12-17T23:28:40.0023423Z settings_text, _ = extract_settings_user_opt_in_from_text(rollout_state) 2024-12-17T23:28:40.0024168Z return parse_settings_from_text(settings_text) 2024-12-17T23:28:40.0024711Z 2024-12-17T23:28:40.0024717Z 2024-12-17T23:28:40.0024980Z def parse_users(rollout_state: str) -> UserOptins: 2024-12-17T23:28:40.0025585Z """ 2024-12-17T23:28:40.0026081Z Parse users from the rollout state. 2024-12-17T23:28:40.0026476Z 2024-12-17T23:28:40.0026649Z """ 2024-12-17T23:28:40.0027229Z _, users_text = extract_settings_user_opt_in_from_text(rollout_state) 2024-12-17T23:28:40.0028077Z return parse_user_opt_in_from_text(users_text) 2024-12-17T23:28:40.0028496Z 2024-12-17T23:28:40.0028502Z 2024-12-17T23:28:40.0028918Z def is_user_opted_in(user: str, user_optins: UserOptins, experiment_name: str) -> bool: 2024-12-17T23:28:40.0030087Z """ 2024-12-17T23:28:40.0030643Z Check if a user is opted into an experiment 2024-12-17T23:28:40.0031218Z """ 2024-12-17T23:28:40.0031716Z return experiment_name in user_optins.get(user, []) 2024-12-17T23:28:40.0032133Z 2024-12-17T23:28:40.0032138Z 2024-12-17T23:28:40.0032659Z def is_user_opted_out(user: str, user_optins: UserOptins, experiment_name: str) -> bool: 2024-12-17T23:28:40.0033457Z """ 2024-12-17T23:28:40.0033933Z Check if a user explicitly opted out of an experiment 2024-12-17T23:28:40.0034633Z """ 2024-12-17T23:28:40.0035196Z # if the experiment is prefixed with a "-", then it's an opt-out 2024-12-17T23:28:40.0036097Z experiment_optout = "-" + experiment_name 2024-12-17T23:28:40.0036839Z if experiment_optout not in user_optins.get(user, []): 2024-12-17T23:28:40.0037514Z return False 2024-12-17T23:28:40.0037795Z 2024-12-17T23:28:40.0038078Z if is_user_opted_in(user, user_optins, experiment_name): 2024-12-17T23:28:40.0038783Z log.warning( 2024-12-17T23:28:40.0039624Z f"User {user} is opted into experiment {experiment_name}, but also opted out of it. Defaulting to opting out" 2024-12-17T23:28:40.0040515Z ) 2024-12-17T23:28:40.0040729Z 2024-12-17T23:28:40.0041109Z return True 2024-12-17T23:28:40.0041378Z 2024-12-17T23:28:40.0041384Z 2024-12-17T23:28:40.0041625Z def get_runner_prefix( 2024-12-17T23:28:40.0042092Z rollout_state: str, 2024-12-17T23:28:40.0042650Z workflow_requestors: Iterable[str], 2024-12-17T23:28:40.0043242Z branch: str, 2024-12-17T23:28:40.0043739Z eligible_experiments: FrozenSet[str] = frozenset(), 2024-12-17T23:28:40.0044438Z is_canary: bool = False, 2024-12-17T23:28:40.0044987Z ) -> str: 2024-12-17T23:28:40.0045424Z settings = parse_settings(rollout_state) 2024-12-17T23:28:40.0046095Z user_optins = parse_users(rollout_state) 2024-12-17T23:28:40.0046494Z 2024-12-17T23:28:40.0046719Z fleet_prefix = "" 2024-12-17T23:28:40.0047157Z prefixes = [] 2024-12-17T23:28:40.0047881Z for experiment_name, experiment_settings in settings.experiments.items(): 2024-12-17T23:28:40.0048871Z if not experiment_settings.all_branches and is_exception_branch(branch): 2024-12-17T23:28:40.0049615Z log.info( 2024-12-17T23:28:40.0050340Z f"Branch {branch} is an exception branch. Not enabling experiment {experiment_name}." 2024-12-17T23:28:40.0051162Z ) 2024-12-17T23:28:40.0051743Z continue 2024-12-17T23:28:40.0052022Z 2024-12-17T23:28:40.0052301Z if eligible_experiments: 2024-12-17T23:28:40.0052929Z if experiment_name not in eligible_experiments: 2024-12-17T23:28:40.0053633Z exp_list = ", ".join(eligible_experiments) 2024-12-17T23:28:40.0054263Z log.info( 2024-12-17T23:28:40.0055100Z f"Skipping experiment '{experiment_name}', as it is not in the eligible_experiments list: {exp_list}" 2024-12-17T23:28:40.0055986Z ) 2024-12-17T23:28:40.0056448Z continue 2024-12-17T23:28:40.0056988Z elif not experiment_settings.default: 2024-12-17T23:28:40.0057579Z log.info( 2024-12-17T23:28:40.0058307Z f"Skipping experiment '{experiment_name}', as it is not a default experiment" 2024-12-17T23:28:40.0059099Z ) 2024-12-17T23:28:40.0059547Z continue 2024-12-17T23:28:40.0059785Z 2024-12-17T23:28:40.0060137Z # Is any workflow_requestor opted out to this experiment? 2024-12-17T23:28:40.0060820Z opted_out_users = [ 2024-12-17T23:28:40.0061335Z requestor 2024-12-17T23:28:40.0061853Z for requestor in workflow_requestors 2024-12-17T23:28:40.0062588Z if is_user_opted_out(requestor, user_optins, experiment_name) 2024-12-17T23:28:40.0063278Z ] 2024-12-17T23:28:40.0063480Z 2024-12-17T23:28:40.0063736Z if opted_out_users: 2024-12-17T23:28:40.0064279Z log.info( 2024-12-17T23:28:40.0064943Z f"{', '.join(opted_out_users)} have opted out of experiment {experiment_name}." 2024-12-17T23:28:40.0065693Z ) 2024-12-17T23:28:40.0066162Z continue 2024-12-17T23:28:40.0066420Z 2024-12-17T23:28:40.0066733Z # Is any workflow_requestor opted in to this experiment? 2024-12-17T23:28:40.0067469Z opted_in_users = [ 2024-12-17T23:28:40.0067959Z requestor 2024-12-17T23:28:40.0068468Z for requestor in workflow_requestors 2024-12-17T23:28:40.0069244Z if is_user_opted_in(requestor, user_optins, experiment_name) 2024-12-17T23:28:40.0071290Z ] 2024-12-17T23:28:40.0071555Z 2024-12-17T23:28:40.0071933Z enabled = False 2024-12-17T23:28:40.0072544Z if opted_in_users: 2024-12-17T23:28:40.0073021Z log.info( 2024-12-17T23:28:40.0073675Z f"{', '.join(opted_in_users)} have opted into experiment {experiment_name}." 2024-12-17T23:28:40.0074474Z ) 2024-12-17T23:28:40.0074890Z enabled = True 2024-12-17T23:28:40.0075221Z 2024-12-17T23:28:40.0075448Z elif experiment_settings.rollout_perc: 2024-12-17T23:28:40.0076392Z # If no user is opted in, then we randomly enable the experiment based on the rollout percentage 2024-12-17T23:28:40.0077327Z if random.uniform(0, 100) <= experiment_settings.rollout_perc: 2024-12-17T23:28:40.0078016Z log.info( 2024-12-17T23:28:40.0078993Z f"Based on rollout percentage of {experiment_settings.rollout_perc}%, enabling experiment {experiment_name}." 2024-12-17T23:28:40.0079914Z ) 2024-12-17T23:28:40.0080434Z enabled = True 2024-12-17T23:28:40.0080724Z 2024-12-17T23:28:40.0081023Z if enabled: 2024-12-17T23:28:40.0081460Z label = experiment_name 2024-12-17T23:28:40.0082071Z if experiment_name == LF_FLEET_EXPERIMENT: 2024-12-17T23:28:40.0083008Z # We give some special treatment to the "lf" experiment since determines the fleet we use 2024-12-17T23:28:40.0083912Z # - If it's enabled, then we always list it's prefix first 2024-12-17T23:28:40.0084688Z # - If we're in the canary branch, then we append ".c" to the lf prefix 2024-12-17T23:28:40.0085488Z if is_canary: 2024-12-17T23:28:40.0086028Z label += CANARY_FLEET_SUFFIX 2024-12-17T23:28:40.0086604Z fleet_prefix = label 2024-12-17T23:28:40.0087398Z else: 2024-12-17T23:28:40.0087920Z prefixes.append(label) 2024-12-17T23:28:40.0088277Z 2024-12-17T23:28:40.0088474Z if len(prefixes) > 1: 2024-12-17T23:28:40.0089054Z log.error( 2024-12-17T23:28:40.0090114Z 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-12-17T23:28:40.0091209Z ) 2024-12-17T23:28:40.0091738Z prefixes = prefixes[:1] 2024-12-17T23:28:40.0092071Z 2024-12-17T23:28:40.0092315Z # Fleet always comes first 2024-12-17T23:28:40.0092798Z if fleet_prefix: 2024-12-17T23:28:40.0093367Z prefixes.insert(0, fleet_prefix) 2024-12-17T23:28:40.0093745Z 2024-12-17T23:28:40.0094038Z return ".".join(prefixes) + "." if prefixes else "" 2024-12-17T23:28:40.0094446Z 2024-12-17T23:28:40.0094452Z 2024-12-17T23:28:40.0094906Z def get_rollout_state_from_issue(github_token: str, repo: str, issue_num: int) -> str: 2024-12-17T23:28:40.0095766Z """ 2024-12-17T23:28:40.0096386Z Gets the first comment of the issue, which contains the desired rollout state. 2024-12-17T23:28:40.0096928Z 2024-12-17T23:28:40.0097334Z The default issue we use - https://github.com/pytorch/test-infra/issues/5132 2024-12-17T23:28:40.0098138Z """ 2024-12-17T23:28:40.0098581Z gh = get_gh_client(github_token) 2024-12-17T23:28:40.0099151Z issue = get_issue(gh, repo, issue_num) 2024-12-17T23:28:40.0099886Z return str(issue.get_comments()[0].body.strip("\n\t ")) 2024-12-17T23:28:40.0100382Z 2024-12-17T23:28:40.0100388Z 2024-12-17T23:28:40.0100790Z def download_json(url: str, headers: Dict[str, str], num_retries: int = 3) -> Any: 2024-12-17T23:28:40.0101561Z for _ in range(num_retries): 2024-12-17T23:28:40.0102145Z try: 2024-12-17T23:28:40.0102623Z req = Request(url=url, headers=headers) 2024-12-17T23:28:40.0103309Z content = urlopen(req, timeout=5).read().decode("utf-8") 2024-12-17T23:28:40.0104099Z return json.loads(content) 2024-12-17T23:28:40.0104644Z except Exception as e: 2024-12-17T23:28:40.0105241Z log.warning(f"Could not download {url}: {e}") 2024-12-17T23:28:40.0105858Z 2024-12-17T23:28:40.0106295Z log.warning(f"All {num_retries} retries exhausted, downloading {url} failed") 2024-12-17T23:28:40.0107008Z return {} 2024-12-17T23:28:40.0107287Z 2024-12-17T23:28:40.0107295Z 2024-12-17T23:28:40.0107473Z @lru_cache(maxsize=None) 2024-12-17T23:28:40.0108295Z def get_pr_info(github_repo: str, github_token: str, pr_number: int) -> Dict[str, Any]: 2024-12-17T23:28:40.0109246Z """ 2024-12-17T23:28:40.0109947Z Dynamically get PR information 2024-12-17T23:28:40.0110611Z """ 2024-12-17T23:28:40.0111143Z github_api = f"https://api.github.com/repos/{github_repo}" 2024-12-17T23:28:40.0111794Z headers = { 2024-12-17T23:28:40.0112394Z "Accept": "application/vnd.github.v3+json", 2024-12-17T23:28:40.0113031Z "Authorization": f"token {github_token}", 2024-12-17T23:28:40.0113598Z } 2024-12-17T23:28:40.0114151Z json_response: Dict[str, Any] = download_json( 2024-12-17T23:28:40.0114781Z url=f"{github_api}/issues/{pr_number}", 2024-12-17T23:28:40.0115366Z headers=headers, 2024-12-17T23:28:40.0115941Z ) 2024-12-17T23:28:40.0116168Z 2024-12-17T23:28:40.0116363Z if not json_response: 2024-12-17T23:28:40.0116954Z log.warning(f"Failed to get the labels for #{pr_number}") 2024-12-17T23:28:40.0117708Z return {} 2024-12-17T23:28:40.0117954Z 2024-12-17T23:28:40.0118149Z return json_response 2024-12-17T23:28:40.0118466Z 2024-12-17T23:28:40.0118472Z 2024-12-17T23:28:40.0118855Z def get_labels(github_repo: str, github_token: str, pr_number: int) -> Set[str]: 2024-12-17T23:28:40.0119708Z """ 2024-12-17T23:28:40.0120275Z Dynamically get the latest list of labels from the pull request 2024-12-17T23:28:40.0120917Z """ 2024-12-17T23:28:40.0121719Z pr_info = get_pr_info(github_repo, github_token, pr_number) 2024-12-17T23:28:40.0122399Z return { 2024-12-17T23:28:40.0122971Z label.get("name") for label in pr_info.get("labels", []) if label.get("name") 2024-12-17T23:28:40.0123831Z } 2024-12-17T23:28:40.0124044Z 2024-12-17T23:28:40.0124050Z 2024-12-17T23:28:40.0124270Z def main() -> None: 2024-12-17T23:28:40.0124692Z args = parse_args() 2024-12-17T23:28:40.0125097Z 2024-12-17T23:28:40.0125330Z runner_label_prefix = DEFAULT_LABEL_PREFIX 2024-12-17T23:28:40.0125716Z 2024-12-17T23:28:40.0125955Z # Check if the PR is opt-out 2024-12-17T23:28:40.0126456Z if args.pr_number: 2024-12-17T23:28:40.0127229Z labels = get_labels(args.github_repo, args.github_token, int(args.pr_number)) 2024-12-17T23:28:40.0128010Z if OPT_OUT_LABEL in labels: 2024-12-17T23:28:40.0128514Z log.info( 2024-12-17T23:28:40.0129310Z f"Opt-out runner determinator because #{args.pr_number} has {OPT_OUT_LABEL} label" 2024-12-17T23:28:40.0130105Z ) 2024-12-17T23:28:40.0130678Z set_github_output(GH_OUTPUT_KEY_LABEL_TYPE, runner_label_prefix) 2024-12-17T23:28:40.0131473Z sys.exit() 2024-12-17T23:28:40.0131783Z 2024-12-17T23:28:40.0131976Z try: 2024-12-17T23:28:40.0132499Z rollout_state = get_rollout_state_from_issue( 2024-12-17T23:28:40.0133225Z args.github_token, args.github_issue_repo, args.github_issue 2024-12-17T23:28:40.0133909Z ) 2024-12-17T23:28:40.0134124Z 2024-12-17T23:28:40.0134419Z username = get_potential_pr_author( 2024-12-17T23:28:40.0134984Z args.github_token, 2024-12-17T23:28:40.0135526Z args.github_repo, 2024-12-17T23:28:40.0136111Z args.github_actor, 2024-12-17T23:28:40.0136625Z args.github_ref_type, 2024-12-17T23:28:40.0137184Z args.github_branch, 2024-12-17T23:28:40.0137752Z ) 2024-12-17T23:28:40.0137987Z 2024-12-17T23:28:40.0138284Z is_canary = args.github_repo == "pytorch/pytorch-canary" 2024-12-17T23:28:40.0138778Z 2024-12-17T23:28:40.0139003Z runner_label_prefix = get_runner_prefix( 2024-12-17T23:28:40.0139643Z rollout_state, 2024-12-17T23:28:40.0140358Z (args.github_issue_owner, username), 2024-12-17T23:28:40.0140949Z args.github_branch, 2024-12-17T23:28:40.0141544Z args.eligible_experiments, 2024-12-17T23:28:40.0142103Z is_canary, 2024-12-17T23:28:40.0142562Z ) 2024-12-17T23:28:40.0142925Z 2024-12-17T23:28:40.0143177Z except Exception as e: 2024-12-17T23:28:40.0143645Z log.error( 2024-12-17T23:28:40.0144337Z f"Failed to get issue. Defaulting to Meta runners and no experiments. Exception: {e}" 2024-12-17T23:28:40.0145231Z ) 2024-12-17T23:28:40.0145446Z 2024-12-17T23:28:40.0145783Z set_github_output(GH_OUTPUT_KEY_LABEL_TYPE, runner_label_prefix) 2024-12-17T23:28:40.0146308Z 2024-12-17T23:28:40.0146315Z 2024-12-17T23:28:40.0146488Z if __name__ == "__main__": 2024-12-17T23:28:40.0147082Z main() 2024-12-17T23:28:40.0147301Z 2024-12-17T23:28:40.0239140Z ##[group]Run python3 -m pip install urllib3==1.26.18 PyGithub==2.3.0 2024-12-17T23:28:40.0240092Z python3 -m pip install urllib3==1.26.18 PyGithub==2.3.0 2024-12-17T23:28:40.0296765Z shell: /usr/bin/bash -e {0} 2024-12-17T23:28:40.0297307Z env: 2024-12-17T23:28:40.0297934Z GITHUB_TOKEN: *** 2024-12-17T23:28:40.0298536Z ISSUE_NUMBER: 5132 2024-12-17T23:28:40.0299021Z TRIGGERING_ACTOR: malfet 2024-12-17T23:28:40.0299475Z ISSUE_OWNER: 2024-12-17T23:28:40.0300035Z CHECK_EXPERIMENTS: 2024-12-17T23:28:40.0300510Z PR_NUMBER: 2024-12-17T23:28:40.0300920Z ##[endgroup] 2024-12-17T23:28:40.4489022Z Defaulting to user installation because normal site-packages is not writeable 2024-12-17T23:28:40.8334895Z Collecting urllib3==1.26.18 2024-12-17T23:28:40.8886785Z Downloading urllib3-1.26.18-py2.py3-none-any.whl (143 kB) 2024-12-17T23:28:40.9224820Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 143.8/143.8 KB 5.9 MB/s eta 0:00:00 2024-12-17T23:28:40.9484858Z Collecting PyGithub==2.3.0 2024-12-17T23:28:40.9544308Z Downloading PyGithub-2.3.0-py3-none-any.whl (354 kB) 2024-12-17T23:28:40.9684555Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 354.4/354.4 KB 29.0 MB/s eta 0:00:00 2024-12-17T23:28:41.0148356Z Collecting typing-extensions>=4.0.0 2024-12-17T23:28:41.0190477Z Downloading typing_extensions-4.12.2-py3-none-any.whl (37 kB) 2024-12-17T23:28:41.0222350Z Requirement already satisfied: requests>=2.14.0 in /usr/lib/python3/dist-packages (from PyGithub==2.3.0) (2.25.1) 2024-12-17T23:28:41.0442896Z Collecting Deprecated 2024-12-17T23:28:41.0483241Z Downloading Deprecated-1.2.15-py2.py3-none-any.whl (9.9 kB) 2024-12-17T23:28:41.0826294Z Collecting pynacl>=1.4.0 2024-12-17T23:28:41.0868044Z Downloading PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl (856 kB) 2024-12-17T23:28:41.1263796Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 856.7/856.7 KB 22.7 MB/s eta 0:00:00 2024-12-17T23:28:41.1574398Z Collecting pyjwt[crypto]>=2.4.0 2024-12-17T23:28:41.1611600Z Downloading PyJWT-2.10.1-py3-none-any.whl (22 kB) 2024-12-17T23:28:41.1745775Z 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-12-17T23:28:41.3965637Z Collecting cffi>=1.4.1 2024-12-17T23:28:41.4007071Z Downloading cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (446 kB) 2024-12-17T23:28:41.4103037Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 446.2/446.2 KB 58.3 MB/s eta 0:00:00 2024-12-17T23:28:41.6020159Z Collecting wrapt<2,>=1.10 2024-12-17T23:28:41.6076033Z Downloading wrapt-1.17.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (82 kB) 2024-12-17T23:28:41.6116282Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 82.7/82.7 KB 33.5 MB/s eta 0:00:00 2024-12-17T23:28:41.6278088Z Collecting pycparser 2024-12-17T23:28:41.6315822Z Downloading pycparser-2.22-py3-none-any.whl (117 kB) 2024-12-17T23:28:41.6359585Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 117.6/117.6 KB 45.0 MB/s eta 0:00:00 2024-12-17T23:28:41.8140420Z Installing collected packages: wrapt, urllib3, typing-extensions, pyjwt, pycparser, Deprecated, cffi, pynacl, PyGithub 2024-12-17T23:28:42.2791435Z Successfully installed Deprecated-1.2.15 PyGithub-2.3.0 cffi-1.17.1 pycparser-2.22 pyjwt-2.10.1 pynacl-1.5.0 typing-extensions-4.12.2 urllib3-1.26.18 wrapt-1.17.0 2024-12-17T23:28:42.3472823Z ##[group]Run curr_branch="release/2.6" 2024-12-17T23:28:42.3473438Z curr_branch="release/2.6" 2024-12-17T23:28:42.3473857Z curr_ref_type="branch" 2024-12-17T23:28:42.3474211Z echo "Current branch is '$curr_branch'" 2024-12-17T23:28:42.3474702Z  2024-12-17T23:28:42.3475038Z python3 runner_determinator.py \ 2024-12-17T23:28:42.3475411Z  --github-token "$GITHUB_TOKEN" \ 2024-12-17T23:28:42.3475883Z  --github-issue "$ISSUE_NUMBER" \ 2024-12-17T23:28:42.3476293Z  --github-branch "$curr_branch" \ 2024-12-17T23:28:42.3476662Z  --github-actor "$TRIGGERING_ACTOR" \ 2024-12-17T23:28:42.3477141Z  --github-issue-owner "$ISSUE_OWNER" \ 2024-12-17T23:28:42.3477590Z  --github-ref-type "$curr_ref_type" \ 2024-12-17T23:28:42.3477958Z  --github-repo "$GITHUB_REPOSITORY" \ 2024-12-17T23:28:42.3478472Z  --eligible-experiments "$CHECK_EXPERIMENTS" \ 2024-12-17T23:28:42.3478978Z  --pr-number "${PR_NUMBER}" 2024-12-17T23:28:42.3536581Z shell: /usr/bin/bash -e {0} 2024-12-17T23:28:42.3536938Z env: 2024-12-17T23:28:42.3537797Z GITHUB_TOKEN: *** 2024-12-17T23:28:42.3538156Z ISSUE_NUMBER: 5132 2024-12-17T23:28:42.3538448Z TRIGGERING_ACTOR: malfet 2024-12-17T23:28:42.3538862Z ISSUE_OWNER: 2024-12-17T23:28:42.3539183Z CHECK_EXPERIMENTS: 2024-12-17T23:28:42.3539522Z PR_NUMBER: 2024-12-17T23:28:42.3539885Z ##[endgroup] 2024-12-17T23:28:42.3615289Z Current branch is 'release/2.6' 2024-12-17T23:28:43.7257727Z INFO : Based on rollout percentage of 95%, enabling experiment lf. 2024-12-17T23:28:43.7258991Z INFO : Skipping experiment 'awsa100', as it is not a default experiment 2024-12-17T23:28:43.7260227Z INFO : Setting output: label-type='lf.' 2024-12-17T23:28:43.7550913Z Evaluate and set job outputs 2024-12-17T23:28:43.7558531Z Set output 'label-type' 2024-12-17T23:28:43.7561013Z Cleaning up orphan processes