diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c1fe300986..b41964b673 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -83,10 +83,11 @@ jobs: - name: Detect version id: version + env: + RELEASE_TYPE: ${{ inputs.release_type }} + VERSION_OVERRIDE: ${{ inputs.version_override }} run: | set -euo pipefail - RELEASE_TYPE="${{ inputs.release_type }}" - VERSION_OVERRIDE="${{ inputs.version_override }}" if [[ -n "$VERSION_OVERRIDE" ]]; then # Strip 'v' prefix if present @@ -319,340 +320,4 @@ jobs: # Strategy per release type (one GitHub release per minor version): # - patch-release: create a new draft release with GitHub auto-generated notes. # - minor-prerelease: if no draft release exists for this minor version, generate - # notes using the AI script and create a draft prerelease. - # Subsequent prereleases for the same minor are no-ops. - # - minor-release: find the existing draft prerelease and update its tag/title - # to the final version (removing prerelease flag). - # ============================================================ - release-notes: - needs: prepare - if: ${{ !inputs.dry_run }} - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - with: - ref: ${{ needs.prepare.outputs.tag }} - fetch-depth: 0 - - # --- Patch release: create release with GitHub auto-generated notes --- - - name: Create GitHub release (patch) - if: ${{ inputs.release_type == 'patch-release' }} - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - gh release create "${{ needs.prepare.outputs.tag }}" \ - --title "v${{ needs.prepare.outputs.version }}" \ - --draft \ - --generate-notes - - # --- Prerelease: generate notes only if no draft exists for this minor --- - - name: Check for existing draft release - if: ${{ inputs.release_type == 'minor-prerelease' }} - id: check_draft - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - MINOR=$(echo "${{ needs.prepare.outputs.version }}" | sed -E 's/^([0-9]+\.[0-9]+).*/\1/') - # Look for any existing GitHub release (draft or published) matching this minor version - EXISTING=$(gh release list --json tagName,isDraft --limit 100 \ - | jq -r ".[] | select(.tagName | startswith(\"v${MINOR}.\")) | .tagName" | head -1) - if [[ -n "$EXISTING" ]]; then - echo "Draft release already exists for v${MINOR}: $EXISTING — skipping" - echo "skip=true" >> $GITHUB_OUTPUT - else - echo "No existing release for v${MINOR} — will generate notes" - echo "skip=false" >> $GITHUB_OUTPUT - fi - - - uses: actions/setup-python@v6 - if: ${{ inputs.release_type == 'minor-prerelease' && steps.check_draft.outputs.skip != 'true' }} - with: - python-version: "3.12" - - name: Install dependencies - if: ${{ inputs.release_type == 'minor-prerelease' && steps.check_draft.outputs.skip != 'true' }} - run: pip install PyGithub - - - name: Install OpenCode - if: ${{ inputs.release_type == 'minor-prerelease' && steps.check_draft.outputs.skip != 'true' }} - run: curl -fsSL https://opencode.ai/install | bash - - - name: Generate release notes with OpenCode - if: ${{ inputs.release_type == 'minor-prerelease' && steps.check_draft.outputs.skip != 'true' }} - env: - HF_TOKEN: ${{ secrets.RELEASE_NOTES_HF_TOKEN }} - GITHUB_TOKEN_RELEASE_NOTES: ${{ secrets.GITHUB_TOKEN }} - RELEASE_NOTES_MODEL: "huggingface/MiniMaxAI/MiniMax-M2.5" - run: | - python -m utils.release_notes.generate_release_notes \ - --since "${{ needs.prepare.outputs.since_tag }}" \ - --${{ needs.prepare.outputs.bump_type }} - - - name: Create draft GitHub release (prerelease) - if: ${{ inputs.release_type == 'minor-prerelease' && steps.check_draft.outputs.skip != 'true' }} - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - TAG="${{ needs.prepare.outputs.tag }}" - VERSION="${{ needs.prepare.outputs.version }}" - - # Find generated notes file (if any) - NOTES_FILE="" - for f in .release-notes/RELEASE_NOTES_*.md; do - if [[ -f "$f" ]]; then - NOTES_FILE="$f" - break - fi - done - - ARGS=( - "$TAG" - --title "v${VERSION}" - --draft - --prerelease - ) - - if [[ -n "$NOTES_FILE" ]]; then - echo "Using generated release notes from $NOTES_FILE" - ARGS+=(--notes-file "$NOTES_FILE") - else - echo "No generated notes found, using GitHub auto-generated notes" - ARGS+=(--generate-notes) - fi - - gh release create "${ARGS[@]}" - - # --- Minor release: update existing draft to point to the final tag --- - - name: Promote draft release to final version - if: ${{ inputs.release_type == 'minor-release' }} - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - TAG="${{ needs.prepare.outputs.tag }}" - VERSION="${{ needs.prepare.outputs.version }}" - MINOR=$(echo "$VERSION" | sed -E 's/^([0-9]+\.[0-9]+).*/\1/') - - # Find the existing draft release for this minor version - EXISTING_TAG=$(gh release list --json tagName,isDraft --limit 100 \ - | jq -r ".[] | select(.isDraft) | select(.tagName | startswith(\"v${MINOR}.\")) | .tagName" | head -1) - - if [[ -n "$EXISTING_TAG" ]]; then - echo "Updating existing draft release from $EXISTING_TAG to $TAG" - gh release edit "$EXISTING_TAG" \ - --tag "$TAG" \ - --title "v${VERSION}" \ - --prerelease=false - else - echo "::warning::No draft release found for v${MINOR}. Creating new release with auto-generated notes." - gh release create "$TAG" \ - --title "v${VERSION}" \ - --draft \ - --generate-notes - fi - - # ============================================================ - # 6. DOWNSTREAM TESTING — test RC in transformers, datasets, etc. - # ============================================================ - test-downstream: - needs: [prepare, publish-pypi] - if: ${{ needs.prepare.outputs.is_prerelease == 'true' && !inputs.dry_run }} - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - target-repo: ["transformers", "datasets", "diffusers", "sentence-transformers"] - steps: - - name: Wait for prerelease to be available on PyPI - run: | - VERSION="${{ needs.prepare.outputs.version }}" - echo "Waiting for huggingface-hub==${VERSION} on PyPI..." - for i in $(seq 1 20); do - if pip install "huggingface-hub==${VERSION}" 2>/dev/null; then - echo "Package available on PyPI!" - exit 0 - fi - echo "Not available yet, retrying in 15s... ($i/20)" - sleep 15 - done - echo "::error::Package not available on PyPI after 5 minutes" - exit 1 - - - name: Checkout target repo - uses: actions/checkout@v6 - with: - repository: huggingface/${{ matrix.target-repo }} - path: ${{ matrix.target-repo }} - token: ${{ secrets.HUGGINGFACE_HUB_AUTOMATIC_RC_TESTING }} - - - name: Configure Git - run: | - cd ${{ matrix.target-repo }} - git config user.name "Hugging Face Bot (RC Testing)" - git config user.email "bot@huggingface.co" - - - name: Create test branch and update dependencies - run: | - cd ${{ matrix.target-repo }} - VERSION="${{ needs.prepare.outputs.version }}" - BRANCH_NAME="ci-test-huggingface-hub-${VERSION}-release" - - git checkout -b "$BRANCH_NAME" - - # Update setup.py if exists - if [ -f "setup.py" ]; then - sed -i -E "s/\"huggingface-hub(>=|==)[^\"]*\"/\"huggingface-hub==${VERSION}\"/" setup.py - git add setup.py - fi - - # transformers-specific - if [ "${{ matrix.target-repo }}" = "transformers" ]; then - sed -i -E "s/\"huggingface-hub(>=|==)[^\"]*\"/\"huggingface-hub==${VERSION}\"/" src/transformers/dependency_versions_table.py - git add src/transformers/dependency_versions_table.py - fi - - # diffusers-specific - if [ "${{ matrix.target-repo }}" = "diffusers" ]; then - sed -i -E "s/\"huggingface-hub\":.*/\"huggingface-hub\": \"huggingface-hub==${VERSION}\",/" src/diffusers/dependency_versions_table.py - git add src/diffusers/dependency_versions_table.py - fi - - # sentence-transformers-specific - if [ "${{ matrix.target-repo }}" = "sentence-transformers" ]; then - sed -i -E "s/\"huggingface-hub(>=|==)[^\"]*\"/\"huggingface-hub==${VERSION}\"/" pyproject.toml - git add pyproject.toml - fi - - # Enable prerelease flag in workflow files - find .github/workflows/ -type f -exec sed -i 's/uv pip install /uv pip install --prerelease=allow /g' {} + - git add .github/workflows/ - - git --no-pager diff --staged - git commit -m "Test hfh ${VERSION}" - git push --set-upstream origin "$BRANCH_NAME" - - - name: Print URLs - run: | - VERSION="${{ needs.prepare.outputs.version }}" - BRANCH_NAME="ci-test-huggingface-hub-${VERSION}-release" - echo "### ${{ matrix.target-repo }}" >> $GITHUB_STEP_SUMMARY - echo "- [Actions](https://github.com/huggingface/${{ matrix.target-repo }}/actions)" >> $GITHUB_STEP_SUMMARY - echo "- [Compare](https://github.com/huggingface/${{ matrix.target-repo }}/compare/main...${BRANCH_NAME})" >> $GITHUB_STEP_SUMMARY - - # ============================================================ - # 7. POST-RELEASE — open PR to bump main to next dev version - # ============================================================ - post-release: - needs: [prepare, publish-pypi] - if: ${{ inputs.release_type == 'minor-release' && !inputs.dry_run }} - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - with: - ref: main - - - name: Configure Git - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - - - name: Create version bump PR - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - VERSION="${{ needs.prepare.outputs.version }}" - MAJOR=$(echo "$VERSION" | cut -d. -f1) - MINOR=$(echo "$VERSION" | cut -d. -f2) - NEXT_MINOR=$((MINOR + 1)) - DEV_VERSION="${MAJOR}.${NEXT_MINOR}.0.dev0" - - # Guard: skip if main already has an equal or higher version (e.g. version_override for older minor) - CURRENT_VERSION=$(grep -oP '__version__ = "\K[^"]+' src/huggingface_hub/__init__.py) - CURRENT_MINOR=$(echo "$CURRENT_VERSION" | cut -d. -f2) - if [[ "$CURRENT_MINOR" -ge "$NEXT_MINOR" ]]; then - echo "::warning::main is already at ${CURRENT_VERSION} (>= ${DEV_VERSION}). Skipping version bump." - exit 0 - fi - - PR_BRANCH="post-release-v${VERSION}" - git checkout -b "$PR_BRANCH" - - sed -i -E "s/__version__ = \".*\"/__version__ = \"${DEV_VERSION}\"/" src/huggingface_hub/__init__.py - git add src/huggingface_hub/__init__.py - git commit -m "Post-release: bump version to ${DEV_VERSION}" - git push -u origin "$PR_BRANCH" - - gh pr create \ - --title "Post-release: bump version to ${DEV_VERSION}" \ - --body "Automated version bump after v${VERSION} release." \ - --base main - - # ============================================================ - # 8. SYNC HF CLI SKILL — update skill docs in skills repo - # ============================================================ - sync-hf-cli-skill: - needs: prepare - if: ${{ needs.prepare.outputs.is_prerelease != 'true' && !inputs.dry_run }} - runs-on: ubuntu-latest - steps: - - name: Checkout huggingface_hub - uses: actions/checkout@v6 - with: - ref: ${{ needs.prepare.outputs.tag }} - - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: "3.12" - - - name: Install dependencies - run: pip install -e . - - - name: Generate skill docs - run: | - mkdir -p /tmp/hf-cli-skill - hf skills preview > /tmp/hf-cli-skill/SKILL.md - - - name: Create GitHub App token - id: app_token - uses: actions/create-github-app-token@v2 - with: - app-id: ${{ secrets.APP_ID_HUB_SKILLS_REPO }} - private-key: ${{ secrets.APP_SECRET_PREM_HUB_SKILLS_REPO }} - repositories: skills - - - name: Checkout skills repo - uses: actions/checkout@v6 - with: - repository: huggingface/skills - token: ${{ steps.app_token.outputs.token }} - path: skills-repo - - - name: Copy generated files - run: cp /tmp/hf-cli-skill/SKILL.md skills-repo/skills/hf-cli/ - - - name: Check for changes - id: check_changes - working-directory: skills-repo - run: | - git diff --quiet && echo "changed=false" >> $GITHUB_OUTPUT || echo "changed=true" >> $GITHUB_OUTPUT - - - name: Create Pull Request - if: steps.check_changes.outputs.changed == 'true' - uses: peter-evans/create-pull-request@v7 - with: - token: ${{ steps.app_token.outputs.token }} - path: skills-repo - branch: sync/hf-cli-${{ github.run_id }} - delete-branch: true - title: "Sync HF CLI Skill (${{ needs.prepare.outputs.tag }})" - reviewers: hanouticelina - body: | - Auto-generated from [huggingface_hub@${{ github.sha }}](https://github.com/huggingface/huggingface_hub/commit/${{ github.sha }}) - - Triggered by changes to `src/huggingface_hub/cli/` - - --- - This PR was created automatically by the [release](https://github.com/huggingface/huggingface_hub/blob/main/.github/workflows/release.yml) workflow. - commit-message: "Sync HF CLI skill from huggingface_hub@${{ github.sha }}" - labels: | - automated - cli-sync + # notes using the AI script and create a \ No newline at end of file