From cb32f329da69d22a040c671b60c286f71b6d4541 Mon Sep 17 00:00:00 2001
From: Chester Curme <chester.curme@gmail.com>
Date: Sun, 8 Sep 2024 10:43:58 -0400
Subject: [PATCH 1/4] update release workflows to support releases from
 non-main branches

---
 .github/workflows/_release.yml      | 10 ++++++++--
 .github/workflows/_test_release.yml |  7 ++++++-
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/_release.yml b/.github/workflows/_release.yml
index bf03d7e5..692bf982 100644
--- a/.github/workflows/_release.yml
+++ b/.github/workflows/_release.yml
@@ -13,6 +13,11 @@ on:
         required: true
         type: string
         default: 'libs/vertexai'
+      dangerous-nonmaster-release:
+        required: false
+        type: boolean
+        default: false
+        description: "Release from a non-master branch (danger!)"
 
 env:
   PYTHON_VERSION: "3.11"
@@ -20,7 +25,7 @@ env:
 
 jobs:
   build:
-    if: github.ref == 'refs/heads/main'
+    if: github.ref == 'refs/heads/main' || inputs.dangerous-nonmaster-release
     runs-on: ubuntu-latest
 
     outputs:
@@ -75,6 +80,7 @@ jobs:
     permissions: write-all
     with:
       working-directory: ${{ inputs.working-directory }}
+      dangerous-nonmaster-release: ${{ inputs.dangerous-nonmaster-release }}
     secrets: inherit
 
   pre-release-checks:
@@ -270,4 +276,4 @@ jobs:
           draft: false
           generateReleaseNotes: true
           tag: ${{ inputs.working-directory }}/v${{ needs.build.outputs.version }}
-          commit: main
+          commit: ${{ github.sha }}
diff --git a/.github/workflows/_test_release.yml b/.github/workflows/_test_release.yml
index 39be5ea1..11436869 100644
--- a/.github/workflows/_test_release.yml
+++ b/.github/workflows/_test_release.yml
@@ -7,6 +7,11 @@ on:
         required: true
         type: string
         description: "From which folder this pipeline executes"
+      dangerous-nonmaster-release:
+        required: false
+        type: boolean
+        default: false
+        description: "Release from a non-master branch (danger!)"
 
 env:
   POETRY_VERSION: "1.7.1"
@@ -14,7 +19,7 @@ env:
 
 jobs:
   build:
-    if: github.ref == 'refs/heads/main'
+    if: github.ref == 'refs/heads/main' || inputs.dangerous-nonmaster-release
     runs-on: ubuntu-latest
 
     outputs:

From 5ed976533d29374a0c765478c27da3318ead9450 Mon Sep 17 00:00:00 2001
From: Chester Curme <chester.curme@gmail.com>
Date: Sun, 8 Sep 2024 10:48:19 -0400
Subject: [PATCH 2/4] support dev and rc releases in min version checks

---
 .github/scripts/get_min_versions.py | 40 +++++++++++++++++++++--------
 .github/workflows/_release.yml      |  2 +-
 2 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/.github/scripts/get_min_versions.py b/.github/scripts/get_min_versions.py
index 46e74c93..a5017613 100644
--- a/.github/scripts/get_min_versions.py
+++ b/.github/scripts/get_min_versions.py
@@ -1,20 +1,30 @@
 import sys
 
-import tomllib
+if sys.version_info >= (3, 11):
+    import tomllib
+else:
+    # for python 3.10 and below, which doesnt have stdlib tomllib
+    import tomli as tomllib
+
 from packaging.version import parse as parse_version
 import re
 
 MIN_VERSION_LIBS = ["langchain-core"]
 
+SKIP_IF_PULL_REQUEST = ["langchain-core"]
+
 
 def get_min_version(version: str) -> str:
+    # base regex for x.x.x with cases for rc/post/etc
+    # valid strings: https://peps.python.org/pep-0440/#public-version-identifiers
+    vstring = r"\d+(?:\.\d+){0,2}(?:(?:a|b|rc|\.post|\.dev)\d+)?"
     # case ^x.x.x
-    _match = re.match(r"^\^(\d+(?:\.\d+){0,2})$", version)
+    _match = re.match(f"^\\^({vstring})$", version)
     if _match:
         return _match.group(1)
 
     # case >=x.x.x,<y.y.y
-    _match = re.match(r"^>=(\d+(?:\.\d+){0,2}),<(\d+(?:\.\d+){0,2})$", version)
+    _match = re.match(f"^>=({vstring}),<({vstring})$", version)
     if _match:
         _min = _match.group(1)
         _max = _match.group(2)
@@ -22,14 +32,14 @@ def get_min_version(version: str) -> str:
         return _min
 
     # case x.x.x
-    _match = re.match(r"^(\d+(?:\.\d+){0,2})$", version)
+    _match = re.match(f"^({vstring})$", version)
     if _match:
         return _match.group(1)
 
     raise ValueError(f"Unrecognized version format: {version}")
 
 
-def get_min_version_from_toml(toml_path: str):
+def get_min_version_from_toml(toml_path: str, versions_for: str):
     # Parse the TOML file
     with open(toml_path, "rb") as file:
         toml_data = tomllib.load(file)
@@ -42,11 +52,18 @@ def get_min_version_from_toml(toml_path: str):
 
     # Iterate over the libs in MIN_VERSION_LIBS
     for lib in MIN_VERSION_LIBS:
+        if versions_for == "pull_request" and lib in SKIP_IF_PULL_REQUEST:
+            # some libs only get checked on release because of simultaneous
+            # changes
+            continue
         # Check if the lib is present in the dependencies
         if lib in dependencies:
             # Get the version string
             version_string = dependencies[lib]
 
+            if isinstance(version_string, dict):
+                version_string = version_string["version"]
+
             # Use parse_version to get the minimum supported version from version_string
             min_version = get_min_version(version_string)
 
@@ -56,10 +73,13 @@ def get_min_version_from_toml(toml_path: str):
     return min_versions
 
 
-# Get the TOML file path from the command line argument
-toml_file = sys.argv[1]
+if __name__ == "__main__":
+    # Get the TOML file path from the command line argument
+    toml_file = sys.argv[1]
+    versions_for = sys.argv[2]
+    assert versions_for in ["release", "pull_request"]
 
-# Call the function to get the minimum versions
-min_versions = get_min_version_from_toml(toml_file)
+    # Call the function to get the minimum versions
+    min_versions = get_min_version_from_toml(toml_file, versions_for)
 
-print(" ".join([f"{lib}=={version}" for lib, version in min_versions.items()]))
+    print(" ".join([f"{lib}=={version}" for lib, version in min_versions.items()]))
\ No newline at end of file
diff --git a/.github/workflows/_release.yml b/.github/workflows/_release.yml
index 692bf982..3ca3374f 100644
--- a/.github/workflows/_release.yml
+++ b/.github/workflows/_release.yml
@@ -182,7 +182,7 @@ jobs:
         id: min-version
         run: |
           poetry run pip install packaging
-          min_versions="$(poetry run python $GITHUB_WORKSPACE/.github/scripts/get_min_versions.py pyproject.toml)"
+          min_versions="$(poetry run python $GITHUB_WORKSPACE/.github/scripts/get_min_versions.py pyproject.toml release)"
           echo "min-versions=$min_versions" >> "$GITHUB_OUTPUT"
           echo "min-versions=$min_versions"
 

From 9ac0c4d7ed719b1abb4ae78354fc153630c6b65b Mon Sep 17 00:00:00 2001
From: Chester Curme <chester.curme@gmail.com>
Date: Sun, 8 Sep 2024 10:52:00 -0400
Subject: [PATCH 3/4] format

---
 .github/scripts/get_min_versions.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/scripts/get_min_versions.py b/.github/scripts/get_min_versions.py
index a5017613..268fdeb0 100644
--- a/.github/scripts/get_min_versions.py
+++ b/.github/scripts/get_min_versions.py
@@ -82,4 +82,4 @@ def get_min_version_from_toml(toml_path: str, versions_for: str):
     # Call the function to get the minimum versions
     min_versions = get_min_version_from_toml(toml_file, versions_for)
 
-    print(" ".join([f"{lib}=={version}" for lib, version in min_versions.items()]))
\ No newline at end of file
+    print(" ".join([f"{lib}=={version}" for lib, version in min_versions.items()]))

From 72d1b5ad853dd1d80c5f74089290caba712221fe Mon Sep 17 00:00:00 2001
From: ccurme <chester.curme@gmail.com>
Date: Sun, 8 Sep 2024 11:04:53 -0400
Subject: [PATCH 4/4] add integration test workflow (#484)

---
 .github/workflows/_integration_test.yml | 64 +++++++++++++++++++++++++
 1 file changed, 64 insertions(+)
 create mode 100644 .github/workflows/_integration_test.yml

diff --git a/.github/workflows/_integration_test.yml b/.github/workflows/_integration_test.yml
new file mode 100644
index 00000000..0c680c55
--- /dev/null
+++ b/.github/workflows/_integration_test.yml
@@ -0,0 +1,64 @@
+name: Integration tests
+
+on:
+  workflow_dispatch:
+    inputs:
+      working-directory:
+        required: true
+        type: string
+      python-version:
+        required: true
+        type: string
+        description: "Python version to use"
+
+env:
+  POETRY_VERSION: "1.7.1"
+
+jobs:
+  build:
+    defaults:
+      run:
+        working-directory: ${{ inputs.working-directory }}
+    runs-on: ubuntu-latest
+    name: Python ${{ inputs.python-version }}
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: Set up Python ${{ inputs.python-version }} + Poetry ${{ env.POETRY_VERSION }}
+        uses: "./.github/actions/poetry_setup"
+        with:
+          python-version: ${{ inputs.python-version }}
+          poetry-version: ${{ env.POETRY_VERSION }}
+          working-directory: ${{ inputs.working-directory }}
+          cache-key: core
+
+      - name: Install dependencies
+        shell: bash
+        run: poetry install --with test,test_integration
+
+      - name: 'Authenticate to Google Cloud'
+        id: 'auth'
+        uses: google-github-actions/auth@v2
+        with:
+          credentials_json: '${{ secrets.GOOGLE_CREDENTIALS }}'
+
+      - name: Run integration tests
+        shell: bash
+        env:
+          GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
+          GOOGLE_SEARCH_API_KEY: ${{ secrets.GOOGLE_SEARCH_API_KEY }}
+          GOOGLE_CSE_ID: ${{ secrets.GOOGLE_CSE_ID }}
+        run: |
+          make integration_tests
+
+      - name: Ensure the tests did not create any additional files
+        shell: bash
+        run: |
+          set -eu
+
+          STATUS="$(git status)"
+          echo "$STATUS"
+
+          # grep will exit non-zero if the target message isn't found,
+          # and `set -e` above will cause the step to fail.
+          echo "$STATUS" | grep 'nothing to commit, working tree clean'