chore(ci): timeout bump + harden langflow grep + build/publish src/bundles/* wheels (#13199)

* chore: bump backend unit test timeout from 30 to 40 minutes

* ci: anchor langflow version grep so new workspace packages can't break it

The pattern `uv tree | grep 'langflow' | grep -v 'langflow-base' | grep -v 'langflow-sdk'`
was used in 8 places to pluck the root `langflow` (or `langflow-nightly`)
line out of `uv tree`. It relied on enumerating every other workspace
package that starts with `langflow-`. As soon as a new one was added
(`langflow-stepflow`, via #12015) the filter let two lines through and
the downstream `awk` / `cut` produced a multi-line string, e.g.:

    Name langflow-stepflow
    langflow-nightly does not match langflow-nightly. Exiting the workflow.

Replace the enumeration with an anchored regex
`grep -E '^langflow(-nightly)?[[:space:]]'` so only the exact `langflow`
or `langflow-nightly` root line matches, regardless of how many other
`langflow-*` workspace packages exist now or in the future.

* ci: build, test, and publish src/bundles/* wheels

Langflow main pins exact versions of every bundle (e.g.
`lfx-arxiv-nightly==0.1.0.dev38`, `lfx-arxiv==0.1.0`), but neither the
nightly workflow nor the release workflow built or published those
bundle wheels. So when cross-platform tests (or downstream consumers)
ran `pip install langflow-nightly`, the resolver couldn't find
`lfx-arxiv-nightly` / `lfx-duckduckgo-nightly` on PyPI and bailed:

    Because lfx-arxiv-nightly was not found in the package registry and
    langflow-nightly==1.10.0.dev38 depends on lfx-arxiv-nightly==0.1.0.dev38,
    we can conclude that langflow-nightly==1.10.0.dev38 cannot be used.

Add a build → test → publish lane for every package under
`src/bundles/*/` in both workflows, plus a matching bundle install step
in cross-platform-test.yml.

`release_nightly.yml`
- `build-nightly-bundles`: iterates `src/bundles/*/pyproject.toml`,
  builds each wheel, uploads as `dist-nightly-bundles`.
- `test-cross-platform` now passes `bundles-artifact-name` so the
  cross-platform test installs bundles before installing main.
- `publish-nightly-bundles`: publishes each bundle wheel to PyPI after
  cross-platform passes and lfx is already published.
- `publish-nightly-main` now waits on `publish-nightly-bundles` so main
  reaches PyPI only after its bundle deps do.

`release.yml`
- New `release_bundles` input (false by default).
- `validate-dependencies` rejects `release_package_main=true` without
  `release_bundles=true`, mirroring the existing lfx/sdk gate.
- `build-bundles`, `publish-bundles` mirror the nightly jobs.
- `publish-main` now needs `publish-bundles`.

`cross-platform-test.yml`
- New optional `bundles-artifact-name` input; download step is gated on
  it being set.
- `build-if-needed` (workflow_dispatch path) also builds bundles and
  publishes the artifact, so adhoc runs stay self-contained.
- Each of the four "Install main package from wheel" steps gets a
  preceding "Install bundle packages from wheel" step that runs only
  when the artifact is present, leaving non-bundle callers
  (e.g. pre-bundle release branches) unaffected.

* ci: drop mapfile from bundle install (macOS Bash 3.2 compat)

`mapfile` is a Bash 4+ builtin and the macOS runners use the system
Bash (3.2). The "Install bundle packages from wheel (Unix)" step
failed on `Install & Run - macos amd64 3.12` with:

    mapfile: command not found
    find: stdout: Broken pipe

Replace with the `shopt -s nullglob` + glob-array pattern already used
in the bundle build/publish steps, which works on Bash 3.2. All
artifact wheels live at the top level of ./bundles-dist, so the simple
glob is equivalent to the previous `find` (which also wasn't recursing
anywhere useful).

---------

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Eric Hare
2026-05-19 08:11:53 -07:00
committed by GitHub
parent e1d79bbaed
commit 9882f9f381
7 changed files with 329 additions and 15 deletions

View File

@ -93,7 +93,7 @@ jobs:
- name: Run unit tests
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
timeout_minutes: 40
max_attempts: 2
command: make unit_tests args="-x -vv --splits ${{ matrix.splitCount }} --group ${{ matrix.group }} --reruns 5 --cov --cov-config=src/backend/.coveragerc --cov-report=xml --cov-report=html"