Revert "build: finish replacing paver assets (#34554)" (#34700)

Reverts #34554, which causes compilation of edX.org's
legacy comprehensive theme to be skipped in their deployment pipeline.
We have not determined the precise cause yet, but it seems like the
compile_sass management command is not correctly getting the
list of comprehensive theme directories from Django settings.
This commit is contained in:
Kyle McCormick
2024-05-06 12:57:51 -04:00
committed by GitHub
parent 08323ccb18
commit 4c0284b87d
9 changed files with 641 additions and 383 deletions

View File

@@ -1,14 +1,13 @@
"""
Management command for compiling sass.
DEPRECATED in favor of `npm run compile-sass`.
"""
import shlex
from django.core.management import BaseCommand
from django.conf import settings
from pavelib.assets import run_deprecated_command_wrapper
from django.core.management import BaseCommand, CommandError
from paver.easy import call_task
from openedx.core.djangoapps.theming.helpers import get_theme_base_dirs, get_themes, is_comprehensive_theming_enabled
from pavelib.assets import ALL_SYSTEMS
class Command(BaseCommand):
@@ -16,7 +15,7 @@ class Command(BaseCommand):
Compile theme sass and collect theme assets.
"""
help = "DEPRECATED. Use 'npm run compile-sass' instead."
help = 'Compile and collect themed assets...'
# NOTE (CCB): This allows us to compile static assets in Docker containers without database access.
requires_system_checks = []
@@ -29,7 +28,7 @@ class Command(BaseCommand):
parser (django.core.management.base.CommandParser): parsed for parsing command line arguments.
"""
parser.add_argument(
'system', type=str, nargs='*', default=["lms", "cms"],
'system', type=str, nargs='*', default=ALL_SYSTEMS,
help="lms or studio",
)
@@ -56,7 +55,7 @@ class Command(BaseCommand):
'--force',
action='store_true',
default=False,
help="DEPRECATED. Full recompilation is now always forced.",
help="Force full compilation",
)
parser.add_argument(
'--debug',
@@ -65,48 +64,77 @@ class Command(BaseCommand):
help="Disable Sass compression",
)
@staticmethod
def parse_arguments(*args, **options): # pylint: disable=unused-argument
"""
Parse and validate arguments for compile_sass command.
Args:
*args: Positional arguments passed to the update_assets command
**options: optional arguments passed to the update_assets command
Returns:
A tuple containing parsed values for themes, system, source comments and output style.
1. system (list): list of system names for whom to compile theme sass e.g. 'lms', 'cms'
2. theme_dirs (list): list of Theme objects
3. themes (list): list of Theme objects
4. force (bool): Force full compilation
5. debug (bool): Disable Sass compression
"""
system = options.get("system", ALL_SYSTEMS)
given_themes = options.get("themes", ["all"])
theme_dirs = options.get("theme_dirs", None)
force = options.get("force", True)
debug = options.get("debug", True)
if theme_dirs:
available_themes = {}
for theme_dir in theme_dirs:
available_themes.update({t.theme_dir_name: t for t in get_themes(theme_dir)})
else:
theme_dirs = get_theme_base_dirs()
available_themes = {t.theme_dir_name: t for t in get_themes()}
if 'no' in given_themes or 'all' in given_themes:
# Raise error if 'all' or 'no' is present and theme names are also given.
if len(given_themes) > 1:
raise CommandError("Invalid themes value, It must either be 'all' or 'no' or list of themes.")
# Raise error if any of the given theme name is invalid
# (theme name would be invalid if it does not exist in themes directory)
elif (not set(given_themes).issubset(list(available_themes.keys()))) and is_comprehensive_theming_enabled():
raise CommandError(
"Given themes '{themes}' do not exist inside any of the theme directories '{theme_dirs}'".format(
themes=", ".join(set(given_themes) - set(available_themes.keys())),
theme_dirs=theme_dirs,
),
)
if "all" in given_themes:
themes = list(available_themes.values())
elif "no" in given_themes:
themes = []
else:
# convert theme names to Theme objects, this will remove all themes if theming is disabled
themes = [available_themes.get(theme) for theme in given_themes if theme in available_themes]
return system, theme_dirs, themes, force, debug
def handle(self, *args, **options):
"""
Handle compile_sass command.
"""
systems = set(
{"lms": "lms", "cms": "cms", "studio": "cms"}[sys]
for sys in options.get("system", ["lms", "cms"])
)
theme_dirs = options.get("theme_dirs", settings.COMPREHENSIVE_THEME_DIRS) or []
themes_option = options.get("themes", []) # '[]' means 'all'
if not settings.ENABLE_COMPREHENSIVE_THEMING:
compile_themes = False
themes = []
elif "no" in themes_option:
compile_themes = False
themes = []
elif "all" in themes_option:
compile_themes = True
themes = []
else:
compile_themes = True
themes = themes_option
run_deprecated_command_wrapper(
old_command="./manage.py [lms|cms] compile_sass",
ignored_old_flags=list(set(["force"]) & set(options)),
new_command=shlex.join([
"npm",
"run",
("compile-sass-dev" if options.get("debug") else "compile-sass"),
"--",
*(["--skip-lms"] if "lms" not in systems else []),
*(["--skip-cms"] if "cms" not in systems else []),
*(["--skip-themes"] if not compile_themes else []),
*(
arg
for theme_dir in theme_dirs
for arg in ["--theme-dir", str(theme_dir)]
system, theme_dirs, themes, force, debug = self.parse_arguments(*args, **options)
themes = [theme.theme_dir_name for theme in themes]
if options.get("themes", None) and not is_comprehensive_theming_enabled():
# log a warning message to let the user know that asset compilation for themes is skipped
self.stdout.write(
self.style.WARNING(
"Skipping theme asset compilation: enable theming to process themed assets"
),
*(
arg
for theme in themes
for arg in ["--theme", theme]
),
]),
)
call_task(
'pavelib.assets.compile_sass',
options={'system': system, 'theme_dirs': theme_dirs, 'themes': themes, 'force': force, 'debug': debug},
)

View File

@@ -2,23 +2,57 @@
Tests for Management commands of comprehensive theming.
"""
from django.core.management import call_command
from django.test import TestCase, override_settings
from unittest.mock import patch
import pytest
from django.core.management import CommandError, call_command
from django.test import TestCase
import pavelib.assets
from openedx.core.djangoapps.theming.helpers import get_themes
from openedx.core.djangoapps.theming.management.commands.compile_sass import Command
class TestUpdateAssets(TestCase):
"""
Test comprehensive theming helper functions.
"""
def setUp(self):
super().setUp()
self.themes = get_themes()
@patch.object(pavelib.assets, 'sh')
@override_settings(COMPREHENSIVE_THEME_DIRS='common/test')
def test_deprecated_wrapper(self, mock_sh):
call_command('compile_sass', '--themes', 'fake-theme1', 'fake-theme2')
assert mock_sh.called_once_with(
"npm run compile-sass -- " +
"--theme-dir common/test --theme fake-theme-1 --theme fake-theme-2"
def test_errors_for_invalid_arguments(self):
"""
Test update_asset command.
"""
# make sure error is raised for invalid theme list
with pytest.raises(CommandError):
call_command("compile_sass", themes=["all", "test-theme"])
# make sure error is raised for invalid theme list
with pytest.raises(CommandError):
call_command("compile_sass", themes=["no", "test-theme"])
# make sure error is raised for invalid theme list
with pytest.raises(CommandError):
call_command("compile_sass", themes=["all", "no"])
# make sure error is raised for invalid theme list
with pytest.raises(CommandError):
call_command("compile_sass", themes=["test-theme", "non-existing-theme"])
def test_parse_arguments(self):
"""
Test parse arguments method for update_asset command.
"""
# make sure compile_sass picks all themes when called with 'themes=all' option
parsed_args = Command.parse_arguments(themes=["all"])
self.assertCountEqual(parsed_args[2], get_themes())
# make sure compile_sass picks no themes when called with 'themes=no' option
parsed_args = Command.parse_arguments(themes=["no"])
self.assertCountEqual(parsed_args[2], [])
# make sure compile_sass picks only specified themes
parsed_args = Command.parse_arguments(themes=["test-theme"])
self.assertCountEqual(
parsed_args[2],
[theme for theme in get_themes() if theme.theme_dir_name == "test-theme"]
)