Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
290 changes: 36 additions & 254 deletions .github/workflows/_release.yml
Original file line number Diff line number Diff line change
@@ -1,267 +1,49 @@
name: release
run-name: Release ${{ inputs.working-directory }} by @${{ github.actor }}
on:
workflow_call:
inputs:
working-directory:
required: true
type: string
description: "From which folder this pipeline executes"
workflow_dispatch:
inputs:
working-directory:
required: true
type: string
default: 'libs/oci'

env:
PYTHON_VERSION: "3.11"
POETRY_VERSION: "1.7.1"

jobs:
build:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest

outputs:
pkg-name: ${{ steps.check-version.outputs.pkg-name }}
version: ${{ steps.check-version.outputs.version }}

steps:
- uses: actions/checkout@v4

- name: Set up Python + Poetry ${{ env.POETRY_VERSION }}
uses: "./.github/actions/poetry_setup"
with:
python-version: ${{ env.PYTHON_VERSION }}
poetry-version: ${{ env.POETRY_VERSION }}
working-directory: ${{ inputs.working-directory }}
cache-key: release
# This workflow will upload a Python Package to PyPI when a release is created
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries

# We want to keep this build stage *separate* from the release stage,
# so that there's no sharing of permissions between them.
# The release stage has trusted publishing and GitHub repo contents write access,
# and we want to keep the scope of that access limited just to the release job.
# Otherwise, a malicious `build` step (e.g. via a compromised dependency)
# could get access to our GitHub or PyPI credentials.
#
# Per the trusted publishing GitHub Action:
# > It is strongly advised to separate jobs for building [...]
# > from the publish job.
# https://github.com/pypa/gh-action-pypi-publish#non-goals
- name: Build project for distribution
run: poetry build
working-directory: ${{ inputs.working-directory }}
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

- name: Upload build
uses: actions/upload-artifact@v4
with:
name: dist
path: ${{ inputs.working-directory }}/dist/
name: Upload Python Package

- name: Check Version
id: check-version
shell: bash
working-directory: ${{ inputs.working-directory }}
run: |
echo pkg-name="$(poetry version | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT
echo version="$(poetry version --short)" >> $GITHUB_OUTPUT
on:
release:
types: [published]
workflow_dispatch:

test-pypi-publish:
needs:
- build
uses:
./.github/workflows/_test_release.yml
permissions: write-all
with:
working-directory: ${{ inputs.working-directory }}
secrets: inherit
permissions:
contents: read

pre-release-checks:
needs:
- build
- test-pypi-publish
jobs:
build-n-publish:
name: Build and publish Python 🐍 distribution 📦 to PyPI
runs-on: ubuntu-latest
defaults:
run:
working-directory: libs/oci # Set default for all steps
environment:
name: pypi
url: https://pypi.org/p/langchain-oci
steps:
- uses: actions/checkout@v4

# We explicitly *don't* set up caching here. This ensures our tests are
# maximally sensitive to catching breakage.
#
# For example, here's a way that caching can cause a falsely-passing test:
# - Make the langchain package manifest no longer list a dependency package
# as a requirement. This means it won't be installed by `pip install`,
# and attempting to use it would cause a crash.
# - That dependency used to be required, so it may have been cached.
# When restoring the venv packages from cache, that dependency gets included.
# - Tests pass, because the dependency is present even though it wasn't specified.
# - The package is published, and it breaks on the missing dependency when
# used in the real world.

- name: Set up Python + Poetry ${{ env.POETRY_VERSION }}
uses: "./.github/actions/poetry_setup"
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
poetry-version: ${{ env.POETRY_VERSION }}
working-directory: ${{ inputs.working-directory }}

- name: Import published package
shell: bash
working-directory: ${{ inputs.working-directory }}
env:
PKG_NAME: ${{ needs.build.outputs.pkg-name }}
VERSION: ${{ needs.build.outputs.version }}
# Here we use:
# - The default regular PyPI index as the *primary* index, meaning
# that it takes priority (https://pypi.org/simple)
# - The test PyPI index as an extra index, so that any dependencies that
# are not found on test PyPI can be resolved and installed anyway.
# (https://test.pypi.org/simple). This will include the PKG_NAME==VERSION
# package because VERSION will not have been uploaded to regular PyPI yet.
# - attempt install again after 5 seconds if it fails because there is
# sometimes a delay in availability on test pypi
python-version: "3.x"
- name: Build distribution 📦
run: |
poetry run pip install \
--extra-index-url https://test.pypi.org/simple/ \
"$PKG_NAME==$VERSION" || \
( \
sleep 5 && \
poetry run pip install \
--extra-index-url https://test.pypi.org/simple/ \
"$PKG_NAME==$VERSION" \
)

# Replace all dashes in the package name with underscores,
# since that's how Python imports packages with dashes in the name.
IMPORT_NAME="$(echo "$PKG_NAME" | sed s/-/_/g)"

poetry run python -c "import $IMPORT_NAME; print(dir($IMPORT_NAME))"

- name: Import test dependencies
run: poetry install --with test,test_integration
working-directory: ${{ inputs.working-directory }}

# Overwrite the local version of the package with the test PyPI version.
- name: Import published package (again)
working-directory: ${{ inputs.working-directory }}
shell: bash
env:
PKG_NAME: ${{ needs.build.outputs.pkg-name }}
VERSION: ${{ needs.build.outputs.version }}
run: |
poetry run pip install \
--extra-index-url https://test.pypi.org/simple/ \
"$PKG_NAME==$VERSION"

- name: Run unit tests
run: make tests
working-directory: ${{ inputs.working-directory }}

- name: Run integration tests
env:
PARTNER_API_KEY: ${{ secrets.PARTNER_API_KEY }}
run: make integration_tests
working-directory: ${{ inputs.working-directory }}

- name: Get minimum versions
working-directory: ${{ inputs.working-directory }}
id: min-version
pip install build
python -m build
- name: Validate
run: |
poetry run pip install packaging
min_versions="$(poetry run python $GITHUB_WORKSPACE/.github/scripts/get_min_versions.py pyproject.toml)"
echo "min-versions=$min_versions" >> "$GITHUB_OUTPUT"
echo "min-versions=$min_versions"

- name: Run unit tests with minimum dependency versions
if: ${{ steps.min-version.outputs.min-versions != '' }}
pip install dist/*.whl
python -c "import langchain_oci;"
- name: Publish distribution 📦 to PyPI
env:
MIN_VERSIONS: ${{ steps.min-version.outputs.min-versions }}
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.GH_LC_OCI_PYPI_TOKEN }}
run: |
poetry run pip install $MIN_VERSIONS
make tests
working-directory: ${{ inputs.working-directory }}

publish:
needs:
- build
- test-pypi-publish
- pre-release-checks
runs-on: ubuntu-latest
permissions:
# This permission is used for trusted publishing:
# https://blog.pypi.org/posts/2023-04-20-introducing-trusted-publishers/
#
# Trusted publishing has to also be configured on PyPI for each package:
# https://docs.pypi.org/trusted-publishers/adding-a-publisher/
id-token: write

defaults:
run:
working-directory: ${{ inputs.working-directory }}

steps:
- uses: actions/checkout@v4

- name: Set up Python + Poetry ${{ env.POETRY_VERSION }}
uses: "./.github/actions/poetry_setup"
with:
python-version: ${{ env.PYTHON_VERSION }}
poetry-version: ${{ env.POETRY_VERSION }}
working-directory: ${{ inputs.working-directory }}
cache-key: release

- uses: actions/download-artifact@v4
with:
name: dist
path: ${{ inputs.working-directory }}/dist/

- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: ${{ inputs.working-directory }}/dist/
verbose: true
print-hash: true
# Temp workaround since attestations are on by default as of gh-action-pypi-publish v1\.11\.0
attestations: false

mark-release:
needs:
- build
- test-pypi-publish
- pre-release-checks
- publish
runs-on: ubuntu-latest
permissions:
# This permission is needed by `ncipollo/release-action` to
# create the GitHub release.
contents: write

defaults:
run:
working-directory: ${{ inputs.working-directory }}

steps:
- uses: actions/checkout@v4

- name: Set up Python + Poetry ${{ env.POETRY_VERSION }}
uses: "./.github/actions/poetry_setup"
with:
python-version: ${{ env.PYTHON_VERSION }}
poetry-version: ${{ env.POETRY_VERSION }}
working-directory: ${{ inputs.working-directory }}
cache-key: releaseartifact@v4

- uses: actions/download-artifact@v4
with:
name: dist
path: ${{ inputs.working-directory }}/dist/

- name: Create Release
uses: ncipollo/release-action@v1
with:
artifacts: "dist/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
generateReleaseNotes: true
tag: ${{ inputs.working-directory }}/v${{ needs.build.outputs.version }}
commit: main
pip install twine
twine upload dist/* -u $TWINE_USERNAME -p $TWINE_PASSWORD
9 changes: 5 additions & 4 deletions libs/oci/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@ version = "0.1.0"
description = "An integration package connecting OCI and LangChain"
authors = []
readme = "README.md"
repository = "https://github.com/langchain-ai/langchain-oci"
repository = "https://github.com/oracle/langchain-oracle"
license = "UPL"

[tool.poetry.urls]
"Source Code" = "https://github.com/langchain-ai/langchain-oci/tree/main/libs/oci"
"Source Code" = "https://github.com/oracle/langchain-oracle/tree/main/libs/oci"

[tool.poetry.dependencies]
python = ">=3.9,<4.0"
langchain-core = ">=0.3.15,<0.4"
langchain-openai = ">=0.3.9"
oci = ">=2.144.0"
oracle-ads = ">=2.13.3"
oci = ">=2.155.1"
oracle-ads = ">=2.13.16"
pydantic = ">=2,<3"
aiohttp = ">=3.12.14"

[tool.poetry.group.test]
optional = true
Expand Down