- 
                Notifications
    
You must be signed in to change notification settings  - Fork 13
 
Adding python script to easily obtain key customer info #41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
          
     Open
      
      
            sarahraza007
  wants to merge
  27
  commits into
  main
  
    
      
        
          
  
    
      Choose a base branch
      
     
    
      
        
      
      
        
          
          
        
        
          
            
              
              
              
  
           
        
        
          
            
              
              
           
        
       
     
  
        
          
            
          
            
          
        
       
    
      
from
sarah/understand-customer-script
  
      
      
   
  
    
  
  
  
 
  
      
    base: main
Could not load branches
            
              
  
    Branch not found: {{ refName }}
  
            
                
      Loading
              
            Could not load tags
            
            
              Nothing to show
            
              
  
            
                
      Loading
              
            Are you sure you want to change the base?
            Some commits from the old base branch may be removed from the timeline,
            and old review comments may become outdated.
          
          
  
     Open
                    Changes from 23 commits
      Commits
    
    
            Show all changes
          
          
            27 commits
          
        
        Select commit
          Hold shift + click to select a range
      
      05c549c
              
                Adding python script to easily obtain key customer info
              
              
                 3ca9d79
              
                added file writing capability
              
              
                 5aaa42e
              
                Merge branch 'main' into sarah/understand-customer-script
              
              
                 d31f707
              
                Merge remote-tracking branch 'origin/main' into sarah/understand-cust…
              
              
                 4d16539
              
                changed directory
              
              
                 21e9ed6
              
                removed comments, added command
              
              
                 9f2fa21
              
                added new folder
              
              
                 cd2988c
              
                added cquery
              
              
                 cad6ce9
              
                Added flag functionality and readme file
              
              
                 93a3a3e
              
                added in comments, removed unecessary import
              
              
                 8687ab4
              
                Fixed aquery formatting, added in target as arg, added execute functi…
              
              
                 08bfd12
              
                removed unecessary comment
              
              
                 0253986
              
                Merge remote-tracking branch 'origin/main' into sarah/understand-cust…
              
              
                 677f3fd
              
                fixed formatting, added error messages, added progress messages
              
              
                 fb015a2
              
                added support for repo paths but data is unorganized, no option for s…
              
              
                 9a34d4c
              
                Added in target organization for action info
              
              
                 e1e7a35
              
                Merge remote-tracking branch 'origin/main' into sarah/understand-cust…
              
              
                 850d543
              
                Merge remote-tracking branch 'origin/main' into sarah/understand-cust…
              
              
                 d48b5ad
              
                added docstrings
              
              
                 9869462
              
                added action summing
              
              
                 7bd919c
              
                increased time out time
              
              
                 e9c4c2a
              
                added support for user options, reorganized bazel targets to be more …
              
              
                 bdf4edd
              
                remvoed TODOs
              
              
                 2941e96
              
                Update scripts/customer-info/README.md
              
              
                sarahraza007 4af3a40
              
                Update scripts/customer-info/README.md
              
              
                sarahraza007 8781a33
              
                Update scripts/customer-info/README.md
              
              
                sarahraza007 6fdd011
              
                changed flags to more relevant ones
              
              
                 File filter
Filter by extension
Conversations
          Failed to load comments.   
        
        
          
      Loading
        
  Jump to
        
          Jump to file
        
      
      
          Failed to load files.   
        
        
          
      Loading
        
  Diff view
Diff view
There are no files selected for viewing
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| # GENERAL SUMMARY | ||
| On a high level, our goal is to improve the customer experience by allowing us to obtain | ||
| the introduction customer information faster. Through running this script, we will recieve | ||
| a yaml file that contains the targets, relevant information about actions (number of total | ||
| actions, set of mnemonics, set of configurations, set of platforms, and set of aspects), the | ||
| bazel version being used, and the values of the relevant bazel flags. | ||
| 
     | 
||
| # RUNNING/EDITING THE SCRIPT | ||
                
      
                  sarahraza007 marked this conversation as resolved.
               
              
                Outdated
          
            Show resolved
            Hide resolved
         | 
||
| To run the script, | ||
| 1. Navigate to the ```scripts``` folder and then the ```customer-info``` folder | ||
| 2. run command | ||
| ``` | ||
| python customer_info.py PATH_TO_REPO | ||
| ``` | ||
| where ```PATH_TO_REPO``` = | ||
| absolute path to repo | ||
| ``` | ||
| python customer_info.py "/Users/sarahraza/example" | ||
| ``` | ||
| 3. if you want cquery to run with a user option add it to the command | ||
| ``` | ||
| python customer_info.py PATH_TO_REPO USER_OPTION | ||
| ``` | ||
| where ```PATH_TO_REPO``` = | ||
| absolute path to repo | ||
| where ```USER_OPTION``` = | ||
| user option flag to run cquery with | ||
| ``` | ||
| python customer_info.py "/Users/sarahraza/example" "--compilation_mode=dbg" | ||
| ``` | ||
| 
     | 
||
| To customize the script, | ||
| - Change the list of relevant flags by editing the ```relevant_flags``` variable | ||
                
      
                  vaibhav-shah marked this conversation as resolved.
               
          
            Show resolved
            Hide resolved
         | 
||
| 
     | 
||
| # DETAILED SUMMARY | ||
                
      
                  sarahraza007 marked this conversation as resolved.
               
              
                Outdated
          
            Show resolved
            Hide resolved
         | 
||
| Within the script, the following commands are called: | ||
| ``` | ||
| bazel --version | ||
| bazel cquery //TARGET | ||
| bazel aquery //TARGET | ||
| bazel config IDENTIFIER | ||
| ``` | ||
| 
     | 
||
| The ```TARGET``` for each command is passed in as the second argument. | ||
| 
     | 
||
| The ```IDENTIFIER``` is the unique identifier from each target outputted by the bazel cquery command. | ||
| 
     | 
||
| The output after running the script is a yaml file in the customer-info folder. The yaml | ||
| file contains 3 main blocks of information: | ||
| - bazel aquery information which contains 5 sub-blocks of information | ||
| 1. Total number of actions | ||
| 2. Mnemonics | ||
| 3. Configurations | ||
| 4. Execution Platform | ||
| 5. Aspects | ||
| - Example: | ||
| ``` | ||
| bazel aquery information: | ||
| - 47 total actions. | ||
| - 'Mnemonics: GenProto: 1 TestRunner: 1 GenProtoDescriptorSet: 1 Action: 3 Middleman: | ||
| 3 FileWrite: 3 TemplateExpand: 3 SymlinkTree: 3 SourceSymlinkManifest: 3 | ||
| JavaDeployJar: 3 Turbine: 5 Javac: 8 JavaSourceJar: 10' | ||
| - 'Configurations: darwin-fastbuild: 47' | ||
| - 'Execution Platforms: @local_config_platform//:host: 47' | ||
| - 'Aspects: BazelJavaProtoAspect: 3' | ||
| ``` | ||
| - bazel cquery targets under which there is a list of targets each of which has a unique | ||
| identifier at the end between parenthesis | ||
| - Example: | ||
| ``` | ||
| bazel cquery targets: | ||
| - //java/com/engflow/example:ExampleTest (8a8f93d) | ||
| ``` | ||
| - bazel flag information in which there is the relevant flag information for each identifier | ||
| - Example: | ||
| ``` | ||
| bazel flag information: | ||
| 8a8f93d: | ||
| experimental_allow_runtime_deps_on_neverlink: 'true' | ||
| experimental_limit_android_lint_to_android_constrained_java: 'false' | ||
| test_timeout: '{short=PT1M, moderate=PT5M, long=PT15M, eternal=PT1H}' | ||
| 94fc984: | ||
| experimental_allow_runtime_deps_on_neverlink: 'true' | ||
| experimental_limit_android_lint_to_android_constrained_java: 'false' | ||
| ``` | ||
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,190 @@ | ||
| import os | ||
| import sys | ||
| import re | ||
| import subprocess | ||
| 
     | 
||
| import yaml | ||
| 
     | 
||
| # download pylint and add config file from engflow | ||
| 
     | 
||
| if len(sys.argv) < 2: | ||
| print("Please provide the following arguments: file path to repo." | ||
| "Check README for further information.") | ||
| quit() | ||
| 
     | 
||
| # add the names of wanted flag values | ||
| # use regular expression instead | ||
| relevant_flags = ["test_timeout", "experimental_allow_runtime_deps_on_neverlink", | ||
| "experimental_limit_android_lint_to_android_constrained_java"] | ||
| 
     | 
||
| def execute(args): | ||
| """ Executes an os command """ | ||
| try: | ||
| the_process = subprocess.run( | ||
| args, | ||
| stdout=subprocess.PIPE, | ||
| stderr=subprocess.PIPE, | ||
| text=True, | ||
| check=True, | ||
| timeout=30 | ||
| ) | ||
| except subprocess.TimeoutExpired as error: | ||
| print("The command '{}' timed out after {} seconds".format(error.cmd, error.timeout), file=sys.stderr) | ||
| sys.exit(1) | ||
| except subprocess.CalledProcessError as error: | ||
| print("Could not execute os command ", error.returncode, " - ", error, file=sys.stderr) | ||
| sys.exit(1) | ||
| except subprocess.SubprocessError as error: | ||
| print("Could not execute os command ", error.returncode, " - ", error, file=sys.stderr) | ||
| sys.exit(1) | ||
| return the_process.stdout, the_process.stderr | ||
| 
     | 
||
| def writeToFile(dict_file, path_to_customer_info): | ||
| '''Takes in dictionary mapping category of data to value and writes to yaml file''' | ||
| path_to_yaml = path_to_customer_info + "/customer_info.yaml" | ||
| with open(path_to_yaml, 'w') as file: | ||
| yaml.dump(dict_file, file) | ||
| 
     | 
||
| def extractFlags(bazel_target): | ||
                
      
                  sarahraza007 marked this conversation as resolved.
               
          
            Show resolved
            Hide resolved
         | 
||
| '''Takes in list of targets from cquery and returns flags for the targets''' | ||
| 
     | 
||
| # creates array of all unique identifiers | ||
| ids = set(re.findall(r'\(.*?\)', bazel_target)) | ||
| 
     | 
||
| # creates dictionary mapping unique identifiers to fragments containing all flag information | ||
| print("Extracting all flags...") | ||
| config_to_flag = {} | ||
| for id in ids: | ||
| config = id[1:-1] # removes parenthesis | ||
| bazel_specific_config_command = ["bazel", "config", config] | ||
| config_output, stderr_flag = execute(bazel_specific_config_command) | ||
| config_to_flag[config] = config_output | ||
| 
     | 
||
| # changes dictionary to map from unique identifiers to dictionary containing strings with relevant flag information | ||
| print("Shortening to relevant flags and saving to file...") | ||
| new_config_to_flag = {} | ||
| for config, config_output in config_to_flag.items(): | ||
| flag_to_val = {} | ||
| for flag in relevant_flags: | ||
| start_index = config_output.find(flag) | ||
| end_index = config_output.find("\n", start_index) | ||
| flag_output = config_output[start_index:end_index] | ||
| if len(flag_output) != 0: | ||
| colon_index = flag_output.find(":") | ||
| flag_to_val[flag_output[:colon_index]] = flag_output[colon_index+2:] | ||
| new_config_to_flag[config] = flag_to_val | ||
| 
     | 
||
| return new_config_to_flag | ||
| 
     | 
||
| def getPotentialCommandFilePaths(): | ||
| '''Returns potential file paths as targets to execute bazel commands''' | ||
| os.chdir(sys.argv[1]) | ||
| bazel_query_command = ["bazel", "query", "..."] | ||
| stdout_version, stderr_version = execute(bazel_query_command) | ||
| all_targets = stdout_version.split('\n') | ||
| potential_targets = set() | ||
| for target in all_targets: | ||
| third_slash_index = target.find("/", 2) | ||
| colon_index = target.find(":") | ||
| if third_slash_index > 0: | ||
| potential_targets.add(target[:third_slash_index] + "/...") | ||
| elif colon_index > 0: | ||
| potential_targets.add(target[:colon_index] + "/...") | ||
| return potential_targets | ||
| 
     | 
||
| 
     | 
||
| 
     | 
||
| if __name__ == '__main__': | ||
| '''Executes bazel commands for each file path, saving targets, action information, and flags to yaml file''' | ||
| potential_targets = getPotentialCommandFilePaths() | ||
| 
     | 
||
| # dictionary with all information to put in yaml file | ||
| dict_file = {} | ||
| # dictionary with all bazel action information | ||
| dict_bazel_actions = {} | ||
| # dictionary with all config to flag information | ||
| dict_flag_information = [] | ||
| # dictionary with bazel target information | ||
| targets_dict = {} | ||
| 
     | 
||
| # path to customer-info directory | ||
| path_to_customer_info = sys.argv[1] + "/scripts/customer-info" | ||
| 
     | 
||
| # if user option passed in save | ||
| user_option = "" | ||
| if len(sys.argv) == 3: | ||
| user_option = sys.argv[2] | ||
| 
     | 
||
| # move to customer project | ||
| os.chdir(path_to_customer_info) | ||
| 
     | 
||
| # get bazel version | ||
| print("Extracting bazel version information...") | ||
| bazel_version_arr = ["bazel", "--version"] | ||
| stdout_version, stderr_version = execute(bazel_version_arr) | ||
| print("Saving in file...") | ||
| dict_file["bazel version"] = str(stdout_version.strip()) | ||
| 
     | 
||
| for target in potential_targets: | ||
| 
     | 
||
| # get targets | ||
| # NOTE: these targets will be used to obtain the flags | ||
| bazel_cquery_target_command = ["bazel", "cquery", target] | ||
| if user_option: | ||
| bazel_cquery_target_command = ["bazel", "cquery", target, user_option] | ||
| print("Extracting bazel targets...") | ||
| try: | ||
| stdout_target, stderr_target = execute(bazel_cquery_target_command) | ||
| processed_stdout_target = stdout_target.split("\n")[:-1] | ||
| for s in processed_stdout_target: | ||
| parts = s.split(' ') | ||
| key = parts[-1][1:-1] | ||
| value = parts[0] | ||
| targets_dict.setdefault(key, []).append(value) | ||
| except SystemExit: | ||
| continue | ||
| 
     | 
||
| # get action information | ||
| bazel_action_summary_command = ["bazel", "aquery", target, "--output=summary"] | ||
| print("Extracting bazel action information based on targets...") | ||
| try: | ||
| stdout_action_summary, stderr_action_summary = execute(bazel_action_summary_command) | ||
| bazel_action_summary = stdout_action_summary.split("\n\n") | ||
| formatted_bazel_action_summary = [] | ||
| for info in bazel_action_summary: | ||
| formatted_bazel_action_summary.append(info.split("\n")) | ||
| 
     | 
||
| # setting or updating action count to dict | ||
| num_actions = re.findall(r'\d+', formatted_bazel_action_summary[0][0]) | ||
| dict_bazel_actions.setdefault("total_actions", []).append(int(num_actions[0])) | ||
| 
     | 
||
| # adding other information to dictionary | ||
| for info in formatted_bazel_action_summary[1:]: | ||
| if info[0] in dict_bazel_actions: | ||
| dict_bazel_actions[info[0]][target] = info[1:] | ||
| else: | ||
| dict_bazel_actions[info[0]] = {} | ||
| dict_bazel_actions[info[0]][target] = info[1:] | ||
| 
     | 
||
| except SystemExit: | ||
| continue | ||
| 
     | 
||
| # get flags | ||
| print("Extracting relevant flag information...") | ||
| new_dict = extractFlags(stdout_target) | ||
| dict_flag_information.append(new_dict) | ||
| 
     | 
||
| # write targets, action, and flag to main dictionary | ||
| print("Saving targets in file...") | ||
| dict_file.setdefault("bazel_targets", []).append(targets_dict) | ||
| print("Saving action information in file...") | ||
| dict_file.setdefault("bazel_action_information", []).append(dict_bazel_actions) | ||
| print("Saving flag information in file...") | ||
| dict_file.setdefault("relevant bazel flags and values", []).append(dict_flag_information) | ||
| 
     | 
||
| # sums all the individual action count and saves that value | ||
| sum_total_actions = sum(dict_file['bazel_action_information'][0]['total_actions']) | ||
| dict_file['bazel_action_information'][0]['total_actions'] = sum_total_actions | ||
| 
     | 
||
| # write everything to the yaml file | ||
| writeToFile(dict_file, path_to_customer_info) | ||
      
      Oops, something went wrong.
        
    
  
  Add this suggestion to a batch that can be applied as a single commit.
  This suggestion is invalid because no changes were made to the code.
  Suggestions cannot be applied while the pull request is closed.
  Suggestions cannot be applied while viewing a subset of changes.
  Only one suggestion per line can be applied in a batch.
  Add this suggestion to a batch that can be applied as a single commit.
  Applying suggestions on deleted lines is not supported.
  You must change the existing code in this line in order to create a valid suggestion.
  Outdated suggestions cannot be applied.
  This suggestion has been applied or marked resolved.
  Suggestions cannot be applied from pending reviews.
  Suggestions cannot be applied on multi-line comments.
  Suggestions cannot be applied while the pull request is queued to merge.
  Suggestion cannot be applied right now. Please check back later.
  
    
  
    
Uh oh!
There was an error while loading. Please reload this page.