261 lines
8.5 KiB
YAML
261 lines
8.5 KiB
YAML
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
|