Skip to content

Commit 214fbd2

Browse files
authored
Merge branch 'master' into api-pr1-scaffolding
2 parents beb4fe9 + b536dd7 commit 214fbd2

17 files changed

Lines changed: 83 additions & 91 deletions

File tree

.github/workflows/sp-deployment-pipeline.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ jobs:
8181
sudo git clean -f -d
8282
sudo git pull origin $DEPLOY_BRANCH
8383
84-
sudo python -m pip install -r requirements.txt
84+
sudo python3 -m pip install -r requirements.txt --break-system-packages
8585
sudo FLASK_APP=./run.py flask db upgrade
8686
8787
sudo cp "install/ci-vm/ci-linux/ci/bootstrap" "${SAMPLE_REPOSITORY}/TestData/ci-linux/bootstrap" 2>/dev/null || true
@@ -156,7 +156,7 @@ jobs:
156156
PREV_COMMIT=$(cat /tmp/previous_commit.txt)
157157
echo "Rolling back to commit: $PREV_COMMIT"
158158
sudo git checkout "$PREV_COMMIT"
159-
sudo python -m pip install -r requirements.txt
159+
sudo python3 -m pip install -r requirements.txt --break-system-packages
160160
sudo systemctl reload platform
161161
echo "Rollback complete"
162162
else

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ regression tests useless. In these cases, the tests can give false negative. For
3232
result files by the following command.
3333

3434
```shell
35-
python manage.py update /path/to/ccextractor/executable
35+
python3 manage.py update /path/to/ccextractor/executable
3636
```
3737

3838
NOTE: Please backup old results and be sure about updating them as there is no method to go back.

install/deploy/deploy.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ echo "✓ Updated to commit: $NEW_COMMIT"
4545
# Step 4: Update dependencies
4646
echo ""
4747
echo "--- Step 3: Updating dependencies ---"
48-
python3 -m pip install -r requirements.txt --quiet --disable-pip-version-check
48+
python3 -m pip install -r requirements.txt --quiet --disable-pip-version-check --break-system-packages
4949
echo "✓ Dependencies updated"
5050

5151
# Step 5: Run database migrations

install/deploy/rollback.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ fi
8484
# Step 3: Reinstall dependencies for rolled-back version
8585
echo ""
8686
echo "--- Step 3: Reinstalling dependencies ---"
87-
python3 -m pip install -r requirements.txt --quiet --disable-pip-version-check
87+
python3 -m pip install -r requirements.txt --quiet --disable-pip-version-check --break-system-packages
8888
echo "✓ Dependencies reinstalled"
8989

9090
# Step 4: Reload application

install/init_db.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/usr/bin/python
1+
#!/usr/bin/python3
22

33
import sys
44
from os import path

install/install.sh

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ echo "-------------------------------"
2626
echo ""
2727
echo "* Updating package list"
2828
apt-get update >> "$install_log" 2>&1
29-
echo "* Installing nginx, python, pip, mediainfo and gunicorn"
29+
echo "* Installing nginx, python3, pip, mediainfo and gunicorn"
3030
add-apt-repository ppa:deadsnakes/ppa -y >> "$install_log" 2>&1
3131
apt-get -q -y install python3.9 nginx python3.9-distutils python3-pip mediainfo gunicorn3 >> "$install_log" 2>&1
32-
update-alternatives --install /usr/bin/python python /usr/bin/python3.9 1 >> "$install_log" 2>&1
33-
update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1 >> "$install_log" 2>&1
32+
update-alternatives --install /usr/bin/python python /usr/bin/python3 1 >> "$install_log" 2>&1
33+
update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3 1 >> "$install_log" 2>&1
3434
rm -f /etc/nginx/sites-available/default
3535
rm -f /etc/nginx/sites-enabled/default
3636
if [ ! -f /etc/init.d/mysql* ]; then
@@ -64,9 +64,9 @@ userInput () {
6464
}
6565

6666
echo "* Update pip, setuptools and wheel"
67-
python -m pip install --upgrade pip setuptools wheel >> "$install_log" 2>&1
67+
python3 -m pip install --upgrade pip setuptools wheel --break-system-packages >> "$install_log" 2>&1
6868
echo "* Installing pip dependencies"
69-
python -m pip install -r "${root_dir}/requirements.txt" >> "$install_log" 2>&1
69+
python3 -m pip install -r "${root_dir}/requirements.txt" --break-system-packages >> "$install_log" 2>&1
7070
echo ""
7171
echo "-------------------------------"
7272
echo "| Configuration |"
@@ -204,13 +204,13 @@ while [[ $admin_password == "" ]];do
204204
fi
205205
done
206206
echo "Creating admin account: "
207-
python "${root_dir}/install/init_db.py" "${config_db_uri}" "${admin_name}" "${admin_email}" "${admin_password}"
207+
python3 "${root_dir}/install/init_db.py" "${config_db_uri}" "${admin_name}" "${admin_email}" "${admin_password}"
208208
# Create sample database if user wanted to
209209
if [ "${sample_response}" == 'y' ]; then
210210
echo "Creating sample database.."
211211
sample_dir="${dir}/sample_files/*"
212212
cp -r $sample_dir "${sample_repository}/TestFiles"
213-
python "${dir}/sample_db.py" "${config_db_uri}"
213+
python3 "${dir}/sample_db.py" "${config_db_uri}"
214214
fi
215215
echo ""
216216
echo "-------------------------------"

install/installation.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ determine what goes wrong. The snippet below shows how this can be done:
162162
163163
```
164164
cd /var/www/sample-platform/
165-
sudo python bootstrap_gunicorn.py
165+
sudo python3 bootstrap_gunicorn.py
166166
```
167167
168168
* If `gunicorn` boots up successfully, most relevant logs will be stored in
@@ -211,7 +211,7 @@ The file `mod_ci/cron.py` is to be run in periodic intervals. To setup a cron jo
211211
1. Open your terminal and enter the command `sudo crontab -e`.
212212
2. To setup a cron job that runs this file every 10 minutes, append this at the bottom of the file
213213
```
214-
*/10 * * * * python /var/www/sample-platform/mod_ci/cron.py > /var/www/sample-platform/logs/cron.log 2>&1
214+
*/10 * * * * python3 /var/www/sample-platform/mod_ci/cron.py > /var/www/sample-platform/logs/cron.log 2>&1
215215
```
216216
Change the `/var/www/sample-plaform` directory, if you have installed the platform in a different directory.
217217

install/sample_db.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/usr/bin/python
1+
#!/usr/bin/python3
22

33
import sys
44
from os import path

mod_ci/controllers.py

Lines changed: 39 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
from pymysql.err import IntegrityError
2929
from sqlalchemy import and_, func, select
3030
from sqlalchemy.sql import label
31-
from sqlalchemy.sql.functions import count
3231
from werkzeug.utils import secure_filename
3332

3433
from database import DeclEnum, create_session
@@ -249,8 +248,8 @@ class Workflow_builds(DeclEnum):
249248
class Artifact_names(DeclEnum):
250249
"""Define CCExtractor GitHub Artifacts names."""
251250

252-
linux = "CCExtractor Linux build"
253-
windows = "CCExtractor Windows x64 Release build"
251+
linux = "CCExtractor Linux build (with migrations)"
252+
windows = "CCExtractor Windows x64 Release build (with migrations)"
254253

255254

256255
def is_valid_commit_hash(commit: Optional[str]) -> bool:
@@ -2276,14 +2275,16 @@ def start_ci():
22762275
return json.dumps({'msg': 'EOL'})
22772276

22782277

2279-
def update_build_badge(status, test) -> None:
2278+
def update_build_badge(status, test, test_results=None) -> None:
22802279
"""
22812280
Build status badge for current test to be displayed on sample-platform.
22822281
22832282
:param status: current testing status
22842283
:type status: str
22852284
:param test: current commit that is tested
22862285
:type test: Test
2286+
:param test_results: pre-computed results from get_test_results; if None, fetched internally
2287+
:type test_results: list | None
22872288
:return: null
22882289
:rtype: null
22892290
"""
@@ -2294,7 +2295,8 @@ def update_build_badge(status, test) -> None:
22942295
shutil.copyfile(original_location, build_status_location)
22952296
g.log.info('Build badge updated successfully!')
22962297

2297-
test_results = get_test_results(test)
2298+
if test_results is None:
2299+
test_results = get_test_results(test)
22982300
test_ids_to_update = []
22992301
for category_results in test_results:
23002302
test_ids_to_update.extend([test['test'].id for test in category_results['tests'] if not test['error']])
@@ -2429,33 +2431,15 @@ def progress_type_request(log, test, test_id, request) -> bool:
24292431
message = 'Tests aborted due to an error; please check'
24302432

24312433
elif status == TestStatus.completed:
2432-
# Determine if success or failure
2433-
# It fails if any of these happen:
2434-
# - A crash (unexpected exit code)
2435-
# - A not None value on the "got" of a TestResultFile (
2436-
# meaning the hashes do not match)
2437-
crashes = g.db.query(count(TestResult.exit_code)).filter(
2438-
and_(
2439-
TestResult.test_id == test.id,
2440-
TestResult.exit_code != TestResult.expected_rc
2441-
)).scalar()
2442-
results_zero_rc = select(RegressionTest.id).filter(
2443-
RegressionTest.expected_rc == 0
2434+
test_results = get_test_results(test)
2435+
has_failures = any(
2436+
t['error']
2437+
for category in test_results
2438+
for t in category['tests']
24442439
)
2445-
results = g.db.query(count(TestResultFile.got)).filter(
2446-
and_(
2447-
TestResultFile.test_id == test.id,
2448-
TestResultFile.regression_test_id.in_(
2449-
results_zero_rc.select()
2450-
),
2451-
TestResultFile.got.isnot(None)
2452-
)
2453-
).scalar()
2454-
log.debug(f'[Test: {test.id}] Test completed: {crashes} crashes, {results} results')
2455-
if crashes > 0 or results > 0:
2440+
if has_failures:
24562441
state = Status.FAILURE
24572442
message = 'Not all tests completed successfully, please check'
2458-
24592443
else:
24602444
state = Status.SUCCESS
24612445
message = 'Tests completed'
@@ -2468,7 +2452,7 @@ def progress_type_request(log, test, test_id, request) -> bool:
24682452
message = 'All tests passed'
24692453
else:
24702454
message = 'Not all tests completed successfully, please check'
2471-
update_build_badge(state, test)
2455+
update_build_badge(state, test, test_results)
24722456

24732457
else:
24742458
message = progress.message
@@ -2526,29 +2510,17 @@ def update_final_status():
25262510
TestProgress.test_id.in_(platform_tests.select())
25272511
)
25282512
)
2529-
in_progress_statuses = [TestStatus.preparation, TestStatus.completed, TestStatus.canceled]
2530-
finished_tests_progress = g.db.query(TestProgress).filter(
2531-
and_(
2532-
TestProgress.test_id.in_(finished_tests.select()),
2533-
TestProgress.status.in_(in_progress_statuses)
2534-
)
2535-
).subquery()
25362513
times = g.db.query(
2537-
finished_tests_progress.c.test_id,
2538-
label('time', func.group_concat(finished_tests_progress.c.timestamp))
2539-
).group_by(finished_tests_progress.c.test_id).all()
2514+
TestProgress.test_id,
2515+
label('start_time', func.min(TestProgress.timestamp)),
2516+
label('end_time', func.max(TestProgress.timestamp))
2517+
).filter(
2518+
TestProgress.test_id.in_(finished_tests)
2519+
).group_by(TestProgress.test_id).all()
25402520

25412521
for p in times:
2542-
parts = p.time.split(',')
2543-
try:
2544-
# Try parsing with microsecond precision first
2545-
start = datetime.datetime.strptime(parts[0], '%Y-%m-%d %H:%M:%S.%f')
2546-
end = datetime.datetime.strptime(parts[-1], '%Y-%m-%d %H:%M:%S.%f')
2547-
except ValueError:
2548-
# Fall back to format without microseconds
2549-
start = datetime.datetime.strptime(parts[0], '%Y-%m-%d %H:%M:%S')
2550-
end = datetime.datetime.strptime(parts[-1], '%Y-%m-%d %H:%M:%S')
2551-
total_time += int((end - start).total_seconds())
2522+
duration = max(0, int((p.end_time - p.start_time).total_seconds()))
2523+
total_time += duration
25522524

25532525
if len(times) != 0:
25542526
average_time = total_time // len(times)
@@ -2559,10 +2531,15 @@ def update_final_status():
25592531
safe_db_commit(g.db, "setting new average time")
25602532

25612533
else:
2562-
all_results = TestResult.query.count()
2563-
regression_test_count = RegressionTest.query.count()
2564-
number_test = all_results / regression_test_count
2565-
updated_average = float(current_average.value) * (number_test - 1)
2534+
# Count actual finished tests for this platform
2535+
platform_tests = g.db.query(Test.id).filter(Test.platform == test.platform).subquery()
2536+
number_test = g.db.query(func.count(func.distinct(TestProgress.test_id))).filter(
2537+
and_(
2538+
TestProgress.status.in_([TestStatus.completed, TestStatus.canceled]),
2539+
TestProgress.test_id.in_(platform_tests)
2540+
)
2541+
).scalar() or 0
2542+
25662543
pr = test.progress_data()
25672544
end_time = pr['end']
25682545
start_time = pr['start']
@@ -2573,9 +2550,14 @@ def update_final_status():
25732550
if start_time.tzinfo is not None:
25742551
start_time = start_time.replace(tzinfo=None)
25752552

2576-
last_running_test = end_time - start_time
2577-
updated_average = updated_average + last_running_test.total_seconds()
2578-
current_average.value = 0 if number_test == 0 else updated_average // number_test
2553+
last_duration = max(0, int((end_time - start_time).total_seconds()))
2554+
2555+
if number_test > 1:
2556+
updated_average = (float(current_average.value) * (number_test - 1) + last_duration) / number_test
2557+
else:
2558+
updated_average = last_duration
2559+
2560+
current_average.value = max(0, int(updated_average))
25792561
safe_db_commit(g.db, "updating average time")
25802562
log.info(f'average time updated to {str(current_average.value)}')
25812563

mod_ci/cron.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/usr/bin/python
1+
#!/usr/bin/python3
22
"""handle cron logic for CI platform."""
33

44
import sys

0 commit comments

Comments
 (0)