11name : ' Authenticate for JFrog'
22description : ' Authenticate with JFrog using OIDC based on the GitHub repository.'
3+ # Some things to note:
4+ # - Run this _after_ installing any tools that need to use JFrog; auth is configured for all the (supported) tools that
5+ # it detects.
6+ # - Where possible we avoid exposing tokens in environment variables, preferring to write them into files instead.
7+ # (Tokens in environment variables tend to be more exposed and easier to leak than those written into files.)
8+ #
9+ # TODO: Factor out into an external action, once releases are allowed.
310outputs :
411 jfrog-access-token :
512 description : " Access token for JFrog"
@@ -11,36 +18,165 @@ runs:
1118 name : Authenticate against JFrog
1219 shell : bash
1320 run : |
21+ if [[ -z "${ACTIONS_ID_TOKEN_REQUEST_URL}" ]] || [[ -z "${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" ]]
22+ then
23+ printf '::error::%s\n' 'This action uses OIDC: job must have "id-token: write" permission'
24+ exit 1
25+ fi
1426 "${GITHUB_ACTION_PATH}/jfrog-auth" "${ACTIONS_ID_TOKEN_REQUEST_URL}" "${ACTIONS_ID_TOKEN_REQUEST_TOKEN}"
27+
1528 - id : detect-cmds
16- name : Detecting python package/project managers.
29+ name : Detecting package/project managers.
1730 shell : bash
1831 run : |
19- for cmd in pip3 uv
32+ for cmd in bun coursier mvn npm pip3 sbt uv
2033 do
21- command -v "${cmd}" > /dev/null && found=true || found=false
22- printf '::debug::%s\n' "Found ${cmd}: ${found}"
23- printf '%s=%s\n' "command_${cmd}" "${found}" >> "${GITHUB_OUTPUT}"
34+ command -v "${cmd}" > /dev/null && found=true || found=false
35+ printf '::debug::%s\n' "Found ${cmd}: ${found}"
36+ printf '%s=%s\n' "command_${cmd}" "${found}" >> "${GITHUB_OUTPUT}"
2437 done
25- - name : Configure pip for JFrog
26- if : " ${{ steps.detect-cmds.outputs.command_pip3 == 'true' }}"
38+
39+ - name : Configure bun for JFrog
40+ if : " ${{ steps.detect-cmds.outputs.command_bun == 'true' }}"
41+ shell : bash
42+ env :
43+ JFROG_ACCESS_TOKEN : " ${{ steps.jfrog-auth.outputs.jfrog-access-token }}"
44+ run : |
45+ umask 077
46+ cat > ~/.bunfig.toml << 'EOF'
47+ [install]
48+ registry = { url = "https://databricks.jfrog.io/artifactory/api/npm/db-npm/", token = "$jfrog_access_token" }
49+ EOF
50+ cat > "${RUNNER_TEMP}/.bun.env" << EOF
51+ # Environment variables loaded by bun.
52+ jfrog_access_token='${JFROG_ACCESS_TOKEN}'
53+ EOF
54+ printf '%s=%s\n' 'BUN_OPTIONS' "--env-file=${RUNNER_TEMP}/.bun.env" >> "${GITHUB_ENV}"
55+ printf '::debug::%s\n' 'Configured JFrog access for bun.'
56+ # There are currently the following issues with JFrog:
57+ # - The default set of CAs doesn't seem to cover the ones used by our JFrog instance.
58+ # - The JSON metadata returned for some NPM artefacts can be invalid JSON.
59+ printf '::warning::%s\n' 'JFrog has compatibility issues with bun; it will probably not work.'
60+
61+ - name : Configure coursier for JFrog
62+ # Note: SBT bootstrapping uses Coursier internally.
63+ if : " ${{ steps.detect-cmds.outputs.command_coursier == 'true' ||
64+ steps.detect-cmds.outputs.command_sbt == 'true' }}"
65+ shell : bash
66+ env :
67+ JFROG_ACCESS_TOKEN : " ${{ steps.jfrog-auth.outputs.jfrog-access-token }}"
68+ run : |
69+ umask 077
70+ cat > "${RUNNER_TEMP}/.coursier-credentials.properties" << EOF
71+ jfrog.host=databricks.jfrog.io
72+ jfrog.realm=Artifactory Realm
73+ jfrog.username=gha-service-account
74+ jfrog.password=${JFROG_ACCESS_TOKEN}
75+ EOF
76+ printf '%s=%s\n' 'COURSIER_CREDENTIALS' "${RUNNER_TEMP}/.coursier-credentials.properties" >> "${GITHUB_ENV}"
77+ printf '::debug::%s\n' 'Configured JFrog access for Coursier.'
78+
79+ - name : Configure Maven for JFrog
80+ if : " ${{ steps.detect-cmds.outputs.command_mvn == 'true' }}"
81+ shell : bash
82+ env :
83+ JFROG_ACCESS_TOKEN : " ${{ steps.jfrog-auth.outputs.jfrog-access-token }}"
84+ run : |
85+ umask 077
86+ mkdir -p ~/.m2
87+ cat > ~/.m2/settings.xml << EOF
88+ <settings>
89+ <mirrors>
90+ <mirror>
91+ <id>jfrog-central</id>
92+ <mirrorOf>*</mirrorOf>
93+ <url>https://databricks.jfrog.io/artifactory/db-maven/</url>
94+ </mirror>
95+ </mirrors>
96+ <servers>
97+ <server>
98+ <id>jfrog-central</id>
99+ <username>gha-service-account</username>
100+ <password>${JFROG_ACCESS_TOKEN}</password>
101+ </server>
102+ </servers>
103+ </settings>
104+ EOF
105+ printf '::debug::%s\n' 'Configured JFrog access for maven.'
106+
107+ - name : Configure netrc for JFrog
108+ if : " ${{ steps.detect-cmds.outputs.command_pip3 == 'true' ||
109+ steps.detect-cmds.outputs.command_uv == 'true' }}"
27110 shell : bash
28111 env :
29112 JFROG_ACCESS_TOKEN : " ${{ steps.jfrog-auth.outputs.jfrog-access-token }}"
30113 run : |
31114 umask 077
32- cat > "$RUNNER_TEMP/.pip.conf" <<EOF
115+ cat > "${RUNNER_TEMP}/.netrc" << EOF
116+ machine databricks.jfrog.io
117+ login gha-service-account
118+ password ${JFROG_ACCESS_TOKEN}
119+ EOF
120+ printf '%s=%s\n' 'NETRC' "${RUNNER_TEMP}/.netrc" >> "${GITHUB_ENV}"
121+
122+ - name : Configure npm/yarn (classic) for JFrog
123+ if : " ${{ steps.detect-cmds.outputs.command_npm == 'true' }}"
124+ shell : bash
125+ env :
126+ JFROG_ACCESS_TOKEN : " ${{ steps.jfrog-auth.outputs.jfrog-access-token }}"
127+ run : |
128+ umask 077
129+ cat > ~/.npmrc << EOF
130+ registry=https://databricks.jfrog.io/artifactory/api/npm/db-npm/
131+ always-auth=true
132+ ignore-scripts=true
133+ //databricks.jfrog.io/artifactory/api/npm/db-npm/:_authToken=${JFROG_ACCESS_TOKEN}
134+ EOF
135+ printf '::debug::%s\n' 'Configured JFrog access for npm/yarn (classic).'
136+
137+ - name : Configure pip for JFrog
138+ if : " ${{ steps.detect-cmds.outputs.command_pip3 == 'true' }}"
139+ shell : bash
140+ run : |
141+ cat > "${RUNNER_TEMP}/.pip.conf" << 'EOF'
33142 [global]
34- index-url = https://gha-service-account:${JFROG_ACCESS_TOKEN}@ databricks.jfrog.io/artifactory/api/pypi/db-pypi/simple
143+ index-url = https://databricks.jfrog.io/artifactory/api/pypi/db-pypi/simple
35144 EOF
36145 printf '%s=%s\n' 'PIP_CONFIG_FILE' "${RUNNER_TEMP}/.pip.conf" >> "${GITHUB_ENV}"
146+ printf '::debug::%s\n' 'Configured JFrog access for pip.'
147+
148+ - name : Configure sbt for JFrog
149+ if : " ${{ steps.detect-cmds.outputs.command_sbt == 'true' }}"
150+ shell : bash
151+ env :
152+ JFROG_ACCESS_TOKEN : " ${{ steps.jfrog-auth.outputs.jfrog-access-token }}"
153+ run : |
154+ umask 077
155+ mkdir -p ~/.sbt/1.0
156+ cat > ~/.sbt/repositories << 'EOF'
157+ [repositories]
158+ local
159+ databricks-jfrog: https://databricks.jfrog.io/artifactory/db-maven/
160+ EOF
161+
162+ cat > "${RUNNER_TEMP}/.sbt.credentials" << EOF
163+ realm=Artifactory Realm
164+ host=databricks.jfrog.io
165+ user=gha-service-account
166+ password=${JFROG_ACCESS_TOKEN}
167+ EOF
168+
169+ cat > ~/.sbt/1.0/global.sbt << 'EOF'
170+ credentials += Credentials(file(sys.env("RUNNER_TEMP")) / ".sbt.credentials")
171+ EOF
172+ printf '::debug::%s\n' 'Configured JFrog access for SBT.'
173+
37174 - name : Configure uv for JFrog
38175 if : " ${{ steps.detect-cmds.outputs.command_uv == 'true' }}"
39176 shell : bash
40177 env :
41- JFROG_ACCESS_TOKEN : " ${{ steps.jfrog-auth.outputs.jfrog-access-token }}"
42178 UV_INDEX_URL : ' https://databricks.jfrog.io/artifactory/api/pypi/db-pypi/simple'
43179 run : |
44- uv auth login "${UV_INDEX_URL}" --username gha-service-account --password "${JFROG_ACCESS_TOKEN }"
45- printf " %s=%s\n" 'UV_INDEX_URL' "${UV_INDEX_URL}" >> "${GITHUB_ENV}"
46- printf "%s=%s\n" 'UV_FROZEN' '1' >> "${GITHUB_ENV}"
180+ printf '%s=%s\n' 'UV_INDEX_URL' "${UV_INDEX_URL}" >> "${GITHUB_ENV }"
181+ printf ' %s=%s\n' 'UV_FROZEN' '1' >> "${GITHUB_ENV}"
182+ printf '::debug::%s\n' 'Configured JFrog access for uv.'
0 commit comments