CI nightlies cpu/gpu & cleanup (#75)
This commit is contained in:
parent
659c69a1c0
commit
b980c5dd9e
|
@ -0,0 +1,142 @@
|
||||||
|
# Misc
|
||||||
|
.git
|
||||||
|
tmp
|
||||||
|
wandb
|
||||||
|
data
|
||||||
|
outputs
|
||||||
|
.vscode
|
||||||
|
rl
|
||||||
|
media
|
||||||
|
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
logs
|
||||||
|
|
||||||
|
# HPC
|
||||||
|
nautilus/*.yaml
|
||||||
|
*.key
|
||||||
|
|
||||||
|
# Slurm
|
||||||
|
sbatch*.sh
|
||||||
|
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
pip-wheel-metadata/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
!tests/data
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
|
@ -1,12 +1,29 @@
|
||||||
# What does this PR do?
|
# What does this PR do?
|
||||||
|
|
||||||
Example: Fixes # (issue)
|
Examples:
|
||||||
|
- Fixes # (issue)
|
||||||
|
- Adds new dataset
|
||||||
|
- Optimizes something
|
||||||
|
|
||||||
|
## How was it tested?
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
- Added `test_something` in `tests/test_stuff.py`.
|
||||||
|
- Added `new_feature` and checked that training converges with policy X on dataset/environment Y.
|
||||||
|
- Optimized `some_function`, it now runs X times faster than previously.
|
||||||
|
|
||||||
|
## How to checkout & try? (for the reviewer)
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
```bash
|
||||||
|
DATA_DIR=tests/data pytest -sx tests/test_stuff.py::test_something
|
||||||
|
```
|
||||||
|
```bash
|
||||||
|
python lerobot/scripts/train.py --some.option=true
|
||||||
|
```
|
||||||
|
|
||||||
## Before submitting
|
## Before submitting
|
||||||
- Read the [contributor guideline](https://github.com/huggingface/lerobot/blob/main/CONTRIBUTING.md#submitting-a-pull-request-pr).
|
Please read the [contributor guideline](https://github.com/huggingface/lerobot/blob/main/CONTRIBUTING.md#submitting-a-pull-request-pr).
|
||||||
- Provide a minimal code example for the reviewer to checkout & try.
|
|
||||||
- Explain how you tested your changes.
|
|
||||||
|
|
||||||
|
|
||||||
## Who can review?
|
## Who can review?
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
PYPROJECT = "pyproject.toml"
|
||||||
|
DEPS = {
|
||||||
|
"gym-pusht": '{ git = "git@github.com:huggingface/gym-pusht.git", optional = true}',
|
||||||
|
"gym-xarm": '{ git = "git@github.com:huggingface/gym-xarm.git", optional = true}',
|
||||||
|
"gym-aloha": '{ git = "git@github.com:huggingface/gym-aloha.git", optional = true}',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def update_envs_as_path_dependencies():
|
||||||
|
with open(PYPROJECT) as file:
|
||||||
|
lines = file.readlines()
|
||||||
|
|
||||||
|
new_lines = []
|
||||||
|
for line in lines:
|
||||||
|
if any(dep in line for dep in DEPS.values()):
|
||||||
|
for dep in DEPS:
|
||||||
|
if dep in line:
|
||||||
|
new_line = f'{dep} = {{ path = "envs/{dep}/", optional = true}}\n'
|
||||||
|
new_lines.append(new_line)
|
||||||
|
break
|
||||||
|
|
||||||
|
else:
|
||||||
|
new_lines.append(line)
|
||||||
|
|
||||||
|
with open(PYPROJECT, "w") as file:
|
||||||
|
file.writelines(new_lines)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
update_envs_as_path_dependencies()
|
|
@ -0,0 +1,207 @@
|
||||||
|
# Inspired by
|
||||||
|
# https://github.com/huggingface/peft/blob/main/.github/workflows/build_docker_images.yml
|
||||||
|
name: Nightly Builds
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
workflow_call:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 1 * * *"
|
||||||
|
|
||||||
|
# concurrency:
|
||||||
|
# group: docker-image-builds
|
||||||
|
# cancel-in-progress: false
|
||||||
|
|
||||||
|
env:
|
||||||
|
PYTHON_VERSION: "3.10"
|
||||||
|
# CI_SLACK_CHANNEL: ${{ secrets.CI_DOCKER_CHANNEL }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
latest-cpu:
|
||||||
|
name: "Build CPU"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Cleanup disk
|
||||||
|
run: |
|
||||||
|
sudo df -h
|
||||||
|
# sudo ls -l /usr/local/lib/
|
||||||
|
# sudo ls -l /usr/share/
|
||||||
|
sudo du -sh /usr/local/lib/
|
||||||
|
sudo du -sh /usr/share/
|
||||||
|
sudo rm -rf /usr/local/lib/android
|
||||||
|
sudo rm -rf /usr/share/dotnet
|
||||||
|
sudo du -sh /usr/local/lib/
|
||||||
|
sudo du -sh /usr/share/
|
||||||
|
sudo df -h
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Check out code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Checkout gym-aloha
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: huggingface/gym-aloha
|
||||||
|
path: envs/gym-aloha
|
||||||
|
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Checkout gym-xarm
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: huggingface/gym-xarm
|
||||||
|
path: envs/gym-xarm
|
||||||
|
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Checkout gym-pusht
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: huggingface/gym-pusht
|
||||||
|
path: envs/gym-pusht
|
||||||
|
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
# HACK(aliberts): to be removed for release
|
||||||
|
# -----------------------------------------
|
||||||
|
- name: Set up Python 3.10
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.10"
|
||||||
|
|
||||||
|
- name: Change envs dependencies as local path
|
||||||
|
run: python .github/scripts/dep_build.py
|
||||||
|
# -----------------------------------------
|
||||||
|
|
||||||
|
- name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Build and Push CPU
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./docker/lerobot-cpu/Dockerfile
|
||||||
|
push: true
|
||||||
|
tags: huggingface/lerobot-cpu
|
||||||
|
build-args: PYTHON_VERSION=${{ env.PYTHON_VERSION }}
|
||||||
|
|
||||||
|
# - name: Post to a Slack channel
|
||||||
|
# id: slack
|
||||||
|
# #uses: slackapi/slack-github-action@v1.25.0
|
||||||
|
# uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001
|
||||||
|
# with:
|
||||||
|
# # Slack channel id, channel name, or user id to post message.
|
||||||
|
# # See also: https://api.slack.com/methods/chat.postMessage#channels
|
||||||
|
# channel-id: ${{ env.CI_SLACK_CHANNEL }}
|
||||||
|
# # For posting a rich message using Block Kit
|
||||||
|
# payload: |
|
||||||
|
# {
|
||||||
|
# "text": "lerobot-cpu Docker Image build result: ${{ job.status }}\n${{ github.event.pull_request.html_url || github.event.head_commit.url }}",
|
||||||
|
# "blocks": [
|
||||||
|
# {
|
||||||
|
# "type": "section",
|
||||||
|
# "text": {
|
||||||
|
# "type": "mrkdwn",
|
||||||
|
# "text": "lerobot-cpu Docker Image build result: ${{ job.status }}\n${{ github.event.pull_request.html_url || github.event.head_commit.url }}"
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
# env:
|
||||||
|
# SLACK_BOT_TOKEN: ${{ secrets.SLACK_CIFEEDBACK_BOT_TOKEN }}
|
||||||
|
|
||||||
|
latest-cuda:
|
||||||
|
name: "Build GPU"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Cleanup disk
|
||||||
|
run: |
|
||||||
|
sudo df -h
|
||||||
|
# sudo ls -l /usr/local/lib/
|
||||||
|
# sudo ls -l /usr/share/
|
||||||
|
sudo du -sh /usr/local/lib/
|
||||||
|
sudo du -sh /usr/share/
|
||||||
|
sudo rm -rf /usr/local/lib/android
|
||||||
|
sudo rm -rf /usr/share/dotnet
|
||||||
|
sudo du -sh /usr/local/lib/
|
||||||
|
sudo du -sh /usr/share/
|
||||||
|
sudo df -h
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Check out code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Checkout gym-aloha
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: huggingface/gym-aloha
|
||||||
|
path: envs/gym-aloha
|
||||||
|
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Checkout gym-xarm
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: huggingface/gym-xarm
|
||||||
|
path: envs/gym-xarm
|
||||||
|
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Checkout gym-pusht
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: huggingface/gym-pusht
|
||||||
|
path: envs/gym-pusht
|
||||||
|
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
# HACK(aliberts): to be removed for release
|
||||||
|
# -----------------------------------------
|
||||||
|
- name: Set up Python 3.10
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.10"
|
||||||
|
|
||||||
|
- name: Change envs dependencies as local path
|
||||||
|
run: python .github/scripts/dep_build.py
|
||||||
|
# -----------------------------------------
|
||||||
|
|
||||||
|
- name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Build and Push GPU
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./docker/lerobot-gpu/Dockerfile
|
||||||
|
push: true
|
||||||
|
tags: huggingface/lerobot-gpu
|
||||||
|
build-args: PYTHON_VERSION=${{ env.PYTHON_VERSION }}
|
||||||
|
|
||||||
|
# - name: Post to a Slack channel
|
||||||
|
# id: slack
|
||||||
|
# #uses: slackapi/slack-github-action@v1.25.0
|
||||||
|
# uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001
|
||||||
|
# with:
|
||||||
|
# # Slack channel id, channel name, or user id to post message.
|
||||||
|
# # See also: https://api.slack.com/methods/chat.postMessage#channels
|
||||||
|
# channel-id: ${{ env.CI_SLACK_CHANNEL }}
|
||||||
|
# # For posting a rich message using Block Kit
|
||||||
|
# payload: |
|
||||||
|
# {
|
||||||
|
# "text": "lerobot-gpu Docker Image build result: ${{ job.status }}\n${{ github.event.pull_request.html_url || github.event.head_commit.url }}",
|
||||||
|
# "blocks": [
|
||||||
|
# {
|
||||||
|
# "type": "section",
|
||||||
|
# "text": {
|
||||||
|
# "type": "mrkdwn",
|
||||||
|
# "text": "lerobot-gpu Docker Image build result: ${{ job.status }}\n${{ github.event.pull_request.html_url || github.event.head_commit.url }}"
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
# env:
|
||||||
|
# SLACK_BOT_TOKEN: ${{ secrets.SLACK_CIFEEDBACK_BOT_TOKEN }}
|
|
@ -0,0 +1,85 @@
|
||||||
|
# Inspired by
|
||||||
|
# https://github.com/huggingface/peft/blob/main/.github/workflows/nightly.yml
|
||||||
|
name: Nightly Tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 2 * * *"
|
||||||
|
|
||||||
|
env:
|
||||||
|
DATA_DIR: tests/data
|
||||||
|
# SLACK_API_TOKEN: ${{ secrets.SLACK_API_TOKEN }}
|
||||||
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
run_all_tests_cpu:
|
||||||
|
name: "Test CPU"
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: huggingface/lerobot-cpu:latest
|
||||||
|
options: --shm-size "16gb"
|
||||||
|
credentials:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
working-directory: /lerobot
|
||||||
|
steps:
|
||||||
|
- name: Tests
|
||||||
|
env:
|
||||||
|
DATA_DIR: tests/data
|
||||||
|
run: pytest -v --cov=./lerobot --disable-warnings tests
|
||||||
|
- name: Tests end-to-end
|
||||||
|
env:
|
||||||
|
DATA_DIR: tests/data
|
||||||
|
run: make test-end-to-end
|
||||||
|
|
||||||
|
run_all_tests_single_gpu:
|
||||||
|
name: "Test GPU"
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
runs-on: [single-gpu, nvidia-gpu, t4, ci]
|
||||||
|
env:
|
||||||
|
CUDA_VISIBLE_DEVICES: "0"
|
||||||
|
TEST_TYPE: "single_gpu"
|
||||||
|
container:
|
||||||
|
image: huggingface/lerobot-gpu:latest
|
||||||
|
options: --gpus all --shm-size "16gb"
|
||||||
|
credentials:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
working-directory: /lerobot
|
||||||
|
steps:
|
||||||
|
- name: Nvidia-smi
|
||||||
|
run: nvidia-smi
|
||||||
|
- name: Test
|
||||||
|
run: pytest -v --cov=./lerobot --cov-report=xml --disable-warnings tests
|
||||||
|
# TODO(aliberts): Link with HF Codecov account
|
||||||
|
# - name: Upload coverage reports to Codecov with GitHub Action
|
||||||
|
# uses: codecov/codecov-action@v4
|
||||||
|
# with:
|
||||||
|
# files: ./coverage.xml
|
||||||
|
# verbose: true
|
||||||
|
- name: Tests end-to-end
|
||||||
|
run: make test-end-to-end
|
||||||
|
- name: Tailscale Wait
|
||||||
|
if: ${{ failure() || runner.debug == '1' }}
|
||||||
|
uses: huggingface/tailscale-action@v1
|
||||||
|
with:
|
||||||
|
waitForSSH: true
|
||||||
|
authkey: ${{ secrets.TAILSCALE_SSH_AUTHKEY }}
|
||||||
|
slackChannel: ${{ secrets.SLACK_CIFEEDBACK_CHANNEL }}
|
||||||
|
slackToken: ${{ secrets.SLACK_CIFEEDBACK_BOT_TOKEN }}
|
||||||
|
|
||||||
|
# - name: Generate Report
|
||||||
|
# if: always()
|
||||||
|
# run: |
|
||||||
|
# pip install slack_sdk tabulate
|
||||||
|
# python scripts/log_reports.py >> $GITHUB_STEP_SUMMARY
|
|
@ -0,0 +1,120 @@
|
||||||
|
# name: Tests poetry
|
||||||
|
|
||||||
|
# on:
|
||||||
|
# pull_request:
|
||||||
|
# branches:
|
||||||
|
# - main
|
||||||
|
# push:
|
||||||
|
# branches:
|
||||||
|
# - main
|
||||||
|
|
||||||
|
# jobs:
|
||||||
|
# tests:
|
||||||
|
# runs-on: ubuntu-latest
|
||||||
|
# env:
|
||||||
|
# POETRY_VERSION: 1.8.2
|
||||||
|
# DATA_DIR: tests/data
|
||||||
|
# MUJOCO_GL: egl
|
||||||
|
# steps:
|
||||||
|
# #----------------------------------------------
|
||||||
|
# # check-out repo and set-up python
|
||||||
|
# #----------------------------------------------
|
||||||
|
# - name: Check out repository
|
||||||
|
# uses: actions/checkout@v4
|
||||||
|
# with:
|
||||||
|
# lfs: true
|
||||||
|
|
||||||
|
# - name: Set up python
|
||||||
|
# id: setup-python
|
||||||
|
# uses: actions/setup-python@v5
|
||||||
|
# with:
|
||||||
|
# python-version: '3.10'
|
||||||
|
|
||||||
|
# - name: Add SSH key for installing envs
|
||||||
|
# uses: webfactory/ssh-agent@v0.9.0
|
||||||
|
# with:
|
||||||
|
# ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
# #----------------------------------------------
|
||||||
|
# # install & configure poetry
|
||||||
|
# #----------------------------------------------
|
||||||
|
# - name: Load cached Poetry installation
|
||||||
|
# id: restore-poetry-cache
|
||||||
|
# uses: actions/cache/restore@v3
|
||||||
|
# with:
|
||||||
|
# path: ~/.local
|
||||||
|
# key: poetry-${{ env.POETRY_VERSION }}
|
||||||
|
|
||||||
|
# - name: Install Poetry
|
||||||
|
# if: steps.restore-poetry-cache.outputs.cache-hit != 'true'
|
||||||
|
# uses: snok/install-poetry@v1
|
||||||
|
# with:
|
||||||
|
# version: ${{ env.POETRY_VERSION }}
|
||||||
|
# virtualenvs-create: true
|
||||||
|
# installer-parallel: true
|
||||||
|
|
||||||
|
# - name: Save cached Poetry installation
|
||||||
|
# if: |
|
||||||
|
# steps.restore-poetry-cache.outputs.cache-hit != 'true' &&
|
||||||
|
# github.ref_name == 'main'
|
||||||
|
# id: save-poetry-cache
|
||||||
|
# uses: actions/cache/save@v3
|
||||||
|
# with:
|
||||||
|
# path: ~/.local
|
||||||
|
# key: poetry-${{ env.POETRY_VERSION }}
|
||||||
|
|
||||||
|
# - name: Configure Poetry
|
||||||
|
# run: poetry config virtualenvs.in-project true
|
||||||
|
|
||||||
|
# #----------------------------------------------
|
||||||
|
# # install dependencies
|
||||||
|
# #----------------------------------------------
|
||||||
|
# # TODO(aliberts): move to gpu runners
|
||||||
|
# - name: Select cpu dependencies # HACK
|
||||||
|
# run: cp -t . .github/poetry/cpu/pyproject.toml .github/poetry/cpu/poetry.lock
|
||||||
|
|
||||||
|
# - name: Load cached venv
|
||||||
|
# id: restore-dependencies-cache
|
||||||
|
# uses: actions/cache/restore@v3
|
||||||
|
# with:
|
||||||
|
# path: .venv
|
||||||
|
# key: venv-${{ steps.setup-python.outputs.python-version }}-${{ env.POETRY_VERSION }}-${{ hashFiles('**/poetry.lock') }}
|
||||||
|
|
||||||
|
# - name: Install dependencies
|
||||||
|
# if: steps.restore-dependencies-cache.outputs.cache-hit != 'true'
|
||||||
|
# run: poetry install --no-interaction --no-root --all-extras
|
||||||
|
|
||||||
|
# - name: Save cached venv
|
||||||
|
# if: |
|
||||||
|
# steps.restore-dependencies-cache.outputs.cache-hit != 'true' &&
|
||||||
|
# github.ref_name == 'main'
|
||||||
|
# id: save-dependencies-cache
|
||||||
|
# uses: actions/cache/save@v3
|
||||||
|
# with:
|
||||||
|
# path: .venv
|
||||||
|
# key: venv-${{ steps.setup-python.outputs.python-version }}-${{ env.POETRY_VERSION }}-${{ hashFiles('**/poetry.lock') }}
|
||||||
|
|
||||||
|
# - name: Install EGL
|
||||||
|
# run: sudo apt-get update && sudo apt-get install -y libegl1-mesa-dev
|
||||||
|
|
||||||
|
# #----------------------------------------------
|
||||||
|
# # install project
|
||||||
|
# #----------------------------------------------
|
||||||
|
# - name: Install project
|
||||||
|
# run: poetry install --no-interaction --all-extras
|
||||||
|
|
||||||
|
# #----------------------------------------------
|
||||||
|
# # run tests & coverage
|
||||||
|
# #----------------------------------------------
|
||||||
|
# - name: Run tests
|
||||||
|
# run: |
|
||||||
|
# source .venv/bin/activate
|
||||||
|
# pytest -v --cov=./lerobot tests
|
||||||
|
|
||||||
|
# #----------------------------------------------
|
||||||
|
# # run end-to-end tests
|
||||||
|
# #----------------------------------------------
|
||||||
|
# - name: Tests end-to-end
|
||||||
|
# run: |
|
||||||
|
# source .venv/bin/activate
|
||||||
|
# make test-end-to-end
|
|
@ -4,210 +4,43 @@ on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
types: [opened, synchronize, reopened, labeled]
|
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
tests:
|
tests:
|
||||||
if: |
|
|
||||||
${{ github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'CI') }} ||
|
|
||||||
${{ github.event_name == 'push' }}
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
POETRY_VERSION: 1.8.2
|
|
||||||
DATA_DIR: tests/data
|
DATA_DIR: tests/data
|
||||||
MUJOCO_GL: egl
|
MUJOCO_GL: egl
|
||||||
steps:
|
steps:
|
||||||
#----------------------------------------------
|
|
||||||
# check-out repo and set-up python
|
|
||||||
#----------------------------------------------
|
|
||||||
- name: Check out repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
lfs: true
|
|
||||||
|
|
||||||
- name: Set up python
|
|
||||||
id: setup-python
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: '3.10'
|
|
||||||
|
|
||||||
- name: Add SSH key for installing envs
|
- name: Add SSH key for installing envs
|
||||||
uses: webfactory/ssh-agent@v0.9.0
|
uses: webfactory/ssh-agent@v0.9.0
|
||||||
with:
|
with:
|
||||||
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||||
|
|
||||||
#----------------------------------------------
|
- uses: actions/checkout@v4
|
||||||
# install & configure poetry
|
|
||||||
#----------------------------------------------
|
|
||||||
- name: Load cached Poetry installation
|
|
||||||
id: restore-poetry-cache
|
|
||||||
uses: actions/cache/restore@v3
|
|
||||||
with:
|
with:
|
||||||
path: ~/.local
|
lfs: true
|
||||||
key: poetry-${{ env.POETRY_VERSION }}
|
|
||||||
|
|
||||||
- name: Install Poetry
|
- name: Set up Python 3.10
|
||||||
if: steps.restore-poetry-cache.outputs.cache-hit != 'true'
|
uses: actions/setup-python@v5
|
||||||
uses: snok/install-poetry@v1
|
|
||||||
with:
|
with:
|
||||||
version: ${{ env.POETRY_VERSION }}
|
python-version: "3.10"
|
||||||
virtualenvs-create: true
|
cache: ${{ (github.ref == 'refs/heads/main') && 'pip' || '' }}
|
||||||
installer-parallel: true
|
cache-dependency-path: pyproject.toml
|
||||||
|
|
||||||
- name: Save cached Poetry installation
|
- name: Install EGL
|
||||||
if: |
|
|
||||||
steps.restore-poetry-cache.outputs.cache-hit != 'true' &&
|
|
||||||
github.ref_name == 'main'
|
|
||||||
id: save-poetry-cache
|
|
||||||
uses: actions/cache/save@v3
|
|
||||||
with:
|
|
||||||
path: ~/.local
|
|
||||||
key: poetry-${{ env.POETRY_VERSION }}
|
|
||||||
|
|
||||||
- name: Configure Poetry
|
|
||||||
run: poetry config virtualenvs.in-project true
|
|
||||||
|
|
||||||
#----------------------------------------------
|
|
||||||
# install dependencies
|
|
||||||
#----------------------------------------------
|
|
||||||
# TODO(aliberts): move to gpu runners
|
|
||||||
- name: Select cpu dependencies # HACK
|
|
||||||
run: cp -t . .github/poetry/cpu/pyproject.toml .github/poetry/cpu/poetry.lock
|
|
||||||
|
|
||||||
- name: Load cached venv
|
|
||||||
id: restore-dependencies-cache
|
|
||||||
uses: actions/cache/restore@v3
|
|
||||||
with:
|
|
||||||
path: .venv
|
|
||||||
key: venv-${{ steps.setup-python.outputs.python-version }}-${{ env.POETRY_VERSION }}-${{ hashFiles('**/poetry.lock') }}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
if: steps.restore-dependencies-cache.outputs.cache-hit != 'true'
|
|
||||||
env:
|
|
||||||
TMPDIR: ~/tmp
|
|
||||||
TEMP: ~/tmp
|
|
||||||
TMP: ~/tmp
|
|
||||||
run: |
|
|
||||||
mkdir ~/tmp
|
|
||||||
poetry install --no-interaction --no-root --all-extras
|
|
||||||
|
|
||||||
- name: Save cached venv
|
|
||||||
if: |
|
|
||||||
steps.restore-dependencies-cache.outputs.cache-hit != 'true' &&
|
|
||||||
github.ref_name == 'main'
|
|
||||||
id: save-dependencies-cache
|
|
||||||
uses: actions/cache/save@v3
|
|
||||||
with:
|
|
||||||
path: .venv
|
|
||||||
key: venv-${{ steps.setup-python.outputs.python-version }}-${{ env.POETRY_VERSION }}-${{ hashFiles('**/poetry.lock') }}
|
|
||||||
|
|
||||||
- name: Install libegl1-mesa-dev (to use MUJOCO_GL=egl)
|
|
||||||
run: sudo apt-get update && sudo apt-get install -y libegl1-mesa-dev
|
run: sudo apt-get update && sudo apt-get install -y libegl1-mesa-dev
|
||||||
|
|
||||||
#----------------------------------------------
|
- name: Install pip dependencies
|
||||||
# install project
|
|
||||||
#----------------------------------------------
|
|
||||||
- name: Install project
|
|
||||||
run: poetry install --no-interaction --all-extras
|
|
||||||
|
|
||||||
#----------------------------------------------
|
|
||||||
# run tests & coverage
|
|
||||||
#----------------------------------------------
|
|
||||||
- name: Run tests
|
|
||||||
run: |
|
run: |
|
||||||
source .venv/bin/activate
|
python -m pip install --upgrade pip
|
||||||
pytest -v --cov=./lerobot --cov-report=xml tests
|
pip install -e ".[test, aloha, xarm, pusht]"
|
||||||
|
|
||||||
# TODO(aliberts): Link with HF Codecov account
|
- name: Test with pytest
|
||||||
# - name: Upload coverage reports to Codecov with GitHub Action
|
run: pytest -v --cov=./lerobot tests
|
||||||
# uses: codecov/codecov-action@v4
|
|
||||||
# with:
|
|
||||||
# files: ./coverage.xml
|
|
||||||
# verbose: true
|
|
||||||
|
|
||||||
#----------------------------------------------
|
- name: Test end-to-end
|
||||||
# run end-to-end tests
|
run: make test-end-to-end
|
||||||
#----------------------------------------------
|
|
||||||
- name: Test train ACT on ALOHA end-to-end
|
|
||||||
run: |
|
|
||||||
source .venv/bin/activate
|
|
||||||
python lerobot/scripts/train.py \
|
|
||||||
policy=act \
|
|
||||||
env=aloha \
|
|
||||||
wandb.enable=False \
|
|
||||||
offline_steps=2 \
|
|
||||||
online_steps=0 \
|
|
||||||
eval_episodes=1 \
|
|
||||||
device=cpu \
|
|
||||||
save_model=true \
|
|
||||||
save_freq=2 \
|
|
||||||
policy.n_action_steps=20 \
|
|
||||||
policy.chunk_size=20 \
|
|
||||||
policy.batch_size=2 \
|
|
||||||
hydra.run.dir=tests/outputs/act/
|
|
||||||
|
|
||||||
- name: Test eval ACT on ALOHA end-to-end
|
|
||||||
run: |
|
|
||||||
source .venv/bin/activate
|
|
||||||
python lerobot/scripts/eval.py \
|
|
||||||
--config tests/outputs/act/.hydra/config.yaml \
|
|
||||||
eval_episodes=1 \
|
|
||||||
env.episode_length=8 \
|
|
||||||
device=cpu \
|
|
||||||
policy.pretrained_model_path=tests/outputs/act/models/2.pt
|
|
||||||
|
|
||||||
- name: Test train Diffusion on PushT end-to-end
|
|
||||||
run: |
|
|
||||||
source .venv/bin/activate
|
|
||||||
python lerobot/scripts/train.py \
|
|
||||||
policy=diffusion \
|
|
||||||
env=pusht \
|
|
||||||
wandb.enable=False \
|
|
||||||
offline_steps=2 \
|
|
||||||
online_steps=0 \
|
|
||||||
eval_episodes=1 \
|
|
||||||
device=cpu \
|
|
||||||
save_model=true \
|
|
||||||
save_freq=2 \
|
|
||||||
policy.batch_size=2 \
|
|
||||||
hydra.run.dir=tests/outputs/diffusion/
|
|
||||||
|
|
||||||
- name: Test eval Diffusion on PushT end-to-end
|
|
||||||
run: |
|
|
||||||
source .venv/bin/activate
|
|
||||||
python lerobot/scripts/eval.py \
|
|
||||||
--config tests/outputs/diffusion/.hydra/config.yaml \
|
|
||||||
eval_episodes=1 \
|
|
||||||
env.episode_length=8 \
|
|
||||||
device=cpu \
|
|
||||||
policy.pretrained_model_path=tests/outputs/diffusion/models/2.pt
|
|
||||||
|
|
||||||
- name: Test train TDMPC on Simxarm end-to-end
|
|
||||||
run: |
|
|
||||||
source .venv/bin/activate
|
|
||||||
python lerobot/scripts/train.py \
|
|
||||||
policy=tdmpc \
|
|
||||||
env=xarm \
|
|
||||||
wandb.enable=False \
|
|
||||||
offline_steps=1 \
|
|
||||||
online_steps=2 \
|
|
||||||
eval_episodes=1 \
|
|
||||||
env.episode_length=2 \
|
|
||||||
device=cpu \
|
|
||||||
save_model=true \
|
|
||||||
save_freq=2 \
|
|
||||||
policy.batch_size=2 \
|
|
||||||
hydra.run.dir=tests/outputs/tdmpc/
|
|
||||||
|
|
||||||
- name: Test eval TDMPC on Simxarm end-to-end
|
|
||||||
run: |
|
|
||||||
source .venv/bin/activate
|
|
||||||
python lerobot/scripts/eval.py \
|
|
||||||
--config tests/outputs/tdmpc/.hydra/config.yaml \
|
|
||||||
eval_episodes=1 \
|
|
||||||
env.episode_length=8 \
|
|
||||||
device=cpu \
|
|
||||||
policy.pretrained_model_path=tests/outputs/tdmpc/models/2.pt
|
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
.PHONY: tests
|
||||||
|
|
||||||
|
build-cpu:
|
||||||
|
docker build -t lerobot:latest -f docker/lerobot-cpu/Dockerfile .
|
||||||
|
|
||||||
|
build-gpu:
|
||||||
|
docker build -t lerobot:latest -f docker/lerobot-gpu/Dockerfile .
|
||||||
|
|
||||||
|
test-end-to-end:
|
||||||
|
${MAKE} test-act-ete-train
|
||||||
|
${MAKE} test-act-ete-eval
|
||||||
|
${MAKE} test-diffusion-ete-train
|
||||||
|
${MAKE} test-diffusion-ete-eval
|
||||||
|
${MAKE} test-tdmpc-ete-train
|
||||||
|
${MAKE} test-tdmpc-ete-eval
|
||||||
|
|
||||||
|
test-act-ete-train:
|
||||||
|
python lerobot/scripts/train.py \
|
||||||
|
policy=act \
|
||||||
|
env=aloha \
|
||||||
|
wandb.enable=False \
|
||||||
|
offline_steps=2 \
|
||||||
|
online_steps=0 \
|
||||||
|
eval_episodes=1 \
|
||||||
|
device=cpu \
|
||||||
|
save_model=true \
|
||||||
|
save_freq=2 \
|
||||||
|
policy.n_action_steps=20 \
|
||||||
|
policy.chunk_size=20 \
|
||||||
|
policy.batch_size=2 \
|
||||||
|
hydra.run.dir=tests/outputs/act/
|
||||||
|
|
||||||
|
test-act-ete-eval:
|
||||||
|
python lerobot/scripts/eval.py \
|
||||||
|
--config tests/outputs/act/.hydra/config.yaml \
|
||||||
|
eval_episodes=1 \
|
||||||
|
env.episode_length=8 \
|
||||||
|
device=cpu \
|
||||||
|
policy.pretrained_model_path=tests/outputs/act/models/2.pt
|
||||||
|
|
||||||
|
test-diffusion-ete-train:
|
||||||
|
python lerobot/scripts/train.py \
|
||||||
|
policy=diffusion \
|
||||||
|
env=pusht \
|
||||||
|
wandb.enable=False \
|
||||||
|
offline_steps=2 \
|
||||||
|
online_steps=0 \
|
||||||
|
eval_episodes=1 \
|
||||||
|
device=cpu \
|
||||||
|
save_model=true \
|
||||||
|
save_freq=2 \
|
||||||
|
policy.batch_size=2 \
|
||||||
|
hydra.run.dir=tests/outputs/diffusion/
|
||||||
|
|
||||||
|
test-diffusion-ete-eval:
|
||||||
|
python lerobot/scripts/eval.py \
|
||||||
|
--config tests/outputs/diffusion/.hydra/config.yaml \
|
||||||
|
eval_episodes=1 \
|
||||||
|
env.episode_length=8 \
|
||||||
|
device=cpu \
|
||||||
|
policy.pretrained_model_path=tests/outputs/diffusion/models/2.pt
|
||||||
|
|
||||||
|
test-tdmpc-ete-train:
|
||||||
|
python lerobot/scripts/train.py \
|
||||||
|
policy=tdmpc \
|
||||||
|
env=xarm \
|
||||||
|
wandb.enable=False \
|
||||||
|
offline_steps=1 \
|
||||||
|
online_steps=2 \
|
||||||
|
eval_episodes=1 \
|
||||||
|
env.episode_length=2 \
|
||||||
|
device=cpu \
|
||||||
|
save_model=true \
|
||||||
|
save_freq=2 \
|
||||||
|
policy.batch_size=2 \
|
||||||
|
hydra.run.dir=tests/outputs/tdmpc/
|
||||||
|
|
||||||
|
test-tdmpc-ete-eval:
|
||||||
|
python lerobot/scripts/eval.py \
|
||||||
|
--config tests/outputs/tdmpc/.hydra/config.yaml \
|
||||||
|
eval_episodes=1 \
|
||||||
|
env.episode_length=8 \
|
||||||
|
device=cpu \
|
||||||
|
policy.pretrained_model_path=tests/outputs/tdmpc/models/2.pt
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Configure image
|
||||||
|
ARG PYTHON_VERSION=3.10
|
||||||
|
|
||||||
|
FROM python:${PYTHON_VERSION}-slim
|
||||||
|
ARG PYTHON_VERSION
|
||||||
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
# Install apt dependencies
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
build-essential cmake \
|
||||||
|
libglib2.0-0 libgl1-mesa-glx libegl1-mesa \
|
||||||
|
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Create virtual environment
|
||||||
|
RUN ln -s /usr/bin/python${PYTHON_VERSION} /usr/bin/python
|
||||||
|
RUN python -m venv /opt/venv
|
||||||
|
ENV PATH="/opt/venv/bin:$PATH"
|
||||||
|
RUN echo "source /opt/venv/bin/activate" >> /root/.bashrc
|
||||||
|
|
||||||
|
# Install LeRobot
|
||||||
|
COPY . /lerobot
|
||||||
|
WORKDIR /lerobot
|
||||||
|
RUN pip install --upgrade --no-cache-dir pip
|
||||||
|
RUN pip install --no-cache-dir ".[test, aloha, xarm, pusht]" \
|
||||||
|
--extra-index-url https://download.pytorch.org/whl/cpu
|
||||||
|
|
||||||
|
# Set EGL as the rendering backend for MuJoCo
|
||||||
|
ENV MUJOCO_GL="egl"
|
||||||
|
|
||||||
|
# Execute in bash shell rather than python
|
||||||
|
CMD ["/bin/bash"]
|
|
@ -0,0 +1,29 @@
|
||||||
|
FROM nvidia/cuda:12.4.1-base-ubuntu22.04
|
||||||
|
|
||||||
|
# Configure image
|
||||||
|
ARG PYTHON_VERSION=3.10
|
||||||
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
|
||||||
|
# Install apt dependencies
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
build-essential cmake \
|
||||||
|
libglib2.0-0 libgl1-mesa-glx libegl1-mesa \
|
||||||
|
python${PYTHON_VERSION} python${PYTHON_VERSION}-venv \
|
||||||
|
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
|
||||||
|
# Create virtual environment
|
||||||
|
RUN ln -s /usr/bin/python${PYTHON_VERSION} /usr/bin/python
|
||||||
|
RUN python -m venv /opt/venv
|
||||||
|
ENV PATH="/opt/venv/bin:$PATH"
|
||||||
|
RUN echo "source /opt/venv/bin/activate" >> /root/.bashrc
|
||||||
|
|
||||||
|
# Install LeRobot
|
||||||
|
COPY . /lerobot
|
||||||
|
WORKDIR /lerobot
|
||||||
|
RUN pip install --upgrade --no-cache-dir pip
|
||||||
|
RUN pip install --no-cache-dir ".[test, aloha, xarm, pusht]"
|
||||||
|
|
||||||
|
# Set EGL as the rendering backend for MuJoCo
|
||||||
|
ENV MUJOCO_GL="egl"
|
|
@ -1164,7 +1164,7 @@ mujoco = "^2.3.7"
|
||||||
type = "git"
|
type = "git"
|
||||||
url = "git@github.com:huggingface/gym-xarm.git"
|
url = "git@github.com:huggingface/gym-xarm.git"
|
||||||
reference = "HEAD"
|
reference = "HEAD"
|
||||||
resolved_reference = "6a88f7d63833705dfbec4b997bf36cac6b4a448c"
|
resolved_reference = "27e65c981f9a8d252eca8f157f83508ba6149db7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gymnasium"
|
name = "gymnasium"
|
||||||
|
@ -2909,6 +2909,7 @@ files = [
|
||||||
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
|
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
|
||||||
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
|
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
|
||||||
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
|
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
|
||||||
|
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
|
||||||
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
|
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
|
||||||
{file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
|
{file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
|
||||||
{file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
|
{file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
from .utils import DEVICE
|
||||||
|
|
||||||
|
|
||||||
|
def pytest_collection_finish():
|
||||||
|
print(f"\nTesting with {DEVICE=}")
|
Loading…
Reference in New Issue