CAMEL-24618: Fix flaky SpringFileAntPathMatcherRemoteFileFilterTest - #26120
CAMEL-24618: Fix flaky SpringFileAntPathMatcherRemoteFileFilterTest#26120gnodet wants to merge 1 commit into
Conversation
utafrali
left a comment
There was a problem hiding this comment.
The three-line test/XML fix (delete=true, initialDelay=0, 30s wait) is correct and targeted, but the PR bundles unrelated CI/Sonar/Scalpel changes — several of which hardcode gnodet/camel and gnodet_camel project keys, drop a security hardening flag, and remove an INFRA-27808 gate. Split the PR and revert the fork-specific configuration before this can be merged.
| -Dsonar.pullrequest.base=${{ env.pr_base_ref }} | ||
| -Dsonar.pullrequest.key=${{ env.pr_number }} | ||
| -Dsonar.pullrequest.github.repository=apache/camel | ||
| -Dsonar.pullrequest.github.repository=gnodet/camel |
There was a problem hiding this comment.
This hardcodes -Dsonar.pullrequest.github.repository=gnodet/camel, -Dsonar.projectKey=gnodet_camel, and -Dsonar.organization=gnodet. If this lands on apache/camel, sonar analysis will publish to your personal fork's Sonar project instead of apache_camel. These look like local testing overrides that shouldn't be committed. Revert to apache/camel, apache_camel, apache.
| jobs: | ||
| sonar: | ||
| # Temporarily disabled until SonarCloud quality gate is adjusted (INFRA-27808) | ||
| if: > |
There was a problem hiding this comment.
Removing github.repository == 'apache/camel' from the condition means the workflow will now attempt to run on every fork that receives a workflow_run event. Combined with the hardcoded gnodet/camel project key below, this looks like fork-local plumbing rather than an intentional main-branch change. Keep the repository guard.
| jobs: | ||
| build: | ||
| if: github.repository == 'apache/camel' | ||
| if: github.repository == 'apache/camel' || github.repository == 'gnodet/camel' |
There was a problem hiding this comment.
github.repository == 'apache/camel' || github.repository == 'gnodet/camel' hardcodes a personal fork into an apache/camel workflow. If you need to test on your fork, use github.repository_owner != '' or drop the guard locally, not in the upstream file.
|
|
||
| - name: Fetch base branch for Scalpel change detection | ||
| run: | | ||
| git fetch --deepen=200 2>/dev/null || true |
There was a problem hiding this comment.
The persist-credentials: false line was removed from the checkout step. This is a hardening default (OSSF Scorecard recommends it for actions/checkout) — restore it unless there is a specific reason later steps need the credential helper.
| build: | ||
| # Temporarily disabled until SonarCloud quality gate is adjusted (INFRA-27808) | ||
| if: false && github.repository == 'apache/camel' | ||
| if: true |
There was a problem hiding this comment.
if: false && ... was replaced by if: true, dropping both the INFRA-27808 gate and the github.repository == 'apache/camel' guard in one go. The linked ticket comment above still says the workflow is disabled pending SonarCloud quality-gate work — either update/remove the comment and confirm INFRA-27808 is resolved, or keep the repo guard.
|
|
||
| <!-- use myFilter as filter to allow setting ANT paths for which files to scan for --> | ||
| <endpoint id="myFTPEndpoint" uri="ftp://admin@localhost:${SpringFileAntPathMatcherRemoteFileFilterTest.ftpPort}/antpath?password=admin&recursive=true&delay=10000&initialDelay=2000&filter=#myAntFilter"/> | ||
| <endpoint id="myFTPEndpoint" uri="ftp://admin@localhost:${SpringFileAntPathMatcherRemoteFileFilterTest.ftpPort}/antpath?password=admin&recursive=true&delay=10000&initialDelay=0&delete=true&filter=#myAntFilter"/> |
There was a problem hiding this comment.
The URI change itself is the right fix, but consider adding readLock=changed (or readLock=none with a comment explaining why it's safe here) alongside delete=true. Without a read lock, on a slow FTP handshake the consumer can begin reading a file that the producer is still writing — historically a source of a different flake class in the FTP itests. If you've already ruled this out for this test, leave it, but a one-line XML comment near delete=true explaining the state-contamination fix would help the next reader.
| void testAntPatchMatherFilter() throws Exception { | ||
|
|
||
| result.expectedBodiesReceived(expectedBody); | ||
| result.setResultWaitTime(30000); |
There was a problem hiding this comment.
Prefer the timed overload MockEndpoint.assertIsSatisfied(context, 30, TimeUnit.SECONDS) in the assertion below instead of calling setResultWaitTime(30000). It reads more clearly at the assertion site and keeps the wait budget next to the assertion it applies to. Per the project guidelines, mock-based waits should use MockEndpoint's native timed API rather than setter side-effects.
| if [ -n "$prId" ]; then | ||
| echo "Fetching PR #${prId} diff..." | ||
| diff_body=$(fetchDiff "$prId" "$repository") | ||
| echo "Computing diff against origin/${GITHUB_BASE_REF:-main}..." |
There was a problem hiding this comment.
Switching PR diff computation from the GitHub API to a local git diff merge-base..HEAD is a meaningful behavior change (previously the diff matched exactly what GitHub shows on the PR; now it includes any local merge commits or force-push artifacts differently). Worth calling out in the PR description and testing on a PR that has been rebased/force-pushed — the two diffs can diverge when the base branch has moved forward and the PR hasn't been rebased.
| <groupId>eu.maveniverse.maven.scalpel</groupId> | ||
| <artifactId>extension3</artifactId> | ||
| <version>0.3.0</version> | ||
| <version>0.3.3</version> |
There was a problem hiding this comment.
Bumping Scalpel from 0.3.0 to 0.3.3 is unrelated to the flaky-test fix advertised in the PR title. Please split: (1) the CAMEL-24618 test fix, (2) the Scalpel bump + shadow-comparison wiring, (3) the sonar/pr-build workflow changes. Right now this PR mixes three independent changes under a title that only names one.
| @@ -0,0 +1,255 @@ | |||
| # | |||
There was a problem hiding this comment.
A new 255-line workflow (full-test-suite.yml) is landing under a PR titled "Fix flaky SpringFileAntPathMatcherRemoteFileFilterTest". Split this out — it deserves its own PR, its own JIRA (or none if infra-only), and its own review. Bundling it here hides it from reviewers looking at the ticket scope.
91325e3 to
cbefb7f
Compare
|
🌟 Thank you for your contribution to the Apache Camel project! 🌟 🐫 Apache Camel Committers, please review the following items:
|
|
🧪 CI tested the following changed modules:
🔬 Scalpel shadow comparison — Scalpel: 1 tested, 0 compile-only — current: 0 all testedMaveniverse Scalpel detected 1 affected modules (current approach: 0).
|
Fix two flakiness root causes: 1. State contamination (expected <1> but was <9>): The FTP consumer had no delete option, so files accumulated across test retries since FtpServiceExtension.afterAll() is a no-op and the FTP server directories are never reset. Added delete=true to the FTP consumer URI so files are removed after processing. 2. Timing race (expected <1> but was <0>): The consumer had initialDelay=2000ms which, combined with the default resultWaitTime, could cause the mock assertion to expire before the first poll completed on slow CI. Changed initialDelay to 0 and set an explicit resultWaitTime of 30 seconds.
cbefb7f to
33bcf38
Compare
|
Addressed all review comments:
|
Problem
SpringFileAntPathMatcherRemoteFileFilterTest.testAntPatchMatcherFilteris flaky with two distinct failure modes:expected <1> but was <9>— state contamination: The FTP consumer URI had nodeleteoption, so consumed files remained on the FTP server. SinceFtpServiceExtension.afterAll()is a no-op (the FTP server is never stopped/reset), files accumulated across test retries, causing the mock to receive duplicate messages.expected <1> but was <0>— timing race: The consumer hadinitialDelay=2000ms, and with the defaultMockEndpoint.resultWaitTime(10s), the assertion could expire before the first poll completed on slow CI environments.Fix
delete=trueto the FTP consumer URI in the Spring XML context — files are deleted after processing, preventing accumulation across retriesinitialDelayfrom 2000 to 0 — the consumer starts polling immediatelyresultWaitTime(30000)on the mock endpoint — generous timeout for slow CI