From 0f5721adc8f1d51ec86c34b7b434cc7cee5e67f3 Mon Sep 17 00:00:00 2001 From: Niklas van Schrick Date: Mon, 29 Dec 2025 02:26:53 +0100 Subject: [PATCH] Setup pyxis for chatops usage --- .gitlab-ci.yml | 4 +++ .gitlab/ci/chatops.gitlab-ci.yml | 14 ++++++++++ bin/chatops | 44 ++++++++++++++++++++++++++++++++ bin/pyxis | 5 +++- lib/pyxis.rb | 2 ++ lib/pyxis/commands/components.rb | 16 +++++++----- lib/pyxis/logger.rb | 2 +- lib/pyxis/permission_helper.rb | 17 ++++++++++++ 8 files changed, 96 insertions(+), 8 deletions(-) create mode 100644 .gitlab/ci/chatops.gitlab-ci.yml create mode 100755 bin/chatops create mode 100644 lib/pyxis/permission_helper.rb diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0dffa1e..0e2a50e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,8 @@ +include: + - local: .gitlab/ci/chatops.gitlab-ci.yml + stages: + - chatops - components default: diff --git a/.gitlab/ci/chatops.gitlab-ci.yml b/.gitlab/ci/chatops.gitlab-ci.yml new file mode 100644 index 0000000..57bb726 --- /dev/null +++ b/.gitlab/ci/chatops.gitlab-ci.yml @@ -0,0 +1,14 @@ +.chatops: + image: ruby:3.2.2 + stage: chatops + timeout: 10 min + script: + - bundle install + - bin/chatops $CI_JOB_NAME $CHAT_INPUT + variables: + THOR_SHELL: 'Basic' + rules: + - if: $CI_PIPELINE_SOURCE == "chat" + +components: + extends: .chatops diff --git a/bin/chatops b/bin/chatops new file mode 100755 index 0000000..97f8c46 --- /dev/null +++ b/bin/chatops @@ -0,0 +1,44 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'stringio' +require_relative '../lib/pyxis' + +original_stdout = $stdout +stringio = StringIO.new +$stdout = stringio + +start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_second) +config = { debug: true } # we want the error to be raised + +begin + result = Pyxis::Cli.start(ARGV, config) + successful = true +rescue Thor::Error, Pyxis::Error => e + result = "#{e.class}\n#{e.message}" + successful = false +end + +end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_second) + +SemanticLogger.flush + +$stdout = original_stdout + +SECTION = 'chat_reply' + +puts "section_start:#{Time.now.to_i}:#{SECTION}\r\033[0K" + +puts "$ pyxis #{ARGV.join(' ')}" +puts '```' +puts + +puts result || stringio.string + +puts +puts '```' +puts "#{successful ? 'Finished' : 'Failed'} in #{(end_time - start_time).round(2)} seconds" + +puts "section_end:#{Time.now.to_i}:#{SECTION}\r\033[0K" + +exit(successful) diff --git a/bin/pyxis b/bin/pyxis index f607a1d..fc55d58 100755 --- a/bin/pyxis +++ b/bin/pyxis @@ -3,4 +3,7 @@ require_relative '../lib/pyxis' -Pyxis::Cli.start(ARGV) +result = Pyxis::Cli.start(ARGV) +SemanticLogger.flush + +puts result diff --git a/lib/pyxis.rb b/lib/pyxis.rb index 850ddcd..df96a15 100644 --- a/lib/pyxis.rb +++ b/lib/pyxis.rb @@ -4,9 +4,11 @@ Bundler.require module Pyxis + Error = Class.new(StandardError) end loader = Zeitwerk::Loader.for_gem loader.setup loader.eager_load_namespace(Pyxis::Logger) loader.eager_load_namespace(Pyxis::DryRunEnforcer) +loader.eager_load_namespace(Pyxis::Project::Base) diff --git a/lib/pyxis/commands/components.rb b/lib/pyxis/commands/components.rb index a5fb286..ad5169e 100644 --- a/lib/pyxis/commands/components.rb +++ b/lib/pyxis/commands/components.rb @@ -3,29 +3,33 @@ module Pyxis module Commands class Components < Thor + include PermissionHelper + desc 'info [BUILD_ID]', 'Get the component versions for a reticulum build' def info(build_id) component_versions = ManagedVersioning::ComponentInfo.new(build_id).execute - SemanticLogger.flush - - puts 'Versions of each component' + result = 'Versions of each component' component_versions.each do |component, version| - puts "#{component}: #{version}" + result += "\n#{component}: #{version}" end + result end desc 'update [COMPONENT]', 'Update a component in reticulum' def update(component) + assert_executed_by_schedule! + updater(component).execute end desc 'list', 'List all available components' def list - puts 'Available components:' + result = 'Available components:' Pyxis::Project.components.each do |project| - puts "- #{project.downcase}" + result += "\n- #{project.downcase}" end + result end desc 'get_version COMPONENT', 'Get the current version of a component in reticulum' diff --git a/lib/pyxis/logger.rb b/lib/pyxis/logger.rb index d798c8c..4885bd9 100644 --- a/lib/pyxis/logger.rb +++ b/lib/pyxis/logger.rb @@ -45,7 +45,7 @@ def call(env) SemanticLogger.application = 'pyxis' SemanticLogger.default_level = ENV.fetch('LOG_LEVEL', 'debug').to_sym -SemanticLogger.add_appender(io: $stdout, level: SemanticLogger.default_level, +SemanticLogger.add_appender(io: $stderr, level: SemanticLogger.default_level, formatter: Pyxis::Logger::NoProcessColorFormatter.new) SemanticLogger.push_tags('dry-run') if Pyxis::GlobalStatus.dry_run? diff --git a/lib/pyxis/permission_helper.rb b/lib/pyxis/permission_helper.rb new file mode 100644 index 0000000..ca77da6 --- /dev/null +++ b/lib/pyxis/permission_helper.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module Pyxis + PermissionError = Class.new(Pyxis::Error) + module PermissionHelper + def checks_active? + ENV['BYPASS_PERMISSION_CHECKS'].nil? + end + + def assert_executed_by_schedule! + return unless checks_active? + return if ENV['CI_PIPELINE_SOURCE'] == 'schedule' + + raise PermissionError, 'This operation can only be run by a pipeline schedule' + end + end +end