Skip to content

Commit ad7f8d0

Browse files
authored
chore: Upgrade versions (#301)
* chore: Upgrade versions * fix: Easy to fix errors in CI * feature: Migarte from pg 11 to pg 13 * fix: Sorcery stuff * feature: pg11->13 * fix: Too board exceptions * fix: Comprehension to generator * fix: Broad error catches * fix: lint * fix: lint * fix: Finally, fix pytest on autochecker * fix: Add some tests (+ I hate Celery testing) * fix: Add tests for bootstrap and linter * fix: Refactors and style fixes * fix: We don't really have yarn.lock yet * fix: NOQA on import subprocces * fix: Test lints * fix: Add noqa to fake pass * fix: Add noqa to fake pass
1 parent 0aca325 commit ad7f8d0

39 files changed

+486
-3061
lines changed

dev_requirements.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
debugpy==1.0.0rc2
2-
ipdb==0.13.3
3-
pytest-cov==2.10.1
1+
debugpy==1.4.3
2+
ipdb==0.13.9
3+
pytest-cov==2.12.1
44
pytest-env==0.6.2

devops/build.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,8 @@ SCRIPT_FILE_PATH=$(readlink -f "${0}")
44
SCRIPT_FOLDER=$(dirname "${SCRIPT_FILE_PATH}")
55
MAIN_FOLDER="${SCRIPT_FOLDER}/.."
66

7+
echo "Asking for sudo to chown the rabbitmq cookie:"
8+
sudo chown "$USER:$USER" "$SCRIPT_FOLDER/rabbitmq.cookie"
9+
710
echo "Running build on folder ${MAIN_FOLDER}"
811
( cd "${MAIN_FOLDER}" && docker build -t lms . )

devops/dev_bootstrap.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ CONFIG_FILE_PATH="${LMSWEB_FOLDER}/config.py"
1515
CONFIG_EXAMPLE_FILE_PATH="${LMSWEB_FOLDER}/config.py.example"
1616
DB_BOOTSTRAP_FILE_PATH="${LMSAPP_FOLDER}/lmsdb/bootstrap.py"
1717

18+
python_exec=python
19+
pip_exec=pip
20+
1821
if ! (test -f "${CONFIG_FILE_PATH}"); then
1922
echo "Creating config from template"
2023
cp "${CONFIG_EXAMPLE_FILE_PATH}" "${CONFIG_FILE_PATH}"

devops/lms.yml

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,31 @@ version: "3"
22

33
services:
44
db:
5-
image: postgres:11-alpine
5+
image: postgres:13-alpine
66
ports:
77
- 5432:5432
88
volumes:
99
- db-data-volume:/pg_data
1010
environment:
11-
- PGDATA=/pg_data
11+
- PGDATA=/pg_data/13/data
1212
- POSTGRES_DB=${DB_NAME:-db}
1313
- POSTGRES_USER=${DB_USERNAME:-postgres}
1414
- POSTGRES_PASSWORD=${DB_PASSWORD:-postgres}
1515
healthcheck:
16-
test: ["CMD-SHELL", "pg_isready", "-U", "$DB_NAME"]
16+
test: ["CMD-SHELL", "pg_isready -U $DB_USERNAME -d $DB_NAME"]
1717
interval: 30s
1818
timeout: 30s
1919
retries: 3
2020
networks:
2121
- lms
2222

2323
rabbitmq:
24-
image: rabbitmq:3.7-management-alpine
24+
image: rabbitmq:3.9-management-alpine
2525
hostname: celery-mq
26-
environment:
27-
- RABBITMQ_ERLANG_COOKIE=AAVyo5djdSMGIZXiwEQs3JeVaBx5l14z
28-
- RABBITMQ_DEFAULT_USER=rabbit-user
29-
- RABBITMQ_DEFAULT_PASS=YgKlCvnYVzpTa3T9adG3NrMoUNe4Z5aZ
30-
- RABBITMQ_DEFAULT_VHOST=/
3126
volumes:
3227
- rabbit-data-volume:/var/lib/rabbitmq
28+
- ./rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf
29+
- ./rabbitmq.cookie:/var/lib/rabbitmq/.erlang.cookie
3330
networks:
3431
- lms
3532

devops/rabbitmq.conf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
default_user=rabbit-user
2+
default_pass=YgKlCvnYVzpTa3T9adG3NrMoUNe4Z5aZ
3+
default_vhost=/

devops/rabbitmq.cookie

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
erlang_cookie=AAVyo5djdSMGIZXiwEQs3JeVaBx5l14z

devops/upgrade_pg/upgrade.sh

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
docker stop lms_db_1
2+
3+
# Put values here if you've configured them before
4+
# DB_NAME=lms
5+
# DB_USERNAME=lmsweb
6+
# DB_PASSWORD=
7+
8+
CURRENT_DATE=$(date +%d-%m-%Y_%H_%M_%S)
9+
MOUNT_PATH=/pg_data
10+
PG_OLD_DATA=/pg_data/11/data
11+
PG_NEW_DATA=/pg_data/13/data
12+
BACKUP_FILENAME=v11.$CURRENT_DATE.sql
13+
BACKUP_PATH=$MOUNT_PATH/backup/$BACKUP_FILENAME
14+
BACKUP_DIR=$(dirname "$BACKUP_PATH")
15+
VOLUME_NAME=lms_db-data-volume
16+
17+
# Step 1: Create a backup
18+
docker run --rm -v $VOLUME_NAME:$MOUNT_PATH \
19+
-e PGDATA=$PG_OLD_DATA \
20+
-e POSTGRES_DB="${DB_NAME:-db}" \
21+
-e POSTGRES_USER="${DB_USERNAME:-postgres}" \
22+
-e POSTGRES_PASSWORD="${DB_PASSWORD:-postgres}" \
23+
postgres:11-alpine \
24+
/bin/bash -c "chown -R postgres:postgres $MOUNT_PATH \
25+
&& su - postgres /bin/bash -c \"/usr/local/bin/pg_ctl -D \\\"\$PGDATA\\\" start\" \
26+
&& mkdir -p \"$BACKUP_DIR\" \
27+
&& pg_dumpall -U $DB_USERNAME -f \"$BACKUP_PATH\" \
28+
&& chown postgres:postgres \"$BACKUP_PATH\""
29+
30+
# Step 2: Create a new database from the backup
31+
docker run --rm -v $VOLUME_NAME:$MOUNT_PATH \
32+
-e PGDATA=$PG_NEW_DATA \
33+
-e POSTGRES_DB="${DB_NAME:-db}" \
34+
-e POSTGRES_USER="${DB_USERNAME:-postgres}" \
35+
-e POSTGRES_PASSWORD="${DB_PASSWORD:-postgres}" \
36+
postgres:13-alpine \
37+
/bin/bash -c "ls -la \"$BACKUP_DIR\" \
38+
&& mkdir -p \"\$PGDATA\" \
39+
&& chown -R postgres:postgres \"\$PGDATA\" \
40+
&& rm -rf $PG_NEW_DATA/* \
41+
&& su - postgres -c \"initdb -D \\\"\$PGDATA\\\"\" \
42+
&& su - postgres -c \"pg_ctl -D \\\"\$PGDATA\\\" -l logfile start\" \
43+
&& su - postgres -c \"psql -f $BACKUP_PATH\" \
44+
&& printf \"\\\nhost all all all md5\\\n\" >> \"\$PGDATA/pg_hba.conf\" \
45+
"

lms/lmsdb/bootstrap.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from typing import Any, Callable, Optional, Tuple, Type
22

33
from peewee import (
4-
Entity, Expression, Field, Model, OP, OperationalError, ProgrammingError,
5-
SQL,
4+
Database, Entity, Expression, Field, Model, OP,
5+
OperationalError, ProgrammingError, SQL,
66
)
77
from playhouse.migrate import migrate
88

@@ -215,12 +215,8 @@ def _drop_constraint_if_needed(table: Type[Model], column_name: str) -> bool:
215215
return True
216216

217217

218-
def has_column_named(table: Model, column_name: str) -> bool:
219-
db = db_config.database
220-
columns = {col.name for col in db.get_columns(table.__name__.lower())}
221-
if column_name not in columns:
222-
return False
223-
return True
218+
def has_column_named(db: Database, table: Model, column_name: str) -> bool:
219+
return column_name in table._meta.sorted_field_names
224220

225221

226222
def _add_api_keys_to_users_table(table: Model, _column: Field) -> None:

lms/lmstests/public/general/tasks.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,14 @@
1212

1313
@app.task
1414
def reset_solution_state_if_needed(solution_pk: str) -> None:
15+
_logger.info('reset_solution_state_if_needed: solution %s', solution_pk)
16+
1517
try:
16-
_logger.info(
17-
'Start reset_solution_state_if_needed solution %s',
18-
solution_pk,
19-
)
2018
solution = models.Solution.get_by_id(solution_pk)
21-
if solution.state == models.Solution.STATES.IN_CHECKING.name:
22-
_logger.info('Reset solution %s to CREATED state', solution_pk)
23-
solution.set_state(models.Solution.STATES.CREATED)
24-
except Exception:
25-
_logger.exception(
26-
'Failed reset_solution_state_if_needed solution %s',
27-
solution_pk,
28-
)
19+
except models.Solution.DoesNotExist:
20+
_logger.exception('Solution %s does not exist', solution_pk)
21+
raise
22+
23+
if solution.state == models.Solution.STATES.IN_CHECKING.name:
24+
_logger.info('Reset solution %s to CREATED state', solution_pk)
25+
solution.set_state(models.Solution.STATES.CREATED)

lms/lmstests/public/identical_tests/services.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,12 @@ def check_for_match_solutions_to_solve(self):
6565
return
6666

6767
match_code = self.solution.solution_files.get().code
68-
for solution_file in models.SolutionFile.select().join(
69-
models.Solution,
70-
).filter(
68+
files = models.SolutionFile.select().join(models.Solution).filter(
7169
models.Solution.exercise == self.solution.exercise,
7270
models.Solution.state == models.Solution.STATES.CREATED.name,
7371
models.SolutionFile.code == match_code,
74-
):
72+
)
73+
for solution_file in files:
7574
self._clone_solution_comments(
7675
from_solution=self.solution,
7776
to_solution=solution_file.solution,

lms/lmstests/public/identical_tests/tasks.py

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from celery.utils.log import get_task_logger
44

5+
from lms.lmsdb.models import Solution
56
from lms.lmstests.public.config.celery import app
67
from lms.lmstests.public.identical_tests import services
78

@@ -12,33 +13,33 @@
1213

1314
@app.task
1415
def solve_solution_with_identical_code(solution_pk: str) -> None:
16+
_logger.info(
17+
'Start solve_solution_with_identical_code solution %s',
18+
solution_pk,
19+
)
20+
checker = services.IdenticalSolutionSolver(solution_pk, _logger)
21+
1522
try:
16-
_logger.info(
17-
'Start solve_solution_with_identical_code solution %s',
18-
solution_pk,
19-
)
20-
checker = services.IdenticalSolutionSolver(solution_pk, _logger)
2123
checker.initialize()
22-
checker.check_identical()
23-
except Exception:
24-
_logger.exception(
25-
'Failed check_if_other_solutions_can_be_solved solution %s',
26-
solution_pk,
27-
)
24+
except Solution.DoesNotExist:
25+
_logger.exception('Solution %s does not exist', solution_pk)
26+
raise
27+
28+
checker.check_identical()
2829

2930

3031
@app.task
3132
def check_if_other_solutions_can_be_solved(solution_pk: str) -> None:
33+
_logger.info(
34+
'Start check_if_other_solutions_can_be_solved solution %s',
35+
solution_pk,
36+
)
37+
checker = services.IdenticalSolutionSolver(solution_pk, _logger)
38+
3239
try:
33-
_logger.info(
34-
'Start check_if_other_solutions_can_be_solved solution %s',
35-
solution_pk,
36-
)
37-
checker = services.IdenticalSolutionSolver(solution_pk, _logger)
3840
checker.initialize()
39-
checker.check_for_match_solutions_to_solve()
40-
except Exception:
41-
_logger.exception(
42-
'Failed check_if_other_solutions_can_be_solved solution %s',
43-
solution_pk,
44-
)
41+
except Solution.DoesNotExist:
42+
_logger.exception('Solution %s does not exist', solution_pk)
43+
raise
44+
45+
checker.check_for_match_solutions_to_solve()

lms/lmstests/public/linters/services.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,7 @@
1616
class LinterChecker:
1717
sandbox_tasks = linters.tasks
1818

19-
def __init__(
20-
self,
21-
solution_check_pk: str,
22-
logger: logging.Logger,
23-
):
19+
def __init__(self, solution_check_pk: str, logger: logging.Logger):
2420
self._solution_id = solution_check_pk
2521
self._app = None
2622
self._solution = None

lms/lmstests/public/linters/tasks.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import logging
22

3+
from celery.exceptions import OperationalError, TaskError
34
from celery.utils.log import get_task_logger
45

6+
from lms.lmsdb import models
57
from lms.lmstests.public.config.celery import app
68
from lms.lmstests.public.linters import services
79

@@ -12,10 +14,16 @@
1214

1315
@app.task
1416
def run_linter_on_solution(solution_pk: str) -> None:
17+
_logger.info('Start running check solution %s', solution_pk)
18+
checker = services.LinterChecker(solution_pk, _logger)
19+
1520
try:
16-
_logger.info('Start running check solution %s', solution_pk)
17-
checker = services.LinterChecker(solution_pk, _logger)
1821
checker.initialize()
22+
except models.Solution.DoesNotExist:
23+
_logger.exception('Solution %s does not exist', solution_pk)
24+
raise
25+
26+
try:
1927
checker.run_check()
20-
except Exception:
28+
except (TaskError, OperationalError):
2129
_logger.exception('Failed to check solution %s', solution_pk)

lms/lmstests/public/unittests/executers.py

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ def __enter__(self):
5050
'--rm', '--name', self._container_name, self.base_image,
5151
'sleep', str(self.timeout_seconds),
5252
)
53-
log.info('Start executing safe container context with %s', args)
53+
command = ' '.join(args)
54+
log.info(f'Start executing safe container context with {command}')
5455
subprocess.check_call(args) # NOQA: S603
5556
return self
5657

@@ -89,9 +90,7 @@ def get_file(self, file_path: str):
8990

9091

9192
class SameProcessExecutor(BaseExecutor):
92-
"""
93-
Used only for testing / local setups without docker
94-
"""
93+
"""Used only for testing / local setups without docker"""
9594
def __init__(self):
9695
self._cwd = tempfile.mkdtemp()
9796

@@ -105,20 +104,22 @@ def run_on_executor(self, args: tuple):
105104
subprocess.run(args, cwd=self._cwd) # NOQA: S603
106105

107106
def write_file(self, file_path: str, content: str):
108-
open(os.path.join(self._cwd, file_path), 'w').write(content)
107+
with open(os.path.join(self._cwd, file_path), 'w') as f:
108+
f.write(content)
109109

110110
def get_file(self, file_path: str):
111-
return open(os.path.join(self._cwd, file_path), 'r').read()
112-
113-
114-
__MAPPING = {
115-
executor.executor_name(): executor
116-
for executor in (
117-
DockerExecutor,
118-
SameProcessExecutor,
119-
)
120-
}
111+
file_content = ''
112+
with open(os.path.join(self._cwd, file_path), 'r') as f:
113+
file_content = f.read()
114+
return file_content
121115

122116

123117
def get_executor(executor_name=None) -> BaseExecutor:
124118
return __MAPPING.get(executor_name, DockerExecutor)()
119+
120+
121+
EXECUTORS = (
122+
DockerExecutor,
123+
SameProcessExecutor,
124+
)
125+
__MAPPING = {executor.executor_name(): executor for executor in EXECUTORS}

lms/lmstests/public/unittests/import_tests.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def register_test_class(file_path: str, test_class: typing.ClassVar):
1515
subject = test_class.__doc__
1616
exercise = models.Exercise.get_or_none(models.Exercise.subject == subject)
1717
if not exercise:
18-
log.info('Failed to find exercise subject %s', subject)
18+
log.info(f'Failed to find exercise subject {subject}')
1919
raise SystemError
2020

2121
with open(file_path, 'r') as file_reader:

0 commit comments

Comments
 (0)