diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6c18ae1..e679c68 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: strategy: matrix: ruby: - - '3.0' + - '3.2.3' steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - name: Set up Ruby diff --git a/.rubocop.yml b/.rubocop.yml index 0b6be3d..0d5a52b 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,5 +1,5 @@ AllCops: - TargetRubyVersion: 3.0 + TargetRubyVersion: 3.2.3 Style/StringLiterals: Enabled: true diff --git a/claws-scan.gemspec b/claws-scan.gemspec index d880e15..e686395 100644 --- a/claws-scan.gemspec +++ b/claws-scan.gemspec @@ -11,7 +11,7 @@ Gem::Specification.new do |spec| spec.summary = "Analyzes your Github Actions" spec.description = "Analyzes your Github Actions" spec.homepage = "https://github.com/Betterment/claws" - spec.required_ruby_version = ">= 3.0" + spec.required_ruby_version = ">= 3.2" spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = "https://github.com/Betterment/claws" diff --git a/lib/claws/application.rb b/lib/claws/application.rb index 5c184c4..cceaf05 100644 --- a/lib/claws/application.rb +++ b/lib/claws/application.rb @@ -43,10 +43,10 @@ def get_workflow_violations(filename, workflow) @detections.each do |detection| detection.on_workflow.each do |rule| violation = run_detection( - filename: filename, - detection: detection, - rule: rule, - workflow: workflow + filename:, + detection:, + rule:, + workflow: ) violations << violation if violation @@ -58,7 +58,7 @@ def get_workflow_violations(filename, workflow) expression: rule[:expression], values: { data: detection.data, - workflow: workflow + workflow: } ) end @@ -72,11 +72,11 @@ def get_job_violations(filename, workflow, job) @detections.each do |detection| detection.on_job.each do |rule| violation = run_detection( - filename: filename, - detection: detection, - rule: rule, - workflow: workflow, - job: job + filename:, + detection:, + rule:, + workflow:, + job: ) violations << violation if violation @@ -88,8 +88,8 @@ def get_job_violations(filename, workflow, job) expression: rule[:expression], values: { data: detection.data, - workflow: workflow, - job: job + workflow:, + job: } ) end @@ -104,12 +104,12 @@ def get_step_violations(filename, workflow, job, step) @detections.each do |detection| detection.on_step.each do |rule| violation = run_detection( - filename: filename, - detection: detection, - rule: rule, - workflow: workflow, - job: job, - step: step + filename:, + detection:, + rule:, + workflow:, + job:, + step: ) violations << violation if violation @@ -121,9 +121,9 @@ def get_step_violations(filename, workflow, job, step) expression: rule[:expression], values: { data: detection.data, - workflow: workflow, - job: job, - step: step + workflow:, + job:, + step: } ) end @@ -137,19 +137,19 @@ def get_step_violations(filename, workflow, job, step) def run_detection(filename:, detection:, rule:, workflow:, job: nil, step: nil) # rubocop:disable Metrics/ParameterLists violation = if rule.is_a? Symbol get_dynamic_violation( - detection: detection, + detection:, method: rule, - workflow: workflow, - job: job, - step: step + workflow:, + job:, + step: ) else get_static_violations( - detection: detection, - rule: rule, - workflow: workflow, - job: job, - step: step + detection:, + rule:, + workflow:, + job:, + step: ) end @@ -164,18 +164,18 @@ def run_detection(filename:, detection:, rule:, workflow:, job: nil, step: nil) def get_dynamic_violation(detection:, method:, workflow:, job:, step:) detection.send( method, - workflow: workflow, - job: job, - step: step + workflow:, + job:, + step: ) end def get_static_violations(rule:, detection:, workflow:, job:, step:) result = rule[:expression].eval_with(values: { data: detection.data, - workflow: workflow, - job: job, - step: step + workflow:, + job:, + step: }) return unless result diff --git a/lib/claws/base_rule.rb b/lib/claws/base_rule.rb index 13eda2a..02763da 100644 --- a/lib/claws/base_rule.rb +++ b/lib/claws/base_rule.rb @@ -45,23 +45,23 @@ def self.description(value) end def self.on_workflow(value, highlight: nil, debug: false) - (@on_workflow ||= []) << extract_value(value, highlight: highlight, debug: debug) + (@on_workflow ||= []) << extract_value(value, highlight:, debug:) end def self.on_job(value, highlight: nil, debug: false) highlight = highlight.to_s unless highlight.nil? - (@on_job ||= []) << extract_value(value, highlight: highlight, debug: debug) + (@on_job ||= []) << extract_value(value, highlight:, debug:) end def self.on_step(value, highlight: nil, debug: false) highlight = highlight.to_s unless highlight.nil? - (@on_step ||= []) << extract_value(value, highlight: highlight, debug: debug) + (@on_step ||= []) << extract_value(value, highlight:, debug:) end def self.extract_value(value, highlight: nil, debug: false) case value when String - { expression: parse_rule(value), highlight: highlight, debug: debug } + { expression: parse_rule(value), highlight:, debug: } when Symbol value else diff --git a/lib/claws/cli/yaml_with_lines.rb b/lib/claws/cli/yaml_with_lines.rb index 9c8c4c8..6e3c6c8 100644 --- a/lib/claws/cli/yaml_with_lines.rb +++ b/lib/claws/cli/yaml_with_lines.rb @@ -18,7 +18,9 @@ module Visitors class ToRuby def accept(target) s = super(target) - if target.respond_to?(:line) and ![TrueClass, FalseClass, NilClass, Integer].include? s.class + + # types that we cannot monkey patch into holding line information + if target.respond_to?(:line) and ![TrueClass, FalseClass, NilClass, Integer, Float].include? s.class s.instance_eval do extend(Locatable) end @@ -49,7 +51,9 @@ def revive_hash(hash, o, _tagged: false) # rubocop:disable Metrics/AbcSize, Metr key.line = 0 if key.respond_to? :line and key.line.nil? key.line += 1 if key.respond_to? :line key.freeze - if [TrueClass, FalseClass, NilClass, Integer].include? key.class + + # types that we cannot monkey patch into holding line information + if [TrueClass, FalseClass, NilClass, Integer, Float].include? key.class val.line = 0 if val.respond_to? :line and val.line.nil? val.line += 1 if val.respond_to? :line end diff --git a/lib/claws/workflow.rb b/lib/claws/workflow.rb index 6967ed4..dba31d8 100644 --- a/lib/claws/workflow.rb +++ b/lib/claws/workflow.rb @@ -173,7 +173,7 @@ def extract_action_data(action) name, version = action.split("@", 2) author = name.split("/", 2)[0] local = author == "." - { type: "action", name: name, author: author, version: version, local: local } + { type: "action", name:, author:, version:, local: } end def extract_container_info_from_job(job) @@ -195,8 +195,8 @@ def extract_container_info_from_action(action) { type: "container", - image: image, - version: version, + image:, + version:, full: "#{image}:#{version}" } end diff --git a/spec/claws/workflow_spec.rb b/spec/claws/workflow_spec.rb index 961ac07..047e4d5 100644 --- a/spec/claws/workflow_spec.rb +++ b/spec/claws/workflow_spec.rb @@ -49,4 +49,33 @@ expect(workflow.meta["triggers"]).to eq(["pull_request"]) end end + + context "line information" do + it "can find the line number of various types" do + workflow = described_class.load(<<~YAML) + on: + pull_request + + jobs: + deploy: + steps: + - id: merge this pull request + name: automerge + uses: "pascalgn/automerge-action@v0.15.5" + with: + type_string: "string" + type_bool: true + type_integer: 1 + type_nil: null + type_float: 1.2 + YAML + + values = { workflow:, job: workflow.jobs["deploy"], step: workflow.jobs["deploy"]["steps"][0] } + expect(BaseRule.parse_rule('$step.with.type_string == "string"').eval_with(values:)).to eq true + expect(BaseRule.parse_rule("$step.with.type_bool == true").eval_with(values:)).to eq true + expect(BaseRule.parse_rule("$step.with.type_integer == 1").eval_with(values:)).to eq true + expect(BaseRule.parse_rule("$step.with.type_nil == nil").eval_with(values:)).to eq true + expect(BaseRule.parse_rule("$step.with.type_float == 1.2").eval_with(values:)).to eq true + end + end end