Files
gitlab-foss/tooling/ci/changed_files.rb
2025-05-22 15:12:03 +00:00

84 lines
2.2 KiB
Ruby
Executable File

#!/usr/bin/env ruby
# frozen_string_literal: true
module CI
class ChangedFiles
FRONTEND_EXTENSIONS = "js|cjs|mjs|vue|graphql"
FRONTEND_FILES_FILTER = /\.(#{FRONTEND_EXTENSIONS})$/
ESLINT_TODO_FILES = %r{\.eslint_todo/[a-z-]+\.mjs$}
ESLINT_TODO_REMOVED_FILE_PATHS = %r{- +'([a-z/_-]+\.(#{FRONTEND_EXTENSIONS}))'}
def initialize(env: ENV, args: ARGV)
@env = env
@args = args
end
private attr_reader :env, :args
# See: https://gitlab.com/groups/gitlab-org/-/epics/16845#note_2370956250
# for why we use `HEAD~` to compare
def get_changed_files_in_merged_results_pipeline
`git diff --name-only --diff-filter=d HEAD~..HEAD`.split("\n")
end
def get_files_removed_from_todo_files(changed_files)
changed_todo_files = changed_files.filter { |file| file =~ ESLINT_TODO_FILES }
return [] if changed_todo_files.empty?
diff = `git diff HEAD~..HEAD -- #{changed_todo_files.join(' ')}`
diff.scan(ESLINT_TODO_REMOVED_FILE_PATHS).map(&:first)
end
def filter_and_get_changed_files_in_mr(filter_pattern: //)
get_changed_files_in_merged_results_pipeline.grep(filter_pattern)
end
def run_eslint_for_changed_files
puts 'Running ESLint for changed files...'
files = filter_and_get_changed_files_in_mr(filter_pattern: FRONTEND_FILES_FILTER)
files += get_files_removed_from_todo_files(files)
if files.empty?
puts 'No files were changed. Skipping...'
return 0
end
command = [
"yarn", "run", "lint:eslint",
"--no-warn-ignored",
"--no-error-on-unmatched-pattern",
"--format", "gitlab",
*files
]
system(*command)
last_command_status.exitstatus
end
def last_command_status
$?
end
def process_command_and_determine_exit_status
return 0 if args.empty?
command = args.first
case command
when "eslint"
run_eslint_for_changed_files
else
warn "Unknown command: #{command}"
1
end
end
end
end
if __FILE__ == $PROGRAM_NAME
runner = CI::ChangedFiles.new
exit runner.process_command_and_determine_exit_status
end