Compare commits
109 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 44eb158748 | |||
| d3917b10e7 | |||
| 86b3b74b21 | |||
| bb385f7786 | |||
| e07ad4c9ee | |||
| 1e03b45986 | |||
| 7a1b556b25 | |||
| d7911ffaf7 | |||
| daa7f54dd0 | |||
| 753136ade4 | |||
| 579763620d | |||
| cbc22adb76 | |||
| 82bb65bd52 | |||
| 671e553239 | |||
| fa4bcc034d | |||
| 0a048da8a4 | |||
| 7808a1166c | |||
| b9b2ebbe13 | |||
| b4b53e80eb | |||
| 2212fdabf7 | |||
| 1e8a174e0c | |||
| 6868d5ba6f | |||
| e203006537 | |||
| 1c72e1e564 | |||
| aecd02e850 | |||
| 5019970d01 | |||
| 446547df04 | |||
| dea98e71b8 | |||
| ea62fa1cec | |||
| 32129ee5a2 | |||
| 6638c13c36 | |||
| 98ab6a52f6 | |||
| f9d3020616 | |||
| 1c98cf7053 | |||
| 6b98cb311f | |||
| 8a4bf2d437 | |||
| db645b7db8 | |||
| 3f4c491202 | |||
| 39d3adddff | |||
| d557058db7 | |||
| 3126bdb90a | |||
| d2f73683f8 | |||
| 83978d4c68 | |||
| bb00940631 | |||
| 29bcd3aa01 | |||
| 42481f2db3 | |||
| 928d22d370 | |||
| 169e12a4c6 | |||
| 26ad0cd2b9 | |||
| 63fc8ff722 | |||
| bb912d3473 | |||
| 7cb41c2daa | |||
| c7af299b48 | |||
| c0698e953b | |||
| 54bf8328a1 | |||
| ace9daea3e | |||
| 255990f45b | |||
| 1742e84da5 | |||
| 2b4021eaa2 | |||
| 670ead38ad | |||
| c12c4a6e0d | |||
| bd5e3b5cb4 | |||
| 82fede52ac | |||
| 76fa43cf78 | |||
| 7ec12a8b9d | |||
| b714ea60c3 | |||
| 1797e83de8 | |||
| 593ae652e6 | |||
| 963818be15 | |||
| 47b977f9b2 | |||
| 8c0f655483 | |||
| e0aacc9dc7 | |||
| 24472967eb | |||
| 1a2e43aa58 | |||
| ffed902922 | |||
| 325868514b | |||
| dbfdd2dec5 | |||
| de7f8f6b70 | |||
| 552fe67430 | |||
| de28654c6d | |||
| 02c190894a | |||
| 7df9a61f89 | |||
| dad8b3c15a | |||
| e24448ed18 | |||
| 9befc84294 | |||
| bb489e8ec2 | |||
| f208f0228c | |||
| e4e8f987e1 | |||
| 9f74f1ca9c | |||
| bb1a9e43cf | |||
| 501182017e | |||
| 710dc3e951 | |||
| 12242d94c2 | |||
| 19336ff9ee | |||
| 8e1de74918 | |||
| 137ed60056 | |||
| d320265936 | |||
| 97346a44bc | |||
| 1e0b08250d | |||
| 6a928e9322 | |||
| 5315431058 | |||
| aa11928c03 | |||
| 369c3e150a | |||
| c4e82e0740 | |||
| 95152b6f7f | |||
| 3bd1a79bfa | |||
| 42fcfc3930 | |||
| 60f2bb743d | |||
| f8902bd258 |
@@ -0,0 +1,12 @@
|
|||||||
|
[bumpversion]
|
||||||
|
current_version = 1.1.5
|
||||||
|
commit = True
|
||||||
|
tag = True
|
||||||
|
tag_name = {new_version}
|
||||||
|
message = New release: {current_version} → {new_version}
|
||||||
|
|
||||||
|
[bumpversion:file:.bumpversion.cfg]
|
||||||
|
|
||||||
|
[bumpversion:file:qmk_cli/__init__.py]
|
||||||
|
|
||||||
|
[bumpversion:file:setup.cfg]
|
||||||
@@ -7,6 +7,8 @@ updates:
|
|||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "daily"
|
||||||
|
reviewers:
|
||||||
|
- "qmk/collaborators"
|
||||||
- package-ecosystem: "pip" # See documentation for possible values
|
- package-ecosystem: "pip" # See documentation for possible values
|
||||||
directory: "/" # Location of package manifests
|
directory: "/" # Location of package manifests
|
||||||
schedule:
|
schedule:
|
||||||
|
|||||||
@@ -7,20 +7,38 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
test_cli_base_container:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container: ghcr.io/qmk/qmk_base_container
|
||||||
|
|
||||||
|
env:
|
||||||
|
QMK_HOME: ~/qmk_firmware
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: apt-get update && apt-get install -y python3-venv
|
||||||
|
|
||||||
|
- name: Run ci_tests
|
||||||
|
run: ./ci_tests -a
|
||||||
|
|
||||||
test_cli_linux_macos:
|
test_cli_linux_macos:
|
||||||
|
needs: test_cli_base_container
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
env:
|
env:
|
||||||
QMK_HOME: ~/qmk_firmware
|
QMK_HOME: ~/qmk_firmware
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [macos-latest, ubuntu-latest]
|
os: [macos-latest, ubuntu-latest]
|
||||||
python-version: [3.7, 3.8, 3.9]
|
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12']
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2.3.4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
uses: actions/setup-python@v2.2.2
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
|
|
||||||
@@ -28,18 +46,20 @@ jobs:
|
|||||||
run: ./ci_tests -a
|
run: ./ci_tests -a
|
||||||
|
|
||||||
test_cli_win:
|
test_cli_win:
|
||||||
|
needs: test_cli_base_container
|
||||||
|
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
env:
|
env:
|
||||||
QMK_HOME: $HOME/qmk_firmware
|
QMK_HOME: $HOME/qmk_firmware
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2.3.4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: (MSYS2) Setup and install dependencies
|
- name: (MSYS2) Setup and install dependencies
|
||||||
uses: msys2/setup-msys2@v2
|
uses: msys2/setup-msys2@v2
|
||||||
with:
|
with:
|
||||||
update: true
|
update: true
|
||||||
install: git mingw-w64-x86_64-toolchain mingw-w64-x86_64-python-pip
|
install: git mingw-w64-x86_64-toolchain mingw-w64-x86_64-python-pip mingw-w64-x86_64-python-pillow mingw-w64-x86_64-rust
|
||||||
|
|
||||||
- name: (MSYS2) Install Python dependencies
|
- name: (MSYS2) Install Python dependencies
|
||||||
shell: msys2 {0}
|
shell: msys2 {0}
|
||||||
|
|||||||
@@ -39,11 +39,11 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v2.3.4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v1
|
uses: github/codeql-action/init@v2
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
@@ -54,7 +54,7 @@ jobs:
|
|||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
# If this step fails, then you should remove it and run the build manually (see below)
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@v1
|
uses: github/codeql-action/autobuild@v2
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
# 📚 https://git.io/JvXDl
|
# 📚 https://git.io/JvXDl
|
||||||
@@ -68,4 +68,4 @@ jobs:
|
|||||||
# make release
|
# make release
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v1
|
uses: github/codeql-action/analyze@v2
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
name: Rebuild Docker Image
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
redeploy:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.7'
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: 'Get Previous tag'
|
||||||
|
id: previoustag
|
||||||
|
uses: "WyriHaximus/github-action-get-previous-tag@v1"
|
||||||
|
|
||||||
|
- name: Download previous artifact
|
||||||
|
run: |
|
||||||
|
pip download -d "${GITHUB_WORKSPACE}/dist" qmk=="${{ steps.previoustag.outputs.tag }}"
|
||||||
|
|
||||||
|
- name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Log in to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and Push to Docker Hub
|
||||||
|
uses: docker/build-push-action@v5.1.0
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
tags: |
|
||||||
|
ghcr.io/qmk/qmk_cli:latest
|
||||||
|
qmkfm/qmk_cli:latest
|
||||||
@@ -17,47 +17,72 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2.3.4
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v2.2.2
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: '3.7'
|
python-version: '3.7'
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Run ci_tests
|
- name: Run ci_tests
|
||||||
run: ./ci_tests
|
run: ./ci_tests
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python3 -m pip install --upgrade pip
|
python3 -m pip install --upgrade pip
|
||||||
pip install setuptools wheel
|
pip install setuptools wheel
|
||||||
pip install -r requirements-dev.txt
|
pip install -r requirements-dev.txt
|
||||||
|
|
||||||
- name: Bump version
|
- name: Bump version
|
||||||
run: |
|
run: |
|
||||||
git config --local user.email "hello@qmk.fm"
|
git config --local user.email "hello@qmk.fm"
|
||||||
git config --local user.name "QMK Bot"
|
git config --local user.name "QMK Bot"
|
||||||
bumpversion ${{ github.event.inputs.version_part }}
|
bumpversion ${{ github.event.inputs.version_part }}
|
||||||
|
|
||||||
- name: Push changes
|
- name: Push changes
|
||||||
uses: ad-m/github-push-action@master
|
uses: ad-m/github-push-action@master
|
||||||
with:
|
with:
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
branch: master
|
branch: master
|
||||||
tags: true
|
tags: true
|
||||||
|
|
||||||
- name: Build and publish
|
- name: Build and publish
|
||||||
env:
|
env:
|
||||||
TWINE_USERNAME: qmk
|
TWINE_USERNAME: __token__
|
||||||
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
|
TWINE_PASSWORD: ${{ secrets.PYPI_APITOKEN }}
|
||||||
run: |
|
run: |
|
||||||
python3 -m build
|
python3 -m build
|
||||||
twine upload dist/*
|
twine upload dist/*
|
||||||
|
|
||||||
|
- name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Log in to Docker Hub
|
- name: Log in to Docker Hub
|
||||||
uses: docker/login-action@v1.10.0
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||||
|
|
||||||
- name: Build and Push to Docker Hub
|
- name: Build and Push to Docker Hub
|
||||||
uses: docker/build-push-action@v2.6.1
|
uses: docker/build-push-action@v5.1.0
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: true
|
||||||
tags: qmkfm/qmk_cli:latest
|
platforms: linux/amd64,linux/arm64
|
||||||
|
tags: |
|
||||||
|
ghcr.io/qmk/qmk_cli:latest
|
||||||
|
qmkfm/qmk_cli:latest
|
||||||
|
|
||||||
- name: Trigger OS package builds
|
- name: Trigger OS package builds
|
||||||
run: ./trigger_packages
|
run: ./trigger_packages
|
||||||
env:
|
env:
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
FROM qmkfm/base_container
|
FROM ghcr.io/qmk/qmk_base_container:latest
|
||||||
|
|
||||||
# Copy package in
|
# Copy package in
|
||||||
ADD dist /tmp/dist
|
ADD dist /tmp/dist
|
||||||
|
|||||||
@@ -17,9 +17,43 @@ A program to help users work with [QMK Firmware](https://qmk.fm/).
|
|||||||
* `qmk lint`
|
* `qmk lint`
|
||||||
* ...and many more!
|
* ...and many more!
|
||||||
|
|
||||||
|
# Packages
|
||||||
|
|
||||||
|
We provide "install and go" packages for many Operating Systems.
|
||||||
|
|
||||||
|
## Linux
|
||||||
|
|
||||||
|
Packages for several distributions available here: https://github.com/qmk/qmk_fpm
|
||||||
|
|
||||||
|
## macOS
|
||||||
|
|
||||||
|
Using [Homebrew](https://brew.sh):
|
||||||
|
|
||||||
|
brew install qmk/qmk/qmk
|
||||||
|
|
||||||
|
## Windows
|
||||||
|
|
||||||
|
Download our custom MSYS2 installer here: https://msys.qmk.fm/
|
||||||
|
|
||||||
# Quickstart
|
# Quickstart
|
||||||
|
|
||||||
* `python3 -m pip install qmk`
|
* `python3 -m pip install qmk`
|
||||||
* `qmk setup`
|
* `qmk setup`
|
||||||
|
|
||||||
|
# Building
|
||||||
|
|
||||||
|
We follow PEP517, you can install using [build](https://pypi.org/project/build/):
|
||||||
|
|
||||||
|
Setup:
|
||||||
|
|
||||||
|
python3 -m pip install build
|
||||||
|
|
||||||
|
Build:
|
||||||
|
|
||||||
|
python3 -m build
|
||||||
|
|
||||||
|
You can read more about working with PEP517 packages in the [Python Packaging User Guide](https://packaging.python.org/guides/distributing-packages-using-setuptools/#packaging-your-project).
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
|
||||||
Full documentation: <https://docs.qmk.fm/#/tutorial>
|
Full documentation: <https://docs.qmk.fm/#/tutorial>
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ python3 -m pip install -r requirements-dev.txt
|
|||||||
# Ensure that qmk works
|
# Ensure that qmk works
|
||||||
echo "*** Testing 'qmk clone -h'"
|
echo "*** Testing 'qmk clone -h'"
|
||||||
qmk clone -h
|
qmk clone -h
|
||||||
echo "*** Testing 'qmk config -a'"
|
#echo "*** Testing 'qmk config -a'" # Test disabled as `milc` at least 1.6.8+ returns False and thus non-zero exit code
|
||||||
qmk config -a
|
#qmk config -a
|
||||||
echo "*** Testing 'qmk setup -n'"
|
echo "*** Testing 'qmk setup -n'"
|
||||||
qmk setup -n
|
qmk setup -n
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
"""A program to help you work with qmk_firmware."""
|
"""A program to help you work with qmk_firmware."""
|
||||||
|
|
||||||
__version__ = '0.3.1'
|
__version__ = '1.1.5'
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import sys
|
|||||||
from platform import platform
|
from platform import platform
|
||||||
from traceback import print_exc
|
from traceback import print_exc
|
||||||
|
|
||||||
|
from . import switch_to_venv # noqa, intentionally unused
|
||||||
|
|
||||||
import milc
|
import milc
|
||||||
|
|
||||||
from . import __version__
|
from . import __version__
|
||||||
|
|||||||
@@ -6,3 +6,4 @@ from . import clone # noqa
|
|||||||
from . import console # noqa
|
from . import console # noqa
|
||||||
from . import env # noqa
|
from . import env # noqa
|
||||||
from . import setup # noqa
|
from . import setup # noqa
|
||||||
|
from . import pip # noqa
|
||||||
|
|||||||
@@ -11,20 +11,21 @@ default_fork = 'qmk/' + default_repo
|
|||||||
default_branch = 'master'
|
default_branch = 'master'
|
||||||
|
|
||||||
|
|
||||||
@cli.argument('--baseurl', default='https://github.com', help='The URL all git operations start from (Default: https://github.com)')
|
@cli.argument('--baseurl', arg_only=True, default='https://github.com', help='The URL all git operations start from (Default: https://github.com)')
|
||||||
@cli.argument('-b', '--branch', default=default_branch, help='The branch to clone. Default: %s' % default_branch)
|
@cli.argument('-b', '--branch', arg_only=True, default=default_branch, help='The branch to clone. Default: %s' % default_branch)
|
||||||
@cli.argument('destination', default=None, nargs='?', help='The directory to clone to. Default: (current directory)')
|
@cli.argument('destination', arg_only=True, default=None, nargs='?', help='The directory to clone to. Default: (current directory)')
|
||||||
@cli.argument('fork', default=default_fork, nargs='?', help='The qmk_firmware fork to clone. Default: %s' % default_fork)
|
@cli.argument('fork', arg_only=True, default=default_fork, nargs='?', help='The qmk_firmware fork to clone. Default: %s' % default_fork)
|
||||||
@cli.subcommand('Clone a qmk_firmware fork.')
|
@cli.subcommand('Clone a qmk_firmware fork.')
|
||||||
def clone(cli):
|
def clone(cli):
|
||||||
if not cli.args.destination:
|
if not cli.args.destination:
|
||||||
cli.args.destination = os.path.join(os.environ['ORIG_CWD'], default_fork.split('/')[-1])
|
cli.args.destination = os.path.join(os.environ['ORIG_CWD'], default_fork.split('/')[-1])
|
||||||
|
|
||||||
qmk_firmware = Path(cli.args.destination)
|
qmk_firmware = Path(cli.args.destination)
|
||||||
git_url = '/'.join((cli.config.clone.baseurl, cli.args.fork))
|
git_url = '/'.join((cli.args.baseurl, cli.args.fork))
|
||||||
|
|
||||||
if qmk_firmware.exists():
|
# Exists (but not an empty dir)
|
||||||
|
if qmk_firmware.exists() and any(qmk_firmware.iterdir()):
|
||||||
cli.log.error('Destination already exists: %s', cli.args.destination)
|
cli.log.error('Destination already exists: %s', cli.args.destination)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
return git_clone(git_url, cli.args.destination, cli.config.clone.branch)
|
return git_clone(git_url, cli.args.destination, cli.args.branch)
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ LOG_COLOR = {
|
|||||||
|
|
||||||
KNOWN_BOOTLOADERS = {
|
KNOWN_BOOTLOADERS = {
|
||||||
# VID , PID
|
# VID , PID
|
||||||
|
('03EB', '2045'): 'lufa-ms: LUFA Mass Storage Bootloader',
|
||||||
|
('03EB', '2067'): 'qmk-hid: HID Bootloader',
|
||||||
('03EB', '2FEF'): 'atmel-dfu: ATmega16U2',
|
('03EB', '2FEF'): 'atmel-dfu: ATmega16U2',
|
||||||
('03EB', '2FF0'): 'atmel-dfu: ATmega32U2',
|
('03EB', '2FF0'): 'atmel-dfu: ATmega32U2',
|
||||||
('03EB', '2FF3'): 'atmel-dfu: ATmega16U4',
|
('03EB', '2FF3'): 'atmel-dfu: ATmega16U4',
|
||||||
@@ -34,24 +36,24 @@ KNOWN_BOOTLOADERS = {
|
|||||||
('03EB', '2FFB'): 'atmel-dfu: AT90USB128',
|
('03EB', '2FFB'): 'atmel-dfu: AT90USB128',
|
||||||
('03EB', '6124'): 'Microchip SAM-BA',
|
('03EB', '6124'): 'Microchip SAM-BA',
|
||||||
('0483', 'DF11'): 'stm32-dfu: STM32 BOOTLOADER',
|
('0483', 'DF11'): 'stm32-dfu: STM32 BOOTLOADER',
|
||||||
('16C0', '05DC'): 'USBasp: USBaspLoader',
|
('16C0', '05DC'): 'usbasploader: USBaspLoader',
|
||||||
('16C0', '05DF'): 'bootloadHID: HIDBoot',
|
('16C0', '05DF'): 'bootloadhid: HIDBoot',
|
||||||
('16C0', '0478'): 'halfkay: Teensy Halfkay',
|
('16C0', '0478'): 'halfkay: Teensy Halfkay',
|
||||||
('1B4F', '9203'): 'caterina: Pro Micro 3.3V',
|
('1B4F', '9203'): 'caterina: Pro Micro 3.3V',
|
||||||
('1B4F', '9205'): 'caterina: Pro Micro 5V',
|
('1B4F', '9205'): 'caterina: Pro Micro 5V',
|
||||||
('1B4F', '9207'): 'caterina: LilyPadUSB',
|
('1B4F', '9207'): 'caterina: LilyPadUSB',
|
||||||
('1C11', 'B007'): 'kiibohd: Kiibohd DFU Bootloader',
|
('1C11', 'B007'): 'kiibohd: Kiibohd DFU Bootloader',
|
||||||
('1EAF', '0003'): 'stm32duino: Maple 003',
|
('1EAF', '0003'): 'stm32duino: Maple 003',
|
||||||
('1FFB', '0101'): 'caterina: Polou A-Star 32U4 Bootloader',
|
('1FFB', '0101'): 'caterina: Pololu A-Star 32U4 Bootloader',
|
||||||
('2341', '0036'): 'caterina: Arduino Leonardo',
|
('2341', '0036'): 'caterina: Arduino Leonardo',
|
||||||
('2341', '0037'): 'caterina: Arduino Micro',
|
('2341', '0037'): 'caterina: Arduino Micro',
|
||||||
('239A', '000C'): 'caterina: Adafruit Feather 32U4',
|
('239A', '000C'): 'caterina: Adafruit Feather 32U4',
|
||||||
('239A', '000D'): 'caterina: Adafruit ItsyBitsy 32U4 3v',
|
('239A', '000D'): 'caterina: Adafruit ItsyBitsy 32U4 3v',
|
||||||
('239A', '000E'): 'caterina: Adafruit ItsyBitsy 32U4 5v',
|
('239A', '000E'): 'caterina: Adafruit ItsyBitsy 32U4 5v',
|
||||||
('239A', '000E'): 'caterina: Adafruit ItsyBitsy 32U4 5v',
|
|
||||||
('2A03', '0036'): 'caterina: Arduino Leonardo',
|
('2A03', '0036'): 'caterina: Arduino Leonardo',
|
||||||
('2A03', '0037'): 'caterina: Arduino Micro',
|
('2A03', '0037'): 'caterina: Arduino Micro',
|
||||||
('314B', '0106'): 'apm32-dfu: APM32 DFU ISP Mode'
|
('314B', '0106'): 'apm32-dfu: APM32 DFU ISP Mode',
|
||||||
|
('342D', 'DFA0'): 'wb32-dfu: WB32 Device in DFU Mode'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -141,7 +143,7 @@ class MonitorDevice(object):
|
|||||||
message['identifier'] = ':'.join(identifier)
|
message['identifier'] = ':'.join(identifier)
|
||||||
message['ts'] = '{style_dim}{fg_green}%s{style_reset_all} ' % (strftime(cli.config.general.datetime_fmt),) if cli.args.timestamp else ''
|
message['ts'] = '{style_dim}{fg_green}%s{style_reset_all} ' % (strftime(cli.config.general.datetime_fmt),) if cli.args.timestamp else ''
|
||||||
|
|
||||||
cli.echo('%(ts)s%(color)s%(identifier)s:%(index)d{style_reset_all}: %(text)s' % message)
|
cli.echo('%s', '%(ts)s%(color)s%(identifier)s:%(index)d{style_reset_all}: %(text)s' % message)
|
||||||
|
|
||||||
except self.hid.HIDException:
|
except self.hid.HIDException:
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from milc import cli
|
|||||||
from qmk_cli.helpers import is_qmk_firmware
|
from qmk_cli.helpers import is_qmk_firmware
|
||||||
|
|
||||||
|
|
||||||
@cli.argument('var', default=None, nargs='?', help='Optional variable to query')
|
@cli.argument('var', arg_only=True, default=None, nargs='?', help='Optional variable to query')
|
||||||
@cli.subcommand('Prints environment information.')
|
@cli.subcommand('Prints environment information.')
|
||||||
def env(cli):
|
def env(cli):
|
||||||
home = os.environ.get('QMK_HOME', "")
|
home = os.environ.get('QMK_HOME', "")
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
"""Installs python dependencies.
|
||||||
|
"""
|
||||||
|
import shlex
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
from milc import cli
|
||||||
|
|
||||||
|
from qmk_cli.helpers import find_qmk_firmware, is_qmk_firmware
|
||||||
|
|
||||||
|
|
||||||
|
def _run_pip(pip_args, dry_run=False, upgrade=False):
|
||||||
|
pip_exe = ['pip']
|
||||||
|
if cli.config.user.pip_exe:
|
||||||
|
pip_exe = shlex.split(cli.config.user.pip_exe)
|
||||||
|
pip_command = [*pip_exe, *pip_args]
|
||||||
|
pip_command[0] = shutil.which(pip_command[0])
|
||||||
|
if shutil.which(pip_command[0]) is None:
|
||||||
|
pip_command[0] = 'pip' # Hope falling back to unqualified path works
|
||||||
|
|
||||||
|
if dry_run:
|
||||||
|
print(" ".join(shlex.quote(str(s)) for s in pip_command))
|
||||||
|
return True
|
||||||
|
|
||||||
|
try:
|
||||||
|
with subprocess.Popen(pip_command, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, bufsize=1, universal_newlines=True, encoding='utf-8') as p:
|
||||||
|
for line in p.stdout:
|
||||||
|
print(line, end='')
|
||||||
|
except Exception as e:
|
||||||
|
pip_cmd = ' '.join([s.replace(' ', r'\ ') for s in pip_command])
|
||||||
|
cli.log.error("Could not run '%s': %s: %s", pip_cmd, e.__class__.__name__, e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
if p.returncode == 0:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def install_qmk_python_deps(upgrade=False, developer=False, dry_run=False):
|
||||||
|
qmk_firmware_dir = find_qmk_firmware()
|
||||||
|
if not is_qmk_firmware(qmk_firmware_dir):
|
||||||
|
cli.log.error('Could not find {fg_cyan}qmk_firmware{fg_reset}!')
|
||||||
|
return False
|
||||||
|
|
||||||
|
reqs_path = qmk_firmware_dir / 'requirements.txt' if not developer else qmk_firmware_dir / 'requirements-dev.txt'
|
||||||
|
|
||||||
|
pip_args = ['install', '-r', reqs_path]
|
||||||
|
if upgrade:
|
||||||
|
pip_args.append('--upgrade')
|
||||||
|
|
||||||
|
if _run_pip(pip_args, dry_run=dry_run):
|
||||||
|
if not dry_run:
|
||||||
|
cli.log.info('Successfully installed python dependencies!')
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
if not dry_run:
|
||||||
|
cli.log.error('Failed to install python dependencies!')
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
@cli.argument('-u', '--upgrade', arg_only=True, action='store_true', help='Upgrades existing packages.')
|
||||||
|
@cli.argument('-d', '--developer', arg_only=True, action='store_true', help='Installs QMK Firmware developer dependencies, too.')
|
||||||
|
@cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help='Prints the commands to execute, rather than executing them.')
|
||||||
|
@cli.subcommand('Installs python dependencies.')
|
||||||
|
def install_deps(cli):
|
||||||
|
return install_qmk_python_deps(upgrade=cli.args.upgrade, developer=cli.args.developer, dry_run=cli.args.dry_run)
|
||||||
|
|
||||||
|
|
||||||
|
@cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help='Prints the commands to execute, rather than executing them.')
|
||||||
|
@cli.argument('arguments', arg_only=True, default=[], nargs='*', help='The arguments to pass to pip.')
|
||||||
|
@cli.subcommand('Runs pip inside the qmk venv.')
|
||||||
|
def pip(cli):
|
||||||
|
return _run_pip(cli.args.arguments, dry_run=cli.args.dry_run)
|
||||||
@@ -20,7 +20,7 @@ default_branch = 'master'
|
|||||||
def git_upstream(destination):
|
def git_upstream(destination):
|
||||||
"""Add the qmk/qmk_firmware upstream to a qmk_firmware clone.
|
"""Add the qmk/qmk_firmware upstream to a qmk_firmware clone.
|
||||||
"""
|
"""
|
||||||
git_url = '/'.join((cli.config.setup.baseurl, default_fork))
|
git_url = '/'.join((cli.args.baseurl, default_fork))
|
||||||
git_cmd = [
|
git_cmd = [
|
||||||
'git',
|
'git',
|
||||||
'-C',
|
'-C',
|
||||||
@@ -45,10 +45,10 @@ def git_upstream(destination):
|
|||||||
|
|
||||||
@cli.argument('-n', '--no', arg_only=True, action='store_true', help='Answer no to all questions')
|
@cli.argument('-n', '--no', arg_only=True, action='store_true', help='Answer no to all questions')
|
||||||
@cli.argument('-y', '--yes', arg_only=True, action='store_true', help='Answer yes to all questions')
|
@cli.argument('-y', '--yes', arg_only=True, action='store_true', help='Answer yes to all questions')
|
||||||
@cli.argument('--baseurl', default=default_base, help='The URL all git operations start from. Default: %s' % default_base)
|
@cli.argument('--baseurl', arg_only=True, default=default_base, help='The URL all git operations start from. Default: %s' % default_base)
|
||||||
@cli.argument('-b', '--branch', default=default_branch, help='The branch to clone. Default: %s' % default_branch)
|
@cli.argument('-b', '--branch', arg_only=True, default=default_branch, help='The branch to clone. Default: %s' % default_branch)
|
||||||
@cli.argument('-H', '--home', default=Path(os.environ['QMK_HOME']), type=Path, help='The location for QMK Firmware. Default: %s' % os.environ['QMK_HOME'])
|
@cli.argument('-H', '--home', arg_only=True, default=Path(os.environ['QMK_HOME']), type=Path, help='The location for QMK Firmware. Default: %s' % os.environ['QMK_HOME'])
|
||||||
@cli.argument('fork', default=default_fork, nargs='?', help='The qmk_firmware fork to clone. Default: %s' % default_fork)
|
@cli.argument('fork', arg_only=True, default=default_fork, nargs='?', help='The qmk_firmware fork to clone. Default: %s' % default_fork)
|
||||||
@cli.subcommand('Setup your computer for qmk_firmware.')
|
@cli.subcommand('Setup your computer for qmk_firmware.')
|
||||||
def setup(cli):
|
def setup(cli):
|
||||||
"""Guide the user through setting up their QMK environment.
|
"""Guide the user through setting up their QMK environment.
|
||||||
@@ -65,7 +65,8 @@ def setup(cli):
|
|||||||
if is_qmk_firmware(cli.args.home):
|
if is_qmk_firmware(cli.args.home):
|
||||||
cli.log.info('Found qmk_firmware at %s.', str(cli.args.home))
|
cli.log.info('Found qmk_firmware at %s.', str(cli.args.home))
|
||||||
|
|
||||||
elif cli.args.home.exists():
|
# Exists (but not an empty dir)
|
||||||
|
elif cli.args.home.exists() and any(cli.args.home.iterdir()):
|
||||||
path_str = str(cli.args.home)
|
path_str = str(cli.args.home)
|
||||||
|
|
||||||
if cli.args.home.name != 'qmk_firmware':
|
if cli.args.home.name != 'qmk_firmware':
|
||||||
@@ -77,9 +78,9 @@ def setup(cli):
|
|||||||
else:
|
else:
|
||||||
cli.log.error('Could not find qmk_firmware!')
|
cli.log.error('Could not find qmk_firmware!')
|
||||||
if yesno(clone_prompt):
|
if yesno(clone_prompt):
|
||||||
git_url = '/'.join((cli.config.setup.baseurl, cli.args.fork))
|
git_url = '/'.join((cli.args.baseurl, cli.args.fork))
|
||||||
|
|
||||||
if git_clone(git_url, cli.args.home, cli.config.setup.branch):
|
if git_clone(git_url, cli.args.home, cli.args.branch):
|
||||||
git_upstream(cli.args.home)
|
git_upstream(cli.args.home)
|
||||||
else:
|
else:
|
||||||
exit(1)
|
exit(1)
|
||||||
@@ -104,4 +105,4 @@ def setup(cli):
|
|||||||
if cli.args.yes:
|
if cli.args.yes:
|
||||||
doctor_command.append('-y')
|
doctor_command.append('-y')
|
||||||
|
|
||||||
cli.run(doctor_command, stdin=None, capture_output=False)
|
cli.run(doctor_command, stdin=None, capture_output=False, cwd=cli.args.home)
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
""" Activates a virtualenv if not already present
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
if not os.environ.get('VIRTUAL_ENV') or True:
|
||||||
|
import site
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Build a venv if required
|
||||||
|
INTENDED_VENV_PATH = Path(os.environ['HOME']) / ".local/qmk_venv"
|
||||||
|
if not INTENDED_VENV_PATH.exists():
|
||||||
|
from venv import EnvBuilder
|
||||||
|
builder = EnvBuilder(with_pip=True)
|
||||||
|
builder.create(str(INTENDED_VENV_PATH))
|
||||||
|
|
||||||
|
# Determine the venv's bin directory
|
||||||
|
bin_dir = INTENDED_VENV_PATH / "bin"
|
||||||
|
|
||||||
|
# Update the environment to point to the QMK venv (effectively matches `source path_to_venv/bin/activate`)
|
||||||
|
os.environ["PATH"] = os.pathsep.join([str(bin_dir), *os.environ.get("PATH", "").split(os.pathsep)])
|
||||||
|
os.environ["VIRTUAL_ENV"] = str(INTENDED_VENV_PATH)
|
||||||
|
if 'PYTHONHOME' in os.environ:
|
||||||
|
os.environ.pop('PYTHONHOME')
|
||||||
|
|
||||||
|
# Prepend the venv's library paths to the python import mechanism
|
||||||
|
pyver = sys.version_info[:2]
|
||||||
|
lib_dir = INTENDED_VENV_PATH / f'lib/python{pyver[0]}.{pyver[1]}/site-packages'
|
||||||
|
for d in [lib_dir, bin_dir]:
|
||||||
|
site.addsitedir(str(d))
|
||||||
|
sys.path.insert(0, str(d))
|
||||||
|
|
||||||
|
# Update the python prefixes
|
||||||
|
sys.base_prefix = sys.prefix
|
||||||
|
sys.prefix = str(INTENDED_VENV_PATH)
|
||||||
+4
-28
@@ -1,28 +1,4 @@
|
|||||||
bleach==4.0.0
|
build
|
||||||
build==0.6.0.post1
|
bumpversion
|
||||||
bump2version==1.0.1
|
requests
|
||||||
bumpversion==0.6.0
|
twine
|
||||||
certifi==2021.5.30
|
|
||||||
cffi==1.14.6
|
|
||||||
chardet==4.0.0
|
|
||||||
cryptography==3.4.7
|
|
||||||
docutils==0.17.1
|
|
||||||
idna==2.10
|
|
||||||
importlib-metadata==4.6.3
|
|
||||||
jeepney==0.7.1
|
|
||||||
keyring==23.0.1
|
|
||||||
packaging==21.0
|
|
||||||
pkginfo==1.7.1
|
|
||||||
pycparser==2.20
|
|
||||||
pyparsing==2.4.7
|
|
||||||
readme-renderer==29.0
|
|
||||||
requests==2.26.0
|
|
||||||
requests-toolbelt==0.9.1
|
|
||||||
rfc3986==1.5.0
|
|
||||||
SecretStorage==3.3.1
|
|
||||||
six==1.16.0
|
|
||||||
tqdm==4.62.0
|
|
||||||
twine==3.4.2
|
|
||||||
urllib3==1.26.6
|
|
||||||
webencodings==0.5.1
|
|
||||||
zipp==3.5.0
|
|
||||||
|
|||||||
@@ -1,13 +1,5 @@
|
|||||||
[bumpversion]
|
#[bumpversion]
|
||||||
current_version = 0.3.1
|
# Bumpversion config has been moved to .bumpversion.cfg
|
||||||
commit = True
|
|
||||||
tag = True
|
|
||||||
tag_name = {new_version}
|
|
||||||
message = New release: {current_version} → {new_version}
|
|
||||||
|
|
||||||
[bumpversion:file:qmk_cli/__init__.py]
|
|
||||||
|
|
||||||
[bumpversion:file:setup.cfg]
|
|
||||||
|
|
||||||
[bdist_wheel]
|
[bdist_wheel]
|
||||||
universal = 1
|
universal = 1
|
||||||
@@ -17,19 +9,19 @@ ignore = E501,E226
|
|||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
name = qmk
|
name = qmk
|
||||||
version = 0.3.0
|
version = 1.1.5
|
||||||
author = skullydazed
|
author = skullydazed
|
||||||
author_email = skullydazed@gmail.com
|
author_email = skullydazed@gmail.com
|
||||||
description = A program to help users work with QMK Firmware.
|
description = A program to help users work with QMK Firmware.
|
||||||
long_description = file: README.md
|
long_description = file: README.md
|
||||||
long_description_content_type = text/markdown
|
long_description_content_type = text/markdown
|
||||||
license = MIT License
|
license = MIT License
|
||||||
project_urls =
|
project_urls =
|
||||||
Bug Tracker = https://github.com/qmk/qmk_cli/issues
|
Bug Tracker = https://github.com/qmk/qmk_cli/issues
|
||||||
Documentation = https://docs.qmk.fm/#/cli
|
Documentation = https://docs.qmk.fm/#/cli
|
||||||
Homepage = https://qmk.fm/
|
Homepage = https://qmk.fm/
|
||||||
Source = https://github.com/qmk/qmk_cli/
|
Source = https://github.com/qmk/qmk_cli/
|
||||||
classifiers =
|
classifiers =
|
||||||
Development Status :: 3 - Alpha
|
Development Status :: 3 - Alpha
|
||||||
Environment :: Console
|
Environment :: Console
|
||||||
Intended Audience :: Developers
|
Intended Audience :: Developers
|
||||||
@@ -43,30 +35,23 @@ classifiers =
|
|||||||
Topic :: Utilities
|
Topic :: Utilities
|
||||||
|
|
||||||
[options]
|
[options]
|
||||||
install_requires =
|
install_requires =
|
||||||
appdirs==1.4.4
|
hid
|
||||||
argcomplete==1.12.3
|
milc>=1.6.8
|
||||||
attrs==21.2.0
|
pyusb
|
||||||
colorama==0.4.4
|
|
||||||
coverage==5.5
|
|
||||||
halo==0.0.31
|
|
||||||
hid==1.0.4
|
|
||||||
log-symbols==0.0.14
|
|
||||||
mccabe==0.6.1
|
|
||||||
milc==1.5.0
|
|
||||||
pycodestyle==2.7.0
|
|
||||||
pyflakes==2.3.1
|
|
||||||
pyrsistent==0.18.0
|
|
||||||
pyusb==1.2.1
|
|
||||||
setuptools>=45
|
setuptools>=45
|
||||||
six==1.16.0
|
# qmk_firmware packages
|
||||||
spinners==0.0.24
|
dotty-dict
|
||||||
termcolor==1.1.0
|
hjson
|
||||||
|
jsonschema>=4
|
||||||
|
pillow
|
||||||
|
pygments
|
||||||
|
pyserial
|
||||||
packages = find:
|
packages = find:
|
||||||
python_requiures = >=3.7
|
python_requires = >=3.7
|
||||||
|
|
||||||
[options.entry_points]
|
[options.entry_points]
|
||||||
console_scripts =
|
console_scripts =
|
||||||
qmk = qmk_cli.script_qmk:main
|
qmk = qmk_cli.script_qmk:main
|
||||||
|
|
||||||
[yapf]
|
[yapf]
|
||||||
@@ -87,13 +72,13 @@ continuation_indent_width = 4
|
|||||||
dedent_closing_brackets = True
|
dedent_closing_brackets = True
|
||||||
disable_ending_comma_heuristic = False
|
disable_ending_comma_heuristic = False
|
||||||
each_dict_entry_on_separate_line = True
|
each_dict_entry_on_separate_line = True
|
||||||
i18n_comment =
|
i18n_comment =
|
||||||
i18n_function_call =
|
i18n_function_call =
|
||||||
indent_blank_lines = False
|
indent_blank_lines = False
|
||||||
indent_dictionary_value = True
|
indent_dictionary_value = True
|
||||||
indent_width = 4
|
indent_width = 4
|
||||||
join_multiple_lines = False
|
join_multiple_lines = False
|
||||||
no_spaces_around_selected_binary_operators =
|
no_spaces_around_selected_binary_operators =
|
||||||
spaces_around_default_or_named_assign = False
|
spaces_around_default_or_named_assign = False
|
||||||
spaces_around_power_operator = False
|
spaces_around_power_operator = False
|
||||||
spaces_before_comment = 2
|
spaces_before_comment = 2
|
||||||
|
|||||||
+2
-2
@@ -11,8 +11,8 @@ gh_user = environ.get('GH_USERNAME', 'qmk-bot')
|
|||||||
gh_pat = environ.get('QMK_BOT_TOKEN', '')
|
gh_pat = environ.get('QMK_BOT_TOKEN', '')
|
||||||
gh_repo_owner = environ.get('REPO_OWNER', 'qmk')
|
gh_repo_owner = environ.get('REPO_OWNER', 'qmk')
|
||||||
gh_repo_name = environ.get('REPO_NAME', 'qmk_fpm')
|
gh_repo_name = environ.get('REPO_NAME', 'qmk_fpm')
|
||||||
gh_ref = environ.get('GITHUB_REF', 'main')
|
gh_ref = environ.get('BRANCH_NAME', 'main')
|
||||||
gh_workflow_ids = environ.get('WORKFLOW_IDS', 'debian-buster-publish.yml,fedora-33-publish.yml,fedora-35-publish.yml,fedora-32-publish.yml,fedora-34-publish.yml,ubuntu-focal-publish.yml').split(',')
|
gh_workflow_ids = environ.get('WORKFLOW_IDS', 'all-trigger.yml').split(',')
|
||||||
gh_api_url = environ.get('GITHUB_API_URL', 'https://api.github.com')
|
gh_api_url = environ.get('GITHUB_API_URL', 'https://api.github.com')
|
||||||
gh_workflow_args = {'ref': gh_ref}
|
gh_workflow_args = {'ref': gh_ref}
|
||||||
gh_workflow_headers = {'Accept': 'application/vnd.github.v3+json'}
|
gh_workflow_headers = {'Accept': 'application/vnd.github.v3+json'}
|
||||||
|
|||||||
Reference in New Issue
Block a user