Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
83691c1
Migrates the reconcile integration tests to Databricks away from loca…
m-abulazm May 4, 2026
f9d7cbe
Implement minimum support for maven mirrors during `install-transpile…
asnare May 5, 2026
0ba44e6
Fix test-profiler-connection to exit non-zero on failure (#2342)
sundarshankar89 May 6, 2026
ae2c29b
Add foreign connections as reconcile source (#2362)
m-abulazm May 6, 2026
1c32cbb
Fix project packaging for source and wheel distributions (#2419)
asnare May 8, 2026
37bb1b5
Add SQL Server Profiler (#2151)
goodwillpunning May 11, 2026
2f00757
Fix reconcile schema fetch failure on Foreign Catalogs (Lakehouse Fed…
moomindani May 11, 2026
ec57e79
Add Redshift connector to Recon (#2339)
bishwajit-db May 11, 2026
535c390
Revamp documentation (#2365)
gueniai May 12, 2026
a8ff8a2
cleanup up leftovers in reconcile and add oracle test (#2433)
m-abulazm May 12, 2026
e50dae5
Lockfile linting and dependency updates (#2434)
asnare May 13, 2026
a2fcbaf
Mark non-deployment environments in GHA as such (#2443)
asnare May 13, 2026
4315feb
More lockfile linting and dependency updates (#2442)
asnare May 13, 2026
8178513
Bump version to 0.13.0 (#2444)
gueniai May 13, 2026
db32752
feat: add --switch-config-path parameter to llm-transpile command (#2…
hiroyukinakazato-db May 14, 2026
7a816c6
create dedicated test cluster for recon e2e tests (#2453)
m-abulazm May 18, 2026
f7bd033
Update project to support Python 3.14 (#2333)
asnare May 19, 2026
88310cf
implement DatabaseConnector#health_check() (#2421)
m-abulazm May 19, 2026
f18285b
[Feat/2093] Collapse DuckDB write helpers and move shared profiler in…
dgomez04 May 20, 2026
bafbefe
Redshift Profiler PR1: Redshift connection and credential support in …
ysmx-github May 20, 2026
4dc10ba
Document PyPI and Maven mirrors during installation (#2457)
asnare May 20, 2026
2482622
Documentation: `node` upgrade, 25 → 26 (#2451)
asnare May 20, 2026
1b493f3
Remove explicit dependency: `cryptography` (#2458)
asnare May 20, 2026
921a066
Bump black from 25.9.0 to 26.3.1 (#2437)
dependabot[bot] May 21, 2026
dc60917
legacy sql dw profiler (#2441)
m-abulazm May 21, 2026
014654f
feature/oracle_profiler (#2187)
lolo115 May 22, 2026
3499659
Standardizes the reconcile sampling query across all dialects (#2465)
m-abulazm May 28, 2026
c1f46fc
Refactor SQL Server profiler to use `DatabaseManager` and switch to S…
m-abulazm Jun 1, 2026
1e02597
Redshift Profiler PR2: Add Redshift assessment extract SQLs and valid…
ysmx-github Jun 1, 2026
90391f2
Add Snowflake profiler source with PAT auth + DuckDB extraction and T…
jneil17 Jun 2, 2026
16391f3
Pytest: quieter tests (#2454)
asnare Jun 2, 2026
0f96b23
Add Teradata support for Recon (#2456)
bishwajit-db Jun 3, 2026
40969c2
Fix version specification for `redshift-connector` (#2467)
asnare Jun 3, 2026
4132a18
Make profiler extract location user-configurable via --output-folder …
m-abulazm Jun 5, 2026
ebef31a
Add optional cli argument `cred_file_path` to `execute-database-profi…
m-abulazm Jun 5, 2026
9d852a2
Run profiler Python steps with the parent interpreter instead of per-…
dgomez04 Jun 8, 2026
1cd012b
add support for sql server trust server (#2498)
m-abulazm Jun 10, 2026
fbff42d
add auto-discovery of source/target tables for reconcile config (#2392)
m-abulazm Jun 10, 2026
170ae70
Add Snowflake rate_sheet extract for TCO rate/tier (#2499)
jneil17 Jun 11, 2026
5af9696
Add BigQuery profiler (continuation of #2445) (#2472)
take60 Jun 11, 2026
f948841
Redshift Profiler PR5: Serverless storage bug fix (#2501)
ysmx-github Jun 12, 2026
1e40af6
log source system in recon commands (#2504)
m-abulazm Jun 12, 2026
74e51b1
Redshift Profiler PR3: CLI, configs and tests (#2306)
ysmx-github Jun 12, 2026
f62a7b2
Redshift Profiler PR4: docs (#2408)
ysmx-github Jun 12, 2026
e969dff
Bump version to 0.14.0
gueniai Jun 12, 2026
bbc2333
Update java requirement: we now need Java 21 (#2507)
asnare Jun 15, 2026
0a5bc31
Update expected SQL assertion (#2516)
m-abulazm Jun 22, 2026
f20fe11
capture variant in execute-profiler (#2511)
m-abulazm Jun 24, 2026
980e85f
remove profiler dashboard (#2524)
m-abulazm Jun 24, 2026
20909f0
implement missing bigquery test connection and cleanup profiler confi…
m-abulazm Jun 24, 2026
7ebd945
test(integration): use pytester ws fixture in reconcile integration t…
BesikiML Jun 24, 2026
5eb38d1
Adding feature to integrate Teradata profiler with Lakebridge (#2343)
dey-abhishek Jun 26, 2026
b44c607
Correct column order in `schemas.py` for tables and views in Synapse …
dgomez04 Jun 26, 2026
db0bfbc
[Snowflake Profiler] Exclude system databases from `automatic_cluster…
dgomez04 Jun 29, 2026
5b2c1db
feat(reconcile): materialize intermediate DataFrames during reconcile…
BesikiML Jun 30, 2026
27a27f6
[DEV] Refactor DatabaseConfig usages in reconcile runtime and tests (…
BesikiML Jun 30, 2026
f1b8edd
Update `lock-dependencies` to also scrub the registry used in CDN URL…
asnare Jul 1, 2026
d17feb0
Disable warning from google.api_core (#2538)
m-abulazm Jul 2, 2026
ffae39c
Add missing BigQuery profiler extract source (#2551)
m-abulazm Jul 3, 2026
55406fe
Add BigQuery as a reconcile source (#2527)
take60 Jul 6, 2026
d2fdae7
Add `WORKSPACE_NAME` to Synapse activity extract tables (#2549)
dgomez04 Jul 8, 2026
7f61051
Add multi-database profiling support for SQL Server (#2536)
m-abulazm Jul 13, 2026
78190e7
Support max_sample_size via sampling_options with engine-aware bounds…
ganeshdogiparthi-db Jul 16, 2026
c1fdb1f
use correct exit code on profiler error (#2571)
m-abulazm Jul 16, 2026
facd119
Fix Synapse profiler failures for empty SQL pools and serverless rout…
dgomez04 Jul 17, 2026
8ba21c1
Reduce Snowflake profiler output size by decoupling query metrics fro…
dgomez04 Jul 17, 2026
8041660
Bump version to 0.14.1
gueniai Jul 17, 2026
80a10be
Update changelog with latest releases details
gueniai Jul 17, 2026
f0c1a50
pass creds file path in BQ profiler (#2577)
m-abulazm Jul 21, 2026
25225cb
docs: overview and reconcile transform add missing info (#2579)
m-abulazm Jul 21, 2026
885c985
Fix profiler DuckDB `DECIMAL` overflow across all source systems. (#2…
dgomez04 Jul 21, 2026
b1bdc30
Upgrade Switch to 0.2.0 (#2582)
gueniai Jul 22, 2026
9fa750c
Add profiler pipeline partial-run contract for optional steps (#2555)
dgomez04 Jul 22, 2026
8ece801
Add desktop app installation flow (#2588)
gueniai Jul 22, 2026
db3499c
Bump version to 0.14.2 (#2589)
gueniai Jul 22, 2026
86b0b32
Small doc update (#2590)
gueniai Jul 22, 2026
d1466d5
Add Entra ID auth (SPN, AD password, Interactive) across MSSQL connec…
sundarshankar89 Jul 23, 2026
4dc2977
Make serverless compute the default for the deployed recon job (#2565)
take60 Jul 24, 2026
cd24783
Add Reconcile RCA dashboard (#2496)
m-abulazm Jul 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
18 changes: 9 additions & 9 deletions .build-constraints.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
hatchling==1.29.0 \
--hash=sha256:50af9343281f34785fab12da82e445ed987a6efb34fd8c2fc0f6e6630dbcc1b0 \
--hash=sha256:793c31816d952cee405b83488ce001c719f325d9cda69f1fc4cd750527640ea6
packaging==26.0 \
--hash=sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4 \
--hash=sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529
packaging==26.2 \
--hash=sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e \
--hash=sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661
# via hatchling
pathspec==1.0.4 \
--hash=sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645 \
--hash=sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723
pathspec==1.1.1 \
--hash=sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a \
--hash=sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189
# via hatchling
pluggy==1.6.0 \
--hash=sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3 \
Expand Down Expand Up @@ -62,7 +62,7 @@ tomli==2.4.1 ; python_full_version < '3.11' \
--hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \
--hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049
# via hatchling
trove-classifiers==2026.1.14.14 \
--hash=sha256:00492545a1402b09d4858605ba190ea33243d361e2b01c9c296ce06b5c3325f3 \
--hash=sha256:1f9553927f18d0513d8e5ff80ab8980b8202ce37ecae0e3274ed2ef11880e74d
trove-classifiers==2026.6.1.19 \
--hash=sha256:ab4c4ec93cc4a4e7815fa759906e05e6bb3f2fbd92ea0f897288c6a43efd15b3 \
--hash=sha256:c5132b4b61a829d11cfbd2d72e97f20a45ed6edb95e45c5efdeb5e00836b2745
# via hatchling
107 changes: 83 additions & 24 deletions .github/actions/jfrog-auth/action.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
name: 'Authenticate for JFrog'
description: 'Authenticate with JFrog using OIDC based on the GitHub repository.'
# Some things to note:
# - Run this _after_ installing any tools that need to use JFrog; auth is configured all the (supported) tools that it
# detects.
# - Run this _after_ installing any tools that need to use JFrog; auth is configured for all the (supported) tools that
# it detects.
# - Where possible we avoid exposing tokens in environment variables, preferring to write them into files instead.
# (Tokens in environment variables tend to be more exposed and easier to leak than those written into files.)
#
Expand All @@ -18,17 +18,22 @@ runs:
name: Authenticate against JFrog
shell: bash
run: |
if [[ -z "${ACTIONS_ID_TOKEN_REQUEST_URL}" ]] || [[ -z "${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" ]]
then
printf '::error::%s\n' 'This action uses OIDC: job must have "id-token: write" permission'
exit 1
fi
"${GITHUB_ACTION_PATH}/jfrog-auth" "${ACTIONS_ID_TOKEN_REQUEST_URL}" "${ACTIONS_ID_TOKEN_REQUEST_TOKEN}"

- id: detect-cmds
name: Detecting python package/project managers.
name: Detecting package/project managers.
shell: bash
run: |
for cmd in bun mvn npm pip3 uv
for cmd in bun coursier mvn npm pip3 sbt uv
do
command -v "${cmd}" > /dev/null && found=true || found=false
printf '::debug::%s\n' "Found ${cmd}: ${found}"
printf '%s=%s\n' "command_${cmd}" "${found}" >> "${GITHUB_OUTPUT}"
command -v "${cmd}" > /dev/null && found=true || found=false
printf '::debug::%s\n' "Found ${cmd}: ${found}"
printf '%s=%s\n' "command_${cmd}" "${found}" >> "${GITHUB_OUTPUT}"
done

- name: Configure bun for JFrog
Expand All @@ -38,7 +43,7 @@ runs:
JFROG_ACCESS_TOKEN: "${{ steps.jfrog-auth.outputs.jfrog-access-token }}"
run: |
umask 077
cat > ~/.bunfig.toml << EOF
cat > ~/.bunfig.toml << 'EOF'
[install]
registry = { url = "https://databricks.jfrog.io/artifactory/api/npm/db-npm/", token = "$jfrog_access_token" }
EOF
Expand All @@ -51,24 +56,28 @@ runs:
# There are currently the following issues with JFrog:
# - The default set of CAs doesn't seem to cover the ones used by our JFrog instance.
# - The JSON metadata returned for some NPM artefacts can be invalid JSON.
printf '::warning::%s\n' 'JFrog has compatibility issues with bun; it probably won't work.'
printf '::warning::%s\n' 'JFrog has compatibility issues with bun; it will probably not work.'

- name: Configure pip for JFrog
if: "${{ steps.detect-cmds.outputs.command_pip3 == 'true' }}"
- name: Configure coursier for JFrog
# Note: SBT bootstrapping uses Coursier internally.
if: "${{ steps.detect-cmds.outputs.command_coursier == 'true' ||
steps.detect-cmds.outputs.command_sbt == 'true' }}"
shell: bash
env:
JFROG_ACCESS_TOKEN: "${{ steps.jfrog-auth.outputs.jfrog-access-token }}"
run: |
umask 077
cat > "$RUNNER_TEMP/.pip.conf" <<EOF
[global]
index-url = https://gha-service-account:${JFROG_ACCESS_TOKEN}@databricks.jfrog.io/artifactory/api/pypi/db-pypi/simple
cat > "${RUNNER_TEMP}/.coursier-credentials.properties" << EOF
jfrog.host=databricks.jfrog.io
jfrog.realm=Artifactory Realm
jfrog.username=gha-service-account
jfrog.password=${JFROG_ACCESS_TOKEN}
EOF
printf '%s=%s\n' 'PIP_CONFIG_FILE' "${RUNNER_TEMP}/.pip.conf" >> "${GITHUB_ENV}"
printf '::debug::%s\n' 'Configured JFrog access for pip.'
printf '%s=%s\n' 'COURSIER_CREDENTIALS' "${RUNNER_TEMP}/.coursier-credentials.properties" >> "${GITHUB_ENV}"
printf '::debug::%s\n' 'Configured JFrog access for Coursier.'

- name: Configure Maven for JFrog
if: "${{ steps.detect-cmds.outputs.command_uv == 'true' }}"
if: "${{ steps.detect-cmds.outputs.command_mvn == 'true' }}"
shell: bash
env:
JFROG_ACCESS_TOKEN: "${{ steps.jfrog-auth.outputs.jfrog-access-token }}"
Expand All @@ -95,17 +104,20 @@ runs:
EOF
printf '::debug::%s\n' 'Configured JFrog access for maven.'

- name: Configure uv for JFrog
if: "${{ steps.detect-cmds.outputs.command_uv == 'true' }}"
- name: Configure netrc for JFrog
if: "${{ steps.detect-cmds.outputs.command_pip3 == 'true' ||
steps.detect-cmds.outputs.command_uv == 'true' }}"
shell: bash
env:
JFROG_ACCESS_TOKEN: "${{ steps.jfrog-auth.outputs.jfrog-access-token }}"
UV_INDEX_URL: 'https://databricks.jfrog.io/artifactory/api/pypi/db-pypi/simple'
run: |
uv auth login "${UV_INDEX_URL}" --username gha-service-account --password "${JFROG_ACCESS_TOKEN}"
printf '%s=%s\n' 'UV_INDEX_URL' "${UV_INDEX_URL}" >> "${GITHUB_ENV}"
printf '%s=%s\n' 'UV_FROZEN' '1' >> "${GITHUB_ENV}"
printf '::debug::%s\n' 'Configured JFrog access for uv.'
umask 077
cat > "${RUNNER_TEMP}/.netrc" << EOF
machine databricks.jfrog.io
login gha-service-account
password ${JFROG_ACCESS_TOKEN}
EOF
printf '%s=%s\n' 'NETRC' "${RUNNER_TEMP}/.netrc" >> "${GITHUB_ENV}"

- name: Configure npm/yarn (classic) for JFrog
if: "${{ steps.detect-cmds.outputs.command_npm == 'true' }}"
Expand All @@ -121,3 +133,50 @@ runs:
//databricks.jfrog.io/artifactory/api/npm/db-npm/:_authToken=${JFROG_ACCESS_TOKEN}
EOF
printf '::debug::%s\n' 'Configured JFrog access for npm/yarn (classic).'

- name: Configure pip for JFrog
if: "${{ steps.detect-cmds.outputs.command_pip3 == 'true' }}"
shell: bash
run: |
cat > "${RUNNER_TEMP}/.pip.conf" << 'EOF'
[global]
index-url = https://databricks.jfrog.io/artifactory/api/pypi/db-pypi/simple
EOF
printf '%s=%s\n' 'PIP_CONFIG_FILE' "${RUNNER_TEMP}/.pip.conf" >> "${GITHUB_ENV}"
printf '::debug::%s\n' 'Configured JFrog access for pip.'

- name: Configure sbt for JFrog
if: "${{ steps.detect-cmds.outputs.command_sbt == 'true' }}"
shell: bash
env:
JFROG_ACCESS_TOKEN: "${{ steps.jfrog-auth.outputs.jfrog-access-token }}"
run: |
umask 077
mkdir -p ~/.sbt/1.0
cat > ~/.sbt/repositories << 'EOF'
[repositories]
local
databricks-jfrog: https://databricks.jfrog.io/artifactory/db-maven/
EOF

cat > "${RUNNER_TEMP}/.sbt.credentials" << EOF
realm=Artifactory Realm
host=databricks.jfrog.io
user=gha-service-account
password=${JFROG_ACCESS_TOKEN}
EOF

cat > ~/.sbt/1.0/global.sbt << 'EOF'
credentials += Credentials(file(sys.env("RUNNER_TEMP")) / ".sbt.credentials")
EOF
printf '::debug::%s\n' 'Configured JFrog access for SBT.'

- name: Configure uv for JFrog
if: "${{ steps.detect-cmds.outputs.command_uv == 'true' }}"
shell: bash
env:
UV_INDEX_URL: 'https://databricks.jfrog.io/artifactory/api/pypi/db-pypi/simple'
run: |
printf '%s=%s\n' 'UV_INDEX_URL' "${UV_INDEX_URL}" >> "${GITHUB_ENV}"
printf '%s=%s\n' 'UV_FROZEN' '1' >> "${GITHUB_ENV}"
printf '::debug::%s\n' 'Configured JFrog access for uv.'
2 changes: 1 addition & 1 deletion .github/actions/jfrog-auth/jfrog-auth
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ printf '::add-mask::%s\n' "${_id_token}"
# Step 2: Exchange it for the JFrog access token.
#
printf '::debug::%s\n' "Exchanging OIDC identifier token for JFrog access token..."
_access_token=$(curl -sLS \
_access_token=$(curl -fsSL \
--json "{\"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\"}" \
"https://databricks.jfrog.io/access/api/v1/oidc/token" |
jq -r .access_token)
Expand Down
143 changes: 143 additions & 0 deletions .github/scripts/lint-uv
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#!/bin/sh
#
# Check the uv settings of the project, to ensure dependencies are being updated properly.
#
# The intent here is that:
#
# - Lock-files should only be updated via the `make lock-dependencies` target.
# - We only re-lock when:
# - Updating the project dependencies in some way.
# - Refreshing the locked versions, where that is the sole purpose of the PR.
# - Developer environment information should not be present in the lock-file; it should be usable by the public.
#
# The checks that we perform to enforce this are:
# - The only registry we should see in uv.lock is "https://pypi.org/simple".
# - The uv.lock file must be consistent with pyproject.toml.
# - If changes to uv.lock are present, there must be no other files changed in the PR _or_ pyproject.toml must also
# be updated.
# - The same applies to .build-constraints.txt.
#

set -eu

PROGNAME="${0##*/}"
die() {
_exitcode="$1"
shift
printf "%s: %s\n" "${PROGNAME}" "$*" 1>&2

exit "${_exitcode}"
}

# Locate the root of the project.
PROJECT_ROOT="$(git rev-parse --show-toplevel)"

# Set up a scratch directory for temporary files during the check.
SCRATCH="$(mktemp -d -t "${PROGNAME}.XXX")"
trap 'rm -fr "${SCRATCH}"' EXIT

# This script handles the locked/frozen flags for uv itself.
unset UV_FROZEN UV_LOCKED

tomlq() {
# Assumes typical project setup: tomlq is present (and locked).
uv run --frozen --quiet --group yq tomlq "$@"
}

#
# Check 1: Verify that uv.lock refers only to PyPI as a registry.
#
check_lock_registry() {
# Collect all registry URLs present in uv.lock, except for the only one we allow.
tomlq --raw-output \
'[.. | objects | .source.registry // empty] - ["https://pypi.org/simple"] | unique | .[]' \
"${PROJECT_ROOT}/uv.lock" > "${SCRATCH}/foreign-registries.txt"
if [ -s "${SCRATCH}/foreign-registries.txt" ]
then
printf "%s: Detected non-PyPI registries:\n" "${PROGNAME}"
sed 's/^/ /' "${SCRATCH}/foreign-registries.txt"
die 1 "uv.lock may only contain PyPI registries."
fi
}
check_lock_registry

#
# Check 2: Verify that uv.lock is consistent with pyproject.toml.
#

detect_index_url() {
# Annoyingly, there is no way to query from uv the index URL it's going to use; the only approach is to use a fake
# project and ask to resolve, then dig the index URL out of the results.
mkdir -p "${SCRATCH}/uvtest"
cat > "${SCRATCH}/uvtest/pyproject.toml" << 'EOF'
[project]
name = "uvtest"
version = "0"
requires-python = ">=3.10"
dependencies = ["packaging"]
EOF
uv lock --quiet --project "${SCRATCH}/uvtest"
tomlq --raw-output 'first(.package[].source.registry // empty)' "${SCRATCH}/uvtest/uv.lock"
}

check_lock_consistency() {
# We can't check uv.lock directly, because we can't reach the registry recorded in there. Instead we make a shadow
# version of this project and check that.
index_url="$(detect_index_url)"
[ -n "${index_url}" ] || die 2 "Could not detect the URL to use for PyPI."
mkdir -p "${SCRATCH}/shadow-project"
ln -s \
"${PROJECT_ROOT}/README.md" \
"${PROJECT_ROOT}/pyproject.toml" \
"${PROJECT_ROOT}/src" \
"${SCRATCH}/shadow-project/"
# shellcheck disable=SC2016 # $index_url is a jq variable, bound via --arg
tomlq --toml-output --arg index_url "${index_url}" \
'(.. | objects | .source | select(.registry? == "https://pypi.org/simple")).registry = $index_url' \
"${PROJECT_ROOT}/uv.lock" > "${SCRATCH}/shadow-project/uv.lock"
uv lock --project "${SCRATCH}/shadow-project" --check --quiet ||
die 2 "Inconsistency detected between pyproject.toml and uv.lock."
}
check_lock_consistency

#
# Check 3: Detect if uv.lock or .build-constraints.txt have been updated with pyproject.toml or on their own.
#

base_rev() {
# A few situations to deal with, in order of priority:
# - In CI, we set BASE_SHA for pull requests and the merge queue.
# - In CI, we also have the push to main where there's no base: in this case we can use GITHUB_REF and diff will
# end up a no-op (because there are no differences).
# - For local dev, fall-back to `main` which by convention is always available.
_base_rev="${BASE_SHA:-${GITHUB_REF:-main}}"
git rev-parse --verify --quiet "${_base_rev}" > /dev/null ||
die 3 "Base revision of repository is not available: ${_base_rev}"
printf "%s" "${_base_rev}"
}
merge_base() {
# Figure out the merge-base between this branch and verify it's available. (CI checkout might be shallow.)
_tip="$1"
_base_rev=$(base_rev)
if ! git merge-base "${_base_rev}" "${_tip}" 2> /dev/null
then
die 4 "Repository is incomplete, merge base between ${_base_rev} and ${_tip} is not available."
fi
}

check_lockfile_updates() {
_merge_base=$(merge_base HEAD)
git diff "${_merge_base}..HEAD" --name-only > "${SCRATCH}/changed-files.txt"

if grep -qxF -e 'uv.lock' -e '.build-constraints.txt' "${SCRATCH}/changed-files.txt"
then
# Lock-files changed: either pyproject.toml has to be changed, or nothing else is allowed.
if grep -vxF -e 'uv.lock' -e '.build-constraints.txt' "${SCRATCH}/changed-files.txt" > "${SCRATCH}/other-files.txt" && ! grep -qxF 'pyproject.toml' "${SCRATCH}/other-files.txt"
then
printf "%s: Detected changes to uv.lock and/or .build-constraints.txt mixed with changes to:\n" "${PROGNAME}"
sed -e 's/^/ /' "${SCRATCH}/other-files.txt"
die 5 "Lock-files must be updated either in conjunction with dependencies in pyproject.toml or on their own."
fi
fi
}
check_lockfile_updates
Loading