Skip to content

CLOUDSEC-27 Add script for pre-downloading Spotless dependencies - #127

Closed
mstachniuk wants to merge 1 commit into
masterfrom
marcin/script-for-fix-spotless-dependencies
Closed

mstachniuk wants to merge 1 commit into
masterfrom
marcin/script-for-fix-spotless-dependencies

Conversation

@mstachniuk

Copy link
Copy Markdown
Contributor

No description provided.

@hashicorp-vault-sonar-prod hashicorp-vault-sonar-prod Bot changed the title Add script for pre-downloading Spotless dependencies CLOUDSEC-27 Add script for pre-downloading Spotless dependencies May 8, 2026
@hashicorp-vault-sonar-prod

hashicorp-vault-sonar-prod Bot commented May 8, 2026 •

Copy link
Copy Markdown

CLOUDSEC-27

@sonar-review-alpha

sonar-review-alpha Bot commented May 8, 2026 •

Copy link
Copy Markdown

Summary

Adds a Python utility script to pre-download Spotless formatter dependencies and avoid OkHttp timeouts on CloudFlare WARP networks.

Problem: The Spotless Groovy/Java Eclipse formatters download large JARs via OkHttp with a 10-second read timeout. When behind CloudFlare WARP, traffic inspection slows downloads below that threshold, causing builds to fail.

Solution: This script pre-populates the Equo P2 bundle pool using urllib (unaffected by OkHttp timeouts). It:

  • Detects greclipse and Eclipse Java formatter versions used in the project
  • Fetches artifact manifests from P2 repositories (with local caching to avoid slow repeats)
  • Parallelizes JAR downloads (8 workers) to populate the Equo bundle pool
  • Supports P2 mirrors for metadata while correctly using canonical URLs for JAR downloads

Developers can run it manually before builds to pre-cache all dependencies, or integrate it into CI/build scripts. Works with SonarSource projects like differential-validation and sonar-iac-enterprise.

What reviewers should know

Script entry points and flow: main() starts by detecting the project's Spotless configuration (greclipse version, Eclipse Java formatter versions) by scanning build scripts. For each formatter, it queries the P2 repository metadata and downloads missing JARs into ~/.m2/repository/dev/equo/p2-data/bundle-pool/.

Key implementation decisions to review:

  • filename_safe(): Replicates Equo's Java OfflineCache.filenameSafe() using MD5 hashing. Verify the truncation logic and base64 encoding match the Java behavior exactly—this is critical for cache key correctness.
  • Mirror handling: _apply_mirror() and _prefill_single_pool() keep mirrors separate from the canonical P2 URL. Mirrors are used only for metadata discovery (compositeContent.xml and artifacts.xml), while JAR downloads always use the canonical URL. This matters for correctness.
  • Manifest caching: Stores artifact lists with a 7-day TTL to avoid refetching on repeat runs. The cache key is the P2 URL itself (not the project path), so different projects sharing Spotless versions reuse the same manifest.
  • Eclipse version detection: Extracts the default greclipse Eclipse version from the bytecode of the GrEclipse formatter class (GrEclipseFormatterStep.class). This allows the script to work even without explicit version config in the build.

Testing angles: Verify that cache invalidation works correctly, that the script handles missing or malformed P2 repositories gracefully, and that the parallelized downloads don't hammer mirrors with too many concurrent requests.


  • Generate Walkthrough
  • Generate Diagram

🗣️ Give feedback

@sonarqube-next

sonarqube-next Bot commented May 8, 2026

Copy link
Copy Markdown

Quality Gate passed Quality Gate passed for 'cloud-native-gradle-modules'

Issues
0 New issues
0 Fixed issues
0 Accepted issues

Measures
0 Security Hotspots
0 Dependency risks
No data about Coverage
No data about Duplication

See analysis details on SonarQube

@sonar-review-alpha sonar-review-alpha Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The script is well-structured and solves a real problem cleanly. One clear bug needs fixing before merge: the mirror parameter accepted by prefill_bundle_pool is silently discarded and never reaches get_p2_artifacts, meaning the mirror configured in project build scripts has zero effect on this script — exactly the opposite of what a developer behind WARP would expect when they've set up a mirror precisely to work around download failures.

🗣️ Give feedback

Comment on lines +277 to +286
def prefill_bundle_pool(p2_url: str, mirror: Optional[str] = None) -> None:
"""
Download all osgi.bundle JARs from a P2 repository into the Equo bundle pool.

Always uses the canonical (non-mirrored) URL as the bundle pool key.
Eclipse P2 mirrors (e.g. ftp.fau.de) only mirror metadata files, not JARs;
Equo falls back to canonical URLs for JAR downloads regardless of mirror config.
"""
print(f"\n P2 URL : {p2_url}")
_prefill_single_pool(p2_url, p2_url)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The mirror parameter is accepted but silently discarded — it is never forwarded to _prefill_single_pool or get_p2_artifacts. The docstring says the canonical URL is always used as the bundle pool key (correct), but that is orthogonal to using the mirror for fetching artifacts.xml.xz. If the canonical download.eclipse.org is slow or unreachable behind WARP, the configured mirror is never tried for metadata, defeating part of the script's purpose.

Either pass mirror through (requires adding it to _prefill_single_pool and forwarding to get_p2_artifacts), or remove the parameter from the signature to make the omission explicit.

  • Mark as noise

Comment on lines +229 to +232
missing_fast = [
(id_, ver) for id_, ver in cached
if not (dest_dir / f"{id_}_{ver}.jar").exists()
or (dest_dir / f"{id_}_{ver}.jar").stat().st_size == 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Logic duplication: This predicate — not jar.exists() or jar.stat().st_size == 0 — is duplicated verbatim at lines 244–246 for the main-path missing list. If the "is a JAR missing?" check ever changes (e.g. adding a checksum comparison), both places must be updated in sync.

Extract a helper:

def _is_jar_missing(dest_dir: Path, id_: str, ver: str) -> bool:
    p = dest_dir / f"{id_}_{ver}.jar"
    return not p.exists() or p.stat().st_size == 0

Then both list comprehensions can call _is_jar_missing(dest_dir, id_, ver).

  • Mark as noise

python3 scripts/spotless-fix-dependencies.py [project_dir]

If project_dir is omitted, uses the current directory.
Works with: differential-validation, sonar-iac-enterprise (and other repos that ise those modules).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Typo: "repos that ise those modules" → "repos that use those modules".

Suggested change
Works with: differential-validation, sonar-iac-enterprise (and other repos that ise those modules).
Works with: differential-validation, sonar-iac-enterprise (and other repos that use those modules).
  • Mark as noise

@jonas-wielage-sonarsource
jonas-wielage-sonarsource marked this pull request as draft May 13, 2026 07:44
@mstachniuk

Copy link
Copy Markdown
Contributor Author

Moved the script to another place: https://github.com/SonarSource/languages-experimental-tooling/pull/594

@mstachniuk mstachniuk closed this May 13, 2026
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.

1 participant