From 4e90538bac15f415d96b1b0a1b4f07f20f02242c Mon Sep 17 00:00:00 2001 From: Eike Waldt Date: Mon, 2 Feb 2026 09:27:31 +0100 Subject: [PATCH 1/3] docs: add CLI section to sphinx and add some style Signed-off-by: Eike Waldt On-behalf-of: SAP --- docs/_static/custom.css | 318 ++++++++++++++++++++++++++++++ docs/_static/gardenlinux-logo.svg | 1 + docs/api.rst | 22 +++ docs/cli.rst | 63 ++++++ docs/conf.py | 29 ++- docs/index.rst | 85 +++++--- docs/release.rst | 4 +- poetry.lock | 38 +++- pyproject.toml | 2 + 9 files changed, 529 insertions(+), 33 deletions(-) create mode 100644 docs/_static/custom.css create mode 100644 docs/_static/gardenlinux-logo.svg create mode 100644 docs/api.rst create mode 100644 docs/cli.rst diff --git a/docs/_static/custom.css b/docs/_static/custom.css new file mode 100644 index 00000000..91fdf275 --- /dev/null +++ b/docs/_static/custom.css @@ -0,0 +1,318 @@ +/* Garden Linux Design System - Sphinx Theme Customization */ + +:root { + /* Primary Green */ + --gardenlinux-primary-base: #027154; + --gardenlinux-primary-dark: #015a43; + --gardenlinux-primary-darker: #014332; + --gardenlinux-primary-darkest: #012c21; + --gardenlinux-primary-light: #038865; + --gardenlinux-primary-lighter: #04a076; + --gardenlinux-primary-lightest: #05b887; + + /* Secondary Green */ + --gardenlinux-secondary-base: #009f76; + --gardenlinux-secondary-dark: #008060; + --gardenlinux-secondary-darker: #006149; + --gardenlinux-secondary-darkest: #004232; + --gardenlinux-secondary-light: #00be8c; + --gardenlinux-secondary-lighter: #00dd9f; + --gardenlinux-secondary-lightest: #00fcb2; + + /* Accent Yellow/Gold */ + --gardenlinux-accent-base: #dfbe00; + --gardenlinux-accent-dark: #b29900; + --gardenlinux-accent-darker: #857400; + --gardenlinux-accent-darkest: #584f00; + --gardenlinux-accent-light: #ffd500; + --gardenlinux-accent-lighter: #ffec33; + --gardenlinux-accent-lightest: #fff366; + + /* Semantic Colors */ + --gardenlinux-success: #009f76; + --gardenlinux-success-light: #00be8c; + --gardenlinux-success-dark: #008060; + --gardenlinux-warning: #dfbe00; + --gardenlinux-warning-light: #ffd500; + --gardenlinux-warning-dark: #b29900; + --gardenlinux-error: #d32f2f; + --gardenlinux-error-light: #ef5350; + --gardenlinux-error-dark: #c62828; + --gardenlinux-info: #027154; + --gardenlinux-info-light: #038865; + --gardenlinux-info-dark: #015a43; +} + +/* Override Read the Docs theme colors with Garden Linux colors */ +.wy-side-nav-search { + background-color: var(--gardenlinux-primary-base); +} + +.wy-side-nav-search > a { + color: #ffffff !important; +} + +.wy-side-nav-search > div.version { + color: rgba(255, 255, 255, 0.9) !important; +} + +/* Ensure all text in the search header is white */ +.wy-side-nav-search * { + color: #ffffff !important; +} + +.wy-side-nav-search input[type="text"] { + background-color: rgba(255, 255, 255, 0.2); + border-color: rgba(255, 255, 255, 0.3); + color: #ffffff; +} + +.wy-side-nav-search input[type="text"]::placeholder { + color: rgba(255, 255, 255, 0.7); +} + +/* Menu colors - improved readability - white background */ +.wy-side-scroll { + background-color: #ffffff; +} + +.wy-menu-vertical { + background-color: #ffffff; +} + +.wy-menu-vertical a { + color: #1a1a1a !important; + font-weight: 500; +} + +/* Make unselected/collapsed menu items more readable */ +.wy-menu-vertical li:not(.current) > a { + color: #1a1a1a !important; +} + +.wy-menu-vertical li.toctree-l1:not(.current) > a { + color: #1a1a1a !important; + font-weight: 500; +} + +.wy-menu-vertical a:hover { + background-color: var(--gardenlinux-primary-lightest); + color: var(--gardenlinux-primary-darkest) !important; +} + +.wy-menu-vertical li.current { + background-color: var(--gardenlinux-primary-lightest); +} + +.wy-menu-vertical li.current > a { + color: var(--gardenlinux-primary-darkest) !important; + border-right: 3px solid var(--gardenlinux-primary-base); + font-weight: 600; + background-color: var(--gardenlinux-primary-lightest); +} + +.wy-menu-vertical li.toctree-l1.current > a { + border-bottom: 1px solid var(--gardenlinux-primary-light); +} + +/* Improve nested menu items readability */ +.wy-menu-vertical li.toctree-l2 a, +.wy-menu-vertical li.toctree-l3 a, +.wy-menu-vertical li.toctree-l4 a { + color: #1a1a1a !important; +} + +/* Make unselected nested items more readable */ +.wy-menu-vertical li.toctree-l2:not(.current) > a, +.wy-menu-vertical li.toctree-l3:not(.current) > a, +.wy-menu-vertical li.toctree-l4:not(.current) > a { + color: #1a1a1a !important; + font-weight: 400; +} + +.wy-menu-vertical li.toctree-l2.current > a, +.wy-menu-vertical li.toctree-l3.current > a, +.wy-menu-vertical li.toctree-l4.current > a { + background-color: var(--gardenlinux-primary-lightest) !important; + color: var(--gardenlinux-primary-darkest) !important; + font-weight: 600; +} + +.wy-menu-vertical header, +.wy-menu-vertical p.caption { + color: #1a1a1a; + font-weight: 600; + background-color: #ffffff; +} + +/* Ensure all sidebar elements have white background */ +.wy-nav-side { + background-color: #ffffff !important; +} + +.wy-nav-side .wy-menu-vertical { + background-color: #ffffff !important; +} + +.wy-side-nav-search input[type="text"] { + background-color: rgba(255, 255, 255, 0.2); + border-color: rgba(255, 255, 255, 0.3); + color: #ffffff; +} + +/* Override any black/dark backgrounds in sidebar */ +.wy-menu-vertical ul { + background-color: #ffffff !important; +} + +.wy-menu-vertical li { + background-color: transparent; +} + +/* Fix selected sub-sections - use light background with dark text */ +.wy-menu-vertical li.current a, +.wy-menu-vertical li.current a:visited { + color: var(--gardenlinux-primary-darkest) !important; + background-color: var(--gardenlinux-primary-lightest) !important; +} + +.wy-menu-vertical li.current a:hover { + color: var(--gardenlinux-primary-darkest) !important; + background-color: var(--gardenlinux-primary-lighter) !important; +} + +/* Fix expand/collapse icon squares - make them dark and readable */ +.wy-menu-vertical .toctree-expand, +.wy-menu-vertical span.toctree-expand, +.wy-menu-vertical a .toctree-expand { + color: #1a1a1a !important; + border-color: #1a1a1a !important; + opacity: 1 !important; + font-weight: bold; +} + +.wy-menu-vertical .toctree-expand:before, +.wy-menu-vertical span.toctree-expand:before, +.wy-menu-vertical a .toctree-expand:before { + color: #1a1a1a !important; + border-color: #1a1a1a !important; +} + +/* Fix icon boxes for expandable items at all levels */ +.wy-menu-vertical li.toctree-l1 > a .toctree-expand, +.wy-menu-vertical li.toctree-l2 > a .toctree-expand, +.wy-menu-vertical li.toctree-l3 > a .toctree-expand, +.wy-menu-vertical li.toctree-l4 > a .toctree-expand { + color: #1a1a1a !important; + border-color: #1a1a1a !important; + background-color: transparent !important; +} + +/* Target the icon element directly */ +.wy-menu-vertical li .toctree-expand { + color: #1a1a1a !important; + border: 1px solid #1a1a1a !important; +} + +/* Make sure plus/minus signs are dark */ +.wy-menu-vertical .toctree-expand:after { + color: #1a1a1a !important; +} + +/* Links */ +a { + color: var(--gardenlinux-primary-base); +} + +a:hover { + color: var(--gardenlinux-secondary-base); +} + +a:visited { + color: var(--gardenlinux-primary-dark); +} + +/* Code blocks */ +.highlight { + background-color: #f5f5f5; +} + +.highlight .hll { + background-color: var(--gardenlinux-primary-lightest); +} + +/* Buttons and important elements */ +.btn-primary, +.rst-content .btn-primary { + background-color: var(--gardenlinux-primary-base); + border-color: var(--gardenlinux-primary-base); + color: #ffffff; +} + +.btn-primary:hover, +.rst-content .btn-primary:hover { + background-color: var(--gardenlinux-primary-dark); + border-color: var(--gardenlinux-primary-dark); +} + +/* Admonitions */ +.rst-content .admonition { + border-left: 4px solid; +} + +.rst-content .admonition.note { + border-left-color: var(--gardenlinux-info); + background-color: var(--gardenlinux-info-lightest); +} + +.rst-content .admonition.warning { + border-left-color: var(--gardenlinux-warning); + background-color: var(--gardenlinux-accent-lightest); +} + +.rst-content .admonition.danger, +.rst-content .admonition.error { + border-left-color: var(--gardenlinux-error); + background-color: var(--gardenlinux-error-light); +} + +.rst-content .admonition.success, +.rst-content .admonition.tip { + border-left-color: var(--gardenlinux-success); + background-color: var(--gardenlinux-secondary-lightest); +} + +/* Headers */ +h1, +h2, +h3, +h4, +h5, +h6 { + color: var(--gardenlinux-primary-base); +} + +/* Table of contents */ +.rst-content .toctree-wrapper > p.caption { + color: var(--gardenlinux-primary-base); + font-weight: bold; +} + +/* Logo styling */ +.logo { + max-width: 250px; + height: auto; + margin: 10px 0; +} + +/* Footer */ +footer { + border-top: 1px solid var(--gardenlinux-primary-light); +} + +/* Responsive adjustments */ +@media screen and (max-width: 768px) { + .wy-side-nav-search { + padding: 0.809em; + } +} diff --git a/docs/_static/gardenlinux-logo.svg b/docs/_static/gardenlinux-logo.svg new file mode 100644 index 00000000..b9823cce --- /dev/null +++ b/docs/_static/gardenlinux-logo.svg @@ -0,0 +1 @@ +Garden Linux_logo \ No newline at end of file diff --git a/docs/api.rst b/docs/api.rst new file mode 100644 index 00000000..ad00ac2d --- /dev/null +++ b/docs/api.rst @@ -0,0 +1,22 @@ +API Reference +============ + +This section provides detailed documentation for all Python modules and classes in python-gardenlinux-lib. + +.. automodule:: gardenlinux + :members: + +.. automodule:: gardenlinux.apt + :members: + +.. automodule:: gardenlinux.features + :members: + +.. automodule:: gardenlinux.flavors + :members: + +.. automodule:: gardenlinux.git + :members: + +.. automodule:: gardenlinux.oci + :members: diff --git a/docs/cli.rst b/docs/cli.rst new file mode 100644 index 00000000..1f94a475 --- /dev/null +++ b/docs/cli.rst @@ -0,0 +1,63 @@ +Command-Line Interface +====================== + +This page documents all available command-line tools provided by python-gardenlinux-lib. + +Features Commands +----------------- + +gl-cname +~~~~~~~~ + +Generate a canonical name (cname) from feature sets. + +.. autoprogram:: gardenlinux.features.cname_main:parser + +gl-features-parse +~~~~~~~~~~~~~~~~~ + +Parse and extract information from GardenLinux features. + +.. autoprogram:: gardenlinux.features.__main__:parser + +Flavors Commands +---------------- + +gl-flavors-parse +~~~~~~~~~~~~~~~~ + +Parse flavors.yaml and generate combinations. + +.. autoprogram:: gardenlinux.flavors.__main__:parser + +OCI Commands +------------ + +gl-oci +~~~~~~ + +Push OCI artifacts to a registry and manage manifests. + +.. click:: gardenlinux.oci.__main__:cli + :prog: gl-oci + :show-nested: + +S3 Commands +----------- + +gl-s3 +~~~~~ + +Upload and download artifacts from S3 buckets. + +.. autoprogram:: gardenlinux.s3.__main__:parser + +GitHub Commands +--------------- + +gl-gh-release +~~~~~~~~~~~~~~ + +Create and manage GitHub releases. + +.. autoprogram:: gardenlinux.github.release.__main__:parser diff --git a/docs/conf.py b/docs/conf.py index 0464e350..130c038c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -12,9 +12,9 @@ # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information -project = "python-gardenlinux-lib" -copyright = "2024, gardenlinux maintainer" -author = "gardenlinux maintainer" +project = "Garden Linux Python Library" +copyright = "2024, Garden Linux Maintainers" +author = "Garden Linux Maintainers" # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration @@ -24,6 +24,8 @@ "sphinx.ext.coverage", "sphinx_rtd_theme", "sphinx.ext.napoleon", + "sphinx_click", + "sphinxcontrib.autoprogram", ] templates_path = ["_templates"] @@ -36,3 +38,24 @@ html_theme = "sphinx_rtd_theme" html_static_path = ["_static"] + +# Logo configuration +html_logo = "_static/gardenlinux-logo.svg" +html_theme_options = { + "logo_only": False, + "display_version": True, + "prev_next_buttons_location": "bottom", + "style_external_links": True, + "vcs_pageview_mode": "", + "style_nav_header_background": "#027154", # Primary green + "collapse_navigation": True, + "sticky_navigation": True, + "navigation_depth": 4, + "includehidden": True, + "titles_only": False, +} + + +# Add custom CSS +def setup(app): + app.add_css_file("custom.css") diff --git a/docs/index.rst b/docs/index.rst index c6fa838c..9de35821 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,28 +1,63 @@ -.. parse_features_lib documentation master file, created by - sphinx-quickstart on Thu Aug 15 22:42:36 2024. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -python-gardenlinux-lib documentation -==================================== -.. automodule:: gardenlinux - :members: -.. automodule:: gardenlinux.apt - :members: -.. automodule:: gardenlinux.features - :members: -.. automodule:: gardenlinux.flavors - :members: -.. automodule:: gardenlinux.git - :members: -.. automodule:: gardenlinux.oci - :members: +Garden Linux Python Library Documentation +========================================== + +Welcome to the Garden Linux Python Library documentation. This library provides +Python tools and utilities for working with Garden Linux features, flavors, +OCI artifacts, S3 buckets, and GitHub releases. + +.. image:: _static/gardenlinux-logo.svg + :alt: Garden Linux Logo + :class: logo + :align: center + +Overview +-------- + +The Garden Linux Python Library is a comprehensive toolkit for managing and +interacting with Garden Linux components. It includes: + +* **Feature Management**: Parse and work with Garden Linux features and generate canonical names +* **Flavor Processing**: Parse flavors.yaml and generate combinations +* **OCI Operations**: Push OCI artifacts to registries and manage manifests +* **S3 Integration**: Upload and download artifacts from S3 buckets +* **GitHub Integration**: Create and manage GitHub releases with release notes + +Quick Start +----------- + +Command-Line Interface +~~~~~~~~~~~~~~~~~~~~~~ + +The library provides several command-line tools for common operations. See the +:doc:`Command-Line Interface documentation ` for detailed information about +all available commands. + +Release Management +~~~~~~~~~~~~~~~~~~ + +For information about versioning and release procedures, see the +:doc:`Release documentation `. + +API Reference +~~~~~~~~~~~~~ + +For detailed Python API documentation, including all modules, classes, and +functions, see the :doc:`API Reference `. + +Documentation Sections +---------------------- + .. toctree:: :maxdepth: 3 - :caption: Contents: + :caption: Documentation: + + cli + release + api + +Additional Resources +-------------------- -Indices and tables -================== -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` +* :ref:`genindex` - Complete index of all functions, classes, and modules +* :ref:`modindex` - Index of all modules +* :ref:`search` - Search the documentation diff --git a/docs/release.rst b/docs/release.rst index da6a50a0..0b98175f 100644 --- a/docs/release.rst +++ b/docs/release.rst @@ -1,5 +1,5 @@ -python-gardenlinux-lib release documentation -============================================ +release documentation +===================== *python-gardenlinux-lib* strictly follow syntax and intention of `Semantic Versioning `. Each release reflects the intention and expected impact therefore. diff --git a/poetry.lock b/poetry.lock index f82f3135..18bb2b95 100644 --- a/poetry.lock +++ b/poetry.lock @@ -821,7 +821,7 @@ version = "8.3.1" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.10" -groups = ["main"] +groups = ["main", "docs"] files = [ {file = "click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6"}, {file = "click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a"}, @@ -841,7 +841,7 @@ files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] -markers = {main = "platform_system == \"Windows\"", dev = "platform_system == \"Windows\" or sys_platform == \"win32\"", docs = "sys_platform == \"win32\""} +markers = {main = "platform_system == \"Windows\"", dev = "platform_system == \"Windows\" or sys_platform == \"win32\"", docs = "platform_system == \"Windows\" or sys_platform == \"win32\""} [[package]] name = "coverage" @@ -2287,6 +2287,23 @@ sphinxcontrib-jsmath = ">=1.0.1" sphinxcontrib-qthelp = ">=1.0.6" sphinxcontrib-serializinghtml = ">=1.1.9" +[[package]] +name = "sphinx-click" +version = "4.4.0" +description = "Sphinx extension that automatically documents click applications" +optional = false +python-versions = ">=3.7" +groups = ["docs"] +files = [ + {file = "sphinx-click-4.4.0.tar.gz", hash = "sha256:cc67692bd28f482c7f01531c61b64e9d2f069bfcf3d24cbbb51d4a84a749fa48"}, + {file = "sphinx_click-4.4.0-py3-none-any.whl", hash = "sha256:2821c10a68fc9ee6ce7c92fad26540d8d8c8f45e6d7258f0e4fb7529ae8fab49"}, +] + +[package.dependencies] +click = ">=7.0" +docutils = "*" +sphinx = ">=2.0" + [[package]] name = "sphinx-rtd-theme" version = "3.1.0" @@ -2324,6 +2341,21 @@ lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] standalone = ["Sphinx (>=5)"] test = ["pytest"] +[[package]] +name = "sphinxcontrib-autoprogram" +version = "0.1.9" +description = "Documenting CLI programs" +optional = false +python-versions = ">=3.8" +groups = ["docs"] +files = [ + {file = "sphinxcontrib-autoprogram-0.1.9.tar.gz", hash = "sha256:219655507fadca29b3062b5d86c37d94db48f03bde4b58d61526872bf72f57cc"}, + {file = "sphinxcontrib_autoprogram-0.1.9-py2.py3-none-any.whl", hash = "sha256:79a5282d7640337e4bf11f624970a43709f1b704c5c59a59756d45e824db5301"}, +] + +[package.dependencies] +Sphinx = ">=1.2" + [[package]] name = "sphinxcontrib-devhelp" version = "2.0.0" @@ -2584,4 +2616,4 @@ test = ["pytest", "pytest-cov"] [metadata] lock-version = "2.1" python-versions = ">=3.13,!=3.14.1" -content-hash = "0e92dd06c0f4f5a06988e7218eaed5d650d9a5a24bb2c8e2c6b5cda303f53f07" +content-hash = "d3d6d40261960ebf3ab3a7a3a939c9f61381a502ec3a33ffc680eef810db2116" diff --git a/pyproject.toml b/pyproject.toml index 18db1b22..bb939d71 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,6 +39,8 @@ boto3-stubs = { extras = ["s3"], version = "^1.42.30" } [tool.poetry.group.docs.dependencies] sphinx-rtd-theme = "^3.0.2" +sphinx-click = "^4.4.0" +sphinxcontrib-autoprogram = "^0.1.8" [tool.poetry.scripts] gl-cname = "gardenlinux.features.cname_main:main" From ed0a9a1bbb1f13a476b5401a3da68c6ed14947d3 Mon Sep 17 00:00:00 2001 From: Eike Waldt Date: Mon, 2 Feb 2026 09:28:23 +0100 Subject: [PATCH 2/3] docs: add missing help test to CLIs and make them work with sphinx Signed-off-by: Eike Waldt On-behalf-of: SAP --- src/gardenlinux/features/__main__.py | 88 ++++++++++-- src/gardenlinux/features/cname_main.py | 52 +++++-- src/gardenlinux/flavors/__main__.py | 27 +++- src/gardenlinux/github/release/__main__.py | 150 +++++++++++++++++---- src/gardenlinux/s3/__main__.py | 57 ++++++-- 5 files changed, 309 insertions(+), 65 deletions(-) diff --git a/src/gardenlinux/features/__main__.py b/src/gardenlinux/features/__main__.py index 76224da2..d1a9bf51 100644 --- a/src/gardenlinux/features/__main__.py +++ b/src/gardenlinux/features/__main__.py @@ -39,33 +39,93 @@ """ -def main() -> None: +def get_parser() -> argparse.ArgumentParser: """ - gl-features-parse main() + Get the argument parser for gl-features-parse. + Used for documentation generation. - :since: 0.7.0 + :return: ArgumentParser instance + :since: 0.10.9 """ + parser = argparse.ArgumentParser( + description="Parse and extract information from GardenLinux features." + ) - parser = argparse.ArgumentParser() - - parser.add_argument("--arch", dest="arch") - parser.add_argument("--cname", dest="cname", required=True) - parser.add_argument("--commit", dest="commit") - parser.add_argument("--feature-dir", default="features") - parser.add_argument("--release-file", dest="release_file") - parser.add_argument("--default-arch", dest="default_arch") - parser.add_argument("--default-version", dest="default_version") - parser.add_argument("--version", dest="version") + parser.add_argument( + "--arch", + dest="arch", + help="Target architecture (e.g., amd64, arm64). Overrides architecture from cname.", + ) + parser.add_argument( + "--cname", + dest="cname", + required=True, + help="Canonical name (cname) to parse. Must be a valid GardenLinux canonical name.", + ) + parser.add_argument( + "--commit", + dest="commit", + help="Git commit hash. If not specified, will be read from COMMIT file or release file.", + ) + parser.add_argument( + "--feature-dir", + default="features", + help="Path to the features directory (default: 'features'). Either --feature-dir or --release-file must be provided.", + ) + parser.add_argument( + "--release-file", + dest="release_file", + help="Path to a release file containing cname metadata. Either --feature-dir or --release-file must be provided.", + ) + parser.add_argument( + "--default-arch", + dest="default_arch", + help="Default architecture to use if architecture cannot be determined from cname or other sources.", + ) + parser.add_argument( + "--default-version", + dest="default_version", + help="Default version to use if version cannot be determined from files or other sources.", + ) + parser.add_argument( + "--version", + dest="version", + help="Version string. If not specified, will be read from VERSION file or release file.", + ) parser.add_argument( "--ignore", dest="ignore", type=lambda arg: set([f for f in arg.split(",") if f]), default=set(), + help="Comma-separated list of features to ignore when processing (e.g., 'feature1,feature2').", ) - parser.add_argument("type", nargs="?", choices=_ARGS_TYPE_ALLOWED, default="cname") + parser.add_argument( + "type", + nargs="?", + choices=_ARGS_TYPE_ALLOWED, + default="cname", + help="Type of output to generate. Choices: {}. Default: 'cname'.".format( + ", ".join(_ARGS_TYPE_ALLOWED) + ), + ) + return parser + + +# Parser object for documentation generation +parser = get_parser() +parser.prog = "gl-features-parse" + + +def main() -> None: + """ + gl-features-parse main() + + :since: 0.7.0 + """ + parser = get_parser() args = parser.parse_args() assert bool(args.feature_dir) or bool(args.release_file), ( diff --git a/src/gardenlinux/features/cname_main.py b/src/gardenlinux/features/cname_main.py index 517d1cd0..d04c2e2c 100644 --- a/src/gardenlinux/features/cname_main.py +++ b/src/gardenlinux/features/cname_main.py @@ -18,6 +18,49 @@ from .parser import Parser +def get_parser() -> argparse.ArgumentParser: + """ + Get the argument parser for gl-cname. + Used for documentation generation. + + :return: ArgumentParser instance + :since: 1.0.0 + """ + parser = argparse.ArgumentParser( + description="Generate a canonical name (cname) from feature sets." + ) + parser.add_argument( + "--arch", + dest="arch", + help="Target architecture (e.g., amd64, arm64). If not specified, will be determined from the cname or feature set.", + ) + parser.add_argument( + "--commit", + dest="commit", + help="Git commit hash. If not specified, will be read from COMMIT file in the GardenLinux root directory.", + ) + parser.add_argument( + "--feature-dir", + default="features", + help="Path to the features directory (default: 'features').", + ) + parser.add_argument( + "--version", + dest="version", + help="Version string. If not specified, will be read from VERSION file in the GardenLinux root directory.", + ) + parser.add_argument( + "cname", + help="Canonical name (cname) to process. Must be a valid GardenLinux canonical name format.", + ) + return parser + + +# Parser object for documentation generation +parser = get_parser() +parser.prog = "gl-cname" + + def main() -> None: """ gl-cname main() @@ -25,14 +68,7 @@ def main() -> None: :since: 0.7.0 """ - parser = argparse.ArgumentParser() - - parser.add_argument("--arch", dest="arch") - parser.add_argument("--commit", dest="commit") - parser.add_argument("--feature-dir", default="features") - parser.add_argument("--version", dest="version") - parser.add_argument("cname") - + parser = get_parser() args = parser.parse_args() re_match = re.match( diff --git a/src/gardenlinux/flavors/__main__.py b/src/gardenlinux/flavors/__main__.py index ea2974d3..1cf2ba51 100644 --- a/src/gardenlinux/flavors/__main__.py +++ b/src/gardenlinux/flavors/__main__.py @@ -47,14 +47,14 @@ def generate_markdown_table(combinations: List[Tuple[Any, str]]) -> str: return table -def parse_args() -> Namespace: +def get_parser() -> ArgumentParser: """ - Parses arguments used for main() + Get the argument parser for gl-flavors-parse. + Used for documentation generation. - :return: (object) Parsed argparse.ArgumentParser namespace - :since: 0.7.0 + :return: ArgumentParser instance + :since: 1.0.0 """ - parser = ArgumentParser(description="Parse flavors.yaml and generate combinations.") parser.add_argument( @@ -122,7 +122,22 @@ def parse_args() -> Namespace: help="Generate a markdown table by platform.", ) - return parser.parse_args() + return parser + + +# Parser object for documentation generation +parser = get_parser() +parser.prog = "gl-flavors-parse" + + +def parse_args() -> Namespace: + """ + Parses arguments used for main() + + :return: (object) Parsed argparse.ArgumentParser namespace + :since: 0.7.0 + """ + return get_parser().parse_args() def main() -> None: diff --git a/src/gardenlinux/github/release/__main__.py b/src/gardenlinux/github/release/__main__.py index e403893f..1915dba4 100644 --- a/src/gardenlinux/github/release/__main__.py +++ b/src/gardenlinux/github/release/__main__.py @@ -14,35 +14,129 @@ LOGGER = LoggerSetup.get_logger("gardenlinux.github", logging.INFO) -def main() -> None: - parser = argparse.ArgumentParser(description="GitHub Release Script") - subparsers = parser.add_subparsers(dest="command") - - create_parser = subparsers.add_parser("create") - create_parser.add_argument("--owner", default="gardenlinux") - create_parser.add_argument("--repo", default="gardenlinux") - create_parser.add_argument("--tag", required=True) - create_parser.add_argument("--name") - create_parser.add_argument("--body", required=True) - create_parser.add_argument("--commit") - create_parser.add_argument("--pre-release", action="store_true", default=True) - create_parser.add_argument("--latest", action="store_true", default=False) - - create_parser_gl = subparsers.add_parser("create-with-gl-release-notes") - create_parser_gl.add_argument("--owner", default="gardenlinux") - create_parser_gl.add_argument("--repo", default="gardenlinux") - create_parser_gl.add_argument("--tag", required=True) - create_parser_gl.add_argument("--commit", required=True) - create_parser_gl.add_argument("--latest", action="store_true", default=False) - create_parser_gl.add_argument("--dry-run", action="store_true", default=False) - - upload_parser = subparsers.add_parser("upload") - upload_parser.add_argument("--owner", default="gardenlinux") - upload_parser.add_argument("--repo", default="gardenlinux") - upload_parser.add_argument("--release_id", required=True) - upload_parser.add_argument("--file_path", required=True) - upload_parser.add_argument("--dry-run", action="store_true", default=False) +def get_parser() -> argparse.ArgumentParser: + """ + Get the argument parser for gl-gh-release. + Used for documentation generation. + + :return: ArgumentParser instance + :since: 1.0.0 + """ + parser = argparse.ArgumentParser(description="Create and manage GitHub releases.") + subparsers = parser.add_subparsers(dest="command", help="Available commands") + + create_parser = subparsers.add_parser("create", help="Create a new GitHub release.") + create_parser.add_argument( + "--owner", + default="gardenlinux", + help="GitHub repository owner (default: 'gardenlinux').", + ) + create_parser.add_argument( + "--repo", + default="gardenlinux", + help="GitHub repository name (default: 'gardenlinux').", + ) + create_parser.add_argument( + "--tag", required=True, help="Git tag name for the release (required)." + ) + create_parser.add_argument( + "--name", help="Release name/title. If not specified, the tag will be used." + ) + create_parser.add_argument( + "--body", required=True, help="Release notes/description body (required)." + ) + create_parser.add_argument( + "--commit", + help="Git commit hash. If not specified, the tag will be used to find the commit.", + ) + create_parser.add_argument( + "--pre-release", + action="store_true", + default=True, + help="Mark the release as a pre-release (default: True).", + ) + create_parser.add_argument( + "--latest", + action="store_true", + default=False, + help="Mark this release as the latest release (default: False).", + ) + + create_parser_gl = subparsers.add_parser( + "create-with-gl-release-notes", + help="Create a GitHub release with auto-generated GardenLinux release notes.", + ) + create_parser_gl.add_argument( + "--owner", + default="gardenlinux", + help="GitHub repository owner (default: 'gardenlinux').", + ) + create_parser_gl.add_argument( + "--repo", + default="gardenlinux", + help="GitHub repository name (default: 'gardenlinux').", + ) + create_parser_gl.add_argument( + "--tag", required=True, help="Git tag name for the release (required)." + ) + create_parser_gl.add_argument( + "--commit", + required=True, + help="Git commit hash used to generate release notes (required).", + ) + create_parser_gl.add_argument( + "--latest", + action="store_true", + default=False, + help="Mark this release as the latest release (default: False).", + ) + create_parser_gl.add_argument( + "--dry-run", + action="store_true", + default=False, + help="Perform a dry run without actually creating the release.", + ) + + upload_parser = subparsers.add_parser( + "upload", help="Upload a file to an existing GitHub release." + ) + upload_parser.add_argument( + "--owner", + default="gardenlinux", + help="GitHub repository owner (default: 'gardenlinux').", + ) + upload_parser.add_argument( + "--repo", + default="gardenlinux", + help="GitHub repository name (default: 'gardenlinux').", + ) + upload_parser.add_argument( + "--release_id", + required=True, + help="GitHub release ID to upload the file to (required).", + ) + upload_parser.add_argument( + "--file_path", + required=True, + help="Path to the file to upload (required).", + ) + upload_parser.add_argument( + "--dry-run", + action="store_true", + default=False, + help="Perform a dry run without actually uploading the file.", + ) + return parser + + +# Parser object for documentation generation +parser = get_parser() +parser.prog = "gl-gh-release" + + +def main() -> None: + parser = get_parser() args = parser.parse_args() if args.command == "create": diff --git a/src/gardenlinux/s3/__main__.py b/src/gardenlinux/s3/__main__.py index 1c2da70d..f87fbfee 100644 --- a/src/gardenlinux/s3/__main__.py +++ b/src/gardenlinux/s3/__main__.py @@ -10,26 +10,65 @@ from .s3_artifacts import S3Artifacts -def main() -> None: +def get_parser() -> argparse.ArgumentParser: """ - gl-s3 main() + Get the argument parser for gl-s3. + Used for documentation generation. - :since: 0.8.0 + :return: ArgumentParser instance + :since: 0.10.9 """ parser = argparse.ArgumentParser() - parser.add_argument("--bucket", dest="bucket") - parser.add_argument("--path", required=False, dest="path") - parser.add_argument("--dry-run", action="store_true") + parser.add_argument( + "--bucket", dest="bucket", help="S3 bucket name to upload to or download from." + ) + + parser.add_argument( + "--path", + required=False, + dest="path", + help="Local directory path for upload (source) or download (destination).", + ) + + parser.add_argument( + "--dry-run", + action="store_true", + help="Perform a dry run without actually uploading or downloading files.", + ) - subparsers = parser.add_subparsers(dest="action") + subparsers = parser.add_subparsers(dest="action", help="Action to perform.") download_parser = subparsers.add_parser("download-artifacts-from-bucket") - download_parser.add_argument("--cname", required=False, dest="cname") + + download_parser.add_argument( + "--cname", + required=False, + dest="cname", + help="Canonical name (cname) used as the S3 key prefix for artifacts.", + ) upload_parser = subparsers.add_parser("upload-artifacts-to-bucket") - upload_parser.add_argument("--artifact-name", required=False, dest="artifact_name") + + upload_parser.add_argument( + "--artifact-name", dest="artifact_name", help="S3 artifact base name." + ) + + return parser + + +# Parser object for documentation generation +parser = get_parser() +parser.prog = "gl-s3" + + +def main() -> None: + """ + gl-s3 main() + + :since: 0.8.0 + """ args = parser.parse_args() From 0569798d9137941c46590ba542171d0030d31c7f Mon Sep 17 00:00:00 2001 From: Tobias Wolf Date: Wed, 25 Feb 2026 09:01:53 +0100 Subject: [PATCH 3/3] Refine Sphinx documentation generation Signed-off-by: Tobias Wolf On-behalf-of: SAP --- .github/workflows/docs.yml | 22 --------------- .github/workflows/release.yml | 22 +++++++++++++++ docs/_static/gardenlinux-logo.svg | 2 +- docs/api.rst | 2 +- docs/cli.rst | 10 +++---- docs/conf.py | 10 ++----- src/gardenlinux/features/__main__.py | 17 ++++++++---- src/gardenlinux/features/cname_main.py | 15 ++++++---- src/gardenlinux/flavors/__main__.py | 32 ++++++++++------------ src/gardenlinux/github/release/__main__.py | 29 ++++++++++++++++---- src/gardenlinux/s3/__main__.py | 8 ++---- tests/flavors/test_main.py | 2 +- 12 files changed, 93 insertions(+), 78 deletions(-) delete mode 100644 .github/workflows/docs.yml diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index 091ed242..00000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Update Sphinx documentation - -on: [push, pull_request, workflow_dispatch] - -permissions: - contents: write - -jobs: - docs: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: ./.github/actions/setup - - run: make docs - - name: Deploy to GitHub Pages - uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0 - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} - with: - publish_branch: gh-pages - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: _build - force_orphan: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0cd297a0..2537a754 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,7 +8,29 @@ env: GIT_CLIFF_VERSION: 2.12.0 jobs: + docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: gardenlinux/python-gardenlinux-lib/.github/actions/setup@main + - run: make docs + - if: ${{ github.ref_name != 'main' }} + name: Upload as artifact + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # pin@v6.0.0 + with: + name: docs + path: _build/ + - if: ${{ github.ref_name == 'main' }} + name: Deploy to GitHub Pages + uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0 + with: + publish_branch: gh-pages + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: _build + force_orphan: true + create-pre-release: + if: ${{ github.ref_name == 'main' }} runs-on: ubuntu-latest permissions: contents: write diff --git a/docs/_static/gardenlinux-logo.svg b/docs/_static/gardenlinux-logo.svg index b9823cce..4b63366a 100644 --- a/docs/_static/gardenlinux-logo.svg +++ b/docs/_static/gardenlinux-logo.svg @@ -1 +1 @@ -Garden Linux_logo \ No newline at end of file +Garden Linux_logo diff --git a/docs/api.rst b/docs/api.rst index ad00ac2d..2d68330a 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -1,5 +1,5 @@ API Reference -============ +============= This section provides detailed documentation for all Python modules and classes in python-gardenlinux-lib. diff --git a/docs/cli.rst b/docs/cli.rst index 1f94a475..80cc963c 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -11,14 +11,14 @@ gl-cname Generate a canonical name (cname) from feature sets. -.. autoprogram:: gardenlinux.features.cname_main:parser +.. autoprogram:: gardenlinux.features.cname_main:get_parser() gl-features-parse ~~~~~~~~~~~~~~~~~ Parse and extract information from GardenLinux features. -.. autoprogram:: gardenlinux.features.__main__:parser +.. autoprogram:: gardenlinux.features.__main__:get_parser() Flavors Commands ---------------- @@ -28,7 +28,7 @@ gl-flavors-parse Parse flavors.yaml and generate combinations. -.. autoprogram:: gardenlinux.flavors.__main__:parser +.. autoprogram:: gardenlinux.flavors.__main__:get_parser() OCI Commands ------------ @@ -50,7 +50,7 @@ gl-s3 Upload and download artifacts from S3 buckets. -.. autoprogram:: gardenlinux.s3.__main__:parser +.. autoprogram:: gardenlinux.s3.__main__:get_parser() GitHub Commands --------------- @@ -60,4 +60,4 @@ gl-gh-release Create and manage GitHub releases. -.. autoprogram:: gardenlinux.github.release.__main__:parser +.. autoprogram:: gardenlinux.github.release.__main__:get_parser() diff --git a/docs/conf.py b/docs/conf.py index 130c038c..30c97c2f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,8 +1,4 @@ -import os -import sys - -sys.path.insert(0, os.path.abspath("../src")) - +from sphinx.application import Sphinx # Configuration file for the Sphinx documentation builder. # @@ -41,9 +37,9 @@ # Logo configuration html_logo = "_static/gardenlinux-logo.svg" + html_theme_options = { "logo_only": False, - "display_version": True, "prev_next_buttons_location": "bottom", "style_external_links": True, "vcs_pageview_mode": "", @@ -57,5 +53,5 @@ # Add custom CSS -def setup(app): +def setup(app: Sphinx) -> None: app.add_css_file("custom.css") diff --git a/src/gardenlinux/features/__main__.py b/src/gardenlinux/features/__main__.py index d1a9bf51..d0b7f8ad 100644 --- a/src/gardenlinux/features/__main__.py +++ b/src/gardenlinux/features/__main__.py @@ -47,8 +47,10 @@ def get_parser() -> argparse.ArgumentParser: :return: ArgumentParser instance :since: 0.10.9 """ + parser = argparse.ArgumentParser( - description="Parse and extract information from GardenLinux features." + prog="gl-features-parse", + description="Parse and extract information from GardenLinux features.", ) parser.add_argument( @@ -56,37 +58,44 @@ def get_parser() -> argparse.ArgumentParser: dest="arch", help="Target architecture (e.g., amd64, arm64). Overrides architecture from cname.", ) + parser.add_argument( "--cname", dest="cname", required=True, help="Canonical name (cname) to parse. Must be a valid GardenLinux canonical name.", ) + parser.add_argument( "--commit", dest="commit", help="Git commit hash. If not specified, will be read from COMMIT file or release file.", ) + parser.add_argument( "--feature-dir", default="features", help="Path to the features directory (default: 'features'). Either --feature-dir or --release-file must be provided.", ) + parser.add_argument( "--release-file", dest="release_file", help="Path to a release file containing cname metadata. Either --feature-dir or --release-file must be provided.", ) + parser.add_argument( "--default-arch", dest="default_arch", help="Default architecture to use if architecture cannot be determined from cname or other sources.", ) + parser.add_argument( "--default-version", dest="default_version", help="Default version to use if version cannot be determined from files or other sources.", ) + parser.add_argument( "--version", dest="version", @@ -110,12 +119,8 @@ def get_parser() -> argparse.ArgumentParser: ", ".join(_ARGS_TYPE_ALLOWED) ), ) - return parser - -# Parser object for documentation generation -parser = get_parser() -parser.prog = "gl-features-parse" + return parser def main() -> None: diff --git a/src/gardenlinux/features/cname_main.py b/src/gardenlinux/features/cname_main.py index d04c2e2c..5ce5998c 100644 --- a/src/gardenlinux/features/cname_main.py +++ b/src/gardenlinux/features/cname_main.py @@ -26,39 +26,42 @@ def get_parser() -> argparse.ArgumentParser: :return: ArgumentParser instance :since: 1.0.0 """ + parser = argparse.ArgumentParser( - description="Generate a canonical name (cname) from feature sets." + prog="gl-cname", + description="Generate a canonical name (cname) from feature sets.", ) + parser.add_argument( "--arch", dest="arch", help="Target architecture (e.g., amd64, arm64). If not specified, will be determined from the cname or feature set.", ) + parser.add_argument( "--commit", dest="commit", help="Git commit hash. If not specified, will be read from COMMIT file in the GardenLinux root directory.", ) + parser.add_argument( "--feature-dir", default="features", help="Path to the features directory (default: 'features').", ) + parser.add_argument( "--version", dest="version", help="Version string. If not specified, will be read from VERSION file in the GardenLinux root directory.", ) + parser.add_argument( "cname", help="Canonical name (cname) to process. Must be a valid GardenLinux canonical name format.", ) - return parser - -# Parser object for documentation generation -parser = get_parser() -parser.prog = "gl-cname" + return parser def main() -> None: diff --git a/src/gardenlinux/flavors/__main__.py b/src/gardenlinux/flavors/__main__.py index 1cf2ba51..9933298f 100644 --- a/src/gardenlinux/flavors/__main__.py +++ b/src/gardenlinux/flavors/__main__.py @@ -6,7 +6,7 @@ """ import json -from argparse import ArgumentParser, Namespace +from argparse import ArgumentParser from pathlib import Path from tempfile import TemporaryDirectory from typing import Any, List, Tuple @@ -55,6 +55,7 @@ def get_parser() -> ArgumentParser: :return: ArgumentParser instance :since: 1.0.0 """ + parser = ArgumentParser(description="Parse flavors.yaml and generate combinations.") parser.add_argument( @@ -62,60 +63,71 @@ def get_parser() -> ArgumentParser: default=None, help="Commit hash to fetch flavors.yaml from GitHub. An existing 'flavors.yaml' file will be preferred.", ) + parser.add_argument( "--no-arch", action="store_true", help="Exclude architecture from the flavor output.", ) + parser.add_argument( "--include-only", action="append", default=[], help="Restrict combinations to those matching wildcard patterns (can be specified multiple times).", ) + parser.add_argument( "--exclude", action="append", default=[], help="Exclude combinations based on wildcard patterns (can be specified multiple times).", ) + parser.add_argument( "--build", action="store_true", help="Filter combinations to include only those with build enabled.", ) + parser.add_argument( "--publish", action="store_true", help="Filter combinations to include only those with publish enabled.", ) + parser.add_argument( "--test", action="store_true", help="Filter combinations to include only those with test enabled.", ) + parser.add_argument( "--test-platform", action="store_true", help="Filter combinations to include only platforms with test-platform: true.", ) + parser.add_argument( "--category", action="append", default=[], help="Filter combinations to include only platforms belonging to the specified categories (can be specified multiple times).", ) + parser.add_argument( "--exclude-category", action="append", default=[], help="Exclude platforms belonging to the specified categories (can be specified multiple times).", ) + parser.add_argument( "--json-by-arch", action="store_true", help="Output a JSON dictionary where keys are architectures and values are lists of flavors.", ) + parser.add_argument( "--markdown-table-by-platform", action="store_true", @@ -125,21 +137,6 @@ def get_parser() -> ArgumentParser: return parser -# Parser object for documentation generation -parser = get_parser() -parser.prog = "gl-flavors-parse" - - -def parse_args() -> Namespace: - """ - Parses arguments used for main() - - :return: (object) Parsed argparse.ArgumentParser namespace - :since: 0.7.0 - """ - return get_parser().parse_args() - - def main() -> None: """ gl-flavors-parse main() @@ -147,7 +144,8 @@ def main() -> None: :since: 0.7.0 """ - args = parse_args() + parser = get_parser() + args = parser.parse_args() try: flavors_data = _get_flavors_file_data(Path(Repository().root, "flavors.yaml")) diff --git a/src/gardenlinux/github/release/__main__.py b/src/gardenlinux/github/release/__main__.py index 1915dba4..013108b9 100644 --- a/src/gardenlinux/github/release/__main__.py +++ b/src/gardenlinux/github/release/__main__.py @@ -22,39 +22,50 @@ def get_parser() -> argparse.ArgumentParser: :return: ArgumentParser instance :since: 1.0.0 """ - parser = argparse.ArgumentParser(description="Create and manage GitHub releases.") + + parser = argparse.ArgumentParser( + prog="gl-gh-release", description="Create and manage GitHub releases." + ) subparsers = parser.add_subparsers(dest="command", help="Available commands") create_parser = subparsers.add_parser("create", help="Create a new GitHub release.") + create_parser.add_argument( "--owner", default="gardenlinux", help="GitHub repository owner (default: 'gardenlinux').", ) + create_parser.add_argument( "--repo", default="gardenlinux", help="GitHub repository name (default: 'gardenlinux').", ) + create_parser.add_argument( "--tag", required=True, help="Git tag name for the release (required)." ) + create_parser.add_argument( "--name", help="Release name/title. If not specified, the tag will be used." ) + create_parser.add_argument( "--body", required=True, help="Release notes/description body (required)." ) + create_parser.add_argument( "--commit", help="Git commit hash. If not specified, the tag will be used to find the commit.", ) + create_parser.add_argument( "--pre-release", action="store_true", default=True, help="Mark the release as a pre-release (default: True).", ) + create_parser.add_argument( "--latest", action="store_true", @@ -66,30 +77,36 @@ def get_parser() -> argparse.ArgumentParser: "create-with-gl-release-notes", help="Create a GitHub release with auto-generated GardenLinux release notes.", ) + create_parser_gl.add_argument( "--owner", default="gardenlinux", help="GitHub repository owner (default: 'gardenlinux').", ) + create_parser_gl.add_argument( "--repo", default="gardenlinux", help="GitHub repository name (default: 'gardenlinux').", ) + create_parser_gl.add_argument( "--tag", required=True, help="Git tag name for the release (required)." ) + create_parser_gl.add_argument( "--commit", required=True, help="Git commit hash used to generate release notes (required).", ) + create_parser_gl.add_argument( "--latest", action="store_true", default=False, help="Mark this release as the latest release (default: False).", ) + create_parser_gl.add_argument( "--dry-run", action="store_true", @@ -100,26 +117,31 @@ def get_parser() -> argparse.ArgumentParser: upload_parser = subparsers.add_parser( "upload", help="Upload a file to an existing GitHub release." ) + upload_parser.add_argument( "--owner", default="gardenlinux", help="GitHub repository owner (default: 'gardenlinux').", ) + upload_parser.add_argument( "--repo", default="gardenlinux", help="GitHub repository name (default: 'gardenlinux').", ) + upload_parser.add_argument( "--release_id", required=True, help="GitHub release ID to upload the file to (required).", ) + upload_parser.add_argument( "--file_path", required=True, help="Path to the file to upload (required).", ) + upload_parser.add_argument( "--dry-run", action="store_true", @@ -130,11 +152,6 @@ def get_parser() -> argparse.ArgumentParser: return parser -# Parser object for documentation generation -parser = get_parser() -parser.prog = "gl-gh-release" - - def main() -> None: parser = get_parser() args = parser.parse_args() diff --git a/src/gardenlinux/s3/__main__.py b/src/gardenlinux/s3/__main__.py index f87fbfee..f794631c 100644 --- a/src/gardenlinux/s3/__main__.py +++ b/src/gardenlinux/s3/__main__.py @@ -19,7 +19,7 @@ def get_parser() -> argparse.ArgumentParser: :since: 0.10.9 """ - parser = argparse.ArgumentParser() + parser = argparse.ArgumentParser("gl-s3") parser.add_argument( "--bucket", dest="bucket", help="S3 bucket name to upload to or download from." @@ -58,11 +58,6 @@ def get_parser() -> argparse.ArgumentParser: return parser -# Parser object for documentation generation -parser = get_parser() -parser.prog = "gl-s3" - - def main() -> None: """ gl-s3 main() @@ -70,6 +65,7 @@ def main() -> None: :since: 0.8.0 """ + parser = get_parser() args = parser.parse_args() if args.action == "download-artifacts-from-bucket": diff --git a/tests/flavors/test_main.py b/tests/flavors/test_main.py index b74a5e2b..8b0a0a89 100644 --- a/tests/flavors/test_main.py +++ b/tests/flavors/test_main.py @@ -44,7 +44,7 @@ def test_parse_args(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(sys, "argv", argv) # Act - args = fm.parse_args() + args = fm.get_parser().parse_args() # Assert assert args.no_arch is True