diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..d681be2 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,13 @@ +.bundle +.git +.github +Dockerfile* +Gemfile.lock +Knylefile +LICENSE +README.md +SPEC.md +docker-bake.hcl +example +test-all-rubies.sh +coverage/ diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..7736f5f --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,57 @@ +name: Tests + +on: + push: + branches: [master] + pull_request: + workflow_dispatch: + +jobs: + test: + name: Ruby ${{ matrix.ruby }} + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.allow_failure || false }} + strategy: + fail-fast: false + matrix: + ruby: + - "1.9" + - "2.0" + - "2.1" + - "2.2" + - "2.3" + - "2.4" + - "2.5" + - "2.6" + - "2.7" + - "3.0" + - "3.1" + - "3.2" + - "3.3" + - "3.4" + - "4.0" + - head + coverage: [0] + include: + - ruby: "4.0" + coverage: 1 + - ruby: head + allow_failure: true + steps: + - uses: actions/checkout@v4 + - uses: docker/setup-buildx-action@v3 + - name: Build + run: docker buildx bake --load "ruby-${RUBY//\./-}" + env: + RUBY: ${{ matrix.ruby }} + - name: Test + run: docker run --rm -e COVERAGE=${{ matrix.coverage }} "kss-test:${{ matrix.ruby }}" + + gate: + name: All Tests + needs: [test] + if: always() + runs-on: ubuntu-slim + steps: + - if: ${{ !success() }} + run: exit 1 diff --git a/.gitignore b/.gitignore index b876770..190c1e9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .bundle Gemfile.lock bin -.sass-cache \ No newline at end of file +.sass-cache +coverage/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index f5422dc..0000000 --- a/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: ruby -rvm: - - 2.0.0 - - 1.9.3 - diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..741aee7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,64 @@ +FROM debian:bullseye + +RUN apt-get update && apt-get install -y \ + autotools-dev build-essential curl ca-certificates \ + libssl-dev libreadline-dev libffi-dev libyaml-dev zlib1g-dev \ + && rm -rf /var/lib/apt/lists/* + +ARG OPENSSL=1.0.2 +# Build OpenSSL 1.0.2 only when needed (Ruby <2.4 is incompatible with OpenSSL 1.1+) +RUN if [ "$OPENSSL" = "1.0.2" ]; then \ + curl -fSL https://www.openssl.org/source/openssl-1.0.2u.tar.gz | tar -xzC /usr/local/src \ + && cd /usr/local/src/openssl-1.0.2u \ + && ./config --prefix=/opt/openssl-1.0.2 shared \ + && make -j"$(nproc)" \ + && make install_sw \ + && rm -rf /usr/local/src/openssl-1.0.2u; \ + fi + +ARG RUBY_MAJOR=1.9 +ARG RUBY_VERSION=1.9.3-p551 +ARG RUBY_ARCHIVE=bz2 + +# Download and extract Ruby source +RUN mkdir -p /usr/local/src/ruby \ + && curl -fSL "https://cache.ruby-lang.org/pub/ruby/${RUBY_MAJOR}/ruby-${RUBY_VERSION}.tar.${RUBY_ARCHIVE}" \ + | tar -x$([ "$RUBY_ARCHIVE" = "bz2" ] && echo j || echo z)C /usr/local/src/ruby --strip-components=1 + +# Patch config.guess/config.sub for aarch64 support, then compile +RUN cp /usr/share/misc/config.guess /usr/local/src/ruby/tool/ \ + && cp /usr/share/misc/config.sub /usr/local/src/ruby/tool/ \ + && cd /usr/local/src/ruby \ + && OPENSSL_DIR=$([ "$OPENSSL" = "1.0.2" ] && echo /opt/openssl-1.0.2 || echo /usr) \ + && ./configure --prefix=/opt/rubies/ruby-${RUBY_VERSION} --disable-install-doc \ + --with-openssl-dir=$OPENSSL_DIR \ + && if [ "$(printf '%s\n' "2.5" "$RUBY_MAJOR" | sort -V | head -n1)" = "2.5" ]; then \ + make -j"$(nproc)"; \ + else \ + make; \ + fi \ + && make install \ + && rm -rf /usr/local/src/ruby + +ENV PATH=/opt/rubies/ruby-${RUBY_VERSION}/bin:$PATH +ENV LD_LIBRARY_PATH=/opt/openssl-1.0.2/lib +ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt + +ARG INSTALL_BUNDLER=1.17.3 +RUN if [ -n "$INSTALL_BUNDLER" ]; then \ + gem install bundler -v $INSTALL_BUNDLER --no-document 2>/dev/null \ + || gem install bundler -v $INSTALL_BUNDLER --no-rdoc --no-ri; \ + fi + +WORKDIR /app +COPY . . + +RUN --mount=type=cache,target=/bundle-cache \ + (bundle config set --local path /bundle-cache 2>/dev/null \ + || bundle config --local path /bundle-cache) \ + && (bundle check || bundle install --jobs $(nproc)) \ + && mkdir -p vendor/bundle \ + && cp -a /bundle-cache/. vendor/bundle/ \ + && (bundle config set --local path vendor/bundle 2>/dev/null \ + || bundle config --local path vendor/bundle) +CMD ["bundle", "exec", "rake", "test"] diff --git a/Dockerfile.head b/Dockerfile.head new file mode 100644 index 0000000..e1992c3 --- /dev/null +++ b/Dockerfile.head @@ -0,0 +1,31 @@ +FROM debian:bookworm + +RUN apt-get update && apt-get install -y \ + autotools-dev autoconf bison build-essential curl ca-certificates git \ + ruby \ + libssl-dev libreadline-dev libffi-dev libyaml-dev zlib1g-dev \ + && rm -rf /var/lib/apt/lists/* + +RUN git clone --depth 1 https://github.com/ruby/ruby.git /usr/local/src/ruby \ + && cd /usr/local/src/ruby \ + && ./autogen.sh \ + && cp /usr/share/misc/config.guess tool/ \ + && cp /usr/share/misc/config.sub tool/ \ + && ./configure --prefix=/opt/rubies/ruby-head --disable-install-doc \ + && make -j"$(nproc)" \ + && make install \ + && rm -rf /usr/local/src/ruby + +ENV PATH=/opt/rubies/ruby-head/bin:$PATH +ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt + +WORKDIR /app +COPY . . + +RUN --mount=type=cache,target=/bundle-cache \ + bundle config set --local path /bundle-cache \ + && (bundle check || bundle install --jobs $(nproc)) \ + && mkdir -p vendor/bundle \ + && cp -a /bundle-cache/* vendor/bundle/ \ + && bundle config set --local path vendor/bundle +CMD ["bundle", "exec", "rake", "test"] diff --git a/Gemfile b/Gemfile index b39e696..7de125a 100644 --- a/Gemfile +++ b/Gemfile @@ -1,11 +1,21 @@ -source 'https://rubygems.org' +source "https://rubygems.org" group :test do - gem "minitest", "~> 5.0.4" + if RUBY_VERSION >= "4.0" + gem "minitest", "~> 6.0" + elsif RUBY_VERSION >= "3.4" + gem "minitest", "~> 5.25" + else + gem "minitest", "~> 5.0.4" + end + gem "test-unit" unless RUBY_VERSION < "2.0" + gem "simplecov", require: false if RUBY_VERSION >= "2.4" end group :development do - gem "mg", ">= 0.0.8" - gem "rake", ">= 0.8.7" - gem "rubyforge", ">= 2.0.3" -end \ No newline at end of file + if RUBY_VERSION < "2.3" + gem "rake", "~> 12.0" + else + gem "rake", "~> 13.0" + end +end diff --git a/Rakefile b/Rakefile index 856c862..4c3d2c0 100644 --- a/Rakefile +++ b/Rakefile @@ -34,23 +34,3 @@ task :console do exec "irb -I lib -rkss" end -# -# Gems -# - -begin - require 'mg' - MG.new("kss.gemspec") -rescue LoadError - warn "mg not available." - warn "Install it with: gem install mg" -end - -desc "Push a new version to Gemcutter and publish docs." -task :publish => "gem:publish" do - require File.dirname(__FILE__) + '/lib/kss/version' - - sh "git tag v#{Kss::VERSION}" - sh "git push origin master --tags" - sh "git clean -fd" -end \ No newline at end of file diff --git a/docker-bake.hcl b/docker-bake.hcl new file mode 100644 index 0000000..9c25144 --- /dev/null +++ b/docker-bake.hcl @@ -0,0 +1,231 @@ +variable "VERSIONS" { + default = { + "1.9" = { version = "1.9.3-p551", archive = "bz2", openssl = "1.0.2", bundler = "1.17.3" } + "2.0" = { version = "2.0.0-p648", archive = "bz2", openssl = "1.0.2", bundler = "1.17.3" } + "2.1" = { version = "2.1.10", archive = "bz2", openssl = "1.0.2", bundler = "1.17.3" } + "2.2" = { version = "2.2.10", archive = "bz2", openssl = "1.0.2", bundler = "1.17.3" } + "2.3" = { version = "2.3.8", archive = "bz2", openssl = "1.0.2", bundler = "1.17.3" } + "2.4" = { version = "2.4.10", archive = "bz2", openssl = "1.1", bundler = "1.17.3" } + "2.5" = { version = "2.5.9", archive = "bz2", openssl = "1.1", bundler = "1.17.3" } + "2.6" = { version = "2.6.10", archive = "bz2", openssl = "1.1", bundler = "1.17.3" } + "2.7" = { version = "2.7.8", archive = "bz2", openssl = "1.1", bundler = "" } + "3.0" = { version = "3.0.7", archive = "gz", openssl = "1.1", bundler = "" } + "3.1" = { version = "3.1.7", archive = "gz", openssl = "1.1", bundler = "" } + "3.2" = { version = "3.2.10", archive = "gz", openssl = "1.1", bundler = "" } + "3.3" = { version = "3.3.10", archive = "gz", openssl = "1.1", bundler = "" } + "3.4" = { version = "3.4.8", archive = "gz", openssl = "1.1", bundler = "" } + "4.0" = { version = "4.0.1", archive = "gz", openssl = "1.1", bundler = "" } + } +} + +group "default" { + targets = [ + "ruby-1-9", + "ruby-2-0", + "ruby-2-1", + "ruby-2-2", + "ruby-2-3", + "ruby-2-4", + "ruby-2-5", + "ruby-2-6", + "ruby-2-7", + "ruby-3-0", + "ruby-3-1", + "ruby-3-2", + "ruby-3-3", + "ruby-3-4", + "ruby-4-0", + "ruby-head", + ] +} + +target "_common" { + dockerfile = "Dockerfile" + context = "." +} + +target "ruby-1-9" { + inherits = ["_common"] + args = { + RUBY_MAJOR = "1.9" + RUBY_VERSION = VERSIONS["1.9"].version + RUBY_ARCHIVE = VERSIONS["1.9"].archive + OPENSSL = VERSIONS["1.9"].openssl + INSTALL_BUNDLER = VERSIONS["1.9"].bundler + } + tags = ["kss-test:1.9"] +} + +target "ruby-2-0" { + inherits = ["_common"] + args = { + RUBY_MAJOR = "2.0" + RUBY_VERSION = VERSIONS["2.0"].version + RUBY_ARCHIVE = VERSIONS["2.0"].archive + OPENSSL = VERSIONS["2.0"].openssl + INSTALL_BUNDLER = VERSIONS["2.0"].bundler + } + tags = ["kss-test:2.0"] +} + +target "ruby-2-1" { + inherits = ["_common"] + args = { + RUBY_MAJOR = "2.1" + RUBY_VERSION = VERSIONS["2.1"].version + RUBY_ARCHIVE = VERSIONS["2.1"].archive + OPENSSL = VERSIONS["2.1"].openssl + INSTALL_BUNDLER = VERSIONS["2.1"].bundler + } + tags = ["kss-test:2.1"] +} + +target "ruby-2-2" { + inherits = ["_common"] + args = { + RUBY_MAJOR = "2.2" + RUBY_VERSION = VERSIONS["2.2"].version + RUBY_ARCHIVE = VERSIONS["2.2"].archive + OPENSSL = VERSIONS["2.2"].openssl + INSTALL_BUNDLER = VERSIONS["2.2"].bundler + } + tags = ["kss-test:2.2"] +} + +target "ruby-2-3" { + inherits = ["_common"] + args = { + RUBY_MAJOR = "2.3" + RUBY_VERSION = VERSIONS["2.3"].version + RUBY_ARCHIVE = VERSIONS["2.3"].archive + OPENSSL = VERSIONS["2.3"].openssl + INSTALL_BUNDLER = VERSIONS["2.3"].bundler + } + tags = ["kss-test:2.3"] +} + +target "ruby-2-4" { + inherits = ["_common"] + args = { + RUBY_MAJOR = "2.4" + RUBY_VERSION = VERSIONS["2.4"].version + RUBY_ARCHIVE = VERSIONS["2.4"].archive + OPENSSL = VERSIONS["2.4"].openssl + INSTALL_BUNDLER = VERSIONS["2.4"].bundler + } + tags = ["kss-test:2.4"] +} + +target "ruby-2-5" { + inherits = ["_common"] + args = { + RUBY_MAJOR = "2.5" + RUBY_VERSION = VERSIONS["2.5"].version + RUBY_ARCHIVE = VERSIONS["2.5"].archive + OPENSSL = VERSIONS["2.5"].openssl + INSTALL_BUNDLER = VERSIONS["2.5"].bundler + } + tags = ["kss-test:2.5"] +} + +target "ruby-2-6" { + inherits = ["_common"] + args = { + RUBY_MAJOR = "2.6" + RUBY_VERSION = VERSIONS["2.6"].version + RUBY_ARCHIVE = VERSIONS["2.6"].archive + OPENSSL = VERSIONS["2.6"].openssl + INSTALL_BUNDLER = VERSIONS["2.6"].bundler + } + tags = ["kss-test:2.6"] +} + +target "ruby-2-7" { + inherits = ["_common"] + args = { + RUBY_MAJOR = "2.7" + RUBY_VERSION = VERSIONS["2.7"].version + RUBY_ARCHIVE = VERSIONS["2.7"].archive + OPENSSL = VERSIONS["2.7"].openssl + INSTALL_BUNDLER = VERSIONS["2.7"].bundler + } + tags = ["kss-test:2.7"] +} + +target "ruby-3-0" { + inherits = ["_common"] + args = { + RUBY_MAJOR = "3.0" + RUBY_VERSION = VERSIONS["3.0"].version + RUBY_ARCHIVE = VERSIONS["3.0"].archive + OPENSSL = VERSIONS["3.0"].openssl + INSTALL_BUNDLER = VERSIONS["3.0"].bundler + } + tags = ["kss-test:3.0"] +} + +target "ruby-3-1" { + inherits = ["_common"] + args = { + RUBY_MAJOR = "3.1" + RUBY_VERSION = VERSIONS["3.1"].version + RUBY_ARCHIVE = VERSIONS["3.1"].archive + OPENSSL = VERSIONS["3.1"].openssl + INSTALL_BUNDLER = VERSIONS["3.1"].bundler + } + tags = ["kss-test:3.1"] +} + +target "ruby-3-2" { + inherits = ["_common"] + args = { + RUBY_MAJOR = "3.2" + RUBY_VERSION = VERSIONS["3.2"].version + RUBY_ARCHIVE = VERSIONS["3.2"].archive + OPENSSL = VERSIONS["3.2"].openssl + INSTALL_BUNDLER = VERSIONS["3.2"].bundler + } + tags = ["kss-test:3.2"] +} + +target "ruby-3-3" { + inherits = ["_common"] + args = { + RUBY_MAJOR = "3.3" + RUBY_VERSION = VERSIONS["3.3"].version + RUBY_ARCHIVE = VERSIONS["3.3"].archive + OPENSSL = VERSIONS["3.3"].openssl + INSTALL_BUNDLER = VERSIONS["3.3"].bundler + } + tags = ["kss-test:3.3"] +} + +target "ruby-3-4" { + inherits = ["_common"] + args = { + RUBY_MAJOR = "3.4" + RUBY_VERSION = VERSIONS["3.4"].version + RUBY_ARCHIVE = VERSIONS["3.4"].archive + OPENSSL = VERSIONS["3.4"].openssl + INSTALL_BUNDLER = VERSIONS["3.4"].bundler + } + tags = ["kss-test:3.4"] +} + +target "ruby-4-0" { + inherits = ["_common"] + args = { + RUBY_MAJOR = "4.0" + RUBY_VERSION = VERSIONS["4.0"].version + RUBY_ARCHIVE = VERSIONS["4.0"].archive + OPENSSL = VERSIONS["4.0"].openssl + INSTALL_BUNDLER = VERSIONS["4.0"].bundler + } + tags = ["kss-test:4.0"] +} + +target "ruby-head" { + dockerfile = "Dockerfile.head" + context = "." + tags = ["kss-test:head"] +} diff --git a/kss.gemspec b/kss.gemspec index d6fdf88..df276c4 100644 --- a/kss.gemspec +++ b/kss.gemspec @@ -8,7 +8,6 @@ Gem::Specification.new do |s| s.homepage = "http://github.com/kneath/kss" s.email = "kneath@gmail.com" s.authors = [ "Kyle Neath" ] - s.has_rdoc = false s.license = "MIT" s.files = %w( README.md Rakefile LICENSE ) diff --git a/lib/kss/comment_parser.rb b/lib/kss/comment_parser.rb index 09bba5b..8e28b13 100644 --- a/lib/kss/comment_parser.rb +++ b/lib/kss/comment_parser.rb @@ -66,7 +66,9 @@ def self.parse_multi_line(line) def initialize(file_path_or_string_input, options={}) @options = options @options[:preserve_whitespace] = false if @options[:preserve_whitespace].nil? - if File.exists?(file_path_or_string_input) + @file_path = nil + @string_input = nil + if File.exist?(file_path_or_string_input) @file_path = file_path_or_string_input else @string_input = file_path_or_string_input diff --git a/lib/kss/parser.rb b/lib/kss/parser.rb index 25f51c0..ddf3491 100644 --- a/lib/kss/parser.rb +++ b/lib/kss/parser.rb @@ -16,7 +16,7 @@ def initialize(*paths_or_strings) @sections = {} paths_or_strings.each do |path_or_string| - if Dir.exists?(path_or_string) + if Dir.exist?(path_or_string) # argument is a path path = path_or_string Dir["#{path}/**/*.{css,less,sass,scss,erb}"].each do |filename| diff --git a/lib/kss/section.rb b/lib/kss/section.rb index eba0526..5ed83a1 100644 --- a/lib/kss/section.rb +++ b/lib/kss/section.rb @@ -23,6 +23,7 @@ def initialize(comment_text=nil, filename=nil, path=nil) @raw = comment_text @filename = filename @path = path + @section = nil end # Splits up the raw comment text into comment sections that represent diff --git a/test-all-rubies.sh b/test-all-rubies.sh new file mode 100755 index 0000000..8eee57a --- /dev/null +++ b/test-all-rubies.sh @@ -0,0 +1,12 @@ +#!/bin/sh +set -e + +echo "Building all Ruby versions..." +docker buildx bake + +echo "" +echo "Running tests..." +parallel --will-cite --tag --tagstring "Ruby {1}" --line-buffer \ + docker run --rm -e COVERAGE={2} "kss-test:{1}" \ + ::: 1.9 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 3.0 3.1 3.2 3.3 3.4 4.0 head \ + :::+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 diff --git a/test/helper.rb b/test/helper.rb index b1f41d8..b619f3b 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -1,3 +1,11 @@ +if ENV["COVERAGE"] == "1" + require "simplecov" + SimpleCov.start do + enable_coverage :branch + add_filter "/test/" + end +end + require 'minitest/autorun' require 'kss' diff --git a/test/section_test.rb b/test/section_test.rb index 29e4138..ae0e4ee 100644 --- a/test/section_test.rb +++ b/test/section_test.rb @@ -40,8 +40,8 @@ def setup end test "parses word phrases as styleguide references" do - @comment_text.gsub!('2.1.1', 'Buttons - Truly Lime') - section = Kss::Section.new(@comment_text, 'example.css') + text = @comment_text.gsub('2.1.1', 'Buttons - Truly Lime') + @section = Kss::Section.new(text, 'example.css') assert_equal 'Buttons - Truly Lime', @section.section end