k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/hack/verify-publishing-bot.py (about)

     1  #!/usr/bin/env python3
     2  
     3  # Copyright 2019 The Kubernetes Authors.
     4  #
     5  # Licensed under the Apache License, Version 2.0 (the "License");
     6  # you may not use this file except in compliance with the License.
     7  # You may obtain a copy of the License at
     8  #
     9  #     http://www.apache.org/licenses/LICENSE-2.0
    10  #
    11  # Unless required by applicable law or agreed to in writing, software
    12  # distributed under the License is distributed on an "AS IS" BASIS,
    13  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  # See the License for the specific language governing permissions and
    15  # limitations under the License.
    16  
    17  import fnmatch
    18  import os
    19  import sys
    20  import json
    21  
    22  
    23  def get_gomod_dependencies(rootdir, components):
    24      all_dependencies = {}
    25      for component in components:
    26          with open(os.path.join(rootdir, component, "go.mod")) as f:
    27              print((component + " dependencies"))
    28              all_dependencies[component] = []
    29              lines = list(set(f))
    30              lines.sort()
    31              for line in lines:
    32                  for dep in components:
    33                      if dep == component:
    34                          continue
    35                      if ("k8s.io/" + dep + " =>") not in line:
    36                          continue
    37                      print(("\t"+dep))
    38                      if dep not in all_dependencies[component]:
    39                          all_dependencies[component].append(dep)
    40      return all_dependencies
    41  
    42  
    43  def get_rules_dependencies(rules_file):
    44      import yaml
    45      with open(rules_file) as f:
    46          data = yaml.safe_load(f)
    47      return data
    48  
    49  
    50  def main():
    51      rootdir = os.path.dirname(__file__) + "/../"
    52      rootdir = os.path.abspath(rootdir)
    53  
    54      components = []
    55      for component in os.listdir(rootdir + '/staging/src/k8s.io/'):
    56          components.append(component)
    57      components.sort()
    58  
    59      rules_file = "/staging/publishing/rules.yaml"
    60      try:
    61          import yaml
    62      except ImportError:
    63          print(("Please install missing pyyaml module and re-run %s" % sys.argv[0]))
    64          sys.exit(1)
    65      rules_dependencies = get_rules_dependencies(rootdir + rules_file)
    66  
    67      gomod_dependencies = get_gomod_dependencies(rootdir + '/staging/src/k8s.io/', components)
    68  
    69      processed_repos = []
    70      for rule in rules_dependencies["rules"]:
    71          branch = rule["branches"][0]
    72  
    73          # If this no longer exists in master
    74          if rule["destination"] not in gomod_dependencies:
    75              # Make sure we don't include a rule to publish it from master
    76              for branch in rule["branches"]:
    77                  if branch["name"] == "master":
    78                      raise Exception("cannot find master branch for destination %s" % rule["destination"])
    79              # And skip validation of publishing rules for it
    80              continue
    81  
    82          for item in rule["branches"]:
    83              if "dir" in item["source"]:
    84                  raise Exception("use of deprecated `dir` field in rules for `%s`" % (rule["destination"]))
    85              if len(item["source"]["dirs"]) > 1:
    86                  raise Exception("cannot have more than one directory (`%s`) per source branch `%s` of `%s`" %
    87                                  (item["source"]["dirs"], item["source"]["branch"], rule["destination"])
    88                                  )
    89              if not item["source"]["dirs"][0].endswith(rule["destination"]):
    90                  raise Exception("copy/paste error `%s` refers to `%s`" % (rule["destination"],item["source"]["dir"]))
    91  
    92          if branch["name"] != "master":
    93              raise Exception("cannot find master branch for destination %s" % rule["destination"])
    94          if branch["source"]["branch"] != "master":
    95              raise Exception("cannot find master source branch for destination %s" % rule["destination"])
    96  
    97          # we specify the go version for all master branches through `default-go-version`
    98          # so ensure we don't specify explicit go version for master branch in rules
    99          if "go" in branch:
   100              raise Exception("go version must not be specified for master branch for destination %s" % rule["destination"])
   101  
   102          print(("processing : %s" % rule["destination"]))
   103          if rule["destination"] not in gomod_dependencies:
   104              raise Exception("missing go.mod for %s" % rule["destination"])
   105          processed_repos.append(rule["destination"])
   106          processed_deps = []
   107          for dep in set(gomod_dependencies[rule["destination"]]):
   108              found = False
   109              if "dependencies" in branch:
   110                  for dep2 in branch["dependencies"]:
   111                      processed_deps.append(dep2["repository"])
   112                      if dep2["branch"] != "master":
   113                          raise Exception("Looking for master branch and found : %s for destination", dep2,
   114                                          rule["destination"])
   115                      if dep2["repository"] == dep:
   116                          found = True
   117              else:
   118                  raise Exception(
   119                      "Please add %s as dependencies under destination %s in %s" % (gomod_dependencies[rule["destination"]], rule["destination"], rules_file))
   120              if not found:
   121                  raise Exception("Please add %s as a dependency under destination %s in %s" % (dep, rule["destination"], rules_file))
   122              else:
   123                  print(("  found dependency %s" % dep))
   124          extraDeps = set(processed_deps) - set(gomod_dependencies[rule["destination"]])
   125          if len(extraDeps) > 0:
   126              raise Exception("extra dependencies in rules for %s: %s" % (rule["destination"], ','.join(str(s) for s in extraDeps)))
   127      items = set(gomod_dependencies.keys()) - set(processed_repos)
   128      if len(items) > 0:
   129          raise Exception("missing rules for %s" % ','.join(str(s) for s in items))
   130      print("Done.")
   131  
   132  
   133  if __name__ == "__main__":
   134      sys.exit(main())