chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
name: Bleeding Edge Dependencies Test
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 6 1 * *' # First day of each month at 6:00 UTC
|
||||
workflow_dispatch: # Allow manual triggering
|
||||
|
||||
jobs:
|
||||
test-bleeding-edge:
|
||||
name: "Bleeding Edge Dependencies: Python Latest"
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: snok/latest-python-versions@v1
|
||||
id: python-versions
|
||||
with:
|
||||
min-version: '3.14'
|
||||
include-prereleases: false
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: ${{ fromJson(steps.python-versions.outputs.latest-python-versions)[0] }}
|
||||
- name: Download cleanvision test data
|
||||
run: |
|
||||
git clone https://github.com/cleanlab/assets.git
|
||||
mv assets/cleanlab_test_data ./tests/datalab/data
|
||||
- name: Install bleeding-edge dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install --pre --upgrade numpy scikit-learn pandas tqdm termcolor
|
||||
pip install --pre torch torchvision || pip install torch torchvision
|
||||
pip install -e ".[all]"
|
||||
- name: Install test dependencies
|
||||
run: pip install --no-cache-dir -r requirements-test-core.txt
|
||||
- name: Test with bleeding-edge deps
|
||||
run: pytest --verbose --maxfail=10 -m "not slow" --ignore=tests/test_frameworks.py --ignore=tests/test_model_pytorch_cnn.py
|
||||
@@ -0,0 +1,165 @@
|
||||
name: CI
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: '0 12 * * 1' # Monday at 12:00 UTC
|
||||
jobs:
|
||||
test-core:
|
||||
name: "Core Tests: Python ${{ matrix.python }} on ${{ matrix.os }}"
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- macos-latest
|
||||
- windows-latest
|
||||
python:
|
||||
- "3.10"
|
||||
- "3.11"
|
||||
- "3.12"
|
||||
- "3.13"
|
||||
- "3.14"
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
- name: Download cleanvision test data
|
||||
run: |
|
||||
git clone https://github.com/cleanlab/assets.git
|
||||
mv assets/cleanlab_test_data ./tests/datalab/data
|
||||
- name: Install cleanlab
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -e ".[all]"
|
||||
- name: Install core test dependencies
|
||||
run: pip install --no-cache-dir -r requirements-test-core.txt
|
||||
- name: Audit dependencies for vulnerabilities
|
||||
uses: pypa/gh-action-pip-audit@v1.1.0
|
||||
with:
|
||||
inputs: requirements-test-core.txt
|
||||
- name: Run core tests (excluding ML framework tests)
|
||||
run: pytest --verbose --maxfail=30 --order-tests --cov=cleanlab/ --cov-config .coveragerc --cov-report=xml -m "not slow" --ignore=tests/test_frameworks.py --ignore=tests/test_model_pytorch_cnn.py
|
||||
- uses: codecov/codecov-action@v5
|
||||
with:
|
||||
version: "v0.7.3"
|
||||
|
||||
test-ml-frameworks:
|
||||
name: "ML Framework Tests: Python ${{ matrix.python }} on ubuntu-latest"
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python:
|
||||
- "3.10"
|
||||
- "3.11"
|
||||
- "3.12"
|
||||
- "3.13"
|
||||
- "3.14"
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
- name: Download cleanvision test data
|
||||
run: |
|
||||
git clone https://github.com/cleanlab/assets.git
|
||||
mv assets/cleanlab_test_data ./tests/datalab/data
|
||||
- name: Install cleanlab
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -e ".[all]"
|
||||
- name: Install ML framework dependencies
|
||||
run: pip install --no-cache-dir -r requirements-dev.txt
|
||||
- name: Audit dependencies for vulnerabilities
|
||||
uses: pypa/gh-action-pip-audit@v1.1.0
|
||||
with:
|
||||
inputs: requirements-dev.txt
|
||||
- name: Run ML framework tests
|
||||
run: pytest --verbose --maxfail=30 tests/test_frameworks.py tests/test_model_pytorch_cnn.py
|
||||
test-without-extras-min-versions:
|
||||
name: Test without optional dependencies and with minimum compatible versions of dependencies
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: '3.10'
|
||||
- name: Install cleanlab
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install .
|
||||
- name: Install test dependencies
|
||||
run: |
|
||||
pip install pytest pipdeptree hypothesis
|
||||
pipdeptree -j > deps.json
|
||||
- name: Install minimum versions
|
||||
run: |
|
||||
python ./.github/get_min_dependencies.py
|
||||
pip install -r requirements-min.txt
|
||||
- name: Run tests
|
||||
run: |
|
||||
pytest tests/test_multilabel_classification.py tests/test_multiannotator.py tests/test_filter_count.py
|
||||
test-max-versions:
|
||||
name: "Maximum Dependency Versions: Python 3.14"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.14'
|
||||
- name: Download cleanvision test data
|
||||
run: |
|
||||
git clone https://github.com/cleanlab/assets.git
|
||||
mv assets/cleanlab_test_data ./tests/datalab/data
|
||||
- name: Install latest stable versions
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install --upgrade numpy scikit-learn pandas tqdm termcolor
|
||||
pip install --upgrade torch torchvision
|
||||
pip install -e ".[all]"
|
||||
- name: Install test dependencies
|
||||
run: pip install --no-cache-dir -r requirements-test-core.txt
|
||||
- name: Test with latest stable versions
|
||||
run: pytest --verbose --maxfail=10 -m "not slow" --ignore=tests/test_frameworks.py --ignore=tests/test_model_pytorch_cnn.py
|
||||
typecheck:
|
||||
name: Type check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: '3.14'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install ".[all]" # install dependencies
|
||||
pip install --no-cache-dir -r requirements-test-core.txt # install core dependencies and type stubs
|
||||
- name: Type check
|
||||
run: mypy --install-types --non-interactive cleanlab
|
||||
fmt:
|
||||
name: Format
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: psf/black@stable
|
||||
flake8:
|
||||
name: Check for unused/wildcard imports
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: '3.14'
|
||||
- name: Install flake8
|
||||
run: pip install flake8
|
||||
- name: Lint with flake8
|
||||
run: flake8 cleanlab tests
|
||||
nblint:
|
||||
name: Lint Notebooks
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: cleanlab/nblint-action@v1
|
||||
with:
|
||||
directory: 'docs'
|
||||
@@ -0,0 +1,210 @@
|
||||
name: GitHub Pages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-24.04
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Pandoc
|
||||
# pin Pandoc version
|
||||
run: |
|
||||
cd /tmp
|
||||
wget https://github.com/jgm/pandoc/releases/download/2.19.2/pandoc-2.19.2-linux-amd64.tar.gz
|
||||
sudo tar xzvf pandoc-2.19.2-linux-amd64.tar.gz --strip-components 1 -C /usr/local
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.11"
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: "22"
|
||||
|
||||
- name: Install FFmpeg
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ffmpeg
|
||||
|
||||
- name: Upgrade pip
|
||||
run: python3 -m pip install --upgrade pip
|
||||
|
||||
# Caching removed to resolve disk space issues
|
||||
# Heavy ML packages (TensorFlow, PyTorch, HuggingFace) will be downloaded fresh each run
|
||||
# but this avoids the 3.7GB cache that causes "No space left on device" errors
|
||||
|
||||
- name: Install cleanlab
|
||||
run: pip install -e ".[all]"
|
||||
|
||||
- name: Install dependencies
|
||||
run: python3 -m pip install -r docs/requirements.txt
|
||||
|
||||
- name: Install katex
|
||||
run: npm install -g katex
|
||||
|
||||
- name: Find and replace "%pip install cleanlab" with master branch in .ipynb files
|
||||
if: ${{ github.ref_type == 'branch' }}
|
||||
uses: jacobtomlinson/gha-find-replace@v2
|
||||
with:
|
||||
find: "%pip install cleanlab ${{ '#' }} for colab"
|
||||
replace: "%pip install git+https://github.com/${{ github.repository }}.git@${{ github.sha }}"
|
||||
include: "docs/source**.ipynb"
|
||||
|
||||
- name: Find and replace "%pip install cleanlab" with release tag in .ipynb files
|
||||
if: ${{ github.ref_type == 'tag' }}
|
||||
uses: jacobtomlinson/gha-find-replace@v2
|
||||
with:
|
||||
find: "%pip install cleanlab ${{ '#' }} for colab"
|
||||
replace: "%pip install cleanlab==${{ github.ref_name }}"
|
||||
include: "docs/source**.ipynb"
|
||||
|
||||
- name: Add and Commit changes to .ipynb files
|
||||
run: |
|
||||
git config --global user.email "actions@github.com"
|
||||
git config --global user.name "GitHub Actions"
|
||||
git add -A && git commit -m "Change cleanlab ver in .ipynb files"
|
||||
|
||||
- name: Change tag to the latest commit
|
||||
if: ${{ github.ref_type == 'tag' }}
|
||||
run: |
|
||||
git tag -f $GITHUB_REF_NAME
|
||||
|
||||
- name: Run Sphinx with sphinx-multiversion wrapper - branch trigger
|
||||
if: ${{ github.ref_type == 'branch' }}
|
||||
env:
|
||||
TF_CPP_MIN_LOG_LEVEL: 3
|
||||
HF_HOME: /tmp/hf_cache
|
||||
HF_HUB_DISABLE_SYMLINKS_WARNING: 1
|
||||
TRANSFORMERS_CACHE: /tmp/transformers
|
||||
TORCH_HOME: /tmp/torch
|
||||
run: sphinx-multiversion docs/source cleanlab-docs -D smv_branch_whitelist=${{ github.ref_name }} -D smv_tag_whitelist=None
|
||||
|
||||
- name: Run Sphinx with sphinx-multiversion wrapper - tag trigger
|
||||
if: ${{ github.ref_type == 'tag' }}
|
||||
env:
|
||||
TF_CPP_MIN_LOG_LEVEL: 3
|
||||
HF_HOME: /tmp/hf_cache
|
||||
HF_HUB_DISABLE_SYMLINKS_WARNING: 1
|
||||
TRANSFORMERS_CACHE: /tmp/transformers
|
||||
TORCH_HOME: /tmp/torch
|
||||
run: sphinx-multiversion docs/source cleanlab-docs -D smv_branch_whitelist=None -D smv_tag_whitelist=${{ github.ref_name }}
|
||||
|
||||
- name: Debug temporary cache usage (not saved)
|
||||
run: |
|
||||
echo "=== Temporary Cache Usage ==="
|
||||
echo "These caches are created in /tmp and cleaned up after build:"
|
||||
echo " /tmp/hf_cache: $(du -sh /tmp/hf_cache 2>/dev/null | cut -f1 || echo 'not found')"
|
||||
echo " /tmp/transformers: $(du -sh /tmp/transformers 2>/dev/null | cut -f1 || echo 'not found')"
|
||||
echo " /tmp/torch: $(du -sh /tmp/torch 2>/dev/null | cut -f1 || echo 'not found')"
|
||||
echo "Pip cache directory: $(pip cache dir)"
|
||||
echo "Pip cache size: $(du -sh $(pip cache dir) 2>/dev/null | cut -f1 || echo 'not found')"
|
||||
echo "========================"
|
||||
|
||||
- name: Get latest stable release
|
||||
id: stable_release
|
||||
continue-on-error: true
|
||||
uses: pozetroninc/github-action-get-latest-release@master
|
||||
with:
|
||||
owner: ${{ github.repository_owner }}
|
||||
repo: cleanlab
|
||||
excludes: prerelease, draft
|
||||
|
||||
- name: Create latest_release.txt file
|
||||
if: ${{ steps.stable_release.outcome == 'success' }}
|
||||
run: echo ${{ steps.stable_release.outputs.release }} > cleanlab-docs/latest_release.txt
|
||||
|
||||
- name: Find and replace "placeholder_version_number" in versioning.js
|
||||
if: ${{ steps.stable_release.outcome == 'success' }}
|
||||
uses: jacobtomlinson/gha-find-replace@v2
|
||||
with:
|
||||
find: "placeholder_version_number"
|
||||
replace: ${{ steps.stable_release.outputs.release }}
|
||||
include: "docs/source/_templates/versioning.js"
|
||||
|
||||
- name: Find and replace "placeholder_commit_hash" in versioning.js
|
||||
uses: jacobtomlinson/gha-find-replace@v2
|
||||
with:
|
||||
find: "placeholder_commit_hash"
|
||||
replace: ${{ github.sha }}
|
||||
include: "docs/source/_templates/versioning.js"
|
||||
|
||||
- name: Copy versioning JS file to cleanlab-docs/
|
||||
run: |
|
||||
cp docs/source/_templates/versioning.js cleanlab-docs/versioning.js
|
||||
|
||||
- name: Find and replace "stable_url" in redirect-to-stable.html
|
||||
if: ${{ github.ref_type == 'tag' && steps.stable_release.outcome == 'success' }}
|
||||
uses: jacobtomlinson/gha-find-replace@v2
|
||||
with:
|
||||
find: "stable_url"
|
||||
replace: ${{ env.DOCS_SITE_URL }}stable/index.html
|
||||
include: "docs/source/_templates/redirect-to-stable.html"
|
||||
|
||||
- name: Copy redirecting HTML file to cleanlab-docs/
|
||||
if: ${{ github.ref_type == 'tag' }}
|
||||
run: cp docs/source/_templates/redirect-to-stable.html cleanlab-docs/index.html
|
||||
|
||||
- name: Update OpenGraph URLs in HTML files
|
||||
# This code fixes the URLs in the HTML files with OpenGraph tags.
|
||||
# It uses a regular expression to capture two parts of the URL:
|
||||
# $1: The first part of the URL, including the protocol and domain.
|
||||
# $2: The rest of the URL, including the path and query string.
|
||||
# The replacement string combines the captured parts with the ref name.
|
||||
# This ensures that the ref name is inserted into the URL correctly.
|
||||
env:
|
||||
REF_URL_SEGMENT: ${{ (github.ref_type == 'tag' && steps.stable_release.outcome == 'success') && 'stable' || github.ref_name }}
|
||||
uses: jacobtomlinson/gha-find-replace@v2
|
||||
with:
|
||||
find: '(<meta property="og:url" content="https?://[^/]+)/([^"]+")'
|
||||
replace: '$1/${{ env.REF_URL_SEGMENT }}/$2'
|
||||
include: "cleanlab-docs/**/*.html"
|
||||
regex: true
|
||||
|
||||
- name: Deploy
|
||||
if: ${{ (github.ref == 'refs/heads/master') || (github.ref_type == 'tag') }}
|
||||
uses: peaceiris/actions-gh-pages@v4
|
||||
with:
|
||||
deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
|
||||
external_repository: ${{ github.repository_owner }}/cleanlab-docs
|
||||
publish_branch: master
|
||||
publish_dir: cleanlab-docs
|
||||
keep_files: true
|
||||
exclude_assets: ""
|
||||
|
||||
- uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: docs-html
|
||||
path: cleanlab-docs
|
||||
retention-days: 1 # don't need this except in link checking step below
|
||||
|
||||
links:
|
||||
needs: deploy
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: docs-html
|
||||
path: cleanlab-docs
|
||||
- uses: anishathalye/proof-html@v1
|
||||
with:
|
||||
directory: ./cleanlab-docs
|
||||
external_only: true
|
||||
url_ignore_re: |
|
||||
^https://pradyunsg.me/
|
||||
^https://keras.io/
|
||||
@@ -0,0 +1,35 @@
|
||||
name: GitHub Markdown Links
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: "0 8 * * 6"
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: sudo apt-get update -y
|
||||
- run: >-
|
||||
sudo apt-get install -y
|
||||
pandoc
|
||||
- uses: actions/checkout@v6
|
||||
- run: |
|
||||
find . -name '*.html' -delete
|
||||
- run: |
|
||||
find . -name '*.md' -exec pandoc -i {} -o {}.html \;
|
||||
- uses: anishathalye/proof-html@v2
|
||||
with:
|
||||
directory: .
|
||||
check_html: false
|
||||
check_favicon: false
|
||||
ignore_missing_alt: true
|
||||
tokens: |
|
||||
{"https://github.com": "${{ secrets.GITHUB_TOKEN }}"}
|
||||
ignore_url: |
|
||||
https://jair.org/index.php/jair/article/view/12125
|
||||
https://stackoverflow.com/questions/41573587/what-is-the-difference-between-venv-pyvenv-pyenv-virtualenv-virtualenvwrappe
|
||||
ignore_url_re: |
|
||||
https://www.gnu.org/software/wget
|
||||
swap_urls: |
|
||||
{"^(\\..*)\\.md(#?.*)$": "\\1.md.html\\2",
|
||||
"^(https://github\\.com/.*)#.*$": "\\1"}
|
||||
@@ -0,0 +1,154 @@
|
||||
name: Manual TestPyPI Release
|
||||
|
||||
on:
|
||||
workflow_dispatch: # Manual trigger only
|
||||
inputs:
|
||||
reason:
|
||||
description: 'Reason for this test release'
|
||||
required: false
|
||||
default: 'Testing changes before official release'
|
||||
|
||||
jobs:
|
||||
extract_project_name:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
cleanlab_package_name: ${{ steps.extract_name.outputs.value }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: TOML Reader
|
||||
uses: SebRollen/toml-action@v1.2.0
|
||||
id: extract_name
|
||||
with:
|
||||
file: "pyproject.toml"
|
||||
field: "project.name"
|
||||
|
||||
build:
|
||||
needs: extract_project_name
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Remove tests directory
|
||||
run: |
|
||||
TEST_DIR=$(find . -type d -name "tests")
|
||||
if [ -n "$TEST_DIR" ]; then
|
||||
rm -rf $TEST_DIR
|
||||
else
|
||||
echo "No tests directory found! This is unexpected."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.11
|
||||
|
||||
- name: Modify version for TestPyPI
|
||||
run: |
|
||||
# Add .dev suffix with run number for TestPyPI
|
||||
sed -i "s/__version__ = \"\(.*\)\"/__version__ = \"\1.dev${{ github.run_number }}\"/" cleanlab/version.py
|
||||
echo "Modified version for TestPyPI:"
|
||||
grep "__version__" cleanlab/version.py
|
||||
|
||||
- name: Install dependencies
|
||||
run: pip install --upgrade "setuptools>=65.0,<70.0" wheel twine==5.0.0 pkginfo
|
||||
|
||||
- name: Clean build artifacts
|
||||
run: |
|
||||
rm -rf build/ dist/ *.egg-info cleanlab.egg-info/
|
||||
|
||||
- name: Perform some tests on the metadata of the package
|
||||
run: |
|
||||
python setup.py check --metadata --strict
|
||||
|
||||
- name: Build package
|
||||
run: |
|
||||
python setup.py sdist bdist_wheel
|
||||
|
||||
- name: Test package
|
||||
run: |
|
||||
twine check dist/*
|
||||
|
||||
- name: Display package info
|
||||
run: |
|
||||
echo "📦 Built packages:"
|
||||
ls -lh dist/
|
||||
echo ""
|
||||
echo "📝 Reason: ${{ github.event.inputs.reason }}"
|
||||
|
||||
- name: Store build artifacts
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: package
|
||||
path: dist/*
|
||||
|
||||
publish-testpypi:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
|
||||
|
||||
steps:
|
||||
- name: Fetch build artifacts
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: package
|
||||
path: dist/
|
||||
|
||||
- name: Publish to TestPyPI
|
||||
uses: pypa/gh-action-pypi-publish@e53eb8b103ffcb59469888563dc324e3c8ba6f06
|
||||
with:
|
||||
repository-url: https://test.pypi.org/legacy/
|
||||
verify-metadata: true
|
||||
|
||||
test-basic-import:
|
||||
needs: [publish-testpypi, extract_project_name]
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.11
|
||||
|
||||
- name: Install package from TestPyPI
|
||||
env:
|
||||
CLEANLAB_PACKAGE_NAME: ${{ needs.extract_project_name.outputs.cleanlab_package_name }}
|
||||
run: pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ $CLEANLAB_PACKAGE_NAME
|
||||
|
||||
- name: Test importing package
|
||||
run: |
|
||||
python -c "import cleanlab
|
||||
from cleanlab.outlier import OutOfDistribution
|
||||
ood = OutOfDistribution()
|
||||
print(ood)
|
||||
print('✅ Basic import test passed!')
|
||||
print('Version:', cleanlab.__version__)"
|
||||
|
||||
test-extras-import:
|
||||
needs: [publish-testpypi, extract_project_name]
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.11
|
||||
|
||||
- name: Install package with extras
|
||||
env:
|
||||
CLEANLAB_PACKAGE_NAME: ${{ needs.extract_project_name.outputs.cleanlab_package_name }}
|
||||
run: pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ $CLEANLAB_PACKAGE_NAME[all]
|
||||
|
||||
- name: Test importing package with extras
|
||||
run: |
|
||||
python -c "import cleanlab
|
||||
from cleanlab import Datalab
|
||||
lab = Datalab({'a': [1, 2, 3, 4, 5], 'b': ['a', 'b', 'c', 'b', 'a']})
|
||||
print(lab)
|
||||
print('✅ Extras import test passed!')
|
||||
print('Version:', cleanlab.__version__)"
|
||||
@@ -0,0 +1,260 @@
|
||||
name: Release Build Publish
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [ published ]
|
||||
|
||||
jobs:
|
||||
extract_project_name:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
cleanlab_package_name: ${{ steps.extract_name.outputs.value }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: TOML Reader
|
||||
uses: SebRollen/toml-action@v1.2.0
|
||||
id: extract_name
|
||||
with:
|
||||
file: "pyproject.toml"
|
||||
field: "project.name"
|
||||
|
||||
store_published_version:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.compare.outputs.version }}
|
||||
steps:
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.11
|
||||
|
||||
- name: Install package
|
||||
run: pip install .
|
||||
|
||||
- name: Compare the published version with the package version
|
||||
id: compare
|
||||
run: |
|
||||
TAG_NAME="${{ github.ref_name }}"
|
||||
# TAG_NAME must be in the form "v1.2.3[...]", error if it doesn't match
|
||||
if [[ ! $TAG_NAME =~ ^v[0-9]+\.[0-9]+\.[0-9]+ ]]; then
|
||||
echo "Tag name '$TAG_NAME' does not match the expected pattern 'vX.Y.Z'"
|
||||
exit 1
|
||||
fi
|
||||
# Strip the 'v' prefix from the tag, and store the version in an output variable
|
||||
VERSION=${TAG_NAME:1} # Strip the 'v' prefix from the tag
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
# Check that the package version matches the tag version
|
||||
PACKAGE_VERSION=$(python -c "import cleanlab; print(cleanlab.__version__)")
|
||||
if [ "$PACKAGE_VERSION" != "$VERSION" ]; then
|
||||
echo "Package version $PACKAGE_VERSION does not match tag $VERSION"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
build:
|
||||
needs: [store_published_version, extract_project_name]
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Remove tests directory
|
||||
run: |
|
||||
# Remove the tests directory from the package
|
||||
TEST_DIR=$(find . -type d -name "tests")
|
||||
if [ -n "$TEST_DIR" ]; then
|
||||
rm -rf $TEST_DIR
|
||||
else
|
||||
echo "No tests directory found! This is unexpected."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.11
|
||||
|
||||
- name: Install dependencies
|
||||
run: pip install --upgrade "setuptools>=65.0,<70.0" wheel twine==5.0.0 pkginfo
|
||||
|
||||
- name: Clean build artifacts
|
||||
run: |
|
||||
rm -rf build/ dist/ *.egg-info cleanlab.egg-info/
|
||||
|
||||
- name: Perform some tests on the metadata of the package
|
||||
run: |
|
||||
python setup.py check --metadata --strict
|
||||
|
||||
- name: Build package
|
||||
run: |
|
||||
python setup.py sdist bdist_wheel
|
||||
|
||||
- name: Test package
|
||||
run: |
|
||||
twine check dist/*
|
||||
|
||||
- name: Verify contents of the tar.gz
|
||||
env:
|
||||
CLEANLAB_PACKAGE_NAME: ${{ needs.extract_project_name.outputs.cleanlab_package_name }}
|
||||
run: |
|
||||
# Extract the tar.gz to a temporary directory
|
||||
TMPDIR=$(mktemp -d)
|
||||
tar -xzf dist/*.tar.gz -C $TMPDIR
|
||||
PACKAGE_DIR=$TMPDIR/$(ls $TMPDIR) # Assuming there's only one directory extracted
|
||||
|
||||
# Define expected files and directories
|
||||
EXPECTED_FILES="LICENSE PKG-INFO MANIFEST.in DEVELOPMENT.md CONTRIBUTING.md CODE_OF_CONDUCT.md README.md pyproject.toml setup.cfg setup.py"
|
||||
EXPECTED_DIRS="cleanlab $CLEANLAB_PACKAGE_NAME.egg-info"
|
||||
|
||||
# Collect actual top-level files and directories
|
||||
ACTUAL_CONTENTS=$(ls $PACKAGE_DIR)
|
||||
ACTUAL_FILES=$(find $PACKAGE_DIR -maxdepth 1 -type f -exec basename {} \;)
|
||||
ACTUAL_DIRS=$(find $PACKAGE_DIR -maxdepth 1 -type d -exec basename {} \; | sed "1d") # Remove the package directory itself from the list
|
||||
|
||||
# Function to check for unexpected or missing files and directories
|
||||
check_contents() {
|
||||
local missing=0
|
||||
# Check for expected files
|
||||
for expected_file in $EXPECTED_FILES; do
|
||||
echo $ACTUAL_FILES | grep -qw $expected_file || { echo "Missing expected file: $expected_file"; missing=1; }
|
||||
done
|
||||
|
||||
# Check for expected directories
|
||||
for expected_dir in $EXPECTED_DIRS; do
|
||||
echo $ACTUAL_DIRS | grep -qw $expected_dir || { echo "Missing expected directory: $expected_dir"; missing=1; }
|
||||
done
|
||||
|
||||
# Check for unexpected files and directories
|
||||
for actual in $ACTUAL_CONTENTS; do
|
||||
echo $EXPECTED_FILES $EXPECTED_DIRS | grep -qw $actual || { echo "Unexpected item in package: $actual"; missing=1; }
|
||||
done
|
||||
|
||||
# Exit if anything unexpected or missing
|
||||
if [ $missing -ne 0 ]; then
|
||||
echo "Package content verification failed."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Execute checks
|
||||
check_contents
|
||||
|
||||
- name: Store build artifacts
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: package
|
||||
path: dist/*
|
||||
|
||||
publish-testpypi:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
|
||||
|
||||
steps:
|
||||
- name: Fetch build artifacts
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: package
|
||||
path: dist/
|
||||
|
||||
- name: Publish to TestPyPI
|
||||
uses: pypa/gh-action-pypi-publish@e53eb8b103ffcb59469888563dc324e3c8ba6f06
|
||||
with:
|
||||
repository-url: https://test.pypi.org/legacy/
|
||||
verify-metadata: true
|
||||
|
||||
verify-version:
|
||||
needs: [publish-testpypi, store_published_version, extract_project_name]
|
||||
runs-on: ubuntu-latest
|
||||
environment: testpypi
|
||||
|
||||
steps:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.11
|
||||
|
||||
- name: Install package from TestPyPI
|
||||
env:
|
||||
CLEANLAB_PACKAGE_NAME: ${{ needs.extract_project_name.outputs.cleanlab_package_name }}
|
||||
run: pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ $CLEANLAB_PACKAGE_NAME
|
||||
|
||||
- name: Verify the published version
|
||||
env:
|
||||
VERSION: ${{ needs.store_published_version.outputs.version }}
|
||||
run: |
|
||||
TEST_IMPORT_VERSION=$(python -c "import cleanlab; print(cleanlab.__version__)")
|
||||
if [ "$TEST_IMPORT_VERSION" != "$VERSION" ]; then
|
||||
echo "Imported version $TEST_IMPORT_VERSION does not match tag $VERSION"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
test-basic-import:
|
||||
needs: [verify-version, extract_project_name]
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.11
|
||||
|
||||
- name: Install package from TestPyPI
|
||||
env:
|
||||
CLEANLAB_PACKAGE_NAME: ${{ needs.extract_project_name.outputs.cleanlab_package_name }}
|
||||
run: pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ $CLEANLAB_PACKAGE_NAME
|
||||
|
||||
- name: Test importing package
|
||||
run: |
|
||||
python -c "import cleanlab
|
||||
from cleanlab.outlier import OutOfDistribution
|
||||
ood = OutOfDistribution()
|
||||
print(ood)"
|
||||
|
||||
test-extras-import:
|
||||
needs: [verify-version, extract_project_name]
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.11
|
||||
|
||||
- name: Install package with extras
|
||||
env:
|
||||
CLEANLAB_PACKAGE_NAME: ${{ needs.extract_project_name.outputs.cleanlab_package_name }}
|
||||
run: pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ $CLEANLAB_PACKAGE_NAME[all]
|
||||
|
||||
- name: Test importing package with extras
|
||||
run: |
|
||||
python -c "import cleanlab
|
||||
from cleanlab import Datalab
|
||||
lab = Datalab({'a': [1, 2, 3, 4, 5], 'b': ['a', 'b', 'c', 'b', 'a']})
|
||||
print(lab)"
|
||||
|
||||
publish-pypi:
|
||||
needs: [test-basic-import, test-extras-import]
|
||||
runs-on: ubuntu-latest
|
||||
environment: pypi
|
||||
permissions:
|
||||
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
|
||||
|
||||
steps:
|
||||
- name: Fetch build artifacts
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: package
|
||||
path: dist/
|
||||
|
||||
- name: Publish to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@e53eb8b103ffcb59469888563dc324e3c8ba6f06
|
||||
with:
|
||||
verify-metadata: true
|
||||
Reference in New Issue
Block a user