Skip to content

fix(amber): declare cloudpickle in LICENSE-binary-python - #8293

Merged
aglinxinyuan merged 2 commits into
apache:mainfrom
aglinxinyuan:fix/cloudpickle-license-bullet
Aug 31, 2026
Merged

fix(amber): declare cloudpickle in LICENSE-binary-python#8293
aglinxinyuan merged 2 commits into
apache:mainfrom
aglinxinyuan:fix/cloudpickle-license-bullet

Conversation

@aglinxinyuan

@aglinxinyuan aglinxinyuan commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

What changes were proposed in this PR?

One bullet in amber/LICENSE-binary-python, in the BSD 3-Clause section:

  - click==8.4.2
+ - cloudpickle==3.1.2
  - contourpy==1.3.3

Why it is a bug. build / pyamber (ubuntu-latest, 3.12) has been red
repo-wide since ~09:00-13:00 UTC on 2026-08-31, on every open PR regardless of
what the PR touches, because joblib 1.6.0 stopped vendoring cloudpickle:

joblib 1.5.3 joblib 1.6.0
joblib/externals/cloudpickle/ in the wheel present (vendored) gone
Requires-Dist (none) cloudpickle>=3.0
visible to pip-licenses no yes

amber/operator-requirements.txt reaches joblib transitively, so pip now
installs cloudpickle as its own distribution and the manifest no longer
describes what the image bundles:

operator-requirements.txt -> scikit-learn==1.7.2 -> joblib>=1.2.0 -> cloudpickle>=3.0
Before:  any PR -> pyamber 3.12 -> "+ cloudpickle==3.1.2"                -> red
After:   any PR -> pyamber 3.12 -> "OK: 110 Python packages match ..."   -> green

Note that the code was always in the distribution -- it shipped inside the
joblib wheel. What changed is that it became a separate distribution, and so
became visible to the license scanner.

License clearance. cloudpickle 3.1.2's wheel METADATA says
License: BSD-3-Clause (PyPI's classifier reports only the generic
BSD License, which is what the CI line quotes), and the bundled LICENSE is
the canonical three-clause text. That is ASF Category A. The wheel ships no
NOTICE, and licenses/LICENSE-BSD-3-Clause.txt already carries the text that
the section references, so no NOTICE-binary / NOTICE-binary-python change is
needed and the one bullet is the entire fix.

Deliberately out of scope. The same step prints a long
DRIFT (transitive, informational) list (charset-normalizer, click,
joblib, regex, scipy, ...). PR runs pass --ignore-transitive-version, so
none of it is fatal, and the nightly exact-match check on main owns refreshing
those pins -- bulk-bumping 22 moving targets here would just add churn. That is
why joblib stays at 1.5.3 in the manifest even though 1.6.0 is what
introduced the coupling.

This unblocks every open PR's build / pyamber (ubuntu-latest, 3.12) job.

Any related issues, documentation, discussions?

Closes #8292

Related: #8294

How was this PR tested?

Reproduced the CI check locally, byte-for-byte, without a full pip install.
CI's own report is a complete description of the diff between the manifest and
reality (1 +, 0 stale, 0 direct drift, 22 transitive drifts), so the installed
set was rebuilt as "every claimed bullet at its bundled version, plus
cloudpickle==3.1.2" and fed to the checker exactly as build.yml invokes it:

python bin/licensing/check_binary_deps.py --ignore-transitive-version python /tmp/pip-licenses.csv
exit output
before (main) 1 + cloudpickle==3.1.2 (license: BSD License) -- identical to run 33394216939
after (this PR) 0 OK: 110 Python packages match LICENSE-binary.

The --ignore-transitive-version-less (nightly) mode still exits 1 on the 22
transitive drifts both before and after this change, so the behavior there is
unchanged -- that is the nightly refresh's job, not this PR's.

Upstream cause confirmed straight from the published wheels:

pip download joblib==1.5.3 --no-deps -d . && pip download joblib==1.6.0 --no-deps -d .
# 1.6.0 METADATA: Requires-Dist: cloudpickle>=3.0, and no joblib/externals/cloudpickle/
# 1.5.3 METADATA: no Requires-Dist,           and joblib/externals/cloudpickle/ present
pip download cloudpickle==3.1.2 --no-deps -d .
# METADATA: License: BSD-3-Clause; licenses/LICENSE is the 3-clause text; no NOTICE

The failure was verified as repo-wide rather than PR-specific on two unrelated
branches -- chore/remove-superseded-sql-updates (run 33394216939, 12:55 UTC)
and ci/8084-backport-manager-approval-gate (run 33392828233, 12:39 UTC) -- both
failing on the same + cloudpickle==3.1.2 line, against green license steps at
08:39 UTC (#8282) and 08:49 UTC (#8286).

One wrinkle worth flagging for the reviewer: build was skipped on this
PR's first runs. amber/LICENSE-binary-python matches no glob in
.github/labeler.yml, so no stack label was applied, precheck selected no
stacks, and the aggregate gate accepts build: skipped as passing -- i.e. a
change to this manifest is not normally gated by the check that validates it.
The pyamber label was applied by hand here so the license check actually runs
against the fix. That gap is filed separately as #8294 and left out of this
diff to keep the hotfix a one-liner.

Was this PR authored or co-authored using generative AI tooling?

Generated-by: Claude Code (Opus 5)

joblib 1.6.0 stopped vendoring cloudpickle -- joblib/externals/cloudpickle
is gone from the wheel and the metadata now carries
`Requires-Dist: cloudpickle>=3.0` -- so pip installs cloudpickle as its own
distribution. amber/operator-requirements.txt reaches joblib transitively
through scikit-learn==1.7.2, which makes cloudpickle newly visible to
pip-licenses and unclaimed by amber/LICENSE-binary-python.

That fails the `Check installed Python packages against per-module
LICENSE-binary files` step of `build / pyamber (ubuntu-latest, 3.12)` on
every open PR, regardless of what the PR touches:

  NEW Python packages not claimed by LICENSE-binary:
    + cloudpickle==3.1.2  (license: BSD License)

cloudpickle 3.1.2 is BSD-3-Clause (its METADATA says
`License: BSD-3-Clause`; PyPI's classifier only reports the generic
"BSD License"), which is ASF Category A. Its wheel ships no NOTICE and
licenses/LICENSE-BSD-3-Clause.txt already carries the license text, so the
one manifest bullet is the whole fix.

The transitive version drift the same step reports is left alone: it is
informational under --ignore-transitive-version, and the nightly
exact-match check on main owns refreshing it.
Copilot AI lite review requested due to automatic review settings August 31, 2026 14:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@mengw15
mengw15 requested a lite review from Copilot August 31, 2026 14:15
@aglinxinyuan
aglinxinyuan enabled auto-merge August 31, 2026 14:21
@Yicong-Huang Yicong-Huang added the release/v1.2 back porting to release/v1.2 label Aug 31, 2026
@github-actions
github-actions Bot requested a review from xuang7 August 31, 2026 14:25
@github-actions

github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Backport auto-label report

This fix: PR was checked against each actively-supported release branch. release/* labels drive the post-merge backport, so add or remove one to change where this fix lands.

Release branch Analysis
⚠️ release/v1.3 Not labeled automatically — none of the files this PR modifies exist on this branch (amber/LICENSE-binary-python). The fix may target code that isn't on this release, or the files were moved/renamed after the branch was cut. Please check and add release/v1.3 by hand if this fix should be backported here.
release/v1.2 Already labeled — this fix is queued to backport here.

Auto-label run.

@github-actions

Copy link
Copy Markdown
Contributor

Automated Reviewer Suggestions

Based on the git blame history of the changed files, we recommend the following reviewers:

  • Contributors with relevant context: @xuang7
    You can notify them by mentioning @xuang7 in a comment.

@github-actions github-actions Bot added the fix label Aug 31, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.90%. Comparing base (50321e4) to head (ec735a4).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #8293      +/-   ##
============================================
- Coverage     93.93%   93.90%   -0.04%     
  Complexity     4762     4762              
============================================
  Files          1191     1191              
  Lines         48308    49051     +743     
  Branches       5377     5377              
============================================
+ Hits          45380    46060     +680     
- Misses         1494     1557      +63     
  Partials       1434     1434              
Flag Coverage Δ *Carryforward flag
access-control-service 81.00% <ø> (ø) Carriedforward from 50321e4
agent-service 99.32% <ø> (ø) Carriedforward from 50321e4
amber 90.03% <ø> (ø) Carriedforward from 50321e4
computing-unit-managing-service 73.67% <ø> (ø) Carriedforward from 50321e4
config-service 86.86% <ø> (ø) Carriedforward from 50321e4
file-service 87.91% <ø> (ø) Carriedforward from 50321e4
frontend 96.41% <ø> (ø) Carriedforward from 50321e4
notebook-migration-service 79.31% <ø> (ø) Carriedforward from 50321e4
pyamber 97.85% <ø> (-1.02%) ⬇️
workflow-compiling-service 77.19% <ø> (ø) Carriedforward from 50321e4

*This pull request uses carry forward flags. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Benchmark changes need a look

🟢 2 better · 🔴 2 worse · ⚪ 11 noise (<±5%) · 0 without baseline

Compared against main 50321e4 benchmarked on this same runner, so the delta is largely free of cross-runner hardware noise. The "7d avg" column still reflects the gh-pages dashboard. Treat <±5% as noise unless repeated.

Dashboard · Run

config throughput MB/s latency max Δ latest / 7d
🔴 bs=10 sw=10 sl=64 560 0.342 17,115/27,086/27,086 us 🔴 +5.6% / 🔴 +73.9%
🟢 bs=100 sw=10 sl=64 1,150 0.702 85,112/118,599/118,599 us 🟢 -11.7% / 🟢 -15.5%
bs=1000 sw=10 sl=64 1,318 0.804 755,442/825,214/825,214 us ⚪ within ±5% / 🟢 +26.5%
Baseline details

Latest main 50321e4 from same runner

config metric PR latest main 7d avg Δ latest Δ 7d
bs=10 sw=10 sl=64 throughput 560 tuples/sec 570 tuples/sec 787.98 tuples/sec -1.8% -28.9%
bs=10 sw=10 sl=64 MB/s 0.342 MB/s 0.348 MB/s 0.481 MB/s -1.7% -28.9%
bs=10 sw=10 sl=64 p50 17,115 us 16,834 us 12,593 us +1.7% +35.9%
bs=10 sw=10 sl=64 p95 27,086 us 25,649 us 15,579 us +5.6% +73.9%
bs=10 sw=10 sl=64 p99 27,086 us 25,649 us 18,786 us +5.6% +44.2%
bs=100 sw=10 sl=64 throughput 1,150 tuples/sec 1,125 tuples/sec 1,008 tuples/sec +2.2% +14.1%
bs=100 sw=10 sl=64 MB/s 0.702 MB/s 0.687 MB/s 0.615 MB/s +2.2% +14.1%
bs=100 sw=10 sl=64 p50 85,112 us 83,841 us 100,701 us +1.5% -15.5%
bs=100 sw=10 sl=64 p95 118,599 us 134,321 us 107,244 us -11.7% +10.6%
bs=100 sw=10 sl=64 p99 118,599 us 134,321 us 116,122 us -11.7% +2.1%
bs=1000 sw=10 sl=64 throughput 1,318 tuples/sec 1,341 tuples/sec 1,042 tuples/sec -1.7% +26.5%
bs=1000 sw=10 sl=64 MB/s 0.804 MB/s 0.819 MB/s 0.636 MB/s -1.8% +26.4%
bs=1000 sw=10 sl=64 p50 755,442 us 741,999 us 981,959 us +1.8% -23.1%
bs=1000 sw=10 sl=64 p95 825,214 us 800,914 us 1,023,080 us +3.0% -19.3%
bs=1000 sw=10 sl=64 p99 825,214 us 800,914 us 1,051,697 us +3.0% -21.5%
Raw CSV
config_idx,batch_size,schema_width,string_len,num_batches,total_ms,total_tuples,total_bytes,tuples_per_sec,mb_per_sec,lat_p50_us,lat_p95_us,lat_p99_us
0,10,10,64,20,357.21,200,128000,560,0.342,17115.16,27085.98,27085.98
1,100,10,64,20,1739.42,2000,1280000,1150,0.702,85111.64,118598.84,118598.84
2,1000,10,64,20,15174.97,20000,12800000,1318,0.804,755442.05,825214.29,825214.29

@aglinxinyuan

aglinxinyuan commented Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

CI note for reviewers — the one red check on this PR is not caused by this diff.

The fix itself is verified on a real runner. build / pyamber (ubuntu-latest, 3.12)
in run 33404550705
passed the previously-failing step with:

OK: 110 Python packages match LICENSE-binary.

and pytest reported 1298 passed, 1 deselected, 1 xfailed. The 3.11 and 3.13
legs passed too. The same license step also passed on the release/v1.2
backport run 33404551297,
so the backport lands correctly as well (apply-check is green — the
cherry-pick applies cleanly).

The red check is backport (release/v1.2) / amber-integration (ubuntu-latest, 17),
which failed after every test had passed (Tests: succeeded 553, failed 0,
Passed: Total 6, Failed 0) with:

.github/scripts/smoke-boot.sh: No such file or directory
##[error]Process completed with exit code 127.

The backport check runs main's build.yml against the release branch's tree,
and smoke-boot.sh was added to main in #6274 — it does not exist on
release/v1.2. A one-line change to a Python license manifest cannot create or
remove that script. Filed as #8295, with the full scope.

It surfaced here only because pyamber had to be applied by hand for this
PR to be tested at all (amber/LICENSE-binary-python matches no
.github/labeler.yml glob — #8294), and pyamber also enables
amber-integration. Across the last 30 Backport Checks runs, this is the only
one that ran that leg.

Also worth ignoring: a Required Checks fail 4s row from run
33402590171. That
is the pre-label run, whose precheck was cancelled when the relabel
superseded it. The live gate is run 33404550705.

Happy to drop the pyamber label if you'd rather this go green — the
verification above is already recorded in those runs — but I've left it on so
the license check is visibly gating the fix.


Update — the runs finished, and they isolate the failure cleanly.
Required Checks on run
33404550705 is
success (every non-skipped job green, amber-integration (ubuntu-latest, 17)
included). The PR is MERGEABLE, state UNSTABLE — the required gate is
satisfied and the only red row is the non-required backport leg.

That gives a controlled A/B on this exact commit: the same job name,
amber-integration (ubuntu-latest, 17), passed on the main build run and
failed on the backport run. The only variable between them is which tree
prepare-backport-checkout.sh put in the workspace — which rules out both this
diff and a flake, and points squarely at smoke-boot.sh being absent from
release/v1.2 (#8295).

@aglinxinyuan
aglinxinyuan added this pull request to the merge queue Aug 31, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 31, 2026
@aglinxinyuan

Copy link
Copy Markdown
Contributor Author

Two things: this PR's own CI is not verifying it, and here is the verification it is missing.

Why its CI proves nothing

Every stack skipped on the latest run. The precheck log says why:

PR labels: fix, release/v1.2
Stacks selected by label union: (none)

The pyamber label is what selects the pyamber stack (LABEL_STACKS in precheck.yml:261). It was on this PR — I added it by hand at 14:45:54 — and then:

2026-08-31T14:45:54Z  labeled    pyamber  by aglinxinyuan
2026-08-31T16:12:10Z  unlabeled  pyamber  by github-actions[bot]

.github/workflows/pr-labeler.yml:31 sets sync-labels: true, and the pyamber globs in .github/labeler.yml:102-106 are amber/**/*.py, amber/pyproject.toml, amber/**/*requirements*.txt. amber/LICENSE-binary-python matches none of them, so the labeler removed the label as not-applicable. Precheck then does exactly what it is designed to do — waits for the labeler to finish because it may have just added labels — and reads the post-strip set.

So the manual-label workaround does not hold: it survives until the next pull_request event and is then swept. That makes #8294 sharper than "these edits skip the checks" — there is currently no way to make the stack run on a LICENSE-binary-only PR without touching .github/labeler.yml.

The verification, run locally

check_binary_deps.py accepts --license-binary, so the real checker can be pointed at each side of this diff. Input is a pip-licenses CSV built from the 109 packages the pre-fix manifest claims, plus the one new distribution CI reported:

Pre-fix manifest (origin/main) — reproduces the CI failure line verbatim:

NEW Python packages not claimed by LICENSE-binary:
  + cloudpickle==3.1.2  (license: BSD License) → add to .../A-prefix.txt
exit=1

Post-fix manifest (this PR) — same input, same command:

OK: 110 Python packages match LICENSE-binary.
exit=0

That 110 is the same count the description quotes from a passing run, which is a useful cross-check that the synthesized package set matches the real installed one.

Reproducible from the repo root:

git show origin/main:amber/LICENSE-binary-python > /tmp/A.txt
git show HEAD:amber/LICENSE-binary-python       > /tmp/B.txt
# build /tmp/pip-licenses.csv = every "- name==ver" bullet under a "Python packages:"
# heading in /tmp/A.txt, plus cloudpickle,3.1.2,"BSD License"
./bin/licensing/check_binary_deps.py --ignore-transitive-version python /tmp/pip-licenses.csv --license-binary /tmp/A.txt   # exit 1
./bin/licensing/check_binary_deps.py --ignore-transitive-version python /tmp/pip-licenses.csv --license-binary /tmp/B.txt   # exit 0

I have not re-added the pyamber label, since it would just be swept again on the next event. Whether the labeler glob gets widened here or under #8294 is a maintainer call — happy to do either.

@aglinxinyuan
aglinxinyuan added this pull request to the merge queue Aug 31, 2026
Merged via the queue into apache:main with commit 267d916 Aug 31, 2026
29 checks passed
@aglinxinyuan
aglinxinyuan deleted the fix/cloudpickle-license-bullet branch August 31, 2026 17:04
@github-actions

Copy link
Copy Markdown
Contributor

Backport to release/v1.2 failed. See job log.

renovate-bot pushed a commit to renovate-bot/apache-_-texera that referenced this pull request Sep 3, 2026
…e#8375)

### What changes were proposed in this PR?

`typing-extensions` is a direct dependency, and the version it resolves
to moved to 4.16.0 while `amber/LICENSE-binary-python` still claimed
4.14.1. Direct-dependency drift hard-fails the license check rather than
being reported as informational, so `build / pyamber (ubuntu-latest,
3.12)` fails its license step on every pull request and on `main` — the
last four `Required Checks` runs on `main` are red — and every later
step in that job is skipped. Re-running does not help: the resolver
picks up 4.16.0 each time.

The version is the only thing that changed. PyPI reports
`license_expression: PSF-2.0` for both 4.14.1 and 4.16.0, so the entry
stays in the Python Software Foundation License section it is already
listed under.

The transitive entries printed alongside it in the same output are
advisory; the nightly exact-match check on `main` refreshes those.

### Any related issues, documentation, discussions?

Closes apache#8374. Same failure mode as apache#8293, with a different package.
apache#7285 is the weekly aggregate tracker `license-binary-checker.yml`
re-uses; it does not name the offending dependency.

### How was this PR tested?

Verified before editing rather than after: the failing run is
[33710669719](https://github.com/apache/texera/actions/runs/33710669719),
whose license step prints `~ typing-extensions: LICENSE-binary=4.14.1
bundled=4.16.0` under `DRIFT (direct)`. PyPI's metadata for both
versions reports `license_expression: PSF-2.0`, and the entry is already
in the Python Software Foundation License section, so no section move is
needed.

The check itself runs in CI on this PR — a green `build / pyamber
(ubuntu-latest, 3.12)` is the confirmation that the manifest now matches
what gets installed.

### Was this PR authored or co-authored using generative AI tooling?

Generated-by: Claude Code (claude-opus-5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix release/v1.2 back porting to release/v1.2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pyamber 3.12 license check fails on every PR after joblib un-vendored cloudpickle

5 participants