From e490f5fb2266016f5557f9f7de6d1eb8156011b2 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Wed, 1 Jul 2026 12:39:51 +1200 Subject: [PATCH 1/2] Enable verbose output from CI debug environment variables. Automatically enable verbose output when a CI provider is running in debug mode, e.g. GitHub Actions re-run with "Enable debug logging" (RUNNER_DEBUG=1). Also supports GitLab CI, Buildkite, Azure Pipelines, and an explicit SUS_VERBOSE toggle. Assisted-By: devx/0e90505d-10c5-4dfa-be04-c43abc87164a --- lib/sus/config.rb | 30 +++++++++++++++++++++++++++++- test/sus/config.rb | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/lib/sus/config.rb b/lib/sus/config.rb index 715e043..a40ae10 100644 --- a/lib/sus/config.rb +++ b/lib/sus/config.rb @@ -38,12 +38,40 @@ def self.load(root: Dir.pwd, arguments: ARGV) end options = { - verbose: !!arguments.delete("--verbose") + verbose: !!arguments.delete("--verbose") || self.verbose_from_environment? } return derived.new(root, arguments, **options) end + # Maps CI environment variables to the values they take when the CI provider is running in debug/verbose mode. When any of these match, we enable verbose output automatically. + # + # - `RUNNER_DEBUG` is set by GitHub Actions when a workflow is re-run with "Enable debug logging". + # - `CI_DEBUG_TRACE` is set by GitLab CI when debug logging (tracing) is enabled. + # - `BUILDKITE_AGENT_DEBUG` is set by Buildkite when agent debug is enabled. + # - `SYSTEM_DEBUG` is set by Azure Pipelines when the `system.debug` variable is enabled. + # - `SUS_VERBOSE` can be set explicitly to enable verbose output regardless of the CI provider. + DEBUG_ENVIRONMENT = { + "SUS_VERBOSE" => "true", + "RUNNER_DEBUG" => "1", + "CI_DEBUG_TRACE" => "true", + "BUILDKITE_AGENT_DEBUG" => "true", + "SYSTEM_DEBUG" => "true", + } + + # Whether verbose output should be enabled based on the environment. + # + # Detects CI environments that request debug logging, e.g. GitHub Actions + # sets `RUNNER_DEBUG=1` when a workflow is re-run with "Enable debug logging". + # + # @parameter env [Hash] The environment to inspect. + # @returns [Boolean] Whether verbose output should be enabled. + def self.verbose_from_environment?(env = ENV) + DEBUG_ENVIRONMENT.any? do |key, value| + env[key] == value + end + end + # Initialize a new Config instance. # @parameter root [String] The root directory for the project. # @parameter paths [Array] Optional paths to specific test files. diff --git a/test/sus/config.rb b/test/sus/config.rb index 851c571..2c689bf 100644 --- a/test/sus/config.rb +++ b/test/sus/config.rb @@ -22,6 +22,48 @@ def print(output) expect(config).not.to be(:nil?) end + with ".verbose_from_environment?" do + it "is enabled by GitHub Actions debug logging" do + expect(subject.verbose_from_environment?({"RUNNER_DEBUG" => "1"})).to be == true + end + + it "is enabled by GitLab CI debug tracing" do + expect(subject.verbose_from_environment?({"CI_DEBUG_TRACE" => "true"})).to be == true + end + + it "is enabled by Buildkite agent debug" do + expect(subject.verbose_from_environment?({"BUILDKITE_AGENT_DEBUG" => "true"})).to be == true + end + + it "is enabled by Azure Pipelines system debug" do + expect(subject.verbose_from_environment?({"SYSTEM_DEBUG" => "true"})).to be == true + end + + it "is enabled by the SUS_VERBOSE environment variable" do + expect(subject.verbose_from_environment?({"SUS_VERBOSE" => "true"})).to be == true + end + + it "is disabled by default" do + expect(subject.verbose_from_environment?({})).to be == false + end + + it "ignores unrelated values" do + expect(subject.verbose_from_environment?({"RUNNER_DEBUG" => "0"})).to be == false + end + end + + with "#verbose?" do + it "is enabled by the --verbose argument" do + config = subject.load(root: root, arguments: ["--verbose"]) + expect(config).to be(:verbose?) + end + + it "is disabled by default" do + config = subject.load(root: root, arguments: []) + expect(config).not.to be(:verbose?) + end + end + with "summary output" do let(:io) {StringIO.new} let(:output) {Sus::Output::Text.new(io)} From c9ecc12502d42ef45d1789ebca566127d254497d Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Wed, 1 Jul 2026 13:26:44 +1200 Subject: [PATCH 2/2] Isolate verbose? tests from the real environment. Add an env: parameter to Config.load so tests can supply an isolated environment, preventing failures when sus itself is run in CI debug mode. Assisted-By: devx/0e90505d-10c5-4dfa-be04-c43abc87164a --- lib/sus/config.rb | 5 +++-- test/sus/config.rb | 9 +++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/sus/config.rb b/lib/sus/config.rb index a40ae10..948b7ba 100644 --- a/lib/sus/config.rb +++ b/lib/sus/config.rb @@ -27,8 +27,9 @@ def self.path(root) # Load configuration from the given root directory. # @parameter root [String] The root directory to load configuration from. # @parameter arguments [Array] Command line arguments to parse. + # @parameter env [Hash] The environment to inspect for debug/verbose settings. # @returns [Config] A new Config instance. - def self.load(root: Dir.pwd, arguments: ARGV) + def self.load(root: Dir.pwd, arguments: ARGV, env: ENV) derived = Class.new(self) if path = self.path(root) @@ -38,7 +39,7 @@ def self.load(root: Dir.pwd, arguments: ARGV) end options = { - verbose: !!arguments.delete("--verbose") || self.verbose_from_environment? + verbose: !!arguments.delete("--verbose") || self.verbose_from_environment?(env) } return derived.new(root, arguments, **options) diff --git a/test/sus/config.rb b/test/sus/config.rb index 2c689bf..9ba6ced 100644 --- a/test/sus/config.rb +++ b/test/sus/config.rb @@ -54,12 +54,17 @@ def print(output) with "#verbose?" do it "is enabled by the --verbose argument" do - config = subject.load(root: root, arguments: ["--verbose"]) + config = subject.load(root: root, arguments: ["--verbose"], env: {}) + expect(config).to be(:verbose?) + end + + it "is enabled by the environment" do + config = subject.load(root: root, arguments: [], env: {"SUS_VERBOSE" => "true"}) expect(config).to be(:verbose?) end it "is disabled by default" do - config = subject.load(root: root, arguments: []) + config = subject.load(root: root, arguments: [], env: {}) expect(config).not.to be(:verbose?) end end