Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -423,3 +423,112 @@ jobs:
echo "zipping debug symbols"
zip -r dbg-symbols.zip dbg-symbols
gh release create "$RELEASE_TAG" wheels-*/* dbg-symbols.zip --generate-notes --prerelease --target ${{github.sha}}

wait-for-pypi:
name: Wait for PyPI availability
runs-on: ubuntu-latest
if: ${{ github.event_name == 'workflow_dispatch' }}
needs: [release-pypi]
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Strip version prefix
id: version
run: |
VERSION="${{ github.event.inputs.tag }}"
VERSION="${VERSION#v}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- name: Wait for PyPI availability
run: |
VERSION="${{ steps.version.outputs.version }}"
for i in $(seq 1 30); do
if curl -sf "https://pypi.org/pypi/hf_xet/$VERSION/json" > /dev/null; then
echo "hf_xet==$VERSION available on PyPI"
exit 0
fi
echo "Waiting for hf_xet==$VERSION on PyPI... (attempt $i/30)"
sleep 30
done
echo "ERROR: hf_xet==$VERSION not found on PyPI after 15 minutes"
exit 1

smoke-test:
name: Smoke test released version
runs-on: ${{ matrix.os }}
needs: [wait-for-pypi]
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Install uv
uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6

- name: Install hf CLI
run: uv tool install huggingface_hub

- name: Run smoke tests
env:
HF_TOKEN: ${{ secrets.HF_SMOKE_TEST_TOKEN }}
shell: bash
run: |
./scripts/smoke_tests/run.sh --hf-xet-version "${{ needs.wait-for-pypi.outputs.version }}" --namespace xet-team
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running "run.sh" in bash on Windows -- worth triggering a test in this PR


smoke-test-notify:
name: Notify smoke test results
runs-on: ubuntu-latest
if: ${{ always() && github.event_name == 'workflow_dispatch' }}
needs: [smoke-test]
steps:
- name: Determine failed platforms
if: ${{ needs.smoke-test.result == 'failure' }}
id: failures
env:
GH_TOKEN: ${{ github.token }}
run: |
failed=$(gh api "repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/jobs" \
--paginate -q '[.jobs[] | select(.name | startswith("Smoke test released version")) | select(.conclusion == "failure") | (.name | capture("\\((?<os>[^)]+)\\)")).os] | join(", ")')
echo "platforms=${failed:-unknown}" >> "$GITHUB_OUTPUT"

- name: Notify Slack on failure
if: ${{ needs.smoke-test.result == 'failure' }}
uses: slackapi/slack-github-action@b0fa283ad8fea605de13dc3f449259339835fc52 # v2.1.0
with:
webhook: ${{ secrets.SLACK_SMOKE_TEST_WEBHOOK_URL }}
webhook-type: incoming-webhook
payload: |
{
"text": ":red_circle: hf-xet smoke tests failed for ${{ github.event.inputs.tag }}",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": ":red_circle: *hf-xet smoke tests failed*\n*Version:* `${{ github.event.inputs.tag }}`\n*Failed:* ${{ steps.failures.outputs.platforms }}\n*Run:* <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View logs>"
}
}
]
}

- name: Notify Slack on success
if: ${{ needs.smoke-test.result == 'success' }}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No Slack notification when smoke tests are skipped

Medium Severity

The smoke-test-notify job only handles needs.smoke-test.result values of 'failure' and 'success'. If wait-for-pypi fails (e.g., the package never appears on PyPI within 15 minutes), the smoke-test job is skipped, producing a result of 'skipped'. Neither notification step fires, and the team receives no Slack alert that post-release validation didn't actually run. The same silent gap occurs if the smoke tests are cancelled. This means a release can complete with zero smoke test coverage and zero notification.

Additional Locations (1)
Fix in Cursor Fix in Web

uses: slackapi/slack-github-action@b0fa283ad8fea605de13dc3f449259339835fc52 # v2.1.0
with:
webhook: ${{ secrets.SLACK_SMOKE_TEST_WEBHOOK_URL }}
webhook-type: incoming-webhook
payload: |
{
"text": ":large_green_circle: hf-xet smoke tests passed for ${{ github.event.inputs.tag }}",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": ":large_green_circle: *hf-xet smoke tests passed*\n*Version:* `${{ github.event.inputs.tag }}`\n*Platforms:* ubuntu, macos, windows\n*Run:* <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View logs>"
}
}
]
}
14 changes: 9 additions & 5 deletions scripts/smoke_tests/test_upload_download.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ def main():
parser.add_argument("--hf-xet-version", help="Expected hf_xet version (display/warn only)")
parser.add_argument("--keep-repo", action="store_true", help="Skip cleanup of test repo/bucket")
parser.add_argument("--repo-prefix", default="smoke-test-xet", help="Prefix for temp resource names")
parser.add_argument("--namespace", help="HF namespace (user/org) for test repos; defaults to token owner")
parser.add_argument("--skip-buckets", action="store_true", help="Skip storage bucket tests")
args = parser.parse_args()

Expand All @@ -139,13 +140,16 @@ def main():
print("hf_xet version: unknown")
print(f"hf CLI: {run(['hf', 'version'])}")

# --- resolve username ---
from huggingface_hub import HfApi
user = HfApi(token=token).whoami()["name"]
# --- resolve namespace ---
if args.namespace:
namespace = args.namespace
else:
from huggingface_hub import HfApi
namespace = HfApi(token=token).whoami()["name"]

suffix = secrets.token_hex(4)
repo_id = f"{user}/{args.repo_prefix}-{suffix}"
bucket_id = f"{user}/{args.repo_prefix}-bucket-{suffix}"
repo_id = f"{namespace}/{args.repo_prefix}-{suffix}"
bucket_id = f"{namespace}/{args.repo_prefix}-bucket-{suffix}"

print(f"\nTest repo: {repo_id}")
if not args.skip_buckets:
Expand Down
Loading