ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
publish_coverage.py
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file publish_coverage.py
1 #!/usr/bin/env python3
2 import os
3 import sys
4 import argparse
5 import subprocess as sp
6 import requests
7 import tempfile
8 from urllib.parse import urljoin
9 
10 from fs.osfs import OSFS
11 import fs.copy
12 import gitlab.exceptions
13 from datetime import datetime
14 from dateutil.parser import parse
15 
16 from concurrent.futures import ThreadPoolExecutor, wait
17 
18 from util import get_lxplus_fs, def_arguments, Spinner, gitlab
19 
20 import logging
21 
22 # logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)
23 
24 
25 def main():
26  p = argparse.ArgumentParser()
27  p = def_arguments(p, acc=True, gl=True)
28  p.add_argument("--coverage-source", required=True)
29  p.add_argument(
30  "--ref", default=os.getenv("CI_COMMIT_TAG", os.getenv("CI_COMMIT_SHA", None))
31  )
32  p.add_argument(
33  "--coverage-commit-limit",
34  default=int(os.getenv("COVERAGE_COMMIT_LIMIT", 10)),
35  type=int,
36  )
37  p.add_argument(
38  "--coverage-root",
39  default=os.getenv(
40  "COVERAGE_WEBSITE_ROOT", "/eos/user/a/atsjenkins/www/ACTS/coverage"
41  ),
42  )
43  p.add_argument(
44  "--website-public-url",
45  default=os.getenv(
46  "COVERAGE_WEBSITE_URL", "https://acts.web.cern.ch/ACTS/coverage/"
47  ),
48  )
49  p.add_argument("--project-id", default=3031, type=int)
50  p.add_argument("--dry-run", "-s", action="store_true")
51 
52  args = p.parse_args()
53 
54  try:
55  www_fs = get_lxplus_fs(args).opendir(args.coverage_root)
56  # www_fs = OSFS("www")
57  listdir = www_fs.listdir(".")
58  except:
59  print("Unable to establish SSH connection to lxplus")
60  print("This might indicate a problem with the credentials")
61  print("or a temporary connection / configuration problem")
62 
63  raise
64  sys.exit(1)
65 
66  gl = gitlab(args)
67  project = gl.projects.get(args.project_id)
68 
69  if len(args.ref) == 40:
70  # is commit hash
71  deploy_name = args.ref[:8]
72  else:
73  # probably tag
74  deploy_name = args.ref
75 
76  coverage_dest = os.path.join(args.coverage_root, deploy_name)
77  print("Going to deploy coverage for", deploy_name, "to", coverage_dest)
78  print(
79  "Will be publicly available under",
80  urljoin(args.website_public_url, deploy_name),
81  )
82 
83  src_fs = OSFS(args.coverage_source)
84 
85  with Spinner(f"Publishing ref {deploy_name}"):
86  if not args.dry_run:
87  fs.copy.copy_dir(src_fs, ".", www_fs, deploy_name)
88 
89  # cleanup
90  # get all deployed commits
91  with Spinner(text="Getting deployed commits"):
92  deployed_commits = set()
93  for item in www_fs.listdir("."):
94  if not www_fs.isdir(item):
95  continue
96  if item.startswith("v"): # skip versions
97  continue
98  deployed_commits.add(item)
99 
100  with Spinner(text="Getting info for deployed commits"):
101  with ThreadPoolExecutor(max_workers=20) as tp:
102  # deployed_commit_info = p.map(project.commits.get, deployed_commits)
103  futures = [tp.submit(project.commits.get, c) for c in deployed_commits]
104  wait(futures)
105 
106  deployed_commits_with_time = []
107  for commit, future in zip(deployed_commits, futures):
108  try:
109  info = future.result()
110  date = parse(info.committed_date)
111  deployed_commits_with_time.append((commit, date))
112  except gitlab.exceptions.GitlabGetError as e:
113  print("Commit", commit, "not found, will remove")
114 
115  deployed_commits_with_time = list(
116  reversed(sorted(deployed_commits_with_time, key=lambda i: i[1]))
117  )
118 
119  # take the n newest commits
120  commits_to_keep = set(
121  h for h, _ in deployed_commits_with_time[: args.coverage_commit_limit]
122  )
123 
124  print("Currently deployed commits:")
125  for idx, (h, t) in enumerate(deployed_commits_with_time):
126  if idx < args.coverage_commit_limit:
127  print(" o", h, "-", t)
128  else:
129  print(" x", h, "-", t)
130 
131  print("Keeping commits:", ", ".join(commits_to_keep))
132 
133  commits_to_delete = deployed_commits - commits_to_keep
134 
135  if len(commits_to_delete) > 0:
136  with Spinner("Removing: %s" % ", ".join(commits_to_delete)):
137  if not args.dry_run:
138  for commit in commits_to_delete:
139  www_fs.removetree(commit)
140 
141  # install / update indexfile
142  latest_commit = deployed_commits_with_time[0][0]
143  latest_coverage_url = urljoin(args.website_public_url, latest_commit)
144  index_content = """
145 <!DOCTYPE html>
146 <html>
147 <head>
148 <meta http-equiv="refresh" content="0; url={0}" />
149 </head>
150 <body>
151 Redirecting to <a href"{0}">{0}</a>
152 </body>
153 </html>
154  """.format(
155  latest_coverage_url
156  )
157 
158  with Spinner("Writing index file redirecting to %s" % latest_coverage_url):
159  if not args.dry_run:
160  with www_fs.open("index.html", "w") as f:
161  f.write(index_content)
162 
163 
164 if "__main__" == __name__:
165  main()