Skip to content
Closed
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
27 changes: 27 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Dependabot: dependency updates + security alerts
# https://docs.github.com/en/code-security/dependabot
version: 2
updates:
# Ruby / Bundler
- package-ecosystem: "bundler"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
open-pull-requests-limit: 5
labels:
- "dependencies"
commit-message:
prefix: "chore(deps)"

# GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
labels:
- "dependencies"
- "github-actions"
commit-message:
prefix: "chore(ci)"
35 changes: 35 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# CodeQL: security and code quality analysis (GitHub Advanced Security)
# https://docs.github.com/en/code-security/code-scanning
name: CodeQL

on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
schedule:
# Weekly run (optional)
- cron: '0 0 * * 1'

jobs:
analyze:
name: Analyze (Ruby)
runs-on: ubuntu-latest
permissions:
security-events: write
actions: read
contents: read
steps:
- uses: actions/checkout@v4

- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ruby
# Optional: use security-extended for more security queries
queries: security-extended

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:ruby"
20 changes: 20 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Lint: RuboCop and style checks
name: Lint

on:
pull_request:
push:
branches: [main, master]

jobs:
rubocop:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.3"
bundler-cache: true
- name: Run RuboCop
run: bundle exec rubocop
35 changes: 35 additions & 0 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Security: dependency review (PRs) + bundler-audit for known gem vulnerabilities
name: Security

on:
pull_request:
branches: [main, master]
push:
branches: [main, master]

jobs:
dependency-review:
name: Dependency review
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v4
- name: Dependency Review
uses: actions/dependency-review-action@v4
with:
fail-on-severity: high

bundler-audit:
name: Bundler audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.3"
bundler-cache: true
- name: Install bundler-audit
run: gem install bundler-audit
- name: Update vulnerability DB and run audit
run: bundler-audit check --update
69 changes: 58 additions & 11 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
Style/StringLiterals:
Enabled: false
AllCops:
NewCops: enable
Exclude:
- 'rubyipmi.gemspec'
SignalException:
Style/SignalException:
EnforcedStyle: only_raise
Documentation:
Style/Documentation:
Enabled: false
ClassAndModuleChildren:
Style/ClassAndModuleChildren:
Enabled: false
HashSyntax:
Style/HashSyntax:
EnforcedStyle: hash_rockets
ClassCheck:
Style/ClassCheck:
EnforcedStyle: kind_of?
SpaceInsideHashLiteralBraces:
Layout/SpaceInsideHashLiteralBraces:
EnforcedStyle: no_space
Style/WordArray:
Enabled: false
Expand All @@ -24,14 +25,22 @@ Metrics/AbcSize:
Max: 60
Metrics/CyclomaticComplexity:
Max: 19
Metrics/LineLength:
Exclude:
- 'lib/rubyipmi.rb'
Layout/LineLength:
Max: 149
Metrics/MethodLength:
Max: 44
Exclude:
- 'lib/rubyipmi.rb'
Metrics/ModuleLength:
Max: 128
Exclude:
- 'lib/rubyipmi.rb'
Metrics/PerceivedComplexity:
Max: 22
Exclude:
- 'lib/rubyipmi.rb'
Style/SpecialGlobalVars:
Exclude:
- 'lib/rubyipmi.rb'
Expand All @@ -44,23 +53,61 @@ Style/RescueModifier:
Style/RegexpLiteral:
Exclude:
- 'spec/spec_helper.rb'
Style/PredicateName:
Naming/PredicatePrefix:
Exclude:
- 'lib/rubyipmi.rb'
Lint/RescueException:
Exclude:
- 'spec/integration/rubyipmi_spec.rb'
Style/AccessorMethodName:
Naming/AccessorMethodName:
Exclude:
- 'lib/rubyipmi/freeipmi/connection.rb'
- 'lib/rubyipmi/ipmitool/connection.rb'

# Fixed by deprecation
Style/MethodName:
Naming/MethodName:
Exclude:
- 'lib/rubyipmi/commands/mixins/power_mixin.rb'

# Don't understand
Style/FileName:
Naming/FileName:
Exclude:
- 'spec/unit/freeipmi/bmc-info_spec.rb'

# Spec files often have long describe blocks and intentional patterns
Metrics/BlockLength:
Exclude:
- 'spec/**/*_spec.rb'
- 'spec/**/*.rb'
Style/OptionalBooleanParameter:
Enabled: false
Lint/DuplicateMethods:
Exclude:
- 'lib/rubyipmi/freeipmi/commands/bmc.rb'
- 'lib/rubyipmi/freeipmi/commands/fru.rb'
- 'lib/rubyipmi/freeipmi/commands/lan.rb'
- 'lib/rubyipmi/ipmitool/commands/fru.rb'
- 'lib/rubyipmi/ipmitool/commands/lan.rb'
Style/MissingRespondToMissing:
Exclude:
- 'lib/rubyipmi/commands/mixins/sensors_mixin.rb'
- 'lib/rubyipmi/freeipmi/commands/fru.rb'
- 'lib/rubyipmi/ipmitool/commands/fru.rb'
Lint/MissingSuper:
Exclude:
- 'lib/rubyipmi.rb'
- 'lib/rubyipmi/freeipmi/commands/fru.rb'
- 'lib/rubyipmi/freeipmi/commands/sensors.rb'
- 'lib/rubyipmi/ipmitool/commands/fru.rb'
- 'lib/rubyipmi/ipmitool/commands/sensors.rb'
Lint/EmptyBlock:
Exclude:
- 'spec/**/*_spec.rb'
Lint/EmptyFile:
Exclude:
- 'spec/unit/freeipmi/lan_spec.rb'
Lint/Void:
Exclude:
- 'lib/rubyipmi/ipmitool/commands/lan.rb'
Naming/PredicateMethod:
Enabled: false
8 changes: 5 additions & 3 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
source "http://rubygems.org"
# frozen_string_literal: true

source "https://rubygems.org"

gemspec

group :development do
gem 'coveralls_reborn', require: false
gem 'coveralls_reborn', :require => false
gem 'pry'
gem 'pry-rescue'
gem "rubocop", :require => false
gem "reline"
gem "rubocop", :require => false
end
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,18 @@ vagrant ssh -c "/rubyipmi/rake integration ipmiuser=... ipmipass=... ipmihost=..

**CI:** The repo uses GitHub Actions; see `.github/workflows/test.yml`. Typical flow: checkout → Ruby 3.x → `bundle install` → `bundle exec rake unit` → `gem build`.

### CI, security, and automation

| Workflow | Purpose |
|----------|---------|
| [test.yml](.github/workflows/test.yml) | Unit tests and gem build (Ruby 3.0–3.4) |
| [lint.yml](.github/workflows/lint.yml) | RuboCop style and lint checks |
| [codeql.yml](.github/workflows/codeql.yml) | CodeQL security and code-quality analysis |
| [security.yml](.github/workflows/security.yml) | Dependency review (PRs) and `bundler-audit` for gem vulnerabilities |

- **Dependabot** (`.github/dependabot.yml`): weekly dependency and GitHub Actions updates; security alerts appear in the **Security** tab.
- **GitHub Copilot Code Review:** For automatic AI-assisted reviews on pull requests, enable **Rules → Rulesets** in the repo **Settings**, add a rule, and choose **Require a review from GitHub Copilot**. You can enable “Run on each push” and “Run on drafts” there. (Requires a Copilot-enabled account.)

---

### Extending the library
Expand Down
30 changes: 15 additions & 15 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
# encoding: utf-8
# frozen_string_literal: true

require 'bundler/gem_tasks'

@base_dir = File.dirname(__FILE__)

begin
Bundler.setup(:default, :development)
rescue Bundler::BundlerError => e
$stderr.puts e.message
$stderr.puts "Run `bundle install` to install missing gems"
warn e.message
warn "Run `bundle install` to install missing gems"
exit e.status_code
end
require 'rake'
Expand All @@ -32,7 +33,7 @@ RSpec::Core::RakeTask.new :integration do |spec|
ENV['ipmiuser'] = 'admin'
ENV['ipmipass'] = 'password'
ENV['ipmihost'] = '10.0.1.16'
providers ||= Array(ENV['ipmiprovider']) || ['freeipmi', 'ipmitool']
providers ||= Array(ENV.fetch('ipmiprovider', nil)) || ['freeipmi', 'ipmitool']

providers.each do |provider|
ENV['ipmiprovider'] = provider
Expand All @@ -59,9 +60,8 @@ task :send_diag, :user, :pass, :host do |_t, args|
require 'json'
require "highline/import"

if args.count < 3
raise "You must provide arguments: rake send_diag[user, pass, host]"
end
raise "You must provide arguments: rake send_diag[user, pass, host]" if args.count < 3

data = Rubyipmi.get_diag(args[:user], args[:pass], args[:host])
emailto = 'corey@logicminds.biz'
subject = "Rubyipmi diagnostics data"
Expand All @@ -78,14 +78,14 @@ def send_email(to, data, opts = {})
opts[:body] ||= data
opts[:to] ||= to
opts[:port] ||= 587
msg = <<END_OF_MESSAGE
From: #{opts[:from_alias]} <#{opts[:from]}>
To: <#{to}>
Subject: #{opts[:subject]}
Date: #{Time.now.rfc2822}

#{opts[:body]}
END_OF_MESSAGE
msg = <<~END_OF_MESSAGE
From: #{opts[:from_alias]} <#{opts[:from]}>
To: <#{to}>
Subject: #{opts[:subject]}
Date: #{Time.now.rfc2822}

#{opts[:body]}
END_OF_MESSAGE

smtp = Net::SMTP.new(opts[:server], opts[:port])
smtp.enable_starttls
Expand Down
Loading