DEVOPS-6131: route sbt resolution through virtana-zing AR mirror (PR pipeline) - #16
Merged
Merged
Conversation
…pipeline) The delta-sharing sbt build fails on jenkins-eng: Maven Central (repo1.maven.org) 429-rate-limits the shared egress IP, so sbt can't download its own launcher (org.scala-sbt:sbt:1.9.9) or its plugins/deps. Fix (sbt analog of the mirrorMavenCentral shared step): before `make build`, point sbt's Central resolution at the virtana-zing Artifact Registry Maven proxy, authenticated with a short-lived OAuth token minted from gcr_push_key: - ~/.sbt/repositories maven-central -> us-maven.pkg.dev/.../virtana-zing - ~/.config/coursier/... launcher (boot) auth - credentials.sbt / project/credentials.sbt build + plugin (meta) auth - pre-fetch sbt-launch.jar through the mirror (bearer header) - -Dsbt.override.build.repos=true Verified green end-to-end on a trimmed clone (rbak-test-build): no 429, no unauthorized, no token leak, image builds. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Refactor the inline pipeline sh into repo-side config templates and one setup
script, so ci/Jenkinsfile just binds the credential and calls it:
ci/sbt-mirror/
repositories static repo list (maven-central -> mirror)
credentials.properties.tmpl coursier boot creds (token populated on the fly)
credentials.sbt lm-coursier creds for deps + plugins (reads ~/.sbt/.ar-token)
setup.sh mints token, renders the above, pre-fetches sbt-launch.jar,
writes .sbtopts (-Dsbt.override.build.repos=true)
Build stage is now:
withCredentials([file(credentialsId:'gcr_push_key', variable:'AR_KEY_FILE')]) {
sh 'ci/sbt-mirror/setup.sh && make -f ci/Makefile build'
}
Same behavior as the previous commit; the shared script lets the inline `build`
job reuse identical logic. Generated copies (credentials.sbt, project/credentials.sbt,
.sbtopts) are gitignored.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ot file read) The previous refactor had project/credentials.sbt read the token via IO.read of a file; that didn't reach the meta build, so plugin resolution 401'd. Revert to the proven mechanism: credentials.sbt reads AR_TOKEN from the environment. setup.sh writes a sourceable .ar-token.env, and the pipeline does `ci/sbt-mirror/setup.sh && . ./.ar-token.env && make build` so $AR_TOKEN reaches sbt (setup.sh runs in its own process). No secret is committed; .ar-token.env is gitignored and removed in the finally block. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ls.sbt - Jenkins runs sh with -x, so sourcing .ar-token.env echoed the token; prefix the build step with `set +x`. - Revert credentials.sbt to the exact Credentials form proven to authenticate plugin + dependency resolution against the mirror. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nd credentials" sbt's Ivy code path (makePom/metadata) matches credentials by realm, not just host. With an empty realm it logged 4x "Unable to find credentials for [https://us-maven.pkg.dev @ us-maven.pkg.dev]" (non-fatal; coursier still resolved by host). Set the realm to exactly what AR advertises (WWW-Authenticate: Basic realm="https://us-maven.pkg.dev") so Ivy matches too. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…y warnings) delta-sharing is multi-project (server/client/spark). A plain `credentials += ...` is root-project-only, so Ivy resolution for the subprojects logged "Unable to find credentials for [https://us-maven.pkg.dev @ us-maven.pkg.dev]" (non-fatal; coursier still downloaded everything build-wide). Scope to `ThisBuild / credentials` so all subprojects have the credential. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…n, self-cleaning)
Replace the setup.sh + .ar-token.env + pipeline-finally-cleanup dance with a single
wrapper that runs the build with the mirror configured:
ci/sbt-mirror/with-mirror.sh make -f ci/Makefile build
- Token stays IN-PROCESS (exported to the child build only); no token is written to
a file that gets passed around. The one transient file that must hold it (coursier
boot creds) plus the rendered sbt config are removed by an EXIT trap, pass or fail.
- gcloud auth already uses a throwaway CLOUDSDK_CONFIG dir, so the agent's own gcloud
account is never activated/replaced (it is not `gcloud auth login`).
- repositories now written workspace-local (.sbt-mirror-repositories) so we don't
clobber a shared ~/.sbt/repositories on the agent.
Pipeline Build stage is now a single line; no finally cleanup of auth files needed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
JRzen
approved these changes
Aug 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
DEVOPS-6131 — the delta-sharing sbt build fails on jenkins-eng with HTTP 429 from Maven Central (
repo1.maven.org). Central's Cloudflare front-end rate-limits jenkins-eng's shared egress IP, so sbt cannot download its own launcher (org.scala-sbt:sbt:1.9.9), plugins, or dependencies. Same root cause as DEVOPS-6083 (Maven), but via sbt.Fix
This is the sbt analog of the
mirrorMavenCentralshared step. sbt doesn't read Maven'ssettings.xml, so we configure sbt's own resolution to go through the virtana-zing Artifact Registry Maven proxy (us-maven.pkg.dev/zing-registry-188222/virtana-zing), authenticated with a short-lived OAuth token minted fromgcr_push_key(SAzing-gcr-push, which hasartifactregistryread onzing-registry-188222).Before
make buildinci/Jenkinsfile(thepull-requestpipeline):~/.sbt/repositories→maven-centralpoints at the mirror~/.config/coursier/credentials.properties→ authenticates the launcher (boot) resolutioncredentials.sbt(build) +project/credentials.sbt(meta) → authenticate library and plugin resolution (lm-coursier only honors sbt's nativecredentials, not the coursier file/env)sbt-launch.jarthrough the mirror (bearer header; the wrapper's barecurlcan't auth)-Dsbt.override.build.repos=trueThe token is minted in a throwaway
CLOUDSDK_CONFIG(agent identity untouched) and never printed (set +x); the coursier properties file is removed in the finally block.Verification
Proven green end-to-end on a trimmed test clone (
micro-services/delta-sharing/rbak-test-build): 0429, 0unauthorized, 0 token leaks,Image built: deltaio/delta-sharing-server:1.3.11-SNAPSHOT. This PR's ownpull-requestbuild exercises the change directly.Follow-up
The
buildjob (inline pipeline) needs the same block — handled separately.🤖 Generated with Claude Code