Skip to content
Merged
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
32 changes: 27 additions & 5 deletions .github/actions/test_ruby_gem_uploads/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -174,20 +174,20 @@ runs:
TRUNK_TEST_COLLECTION_ID: ${{ inputs.test-collection-id }}
TRUNK_VARIANT: ""

- name: Run variant quarantine test with variant (should pass - quarantined)
- name: Run variant and pending quarantine tests with variant (should pass - quarantined)
id: run-variant-test-with-variant
if: inputs.alpine != 'true'
shell: bash
working-directory: ${{ github.action_path }}
run: |
bundle exec rspec spec/variant_quarantine_spec.rb --format documentation
bundle exec rspec spec/variant_quarantine_spec.rb spec/pending_spec.rb --format documentation
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "ERROR: Variant quarantine test with variant should have passed (test should be quarantined)"
echo "Note: The variant_quarantine_test must be quarantined with variant 'smoke-test-variant' in the system"
echo "ERROR: Quarantine tests with variant should have passed (tests should be quarantined)"
echo "Note: variant_quarantine_test and pending_quarantine_test must be quarantined with variant 'smoke-test-variant' in the system"
exit 1
else
echo "SUCCESS: Variant quarantine test with variant passed (test was quarantined)"
echo "SUCCESS: Quarantine tests with variant passed (tests were quarantined)"
fi
env:
TRUNK_PUBLIC_API_ADDRESS: ${{ inputs.trunk-public-api-address }}
Expand All @@ -196,6 +196,28 @@ runs:
TRUNK_TEST_COLLECTION_ID: ${{ inputs.test-collection-id }}
TRUNK_VARIANT: smoke-test-variant

- name: Run pending quarantine test without variant (should fail - not quarantined)
id: run-pending-test-no-variant
if: inputs.alpine != 'true'
shell: bash
working-directory: ${{ github.action_path }}
run: |
set +e
bundle exec rspec spec/pending_spec.rb --format documentation
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
echo "ERROR: Pending quarantine test without variant should have failed (fixed-pending is not quarantined)"
exit 1
else
echo "SUCCESS: Pending quarantine test without variant failed as expected (fixed-pending is not quarantined)"
fi
env:
TRUNK_PUBLIC_API_ADDRESS: ${{ inputs.trunk-public-api-address }}
TRUNK_ORG_URL_SLUG: ${{ inputs.trunk-org-slug }}
TRUNK_API_TOKEN: ${{ inputs.trunk-token }}
TRUNK_TEST_COLLECTION_ID: ${{ inputs.test-collection-id }}
TRUNK_VARIANT: ""

- name: Run quarantine lookup failure abort test (should fail fast, skip slow_test)
id: run-quarantine-abort-test
if: inputs.alpine != 'true'
Expand Down
11 changes: 11 additions & 0 deletions .github/actions/test_ruby_gem_uploads/spec/pending_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

# A fixed-pending example (body now passes -> PendingExampleFixedError) reds the
# build unless quarantined: it fails without a variant and passes (quarantined)
# when run with the smoke-test-variant variant.
describe 'pending_quarantine_test' do
it 'should be quarantined when run with variant' do
pending('expected to still fail, but the body now passes')
expect(2 + 2).to eq(4)
end
end
27 changes: 22 additions & 5 deletions rspec-trunk-flaky-tests/lib/trunk_spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,25 @@ class Example
# decide if we want to fail the test or not
# trunk-ignore(rubocop/Naming/AccessorMethodName)
def set_exception(exception)
return set_exception_core(exception) if metadata[:pending]
# Pending stays green, except a fixed pending example is a real failure.
return set_exception_core(exception) if metadata[:pending] && !pending_example_fixed?(exception)
return set_exception_core(exception) if trunk_disabled
return set_exception_core(exception) if metadata[:retry_attempts]&.positive?

handle_quarantine_check_safely(exception)
end

# If the quarantine machinery itself blows up, the failure must stand.
def handle_quarantine_check_safely(exception)
handle_quarantine_check(exception)
rescue StandardError => e
puts "Quarantine check errored (#{e.class}: #{e.message}), treating test as not quarantined".yellow
set_exception_core(exception)
end

def pending_example_fixed?(exception)
defined?(RSpec::Core::Pending::PendingExampleFixedError) &&
exception.is_a?(RSpec::Core::Pending::PendingExampleFixedError)
end

# trunk-ignore(rubocop/Metrics/AbcSize,rubocop/Metrics/MethodLength,rubocop/Metrics/CyclomaticComplexity)
Expand Down Expand Up @@ -401,10 +415,13 @@ def status_and_exception(example)
# the build (the pending expectation was violated), so it is a failure here too.
[Status.new('failure'), example.exception || quarantined_exception]
when :pending
# Not a skip (handled above), so this is a pending example whose body ran and
# failed as expected: the pending expectation ("this should fail") was met, so
# RSpec keeps the build green -- report it as a success.
[Status.new('success'), nil]
# A quarantined fixed-pending is left :pending but pending_fixed? -- still a
# failure. Otherwise the pending "should fail" expectation was met -> success.
if result.pending_fixed?
[Status.new('failure'), quarantined_exception || example.exception]
else
[Status.new('success'), nil]
end
else
[Status.new(result.status.to_s), example.exception || quarantined_exception]
end
Expand Down
Loading