mirror of
https://github.com/unslothai/unsloth.git
synced 2026-07-09 15:58:41 +00:00
Bumps the actions group with 11 updates in the / directory: | Package | From | To | | --- | --- | --- | | [actions/checkout](https://github.com/actions/checkout) | `4.2.2` | `7.0.0` | | [actions/setup-python](https://github.com/actions/setup-python) | `6.2.0` | `6.3.0` | | [actions/cache/restore](https://github.com/actions/cache) | `5.0.5` | `6.1.0` | | [actions/cache/save](https://github.com/actions/cache) | `5.0.5` | `6.1.0` | | [actions/upload-artifact](https://github.com/actions/upload-artifact) | `4.6.1` | `7.0.1` | | [step-security/harden-runner](https://github.com/step-security/harden-runner) | `2.19.1` | `2.19.4` | | [ossf/scorecard-action](https://github.com/ossf/scorecard-action) | `2.4.1` | `2.4.3` | | [github/codeql-action](https://github.com/github/codeql-action) | `3` | `4.36.3` | | [tauri-apps/tauri-action](https://github.com/tauri-apps/tauri-action) | `0.6.2` | `1.0.0` | | [trufflesecurity/trufflehog](https://github.com/trufflesecurity/trufflehog) | `3.95.3` | `3.95.8` | | [actions/stale](https://github.com/actions/stale) | `10.2.0` | `10.3.0` | Updates `actions/checkout` from 4.2.2 to 7.0.0 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.2.2...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) Updates `actions/setup-python` from 6.2.0 to 6.3.0 - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v6.2.0...ece7cb06caefa5fff74198d8649806c4678c61a1) Updates `actions/cache/restore` from 5.0.5 to 6.1.0 - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](27d5ce7f10...55cc834586) Updates `actions/cache/save` from 5.0.5 to 6.1.0 - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](27d5ce7f10...55cc834586) Updates `actions/upload-artifact` from 4.6.1 to 7.0.1 - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v4.6.1...043fb46d1a93c77aae656e7c1c64a875d1fc6a0a) Updates `step-security/harden-runner` from 2.19.1 to 2.19.4 - [Release notes](https://github.com/step-security/harden-runner/releases) - [Commits](a5ad31d6a1...9af89fc715) Updates `ossf/scorecard-action` from 2.4.1 to 2.4.3 - [Release notes](https://github.com/ossf/scorecard-action/releases) - [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md) - [Commits](f49aabe0b5...4eaacf0543) Updates `github/codeql-action` from 3 to 4.36.3 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v3...v4.36.3) Updates `tauri-apps/tauri-action` from 0.6.2 to 1.0.0 - [Release notes](https://github.com/tauri-apps/tauri-action/releases) - [Changelog](https://github.com/tauri-apps/tauri-action/blob/dev/CHANGELOG.md) - [Commits](84b9d35b5f...1deb371b0c) Updates `trufflesecurity/trufflehog` from 3.95.3 to 3.95.8 - [Release notes](https://github.com/trufflesecurity/trufflehog/releases) - [Commits](37b77001d0...00155c9dc5) Updates `actions/stale` from 10.2.0 to 10.3.0 - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](b5d41d4e1d...eb5cf3af3a) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: actions - dependency-name: actions/setup-python dependency-version: 6.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions - dependency-name: actions/cache/restore dependency-version: 6.1.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: actions - dependency-name: actions/cache/save dependency-version: 6.1.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: actions - dependency-name: actions/upload-artifact dependency-version: 7.0.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: actions - dependency-name: step-security/harden-runner dependency-version: 2.19.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions - dependency-name: ossf/scorecard-action dependency-version: 2.4.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions - dependency-name: github/codeql-action dependency-version: 4.36.3 dependency-type: direct:production update-type: version-update:semver-major dependency-group: actions - dependency-name: tauri-apps/tauri-action dependency-version: 1.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: actions - dependency-name: trufflesecurity/trufflehog dependency-version: 3.95.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions - dependency-name: actions/stale dependency-version: 10.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions ... Signed-off-by: dependabot[bot] <support@github.com>
170 lines
6.2 KiB
YAML
170 lines
6.2 KiB
YAML
# SPDX-License-Identifier: AGPL-3.0-only
|
|
# Copyright 2026-present the Unsloth AI Inc. team. All rights reserved.
|
|
|
|
# Studio API & Auth Tests -- HTTP-level integration tests for the
|
|
# FastAPI surface. No Playwright, no model UI; tests/studio/test_studio_api_smoke.py
|
|
# runs ~30 s and asserts:
|
|
# - CORS hardening (no wildcard + credentials, no bootstrap leak)
|
|
# - /api/system + /api/system/hardware require auth
|
|
# - Auth state machine + JWT expiry
|
|
# - API key lifecycle E2E (create / list / use / delete / reject)
|
|
# - Auth file-mode hardening (Linux only)
|
|
# - Inference lifecycle (force reload, bogus variant, /v1/models, /v1/embeddings, /v1/responses)
|
|
# - Endpoint-by-endpoint auth audit
|
|
#
|
|
# Reuses the GGUF cache key from studio-ui-smoke.yml so the model
|
|
# download is one cache-hit on the second job.
|
|
|
|
name: Studio API CI
|
|
|
|
on:
|
|
pull_request:
|
|
paths:
|
|
- 'studio/**'
|
|
- 'unsloth/**'
|
|
- 'unsloth_cli/**'
|
|
- 'install.sh'
|
|
- 'pyproject.toml'
|
|
- 'tests/studio/**'
|
|
- '.github/workflows/studio-api-smoke.yml'
|
|
push:
|
|
branches: [main, pip]
|
|
workflow_dispatch:
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
api-smoke:
|
|
name: Studio API & Auth Tests
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 12
|
|
env:
|
|
GGUF_REPO: unsloth/gemma-3-270m-it-GGUF
|
|
GGUF_VARIANT: UD-Q4_K_XL
|
|
GGUF_FILE: gemma-3-270m-it-UD-Q4_K_XL.gguf
|
|
STUDIO_PORT: '18893'
|
|
HF_HOME: ${{ github.workspace }}/hf-cache
|
|
steps:
|
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Linux deps
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y --no-install-recommends \
|
|
libcurl4-openssl-dev libssl-dev jq
|
|
|
|
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
with:
|
|
node-version: '22'
|
|
|
|
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
|
with:
|
|
python-version: '3.12'
|
|
cache: 'pip'
|
|
|
|
- name: Restore HF_HOME for ${{ env.GGUF_REPO }}
|
|
id: cache-hf
|
|
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
continue-on-error: true
|
|
with:
|
|
path: hf-cache
|
|
# Same key as studio-ui-smoke.yml so the two jobs share a
|
|
# single GGUF download across CI.
|
|
key: ${{ runner.os }}-hf-${{ env.GGUF_REPO }}-${{ env.GGUF_VARIANT }}-v2
|
|
|
|
- name: Prime HF_HOME with the GGUF
|
|
id: prime-hf
|
|
if: steps.cache-hf.outputs.cache-hit != 'true' || steps.cache-hf.outcome != 'success'
|
|
env:
|
|
# Withheld on PR: this step runs checked-out PR code; public GGUF still downloads.
|
|
HF_TOKEN: ${{ github.event_name != 'pull_request' && secrets.HF_TOKEN || '' }}
|
|
run: |
|
|
python -m pip install --upgrade huggingface_hub
|
|
mkdir -p hf-cache
|
|
bash .github/scripts/hf-download-with-retry.sh "$GGUF_REPO" "$GGUF_FILE"
|
|
bash .github/scripts/hf-download-with-retry.sh ggml-org/models tinyllamas/stories260K.gguf
|
|
|
|
- name: Save HF_HOME for ${{ env.GGUF_REPO }}
|
|
if: always() && steps.prime-hf.outcome == 'success'
|
|
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
with:
|
|
path: hf-cache
|
|
key: ${{ runner.os }}-hf-${{ env.GGUF_REPO }}-${{ env.GGUF_VARIANT }}-v2
|
|
|
|
- name: Install Studio (--local, --no-torch)
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
# Withheld on PR: this step runs checked-out PR code; public GGUF still downloads.
|
|
HF_TOKEN: ${{ github.event_name != 'pull_request' && secrets.HF_TOKEN || '' }}
|
|
run: |
|
|
mkdir -p logs
|
|
set -o pipefail
|
|
bash install.sh --local --no-torch 2>&1 | tee logs/install.log
|
|
|
|
- name: Install pyjwt for the JWT-expiry forge test
|
|
run: pip install 'pyjwt>=2.6'
|
|
|
|
- name: Reset auth + boot Studio (API-only)
|
|
run: |
|
|
unsloth studio reset-password
|
|
mkdir -p logs
|
|
UNSLOTH_API_ONLY=1 unsloth studio -H 127.0.0.1 -p "$STUDIO_PORT" \
|
|
> logs/studio.log 2>&1 &
|
|
echo "STUDIO_PID=$!" >> "$GITHUB_ENV"
|
|
|
|
- name: Wait for /api/health
|
|
run: |
|
|
for i in $(seq 1 180); do
|
|
if curl -fs "http://127.0.0.1:${STUDIO_PORT}/api/health" > /tmp/health.json; then
|
|
jq -e '.status == "healthy"' /tmp/health.json && break
|
|
fi
|
|
sleep 1
|
|
done
|
|
jq -e '.status == "healthy"' /tmp/health.json
|
|
|
|
- name: Pass bootstrap password + rotated targets to the test
|
|
# The test does its own bootstrap-login + rotation to exercise
|
|
# the auth state machine; we just pre-mint two random rotated
|
|
# passwords for it. Mask them so the log is clean.
|
|
run: |
|
|
OLD=$(cat ~/.unsloth/studio/auth/.bootstrap_password)
|
|
NEW="ApiSmoke-$(python -c 'import secrets; print(secrets.token_urlsafe(16))')"
|
|
NEW2="ApiSmoke-$(python -c 'import secrets; print(secrets.token_urlsafe(16))')"
|
|
echo "::add-mask::$OLD"
|
|
echo "::add-mask::$NEW"
|
|
echo "::add-mask::$NEW2"
|
|
echo "STUDIO_OLD_PW=$OLD" >> "$GITHUB_ENV"
|
|
echo "STUDIO_NEW_PW=$NEW" >> "$GITHUB_ENV"
|
|
echo "STUDIO_NEW2_PW=$NEW2" >> "$GITHUB_ENV"
|
|
|
|
- name: Run Studio API & Auth tests
|
|
# The script is named WITHOUT a `test_` prefix so it isn't
|
|
# auto-collected by pytest in Backend CI's `tests/` walk
|
|
# (which doesn't set BASE_URL and would crash at import).
|
|
env:
|
|
BASE_URL: http://127.0.0.1:18893
|
|
STUDIO_AUTH_DIR: /home/runner/.unsloth/studio/auth
|
|
run: python tests/studio/studio_api_smoke.py
|
|
|
|
- name: Stop Studio
|
|
if: always()
|
|
run: |
|
|
kill "${STUDIO_PID}" 2>/dev/null || true
|
|
sleep 2
|
|
|
|
- name: Upload API smoke logs
|
|
if: always()
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
with:
|
|
name: studio-api-smoke-log
|
|
path: |
|
|
logs/install.log
|
|
logs/studio.log
|
|
retention-days: 7
|