From a277209fe4e2e109141af41d3c07d5d91693f07f Mon Sep 17 00:00:00 2001 From: vjgit96 Date: Thu, 25 Jun 2026 16:39:39 -0400 Subject: [PATCH] ci: push nightly .devX Docker images to langflowai/langflow and fix db-migration-validation image references (#13836) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ci: push nightly .devX docker images to langflowai/langflow in addition to langflowai/langflow-nightly Mirrors PyPI behaviour where .devX releases are published under the 'langflow' package name (not 'langflow-nightly'). The Docker nightly workflow now tags and pushes every nightly image to both repos: - langflowai/langflow-nightly:{ver} (existing) - langflowai/langflow:{ver} (new — matches PyPI) - langflowai/langflow-nightly:latest (existing) - langflowai/langflow:latest (new) Same mirroring applied to the base and main-all variants, and to GHCR. The arch-specific intermediate tags (used to assemble multi-arch manifests) remain under the '-nightly' repos; only the final merged manifests are additionally published to the canonical 'langflow' repos. Fixes: LE-1667 * ci: update db-migration-validation to use canonical langflowai/langflow image The db-migration-validation workflow was still referencing the old langflowai/langflow-nightly image for its nightly upgrade step. Now that .devX images are also pushed to langflowai/langflow (canonical repo, matching PyPI), update all consumer-side references: - nightly_build.yml: nightly_tag now passes langflowai/langflow: - db-migration-validation.yml: default and shell fallbacks updated to langflowai/langflow:latest; inline comments updated to match The langflowai/langflow-nightly images remain in use as intermediate arch-specific staging tags inside docker-nightly-build.yml only. Relates to: LE-1667 * ci: fix stale langflow-nightly package name reference in comment The nightly is published as canonical .devN pre-releases of langflow / langflow-base (not as separate langflow-nightly / langflow-base-nightly packages). Update the generate-shared-tag step comment to accurately reflect this since the rename that happened in the 1.10 release cycle. Relates to: LE-1353, LE-1667 * fix(ci): do not set :latest on canonical langflow repo for nightly .devX images Nightly .devX images should not overwrite the stable :latest tag on langflowai/langflow. The :latest (and :base-latest) floating tags are only set on the -nightly repos (langflowai/langflow-nightly), which are explicitly nightly-only. The canonical langflowai/langflow repo only receives the versioned tag (e.g. :1.11.0.dev20250522), matching PyPI behaviour where langflow==1.11.0.dev20250522 is published but never becomes the 'latest' release index entry. Addresses PR review comment from @jordanrfrazier. Relates to: LE-1667 * fix(ci): prevent shell injection from inputs.nightly_tag in db-migration-validation Pass inputs.nightly_tag through an env: block and reference it as $INPUT_NIGHTLY_TAG in the shell script rather than expanding the GitHub Actions expression directly inside run:. Direct expansion of ${{ inputs.* }} in shell scripts allows an attacker-controlled input to inject arbitrary shell commands (CWE-78). Flagged by CodeRabbit security review. Relates to: LE-1667 --- .github/workflows/db-migration-validation.yml | 16 ++++++----- .github/workflows/docker-nightly-build.yml | 27 ++++++++++++------- .github/workflows/nightly_build.yml | 11 ++++---- 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/.github/workflows/db-migration-validation.yml b/.github/workflows/db-migration-validation.yml index 9a3c905c4c..509a805a67 100644 --- a/.github/workflows/db-migration-validation.yml +++ b/.github/workflows/db-migration-validation.yml @@ -10,10 +10,10 @@ on: workflow_dispatch: inputs: nightly_tag: - description: "Nightly tag to test migration to (e.g., langflowai/langflow-nightly:latest)" + description: "Nightly tag to test migration to (e.g., langflowai/langflow:latest)" required: false type: string - default: "langflowai/langflow-nightly:latest" + default: "langflowai/langflow:latest" # Note: This workflow is called by nightly_build.yml after Docker images are built env: @@ -155,10 +155,12 @@ jobs: - name: Upgrade to nightly version working-directory: migration-test + env: + INPUT_NIGHTLY_TAG: ${{ inputs.nightly_tag }} run: | source .venv/bin/activate - NIGHTLY_TAG="${{ inputs.nightly_tag || 'langflowai/langflow-nightly:latest' }}" + NIGHTLY_TAG="${INPUT_NIGHTLY_TAG:-langflowai/langflow:latest}" echo "Upgrading to nightly version: $NIGHTLY_TAG" # Remove the stable install first. The nightly now publishes as a `.devN` pre-release of @@ -169,7 +171,7 @@ jobs: echo "Removing stable langflow to force a clean install of the nightly dev version..." uv pip uninstall -y langflow langflow-base || true - # Extract version from Docker tag (format: langflowai/langflow-nightly:v1.10.0.dev20260522) + # Extract version from Docker tag (format: langflowai/langflow:v1.10.0.dev20260522) if [[ "$NIGHTLY_TAG" == *":"* ]]; then VERSION="${NIGHTLY_TAG##*:}" echo "Extracted version from tag: $VERSION" @@ -412,10 +414,12 @@ jobs: - name: Update to nightly image working-directory: docker-migration-test + env: + INPUT_NIGHTLY_TAG: ${{ inputs.nightly_tag }} run: | - NIGHTLY_TAG="${{ inputs.nightly_tag || 'langflowai/langflow-nightly:latest' }}" + NIGHTLY_TAG="${INPUT_NIGHTLY_TAG:-langflowai/langflow:latest}" # Strip 'v' prefix from version part — Docker images are published without it - # e.g. langflowai/langflow-nightly:v1.10.0.dev20260522 → langflowai/langflow-nightly:1.10.0.dev20260522 + # e.g. langflowai/langflow:v1.10.0.dev20260522 → langflowai/langflow:1.10.0.dev20260522 VERSION_PART="${NIGHTLY_TAG##*:}" IMAGE_NAME="${NIGHTLY_TAG%%:*}" DOCKER_TAG="${IMAGE_NAME}:${VERSION_PART#v}" diff --git a/.github/workflows/docker-nightly-build.yml b/.github/workflows/docker-nightly-build.yml index 1ac15fde5a..35796dd400 100644 --- a/.github/workflows/docker-nightly-build.yml +++ b/.github/workflows/docker-nightly-build.yml @@ -92,8 +92,8 @@ jobs: id: tags run: | version="${{ steps.version.outputs.version }}" - echo "docker_tags=langflowai/langflow-nightly:base-${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT - echo "ghcr_tags=ghcr.io/langflow-ai/langflow-nightly:base-${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT + echo "docker_tags=langflowai/langflow-nightly:base-${version}-${{ matrix.arch }},langflowai/langflow:base-${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT + echo "ghcr_tags=ghcr.io/langflow-ai/langflow-nightly:base-${version}-${{ matrix.arch }},ghcr.io/langflow-ai/langflow:base-${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT - name: Docker cleanup run: | @@ -187,8 +187,8 @@ jobs: id: tags run: | version="${{ steps.version.outputs.version }}" - echo "docker_tags=langflowai/langflow-nightly:${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT - echo "ghcr_tags=ghcr.io/langflow-ai/langflow-nightly:${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT + echo "docker_tags=langflowai/langflow-nightly:${version}-${{ matrix.arch }},langflowai/langflow:${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT + echo "ghcr_tags=ghcr.io/langflow-ai/langflow-nightly:${version}-${{ matrix.arch }},ghcr.io/langflow-ai/langflow:${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT - name: Docker cleanup run: | @@ -282,8 +282,8 @@ jobs: id: tags run: | version="${{ steps.version.outputs.version }}" - echo "docker_tags=langflowai/langflow-nightly-all:${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT - echo "ghcr_tags=ghcr.io/langflow-ai/langflow-nightly-all:${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT + echo "docker_tags=langflowai/langflow-nightly-all:${version}-${{ matrix.arch }},langflowai/langflow-all:${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT + echo "ghcr_tags=ghcr.io/langflow-ai/langflow-nightly-all:${version}-${{ matrix.arch }},ghcr.io/langflow-ai/langflow-all:${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT - name: Docker cleanup run: | @@ -368,17 +368,26 @@ jobs: version="${{ steps.version.outputs.version }}" case "${{ inputs.release_type }}" in "nightly-base") - echo "final_tags=langflowai/langflow-nightly:base-${version},langflowai/langflow-nightly:base-latest,ghcr.io/langflow-ai/langflow-nightly:base-${version},ghcr.io/langflow-ai/langflow-nightly:base-latest" >> $GITHUB_OUTPUT + # Push versioned tag to canonical langflow repo (matches PyPI langflow-base .devN publish). + # :base-latest is only set on the -nightly repo to avoid overwriting the stable :base-latest + # on langflowai/langflow with a pre-release image. + echo "final_tags=langflowai/langflow-nightly:base-${version},langflowai/langflow-nightly:base-latest,langflowai/langflow:base-${version},ghcr.io/langflow-ai/langflow-nightly:base-${version},ghcr.io/langflow-ai/langflow-nightly:base-latest,ghcr.io/langflow-ai/langflow:base-${version}" >> $GITHUB_OUTPUT echo "arch_base=langflowai/langflow-nightly:base-${version}" >> $GITHUB_OUTPUT echo "ghcr_arch_base=ghcr.io/langflow-ai/langflow-nightly:base-${version}" >> $GITHUB_OUTPUT ;; "nightly-main") - echo "final_tags=langflowai/langflow-nightly:${version},langflowai/langflow-nightly:latest,ghcr.io/langflow-ai/langflow-nightly:${version},ghcr.io/langflow-ai/langflow-nightly:latest" >> $GITHUB_OUTPUT + # Push versioned tag to canonical langflow repo (matches PyPI langflow .devN publish). + # :latest is only set on the -nightly repo to avoid overwriting the stable :latest + # on langflowai/langflow with a pre-release image. + echo "final_tags=langflowai/langflow-nightly:${version},langflowai/langflow-nightly:latest,langflowai/langflow:${version},ghcr.io/langflow-ai/langflow-nightly:${version},ghcr.io/langflow-ai/langflow-nightly:latest,ghcr.io/langflow-ai/langflow:${version}" >> $GITHUB_OUTPUT echo "arch_base=langflowai/langflow-nightly:${version}" >> $GITHUB_OUTPUT echo "ghcr_arch_base=ghcr.io/langflow-ai/langflow-nightly:${version}" >> $GITHUB_OUTPUT ;; "nightly-main-all") - echo "final_tags=langflowai/langflow-nightly-all:${version},langflowai/langflow-nightly-all:latest,ghcr.io/langflow-ai/langflow-nightly-all:${version},ghcr.io/langflow-ai/langflow-nightly-all:latest" >> $GITHUB_OUTPUT + # Push versioned tag to canonical langflow-all repo (matches PyPI publish). + # :latest is only set on the -nightly-all repo to avoid overwriting the stable :latest + # on langflowai/langflow-all with a pre-release image. + echo "final_tags=langflowai/langflow-nightly-all:${version},langflowai/langflow-nightly-all:latest,langflowai/langflow-all:${version},ghcr.io/langflow-ai/langflow-nightly-all:${version},ghcr.io/langflow-ai/langflow-nightly-all:latest,ghcr.io/langflow-ai/langflow-all:${version}" >> $GITHUB_OUTPUT echo "arch_base=langflowai/langflow-nightly-all:${version}" >> $GITHUB_OUTPUT echo "ghcr_arch_base=ghcr.io/langflow-ai/langflow-nightly-all:${version}" >> $GITHUB_OUTPUT ;; diff --git a/.github/workflows/nightly_build.yml b/.github/workflows/nightly_build.yml index def8504263..5a88b33066 100644 --- a/.github/workflows/nightly_build.yml +++ b/.github/workflows/nightly_build.yml @@ -110,9 +110,9 @@ jobs: - name: Generate shared nightly tag (main == base, lockstep) id: generate_shared_tag run: | - # langflow-nightly pins langflow-base-nightly[complete]==, so both tags - # MUST be identical. Compute them in ONE invocation (single PyPI snapshot) so they - # cannot drift across separate calls. + # langflow (nightly .devN pre-release) pins langflow-base[complete]==, so + # both tags MUST be identical. Compute them in ONE invocation (single PyPI snapshot) + # so they cannot drift across separate calls. # NOTE: This outputs the tag with the `v` prefix. TAGS_OUTPUT="$(uv run ./scripts/ci/pypi_nightly_tag.py both)" RELEASE_TAG="$(printf '%s\n' "$TAGS_OUTPUT" | sed -n '1p')" @@ -314,8 +314,9 @@ jobs: with: # Pass Docker image reference for docker-compose and version without 'v' prefix for pip # release_tag format: v1.10.0.dev20260522 - # We need: langflowai/langflow-nightly:1.10.0.dev20260522 for Docker - nightly_tag: langflowai/langflow-nightly:${{ needs.create-nightly-tag.outputs.release_tag }} + # We need: langflowai/langflow:1.10.0.dev20260522 for Docker (nightly .devX images are + # pushed to the canonical langflowai/langflow repo to match PyPI langflow package naming) + nightly_tag: langflowai/langflow:${{ needs.create-nightly-tag.outputs.release_tag }} secrets: inherit slack-notification: