name: CI on: workflow_call: inputs: python-versions: description: "Python Versions" required: false type: string default: "['3.10']" frontend-tests-folder: description: "Frontend Tests Folder" required: false type: string default: "tests/core" release: description: "Release" required: false type: boolean default: false workflow_dispatch: inputs: branch: description: "(Optional) Branch to checkout" required: false type: string openai_api_key: description: "OpenAI API Key" required: false type: string store_api_key: description: "Store API Key" required: false type: string python-versions: description: "Python Versions" required: false type: string default: "['3.10']" pull_request: types: [synchronize, labeled] merge_group: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: check-nightly-status: name: Check PyPI Version Update runs-on: ubuntu-latest outputs: should-proceed: ${{ steps.check-pypi.outputs.success }} steps: - name: Check PyPI package update id: check-pypi run: | # Get today's date in ISO format for comparison TODAY=$(date -u +"%Y-%m-%d") echo "Today's date: $TODAY" # Query PyPI API for the langflow package HTTP_STATUS=$(curl -s -o response.json -w "%{http_code}" https://pypi.org/pypi/langflow-nightly/json) # Check HTTP status code first if [ "$HTTP_STATUS" -ne 200 ]; then echo "Error: PyPI API returned HTTP status $HTTP_STATUS" echo "success=false" >> $GITHUB_OUTPUT exit 0 fi # Check if response is valid JSON before proceeding if ! jq -e . response.json >/dev/null 2>&1; then echo "Error: Invalid JSON response from PyPI API" echo "Response preview:" head -n 10 response.json echo "success=false" >> $GITHUB_OUTPUT exit 0 fi # Extract the latest version LATEST_VERSION=$(jq -r '.info.version // empty' response.json) if [ -z "$LATEST_VERSION" ]; then echo "Could not extract latest version" echo "success=false" >> $GITHUB_OUTPUT exit 0 fi # Extract the release date of the latest version RELEASE_DATE=$(jq -r --arg ver "$LATEST_VERSION" '.releases[$ver][0].upload_time_iso_8601 // empty' response.json | cut -d'T' -f1) if [ -z "$RELEASE_DATE" ]; then echo "Could not extract release date" echo "success=false" >> $GITHUB_OUTPUT exit 0 fi echo "Latest version: $LATEST_VERSION" echo "Release date: $RELEASE_DATE" # Check if the release date is today if [[ "$RELEASE_DATE" == "$TODAY" ]]; then echo "Package was updated today" echo "success=true" >> $GITHUB_OUTPUT else echo "Package was not updated today" echo "success=false" >> $GITHUB_OUTPUT fi # Clean up rm -f response.json set-ci-condition: needs: check-nightly-status name: Should Run CI runs-on: ubuntu-latest outputs: should-run-ci: ${{ (needs.check-nightly-status.outputs.should-proceed == 'true' || github.event_name == 'workflow_dispatch') && ((contains( github.event.pull_request.labels.*.name, 'lgtm') && github.event.pull_request.draft == false) || (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call' || github.event_name == 'merge_group')) }} should-run-tests: ${{ !contains(github.event.pull_request.labels.*.name, 'fast-track') || github.event_name == 'workflow_call' || github.event_name == 'workflow_dispatch' || github.event_name == 'merge_group' }} steps: # Do anything just to make the job run - run: echo "Debug CI Condition" - run: echo "Labels -> ${{ join(github.event.pull_request.labels.*.name, ',') }}" - run: echo "IsDraft -> ${{ github.event.pull_request.draft }}" - run: echo "Event name -> ${{ github.event_name }}" - run: echo "Nightly build status -> ${{ needs.check-nightly-status.outputs.should-proceed }}" - run: echo "Should run tests -> ${{ !contains(github.event.pull_request.labels.*.name, 'fast-track') || github.event_name == 'workflow_call' || github.event_name == 'workflow_dispatch' || github.event_name == 'merge_group' }}" path-filter: needs: set-ci-condition if: ${{ needs.set-ci-condition.outputs.should-run-ci == 'true' }} name: Filter Paths runs-on: ubuntu-latest outputs: python: ${{ steps.filter.outputs.python }} frontend: ${{ steps.filter.outputs.frontend }} docs: ${{ steps.filter.outputs.docs }} frontend-tests: ${{ steps.filter.outputs.frontend-tests }} components-changes: ${{ steps.filter.outputs.components-changes }} starter-projects-changes: ${{ steps.filter.outputs.starter-projects-changes }} starter-projects: ${{ steps.filter.outputs.starter-projects }} components: ${{ steps.filter.outputs.components }} workspace: ${{ steps.filter.outputs.workspace }} api: ${{ steps.filter.outputs.api }} database: ${{ steps.filter.outputs.database }} steps: - name: Checkout code uses: actions/checkout@v4 with: ref: ${{ inputs.branch || github.ref }} - name: Filter Paths id: filter uses: dorny/paths-filter@v3 with: filters: ./.github/changes-filter.yaml test-backend: needs: [path-filter, set-ci-condition] name: Run Backend Tests if: ${{ needs.path-filter.outputs.python == 'true' && needs.set-ci-condition.outputs.should-run-tests == 'true' }} uses: ./.github/workflows/python_test.yml with: python-versions: ${{ inputs.python-versions || '["3.10"]' }} test-frontend: needs: [path-filter, set-ci-condition] name: Run Frontend Tests if: ${{ (needs.path-filter.outputs.frontend == 'true' || needs.path-filter.outputs.frontend-tests == 'true' || needs.path-filter.outputs.components-changes == 'true' || needs.path-filter.outputs.starter-projects-changes == 'true' || needs.path-filter.outputs.starter-projects == 'true' || needs.path-filter.outputs.components == 'true' || needs.path-filter.outputs.workspace == 'true' || needs.path-filter.outputs.api == 'true' || needs.path-filter.outputs.database == 'true') && needs.set-ci-condition.outputs.should-run-tests == 'true' }} uses: ./.github/workflows/typescript_test.yml with: tests_folder: ${{ inputs.frontend-tests-folder }} release: ${{ inputs.release || false }} secrets: OPENAI_API_KEY: "${{ secrets.OPENAI_API_KEY }}" STORE_API_KEY: "${{ secrets.STORE_API_KEY }}" ANTHROPIC_API_KEY: "${{ secrets.ANTHROPIC_API_KEY }}" TAVILY_API_KEY: "${{ secrets.TAVILY_API_KEY }}" lint-backend: needs: path-filter if: ${{ needs.path-filter.outputs.python == 'true'}} name: Lint Backend uses: ./.github/workflows/lint-py.yml test-docs-build: needs: path-filter if: ${{ needs.path-filter.outputs.docs == 'true' }} name: Test Docs Build uses: ./.github/workflows/docs_test.yml # https://github.com/langchain-ai/langchain/blob/master/.github/workflows/check_diffs.yml ci_success: name: "CI Success" needs: [ test-backend, test-frontend, lint-backend, test-docs-build, set-ci-condition, path-filter ] if: always() runs-on: ubuntu-latest env: JOBS_JSON: ${{ toJSON(needs) }} RESULTS_JSON: ${{ toJSON(needs.*.result) }} EXIT_CODE: ${{ ((!contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') && needs.set-ci-condition.outputs.should-run-ci == 'true') || (needs.set-ci-condition.outputs.should-run-tests == 'false' && needs.set-ci-condition.outputs.should-run-ci == 'true')) && '0' || '1' }} steps: - name: "CI Success" run: | echo $JOBS_JSON echo $RESULTS_JSON echo "Should run tests: ${{ needs.set-ci-condition.outputs.should-run-tests }}" echo "Should run CI: ${{ needs.set-ci-condition.outputs.should-run-ci }}" echo "Exiting with $EXIT_CODE" exit $EXIT_CODE