Skip to content
Open
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
31 changes: 23 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,11 @@ jobs:
fail-fast: false
matrix:
os: [ ubuntu-latest, macos-latest, windows-latest ]
ruby: [ '2.4', '2.5', '2.6', '2.7', '3.0', '3.1', '3.2', '3.3', head, jruby, truffleruby ]
# CRuby < 2.6 does not support macos-arm64, so test those on amd64 instead
# JRuby 9.4.7.0 does not have native console support on macos-arm64: https://github.com/jruby/jruby/issues/8271
ruby: [ '3.2', '3.3', '3.4', '4.0', head, jruby, truffleruby ]
# JRuby does not have native console support on macos-arm64: https://github.com/jruby/jruby/issues/8271
include:
- { os: macos-13, ruby: '2.4' }
- { os: macos-13, ruby: '2.5' }
- { os: macos-13, ruby: jruby }
exclude:
- { os: macos-latest, ruby: '2.4' }
- { os: macos-latest, ruby: '2.5' }
- { os: macos-latest, ruby: jruby }
- { os: windows-latest, ruby: truffleruby }
# fails to load rspec: RuntimeError: CRITICAL: RUBYGEMS_ACTIVATION_MONITOR.owned?: before false -> after true
Expand All @@ -24,9 +19,29 @@ jobs:
env:
CHILDPROCESS_UNSET: should-be-unset
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- run: bundle exec rake spec

lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: '4.0'
bundler-cache: true
- run: bundle exec rubocop

audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: '4.0'
bundler-cache: true
- run: bundle exec bundler-audit check --update
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ tmtags
## PROJECT::GENERAL
coverage
rdoc
doc
.yardoc
pkg
.rbx
Gemfile.lock
.ruby-version
.bundle

## PROJECT::SPECIFIC
109 changes: 109 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
plugins:
- rubocop-performance
- rubocop-rspec

AllCops:
NewCops: enable
TargetRubyVersion: 3.2
SuggestExtensions: false
Exclude:
- 'pkg/**/*'
- 'vendor/**/*'

# This is a small, stable library with a deliberately plain style;
# these formatting cops fight the existing (consistent) house style
# more than they help, so they're tuned down rather than left default.
Layout/LineLength:
Max: 120

Style/Documentation:
Enabled: false

Style/FrozenStringLiteralComment:
Enabled: true
EnforcedStyle: always

Metrics/AbcSize:
Max: 30

Metrics/MethodLength:
Max: 30

Metrics/ClassLength:
Max: 150

Metrics/CyclomaticComplexity:
Max: 10

Metrics/PerceivedComplexity:
Max: 10

# ChildProcess is the library's single namespace module and legitimately
# holds all of the platform-detection API; splitting it up would hurt more
# than a slightly relaxed line budget.
Metrics/ModuleLength:
Max: 200

Metrics/BlockLength:
Exclude:
- 'spec/**/*'

# Standard Bundler::GemHelper Rakefile boilerplate.
Style/MixinUsage:
Exclude:
- 'Rakefile'

# `set_exit_code` etc. are private helpers, not public accessors -- the
# `set_`/`has_`/`is_` prefixes they use are clearer here than the cops'
# preferred alternatives (e.g. `to_io?` would be actively confusing next
# to the real `Kernel#to_io`).
Naming/AccessorMethodName:
Enabled: false

Naming/PredicatePrefix:
Enabled: false

# The project's gem/module name is "childprocess" (no underscore)
# throughout -- file names already match that convention, not the cop's
# ActiveSupport-style `child_process` inflection of the `ChildProcess`
# constant.
RSpec/SpecFilePathFormat:
Enabled: false

# `before(:all)`/`after(:all)` are used once, deliberately, to save and
# restore process-global RbConfig state around the OS-detection specs --
# not to share database/records state across examples.
RSpec/BeforeAfterAll:
Enabled: false

RSpec/InstanceVariable:
Exclude:
- 'spec/childprocess_spec.rb'

# These specs `eval` the `Hash#inspect`/`Array#inspect` output that a
# child process (spawned by the very same spec, from a tempfile the spec
# itself wrote) reports its ENV/ARGV as -- not attacker-controlled input.
Security/Eval:
Exclude:
- 'spec/childprocess_spec.rb'

# Dev dependencies are declared in the gemspec (not the Gemfile) so that
# `gem build`/`rake` consumers of a checked-out clone get a consistent,
# pinned toolchain without needing a separate Gemfile entry per tool.
Gemspec/DevelopmentDependencies:
Enabled: false

RSpec/ExampleLength:
Max: 35

RSpec/MultipleExpectations:
Max: 10

RSpec/NestedGroups:
Max: 5

RSpec/DescribeClass:
Exclude:
- 'spec/childprocess_spec.rb'
- 'spec/io_spec.rb'
- 'spec/pid_behavior.rb'
1 change: 1 addition & 0 deletions .ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
4.0.6
10 changes: 3 additions & 7 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# frozen_string_literal: true

source 'https://rubygems.org'

# Specify your gem's dependencies in child_process.gemspec
# Specify your gem's dependencies in childprocess.gemspec
gemspec

# Used for local development/testing only
gem 'rake'

# Newer versions of term-ansicolor (used by coveralls) do not work on Ruby 2.4
gem 'term-ansicolor', '< 1.8.0' if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.5')
33 changes: 23 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@ a standalone library.
[![CI](https://github.com/enkessler/childprocess/actions/workflows/ci.yml/badge.svg)](https://github.com/enkessler/childprocess/actions/workflows/ci.yml)
![Gem Version](https://img.shields.io/gem/v/childprocess)
[![Code Climate](https://codeclimate.com/github/enkessler/childprocess.svg)](https://codeclimate.com/github/enkessler/childprocess)
[![Coverage Status](https://coveralls.io/repos/enkessler/childprocess/badge.svg?branch=master)](https://coveralls.io/r/enkessler/childprocess?branch=master)

Test coverage is measured locally with [SimpleCov](https://github.com/simplecov-ruby/simplecov)
(`bundle exec rake spec` prints the summary; the full report is written to `coverage/`) -- the
suite maintains 100% line coverage.

# Requirements

* Ruby 2.4+, JRuby 9+
* Ruby 3.2+, JRuby 9+, TruffleRuby
* Tested against Ruby 3.2, 3.3, 3.4, 4.0 and `head` in CI (see
[.github/workflows/ci.yml](.github/workflows/ci.yml))

# Usage

Expand Down Expand Up @@ -183,11 +188,21 @@ ChildProcess.logger = logger

ChildProcess 5+ uses `Process.spawn` from the Ruby core library for maximum portability.

# Development

```
bundle install
bundle exec rake spec # run the test suite (100% line coverage enforced via SimpleCov)
bundle exec rubocop # lint
bundle exec yard doc # generate API docs into doc/
bundle exec bundler-audit check --update # dependency security audit
```

# Note on Patches/Pull Requests

1. Fork it
2. Create your feature branch (off of the development branch)
`git checkout -b my-new-feature dev`
2. Create your feature branch (off of `master`)
`git checkout -b my-new-feature`
3. Commit your changes
`git commit -am 'Add some feature'`
4. Push to the branch
Expand All @@ -198,14 +213,12 @@ ChildProcess 5+ uses `Process.spawn` from the Ruby core library for maximum port

When publishing a new gem release:

1. Ensure [latest build is green on the `dev` branch](https://travis-ci.org/enkessler/childprocess/branches)
1. Ensure the [latest build is green on `master`](https://github.com/enkessler/childprocess/actions/workflows/ci.yml)
2. Ensure [CHANGELOG](CHANGELOG.md) is updated
3. Ensure [version is bumped](lib/childprocess/version.rb) following [Semantic Versioning](https://semver.org/)
4. Merge the `dev` branch into `master`: `git checkout master && git merge dev`
5. Ensure [latest build is green on the `master` branch](https://travis-ci.org/enkessler/childprocess/branches)
6. Build gem from the green `master` branch: `git checkout master && gem build childprocess.gemspec`
7. Push gem to RubyGems: `gem push childprocess-<VERSION>.gem`
8. Tag commit with version, annotated with release notes: `git tag -a <VERSION>`
4. Build the gem: `gem build childprocess.gemspec`
5. Push gem to RubyGems: `gem push childprocess-<VERSION>.gem`
6. Tag commit with version, annotated with release notes: `git tag -a <VERSION>`

# Copyright

Expand Down
30 changes: 16 additions & 14 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,61 +1,63 @@
# frozen_string_literal: true

require 'rubygems'
require 'rake'
require 'tmpdir'

require 'bundler'
Bundler::GemHelper.install_tasks

include Rake::DSL if defined?(::Rake::DSL)
include Rake::DSL if defined?(Rake::DSL)

require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec) do |spec|
spec.ruby_opts = "-I lib:spec -w"
spec.ruby_opts = '-I lib:spec -w'
spec.pattern = 'spec/**/*_spec.rb'
end

desc 'Run specs for rcov'
RSpec::Core::RakeTask.new(:rcov) do |spec|
spec.ruby_opts = "-I lib:spec"
spec.ruby_opts = '-I lib:spec'
spec.pattern = 'spec/**/*_spec.rb'
spec.rcov = true
spec.rcov_opts = %w[--exclude spec,ruby-debug,/Library/Ruby,.gem --include lib/childprocess]
end

task :default => :spec
task default: :spec

begin
require 'yard'
YARD::Rake::YardocTask.new
rescue LoadError
task :yardoc do
abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
abort 'YARD is not available. In order to run yardoc, you must: sudo gem install yard'
end
end

task :clean do
rm_rf "pkg"
rm_rf "childprocess.jar"
rm_rf 'pkg'
rm_rf 'childprocess.jar'
end

desc 'Create jar to bundle in selenium-webdriver'
task :jar => [:clean, :build] do
tmpdir = Dir.mktmpdir("childprocess-jar")
task jar: %i[clean build] do
tmpdir = Dir.mktmpdir('childprocess-jar')
gem_to_package = Dir['pkg/*.gem'].first
gem_name = File.basename(gem_to_package, ".gem")
p :gem_to_package => gem_to_package, :gem_name => gem_name
gem_name = File.basename(gem_to_package, '.gem')
p gem_to_package: gem_to_package, gem_name: gem_name

sh "gem install -i #{tmpdir} #{gem_to_package} --ignore-dependencies --no-rdoc --no-ri"
sh "jar cf childprocess.jar -C #{tmpdir}/gems/#{gem_name}/lib ."
sh "jar tf childprocess.jar"
sh 'jar tf childprocess.jar'
end

task :env do
$:.unshift File.expand_path("../lib", __FILE__)
$LOAD_PATH.unshift File.expand_path('lib', __dir__)
require 'childprocess'
end

desc 'Calculate size of posix_spawn structs for the current platform'
task :generate => :env do
task generate: :env do
require 'childprocess/tools/generator'
ChildProcess::Tools::Generator.generate
end
45 changes: 29 additions & 16 deletions childprocess.gemspec
Original file line number Diff line number Diff line change
@@ -1,28 +1,41 @@
# -*- encoding: utf-8 -*-
$:.push File.expand_path("../lib", __FILE__)
require "childprocess/version"
# frozen_string_literal: true

lib = File.expand_path('lib', __dir__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'childprocess/version'

Gem::Specification.new do |s|
s.name = "childprocess"
s.name = 'childprocess'
s.version = ChildProcess::VERSION
s.platform = Gem::Platform::RUBY
s.authors = ["Jari Bakken", "Eric Kessler", "Shane da Silva"]
s.email = ["morrow748@gmail.com", "shane@dasilva.io"]
s.homepage = "https://github.com/enkessler/childprocess"
s.summary = %q{A simple and reliable solution for controlling external programs running in the background on any Ruby / OS combination.}
s.description = %q{This gem aims at being a simple and reliable solution for controlling external programs running in the background on any Ruby / OS combination.}
s.authors = ['Jari Bakken', 'Eric Kessler', 'Shane da Silva']
s.email = ['morrow748@gmail.com', 'shane@dasilva.io']
s.homepage = 'https://github.com/enkessler/childprocess'
s.summary = 'A simple and reliable solution for controlling external programs running in the background.'
s.description = 'This gem aims at being a simple and reliable solution for controlling external programs ' \
'running in the background on any Ruby / OS combination.'

s.license = 'MIT'
s.metadata = {
'bug_tracker_uri' => 'https://github.com/enkessler/childprocess/issues',
'changelog_uri' => 'https://github.com/enkessler/childprocess/blob/master/CHANGELOG.md',
'source_code_uri' => 'https://github.com/enkessler/childprocess/',
'rubygems_mfa_required' => 'true'
}

s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- spec/*`.split("\n")
s.require_paths = ["lib"]
s.require_paths = ['lib']

s.required_ruby_version = '>= 2.4.0'
s.required_ruby_version = '>= 3.2'

s.add_dependency "logger", "~> 1.5"
s.add_dependency 'logger', '~> 1.5'

s.add_development_dependency "rspec", "~> 3.0"
s.add_development_dependency "yard", "~> 0.0"
s.add_development_dependency 'coveralls', '< 1.0'
s.add_development_dependency 'bundler-audit', '~> 0.9'
s.add_development_dependency 'rake', '~> 13.0'
s.add_development_dependency 'rspec', '~> 3.13'
s.add_development_dependency 'rubocop', '~> 1.88'
s.add_development_dependency 'rubocop-performance', '~> 1.26'
s.add_development_dependency 'rubocop-rspec', '~> 3.10'
s.add_development_dependency 'simplecov', '~> 0.22'
s.add_development_dependency 'yard', '~> 0.9'
end
Loading