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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# SPDX-FileCopyrightText: 2026 Igalia S.L.
# SPDX-License-Identifier: MIT

[flake8]
max-line-length = 140
doctests = True
exclude = .git, .eggs, __pycache__, build/, dist/
ignore = F824, W504
30 changes: 30 additions & 0 deletions .github/workflows/python-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Python Linting

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
lint:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1

- name: Set up environment
run: |
sudo apt update
sudo apt install python3-pip
sudo pip3 install --break-system-packages flake8 mypy

- name: Flake8
run: |
python3 -m flake8 src

- name: MyPy
run: |
python3 -m mypy src
26 changes: 26 additions & 0 deletions .github/workflows/reuse-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: License Linting

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
lint:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1

- name: Set up environment
run: |
sudo apt update
sudo apt install python3-pip
sudo pip3 install --break-system-packages reuse

- name: REUSE
run: |
python3 -m reuse lint
18 changes: 9 additions & 9 deletions REUSE.toml
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
version = 1
SPDX-PackageName = "moonforge-cli"
SPDX-PackageSupplier = "The Moonforge Project"
SPDX-PackageSupplier = "Igalia S.L."
SPDX-PackageDownloadLocation = "https://github.com/moonforgelinux/moonforge-cli"

[[annotations]]
path = "README.md"
path = ".github/workflows/*.yml"
precedence = "aggregate"
SPDX-FileCopyrightText = "2026 Igalia S.L."
SPDX-License-Identifier = "CC0-1.0"
SPDX-FileCopyrightText = "2026 Igalia S.L."
SPDX-License-Identifier = "MIT"

[[annotations]]
path = "CHANGELOG.md"
path = ["CHANGELOG.md", "README.md"]
precedence = "aggregate"
SPDX-FileCopyrightText = "2026 Igalia S.L."
SPDX-FileCopyrightText = "2026 Igalia S.L."
SPDX-License-Identifier = "CC0-1.0"

[[annotations]]
path = "pyproject.toml"
precedence = "aggregate"
SPDX-FileCopyrightText = "2026 Igalia S.L."
SPDX-License-Identifier = "CC0-1.0"
SPDX-FileCopyrightText = "2026 Igalia S.L."
SPDX-License-Identifier = "MIT"

[[annotations]]
path = "src/moonforgecli/.gitignore"
precedence = "aggregate"
SPDX-FileCopyrightText = "2026 Igalia S.L."
SPDX-FileCopyrightText = "2026 Igalia S.L."
SPDX-License-Identifier = "CC0-1.0"
14 changes: 5 additions & 9 deletions src/moonforgecli/feature.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# SPDX-FileCopyrightText: 2026 Igalia S.L.
# SPDX-License-Identifier: MIT

import argparse
import os
import sys

from . import log, term
from .features import available_features, get_feature

Expand Down Expand Up @@ -41,11 +37,11 @@ def run(options) -> int:

features = []
for feat in options.features:
f = get_feature(feat)
if f is None:
log.error(f"Invalid feature {feat}.")
try:
f = get_feature(feat)
except IndexError as err:
log.error(f"{err}")
features.append(f)

for feature in features:
res = []
res.append(f"{term.heading('Feature:')} {term.bold(feature.name)}")
Expand All @@ -64,7 +60,7 @@ def run(options) -> int:
for include in feature.includes:
res.append(f" - {term.green(include.file)} from {term.green(include.repo)}")
res.append("")
if len(feature.conflicts) > 0:
if feature.conflicts is not None and len(feature.conflicts) > 0:
res.append(term.heading("Conflicts:"))
for conflict in feature.conflicts:
res.append(f" - {term.red(conflict)}")
Expand Down
28 changes: 18 additions & 10 deletions src/moonforgecli/features/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
@dataclass
class FeatureFragment:
"""Class for weighted template fragments."""

section: str
key: str
value: str
Expand Down Expand Up @@ -44,6 +45,7 @@ class FeatureRepo:
@dataclass
class Feature:
"""Class for feature templates."""

name: str
description: str
includes: list[FeatureInclude] = field(default_factory=list)
Expand All @@ -53,12 +55,13 @@ class Feature:
variables: list[FeatureVariable] | None = field(default_factory=list)


def available_features() -> list[Features]:
def available_features() -> list[Feature]:
from .docker import DOCKER_FEATURE
from .graphics_weston import GRAPHICS_WESTON_FEATURE
from .graphics_wpe import GRAPHICS_WPE_FEATURE
from .podman import PODMAN_FEATURE
from .rauc_simple import RAUC_FEATURE

return [
DOCKER_FEATURE,
GRAPHICS_WESTON_FEATURE,
Expand All @@ -68,30 +71,35 @@ def available_features() -> list[Features]:
]


def get_feature(name: str) -> Feature | None:
def get_feature(name: str) -> Feature:
for feature in available_features():
if feature.name == name:
return feature
return None
raise IndexError(f"Feature {name} not found")


def check_conflicts(name: str, features: list[str]) -> list[str] | None:
feature = get_feature(name)
def check_conflicts(name: str, features: list[str]) -> list[str]:
try:
feature = get_feature(name)
except IndexError:
return []

feature_conflicts = getattr(feature, "conflicts", [])
if len(feature_conflicts) == 0:
return None
return []

res = []
for feat in features:
check = get_feature(feat)
try:
check = get_feature(feat)
except IndexError:
continue

if check.name in feature_conflicts:
res.append(check.name)
else:
check_conflicts = getattr(check, "conflicts", [])
if feature.name in check_conflicts:
res.append(check.name)

if len(res) == 0:
return None

return res
16 changes: 9 additions & 7 deletions src/moonforgecli/features/docker.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
# SPDX-FileCopyrightText: 2026 Igalia S.L.
# SPDX-License-Identifier: MIT

from . import Feature, FeatureFragment, FeatureInclude
from . import Feature, FeatureInclude


DOCKER_FEATURE = Feature(name="docker",
description="Container support using Docker",
includes=[
FeatureInclude("meta-moonforge", "kas/include/layer/meta-moonforge-docker.yml")
],
conflicts=["podman"])
DOCKER_FEATURE = Feature(
name="docker",
description="Container support using Docker",
includes=[
FeatureInclude("meta-moonforge", "kas/include/layer/meta-moonforge-docker.yml")
],
conflicts=["podman"],
)
18 changes: 11 additions & 7 deletions src/moonforgecli/features/graphics_weston.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
# SPDX-FileCopyrightText: 2026 Igalia S.L.
# SPDX-License-Identifier: MIT

from . import Feature, FeatureFragment, FeatureInclude
from . import Feature, FeatureInclude


GRAPHICS_WESTON_FEATURE = Feature(name="graphics-weston",
description="Graphics support, using Weston",
includes=[
FeatureInclude("meta-moonforge", "kas/include/layer/meta-moonforge-graphics.yml")
],
conflicts=['graphics-wpe'])
GRAPHICS_WESTON_FEATURE = Feature(
name="graphics-weston",
description="Graphics support, using Weston",
includes=[
FeatureInclude(
"meta-moonforge", "kas/include/layer/meta-moonforge-graphics.yml"
)
],
conflicts=["graphics-wpe"],
)
44 changes: 26 additions & 18 deletions src/moonforgecli/features/graphics_wpe.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,29 @@
from . import Feature, FeatureFragment, FeatureInclude, FeatureVariable


GRAPHICS_WPE_FEATURE = Feature(name="graphics-wpe",
description="Web Platform for Embedded",
includes=[
FeatureInclude("meta-moonforge", "kas/include/layer/meta-moonforge-graphics.yml"),
FeatureInclude("meta-moonforge", "kas/include/layer/meta-moonforge-wpe.yml"),
],
local_conf=[
FeatureFragment(section="meta-moonforge-wpe",
weight=30,
key="WAYLAND_COG_LAUNCH_URL",
value="http://10.0.2.2:8080"),
],
conflicts=['graphics-weston'],
variables=[
FeatureVariable(name="WAYLAND_COG_LAUNCH_URL",
description="The URL to display at boot",
default="http://10.0.2.2:8080"),
])
GRAPHICS_WPE_FEATURE = Feature(
name="graphics-wpe",
description="Web Platform for Embedded",
includes=[
FeatureInclude(
"meta-moonforge", "kas/include/layer/meta-moonforge-graphics.yml"
),
FeatureInclude("meta-moonforge", "kas/include/layer/meta-moonforge-wpe.yml"),
],
local_conf=[
FeatureFragment(
section="meta-moonforge-wpe",
weight=30,
key="WAYLAND_COG_LAUNCH_URL",
value="http://10.0.2.2:8080",
),
],
conflicts=["graphics-weston"],
variables=[
FeatureVariable(
name="WAYLAND_COG_LAUNCH_URL",
description="The URL to display at boot",
default="http://10.0.2.2:8080",
),
],
)
16 changes: 9 additions & 7 deletions src/moonforgecli/features/podman.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
# SPDX-FileCopyrightText: 2026 Igalia S.L.
# SPDX-License-Identifier: MIT

from . import Feature, FeatureFragment, FeatureInclude
from . import Feature, FeatureInclude


PODMAN_FEATURE = Feature(name="podman",
description="Container support using Podman",
includes=[
FeatureInclude("meta-moonforge", "kas/include/layer/meta-moonforge-podman.yml")
],
conflicts=["docker"])
PODMAN_FEATURE = Feature(
name="podman",
description="Container support using Podman",
includes=[
FeatureInclude("meta-moonforge", "kas/include/layer/meta-moonforge-podman.yml")
],
conflicts=["docker"],
)
Loading