Repository: huggingface/transformers
Pull request: Automatic release script

Automatic releases to pypi when a tag is pushed; the workflow will still need to be validated by a core maintainer.

Changed files:
filename: .github/workflows/release.yml
patch: @@ -0,0 +1,60 @@
+name: Release
+on:
+  push:
+    tags:
+      - v*
+    branches:
+      - 'v*-release'
+
+jobs:
+  build_and_test:
+    name: build release
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: set up python
+        uses: actions/setup-python@v5
+        with:
+          python-version: "3.13"
+
+      - run: pip install setuptools
+      - run: pip install -e .
+      - run: make build-release
+
+      - run: pip uninstall -y transformers
+      - run: pip install dist/*.whl
+
+      - run: python -c "from transformers import *"
+
+      - run: pip install -e .[torch]
+      - run: python -c "from transformers import pipeline; classifier = pipeline('text-classification'); assert classifier('What a nice release')[0]['score'] > 0"
+
+      - name: Upload build artifacts
+        uses: actions/upload-artifact@v4
+        with:
+          name: python-dist
+          path: |
+            dist/**
+            build/**
+
+  upload_package:
+    needs: build_and_test
+    if: startsWith(github.ref, 'refs/tags/')
+    runs-on: ubuntu-latest
+    environment: pypi-release
+    permissions:
+      id-token: write
+
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: Download build artifacts
+        uses: actions/download-artifact@v4
+        with:
+          name: python-dist
+          path: .
+
+      - name: Publish package distributions to TestPyPI
+        uses: pypa/gh-action-pypi-publish@release/v1
+

filename: Makefile
patch: @@ -135,4 +135,3 @@ build-release:
 	rm -rf build
 	python setup.py bdist_wheel
 	python setup.py sdist
-	python utils/check_build.py

filename: setup.py
patch: @@ -36,35 +36,7 @@
 5. On the release branch, add a tag in git to mark the release: "git tag v<VERSION> -m 'Adds tag v<VERSION> for pypi' "
    Push the tag to git: git push --tags origin v<RELEASE>-release
 
-6. Build both the sources and the wheel. Do not change anything in setup.py between
-   creating the wheel and the source distribution (obviously).
-
-   Run `make build-release`. This will build the release and do some sanity checks for you. If this ends with an error
-   message, you need to fix things before going further.
-
-   You should now have a /dist directory with both .whl and .tar.gz source versions.
-
-7. Check that everything looks correct by uploading the package to the pypi test server:
-
-   twine upload dist/* -r testpypi
-   (pypi suggest using twine as other methods upload files via plaintext.)
-   You may have to specify the repository url, use the following command then:
-   twine upload dist/* -r testpypi --repository-url=https://test.pypi.org/legacy/
-
-   Check that you can install it in a virtualenv by running:
-   pip install -i https://test.pypi.org/simple/ transformers
-
-   Check you can run the following commands:
-   python -c "from transformers import pipeline; classifier = pipeline('text-classification'); print(classifier('What a nice release'))"
-   python -c "from transformers import *"
-   python utils/check_build.py --check_lib
-
-   If making a patch release, double check the bug you are patching is indeed resolved.
-
-8. Upload the final version to actual pypi:
-   twine upload dist/* -r pypi
-
-9. Copy the release notes from RELEASE.md to the tag in github once everything is looking hunky-dory.
+6. Have a core maintainer review and approve the deployment to pypi.
 """
 
 import re

filename: utils/check_build.py
patch: @@ -1,49 +0,0 @@
-# coding=utf-8
-# Copyright 2023 The HuggingFace Inc. team.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-import argparse
-import importlib
-from pathlib import Path
-
-
-# Test all the extensions added in the setup
-FILES_TO_FIND = [
-    "kernels/rwkv/wkv_cuda.cu",
-    "kernels/rwkv/wkv_op.cpp",
-    "kernels/falcon_mamba/selective_scan_with_ln_interface.py",
-    "kernels/falcon_mamba/__init__.py",
-    "kernels/__init__.py",
-    "models/graphormer/algos_graphormer.pyx",
-]
-
-
-def test_custom_files_are_present(transformers_path):
-    # Test all the extensions added in the setup
-    for file in FILES_TO_FIND:
-        if not (transformers_path / file).exists():
-            return False
-    return True
-
-
-if __name__ == "__main__":
-    parser = argparse.ArgumentParser()
-    parser.add_argument("--check_lib", action="store_true", help="Whether to check the build or the actual package.")
-    args = parser.parse_args()
-    if args.check_lib:
-        transformers_module = importlib.import_module("transformers")
-        transformers_path = Path(transformers_module.__file__).parent
-    else:
-        transformers_path = Path.cwd() / "build/lib/transformers"
-    if not test_custom_files_are_present(transformers_path):
-        raise ValueError("The built release does not contain the custom files. Fix this before going further!")