If you are not following... Yesterday, our belov...
# random
j
If you are not following... Yesterday, our belove Gradle Technologies dropped v6 of their GitHub Actions for Gradle builds. 45,000+ open source repositories use this thing. It's literally baked into GitHub's own starter workflows. Here's what they actually did, stripped of the PR spin: They took a fully open-source, MIT-licensed tool. And made a core piece of it proprietary. Overnight. The caching functionality in setup-gradle, you know, the part that makes the whole thing actually useful, has been quietly extracted into a closed-source library called gradle-actions-caching, now distributed under their own Terms of Use. Not MIT. Not Apache. Their fucking terms. And the kicker? By simply upgrading to v6, you automatically accept those terms. No negotiation. No opt-in. Just bump the version number, and congratulations, you've agreed to a proprietary license you probably didn't read. Let's go through the greatest hits of this announcement: "We're not introducing any functional restrictions in this release." Translation: not yet. They literally say in the same post: "We may introduce functionality restrictions in future updates." So they're asking you to migrate to a proprietary dependency today, on the promise that they won't lock you out... until they decide to. They removed Configuration Cache support, the one experimental feature that was actually forward-looking, and called it a "functional change." Cool. You took something away AND made the rest proprietary. Two for one. "Caching will remain free for public repositories." Great. What about private ones? What about enterprises running self-hosted runners at scale? Oh, those people should go buy Develocity. Funny how that works. The whole justification is "supporting this requires engineering investment." Sure. Every open source project does. The difference is most maintainers don't respond to that by quietly relicensing the most critical component and burying the news in a blog post on a Monday. This is the classic open-core bait-and-switch. Build trust and adoption with open source. Wait until you're deeply embedded in tens of thousands of workflows. Then start closing the doors, one component at a time, while pointing at your commercial product. The open source community deserves better than this. Especially from a company that still has the audacity to write "we have a long-standing commitment to open source" in the same post where they announce this. If you're using gradle/actions/setup-gradle, I'd strongly suggest you read what you're actually agreeing to before you upgrade. https://blog.gradle.org/github-actions-for-gradle-v6
😟 6
🧵 1
👀 9
t
Almost certainly its because they are preparing the path toward their universal cache behavior in develocity reaching a GA release (additional cost upgrade on top of regular per seat licensing I believe).
What about enterprises running self-hosted runners at scale?
if you are self hosting you should absolutely rebuild every cache action you use that are backed by your own S3 storage instead of using the actions/cache* stuff. You stand to save a ton of time by keeping the heavy file moves local to the cloud region you are hosting in. Assuming you have an S3 vpc endpoint configured it will also be eliminating a TON of NAT gateway bandwidth saving you thousands per month before even considering the time savings for your engineering team. (Aws phrasing in all of that but pretty sure you could replicate everything in any of the major clouds)
👀 1
c
By the way, you didn't mention the best part. This is in the terms of service:
By submitting User Submissions through the Services, you hereby do and shall grant Gradle a worldwide, non-exclusive, perpetual, royalty-free, fully paid, sublicensable and transferable license to use, edit, modify, truncate, aggregate, reproduce, distribute, prepare derivative works of, display, perform, and otherwise fully exploit the User Submissions in connection with this site, the Services and our (and our successors’ and assigns’) businesses
So everything that ends up in the build cache belongs to them now
s
I am no lawyer, bu this piece seems to suggest that you still own your submission, it's just that they have the right to copy your submission (regardless of licence), and do whatever they want with that copy.
For clarity, the foregoing license grants to us and our users do not affect your other ownership or license rights in your User Submissions, including the right to grant additional licenses to your User Submissions, unless otherwise agreed in writing.
c
The word 'belong' was the wrong one, but my point is that they give themselves to right to share your private code with whoever, and do whatever with it. Including train AIs, whatever
s
Yeah, definitely uncool, agree with you there.
t
If you are in the zone of building self hosted runner infra I want to dump some of the details of what I have recently rolled out. Working incredibly well so far. Summary dump from opus.
Copy code
Here's the full picture:

  ---
  tool-cache-s3: Backs the runner's tool cache directory to/from S3. On restore, it downloads a manifest (manifests/{cache-key}.json) and fetches
  tar.zst archives in parallel into _tool/{name}/{version}/{arch}/. On save (post step), it scans for new .complete markers, tars them up, and
  uploads. Same directory layout as GitHub's @actions/tool-cache.

  setup-android: Starts a local HTTPS proxy that intercepts sdkmanager downloads. On cache hit, it serves files from the tool cache directory. On
  cache miss, it downloads and writes them into the tool cache with .complete markers — which tool-cache-s3's post step then picks up and persists
  to S3. Next run, tool-cache-s3 restores them and the proxy serves them locally. Net effect: Android SDK packages download once, then get served
  from S3 cache on every subsequent run.

  Parallelization — two levels:

  1. Across tools: Both restore and save dispatch all tools concurrently via Promise.all(manifest.tools.map(...)). Every tool in the manifest
  downloads/uploads at the same time rather than sequentially.
  2. Within each S3 object (the s3.ts layer): Large files (>32MB) use parallel byte-range transfers:
    - Download: HEAD to get size → split into 32MB ranges → fire up to 10 concurrent Range GET requests → write each chunk at its offset into a
  pre-allocated file. Uses a bounded-concurrency pattern (Set<Promise> + Promise.race when pool is full).
    - Upload: AWS SDK Upload with 32MB parts and queueSize: 10, which streams 10 multipart upload parts in flight simultaneously.
    - Small files (≤32MB): skip the range machinery and do a single GET/PUT — avoids the HEAD + range overhead.

  So a restore of 8 tools fires 8 parallel downloads, each of which internally parallelizes into 10 concurrent 32MB range GETs. Same pattern on
  save. The result is saturating the EC2-to-S3 network link rather than bottlenecking on sequential transfers.
👍🏾 1
extra context on the tool cache dir I am abusing to make this work in a low impact way.
Copy code
The _tool directory (usually /opt/hostedtoolcache or $RUNNER_TOOL_CACHE) is a convention shared between GitHub's @actions/tool-cache npm package
  and all the official actions/setup-* actions.

  When actions/setup-node (or setup-java, setup-python, etc.) runs, it calls tc.find('node', '20.x', 'x64') which checks
  _tool/node/20.11.1/x64/.complete. If that marker file exists, it skips downloading entirely and just adds the directory to PATH. If not, it
  downloads, extracts, calls tc.cacheDir() which writes the files and creates the .complete marker.

  tool-cache-s3 exploits this directly. It restores tar.zst archives into the exact same _tool/{name}/{version}/{arch}/ layout with .complete
  markers before any setup-* action runs. When actions/setup-node later calls tc.find(), it sees the marker, treats it as a cache hit, and skips
  the download. The setup action has no idea S3 was involved — it just sees a pre-populated tool cache directory.

  On the save side, any tool installed during the job (cache miss on restore) gets a .complete marker written by the setup action's tc.cacheDir()
  call. tool-cache-s3's post step scans for these markers, tars up anything new, and uploads to S3 for next time.

  So it's a transparent layer that sits beneath the standard tool-cache API — no changes needed to any actions/setup-* action.
👍🏾 1
get a bit creative with all that info and how the setup-gradle action works.... you can get config cache working while driving dep downloads for most jobs to zero.