Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: CI

on:
push:
branches: [master]
pull_request:

jobs:
css:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
ruby: ['3.1', '3.4']
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- run: bundle exec rake css
7 changes: 6 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
source 'https://rubygems.org'

# Specify your gem's dependencies in activeadmin_theme.gemspec
# Specify your gem's dependencies in active_admin_theme.gemspec
gemspec

group :development, :test do
gem 'rake'
gem 'sassc'
end
6 changes: 6 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
require "bundler/gem_tasks"

desc "Compile the theme against ActiveAdmin and check the result"
task :css do
ruby "test/css_check.rb"
end

task default: :css
22 changes: 22 additions & 0 deletions app/assets/stylesheets/wigu/active_admin_theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,28 @@ $skinMainSecondColor: #5ea3d3!default;
$skinBorderRadius: 4px!default;
$skinBorderWindowColor: #e6e9ee!default;
$skinTablePadding: 10px!default;

// A wrong-typed override is legal SassScript, so it compiles without a word and
// emits CSS the browser drops — `border-bottom: none solid #5ea3d3`,
// `padding: 10 12px`. The rule silently vanishes and ActiveAdmin's own value
// reappears. Fail the build with a readable message instead.
@each $name, $value in (
skinBorderRadius: $skinBorderRadius,
skinTablePadding: $skinTablePadding
) {
@if type-of($value) != number or (unitless($value) and $value != 0) {
@error "$#{$name} must be a length with a unit (e.g. 10px), got `#{$value}`.";
}
}
@each $name, $value in (
skinMainFirstColor: $skinMainFirstColor,
skinMainSecondColor: $skinMainSecondColor,
skinBorderWindowColor: $skinBorderWindowColor
) {
@if type-of($value) != color {
@error "$#{$name} must be a color (use `transparent`, not `none`), got `#{$value}`.";
}
}
//HTML----------------------------------------------------------------------------------------------------------------//

html {
Expand Down
73 changes: 73 additions & 0 deletions test/css_check.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Compiles the theme against ActiveAdmin's own stylesheets and checks the
# result. Run with `rake css`.
#
# The gem ships SCSS, not CSS, so nothing in this repo's build ever compiles
# the theme: a change that only breaks under a particular variable override
# reaches consumers unnoticed. This is the only thing here that does compile it.
require "sassc"

module CssCheck
STYLESHEETS = File.expand_path("../app/assets/stylesheets", __dir__)
THEME = "wigu/active_admin_theme"

# Overrides a host project would plausibly write. Each must compile and keep
# producing CSS the browser accepts.
GOOD = {
"defaults" => "",
"accent" => '$skinMainSecondColor: #0066cc;',
"dark chrome" => '$skinMainFirstColor: #111418; $skinBorderWindowColor: #b8babe;',
"square + wide" => '$skinBorderRadius: 0; $skinTablePadding: 14px;',
"rem radius" => '$skinBorderRadius: 0.25rem;',
}.freeze

# Wrong-typed overrides. All of these are legal SassScript, so without the
# guards in the theme they compile silently and emit declarations the browser
# drops — the rule simply vanishes and ActiveAdmin's own value reappears, with
# nothing in the build output to say why.
BAD = {
"$skinBorderRadius without a unit" => '$skinBorderRadius: 4;',
"$skinTablePadding: none" => '$skinTablePadding: none;',
"$skinBorderWindowColor: none" => '$skinBorderWindowColor: none;',
}.freeze

def self.load_paths
activeadmin = Gem::Specification.find_by_name("activeadmin").gem_dir
[File.join(activeadmin, "app/assets/stylesheets"), STYLESHEETS]
end

def self.compile(overrides)
source = <<~SCSS
@import "active_admin/mixins";
#{overrides}
@import "active_admin/base";
@import "#{THEME}";
SCSS
SassC::Engine.new(source, load_paths: load_paths, style: :expanded).render
end

def self.run
failures = []

GOOD.each do |name, overrides|
compile(overrides)
rescue SassC::SyntaxError => e
failures << "#{name}: should compile, but does not — #{e.message.lines.first.strip}"
end

BAD.each do |name, overrides|
compile(overrides)
failures << "#{name}: should be rejected with @error, but compiled silently"
rescue SassC::SyntaxError
# expected — the theme's type guards caught it
end

if failures.empty?
puts "css_check: #{GOOD.size} overrides compile clean, #{BAD.size} bad ones rejected"
else
failures.each { |failure| warn "css_check: #{failure}" }
abort "css_check: #{failures.size} problem(s)"
end
end
end

CssCheck.run if $PROGRAM_NAME == __FILE__
Loading