ci(infra): add dropdown + override inputs to release and integration test workflows (#36687)

Both `_release.yml` and `integration_tests.yml` previously required
manually typing a package path to target a specific library. Replace the
free-text-only inputs with a dropdown of known packages plus a free-text
override for unlisted paths. The release workflow consolidates the
override-or-default resolution into a single `EFFECTIVE_WORKING_DIR` env
var to eliminate duplication across 20+ step references.
This commit is contained in:
Mason Daugherty
2026-04-12 13:49:37 -05:00
committed by GitHub
parent cfb16f634f
commit c59e83a1ff
2 changed files with 87 additions and 49 deletions

View File

@@ -5,7 +5,7 @@
# Handles version bumping, building, and publishing to PyPI with authentication.
name: "🚀 Package Release"
run-name: "Release ${{ inputs.working-directory }} ${{ inputs.release-version }}"
run-name: "Release ${{ inputs.working-directory-override || inputs.working-directory }} ${{ inputs.release-version }}"
on:
workflow_call:
inputs:
@@ -42,6 +42,10 @@ on:
- libs/partners/perplexity
- libs/partners/qdrant
- libs/partners/xai
working-directory-override:
required: false
type: string
description: "Manual override — takes precedence over dropdown (e.g. libs/partners/partner-xyz)"
release-version:
required: true
type: string
@@ -57,6 +61,7 @@ env:
PYTHON_VERSION: "3.11"
UV_FROZEN: "true"
UV_NO_SYNC: "true"
EFFECTIVE_WORKING_DIR: ${{ inputs.working-directory-override || inputs.working-directory }}
permissions:
contents: read # Job-level overrides grant write only where needed (mark-release)
@@ -97,18 +102,18 @@ jobs:
# https://github.com/pypa/gh-action-pypi-publish#non-goals
- name: Build project for distribution
run: uv build
working-directory: ${{ inputs.working-directory }}
working-directory: ${{ env.EFFECTIVE_WORKING_DIR }}
- name: Upload build
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
name: dist
path: ${{ inputs.working-directory }}/dist/
path: ${{ env.EFFECTIVE_WORKING_DIR }}/dist/
- name: Check version
id: check-version
shell: python
working-directory: ${{ inputs.working-directory }}
working-directory: ${{ env.EFFECTIVE_WORKING_DIR }}
run: |
import os
import tomllib
@@ -135,13 +140,13 @@ jobs:
repository: langchain-ai/langchain
path: langchain
sparse-checkout: | # this only grabs files for relevant dir
${{ inputs.working-directory }}
${{ env.EFFECTIVE_WORKING_DIR }}
ref: ${{ github.ref }} # this scopes to just ref'd branch
fetch-depth: 0 # this fetches entire commit history
- name: Check tags
id: check-tags
shell: bash
working-directory: langchain/${{ inputs.working-directory }}
working-directory: langchain/${{ env.EFFECTIVE_WORKING_DIR }}
env:
PKG_NAME: ${{ needs.build.outputs.pkg-name }}
VERSION: ${{ needs.build.outputs.version }}
@@ -198,7 +203,7 @@ jobs:
id: generate-release-body
working-directory: langchain
env:
WORKING_DIR: ${{ inputs.working-directory }}
WORKING_DIR: ${{ env.EFFECTIVE_WORKING_DIR }}
PKG_NAME: ${{ needs.build.outputs.pkg-name }}
TAG: ${{ steps.check-tags.outputs.tag }}
PREV_TAG: ${{ steps.check-tags.outputs.prev-tag }}
@@ -238,12 +243,12 @@ jobs:
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: dist
path: ${{ inputs.working-directory }}/dist/
path: ${{ env.EFFECTIVE_WORKING_DIR }}/dist/
- name: Publish to test PyPI
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # release/v1
with:
packages-dir: ${{ inputs.working-directory }}/dist/
packages-dir: ${{ env.EFFECTIVE_WORKING_DIR }}/dist/
verbose: true
print-hash: true
repository-url: https://test.pypi.org/legacy/
@@ -288,11 +293,11 @@ jobs:
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: dist
path: ${{ inputs.working-directory }}/dist/
path: ${{ env.EFFECTIVE_WORKING_DIR }}/dist/
- name: Import dist package
shell: bash
working-directory: ${{ inputs.working-directory }}
working-directory: ${{ env.EFFECTIVE_WORKING_DIR }}
env:
PKG_NAME: ${{ needs.build.outputs.pkg-name }}
VERSION: ${{ needs.build.outputs.version }}
@@ -310,11 +315,11 @@ jobs:
- name: Import test dependencies
run: uv sync --group test
working-directory: ${{ inputs.working-directory }}
working-directory: ${{ env.EFFECTIVE_WORKING_DIR }}
# Overwrite the local version of the package with the built version
- name: Import published package (again)
working-directory: ${{ inputs.working-directory }}
working-directory: ${{ env.EFFECTIVE_WORKING_DIR }}
shell: bash
env:
PKG_NAME: ${{ needs.build.outputs.pkg-name }}
@@ -325,17 +330,17 @@ jobs:
- name: Check for prerelease versions
# Block release if any dependencies allow prerelease versions
# (unless this is itself a prerelease version)
working-directory: ${{ inputs.working-directory }}
working-directory: ${{ env.EFFECTIVE_WORKING_DIR }}
run: |
uv run python $GITHUB_WORKSPACE/.github/scripts/check_prerelease_dependencies.py pyproject.toml
- name: Run unit tests
run: make tests
working-directory: ${{ inputs.working-directory }}
working-directory: ${{ env.EFFECTIVE_WORKING_DIR }}
- name: Get minimum versions
# Find the minimum published versions that satisfies the given constraints
working-directory: ${{ inputs.working-directory }}
working-directory: ${{ env.EFFECTIVE_WORKING_DIR }}
id: min-version
run: |
VIRTUAL_ENV=.venv uv pip install packaging requests
@@ -352,15 +357,15 @@ jobs:
VIRTUAL_ENV=.venv uv pip install --force-reinstall --editable .
VIRTUAL_ENV=.venv uv pip install --force-reinstall $MIN_VERSIONS
make tests
working-directory: ${{ inputs.working-directory }}
working-directory: ${{ env.EFFECTIVE_WORKING_DIR }}
- name: Import integration test dependencies
run: uv sync --group test --group test_integration
working-directory: ${{ inputs.working-directory }}
working-directory: ${{ env.EFFECTIVE_WORKING_DIR }}
- name: Run integration tests
# Uses the Makefile's `integration_tests` target for the specified package
if: ${{ startsWith(inputs.working-directory, 'libs/partners/') }}
if: ${{ startsWith(env.EFFECTIVE_WORKING_DIR, 'libs/partners/') }}
env:
AI21_API_KEY: ${{ secrets.AI21_API_KEY }}
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
@@ -400,7 +405,7 @@ jobs:
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
LANGCHAIN_TESTS_USER_AGENT: ${{ secrets.LANGCHAIN_TESTS_USER_AGENT }}
run: make integration_tests
working-directory: ${{ inputs.working-directory }}
working-directory: ${{ env.EFFECTIVE_WORKING_DIR }}
# Test select published packages against new core
# Done when code changes are made to langchain-core
@@ -441,25 +446,25 @@ jobs:
# TODO: this seems to be resolved upstream, so we can probably remove this workaround
- name: Check if libs/core
run: |
if [ "${{ startsWith(inputs.working-directory, 'libs/core') }}" != "true" ]; then
if [ "${{ startsWith(env.EFFECTIVE_WORKING_DIR, 'libs/core') }}" != "true" ]; then
echo "Not in libs/core. Exiting successfully."
exit 0
fi
- name: Set up Python + uv
if: startsWith(inputs.working-directory, 'libs/core')
if: startsWith(env.EFFECTIVE_WORKING_DIR, 'libs/core')
uses: "./.github/actions/uv_setup"
with:
python-version: ${{ env.PYTHON_VERSION }}
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
if: startsWith(inputs.working-directory, 'libs/core')
if: startsWith(env.EFFECTIVE_WORKING_DIR, 'libs/core')
with:
name: dist
path: ${{ inputs.working-directory }}/dist/
path: ${{ env.EFFECTIVE_WORKING_DIR }}/dist/
- name: Test against ${{ matrix.partner }}
if: startsWith(inputs.working-directory, 'libs/core')
if: startsWith(env.EFFECTIVE_WORKING_DIR, 'libs/core')
run: |
# Identify latest tag, excluding pre-releases
LATEST_PACKAGE_TAG="$(
@@ -504,8 +509,11 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: read
# Only run for core or langchain_v1 releases
if: startsWith(inputs.working-directory, 'libs/core') || startsWith(inputs.working-directory, 'libs/langchain_v1')
# Only run for core or langchain_v1 releases.
# Job-level 'if' does not support env context; must use inputs directly.
if: >-
startsWith(inputs.working-directory-override || inputs.working-directory, 'libs/core')
|| startsWith(inputs.working-directory-override || inputs.working-directory, 'libs/langchain_v1')
strategy:
fail-fast: false
matrix:
@@ -575,7 +583,7 @@ jobs:
defaults:
run:
working-directory: ${{ inputs.working-directory }}
working-directory: ${{ env.EFFECTIVE_WORKING_DIR }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
@@ -588,12 +596,12 @@ jobs:
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: dist
path: ${{ inputs.working-directory }}/dist/
path: ${{ env.EFFECTIVE_WORKING_DIR }}/dist/
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # release/v1
with:
packages-dir: ${{ inputs.working-directory }}/dist/
packages-dir: ${{ env.EFFECTIVE_WORKING_DIR }}/dist/
verbose: true
print-hash: true
# Temp workaround since attestations are on by default as of gh-action-pypi-publish v1.11.0
@@ -617,7 +625,7 @@ jobs:
defaults:
run:
working-directory: ${{ inputs.working-directory }}
working-directory: ${{ env.EFFECTIVE_WORKING_DIR }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
@@ -630,7 +638,7 @@ jobs:
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: dist
path: ${{ inputs.working-directory }}/dist/
path: ${{ env.EFFECTIVE_WORKING_DIR }}/dist/
- name: Create Tag
uses: ncipollo/release-action@339a81892b84b4eeb0f6e744e4574d79d0d9b8dd # v1

View File

@@ -5,17 +5,44 @@
# Runs daily with the option to trigger manually.
name: "⏰ Integration Tests"
run-name: "Run Integration Tests - ${{ inputs.working-directory-force || 'all libs' }} (Python ${{ inputs.python-version-force || '3.10, 3.13' }})"
run-name: "Run Integration Tests - ${{ inputs.working-directory-override || (inputs.working-directory != 'all' && inputs.working-directory) || 'all libs' }} (Python ${{ inputs.python-version-override || '3.10, 3.13' }})"
on:
workflow_dispatch:
inputs:
working-directory-force:
working-directory:
type: choice
description: "Library to test (select from dropdown)"
default: "all"
options:
- "all"
- "libs/core"
- "libs/langchain"
- "libs/langchain_v1"
- "libs/text-splitters"
- "libs/standard-tests"
- "libs/model-profiles"
- "libs/partners/anthropic"
- "libs/partners/chroma"
- "libs/partners/deepseek"
- "libs/partners/exa"
- "libs/partners/fireworks"
- "libs/partners/groq"
- "libs/partners/huggingface"
- "libs/partners/mistralai"
- "libs/partners/nomic"
- "libs/partners/ollama"
- "libs/partners/openai"
- "libs/partners/openrouter"
- "libs/partners/perplexity"
- "libs/partners/qdrant"
- "libs/partners/xai"
working-directory-override:
type: string
description: "From which folder this pipeline executes - defaults to all in matrix - example value: libs/partners/anthropic"
python-version-force:
description: "Manual override — takes precedence over dropdown (e.g. libs/partners/partner-xyz)"
python-version-override:
type: string
description: "Python version to use - defaults to 3.10 and 3.13 in matrix - example value: 3.11"
description: "Python version override defaults to 3.10 and 3.13 in matrix (e.g. 3.11)"
schedule:
- cron: "0 13 * * *" # Runs daily at 1PM UTC (9AM EDT/6AM PDT)
@@ -52,29 +79,32 @@ jobs:
id: set-matrix
env:
DEFAULT_LIBS: ${{ env.DEFAULT_LIBS }}
WORKING_DIRECTORY_FORCE: ${{ github.event.inputs.working-directory-force || '' }}
PYTHON_VERSION_FORCE: ${{ github.event.inputs.python-version-force || '' }}
WORKING_DIRECTORY_OVERRIDE: ${{ github.event.inputs.working-directory-override || '' }}
WORKING_DIRECTORY_CHOICE: ${{ github.event.inputs.working-directory || 'all' }}
PYTHON_VERSION_OVERRIDE: ${{ github.event.inputs.python-version-override || '' }}
run: |
# echo "matrix=..." where matrix is a json formatted str with keys python-version and working-directory
# python-version should default to 3.10 and 3.13, but is overridden to [PYTHON_VERSION_FORCE] if set
# working-directory should default to DEFAULT_LIBS, but is overridden to [WORKING_DIRECTORY_FORCE] if set
# python-version defaults to 3.10 and 3.13, overridden to [PYTHON_VERSION_OVERRIDE] if set
# working-directory priority: override string > dropdown choice > DEFAULT_LIBS
python_version='["3.10", "3.13"]'
python_version_min_3_11='["3.11", "3.13"]'
working_directory="$DEFAULT_LIBS"
if [ -n "$PYTHON_VERSION_FORCE" ]; then
python_version="[\"$PYTHON_VERSION_FORCE\"]"
# Bound forced version to >= 3.11 for packages requiring it
if [ "$(echo "$PYTHON_VERSION_FORCE >= 3.11" | bc -l)" -eq 1 ]; then
python_version_min_3_11="[\"$PYTHON_VERSION_FORCE\"]"
if [ -n "$PYTHON_VERSION_OVERRIDE" ]; then
python_version="[\"$PYTHON_VERSION_OVERRIDE\"]"
# Bound override version to >= 3.11 for packages requiring it
if [ "$(echo "$PYTHON_VERSION_OVERRIDE >= 3.11" | bc -l)" -eq 1 ]; then
python_version_min_3_11="[\"$PYTHON_VERSION_OVERRIDE\"]"
else
python_version_min_3_11='["3.11"]'
fi
fi
if [ -n "$WORKING_DIRECTORY_FORCE" ]; then
working_directory="[\"$WORKING_DIRECTORY_FORCE\"]"
if [ -n "$WORKING_DIRECTORY_OVERRIDE" ]; then
working_directory="[\"$WORKING_DIRECTORY_OVERRIDE\"]"
elif [ "$WORKING_DIRECTORY_CHOICE" != "all" ]; then
working_directory="[\"$WORKING_DIRECTORY_CHOICE\"]"
fi
matrix="{\"python-version\": $python_version, \"working-directory\": $working_directory}"
echo $matrix
echo "$matrix"
echo "matrix=$matrix" >> $GITHUB_OUTPUT
echo "python-version-min-3-11=$python_version_min_3_11" >> $GITHUB_OUTPUT