Skip to content

SONARJAVA-6421 Implement S9352: Bean autowiring ambiguity should be resolved using "@Qualifier" or "@Primary" - #6044

Draft
NoemieBenard wants to merge 15 commits into
epic-SONARJAVA-6237from
nb/sonarjava-6421-ambiguous-dependency-rule
Draft

SONARJAVA-6421 Implement S9352: Bean autowiring ambiguity should be resolved using "@Qualifier" or "@Primary"#6044
NoemieBenard wants to merge 15 commits into
epic-SONARJAVA-6237from
nb/sonarjava-6421-ambiguous-dependency-rule

Conversation

@NoemieBenard

@NoemieBenard NoemieBenard commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Summary by Gitar

  • New Spring Rule (S9352):
    • Implemented AmbiguousDependencyCheck to detect Spring bean autowiring ambiguity and support @Fallback configuration

This will update automatically on new commits.

@hashicorp-vault-sonar-prod

hashicorp-vault-sonar-prod Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

SONARJAVA-6421

Comment on lines +75 to +89
private static boolean isResolved(Set<String> candidates, Set<String> injectionPointNames, BeanDefinitionRegistry registry) {
// injectionPointNames merges every injection point of this type declared on the bean: it is only resolved
// if EVERY one of them names a candidate (by bean name or by a @Qualifier declared on that candidate bean
// itself), otherwise at least one injection point remains ambiguous.
return candidates.size() <= 1
|| injectionPointNames.stream().allMatch(name -> matchesCandidate(name, candidates, registry))
|| candidates.stream().anyMatch(candidate -> isPrimary(registry, candidate));
}

private static boolean matchesCandidate(String injectionPointName, Set<String> candidates, BeanDefinitionRegistry registry) {
return candidates.contains(injectionPointName)
|| candidates.stream().anyMatch(candidate -> injectionPointName.equals(qualifierOf(registry, candidate)));
}

@Nullable

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Bug: Field name matched against a bean's own @qualifier hides ambiguity

dependencyKey collapses an injection point's @qualifier value and its field/parameter name into the same string, so matchesCandidate cannot tell them apart and now accepts a plain field name as a match against a candidate bean's own declared @qualifier. Trigger: @Component @Qualifier("mainService") class A implements Svc, @Component class B implements Svc, and a consumer with @Autowired private Svc mainService; (no @qualifier at the injection point). Spring's by-name fallback (DefaultListableBeanFactory.determineAutowireCandidate -> matchesBeanName) only compares bean names and aliases, never a bean's @qualifier value, so Spring fails with NoUniqueBeanDefinitionException while the rule now stays silent (false negative). Fix by marking qualifier-derived names in the dependency model so the qualifier-vs-qualifier comparison is only applied to injection points that actually declare @qualifier.

Distinguish qualifier-derived injection point names from field/parameter names (serialization/deserialization keeps working since the marker is inside the Base64-encoded name).:

// BeanDefinitionGatherer: tag qualifier-derived names so consumers can distinguish them
private static final String QUALIFIER_MARKER = "@";

private static String dependencyKey(String fieldOrParamName, @Nullable String qualifier) {
  return qualifier != null ? QUALIFIER_MARKER + qualifier : fieldOrParamName;
}

// AmbiguousDependencyCheck: only match against a candidate's own @Qualifier for
// injection points that declared one
private static boolean matchesCandidate(String injectionPointName, Set<String> candidates, BeanDefinitionRegistry registry) {
  if (injectionPointName.startsWith("@")) {
    String qualifier = injectionPointName.substring(1);
    return candidates.contains(qualifier)
      || candidates.stream().anyMatch(c -> qualifier.equals(qualifierOf(registry, c)));
  }
  return candidates.contains(injectionPointName);
}
  • Apply fix

Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎

Comment on lines +84 to +96
private static boolean matchesCandidate(String injectionPointName, Set<String> candidates, BeanDefinitionRegistry registry) {
return candidates.contains(injectionPointName)
|| candidates.stream().anyMatch(candidate -> injectionPointName.equals(qualifierOf(registry, candidate)));
}

@Nullable
private static String qualifierOf(BeanDefinitionRegistry registry, String beanName) {
return registry.getByName(beanName).stream()
.map(BeanDefinitionHolder::getQualifier)
.filter(Objects::nonNull)
.findFirst()
.orElse(null);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Edge Case: Several candidates sharing one @qualifier value counted as resolved

matchesCandidate uses anyMatch, so an injection point is considered resolved as soon as at least one candidate carries the matching qualifier. Trigger: two beans of the same type both annotated @Qualifier("main") plus a consumer with @Qualifier("main") — Spring still throws NoUniqueBeanDefinitionException, but the rule reports nothing. The same holds when one candidate's bean name and another candidate's @qualifier value both equal the injection point name. Require exactly one matching candidate instead of at least one.

Treat the injection point as resolved only when a single candidate matches by name or by its own @qualifier.:

private static boolean matchesCandidate(String injectionPointName, Set<String> candidates, BeanDefinitionRegistry registry) {
  return candidates.stream()
    .filter(candidate -> candidate.equals(injectionPointName)
      || injectionPointName.equals(qualifierOf(registry, candidate)))
    .count() == 1;
}
  • Apply fix

Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎

Comment on lines +190 to +192
var encodedQualifier = bean.qualifier() != null
? Base64.getEncoder().encodeToString(bean.qualifier().getBytes(StandardCharsets.UTF_8))
: "";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Quality: Bean-level qualifier cache round-trip is never exercised by tests

The new bean-level qualifier field was added to the cache format, but every updated test literal uses the empty (||) form, and no test scans a class annotated with a class-level @Qualifier to assert BeanDefinitionHolder.getQualifier() or a non-empty serialize/deserialize round-trip. A regression in that field (wrong index, missing Base64 encoding) would silently drop qualifiers on cache hits during incremental analysis, turning the new resolution logic back into false positives, and no test would fail. Add a gatherer test with a @Qualifier-annotated component asserting getQualifier() after a normal scan and after scanWithoutParsing restores it from cache.

Was this helpful? React with 👍 / 👎

@datadog-sonarsource

This comment has been minimized.

TypeToBeanNamesIndex typeToBeanNamesIndex = model.getTypeToBeanNamesIndex();

List<AmbiguousDependency> ambiguousDependencies = new ArrayList<>();
for (BeanDefinitionHolder bean : registry.getAll()) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here makes sense to iterate in outer loop through TypeToBeanNamesIndex map to inspect types, then for each type iterate through specific beans using BeanDefinitionRegistry.

// itself), otherwise at least one injection point remains ambiguous.
return candidates.size() <= 1
|| injectionPointNames.stream().allMatch(name -> matchesCandidate(name, candidates, registry))
|| hasExactlyOnePrimaryCandidate(candidates, registry);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here it's very important to check for having Profile set for the candidates. Candidates having configured profile should be excluded from consideration as possibly mutually exclusive.

if (!isResolved(candidates, dependency.getValue(), registry)) {
// A @Fallback candidate is only a real contender when it is the sole remaining one; otherwise it is
// ignored by Spring, so the effective candidates are whichever bean(s) are not marked @Fallback.
Set<String> effectiveCandidates = excludeFallbackCandidates(candidates, registry);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fallback annotation is modern (introduced in Spring Framework 6.2) and thus currently low used. We can add it later in follow-up ticket.

// ignored by Spring, so the effective candidates are whichever bean(s) are not marked @Fallback.
Set<String> effectiveCandidates = excludeFallbackCandidates(candidates, registry);
if (effectiveCandidates.size() > 1) {
ambiguousDependencies.add(new AmbiguousDependency(bean.getLocation(), message(requiredType, effectiveCandidates)));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we've discussed, another alternative is to raise issues on project level instead. Drawback is that we won't see it in SonarLint. So the current approach looks appropriate.

@Override
public void execute(SensorContext context) {
// Nothing to do for now
reportAmbiguousDependencies(context);

@asya-vorobeva asya-vorobeva Aug 28, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we have in mind that we'll implement multiple checks which will be called here. So I'd recommend to use Strategy design pattern.
For it we need to create some common interface with some execute method which all the needed checks will implement, and common record with information needed to create an issue (generalize AmbiguousDependency).
Then we can inject all of them into this sensor (injection mechanism is on you) and run execute method for all of them in a loop.

@asya-vorobeva asya-vorobeva left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To properly test such checks, please use scanner-integration-framework capabilities provided in this ticket.

@gitar-bot

gitar-bot Bot commented Aug 31, 2026

Copy link
Copy Markdown
CI failed: CI workflow completed successfully with all tests passing and a diff report artifact generated.

Overview

All 12 analyzed logs indicate that the CI workflow completed successfully. The autoscan tests and diff report generation executed as expected without any blocking errors or test failures.

Failures

No Failures Detected (confidence: high)

  • Type: other
  • Affected jobs: 98181453872, 98206459188, 98457115131, 98475350195, 98537449746, 98565225632, 98572518940, 99524204030, 99537572272
  • Related to change: yes
  • Root cause: None; the build, test, and artifact upload steps completed successfully.
  • Suggested fix: No action required.

Summary

  • Change-related failures: 0 failures
  • Infrastructure/flaky failures: 0 failures
  • Recommended action: None, the build is healthy.
Code Review ⚠️ Changes requested 9 resolved / 12 findings

Implements S9352 to detect Spring bean autowiring ambiguity, but three issues must be resolved before merge:

  • Field name matched against a bean's own @Qualifier hides ambiguity: dependencyKey conflates injection point @Qualifier values with field/parameter names, causing matchesCandidate to accept plain field names as matches against a candidate bean's own declared @Qualifier. Spring only matches bean names and aliases, never a bean's @Qualifier value, so this produces false negatives. Mark qualifier-derived names in the dependency model to separate qualifier-vs-qualifier comparison from by-name fallback.
  • Several candidates sharing one @Qualifier value counted as resolved: matchesCandidate uses anyMatch, treating an injection point as resolved when at least one candidate carries the matching qualifier. Spring throws NoUniqueBeanDefinitionException if multiple candidates match, so require exactly one matching candidate instead.
  • Bean-level qualifier cache round-trip is never exercised by tests: All updated test cache literals use the empty form, and no test scans a @Qualifier-annotated component to assert the field after cache restoration. A regression in serialization would silently drop qualifiers on cache hits during incremental analysis without test failure. Add a test asserting BeanDefinitionHolder.getQualifier() after both normal scan and cache restore.
⚠️ Bug: Field name matched against a bean's own @Qualifier hides ambiguity

📄 java-checks/src/main/java/org/sonar/java/checks/spring/AmbiguousDependencyCheck.java:75-89 📄 java-frontend/src/main/java/org/sonar/java/model/springcontext/BeanDefinitionGatherer.java:356-370

dependencyKey collapses an injection point's @Qualifier value and its field/parameter name into the same string, so matchesCandidate cannot tell them apart and now accepts a plain field name as a match against a candidate bean's own declared @Qualifier. Trigger: @Component @Qualifier("mainService") class A implements Svc, @Component class B implements Svc, and a consumer with @Autowired private Svc mainService; (no @Qualifier at the injection point). Spring's by-name fallback (DefaultListableBeanFactory.determineAutowireCandidate -> matchesBeanName) only compares bean names and aliases, never a bean's @Qualifier value, so Spring fails with NoUniqueBeanDefinitionException while the rule now stays silent (false negative). Fix by marking qualifier-derived names in the dependency model so the qualifier-vs-qualifier comparison is only applied to injection points that actually declare @Qualifier.

Distinguish qualifier-derived injection point names from field/parameter names (serialization/deserialization keeps working since the marker is inside the Base64-encoded name).
// BeanDefinitionGatherer: tag qualifier-derived names so consumers can distinguish them
private static final String QUALIFIER_MARKER = "@";

private static String dependencyKey(String fieldOrParamName, @Nullable String qualifier) {
  return qualifier != null ? QUALIFIER_MARKER + qualifier : fieldOrParamName;
}

// AmbiguousDependencyCheck: only match against a candidate's own @Qualifier for
// injection points that declared one
private static boolean matchesCandidate(String injectionPointName, Set<String> candidates, BeanDefinitionRegistry registry) {
  if (injectionPointName.startsWith("@")) {
    String qualifier = injectionPointName.substring(1);
    return candidates.contains(qualifier)
      || candidates.stream().anyMatch(c -> qualifier.equals(qualifierOf(registry, c)));
  }
  return candidates.contains(injectionPointName);
}
💡 Edge Case: Several candidates sharing one @Qualifier value counted as resolved

📄 java-checks/src/main/java/org/sonar/java/checks/spring/AmbiguousDependencyCheck.java:84-96

matchesCandidate uses anyMatch, so an injection point is considered resolved as soon as at least one candidate carries the matching qualifier. Trigger: two beans of the same type both annotated @Qualifier("main") plus a consumer with @Qualifier("main") — Spring still throws NoUniqueBeanDefinitionException, but the rule reports nothing. The same holds when one candidate's bean name and another candidate's @Qualifier value both equal the injection point name. Require exactly one matching candidate instead of at least one.

Treat the injection point as resolved only when a single candidate matches by name or by its own @qualifier.
private static boolean matchesCandidate(String injectionPointName, Set<String> candidates, BeanDefinitionRegistry registry) {
  return candidates.stream()
    .filter(candidate -> candidate.equals(injectionPointName)
      || injectionPointName.equals(qualifierOf(registry, candidate)))
    .count() == 1;
}
💡 Quality: Bean-level qualifier cache round-trip is never exercised by tests

📄 java-frontend/src/main/java/org/sonar/java/model/springcontext/BeanDefinitionGatherer.java:190-192 📄 java-frontend/src/main/java/org/sonar/java/model/springcontext/BeanDefinitionGatherer.java:271-273 📄 java-frontend/src/test/java/org/sonar/java/model/springcontext/BeanDefinitionGathererTest.java:340-345 📄 java-frontend/src/test/java/org/sonar/java/model/springcontext/BeanDefinitionGathererTest.java:460-474

The new bean-level qualifier field was added to the cache format, but every updated test literal uses the empty (||) form, and no test scans a class annotated with a class-level @Qualifier to assert BeanDefinitionHolder.getQualifier() or a non-empty serialize/deserialize round-trip. A regression in that field (wrong index, missing Base64 encoding) would silently drop qualifiers on cache hits during incremental analysis, turning the new resolution logic back into false positives, and no test would fail. Add a gatherer test with a @Qualifier-annotated component asserting getQualifier() after a normal scan and after scanWithoutParsing restores it from cache.

✅ 9 resolved
Bug: Rule flags its own documented @fallback compliant example

📄 sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9352.html:122-136 📄 java-checks-test-sources/default/src/main/files/non-compiling/checks/spring/s9352/FallbackRegularComponent.java:7-10 📄 sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/Sonar_way_profile.json:541-542
The shipped description presents @Fallback as a third valid fix (diff-id 3 "Compliant solution"), but the implementation ignores @Fallback entirely — only @Primary, qualifier and name matches are consulted — as the new non-compiling samples acknowledge. Running the rule on the doc's own compliant snippet (two DataSource beans, one @Fallback, field dataSource matching neither bean name) raises an issue, so the rule contradicts its documentation on a default-profile Critical rule. Either treat @Fallback candidates as excluded from the candidate pool before enabling the rule in Sonar way, or remove the @Fallback fix section from the description.

Bug: One resolved injection point hides other ambiguous ones

📄 java-checks/src/main/java/org/sonar/java/checks/spring/AmbiguousDependencyCheck.java:56-70
collectAutowiredDependencies merges every injection point of the same type into a single name set per type, and isAmbiguous clears the whole type as soon as one of those names matches a candidate (candidates.stream().noneMatch(injectionPointNames::contains)). For @Service class C { @Autowired @Qualifier("componentOne") ApplicationContextAware a; @Autowired ApplicationContextAware b; } the set is {componentOne, b}, componentOne matches a candidate, so the genuinely ambiguous field b is never reported even though Spring fails to start. Require every recorded name to resolve instead of any one of them.

Bug: False positive when @qualifier is declared on the bean itself

📄 java-checks/src/main/java/org/sonar/java/checks/spring/AmbiguousDependencyCheck.java:67-71
The check compares injection-point qualifier values against bean names only (typeToBeanNamesIndex.getNamesForType, populated from extractBeanName/defaultBeanName). Spring also resolves @Autowired @Qualifier("main") Foo f against a bean declared @Component @Qualifier("main") (or a @Bean method annotated with @Qualifier), which the gatherer never records; such code is reported as ambiguous although the context starts fine. Since S9352 is enabled in Sonar way with Critical/HIGH reliability, this is a user-visible false positive — index bean-side qualifier values in TypeToBeanNamesIndex (or skip injection points whose qualifier matches no known bean name at all).

Edge Case: Two @primary candidates silently treated as resolved

📄 java-checks/src/main/java/org/sonar/java/checks/spring/AmbiguousDependencyCheck.java:67-75
isAmbiguous only asks whether any candidate is @Primary; when two beans of the same type are both annotated @Primary, Spring still throws NoUniqueBeanDefinitionException, yet the check reports nothing. Count the primary candidates and keep the dependency ambiguous unless exactly one is primary.

Quality: Two-candidate fallback test passes even if exclusion is broken

📄 java-checks/src/test/java/org/sonar/java/checks/spring/AmbiguousDependencyCheckTest.java:86-92
fallback_candidate_does_not_resolve_ambiguity_with_two_other_candidates only asserts hasSize(1), which holds whether the @Fallback bean is excluded (2 candidates reported) or not (3 candidates reported) — so it does not actually exercise excludeFallbackCandidates. This matters because detection relies on matching the fully-qualified unresolved annotation name in non-compiling sources (spring-context 5.3.31 has no Fallback), which is exactly what the assertion should pin down. Assert the issue message so that the fallback bean is verified to be absent from the reported candidate list.

...and 4 more resolved from earlier reviews

🤖 Prompt for agents
Code Review: Implements S9352 to detect Spring bean autowiring ambiguity, but three issues must be resolved before merge:
  
  - **Field name matched against a bean's own @Qualifier hides ambiguity**: `dependencyKey` conflates injection point @Qualifier values with field/parameter names, causing `matchesCandidate` to accept plain field names as matches against a candidate bean's own declared @Qualifier. Spring only matches bean names and aliases, never a bean's @Qualifier value, so this produces false negatives. Mark qualifier-derived names in the dependency model to separate qualifier-vs-qualifier comparison from by-name fallback.
  - **Several candidates sharing one @Qualifier value counted as resolved**: `matchesCandidate` uses `anyMatch`, treating an injection point as resolved when *at least one* candidate carries the matching qualifier. Spring throws NoUniqueBeanDefinitionException if multiple candidates match, so require exactly one matching candidate instead.
  - **Bean-level qualifier cache round-trip is never exercised by tests**: All updated test cache literals use the empty form, and no test scans a `@Qualifier`-annotated component to assert the field after cache restoration. A regression in serialization would silently drop qualifiers on cache hits during incremental analysis without test failure. Add a test asserting `BeanDefinitionHolder.getQualifier()` after both normal scan and cache restore.

1. ⚠️ Bug: Field name matched against a bean's own @Qualifier hides ambiguity
   Files: java-checks/src/main/java/org/sonar/java/checks/spring/AmbiguousDependencyCheck.java:75-89, java-frontend/src/main/java/org/sonar/java/model/springcontext/BeanDefinitionGatherer.java:356-370

   `dependencyKey` collapses an injection point's @Qualifier value and its field/parameter name into the same string, so `matchesCandidate` cannot tell them apart and now accepts a *plain field name* as a match against a candidate bean's own declared @Qualifier. Trigger: `@Component @Qualifier("mainService") class A implements Svc`, `@Component class B implements Svc`, and a consumer with `@Autowired private Svc mainService;` (no @Qualifier at the injection point). Spring's by-name fallback (`DefaultListableBeanFactory.determineAutowireCandidate` -> `matchesBeanName`) only compares bean names and aliases, never a bean's @Qualifier value, so Spring fails with NoUniqueBeanDefinitionException while the rule now stays silent (false negative). Fix by marking qualifier-derived names in the dependency model so the qualifier-vs-qualifier comparison is only applied to injection points that actually declare @Qualifier.

   Fix (Distinguish qualifier-derived injection point names from field/parameter names (serialization/deserialization keeps working since the marker is inside the Base64-encoded name).):
   // BeanDefinitionGatherer: tag qualifier-derived names so consumers can distinguish them
   private static final String QUALIFIER_MARKER = "@";
   
   private static String dependencyKey(String fieldOrParamName, @Nullable String qualifier) {
     return qualifier != null ? QUALIFIER_MARKER + qualifier : fieldOrParamName;
   }
   
   // AmbiguousDependencyCheck: only match against a candidate's own @Qualifier for
   // injection points that declared one
   private static boolean matchesCandidate(String injectionPointName, Set<String> candidates, BeanDefinitionRegistry registry) {
     if (injectionPointName.startsWith("@")) {
       String qualifier = injectionPointName.substring(1);
       return candidates.contains(qualifier)
         || candidates.stream().anyMatch(c -> qualifier.equals(qualifierOf(registry, c)));
     }
     return candidates.contains(injectionPointName);
   }

2. 💡 Edge Case: Several candidates sharing one @Qualifier value counted as resolved
   Files: java-checks/src/main/java/org/sonar/java/checks/spring/AmbiguousDependencyCheck.java:84-96

   `matchesCandidate` uses `anyMatch`, so an injection point is considered resolved as soon as *at least one* candidate carries the matching qualifier. Trigger: two beans of the same type both annotated `@Qualifier("main")` plus a consumer with `@Qualifier("main")` — Spring still throws NoUniqueBeanDefinitionException, but the rule reports nothing. The same holds when one candidate's bean name and another candidate's @Qualifier value both equal the injection point name. Require exactly one matching candidate instead of at least one.

   Fix (Treat the injection point as resolved only when a single candidate matches by name or by its own @Qualifier.):
   private static boolean matchesCandidate(String injectionPointName, Set<String> candidates, BeanDefinitionRegistry registry) {
     return candidates.stream()
       .filter(candidate -> candidate.equals(injectionPointName)
         || injectionPointName.equals(qualifierOf(registry, candidate)))
       .count() == 1;
   }

3. 💡 Quality: Bean-level qualifier cache round-trip is never exercised by tests
   Files: java-frontend/src/main/java/org/sonar/java/model/springcontext/BeanDefinitionGatherer.java:190-192, java-frontend/src/main/java/org/sonar/java/model/springcontext/BeanDefinitionGatherer.java:271-273, java-frontend/src/test/java/org/sonar/java/model/springcontext/BeanDefinitionGathererTest.java:340-345, java-frontend/src/test/java/org/sonar/java/model/springcontext/BeanDefinitionGathererTest.java:460-474

   The new bean-level `qualifier` field was added to the cache format, but every updated test literal uses the empty (`||`) form, and no test scans a class annotated with a class-level `@Qualifier` to assert `BeanDefinitionHolder.getQualifier()` or a non-empty serialize/deserialize round-trip. A regression in that field (wrong index, missing Base64 encoding) would silently drop qualifiers on cache hits during incremental analysis, turning the new resolution logic back into false positives, and no test would fail. Add a gatherer test with a `@Qualifier`-annotated component asserting `getQualifier()` after a normal scan and after `scanWithoutParsing` restores it from cache.

Tip

Comment Gitar fix CI or enable auto-apply: gitar auto-apply:on

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.
Unblock → Override a blocking verdict and allow merging.

Comment with these commands to change the behavior for this request:

Auto-apply Compact Unblock
gitar auto-apply:on         
gitar display:verbose         
gitar unblock         

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqube-next

Copy link
Copy Markdown
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants