Skip to content

Commit 52b1ea1

Browse files
authored
feat: Complete RBAC and distribution contracts (#14230)
* feat(authz): complete release 1.12 contracts * docs: fix versioned image profile links * fix: address release completion review feedback
1 parent 9d6346e commit 52b1ea1

33 files changed

Lines changed: 2893 additions & 130 deletions

.github/workflows/release-inventory-gate.yml

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ jobs:
5151
- name: Check out release profiles
5252
uses: actions/checkout@v6
5353
with:
54+
persist-credentials: false
5455
ref: ${{ inputs.ref }}
5556

5657
- name: Set up Python
@@ -76,6 +77,140 @@ jobs:
7677
path: bundle-profile-inventories/*.lock.json
7778
if-no-files-found: error
7879

80+
python-core-inventory:
81+
name: Python ${{ matrix.python-version }} / python-core
82+
if: ${{ inputs.core-artifact-name != '' }}
83+
runs-on: ubuntu-latest
84+
strategy:
85+
fail-fast: false
86+
matrix:
87+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
88+
steps:
89+
- name: Check out release contract
90+
uses: actions/checkout@v6
91+
with:
92+
persist-credentials: false
93+
ref: ${{ inputs.ref }}
94+
95+
- name: Set up Python
96+
uses: actions/setup-python@v6
97+
with:
98+
python-version: ${{ matrix.python-version }}
99+
100+
- name: Set up uv
101+
uses: astral-sh/setup-uv@v6
102+
with:
103+
enable-cache: false
104+
105+
- name: Download SDK wheel
106+
if: ${{ inputs.sdk-artifact-name != '' }}
107+
uses: actions/download-artifact@v7
108+
with:
109+
name: ${{ inputs.sdk-artifact-name }}
110+
path: sdk-dist
111+
112+
- name: Download LFX wheel
113+
if: ${{ inputs.lfx-artifact-name != '' }}
114+
uses: actions/download-artifact@v7
115+
with:
116+
name: ${{ inputs.lfx-artifact-name }}
117+
path: lfx-dist
118+
119+
- name: Download base wheel
120+
if: ${{ inputs.base-artifact-name != '' }}
121+
uses: actions/download-artifact@v7
122+
with:
123+
name: ${{ inputs.base-artifact-name }}
124+
path: base-dist
125+
126+
- name: Download core wheel
127+
uses: actions/download-artifact@v7
128+
with:
129+
name: ${{ inputs.core-artifact-name }}
130+
path: core-dist
131+
132+
- name: Install core release shape from wheels
133+
run: |
134+
set -euo pipefail
135+
shopt -s nullglob
136+
uv venv inventory-env --seed --python "${{ matrix.python-version }}"
137+
138+
LOCAL_WHEELS=()
139+
for wheel_dir in sdk-dist lfx-dist base-dist core-dist; do
140+
if [ ! -d "$wheel_dir" ]; then
141+
continue
142+
fi
143+
WHEELS=("$wheel_dir"/*.whl)
144+
if [ ${#WHEELS[@]} -ne 1 ]; then
145+
echo "Expected exactly one wheel in $wheel_dir, found ${#WHEELS[@]}"
146+
exit 1
147+
fi
148+
LOCAL_WHEELS+=("${WHEELS[0]}")
149+
done
150+
151+
CORE_WHEELS=(core-dist/langflow_core-*.whl)
152+
if [ ${#CORE_WHEELS[@]} -ne 1 ]; then
153+
echo "Expected exactly one langflow-core wheel, found ${#CORE_WHEELS[@]}"
154+
exit 1
155+
fi
156+
157+
SDK_TARGET=()
158+
if [ ! -d sdk-dist ]; then
159+
# The SDK is independently versioned and may already be published
160+
# when a core-only release is cut.
161+
SDK_TARGET=(langflow-sdk)
162+
fi
163+
164+
uv pip install --python inventory-env/bin/python \
165+
--prerelease=if-necessary-or-explicit \
166+
"${LOCAL_WHEELS[@]}" "${SDK_TARGET[@]}"
167+
uv pip check --python inventory-env/bin/python
168+
169+
- name: Validate core distribution and component inventory
170+
run: |
171+
inventory-env/bin/python scripts/ci/check_release_inventory.py \
172+
--contract scripts/ci/release_inventory_contract.json \
173+
--profile python-core \
174+
--output "inventory-reports/python-core-py${{ matrix.python-version }}.json"
175+
176+
- name: Verify core authorization lifecycle imports
177+
run: |
178+
inventory-env/bin/python - <<'PY'
179+
from lfx.services.authorization import AuthorizationMutationKind, AuthorizationMutationRejected
180+
181+
assert isinstance(AuthorizationMutationKind.USER_DISABLED, str)
182+
assert AuthorizationMutationKind.USER_DISABLED.value == "user.disabled"
183+
assert AuthorizationMutationRejected("safe detail").public_detail == "safe detail"
184+
PY
185+
186+
- name: Verify core application startup and health
187+
timeout-minutes: 5
188+
run: |
189+
set -euo pipefail
190+
inventory-env/bin/python -m langflow run --host 127.0.0.1 --port 7860 --backend-only &
191+
server_pid=$!
192+
trap 'kill "$server_pid" >/dev/null 2>&1 || true' EXIT
193+
for _ in $(seq 1 60); do
194+
if curl -fsS http://127.0.0.1:7860/health_check >/dev/null; then
195+
exit 0
196+
fi
197+
if ! kill -0 "$server_pid" 2>/dev/null; then
198+
echo "Langflow core exited before becoming healthy"
199+
exit 1
200+
fi
201+
sleep 2
202+
done
203+
echo "Langflow core did not become healthy"
204+
exit 1
205+
206+
- name: Upload core Python inventory report
207+
if: always()
208+
uses: actions/upload-artifact@v6
209+
with:
210+
name: inventory-python-core-py${{ matrix.python-version }}
211+
path: inventory-reports/*.json
212+
if-no-files-found: warn
213+
79214
python-inventory:
80215
name: Python ${{ matrix.python-version }} / ${{ matrix.profile }}
81216
if: ${{ inputs.main-artifact-name != '' }}
@@ -89,6 +224,7 @@ jobs:
89224
- name: Check out release contract
90225
uses: actions/checkout@v6
91226
with:
227+
persist-credentials: false
92228
ref: ${{ inputs.ref }}
93229

94230
- name: Set up Python
@@ -228,6 +364,7 @@ jobs:
228364
- name: Check out release contract
229365
uses: actions/checkout@v6
230366
with:
367+
persist-credentials: false
231368
ref: ${{ inputs.ref }}
232369

233370
- name: Download bundle wheels for downstream-image test

docs/docs/Deployment/deployment-docker.mdx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ import PartialPodmanAlt from '@site/docs/_partial-podman-alt.mdx';
99

1010
Running applications in Docker containers ensures consistent behavior across different systems and eliminates dependency conflicts.
1111

12+
Langflow publishes core, default, and full application images with different
13+
provider inventories. Before deploying, see
14+
[Choose a Langflow Docker image](./docker-image-profiles.mdx) for the
15+
canonical tags, composition, version-pinning, migration, and rollback guidance.
16+
1217
This guide demonstrates several ways to run Langflow with [Docker](https://docs.docker.com/) and [Docker Compose](https://docs.docker.com/compose/):
1318

1419
* [Quickstart](#quickstart): Start a Langflow container with default values.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
---
2+
title: Choose a Langflow Docker image
3+
slug: /deployment/docker-image-profiles
4+
---
5+
6+
Langflow publishes three application image profiles. They run the same Langflow
7+
service, but they contain different component and provider inventories. Choose
8+
the smallest profile that contains every component used by your flows.
9+
10+
| Profile | Docker Hub image | GitHub Container Registry image | Included inventory |
11+
| --- | --- | --- | --- |
12+
| Core | `langflowai/langflow:core-VERSION` | `ghcr.io/langflow-ai/langflow:core-VERSION` | The Langflow service, UI, core components, and no provider bundle distributions |
13+
| Default | `langflowai/langflow:VERSION` | `ghcr.io/langflow-ai/langflow:VERSION` | Core plus the curated provider set used by the standard Langflow installation |
14+
| Full | `langflowai/langflow-all:VERSION` | `ghcr.io/langflow-ai/langflow-all:VERSION` | Default plus the long-tail `lfx-bundles` provider inventory |
15+
16+
The full profile intentionally uses a separate `langflow-all` repository. The
17+
core and default profiles use different tags in the `langflow` repository.
18+
Core omits all provider distributions; default omits the long-tail
19+
`lfx-bundles` distribution. A flow that references an omitted component cannot
20+
run until you select a profile that provides it or build that provider into a
21+
derived image.
22+
23+
## Pin a release
24+
25+
Use a versioned tag in deployments:
26+
27+
```yaml
28+
services:
29+
langflow:
30+
image: langflowai/langflow:core-1.12.0
31+
```
32+
33+
The moving tags are `langflowai/langflow:core-latest`,
34+
`langflowai/langflow:latest`, and `langflowai/langflow-all:latest`,
35+
respectively. They are convenient for local evaluation, but they can select a
36+
new release without a configuration change. Production deployments should pin
37+
a version tag and, when reproducibility is required, the registry digest:
38+
39+
```yaml
40+
services:
41+
langflow:
42+
image: langflowai/langflow:core-1.12.0@sha256:IMAGE_DIGEST
43+
```
44+
45+
Record both the tag and digest in release records. A tag identifies the
46+
Langflow release; the digest identifies the exact multi-platform image selected
47+
by the deployment.
48+
49+
## Change profiles or versions safely
50+
51+
Changing a profile changes the installed component inventory. Changing a
52+
version can also run database migrations at application startup. Treat either
53+
change as a deployment migration:
54+
55+
1. Inventory the components used by production flows and select a profile that
56+
contains them. Test custom components and provider integrations explicitly.
57+
2. Record the current image digest, configuration, and persistent volume
58+
layout. Back up the database before starting a newer Langflow version.
59+
3. Start the candidate image against a copy of production data and run smoke
60+
tests for login, flow loading, flow execution, file access, and provider
61+
credentials.
62+
4. Deploy the candidate with the same persistent database and data mounts. Do
63+
not copy mutable application files out of the old container.
64+
5. Confirm health and component availability before removing the previous
65+
image from the registry or deployment platform.
66+
67+
Moving from full or default to core is safe only when no saved flow depends on
68+
a removed provider component. If you need a bounded provider set, derive an
69+
image from the versioned core image and install the reviewed provider packages
70+
at image-build time:
71+
72+
```dockerfile
73+
FROM langflowai/langflow:core-1.12.0
74+
RUN uv pip install --python /app/.venv/bin/python \
75+
"lfx-openai==COMPATIBLE_VERSION"
76+
```
77+
78+
Build and test the derived image before deployment. Do not install or remove
79+
provider packages in a running container, because that makes replicas and
80+
rollbacks non-reproducible.
81+
82+
## Roll back
83+
84+
Keep the previous pinned image and database backup until the candidate passes
85+
production verification. To roll back a profile-only change on the same
86+
Langflow version, redeploy the previous digest with the unchanged persistent
87+
data. To roll back across Langflow versions after a database migration, stop
88+
the candidate, restore the pre-upgrade database backup, and redeploy the
89+
previous digest. Do not run an older application against a database that a
90+
newer version migrated unless that downgrade path is explicitly documented.
91+
92+
For general Docker configuration, persistence, and source builds, see
93+
[Deploy Langflow on Docker](./deployment-docker.mdx).

docs/sidebars.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,11 @@ module.exports = {
239239
id: "Deployment/deployment-docker",
240240
label: "Langflow Docker images"
241241
},
242+
{
243+
type: "doc",
244+
id: "Deployment/docker-image-profiles",
245+
label: "Choose a Langflow image"
246+
},
242247
{
243248
type: "doc",
244249
id: "Deployment/downstream-bundle-profiles",

0 commit comments

Comments
 (0)