Skip to content

Commit ad9eb35

Browse files
Move CI to Databricks protected runners with JFrog OIDC (#59)
Add .github/actions/setup-jfrog composite action for OIDC-based JFrog authentication (configures both pip and Poetry) Switch all workflow jobs from ubuntu-latest to databricks-protected-runner-group Replace third-party tisonkun/actions-dco action with inline bash script for DCO sign-off checking (matching databricks-sql-go pattern) Update actions/checkout to v4 and actions/setup-python to v5 Add id-token: write permission for JFrog OIDC token exchange
2 parents 349e581 + e7dc28b commit ad9eb35

5 files changed

Lines changed: 178 additions & 145 deletions

File tree

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Setup JFrog OIDC
2+
description: Obtain a JFrog access token via GitHub OIDC and configure pip to use JFrog PyPI proxy
3+
4+
runs:
5+
using: composite
6+
steps:
7+
- name: Get JFrog OIDC token
8+
shell: bash
9+
run: |
10+
set -euo pipefail
11+
ID_TOKEN=$(curl -sLS \
12+
-H "User-Agent: actions/oidc-client" \
13+
-H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
14+
"${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=jfrog-github" | jq .value | tr -d '"')
15+
echo "::add-mask::${ID_TOKEN}"
16+
ACCESS_TOKEN=$(curl -sLS -XPOST -H "Content-Type: application/json" \
17+
"https://databricks.jfrog.io/access/api/v1/oidc/token" \
18+
-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 .access_token | tr -d '"')
19+
echo "::add-mask::${ACCESS_TOKEN}"
20+
if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then
21+
echo "FAIL: Could not extract JFrog access token"
22+
exit 1
23+
fi
24+
echo "JFROG_ACCESS_TOKEN=${ACCESS_TOKEN}" >> "$GITHUB_ENV"
25+
echo "JFrog OIDC token obtained successfully"
26+
27+
- name: Configure pip
28+
shell: bash
29+
run: |
30+
set -euo pipefail
31+
echo "PIP_INDEX_URL=https://gha-service-account:${JFROG_ACCESS_TOKEN}@databricks.jfrog.io/artifactory/api/pypi/db-pypi/simple" >> "$GITHUB_ENV"
32+
echo "pip configured to use JFrog registry"
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
name: Setup Poetry with JFrog
2+
description: Install Poetry, configure JFrog as primary PyPI source, and install project dependencies
3+
4+
inputs:
5+
python-version:
6+
description: Python version to set up
7+
required: true
8+
install-args:
9+
description: Extra arguments for poetry install (e.g. --all-extras)
10+
required: false
11+
default: ""
12+
13+
runs:
14+
using: composite
15+
steps:
16+
- name: Setup JFrog
17+
uses: ./.github/actions/setup-jfrog
18+
19+
- name: Set up python ${{ inputs.python-version }}
20+
id: setup-python
21+
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
22+
with:
23+
python-version: ${{ inputs.python-version }}
24+
25+
- name: Install Poetry
26+
shell: bash
27+
run: |
28+
pip install poetry==2.2.1
29+
poetry config virtualenvs.create true
30+
poetry config virtualenvs.in-project true
31+
poetry config installer.parallel true
32+
33+
- name: Configure Poetry JFrog source
34+
shell: bash
35+
run: |
36+
poetry config repositories.jfrog https://databricks.jfrog.io/artifactory/api/pypi/db-pypi/simple
37+
poetry config http-basic.jfrog gha-service-account "${JFROG_ACCESS_TOKEN}"
38+
poetry source add --priority=primary jfrog https://databricks.jfrog.io/artifactory/api/pypi/db-pypi/simple
39+
poetry lock
40+
41+
- name: Load cached venv
42+
id: cached-poetry-dependencies
43+
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
44+
with:
45+
path: .venv
46+
key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ github.event.repository.name }}-${{ hashFiles('**/poetry.lock') }}
47+
48+
- name: Install dependencies
49+
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
50+
shell: bash
51+
run: poetry install --no-interaction --no-root
52+
53+
- name: Install library
54+
shell: bash
55+
run: poetry install --no-interaction ${{ inputs.install-args }}

.github/workflows/code-quality-checks.yml

Lines changed: 15 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -10,112 +10,41 @@ on:
1010

1111
permissions:
1212
contents: read
13+
id-token: write
1314

1415
jobs:
1516
check-linting:
16-
runs-on: ubuntu-latest
17+
runs-on:
18+
group: databricks-protected-runner-group
19+
labels: linux-ubuntu-latest
1720
strategy:
1821
matrix:
1922
python-version: [3.9, "3.10", "3.11", "3.12"]
2023
steps:
21-
#----------------------------------------------
22-
# check-out repo and set-up python
23-
#----------------------------------------------
2424
- name: Check out repository
25-
uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2
26-
- name: Set up python ${{ matrix.python-version }}
27-
id: setup-python
28-
uses: actions/setup-python@e9aba2c848f5ebd159c070c61ea2c4e2b122355e # v2
25+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
26+
- name: Setup Poetry
27+
uses: ./.github/actions/setup-poetry
2928
with:
3029
python-version: ${{ matrix.python-version }}
31-
#----------------------------------------------
32-
# ----- install & configure poetry -----
33-
#----------------------------------------------
34-
- name: Install Poetry
35-
uses: snok/install-poetry@76e04a911780d5b312d89783f7b1cd627778900a # v1
36-
with:
37-
version: "2.2.1"
38-
virtualenvs-create: true
39-
virtualenvs-in-project: true
40-
installer-parallel: true
41-
42-
#----------------------------------------------
43-
# load cached venv if cache exists
44-
#----------------------------------------------
45-
- name: Load cached venv
46-
id: cached-poetry-dependencies
47-
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
48-
with:
49-
path: .venv
50-
key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ github.event.repository.name }}-${{ hashFiles('**/poetry.lock') }}
51-
#----------------------------------------------
52-
# install dependencies if cache does not exist
53-
#----------------------------------------------
54-
- name: Install dependencies
55-
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
56-
run: poetry install --no-interaction --no-root
57-
#----------------------------------------------
58-
# install your root project, if required
59-
#----------------------------------------------
60-
- name: Install library
61-
run: poetry install --no-interaction
62-
#----------------------------------------------
63-
# black the code
64-
#----------------------------------------------
6530
- name: Black
6631
run: poetry run black --check src
6732

6833
check-types:
69-
runs-on: ubuntu-latest
34+
runs-on:
35+
group: databricks-protected-runner-group
36+
labels: linux-ubuntu-latest
7037
strategy:
7138
matrix:
7239
python-version: [3.9, "3.10", "3.11", "3.12"]
7340
steps:
74-
#----------------------------------------------
75-
# check-out repo and set-up python
76-
#----------------------------------------------
7741
- name: Check out repository
78-
uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2
79-
- name: Set up python ${{ matrix.python-version }}
80-
id: setup-python
81-
uses: actions/setup-python@e9aba2c848f5ebd159c070c61ea2c4e2b122355e # v2
42+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
43+
- name: Setup Poetry
44+
uses: ./.github/actions/setup-poetry
8245
with:
8346
python-version: ${{ matrix.python-version }}
84-
#----------------------------------------------
85-
# ----- install & configure poetry -----
86-
#----------------------------------------------
87-
- name: Install Poetry
88-
uses: snok/install-poetry@76e04a911780d5b312d89783f7b1cd627778900a # v1
89-
with:
90-
version: "2.2.1"
91-
virtualenvs-create: true
92-
virtualenvs-in-project: true
93-
installer-parallel: true
94-
95-
#----------------------------------------------
96-
# load cached venv if cache exists
97-
#----------------------------------------------
98-
- name: Load cached venv
99-
id: cached-poetry-dependencies
100-
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
101-
with:
102-
path: .venv
103-
key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ github.event.repository.name }}-${{ hashFiles('**/poetry.lock') }}
104-
#----------------------------------------------
105-
# install dependencies if cache does not exist
106-
#----------------------------------------------
107-
- name: Install dependencies
108-
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
109-
run: poetry install --no-interaction --no-root
110-
#----------------------------------------------
111-
# install your root project, if required
112-
#----------------------------------------------
113-
- name: Install library
114-
run: poetry install --no-interaction
115-
#----------------------------------------------
116-
# mypy the code
117-
#----------------------------------------------
11847
- name: Mypy
11948
run: |
120-
mkdir .mypy_cache # Workaround for bad error message "error: --install-types failed (no mypy cache directory)"; see https://github.com/python/mypy/issues/10768#issuecomment-2178450153
121-
poetry run mypy --install-types --non-interactive src
49+
mkdir .mypy_cache
50+
poetry run mypy --install-types --non-interactive src

.github/workflows/dco-check.yml

Lines changed: 68 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,74 @@
11
name: DCO Check
22

3-
on: [pull_request]
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened]
6+
branches: [main]
47

58
permissions:
6-
contents: read
7-
pull-requests: write
9+
contents: read
810

911
jobs:
10-
check:
11-
runs-on: ubuntu-latest
12-
steps:
13-
- name: Check for DCO
14-
id: dco-check
15-
uses: tisonkun/actions-dco@6d1f8a197db1b04df1769707b46b9366b1eca902 # v1.1
16-
- name: Comment about DCO status
17-
uses: actions/github-script@00f12e3e20659f42342b1c0226afda7f7c042325 # v6
18-
if: ${{ failure() }}
19-
with:
20-
script: |
21-
github.rest.issues.createComment({
22-
issue_number: context.issue.number,
23-
owner: context.repo.owner,
24-
repo: context.repo.repo,
25-
body: `Thanks for your contribution! To satisfy the DCO policy in our \
26-
[contributing guide](https://github.com/databricks/databricks-sqlalchemy/blob/main/CONTRIBUTING.md) \
27-
every commit message must include a sign-off message. One or more of your commits is missing this message. \
28-
You can reword previous commit messages with an interactive rebase (\`git rebase -i main\`).`
29-
})
12+
dco-check:
13+
runs-on:
14+
group: databricks-protected-runner-group
15+
labels: linux-ubuntu-latest
16+
name: Check DCO Sign-off
17+
steps:
18+
- name: Checkout
19+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
20+
with:
21+
fetch-depth: 0
22+
23+
- name: Check DCO Sign-off
24+
env:
25+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
26+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
27+
run: |
28+
#!/bin/bash
29+
set -e
30+
31+
echo "Checking commits from $BASE_SHA to $HEAD_SHA"
32+
33+
COMMITS=$(git rev-list --no-merges "$BASE_SHA..$HEAD_SHA")
34+
35+
if [ -z "$COMMITS" ]; then
36+
echo "No commits found in this PR"
37+
exit 0
38+
fi
39+
40+
FAILED_COMMITS=()
41+
42+
for commit in $COMMITS; do
43+
echo "Checking commit: $commit"
44+
COMMIT_MSG=$(git log --format=%B -n 1 "$commit")
45+
if echo "$COMMIT_MSG" | grep -q "^Signed-off-by: "; then
46+
echo " Commit $commit has DCO sign-off"
47+
else
48+
echo " Commit $commit is missing DCO sign-off"
49+
FAILED_COMMITS+=("$commit")
50+
fi
51+
done
52+
53+
if [ ${#FAILED_COMMITS[@]} -ne 0 ]; then
54+
echo ""
55+
echo "DCO Check Failed!"
56+
echo "The following commits are missing the required 'Signed-off-by' line:"
57+
for commit in "${FAILED_COMMITS[@]}"; do
58+
echo " - $commit: $(git log --format=%s -n 1 "$commit")"
59+
done
60+
echo ""
61+
echo "To fix this, you need to sign off your commits. You can:"
62+
echo "1. Add sign-off to new commits: git commit -s -m 'Your commit message'"
63+
echo "2. Amend existing commits: git commit --amend --signoff"
64+
echo "3. For multiple commits, use: git rebase --signoff HEAD~N (where N is the number of commits)"
65+
echo ""
66+
echo "The sign-off should be in the format:"
67+
echo "Signed-off-by: Your Name <your.email@example.com>"
68+
echo ""
69+
echo "For more details, see CONTRIBUTING.md"
70+
exit 1
71+
else
72+
echo ""
73+
echo "All commits have proper DCO sign-off!"
74+
fi

.github/workflows/integration.yml

Lines changed: 8 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@ on:
99

1010
permissions:
1111
contents: read
12+
id-token: write
1213

1314
jobs:
1415
run-e2e-tests:
15-
runs-on: ubuntu-latest
16+
runs-on:
17+
group: databricks-protected-runner-group
18+
labels: linux-ubuntu-latest
1619
environment: azure-prod
1720
env:
1821
DATABRICKS_SERVER_HOSTNAME: ${{ secrets.DATABRICKS_HOST }}
@@ -22,43 +25,12 @@ jobs:
2225
DATABRICKS_SCHEMA: ${{ secrets.SQLALCHEMY_SCHEMA }}
2326
DATABRICKS_USER: ${{ secrets.TEST_PECO_SP_ID }}
2427
steps:
25-
#----------------------------------------------
26-
# check-out repo and set-up python
27-
#----------------------------------------------
2828
- name: Check out repository
29-
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3
30-
- name: Set up python
31-
id: setup-python
32-
uses: actions/setup-python@7f4fc3e22c37d6ff65e88745f38bd3157c663f7c # v4
29+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
30+
- name: Setup Poetry
31+
uses: ./.github/actions/setup-poetry
3332
with:
3433
python-version: "3.10"
35-
#----------------------------------------------
36-
# ----- install & configure poetry -----
37-
#----------------------------------------------
38-
- name: Install Poetry
39-
uses: snok/install-poetry@76e04a911780d5b312d89783f7b1cd627778900a # v1
40-
with:
41-
version: "2.2.1"
42-
virtualenvs-create: true
43-
virtualenvs-in-project: true
44-
installer-parallel: true
45-
46-
#----------------------------------------------
47-
# load cached venv if cache exists
48-
#----------------------------------------------
49-
- name: Load cached venv
50-
id: cached-poetry-dependencies
51-
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
52-
with:
53-
path: .venv
54-
key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ github.event.repository.name }}-${{ hashFiles('**/poetry.lock') }}
55-
#----------------------------------------------
56-
# install dependencies if cache does not exist
57-
#----------------------------------------------
58-
- name: Install dependencies
59-
run: poetry install --no-interaction --all-extras
60-
#----------------------------------------------
61-
# run test suite
62-
#----------------------------------------------
34+
install-args: "--all-extras"
6335
- name: Run SQL Alchemy tests
6436
run: poetry run python -m pytest tests/test_local

0 commit comments

Comments
 (0)