1- name : release
2- run-name : Release ${{ inputs.working-directory }} by @${{ github.actor }}
3- on :
4- workflow_call :
5- inputs :
6- working-directory :
7- required : true
8- type : string
9- description : " From which folder this pipeline executes"
10- workflow_dispatch :
11- inputs :
12- working-directory :
13- required : true
14- type : string
15- default : ' libs/oci'
16-
17- env :
18- PYTHON_VERSION : " 3.11"
19- POETRY_VERSION : " 1.7.1"
20-
21- jobs :
22- build :
23- if : github.ref == 'refs/heads/main'
24- runs-on : ubuntu-latest
25-
26- outputs :
27- pkg-name : ${{ steps.check-version.outputs.pkg-name }}
28- version : ${{ steps.check-version.outputs.version }}
29-
30- steps :
31- - uses : actions/checkout@v4
32-
33- - name : Set up Python + Poetry ${{ env.POETRY_VERSION }}
34- uses : " ./.github/actions/poetry_setup"
35- with :
36- python-version : ${{ env.PYTHON_VERSION }}
37- poetry-version : ${{ env.POETRY_VERSION }}
38- working-directory : ${{ inputs.working-directory }}
39- cache-key : release
1+ # This workflow will upload a Python Package to PyPI when a release is created
2+ # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
403
41- # We want to keep this build stage *separate* from the release stage,
42- # so that there's no sharing of permissions between them.
43- # The release stage has trusted publishing and GitHub repo contents write access,
44- # and we want to keep the scope of that access limited just to the release job.
45- # Otherwise, a malicious `build` step (e.g. via a compromised dependency)
46- # could get access to our GitHub or PyPI credentials.
47- #
48- # Per the trusted publishing GitHub Action:
49- # > It is strongly advised to separate jobs for building [...]
50- # > from the publish job.
51- # https://github.com/pypa/gh-action-pypi-publish#non-goals
52- - name : Build project for distribution
53- run : poetry build
54- working-directory : ${{ inputs.working-directory }}
4+ # This workflow uses actions that are not certified by GitHub.
5+ # They are provided by a third-party and are governed by
6+ # separate terms of service, privacy policy, and support
7+ # documentation.
558
56- - name : Upload build
57- uses : actions/upload-artifact@v4
58- with :
59- name : dist
60- path : ${{ inputs.working-directory }}/dist/
9+ name : Upload Python Package
6110
62- - name : Check Version
63- id : check-version
64- shell : bash
65- working-directory : ${{ inputs.working-directory }}
66- run : |
67- echo pkg-name="$(poetry version | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT
68- echo version="$(poetry version --short)" >> $GITHUB_OUTPUT
11+ on :
12+ release :
13+ types : [published]
14+ workflow_dispatch :
6915
70- test-pypi-publish :
71- needs :
72- - build
73- uses :
74- ./.github/workflows/_test_release.yml
75- permissions : write-all
76- with :
77- working-directory : ${{ inputs.working-directory }}
78- secrets : inherit
16+ permissions :
17+ contents : read
7918
80- pre-release-checks :
81- needs :
82- - build
83- - test-pypi-publish
19+ jobs :
20+ build-n-publish :
21+ name : Build and publish Python 🐍 distribution 📦 to PyPI
8422 runs-on : ubuntu-latest
23+ defaults :
24+ run :
25+ working-directory : libs/oci # Set default for all steps
26+ environment :
27+ name : pypi
28+ url : https://pypi.org/p/langchain-oci
8529 steps :
8630 - uses : actions/checkout@v4
87-
88- # We explicitly *don't* set up caching here. This ensures our tests are
89- # maximally sensitive to catching breakage.
90- #
91- # For example, here's a way that caching can cause a falsely-passing test:
92- # - Make the langchain package manifest no longer list a dependency package
93- # as a requirement. This means it won't be installed by `pip install`,
94- # and attempting to use it would cause a crash.
95- # - That dependency used to be required, so it may have been cached.
96- # When restoring the venv packages from cache, that dependency gets included.
97- # - Tests pass, because the dependency is present even though it wasn't specified.
98- # - The package is published, and it breaks on the missing dependency when
99- # used in the real world.
100-
101- - name : Set up Python + Poetry ${{ env.POETRY_VERSION }}
102- uses : " ./.github/actions/poetry_setup"
31+ - name : Set up Python
32+ uses : actions/setup-python@v5
10333 with :
104- python-version : ${{ env.PYTHON_VERSION }}
105- poetry-version : ${{ env.POETRY_VERSION }}
106- working-directory : ${{ inputs.working-directory }}
107-
108- - name : Import published package
109- shell : bash
110- working-directory : ${{ inputs.working-directory }}
111- env :
112- PKG_NAME : ${{ needs.build.outputs.pkg-name }}
113- VERSION : ${{ needs.build.outputs.version }}
114- # Here we use:
115- # - The default regular PyPI index as the *primary* index, meaning
116- # that it takes priority (https://pypi.org/simple)
117- # - The test PyPI index as an extra index, so that any dependencies that
118- # are not found on test PyPI can be resolved and installed anyway.
119- # (https://test.pypi.org/simple). This will include the PKG_NAME==VERSION
120- # package because VERSION will not have been uploaded to regular PyPI yet.
121- # - attempt install again after 5 seconds if it fails because there is
122- # sometimes a delay in availability on test pypi
34+ python-version : " 3.x"
35+ - name : Build distribution 📦
12336 run : |
124- poetry run pip install \
125- --extra-index-url https://test.pypi.org/simple/ \
126- "$PKG_NAME==$VERSION" || \
127- ( \
128- sleep 5 && \
129- poetry run pip install \
130- --extra-index-url https://test.pypi.org/simple/ \
131- "$PKG_NAME==$VERSION" \
132- )
133-
134- # Replace all dashes in the package name with underscores,
135- # since that's how Python imports packages with dashes in the name.
136- IMPORT_NAME="$(echo "$PKG_NAME" | sed s/-/_/g)"
137-
138- poetry run python -c "import $IMPORT_NAME; print(dir($IMPORT_NAME))"
139-
140- - name : Import test dependencies
141- run : poetry install --with test,test_integration
142- working-directory : ${{ inputs.working-directory }}
143-
144- # Overwrite the local version of the package with the test PyPI version.
145- - name : Import published package (again)
146- working-directory : ${{ inputs.working-directory }}
147- shell : bash
148- env :
149- PKG_NAME : ${{ needs.build.outputs.pkg-name }}
150- VERSION : ${{ needs.build.outputs.version }}
151- run : |
152- poetry run pip install \
153- --extra-index-url https://test.pypi.org/simple/ \
154- "$PKG_NAME==$VERSION"
155-
156- - name : Run unit tests
157- run : make tests
158- working-directory : ${{ inputs.working-directory }}
159-
160- - name : Run integration tests
161- env :
162- PARTNER_API_KEY : ${{ secrets.PARTNER_API_KEY }}
163- run : make integration_tests
164- working-directory : ${{ inputs.working-directory }}
165-
166- - name : Get minimum versions
167- working-directory : ${{ inputs.working-directory }}
168- id : min-version
37+ pip install build
38+ python -m build
39+ - name : Validate
16940 run : |
170- poetry run pip install packaging
171- min_versions="$(poetry run python $GITHUB_WORKSPACE/.github/scripts/get_min_versions.py pyproject.toml)"
172- echo "min-versions=$min_versions" >> "$GITHUB_OUTPUT"
173- echo "min-versions=$min_versions"
174-
175- - name : Run unit tests with minimum dependency versions
176- if : ${{ steps.min-version.outputs.min-versions != '' }}
41+ pip install dist/*.whl
42+ python -c "import langchain_oci;"
43+ - name : Publish distribution 📦 to PyPI
17744 env :
178- MIN_VERSIONS : ${{ steps.min-version.outputs.min-versions }}
45+ TWINE_USERNAME : __token__
46+ TWINE_PASSWORD : ${{ secrets.GH_LC_OCI_PYPI_TOKEN }}
17947 run : |
180- poetry run pip install $MIN_VERSIONS
181- make tests
182- working-directory : ${{ inputs.working-directory }}
183-
184- publish :
185- needs :
186- - build
187- - test-pypi-publish
188- - pre-release-checks
189- runs-on : ubuntu-latest
190- permissions :
191- # This permission is used for trusted publishing:
192- # https://blog.pypi.org/posts/2023-04-20-introducing-trusted-publishers/
193- #
194- # Trusted publishing has to also be configured on PyPI for each package:
195- # https://docs.pypi.org/trusted-publishers/adding-a-publisher/
196- id-token : write
197-
198- defaults :
199- run :
200- working-directory : ${{ inputs.working-directory }}
201-
202- steps :
203- - uses : actions/checkout@v4
204-
205- - name : Set up Python + Poetry ${{ env.POETRY_VERSION }}
206- uses : " ./.github/actions/poetry_setup"
207- with :
208- python-version : ${{ env.PYTHON_VERSION }}
209- poetry-version : ${{ env.POETRY_VERSION }}
210- working-directory : ${{ inputs.working-directory }}
211- cache-key : release
212-
213- - uses : actions/download-artifact@v4
214- with :
215- name : dist
216- path : ${{ inputs.working-directory }}/dist/
217-
218- - name : Publish package distributions to PyPI
219- uses : pypa/gh-action-pypi-publish@release/v1
220- with :
221- packages-dir : ${{ inputs.working-directory }}/dist/
222- verbose : true
223- print-hash : true
224- # Temp workaround since attestations are on by default as of gh-action-pypi-publish v1\.11\.0
225- attestations : false
226-
227- mark-release :
228- needs :
229- - build
230- - test-pypi-publish
231- - pre-release-checks
232- - publish
233- runs-on : ubuntu-latest
234- permissions :
235- # This permission is needed by `ncipollo/release-action` to
236- # create the GitHub release.
237- contents : write
238-
239- defaults :
240- run :
241- working-directory : ${{ inputs.working-directory }}
242-
243- steps :
244- - uses : actions/checkout@v4
245-
246- - name : Set up Python + Poetry ${{ env.POETRY_VERSION }}
247- uses : " ./.github/actions/poetry_setup"
248- with :
249- python-version : ${{ env.PYTHON_VERSION }}
250- poetry-version : ${{ env.POETRY_VERSION }}
251- working-directory : ${{ inputs.working-directory }}
252- cache-key : releaseartifact@v4
253-
254- - uses : actions/download-artifact@v4
255- with :
256- name : dist
257- path : ${{ inputs.working-directory }}/dist/
258-
259- - name : Create Release
260- uses : ncipollo/release-action@v1
261- with :
262- artifacts : " dist/*"
263- token : ${{ secrets.GITHUB_TOKEN }}
264- draft : false
265- generateReleaseNotes : true
266- tag : ${{ inputs.working-directory }}/v${{ needs.build.outputs.version }}
267- commit : main
48+ pip install twine
49+ twine upload dist/* -u $TWINE_USERNAME -p $TWINE_PASSWORD
0 commit comments