Repository: freedomofpress/securedrop

Issue:
Ruby sass gem used at build time has reached end-of-life
Per https://github.com/sass/ruby-sass (which is archived) and https://sass-lang.com/ruby-sass, this gem, which is [used at package build time](https://github.com/freedomofpress/securedrop/blob/develop/install_files/ansible-base/roles/build-securedrop-app-code-deb-pkg/tasks/sass.yml) for CSS generation, has reached end-of-life. We should consider migrating to a maintained codebase, like [sassc](https://github.com/sass/sassc) / `libsass`.

Note that we're also using a pinned outdated version due to #1594; we could update now that we're on Xenial, but that no longer seems worth resolving at this point.


Discussion:
Since I started working on the SI frontend, I looked into this a bit:

* [sassc](https://github.com/sass/sassc), while available from Debian/Ubuntu/Fedora repos, is now also deprecated but (supposedly) maintained (at time of writing the CI badges show that builds fail :shrug:)
* [DartSass](https://github.com/sass/dart-sass) is the only library/tool that is being actively worked on anymore. It requires either node.js to run the compiled-to-JS version, or Dart to build a native version. Dart itself is not available in Debian/Ubuntu (or Fedora) repos, instead they provide their own repo. They also release binaries on GitHub, but there's no signatures for those.

However, it may turn out that relying on Sass at all may not be necessary - after all, SecureDrop is an unusual webapp that has different targets and goals than most contemporary web apps. I'll look into that first, once I'm closer with #6211 
> However, it may turn out that relying on Sass at all may not be necessary - after all, SecureDrop is an unusual webapp that has different targets and goals than most contemporary web apps. I'll look into that first, once I'm closer with https://github.com/freedomofpress/securedrop/issues/6211

@eaon I'm curious how you feel about this now that #6315 has landed. If we're still stuck with sass in the short term, I would like to switch us over to sassc, which is at least maintained in Debian, allowing us to drop all the ruby stuff from our stack.
Briefly discussed with @eaon, we could theoretically get rid of sass but it would require compiling everything to CSS and switching to CSS variables, etc. and I'm not ready to take that all on. I'm first going to see how difficult it would be to drop in sassc, as that would be enough to unblock my Debian packaging work.
I generated journalist.css using both the ruby gem and sassc, the diff is: https://gist.github.com/legoktm/8700e8e132a592f00689c040d7a3fdec

Differences:
* single quotes instead of double quotes
* escape sequences instead of unicode symbols
* omitting `0.` prefix for numbers
* weird comment indentation

Resolving patch:
diff --git a/securedrop/management/run.py b/securedrop/management/run.py
--- a/securedrop/management/run.py
+++ b/securedrop/management/run.py
@@ -167,9 +167,6 @@ def run(args: Any) -> None:  # pragma: no cover
     procs = [
         lambda: DevServerProcess("Source Interface", ["python", "source.py"], "blue"),
         lambda: DevServerProcess("Journalist Interface", ["python", "journalist.py"], "cyan"),
-        lambda: DevServerProcess(
-            "SASS Compiler", ["sass", "--watch", "sass:static/css"], "magenta"
-        ),
     ]
 
     monitor = DevServerProcessMonitor(procs)


Test patch:
diff --git a/molecule/builder-focal/tests/test_build_dependencies.py b/molecule/builder-focal/tests/test_build_dependencies.py
--- a/molecule/builder-focal/tests/test_build_dependencies.py
+++ b/molecule/builder-focal/tests/test_build_dependencies.py
@@ -9,15 +9,6 @@
 testinfra_hosts = ["docker://{}-sd-app".format(SECUREDROP_TARGET_DISTRIBUTION)]
 
 
-def test_sass_gem_installed(host):
-    """
-    Ensure the `sass` Ruby gem is installed, for compiling SASS to CSS.
-    """
-    c = host.run("gem list")
-    assert "sass (3.4.23)" in c.stdout
-    assert c.rc == 0
-
-
 @pytest.mark.xfail(reason="This check conflicts with the concept of pegging" "dependencies")
 def test_build_all_packages_updated(host):
     """
diff --git a/molecule/builder-focal/tests/test_securedrop_deb_package.py b/molecule/builder-focal/tests/test_securedrop_deb_package.py
--- a/molecule/builder-focal/tests/test_securedrop_deb_package.py
+++ b/molecule/builder-focal/tests/test_securedrop_deb_package.py
@@ -266,12 +266,6 @@ def test_deb_package_contains_no_generated_assets(securedrop_app_code_contents:
         re.M,
     )
 
-    # no SASS files should exist.
-    assert not re.search("^.*sass$", securedrop_app_code_contents, re.M)
-
-    # no .map files should exist.
-    assert not re.search("^.*css.map$", securedrop_app_code_contents, re.M)
-
 
 @pytest.mark.parametrize("deb", deb_paths.values())
 def test_deb_package_contains_expected_conffiles(host: Host, deb: Path):
@@ -307,8 +301,7 @@ def test_deb_package_contains_expected_conffiles(host: Host, deb: Path):
 
 def test_securedrop_app_code_contains_css(securedrop_app_code_contents: str) -> None:
     """
-    Ensures the `securedrop-app-code` package contains files that
-    are generated during the `sass` build process.
+    Ensures the `securedrop-app-code` package contains necessary css files
     """
     for css_type in ["journalist", "source"]:
         assert re.search(