mirror of
https://github.com/YunoHost/ynh-dev.git
synced 2024-09-03 20:05:59 +02:00
Merge 49dbf38461
into 021514666f
This commit is contained in:
commit
6c63fd4707
7 changed files with 124 additions and 72 deletions
35
.github/workflows/autoblack.yml
vendored
35
.github/workflows/autoblack.yml
vendored
|
@ -1,35 +0,0 @@
|
||||||
name: Check / auto apply Black
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
jobs:
|
|
||||||
black:
|
|
||||||
name: Check / auto apply black
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Check files using the black formatter
|
|
||||||
uses: psf/black@stable
|
|
||||||
id: black
|
|
||||||
with:
|
|
||||||
options: "."
|
|
||||||
continue-on-error: true
|
|
||||||
- shell: pwsh
|
|
||||||
id: check_files_changed
|
|
||||||
run: |
|
|
||||||
# Diff HEAD with the previous commit
|
|
||||||
$diff = git diff
|
|
||||||
$HasDiff = $diff.Length -gt 0
|
|
||||||
Write-Host "::set-output name=files_changed::$HasDiff"
|
|
||||||
- name: Create Pull Request
|
|
||||||
if: steps.check_files_changed.outputs.files_changed == 'true'
|
|
||||||
uses: peter-evans/create-pull-request@v6
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
title: "Format Python code with Black"
|
|
||||||
commit-message: ":art: Format Python code with Black"
|
|
||||||
body: |
|
|
||||||
This pull request uses the [psf/black](https://github.com/psf/black) formatter.
|
|
||||||
base: ${{ github.head_ref }} # Creates pull request onto pull request or commit branch
|
|
||||||
branch: actions/black
|
|
28
.github/workflows/python-check.yml
vendored
Normal file
28
.github/workflows/python-check.yml
vendored
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
name: Python Lint with Ruff and Mypy
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ruff:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.9"
|
||||||
|
- name: Install Ruff and Mypy
|
||||||
|
run: pip install ruff mypy
|
||||||
|
|
||||||
|
- name: Ruff check
|
||||||
|
run: |
|
||||||
|
ruff check .
|
||||||
|
|
||||||
|
- name: Mypy install types
|
||||||
|
run: yes | mypy . --install-types || true
|
||||||
|
|
||||||
|
- name: Mypy check
|
||||||
|
run: mypy .
|
34
.github/workflows/python-format.yml
vendored
Normal file
34
.github/workflows/python-format.yml
vendored
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
name: Python formatting with Black and Ruff
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
format:
|
||||||
|
name: Formatting with Black and Ruff
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Check files using the black formatter
|
||||||
|
uses: psf/black@stable
|
||||||
|
id: black
|
||||||
|
with:
|
||||||
|
options: "."
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.9"
|
||||||
|
- name: Install Ruff
|
||||||
|
run: pip install ruff
|
||||||
|
|
||||||
|
- name: Ruff check and fix
|
||||||
|
run: |
|
||||||
|
ruff check .
|
||||||
|
ruff check --fix .
|
||||||
|
|
||||||
|
- uses: stefanzweifel/git-auto-commit-action@v5
|
||||||
|
with:
|
||||||
|
commit_message: 'Python formatting fixes from Black and Ruff'
|
3
.github/workflows/shellcheck.yml
vendored
3
.github/workflows/shellcheck.yml
vendored
|
@ -2,6 +2,7 @@ name: Run Shellcheck on push and PR
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
branches: [master]
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
@ -9,7 +10,7 @@ jobs:
|
||||||
name: Shellcheck
|
name: Shellcheck
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: Run ShellCheck
|
- name: Run ShellCheck
|
||||||
uses: ludeeus/action-shellcheck@master
|
uses: ludeeus/action-shellcheck@master
|
||||||
with:
|
with:
|
||||||
|
|
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -16,3 +16,8 @@ ssowat
|
||||||
# Folders
|
# Folders
|
||||||
apps
|
apps
|
||||||
backup
|
backup
|
||||||
|
|
||||||
|
|
||||||
|
__pycache__/
|
||||||
|
.mypy_cache/
|
||||||
|
.ruff_cache/
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import json
|
import json
|
||||||
import toml
|
import os
|
||||||
import yaml
|
import sys
|
||||||
import time
|
import time
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
CATALOG_LIST_PATH = "/etc/yunohost/apps_catalog.yml"
|
import toml
|
||||||
assert os.path.exists(
|
import yaml
|
||||||
CATALOG_LIST_PATH
|
|
||||||
), f"Catalog list yaml file '{CATALOG_LIST_PATH} does not exists"
|
CATALOG_LIST_PATH = Path("/etc/yunohost/apps_catalog.yml").resolve()
|
||||||
|
assert CATALOG_LIST_PATH.exists(), f"Catalog list yaml file '{CATALOG_LIST_PATH} does not exists"
|
||||||
|
|
||||||
now = time.time()
|
now = time.time()
|
||||||
my_env = os.environ.copy()
|
my_env = os.environ.copy()
|
||||||
|
@ -21,13 +22,14 @@ DEFAULT_APPS_FOLDER = "/ynh-dev/custom-catalog/"
|
||||||
DEFAULT_APP_BRANCH = "master"
|
DEFAULT_APP_BRANCH = "master"
|
||||||
|
|
||||||
|
|
||||||
def build(folder=DEFAULT_APPS_FOLDER):
|
def build(folder: Path | str = DEFAULT_APPS_FOLDER) -> None:
|
||||||
assert os.path.exists(folder), f"'{folder}' doesn't exists."
|
folder = Path(folder)
|
||||||
|
assert folder.exists(), f"'{folder}' doesn't exists."
|
||||||
|
|
||||||
app_list_path = os.path.join(folder, "apps.json")
|
app_list_path = folder / "apps.json"
|
||||||
assert os.path.exists(app_list_path), "no 'apps.json' app list found."
|
assert app_list_path.exists(), "no 'apps.json' app list found."
|
||||||
|
|
||||||
with open(app_list_path) as f:
|
with app_list_path.open() as f:
|
||||||
app_list = json.load(f)
|
app_list = json.load(f)
|
||||||
|
|
||||||
apps = {}
|
apps = {}
|
||||||
|
@ -44,37 +46,38 @@ def build(folder=DEFAULT_APPS_FOLDER):
|
||||||
|
|
||||||
apps[app_dict["id"]] = app_dict
|
apps[app_dict["id"]] = app_dict
|
||||||
|
|
||||||
# We also remove the app install question and resources parts which aint needed anymore by webadmin etc (or at least we think ;P)
|
# We also remove the app install question and resources parts which aint needed
|
||||||
|
# anymore by webadmin etc (or at least we think ;P)
|
||||||
for app in apps.values():
|
for app in apps.values():
|
||||||
if "manifest" in app and "install" in app["manifest"]:
|
if "manifest" in app and "install" in app["manifest"]:
|
||||||
del app["manifest"]["install"]
|
del app["manifest"]["install"]
|
||||||
if "manifest" in app and "resources" in app["manifest"]:
|
if "manifest" in app and "resources" in app["manifest"]:
|
||||||
del app["manifest"]["resources"]
|
del app["manifest"]["resources"]
|
||||||
|
|
||||||
output_file = os.path.join(folder, "catalog.json")
|
output_file = folder / "catalog.json"
|
||||||
data = {
|
data = {
|
||||||
"apps": apps,
|
"apps": apps,
|
||||||
"from_api_version": 3,
|
"from_api_version": 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
with open(output_file, "w") as f:
|
with output_file.open("w") as f:
|
||||||
f.write(json.dumps(data, sort_keys=True, indent=2))
|
f.write(json.dumps(data, sort_keys=True, indent=2))
|
||||||
|
|
||||||
if fail:
|
if fail:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
def build_app_dict(app, infos, folder):
|
def build_app_dict(app: str, infos: dict[str, Any], folder: Path) -> dict[str, Any]:
|
||||||
app_folder = os.path.join(folder, app + "_ynh")
|
app_folder = folder / f"{app}_ynh"
|
||||||
|
|
||||||
# Build the dict with all the infos
|
# Build the dict with all the infos
|
||||||
manifest_toml = os.path.join(app_folder, "manifest.toml")
|
manifest_toml = app_folder / "manifest.toml"
|
||||||
manifest_json = os.path.join(app_folder, "manifest.json")
|
manifest_json = app_folder / "manifest.json"
|
||||||
if os.path.exists(manifest_toml):
|
if manifest_toml.exists():
|
||||||
with open(manifest_toml) as f:
|
with manifest_toml.open() as f:
|
||||||
manifest = toml.load(f, _dict=OrderedDict)
|
manifest = toml.load(f, _dict=OrderedDict)
|
||||||
else:
|
else:
|
||||||
with open(manifest_json) as f:
|
with manifest_json.open() as f:
|
||||||
manifest = json.load(f, _dict=OrderedDict)
|
manifest = json.load(f, _dict=OrderedDict)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -94,32 +97,27 @@ def build_app_dict(app, infos, folder):
|
||||||
"category": infos.get("category", None),
|
"category": infos.get("category", None),
|
||||||
"subtags": infos.get("subtags", []),
|
"subtags": infos.get("subtags", []),
|
||||||
"potential_alternative_to": infos.get("potential_alternative_to", []),
|
"potential_alternative_to": infos.get("potential_alternative_to", []),
|
||||||
"antifeatures": list(
|
"antifeatures": list(set(list(manifest.get("antifeatures", {}).keys()) + infos.get("antifeatures", []))),
|
||||||
set(
|
|
||||||
list(manifest.get("antifeatures", {}).keys())
|
|
||||||
+ infos.get("antifeatures", [])
|
|
||||||
)
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def reset():
|
def reset() -> None:
|
||||||
with open(CATALOG_LIST_PATH, "w") as f:
|
with CATALOG_LIST_PATH.open("w") as f:
|
||||||
catalog_list = [{"id": "default", "url": "https://app.yunohost.org/default/"}]
|
catalog_list = [{"id": "default", "url": "https://app.yunohost.org/default/"}]
|
||||||
yaml.safe_dump(catalog_list, f, default_flow_style=False)
|
yaml.safe_dump(catalog_list, f, default_flow_style=False)
|
||||||
|
|
||||||
|
|
||||||
def add():
|
def add() -> None:
|
||||||
with open(CATALOG_LIST_PATH) as f:
|
with CATALOG_LIST_PATH.open("r") as f:
|
||||||
catalog_list = yaml.load(f, Loader=yaml.FullLoader)
|
catalog_list = yaml.load(f, Loader=yaml.FullLoader)
|
||||||
ids = [catalog["id"] for catalog in catalog_list]
|
ids = [catalog["id"] for catalog in catalog_list]
|
||||||
if "custom" not in ids:
|
if "custom" not in ids:
|
||||||
catalog_list.append({"id": "custom", "url": None})
|
catalog_list.append({"id": "custom", "url": None})
|
||||||
with open(CATALOG_LIST_PATH, "w") as f:
|
with CATALOG_LIST_PATH.open("w") as f:
|
||||||
yaml.safe_dump(catalog_list, f, default_flow_style=False)
|
yaml.safe_dump(catalog_list, f, default_flow_style=False)
|
||||||
|
|
||||||
|
|
||||||
def override():
|
def override() -> None:
|
||||||
with open(CATALOG_LIST_PATH, "w") as f:
|
with CATALOG_LIST_PATH.open("w") as f:
|
||||||
catalog_list = [{"id": "custom", "url": None}]
|
catalog_list = [{"id": "custom", "url": None}]
|
||||||
yaml.safe_dump(catalog_list, f, default_flow_style=False)
|
yaml.safe_dump(catalog_list, f, default_flow_style=False)
|
||||||
|
|
21
pyproject.toml
Normal file
21
pyproject.toml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
[tool.black]
|
||||||
|
line-length = 120
|
||||||
|
|
||||||
|
[tool.ruff]
|
||||||
|
line-length = 120
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
select = [
|
||||||
|
"F", # pyflakes
|
||||||
|
"E", # pycodestyle
|
||||||
|
"W", # pycodestyle
|
||||||
|
"I", # isort
|
||||||
|
"N", # pep8-naming
|
||||||
|
"B", # flake8-ubgbear
|
||||||
|
"ANN", # flake8-annotations
|
||||||
|
"Q", # flake8-quotes
|
||||||
|
"PTH", # flake8-use-pathlib
|
||||||
|
"UP", # pyupgrade,
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.mypy]
|
Loading…
Add table
Reference in a new issue