From a2a996a3b43f8aceb42d20c10cd3f36b8f07c39b Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Thu, 2 Apr 2026 15:17:16 +0200 Subject: [PATCH 1/7] Add shared setup-jfrog composite action Replace the jfrog/setup-jfrog-cli third-party action and jf CLI commands with a custom composite action that exchanges a GitHub OIDC token for a JFrog access token and configures Go and Python package managers to use the JFrog Artifactory proxy. Co-authored-by: Isaac --- .../setup-build-environment/action.yml | 17 +---- .github/actions/setup-jfrog/action.yml | 64 +++++++++++++++++++ 2 files changed, 66 insertions(+), 15 deletions(-) create mode 100644 .github/actions/setup-jfrog/action.yml diff --git a/.github/actions/setup-build-environment/action.yml b/.github/actions/setup-build-environment/action.yml index 753315a89d..60f42b1d8e 100644 --- a/.github/actions/setup-build-environment/action.yml +++ b/.github/actions/setup-build-environment/action.yml @@ -12,13 +12,8 @@ runs: - name: Checkout repository and submodules uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - name: Setup JFrog CLI with OIDC - if: runner.os != 'macOS' - uses: jfrog/setup-jfrog-cli@279b1f629f43dd5bc658d8361ac4802a7ef8d2d5 # v4.9.1 - env: - JF_URL: https://databricks.jfrog.io - with: - oidc-provider-name: github-actions + - name: Setup JFrog + uses: ./.github/actions/setup-jfrog - name: Create cache identifier run: echo "${{ inputs.cache-key }}" > cache.txt @@ -32,14 +27,6 @@ runs: go.sum cache.txt - - name: Download Go modules via JFrog - if: runner.os != 'macOS' - shell: bash - run: | - jf goc --repo-resolve=db-golang - jf go mod download - jf go mod download -modfile=tools/go.mod - - name: Setup Python uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: diff --git a/.github/actions/setup-jfrog/action.yml b/.github/actions/setup-jfrog/action.yml new file mode 100644 index 0000000000..58ca3bf9ed --- /dev/null +++ b/.github/actions/setup-jfrog/action.yml @@ -0,0 +1,64 @@ +name: 'Setup JFrog' +description: >- + Exchange a GitHub OIDC token for a JFrog access token and configure + Go and Python package managers to use the JFrog Artifactory proxy. + Requires the calling job to have "permissions: id-token: write". + +runs: + using: 'composite' + steps: + - name: Get JFrog OIDC token + shell: bash + run: | + set -euo pipefail + + # Verify that the job has id-token: write permission. + if [ -z "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" ] || [ -z "${ACTIONS_ID_TOKEN_REQUEST_TOKEN:-}" ]; then + echo "::error::OIDC token request URL/token not available. Does this job have 'permissions: id-token: write'?" + exit 1 + fi + + # Exchange GitHub OIDC token for JFrog access token. + ID_TOKEN=$(curl -sLS \ + -H "User-Agent: actions/oidc-client" \ + -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \ + "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=jfrog-github" | jq -r .value) + echo "::add-mask::${ID_TOKEN}" + + if [ -z "$ID_TOKEN" ] || [ "$ID_TOKEN" = "null" ]; then + echo "::error::Failed to obtain GitHub OIDC token." + exit 1 + fi + + ACCESS_TOKEN=$(curl -sLS -XPOST -H "Content-Type: application/json" \ + "https://databricks.jfrog.io/access/api/v1/oidc/token" \ + -d "{\"grant_type\": \"urn:ietf:params:oauth:grant-type:token-exchange\", \"subject_token_type\":\"urn:ietf:params:oauth:token-type:id_token\", \"subject_token\": \"${ID_TOKEN}\", \"provider_name\": \"github-actions\"}" | jq -r .access_token) + echo "::add-mask::${ACCESS_TOKEN}" + + if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then + echo "::error::Failed to exchange GitHub OIDC token for JFrog access token." + exit 1 + fi + + echo "JFROG_ACCESS_TOKEN=${ACCESS_TOKEN}" >> "$GITHUB_ENV" + + - name: Configure Go to use JFrog proxy + shell: bash + run: | + set -euo pipefail + echo "GOPROXY=https://databricks.jfrog.io/artifactory/api/go/db-golang,direct" >> "$GITHUB_ENV" + echo "GONOSUMDB=*" >> "$GITHUB_ENV" + cat > ~/.netrc <> "$GITHUB_ENV" + echo "PIP_INDEX_URL=https://gha-service-account:${JFROG_ACCESS_TOKEN}@databricks.jfrog.io/artifactory/api/pypi/db-pypi/simple" >> "$GITHUB_ENV" From 6942745ee92976c7bdeb0319c131a110ce7be46d Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Thu, 2 Apr 2026 15:31:04 +0200 Subject: [PATCH 2/7] Use URL-embedded credentials for Go proxy instead of .netrc The JFrog Go proxy returns 403 with .netrc basic auth. Embed credentials directly in the GOPROXY URL, matching the pattern already used for Python (UV_INDEX_URL, PIP_INDEX_URL). Co-authored-by: Isaac --- .github/actions/setup-jfrog/action.yml | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/.github/actions/setup-jfrog/action.yml b/.github/actions/setup-jfrog/action.yml index 58ca3bf9ed..def90a4b2e 100644 --- a/.github/actions/setup-jfrog/action.yml +++ b/.github/actions/setup-jfrog/action.yml @@ -42,23 +42,13 @@ runs: echo "JFROG_ACCESS_TOKEN=${ACCESS_TOKEN}" >> "$GITHUB_ENV" - - name: Configure Go to use JFrog proxy + - name: Configure Go and Python to use JFrog proxy shell: bash run: | set -euo pipefail - echo "GOPROXY=https://databricks.jfrog.io/artifactory/api/go/db-golang,direct" >> "$GITHUB_ENV" + CREDS="gha-service-account:${JFROG_ACCESS_TOKEN}" + echo "::add-mask::${CREDS}" + echo "GOPROXY=https://${CREDS}@databricks.jfrog.io/artifactory/api/go/db-golang,direct" >> "$GITHUB_ENV" echo "GONOSUMDB=*" >> "$GITHUB_ENV" - cat > ~/.netrc <> "$GITHUB_ENV" - echo "PIP_INDEX_URL=https://gha-service-account:${JFROG_ACCESS_TOKEN}@databricks.jfrog.io/artifactory/api/pypi/db-pypi/simple" >> "$GITHUB_ENV" + echo "UV_INDEX_URL=https://${CREDS}@databricks.jfrog.io/artifactory/api/pypi/db-pypi/simple" >> "$GITHUB_ENV" + echo "PIP_INDEX_URL=https://${CREDS}@databricks.jfrog.io/artifactory/api/pypi/db-pypi/simple" >> "$GITHUB_ENV" From 8807a9a59b50dd9c48abf117ff70acdf5c03c647 Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Thu, 2 Apr 2026 15:39:56 +0200 Subject: [PATCH 3/7] Add authenticated ping check after JFrog token exchange Co-authored-by: Isaac --- .github/actions/setup-jfrog/action.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/actions/setup-jfrog/action.yml b/.github/actions/setup-jfrog/action.yml index def90a4b2e..e3012c3bc2 100644 --- a/.github/actions/setup-jfrog/action.yml +++ b/.github/actions/setup-jfrog/action.yml @@ -40,6 +40,15 @@ runs: exit 1 fi + # Verify the token works. + HTTP_STATUS=$(curl -sL -o /dev/null -w "%{http_code}" \ + -H "Authorization: Bearer ${ACCESS_TOKEN}" \ + "https://databricks.jfrog.io/artifactory/api/system/version") + if [ "$HTTP_STATUS" != "200" ]; then + echo "::error::JFrog auth check failed (HTTP ${HTTP_STATUS})." + exit 1 + fi + echo "JFROG_ACCESS_TOKEN=${ACCESS_TOKEN}" >> "$GITHUB_ENV" - name: Configure Go and Python to use JFrog proxy From ad91e76edb52610d940dd4aa990521130f9e11fd Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Thu, 2 Apr 2026 15:52:39 +0200 Subject: [PATCH 4/7] Add Go proxy smoke test to setup-jfrog action Co-authored-by: Isaac --- .github/actions/setup-jfrog/action.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/actions/setup-jfrog/action.yml b/.github/actions/setup-jfrog/action.yml index e3012c3bc2..9e275c167d 100644 --- a/.github/actions/setup-jfrog/action.yml +++ b/.github/actions/setup-jfrog/action.yml @@ -61,3 +61,20 @@ runs: echo "GONOSUMDB=*" >> "$GITHUB_ENV" echo "UV_INDEX_URL=https://${CREDS}@databricks.jfrog.io/artifactory/api/pypi/db-pypi/simple" >> "$GITHUB_ENV" echo "PIP_INDEX_URL=https://${CREDS}@databricks.jfrog.io/artifactory/api/pypi/db-pypi/simple" >> "$GITHUB_ENV" + + - name: Verify Go proxy access + shell: bash + run: | + set -euo pipefail + BASE="https://databricks.jfrog.io/artifactory/api/go/db-golang" + AUTH="gha-service-account:${JFROG_ACCESS_TOKEN}" + # Fetch .info (metadata) and .zip (artifact) for the SDK to compare. + curl -sL -u "${AUTH}" -w "\nHTTP %{http_code}\n" \ + "${BASE}/github.com/databricks/databricks-sdk-go/@v/v0.126.0.info" + curl -sL -o /dev/null -u "${AUTH}" -w "HTTP %{http_code}\n" \ + "${BASE}/github.com/databricks/databricks-sdk-go/@v/v0.126.0.zip" + # Same for a known-good package. + curl -sL -u "${AUTH}" -w "\nHTTP %{http_code}\n" \ + "${BASE}/golang.org/x/sys/@v/v0.31.0.info" + curl -sL -o /dev/null -u "${AUTH}" -w "HTTP %{http_code}\n" \ + "${BASE}/golang.org/x/sys/@v/v0.31.0.zip" From 9cad3cd0d108e65924dc914a91a180623fbc8064 Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Thu, 2 Apr 2026 18:19:44 +0200 Subject: [PATCH 5/7] Remove smoke test step from setup-jfrog action Co-authored-by: Isaac --- .github/actions/setup-jfrog/action.yml | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/.github/actions/setup-jfrog/action.yml b/.github/actions/setup-jfrog/action.yml index 9e275c167d..e3012c3bc2 100644 --- a/.github/actions/setup-jfrog/action.yml +++ b/.github/actions/setup-jfrog/action.yml @@ -61,20 +61,3 @@ runs: echo "GONOSUMDB=*" >> "$GITHUB_ENV" echo "UV_INDEX_URL=https://${CREDS}@databricks.jfrog.io/artifactory/api/pypi/db-pypi/simple" >> "$GITHUB_ENV" echo "PIP_INDEX_URL=https://${CREDS}@databricks.jfrog.io/artifactory/api/pypi/db-pypi/simple" >> "$GITHUB_ENV" - - - name: Verify Go proxy access - shell: bash - run: | - set -euo pipefail - BASE="https://databricks.jfrog.io/artifactory/api/go/db-golang" - AUTH="gha-service-account:${JFROG_ACCESS_TOKEN}" - # Fetch .info (metadata) and .zip (artifact) for the SDK to compare. - curl -sL -u "${AUTH}" -w "\nHTTP %{http_code}\n" \ - "${BASE}/github.com/databricks/databricks-sdk-go/@v/v0.126.0.info" - curl -sL -o /dev/null -u "${AUTH}" -w "HTTP %{http_code}\n" \ - "${BASE}/github.com/databricks/databricks-sdk-go/@v/v0.126.0.zip" - # Same for a known-good package. - curl -sL -u "${AUTH}" -w "\nHTTP %{http_code}\n" \ - "${BASE}/golang.org/x/sys/@v/v0.31.0.info" - curl -sL -o /dev/null -u "${AUTH}" -w "HTTP %{http_code}\n" \ - "${BASE}/golang.org/x/sys/@v/v0.31.0.zip" From 6a33bec957ac0f6db247dacc18e677f03c9b1fc2 Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Thu, 2 Apr 2026 18:24:25 +0200 Subject: [PATCH 6/7] Fix yamlfmt: use |- block scalar to strip trailing newline Co-authored-by: Isaac --- .github/actions/setup-jfrog/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/setup-jfrog/action.yml b/.github/actions/setup-jfrog/action.yml index e3012c3bc2..8dca0725f1 100644 --- a/.github/actions/setup-jfrog/action.yml +++ b/.github/actions/setup-jfrog/action.yml @@ -53,7 +53,7 @@ runs: - name: Configure Go and Python to use JFrog proxy shell: bash - run: | + run: |- set -euo pipefail CREDS="gha-service-account:${JFROG_ACCESS_TOKEN}" echo "::add-mask::${CREDS}" From efdfdcd2b27df265e2ad2c180ab16cf0aa15832e Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Thu, 2 Apr 2026 19:12:45 +0200 Subject: [PATCH 7/7] Split Go and Python proxy config into separate steps Co-authored-by: Isaac --- .github/actions/setup-jfrog/action.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/actions/setup-jfrog/action.yml b/.github/actions/setup-jfrog/action.yml index 8dca0725f1..e34e98542c 100644 --- a/.github/actions/setup-jfrog/action.yml +++ b/.github/actions/setup-jfrog/action.yml @@ -51,7 +51,7 @@ runs: echo "JFROG_ACCESS_TOKEN=${ACCESS_TOKEN}" >> "$GITHUB_ENV" - - name: Configure Go and Python to use JFrog proxy + - name: Configure Go to use JFrog proxy shell: bash run: |- set -euo pipefail @@ -59,5 +59,12 @@ runs: echo "::add-mask::${CREDS}" echo "GOPROXY=https://${CREDS}@databricks.jfrog.io/artifactory/api/go/db-golang,direct" >> "$GITHUB_ENV" echo "GONOSUMDB=*" >> "$GITHUB_ENV" + + - name: Configure Python (uv/pip) to use JFrog proxy + shell: bash + run: |- + set -euo pipefail + CREDS="gha-service-account:${JFROG_ACCESS_TOKEN}" + echo "::add-mask::${CREDS}" echo "UV_INDEX_URL=https://${CREDS}@databricks.jfrog.io/artifactory/api/pypi/db-pypi/simple" >> "$GITHUB_ENV" echo "PIP_INDEX_URL=https://${CREDS}@databricks.jfrog.io/artifactory/api/pypi/db-pypi/simple" >> "$GITHUB_ENV"