Skip to content

Commit bba76d9

Browse files
Merge remote-tracking branch 'origin/master' into ticket_7914_update_script
2 parents e9ab25a + 1589d90 commit bba76d9

File tree

94 files changed

+3927
-1743
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

94 files changed

+3927
-1743
lines changed

.git-blame-ignore-revs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# ignore ruff format and --fix
2+
fd6ed57462bc032c465524101802519dfa03c05b
3+
13d1293171c0631eaed924b56e7b6986f08571b2

.github/workflows/Linter.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
name: Linter
2+
on: [pull_request]
3+
jobs:
4+
call-workflow:
5+
uses: ISISComputingGroup/reusable-workflows/.github/workflows/linters.yml@main
6+
with:
7+
compare-branch: origin/master
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Push Event Workflow
2+
3+
on: push
4+
5+
jobs:
6+
unit-testing:
7+
runs-on: windows-latest
8+
9+
steps:
10+
- name : Checkout code
11+
uses : actions/checkout@v4
12+
13+
- name: Setup python
14+
uses: actions/setup-python@v5
15+
with:
16+
python-version: '3.11'
17+
18+
- name: Install dependencies
19+
run: |
20+
python -m pip install --upgrade pip
21+
pip install -r ./installation_and_upgrade/requirements.txt
22+
23+
- name : Run tests
24+
working-directory: ./installation_and_upgrade
25+
run: |
26+
pip install pytest
27+
python -m pytest

SECI_Config_Analyser/Directory_Operations.py

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
# 3. for each file, parse XML for required tag and add value to list
44
# 4. remove duplicates from list
55

6-
from os import listdir
7-
from fnmatch import fnmatch
86
import xml.etree.ElementTree as ET
7+
from fnmatch import fnmatch
8+
from os import listdir
99

1010

1111
class ReadConfigFiles:
@@ -17,7 +17,7 @@ def __init__(self, search_path):
1717
"""
1818
create lists for filenames and initialise to empty lists
1919
call methods for reading directory contents and searching for config filenames
20-
:param search_path: the search path for files
20+
:param search_path: the search path for files
2121
"""
2222

2323
self.full_path = search_path
@@ -34,19 +34,16 @@ def _extract_config_filenames(self):
3434
"""
3535

3636
for filename in self.directory_contents:
37-
38-
if fnmatch(filename, '*.conf'):
39-
37+
if fnmatch(filename, "*.conf"):
4038
self.config_filenames.append(filename)
4139

42-
elif fnmatch(filename, '*.comp'):
43-
40+
elif fnmatch(filename, "*.comp"):
4441
self.comp_filenames.append(filename)
4542

4643
def _parse_vis_from_files(self, filenames):
4744
"""
4845
extracts VI names and paths from config files
49-
:param filenames: list of filenames to process
46+
:param filenames: list of filenames to process
5047
:return: vis_in_files: list of VIs with fullpaths
5148
"""
5249

@@ -70,7 +67,7 @@ def _parse_file(filename_and_path):
7067
vis_in_file = []
7168
tree = ET.parse(filename_and_path)
7269
root = tree.getroot()
73-
for child in root.iter('FilePath'):
70+
for child in root.iter("FilePath"):
7471
vi_path = ET.tostring(child, encoding=None, method="text")
7572
vis_in_file.append(vi_path.strip())
7673

@@ -91,8 +88,7 @@ def _remove_duplicates(input_list):
9188
encountered = set()
9289

9390
for item in input_list:
94-
95-
item = str(item, 'UTF-8')
91+
item = str(item, "UTF-8")
9692
if item not in encountered:
9793
output_list.append(item)
9894
encountered.add(item)

SECI_Config_Analyser/SECI_Config_Analyser.py

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,69 +2,72 @@
22
Script to analyse SECI configurations and components and output results to file
33
"""
44

5-
from Directory_Operations import ReadConfigFiles
65
import argparse
76
from os import system
87

9-
if __name__ == '__main__':
8+
from Directory_Operations import ReadConfigFiles
109

10+
if __name__ == "__main__":
1111
parser = argparse.ArgumentParser(
12-
description='Analyse the SECI configuration files of specified instrument and output results to file')
12+
description="Analyse the SECI configuration files of specified instrument and output results to file"
13+
)
1314

14-
parser.add_argument('--instrument', '-i',
15-
type=str,
16-
default=None,
17-
help='instrument to be analysed')
15+
parser.add_argument(
16+
"--instrument", "-i", type=str, default=None, help="instrument to be analysed"
17+
)
1818

19-
parser.add_argument('--output_file', '-o',
20-
type=str,
21-
default=None,
22-
help='file to write the results to')
19+
parser.add_argument(
20+
"--output_file", "-o", type=str, default=None, help="file to write the results to"
21+
)
2322

24-
parser.add_argument('--adminaccount', '-a',
25-
type=str,
26-
default=None,
27-
help=r'admin account name (without host i.e. NOT \\NDXxxx\xxx, just xxx')
23+
parser.add_argument(
24+
"--adminaccount",
25+
"-a",
26+
type=str,
27+
default=None,
28+
help=r"admin account name (without host i.e. NOT \\NDXxxx\xxx, just xxx",
29+
)
2830

29-
parser.add_argument('--adminpassword', '-p',
30-
type=str,
31-
default=None,
32-
help='admin account password')
31+
parser.add_argument(
32+
"--adminpassword", "-p", type=str, default=None, help="admin account password"
33+
)
3334

3435
args = parser.parse_args()
3536

3637
if args.instrument is None:
3738
parser.print_help()
3839

3940
if args.output_file is None:
40-
args.output_file = f'{args.instrument.upper()}_-_VIs_from_SECI_configs.txt'
41+
args.output_file = f"{args.instrument.upper()}_-_VIs_from_SECI_configs.txt"
4142

4243
# open reference to appropriate network drive with supplied credentials
4344

44-
print('Connecting to remote directory...')
45-
system(f"net use \\\\ndx{args.instrument}\\c$ /user:ndx{args.instrument}\\{args.adminaccount} {args.adminpassword}")
45+
print("Connecting to remote directory...")
46+
system(
47+
f"net use \\\\ndx{args.instrument}\\c$ /user:ndx{args.instrument}\\{args.adminaccount} {args.adminpassword}"
48+
)
4649

4750
# create instance of 'ReadConfigFiles' as 'filelist' and supply directory to be read
4851

49-
print('Reading configuration files...')
50-
filelist = ReadConfigFiles(f"//ndx{args.instrument}/c$/Program Files (x86)/STFC ISIS Facility/SECI/Configurations/")
52+
print("Reading configuration files...")
53+
filelist = ReadConfigFiles(
54+
f"//ndx{args.instrument}/c$/Program Files (x86)/STFC ISIS Facility/SECI/Configurations/"
55+
)
5156

52-
print('Analysing files...')
57+
print("Analysing files...")
5358
xml_data = filelist.analyse_config_files()
5459

5560
# delete reference to network drive
5661

57-
print('Removing network connection...')
62+
print("Removing network connection...")
5863
system(f"net use \\\\ndx{args.instrument}\\c$ /delete")
5964

6065
# concatenate each element in list with newline character, then print whole string
6166

62-
print('Writing output file...')
63-
with open(args.output_file, 'w') as outputfile:
64-
67+
print("Writing output file...")
68+
with open(args.output_file, "w") as outputfile:
6569
outputfile.write(f"SECI configuration analysis for {args.instrument.upper()}:\n\n")
6670

6771
for item in xml_data:
68-
69-
outputfile.write('\n'.join(x for x in item))
72+
outputfile.write("\n".join(x for x in item))
7073
outputfile.write(f"\nNumber of VIs in configuration/component: {str(len(item))}\n\n")
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
setlocal
2-
call "%~dp0..\installation_and_upgrade\define_latest_genie_python.bat" 3
2+
call "%~dp0..\installation_and_upgrade\define_latest_genie_python.bat"
3+
IF %errorlevel% neq 0 EXIT /b %errorlevel%
34
set PYTHONUNBUFFERED=TRUE
45
REM use LATEST_PYTHON3 so not killed by stop_ibex_server
56
call "%LATEST_PYTHON3%" -u "%~dp0check_builds_are_recent.py"
7+
call "%~dp0..\installation_and_upgrade\remove_genie_python.bat" %LATEST_PYTHON_DIR%

build_tools/check_builds_are_recent.py

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,100 @@
1+
import json
12
import os
2-
from typing import Union
3-
from datetime import datetime
43
import sys
4+
from datetime import datetime
5+
from typing import Union
6+
7+
kits_root = r"\\isis\inst$\kits$\CompGroup\ICP"
58

6-
def format_build_num_without_dash(build_num):
7-
return f"BUILD{build_num}"
89

910
def format_build_num_with_dash(build_num):
1011
return f"BUILD-{build_num}"
1112

12-
kits_root = r"\\isis\inst$\kits$\CompGroup\ICP"
13-
epics_builds = ["EPICS_CLEAN_win10_x64", "EPICS_CLEAN_win7_x64", "EPICS_win7_x64", "EPICS_CLEAN_win10_x86", "EPICS_STATIC_CLEAN_win7_x64"]
14-
epics_build_dirs = [(f"EPICS\\{build}", format_build_num_with_dash) for build in epics_builds]
15-
build_dirs = [("Client_E4", format_build_num_without_dash), ("genie_python_3", format_build_num_with_dash)] + epics_build_dirs
1613

1714
def get_latest_build(dir, directory_formatter) -> Union[None, str]:
1815
latest_build = None
1916
with open(os.path.join(dir, "LATEST_BUILD.txt")) as latest_build_file:
2017
latest_build = latest_build_file.readline().strip()
21-
latest_build_dir = os.path.join(dir, directory_formatter(latest_build)) if latest_build is not None else None
18+
latest_build_dir = (
19+
os.path.join(dir, directory_formatter(latest_build)) if latest_build is not None else None
20+
)
2221
return latest_build_dir
2322

23+
2424
def get_last_modified_datetime(dir):
2525
time_in_seconds_of_last_modification = os.path.getmtime(dir)
2626
datetime_of_last_modification = datetime.fromtimestamp(time_in_seconds_of_last_modification)
2727
return datetime_of_last_modification
2828

29+
2930
def get_formatted_last_modified_datetime(dir):
3031
last_modified_date = get_last_modified_datetime(dir)
3132
return last_modified_date.strftime("%d/%m/%Y, %H:%M:%S")
3233

34+
3335
def modified_in_last_x_days(dir, x_days):
3436
datetime_of_last_modification = get_last_modified_datetime(dir)
3537
datetime_now = datetime.now()
3638
timedelta_since_last_modification = datetime_now - datetime_of_last_modification
3739
return timedelta_since_last_modification.days < x_days
3840

39-
def was_modified_recently(latest_build):
40-
x_days = 5
41+
42+
def was_modified_recently(latest_build, num_days):
4143
last_modified_datetime = get_formatted_last_modified_datetime(latest_build)
42-
modified_recently = modified_in_last_x_days(latest_build, x_days)
44+
modified_recently = modified_in_last_x_days(latest_build, num_days)
4345
if modified_recently:
44-
print(f"SUCCESS: {latest_build} has been modified in the last {x_days} days. Last modified: {last_modified_datetime}")
46+
print(
47+
f"SUCCESS: {latest_build} has been modified in the last {num_days} days. Last modified: {last_modified_datetime}"
48+
)
4549
else:
46-
print(f"WARNING: {latest_build} modified longer than {x_days} ago. Last modified: {last_modified_datetime}")
50+
print(
51+
f"WARNING: {latest_build} modified longer than {num_days} ago. Last modified: {last_modified_datetime}"
52+
)
4753
return modified_recently
4854

49-
def check_build_dir(build_dir, directory_formatter):
55+
56+
def check_build_dir(build_dir, num_days, directory_formatter):
5057
latest_build = get_latest_build(build_dir, directory_formatter)
5158
modified_recently = False
5259
if latest_build is None:
5360
print(f"WARNING: Could not get latest build dir from {build_dir}")
5461
else:
55-
modified_recently = was_modified_recently(latest_build)
62+
modified_recently = was_modified_recently(latest_build, num_days)
5663
return modified_recently
5764

65+
5866
def check_build_dirs(build_dirs):
5967
build_dirs_not_modified_recently = []
6068
for build_dir in build_dirs:
6169
directory = build_dir[0]
62-
directory_formatter = build_dir[1]
70+
stale_days_limit = int(build_dir[1])
71+
directory_formatter = build_dir[2]
6372
build_dir_full_path = os.path.join(kits_root, directory)
64-
modified_recently = check_build_dir(build_dir_full_path, directory_formatter)
73+
modified_recently = check_build_dir(
74+
build_dir_full_path, stale_days_limit, directory_formatter
75+
)
6576
if not modified_recently:
6677
build_dirs_not_modified_recently.append(build_dir_full_path)
6778
return build_dirs_not_modified_recently
6879

80+
6981
if __name__ == "__main__":
82+
builds_to_check = os.getenv("BUILDS_TO_CHECK")
83+
if builds_to_check is None:
84+
print("ERROR: BUILDS_TO_CHECK enviroment variable not set")
85+
sys.exit(1)
86+
try:
87+
builds_by_stale_times = json.loads(builds_to_check)
88+
except ValueError as e:
89+
print(
90+
f"ERROR: parameter is not valid JSON.\nParameter:{builds_to_check}\nSpecific Error: {e.args}"
91+
)
92+
sys.exit(1)
93+
build_dirs = []
94+
for time, builds_by_stale_time in builds_by_stale_times.items():
95+
for build in builds_by_stale_time:
96+
directory_formatter = format_build_num_with_dash
97+
build_dirs.append((build, time, directory_formatter))
7098
build_dirs_not_modified_recently = check_build_dirs(build_dirs)
7199
if build_dirs_not_modified_recently:
72100
sys.exit(1)

build_tools/purge_archive.bat

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
11
setlocal EnableDelayedExpansion
22
REM Remove old builds from the archive
3-
call "%~dp0..\installation_and_upgrade\define_latest_genie_python.bat" 3
43

5-
if not "%WORKSPACE%" == "" (
4+
if "%WORKSPACE%" == "" (
5+
call "%~dp0..\installation_and_upgrade\define_latest_genie_python.bat"
6+
) else (
67
if exist "%WORKSPACE%\Python3" rd /s /q %WORKSPACE%\Python3
7-
call %LATEST_PYTHON_DIR%..\genie_python_install.bat %WORKSPACE%\Python3
88
if !errorlevel! neq 0 exit /b 1
9-
set "LATEST_PYTHON3=%WORKSPACE%\Python3\python3.exe"
9+
call "%~dp0..\installation_and_upgrade\define_latest_genie_python.bat" %WORKSPACE%\Python3
1010
)
11+
IF %errorlevel% neq 0 EXIT /b %errorlevel%
1112

1213
set PYTHONUNBUFFERED=TRUE
13-
REM use LATEST_PYTHON3 to avoid process being killed
14+
REM use LATEST_PYTHON3 to avoid process being killed
1415
"%LATEST_PYTHON3%" -u "%~dp0purge_archive.py"
1516
set errcode=!errorlevel!
1617
@echo purge_archive.py exited with code !errcode!
1718
for /F "skip=1" %%I in ('wmic path win32_localtime get dayofweek') do (set /a DOW=%%I 2>NUL)
1819
if %DOW% neq 6 (
1920
@echo Skipping debug symbol cleanup as day of week %DOW% is not 6
21+
CALL "%~dp0..\installation_and_upgrade\remove_genie_python.bat" %LATEST_PYTHON_DIR%
2022
exit /b !errcode!
2123
)
2224
REM Remove old debug symbols from the archive
@@ -33,3 +35,5 @@ if exist "%AGESTORE%" (
3335
) else (
3436
@echo agestore does not exist
3537
)
38+
39+
CALL "%~dp0..\installation_and_upgrade\remove_genie_python.bat" %LATEST_PYTHON_DIR%

0 commit comments

Comments
 (0)