mkdocstrings-github 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mkdocstrings_github-0.1.0.dist-info/METADATA +64 -0
- mkdocstrings_github-0.1.0.dist-info/RECORD +17 -0
- mkdocstrings_github-0.1.0.dist-info/WHEEL +4 -0
- mkdocstrings_github-0.1.0.dist-info/licenses/LICENSE +21 -0
- mkdocstrings_handlers/github/__init__.py +9 -0
- mkdocstrings_handlers/github/config.py +189 -0
- mkdocstrings_handlers/github/handler.py +214 -0
- mkdocstrings_handlers/github/objects.py +216 -0
- mkdocstrings_handlers/github/py.typed +0 -0
- mkdocstrings_handlers/github/rendering.py +69 -0
- mkdocstrings_handlers/github/templates/material/action.html.jinja +73 -0
- mkdocstrings_handlers/github/templates/material/heading.html.jinja +39 -0
- mkdocstrings_handlers/github/templates/material/inputs.html.jinja +94 -0
- mkdocstrings_handlers/github/templates/material/outputs.html.jinja +78 -0
- mkdocstrings_handlers/github/templates/material/secrets.html.jinja +82 -0
- mkdocstrings_handlers/github/templates/material/style.css +59 -0
- mkdocstrings_handlers/github/templates/material/workflow.html.jinja +90 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mkdocstrings-github
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A GitHub Action handler for mkdocstrings
|
|
5
|
+
Author-email: Mark Hu <watermarkhu@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Programming Language :: Python
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Documentation
|
|
18
|
+
Classifier: Topic :: Software Development
|
|
19
|
+
Classifier: Topic :: Software Development :: Documentation
|
|
20
|
+
Classifier: Topic :: Utilities
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: <3.14,>=3.10
|
|
23
|
+
Requires-Dist: gitpython~=3.1.45
|
|
24
|
+
Requires-Dist: mkdocstrings~=0.29
|
|
25
|
+
Requires-Dist: pygithub~=2.8.1
|
|
26
|
+
Requires-Dist: typing-extensions>=4.0; python_version < '3.11'
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
<!-- --8<-- [start:header] -->
|
|
30
|
+
|
|
31
|
+
<h1 align="center">mkdocstrings-github</h1>
|
|
32
|
+
|
|
33
|
+
<p align="center">A GitHub Actions handler for <a href="https://github.com/mkdocstrings/mkdocstrings"><i>mkdocstrings</i></a>.</p>
|
|
34
|
+
|
|
35
|
+
<p align="center"><img width=300px src="logo.png"></p>
|
|
36
|
+
|
|
37
|
+
[](https://github.com/watermarkhu/mkdocstrings-github/actions/workflows/qualify.yaml)
|
|
38
|
+
[](https://watermarkhu.nl/mkdocstrings-github)
|
|
39
|
+
[](https://pypi.org/project/mkdocstrings-github/)
|
|
40
|
+
|
|
41
|
+
<!-- --8<-- [end:header] -->
|
|
42
|
+
<!-- --8<-- [start:install] -->
|
|
43
|
+
You can install the GitHub handler by specifying it as a dependency:
|
|
44
|
+
|
|
45
|
+
```toml title="pyproject.toml"
|
|
46
|
+
# PEP 621 dependencies declaration
|
|
47
|
+
# adapt to your dependencies manager
|
|
48
|
+
[project]
|
|
49
|
+
dependencies = [
|
|
50
|
+
"mkdocstrings-github>=0.X.Y",
|
|
51
|
+
]
|
|
52
|
+
```
|
|
53
|
+
<!-- --8<-- [end:install] -->
|
|
54
|
+
|
|
55
|
+
<!-- --8<-- [start:footer] -->
|
|
56
|
+
|
|
57
|
+
## Features
|
|
58
|
+
|
|
59
|
+
- 📝 **Automatic Example Signature**: Displays an example call signature alongside the description. The version shown can be the latest release, latest major, current reference, or any custom string.
|
|
60
|
+
- ✨ **Enhanced Markdown Descriptions**: All description elements are parsed using a markdown parser, enabling comprehensive formatting and rich documentation capabilities.
|
|
61
|
+
- 🧩 **Individual Parameter Hyperlinks**: Each action or workflow parameter—including inputs, outputs, and secrets—receives a unique HTML id, facilitating direct linking to specific parameter documentation.
|
|
62
|
+
- đź”’ **Automated Permission Aggregation**: For reusable workflows, if permissions are specified at the job level rather than the workflow level, the required final permissions are automatically determined and displayed in the signature.
|
|
63
|
+
|
|
64
|
+
<!-- --8<-- [end:footer] -->
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
mkdocstrings_handlers/github/__init__.py,sha256=0WdFUIq4Xu2ZFtlZNIYCQSoqcx3Ot9Wv41_X_dwbFww,248
|
|
2
|
+
mkdocstrings_handlers/github/config.py,sha256=Lma2xz46TfG5Tgj-Bkh6Lqa1hBuJH3uCtmfOFab7kI4,5459
|
|
3
|
+
mkdocstrings_handlers/github/handler.py,sha256=dN3maFhASZc4JzJKjpgMTDeXuz9VBwjR2YygnvTIEdk,8017
|
|
4
|
+
mkdocstrings_handlers/github/objects.py,sha256=deZlW1nuyaFd4FivOA5dJb2uzY7gHTheTdUzMkOIS9E,6796
|
|
5
|
+
mkdocstrings_handlers/github/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
mkdocstrings_handlers/github/rendering.py,sha256=XxejVRXR8n5pkKHAPyYWx4n0NyH8kHNUy2uHRlhQA3w,2184
|
|
7
|
+
mkdocstrings_handlers/github/templates/material/action.html.jinja,sha256=87NCgz-zY16rU7tEmJETJ0gLwdzxoBrqLtp9vsVCsiw,2435
|
|
8
|
+
mkdocstrings_handlers/github/templates/material/heading.html.jinja,sha256=wnvZpNED8Dhb935qnddeDExXN-MIUz8frRRfgq-A9VA,1396
|
|
9
|
+
mkdocstrings_handlers/github/templates/material/inputs.html.jinja,sha256=zP7z_9CO248LhSwvQZ-eG54y73DB67M2TFwNI5iFfM4,3352
|
|
10
|
+
mkdocstrings_handlers/github/templates/material/outputs.html.jinja,sha256=zDmKj9QjD9kd3VVN3xZqQSncVdNjXnTs1m98_Hj2hTM,2780
|
|
11
|
+
mkdocstrings_handlers/github/templates/material/secrets.html.jinja,sha256=uaKsGH_08JSdy5WbjDiDNaYaOXkCJ1K6Ac-6wYkLo2c,2990
|
|
12
|
+
mkdocstrings_handlers/github/templates/material/style.css,sha256=R2hh1RfHwJ6XNT4YQl_txNkNXcPBZJMCBZn5kQEMQ6M,962
|
|
13
|
+
mkdocstrings_handlers/github/templates/material/workflow.html.jinja,sha256=E1VUi2w7_NDkpS9VNrWRV52hhyhQvnKUrjPbV_j0Qcg,3312
|
|
14
|
+
mkdocstrings_github-0.1.0.dist-info/METADATA,sha256=4zfACSDnMmVa33t2ZLF8OFa7Cx4r-MRZvsYb9wTICUc,3008
|
|
15
|
+
mkdocstrings_github-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
16
|
+
mkdocstrings_github-0.1.0.dist-info/licenses/LICENSE,sha256=5enZtJ4zSp0Ps3jTqFQ4kadcx62BhgTaDNPrXWb3g3E,1069
|
|
17
|
+
mkdocstrings_github-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Mark Shui Hu
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"""Configuration and options dataclasses."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
import sys
|
|
7
|
+
from typing import Literal
|
|
8
|
+
|
|
9
|
+
from mkdocstrings import get_logger
|
|
10
|
+
from pydantic import BaseModel, Field
|
|
11
|
+
|
|
12
|
+
# YORE: EOL 3.10: Replace block with line 2.
|
|
13
|
+
if sys.version_info >= (3, 11):
|
|
14
|
+
pass
|
|
15
|
+
else:
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
logger = get_logger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
SIGNATURE_VERSION = Literal["ref", "major", "semver", "string"]
|
|
23
|
+
PARAMETERS_ORDER = Literal["alphabetical", "source"]
|
|
24
|
+
PARAMETERS_SECTION_STYLE = Literal["table", "list"]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class GitHubOptions(BaseModel):
|
|
28
|
+
"""Input options for the GitHub handler."""
|
|
29
|
+
|
|
30
|
+
# General options
|
|
31
|
+
show_description: bool = Field(
|
|
32
|
+
default=True,
|
|
33
|
+
description="Whether to show the description in the documentation.",
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
description: str = Field(
|
|
37
|
+
default="",
|
|
38
|
+
description="A custom string to override the autogenerated description of the object.",
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
show_source: bool = Field(
|
|
42
|
+
default=True,
|
|
43
|
+
description="Whether to show the source link in the documentation.",
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
# Heading options
|
|
47
|
+
show_heading: bool = Field(
|
|
48
|
+
default=True,
|
|
49
|
+
description="Whether to show the heading in the documentation.",
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
heading: str = Field(
|
|
53
|
+
default="",
|
|
54
|
+
description="A custom string to override the autogenerated heading of the object.",
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
heading_level: int = Field(
|
|
58
|
+
default=2,
|
|
59
|
+
description="The initial heading level to use.",
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
show_branding: bool = Field(
|
|
63
|
+
default=True,
|
|
64
|
+
description="Whether to show the action branding (logo and color) in the documentation.",
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
branding_icon: str = Field(
|
|
68
|
+
default="",
|
|
69
|
+
description="Custom icon from https://feathericons.com/ to use for the branding.",
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
branding_icon_color: str = Field(
|
|
73
|
+
default="",
|
|
74
|
+
description="Custom icon color for the feather icon.",
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
show_toc_entry: bool = Field(
|
|
78
|
+
default=True,
|
|
79
|
+
description="If the heading is not shown, at least add a ToC entry for it.",
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
toc_label: str = Field(
|
|
83
|
+
default="",
|
|
84
|
+
description="A custom string to override the autogenerated toc label of the root object.",
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
# Signature options
|
|
88
|
+
show_signature: bool = Field(
|
|
89
|
+
default=True,
|
|
90
|
+
description="Whether to show the signature in the documentation.",
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
signature_show_secrets: bool = Field(
|
|
94
|
+
default=False,
|
|
95
|
+
description="Whether to show secrets in the signature.",
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
signature_show_permissions: bool = Field(
|
|
99
|
+
default=True,
|
|
100
|
+
description="Whether to show permissions in the workflow signature.",
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
signature_version: SIGNATURE_VERSION = Field(
|
|
104
|
+
default="ref",
|
|
105
|
+
description="The versioning scheme to use for the signature.",
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
signature_version_string: str = Field(
|
|
109
|
+
default="latest",
|
|
110
|
+
description="The version string to use if `signature_version` is set to `string`.",
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# Parameter options
|
|
114
|
+
show_inputs: bool = Field(
|
|
115
|
+
default=True,
|
|
116
|
+
description="Whether to show inputs in the documentation.",
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
show_inputs_only_required: bool = Field(
|
|
120
|
+
default=False,
|
|
121
|
+
description="Whether to show only required inputs in the documentation.",
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
show_outputs: bool = Field(
|
|
125
|
+
default=False,
|
|
126
|
+
description="Whether to show outputs in the documentation.",
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
show_secrets: bool = Field(
|
|
130
|
+
default=True,
|
|
131
|
+
description="Whether to show secrets in the documentation.",
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
show_secrets_only_required: bool = Field(
|
|
135
|
+
default=False,
|
|
136
|
+
description="Whether to show only required secrets in the documentation.",
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
parameters_order: PARAMETERS_ORDER = Field(
|
|
140
|
+
default="source",
|
|
141
|
+
description="""The parameters ordering to use.
|
|
142
|
+
|
|
143
|
+
- `alphabetical`: order by the parameters names,
|
|
144
|
+
- `source`: order parameters as they appear in the source file.
|
|
145
|
+
""",
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
parameters_section_style: PARAMETERS_SECTION_STYLE = Field(
|
|
149
|
+
default="table",
|
|
150
|
+
description="""The style used to render docstring sections.
|
|
151
|
+
|
|
152
|
+
- `table`: render parameters in a table,
|
|
153
|
+
- `list`: render parameters in a list.
|
|
154
|
+
""",
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
parameters_anchors: bool = Field(
|
|
158
|
+
default=True,
|
|
159
|
+
description="Whether to add anchors to parameters in the documentation.",
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class GitHubConfig(BaseModel):
|
|
164
|
+
"""Configuration options for the GitHub handler."""
|
|
165
|
+
|
|
166
|
+
repo: str = Field(
|
|
167
|
+
default="",
|
|
168
|
+
description="""The GitHub repository in the format *owner/repo*.
|
|
169
|
+
|
|
170
|
+
By default, the repository is inferred from the current git repository using the default origin remote.
|
|
171
|
+
If it cannot be inferred, it must be set manually.
|
|
172
|
+
""",
|
|
173
|
+
pattern=re.compile(r"^[\w.-]+/[\w.-]+$"),
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
feather_icons_source: str = Field(
|
|
177
|
+
default="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js",
|
|
178
|
+
description="""The source URL for Feather icons.
|
|
179
|
+
|
|
180
|
+
In certain enterprise environments, external CDN access may be restricted.
|
|
181
|
+
In such cases, you can host the `feather.min.js` file locally and set this option to the local path or URL.
|
|
182
|
+
See more information at https://github.com/feathericons/feather.
|
|
183
|
+
""",
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
options: GitHubOptions = Field(
|
|
187
|
+
default_factory=GitHubOptions,
|
|
188
|
+
description="Options for the GitHub handler.",
|
|
189
|
+
)
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"""The mkdocstrings handler for processing MATLAB code documentation."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import re
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import TYPE_CHECKING, Any, ClassVar, Mapping
|
|
10
|
+
|
|
11
|
+
import git
|
|
12
|
+
from mkdocs.exceptions import PluginError
|
|
13
|
+
from mkdocstrings import (
|
|
14
|
+
BaseHandler,
|
|
15
|
+
CollectionError,
|
|
16
|
+
HandlerOptions,
|
|
17
|
+
get_logger,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
from github import Github
|
|
21
|
+
from mkdocstrings_handlers.github import rendering
|
|
22
|
+
from mkdocstrings_handlers.github.config import GitHubConfig, GitHubOptions
|
|
23
|
+
from mkdocstrings_handlers.github.objects import Action, Workflow
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from collections.abc import MutableMapping
|
|
27
|
+
|
|
28
|
+
from mkdocs.config.defaults import MkDocsConfig
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
SEMVER_PATTERN = re.compile(r"^v(\d+\.\d+\.\d+)$")
|
|
32
|
+
MAJOR_PATTERN = re.compile(r"^v(\d+)$")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
_logger = get_logger(__name__)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class GitHubHandler(BaseHandler):
|
|
39
|
+
"""The `GitHubHandler` class is a handler for processing GitHub code documentation."""
|
|
40
|
+
|
|
41
|
+
name: ClassVar[str] = "github"
|
|
42
|
+
"""The GitHub handler class."""
|
|
43
|
+
|
|
44
|
+
domain: ClassVar[str] = "gh" # to match Sphinx's default domain
|
|
45
|
+
"""The cross-documentation domain/language for this handler."""
|
|
46
|
+
|
|
47
|
+
enable_inventory: ClassVar[bool] = True
|
|
48
|
+
"""Whether this handler is interested in enabling the creation of the `objects.inv` Sphinx inventory file."""
|
|
49
|
+
|
|
50
|
+
fallback_theme: ClassVar[str] = "material"
|
|
51
|
+
"""The fallback theme."""
|
|
52
|
+
|
|
53
|
+
def __init__(
|
|
54
|
+
self,
|
|
55
|
+
config: GitHubConfig,
|
|
56
|
+
repo: git.Repo,
|
|
57
|
+
**kwargs: Any,
|
|
58
|
+
) -> None:
|
|
59
|
+
"""
|
|
60
|
+
Initialize the handler with the given configuration.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
config: The handler configuration.
|
|
64
|
+
base_dir: The base directory of the project.
|
|
65
|
+
**kwargs: Arguments passed to the parent constructor.
|
|
66
|
+
"""
|
|
67
|
+
super().__init__(**kwargs)
|
|
68
|
+
self.config = config
|
|
69
|
+
self.repo = repo
|
|
70
|
+
self.global_options = config.options.__dict__
|
|
71
|
+
self.workflows: dict[Path, Workflow] = {}
|
|
72
|
+
self.actions: dict[Path, Action] = {}
|
|
73
|
+
self.major: str = ""
|
|
74
|
+
self.semver: str = ""
|
|
75
|
+
|
|
76
|
+
# Only run GitHub releases code if not running under pytest
|
|
77
|
+
if (
|
|
78
|
+
rendering.ENV_MAJOR_TAG not in os.environ or rendering.ENV_SEMVER_TAG not in os.environ
|
|
79
|
+
) and "pytest" not in sys.modules:
|
|
80
|
+
# Use PyGitHub to find last GitHub releases with tags matching vX.X.X and vX
|
|
81
|
+
gh = Github()
|
|
82
|
+
owner, repo_name = self.config.repo.split("/", 1)
|
|
83
|
+
gh_repo = gh.get_repo(f"{owner}/{repo_name}")
|
|
84
|
+
releases = list(gh_repo.get_releases())
|
|
85
|
+
for release in releases:
|
|
86
|
+
tag = release.tag_name
|
|
87
|
+
if not self.semver and SEMVER_PATTERN.match(tag):
|
|
88
|
+
self.semver = tag
|
|
89
|
+
if not self.major and MAJOR_PATTERN.match(tag):
|
|
90
|
+
self.major = tag
|
|
91
|
+
if self.semver and self.major:
|
|
92
|
+
break
|
|
93
|
+
else:
|
|
94
|
+
_logger.warning(
|
|
95
|
+
"Could not find suitable GitHub releases for repo '%s'. "
|
|
96
|
+
"Make sure there are releases with tags matching 'vX.X.X' and 'vX', "
|
|
97
|
+
"if you wish to use the 'semver' and 'major' signature versions.",
|
|
98
|
+
self.config.repo,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
if self.config.repo == ".":
|
|
102
|
+
url = next(repo.remote("origin").urls)
|
|
103
|
+
match = re.search(r"github.com[:/](?P<owner>[^/]+)/(?P<repo>[^/.]+)", url)
|
|
104
|
+
if match:
|
|
105
|
+
self.config.repo = f"{match.group('owner')}/{match.group('repo')}"
|
|
106
|
+
else:
|
|
107
|
+
_logger.warning(
|
|
108
|
+
"Could not determine GitHub repository automatically from git remote URL '%s'. "
|
|
109
|
+
"Make sure the remote URL is a GitHub URL, "
|
|
110
|
+
"or set the 'repo' option in the configuration.",
|
|
111
|
+
url,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
# Glob all workflow YAML files using pathlib
|
|
115
|
+
working_tree_dir = Path(repo.working_tree_dir)
|
|
116
|
+
workflows_dir = working_tree_dir / ".github" / "workflows"
|
|
117
|
+
for workflow_file in list(workflows_dir.glob("*.yml")) + list(workflows_dir.glob("*.yaml")):
|
|
118
|
+
id = str(workflow_file.relative_to(working_tree_dir))
|
|
119
|
+
workflow = Workflow.from_file(workflow_file, id)
|
|
120
|
+
if workflow is not None:
|
|
121
|
+
self.workflows[workflow_file] = workflow
|
|
122
|
+
|
|
123
|
+
# Glob all action.yaml and action.yml files, skipping .git folder entirely using pathlib
|
|
124
|
+
def find_action_files(base: Path):
|
|
125
|
+
for entry in base.iterdir():
|
|
126
|
+
if entry.is_dir():
|
|
127
|
+
if entry.name == ".git":
|
|
128
|
+
continue
|
|
129
|
+
yield from find_action_files(entry)
|
|
130
|
+
elif entry.is_file() and entry.name in ("action.yaml", "action.yml"):
|
|
131
|
+
yield entry
|
|
132
|
+
|
|
133
|
+
for action_file in find_action_files(working_tree_dir):
|
|
134
|
+
id = str(action_file.relative_to(working_tree_dir).parent)
|
|
135
|
+
action = Action.from_file(action_file, id)
|
|
136
|
+
if action is not None:
|
|
137
|
+
self.actions[action_file] = action
|
|
138
|
+
|
|
139
|
+
def get_options(self, local_options: Mapping[str, Any]) -> HandlerOptions:
|
|
140
|
+
"""Get combined default, global and local options.
|
|
141
|
+
|
|
142
|
+
Arguments:
|
|
143
|
+
local_options: The local options.
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
The combined options.
|
|
147
|
+
"""
|
|
148
|
+
|
|
149
|
+
options = {**self.global_options, **local_options}
|
|
150
|
+
try:
|
|
151
|
+
return GitHubOptions(**options)
|
|
152
|
+
except Exception as error:
|
|
153
|
+
raise PluginError(f"Invalid options: {error}") from error
|
|
154
|
+
|
|
155
|
+
def update_env(self, config: Any) -> None:
|
|
156
|
+
self.env.trim_blocks = True
|
|
157
|
+
self.env.lstrip_blocks = True
|
|
158
|
+
self.env.keep_trailing_newline = False
|
|
159
|
+
self.env.filters["format_action_signature"] = rendering.format_action_signature
|
|
160
|
+
self.env.filters["order_parameters"] = rendering.order_parameters
|
|
161
|
+
self.env.filters["filter_parameters"] = rendering.filter_parameters
|
|
162
|
+
self.env.globals["semver_tag"] = self.semver
|
|
163
|
+
self.env.globals["major_tag"] = self.major
|
|
164
|
+
self.env.globals["git_repo"] = self.repo
|
|
165
|
+
|
|
166
|
+
def collect(self, identifier: str, options: GitHubOptions) -> Workflow | Action:
|
|
167
|
+
path = Path(self.repo.working_tree_dir) / identifier
|
|
168
|
+
if path in self.workflows:
|
|
169
|
+
return self.workflows[path]
|
|
170
|
+
elif (action_path := path / "action.yml") in self.actions:
|
|
171
|
+
return self.actions[action_path]
|
|
172
|
+
elif (action_path := path / "action.yaml") in self.actions:
|
|
173
|
+
return self.actions[action_path]
|
|
174
|
+
else:
|
|
175
|
+
raise CollectionError(f"Identifier '{identifier}' not found as a workflow or action.")
|
|
176
|
+
|
|
177
|
+
def render(self, data: Workflow | Action, options: GitHubOptions) -> str:
|
|
178
|
+
"""Render a template using provided data and configuration options.
|
|
179
|
+
|
|
180
|
+
Arguments:
|
|
181
|
+
data: The collected data to render.
|
|
182
|
+
options: The handler's configuration options.
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
The rendered template as HTML.
|
|
186
|
+
"""
|
|
187
|
+
template = self.env.get_template(data.template)
|
|
188
|
+
html = template.render(options=options, data=data, config=self.config)
|
|
189
|
+
return html
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def get_handler(
|
|
193
|
+
handler_config: MutableMapping[str, Any],
|
|
194
|
+
tool_config: MkDocsConfig,
|
|
195
|
+
**kwargs: Any,
|
|
196
|
+
) -> GitHubHandler:
|
|
197
|
+
"""
|
|
198
|
+
Create and return a GitHubHandler object with the specified configuration.
|
|
199
|
+
|
|
200
|
+
Parameters:
|
|
201
|
+
handler_config: The handler configuration.
|
|
202
|
+
tool_config: The tool (SSG) configuration.
|
|
203
|
+
|
|
204
|
+
Returns:
|
|
205
|
+
GitHubHandler: An instance of GitHubHandler configured with the provided parameters.
|
|
206
|
+
"""
|
|
207
|
+
config_file = Path(tool_config.config_file_path)
|
|
208
|
+
repo = git.Repo(path=config_file.parent, search_parent_directories=True)
|
|
209
|
+
|
|
210
|
+
return GitHubHandler(
|
|
211
|
+
config=GitHubConfig(**handler_config),
|
|
212
|
+
repo=repo,
|
|
213
|
+
**kwargs,
|
|
214
|
+
)
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
from collections import OrderedDict
|
|
2
|
+
from dataclasses import dataclass, field
|
|
3
|
+
from enum import Enum
|
|
4
|
+
from os import PathLike
|
|
5
|
+
from typing import Any, Literal, Optional
|
|
6
|
+
|
|
7
|
+
import yaml
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class Input:
|
|
12
|
+
name: str
|
|
13
|
+
description: str = ""
|
|
14
|
+
required: bool = False
|
|
15
|
+
type: Literal["boolean", "number", "string"] = "string"
|
|
16
|
+
default: bool | float | int | str | None = None
|
|
17
|
+
deprecationMessage: Optional[str] = None
|
|
18
|
+
|
|
19
|
+
@staticmethod
|
|
20
|
+
def from_data(
|
|
21
|
+
name: str,
|
|
22
|
+
description: str = "",
|
|
23
|
+
required: bool = False,
|
|
24
|
+
type: Literal["boolean", "number", "string"] = "string",
|
|
25
|
+
default: bool | float | int | str | None = None,
|
|
26
|
+
deprecationMessage: Optional[str] = None,
|
|
27
|
+
**kwargs,
|
|
28
|
+
) -> "Input":
|
|
29
|
+
return Input(name, description, required, type, default, deprecationMessage)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass
|
|
33
|
+
class Output:
|
|
34
|
+
name: str
|
|
35
|
+
description: str = ""
|
|
36
|
+
|
|
37
|
+
@staticmethod
|
|
38
|
+
def from_data(name: str, description: str = "", **kwargs) -> "Output":
|
|
39
|
+
return Output(name, description)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass
|
|
43
|
+
class Secret:
|
|
44
|
+
name: str
|
|
45
|
+
description: str = ""
|
|
46
|
+
required: bool = False
|
|
47
|
+
|
|
48
|
+
@staticmethod
|
|
49
|
+
def from_data(name: str, description: str = "", required: bool = False, **kwargs) -> "Secret":
|
|
50
|
+
return Secret(name, description, required)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _get_member(d: dict, key: str, error_message: str = "", default: Any = None) -> Any:
|
|
54
|
+
if key not in d:
|
|
55
|
+
if default is not None:
|
|
56
|
+
return default
|
|
57
|
+
raise KeyError(error_message)
|
|
58
|
+
return d[key]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class _OrderedLoader(yaml.Loader):
|
|
62
|
+
pass
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# Remove boolean resolver for "on", "off", "yes", "no" (and case variants)
|
|
66
|
+
for ch in "yYnNoO":
|
|
67
|
+
if ch in _OrderedLoader.yaml_implicit_resolvers:
|
|
68
|
+
_OrderedLoader.yaml_implicit_resolvers[ch] = [
|
|
69
|
+
res
|
|
70
|
+
for res in _OrderedLoader.yaml_implicit_resolvers[ch]
|
|
71
|
+
if res[0] != "tag:yaml.org,2002:bool"
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _construct_mapping(loader, node):
|
|
76
|
+
loader.flatten_mapping(node)
|
|
77
|
+
return OrderedDict(loader.construct_pairs(node))
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
_OrderedLoader.add_constructor(
|
|
81
|
+
yaml.SafeLoader.DEFAULT_MAPPING_TAG,
|
|
82
|
+
_construct_mapping,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _read_file(file: PathLike) -> tuple[str, dict]:
|
|
87
|
+
with open(file, "r", encoding="utf-8") as f:
|
|
88
|
+
source = f.read()
|
|
89
|
+
f.seek(0)
|
|
90
|
+
data = yaml.load(f, Loader=_OrderedLoader)
|
|
91
|
+
return source, data
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@dataclass
|
|
95
|
+
class Action:
|
|
96
|
+
# https://docs.github.com/en/actions/reference/workflows-and-actions/metadata-syntax
|
|
97
|
+
file: PathLike
|
|
98
|
+
source: str
|
|
99
|
+
id: str
|
|
100
|
+
name: str
|
|
101
|
+
description: str
|
|
102
|
+
using: str
|
|
103
|
+
author: str = ""
|
|
104
|
+
inputs: list[Input] = field(default_factory=list)
|
|
105
|
+
outputs: list[Output] = field(default_factory=list)
|
|
106
|
+
branding: dict = field(default_factory=dict)
|
|
107
|
+
template: Literal["action.html.jinja"] = "action.html.jinja"
|
|
108
|
+
|
|
109
|
+
@staticmethod
|
|
110
|
+
def from_file(file: PathLike, id: str) -> "Action":
|
|
111
|
+
source, data = _read_file(file)
|
|
112
|
+
|
|
113
|
+
action = Action(
|
|
114
|
+
file=file,
|
|
115
|
+
source=source,
|
|
116
|
+
id=id,
|
|
117
|
+
name=_get_member(data, "name", "Action must have a name"),
|
|
118
|
+
description=_get_member(data, "description", "Action must have a description"),
|
|
119
|
+
using=_get_member(data, "runs", "Action must have a 'runs' section").get("using", ""),
|
|
120
|
+
author=_get_member(data, "author", default=""),
|
|
121
|
+
branding=_get_member(data, "branding", default={}),
|
|
122
|
+
)
|
|
123
|
+
for key, value in data.get("inputs", {}).items():
|
|
124
|
+
action.inputs.append(Input.from_data(key, **value))
|
|
125
|
+
for key, value in data.get("outputs", {}).items():
|
|
126
|
+
action.outputs.append(Output.from_data(key, **value))
|
|
127
|
+
return action
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class PermissionLevel(Enum):
|
|
131
|
+
none = ("none", 0)
|
|
132
|
+
read = ("read", 1)
|
|
133
|
+
write = ("write", 2)
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def label(self) -> str:
|
|
137
|
+
return self.value[0]
|
|
138
|
+
|
|
139
|
+
@property
|
|
140
|
+
def number(self) -> int:
|
|
141
|
+
return self.value[1]
|
|
142
|
+
|
|
143
|
+
@staticmethod
|
|
144
|
+
def from_label(label: str) -> "PermissionLevel":
|
|
145
|
+
for perm in PermissionLevel:
|
|
146
|
+
if perm.label == label:
|
|
147
|
+
return perm
|
|
148
|
+
raise ValueError(f"No Permission with label '{label}'")
|
|
149
|
+
|
|
150
|
+
def __le__(self, other):
|
|
151
|
+
if isinstance(other, PermissionLevel):
|
|
152
|
+
return self.number <= other.number
|
|
153
|
+
return NotImplemented
|
|
154
|
+
|
|
155
|
+
def __lt__(self, other):
|
|
156
|
+
if isinstance(other, PermissionLevel):
|
|
157
|
+
return self.number < other.number
|
|
158
|
+
return NotImplemented
|
|
159
|
+
|
|
160
|
+
def __ge__(self, other):
|
|
161
|
+
if isinstance(other, PermissionLevel):
|
|
162
|
+
return self.number >= other.number
|
|
163
|
+
return NotImplemented
|
|
164
|
+
|
|
165
|
+
def __gt__(self, other):
|
|
166
|
+
if isinstance(other, PermissionLevel):
|
|
167
|
+
return self.number > other.number
|
|
168
|
+
return NotImplemented
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
@dataclass
|
|
172
|
+
class Workflow:
|
|
173
|
+
# https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax
|
|
174
|
+
file: PathLike
|
|
175
|
+
source: str
|
|
176
|
+
id: str
|
|
177
|
+
name: str
|
|
178
|
+
description: str
|
|
179
|
+
permissions: dict[str, PermissionLevel] = field(default_factory=dict)
|
|
180
|
+
inputs: list[Input] = field(default_factory=list)
|
|
181
|
+
secrets: list[Secret] = field(default_factory=list)
|
|
182
|
+
outputs: list[Output] = field(default_factory=list)
|
|
183
|
+
template: Literal["workflow.html.jinja"] = "workflow.html.jinja"
|
|
184
|
+
|
|
185
|
+
@staticmethod
|
|
186
|
+
def from_file(file: PathLike, id: str) -> "Workflow | None":
|
|
187
|
+
source, data = _read_file(file)
|
|
188
|
+
|
|
189
|
+
if "on" not in data or "workflow_call" not in data["on"]:
|
|
190
|
+
return None
|
|
191
|
+
call = data["on"]["workflow_call"]
|
|
192
|
+
|
|
193
|
+
workflow = Workflow(
|
|
194
|
+
file=file,
|
|
195
|
+
source=source,
|
|
196
|
+
id=id,
|
|
197
|
+
name=_get_member(data, "name", "Workflow must have a name"),
|
|
198
|
+
description=_get_member(data, "description", default=""),
|
|
199
|
+
)
|
|
200
|
+
for key, value in call.get("inputs", {}).items():
|
|
201
|
+
workflow.inputs.append(Input.from_data(key, **value))
|
|
202
|
+
for key, value in call.get("outputs", {}).items():
|
|
203
|
+
workflow.outputs.append(Output.from_data(key, **value))
|
|
204
|
+
for key, value in call.get("secrets", {}).items():
|
|
205
|
+
workflow.secrets.append(Secret.from_data(key, **value))
|
|
206
|
+
|
|
207
|
+
for key, label in data.get("permissions", {}).items():
|
|
208
|
+
workflow.permissions[key] = PermissionLevel.from_label(label)
|
|
209
|
+
for job in data.get("jobs", {}).values():
|
|
210
|
+
for key, label in job.get("permissions", {}).items():
|
|
211
|
+
if key in workflow.permissions:
|
|
212
|
+
if permission := PermissionLevel.from_label(label) > workflow.permissions[key]:
|
|
213
|
+
workflow.permissions[key] = permission
|
|
214
|
+
else:
|
|
215
|
+
workflow.permissions[key] = PermissionLevel.from_label(label)
|
|
216
|
+
return workflow
|
|
File without changes
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from typing import TYPE_CHECKING, Sequence
|
|
5
|
+
|
|
6
|
+
from jinja2 import pass_context
|
|
7
|
+
|
|
8
|
+
from mkdocstrings_handlers.github.config import PARAMETERS_ORDER, GitHubOptions
|
|
9
|
+
from mkdocstrings_handlers.github.objects import Input, Output, Secret
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from git import Repo
|
|
13
|
+
from jinja2.runtime import Context
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
ENV_MAJOR_TAG = "MKDOCSTRINGS_GITHUB_MAJOR_TAG"
|
|
17
|
+
ENV_SEMVER_TAG = "MKDOCSTRINGS_GITHUB_SEMVER_TAG"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@pass_context
|
|
21
|
+
def format_action_signature(context: Context, id: str, repo: str, options: GitHubOptions) -> str:
|
|
22
|
+
name = repo if id == "." else f"{repo}/{id}"
|
|
23
|
+
match options.signature_version:
|
|
24
|
+
case "ref":
|
|
25
|
+
try:
|
|
26
|
+
repo: Repo = context.environment.globals["git_repo"]
|
|
27
|
+
version = repo.head.ref.name
|
|
28
|
+
except Exception:
|
|
29
|
+
version = "unknown"
|
|
30
|
+
case "major":
|
|
31
|
+
version = os.environ.get(ENV_MAJOR_TAG, context.environment.globals["major_tag"])
|
|
32
|
+
case "semver":
|
|
33
|
+
version = os.environ.get(ENV_SEMVER_TAG, context.environment.globals["semver_tag"])
|
|
34
|
+
case "string":
|
|
35
|
+
version = options.signature_version_string
|
|
36
|
+
|
|
37
|
+
return f"{name}@{version}"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def order_parameters(
|
|
41
|
+
parameters: Sequence[Input | Output | Secret], parameters_order: PARAMETERS_ORDER
|
|
42
|
+
):
|
|
43
|
+
if parameters_order == "alphabetical":
|
|
44
|
+
return sorted(parameters, key=lambda x: x.name)
|
|
45
|
+
else:
|
|
46
|
+
return parameters
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def filter_parameters(
|
|
50
|
+
parameters: Sequence[Input | Output | Secret],
|
|
51
|
+
required: bool = False,
|
|
52
|
+
optional: bool = False,
|
|
53
|
+
description: bool = False,
|
|
54
|
+
default: bool = False,
|
|
55
|
+
):
|
|
56
|
+
filtered = []
|
|
57
|
+
for parameter in parameters:
|
|
58
|
+
filter = False
|
|
59
|
+
if required and not getattr(parameter, "required", False):
|
|
60
|
+
filter = True
|
|
61
|
+
if optional and getattr(parameter, "required", False):
|
|
62
|
+
filter = True
|
|
63
|
+
if description and not getattr(parameter, "description", ""):
|
|
64
|
+
filter = True
|
|
65
|
+
if default and not getattr(parameter, "default", None):
|
|
66
|
+
filter = True
|
|
67
|
+
if not filter:
|
|
68
|
+
filtered.append(parameter)
|
|
69
|
+
return filtered
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{#- Template for GitHub Action.
|
|
2
|
+
|
|
3
|
+
This template renders a GitHub Action.
|
|
4
|
+
|
|
5
|
+
Context:
|
|
6
|
+
data (mkdocstrings_handlers.github.objects.Action): The action to render.
|
|
7
|
+
config (mkdocstrings_handlers.github.config.GitHubConfig): The global configuration
|
|
8
|
+
options (dict): The local options
|
|
9
|
+
-#}
|
|
10
|
+
|
|
11
|
+
{% block logs scoped %}
|
|
12
|
+
{#- Logging block.
|
|
13
|
+
|
|
14
|
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
|
|
15
|
+
-#}
|
|
16
|
+
{{ log.debug("Rendering " + data.id) }}
|
|
17
|
+
{% endblock logs %}
|
|
18
|
+
|
|
19
|
+
{% if options.show_branding %}
|
|
20
|
+
<script src="{{ config.feather_icons_source }}"></script>
|
|
21
|
+
{% endif %}
|
|
22
|
+
<div class="doc doc-object doc-action">
|
|
23
|
+
|
|
24
|
+
{% include "heading.html.jinja" with context %}
|
|
25
|
+
|
|
26
|
+
{% set signature = data.id | format_action_signature(config.repo, options) %}
|
|
27
|
+
|
|
28
|
+
{% block signature scoped %}
|
|
29
|
+
{% if options.show_signature %}
|
|
30
|
+
{% with inputs = data.inputs | order_parameters(options.parameters_order) | filter_parameters(required=True) %}
|
|
31
|
+
{% filter highlight(language="yaml", inline=False, linenums=False) %}
|
|
32
|
+
- uses: {{ signature }}
|
|
33
|
+
with:
|
|
34
|
+
{%+ for input in inputs %}{{ input.name }}: ''{% endfor +%}
|
|
35
|
+
{% endfilter %}
|
|
36
|
+
{% endwith %}
|
|
37
|
+
{% endif %}
|
|
38
|
+
{% endblock signature %}
|
|
39
|
+
|
|
40
|
+
{% block description scoped %}
|
|
41
|
+
{% if options.show_description %}
|
|
42
|
+
{{ options.description if options.description else data.description | convert_markdown(options.heading_level, data.id) }}
|
|
43
|
+
{% endif %}
|
|
44
|
+
{% endblock description %}
|
|
45
|
+
|
|
46
|
+
{% block inputs scoped %}
|
|
47
|
+
{% if options.show_inputs %}
|
|
48
|
+
{% with inputs = data.inputs | order_parameters(options.parameters_order) | filter_parameters(required=options.show_inputs_only_required) %}
|
|
49
|
+
{% include "inputs.html.jinja" with context %}
|
|
50
|
+
{% endwith %}
|
|
51
|
+
{% endif %}
|
|
52
|
+
{% endblock inputs %}
|
|
53
|
+
|
|
54
|
+
{% block outputs scoped %}
|
|
55
|
+
{% if options.show_outputs %}
|
|
56
|
+
{% with outputs = data.outputs | order_parameters(options.parameters_order) %}
|
|
57
|
+
{% include "outputs.html.jinja" with context %}
|
|
58
|
+
{% endwith %}
|
|
59
|
+
{% endif %}
|
|
60
|
+
{% endblock outputs %}
|
|
61
|
+
|
|
62
|
+
{% block source scoped %}
|
|
63
|
+
{% if options.show_source %}
|
|
64
|
+
<details class="quote">
|
|
65
|
+
<summary>Source of <code>{{ signature }}</code></summary>
|
|
66
|
+
{{ data.source|highlight(language="yaml", linenums=True) }}
|
|
67
|
+
</details>
|
|
68
|
+
{% endif %}
|
|
69
|
+
{% endblock %}
|
|
70
|
+
</div>
|
|
71
|
+
{% if options.show_branding %}
|
|
72
|
+
<script>feather.replace()</script>
|
|
73
|
+
{% endif %}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{#- Template for heading
|
|
2
|
+
|
|
3
|
+
Context:
|
|
4
|
+
data (mkdocstrings_handlers.github.objects.Action | Workfow): The object to render.
|
|
5
|
+
config (mkdocstrings_handlers.github.config.GitHubConfig): The global configuration
|
|
6
|
+
options (dict): The local options
|
|
7
|
+
-#}
|
|
8
|
+
|
|
9
|
+
{% if options.show_heading %}
|
|
10
|
+
{% filter heading(
|
|
11
|
+
options.heading_level,
|
|
12
|
+
role="gh",
|
|
13
|
+
id=data.id,
|
|
14
|
+
class="doc doc-heading",
|
|
15
|
+
toc_label=options.toc_label if options.toc_label else data.name,
|
|
16
|
+
)%}
|
|
17
|
+
{% block heading scoped %}
|
|
18
|
+
{% if options.show_branding and (options.branding_icon or data.branding) and (options.branding_icon_color or data.branding.icon) %}
|
|
19
|
+
<span style="display: inline-flex; align-items: center;">
|
|
20
|
+
<span class="gh-action-badge-img gh-action-badge--{{ options.branding_icon_color or data.branding.color }}" style="margin-right: 0.5em;">
|
|
21
|
+
<i data-feather="{{ options.branding_icon or data.branding.icon }}"></i>
|
|
22
|
+
</span>
|
|
23
|
+
{{ options.heading if options.heading else data.name }}
|
|
24
|
+
</span>
|
|
25
|
+
{% else %}
|
|
26
|
+
{{ options.heading if options.heading else data.name }}
|
|
27
|
+
{% endif %}
|
|
28
|
+
{% endblock heading %}
|
|
29
|
+
{% endfilter %}
|
|
30
|
+
{% elif options.show_toc_entry %}
|
|
31
|
+
{% filter heading(
|
|
32
|
+
options.heading_level,
|
|
33
|
+
role="gh",
|
|
34
|
+
id=data.id,
|
|
35
|
+
class="doc doc-heading",
|
|
36
|
+
toc_label=options.toc_label if options.toc_label else data.name,
|
|
37
|
+
)%}
|
|
38
|
+
{% endfilter %}
|
|
39
|
+
{% endif %}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
{#- Template for inputs.
|
|
2
|
+
|
|
3
|
+
Context:
|
|
4
|
+
inputs (list of mkdocstrings_handlers.github.objects.Input): The inputs to render.
|
|
5
|
+
data (mkdocstrings_handlers.github.objects.Action | Workflow): The object to render.
|
|
6
|
+
config (mkdocstrings_handlers.github.config.GitHubConfig): The global configuration
|
|
7
|
+
options (dict): The local options
|
|
8
|
+
-#}
|
|
9
|
+
|
|
10
|
+
{% block logs scoped %}
|
|
11
|
+
{{ log.debug("Rendering inputs of " + data.id) }}
|
|
12
|
+
{% endblock logs %}
|
|
13
|
+
|
|
14
|
+
{% set header_id -%}
|
|
15
|
+
inputs-{{ data.id | replace('/', '-') | replace('.', '') | lower }}
|
|
16
|
+
{%- endset %}
|
|
17
|
+
|
|
18
|
+
{% if options.parameters_section_style == "table" %}
|
|
19
|
+
{% block table_style scoped %}
|
|
20
|
+
<p>
|
|
21
|
+
<span class="doc-section-title">Inputs:</span>
|
|
22
|
+
<a class="headerlink" href="#{{ header_id }}" title="Link to {{ data.name }} outputs">¤</a>
|
|
23
|
+
</p>
|
|
24
|
+
<table>
|
|
25
|
+
<thead>
|
|
26
|
+
<tr>
|
|
27
|
+
<th>Name</th>
|
|
28
|
+
<th>Description</th>
|
|
29
|
+
<th>Default</th>
|
|
30
|
+
</tr>
|
|
31
|
+
</thead>
|
|
32
|
+
<tbody>
|
|
33
|
+
{% for input in inputs %}
|
|
34
|
+
{% if options.parameters_anchors %}
|
|
35
|
+
{% set anchor_id -%}
|
|
36
|
+
input-{{ data.id | replace('/', '-') | replace('.', '') | lower }}-{{ input.name | replace(' ', '-') | lower }}
|
|
37
|
+
{%- endset %}
|
|
38
|
+
{% else %}
|
|
39
|
+
{% set anchor_id = None %}
|
|
40
|
+
{% endif %}
|
|
41
|
+
<tr class="doc-section-item">
|
|
42
|
+
<td id="{{ anchor_id }}">
|
|
43
|
+
{% if input.required %}
|
|
44
|
+
<strong><code>{{ input.name }}</code></strong>
|
|
45
|
+
{% else %}
|
|
46
|
+
<code>{{ input.name }}</code>
|
|
47
|
+
{% endif %}
|
|
48
|
+
{% if options.parameters_anchors %}
|
|
49
|
+
<a class="headerlink" href="#{{ anchor_id }}" title="Link to {{ input.name }}">¤</a>
|
|
50
|
+
{% endif %}
|
|
51
|
+
</td>
|
|
52
|
+
<td>
|
|
53
|
+
{{ input.description | convert_markdown(options.heading_level, data.id) }}
|
|
54
|
+
</td>
|
|
55
|
+
<td>
|
|
56
|
+
{% if input.default %}
|
|
57
|
+
<code>{{ input.default }}</code>
|
|
58
|
+
{% endif %}
|
|
59
|
+
</td>
|
|
60
|
+
</tr>
|
|
61
|
+
{% endfor %}
|
|
62
|
+
</tbody>
|
|
63
|
+
</table>
|
|
64
|
+
{% endblock table_style %}
|
|
65
|
+
{% elif options.parameters_section_style == "list" %}
|
|
66
|
+
{% block list_style scoped %}
|
|
67
|
+
<p>
|
|
68
|
+
<span class="doc-section-title">Inputs:</span>
|
|
69
|
+
<a class="headerlink" href="#{{ header_id }}" title="Link to {{ data.name }} outputs">¤</a>
|
|
70
|
+
</p>
|
|
71
|
+
<ul>
|
|
72
|
+
{% for input in inputs %}
|
|
73
|
+
{% set anchor_id -%}
|
|
74
|
+
input-{{ data.id | replace('/', '-') | replace('.', '') | lower }}-{{ input.name | replace(' ', '-') | lower }}
|
|
75
|
+
{%- endset %}
|
|
76
|
+
<li class="doc-section-item field-body">
|
|
77
|
+
<b><code>{{ input.name }}</code></b>
|
|
78
|
+
{%- if input.required %} - <em>required</em>{% endif %}
|
|
79
|
+
{% if options.parameters_anchors %}
|
|
80
|
+
<a class="headerlink" href="#{{ anchor_id }}" title="Link to {{ input.name }}">¤</a>
|
|
81
|
+
{% endif %}
|
|
82
|
+
<div class="doc-md-description">
|
|
83
|
+
{{ input.description|convert_markdown(options.heading_level, data.id) }}
|
|
84
|
+
</div>
|
|
85
|
+
{% if input.default is not none %}
|
|
86
|
+
<div class="doc-md-description">
|
|
87
|
+
Default: <code>{{ input.default }}</code>
|
|
88
|
+
</div>
|
|
89
|
+
{% endif %}
|
|
90
|
+
</li>
|
|
91
|
+
{% endfor %}
|
|
92
|
+
</ul>
|
|
93
|
+
{% endblock list_style %}
|
|
94
|
+
{% endif %}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{#- Template for outputs.
|
|
2
|
+
|
|
3
|
+
Context:
|
|
4
|
+
outputs (list of mkdocstrings_handlers.github.objects.Output): The outputs to render.
|
|
5
|
+
data (mkdocstrings_handlers.github.objects.Action | Workflow): The object to render.
|
|
6
|
+
config (mkdocstrings_handlers.github.config.GitHubConfig): The global configuration
|
|
7
|
+
options (dict): The local options
|
|
8
|
+
-#}
|
|
9
|
+
|
|
10
|
+
{% block logs scoped %}
|
|
11
|
+
{{ log.debug("Rendering outputs of " + data.id) }}
|
|
12
|
+
{% endblock logs %}
|
|
13
|
+
|
|
14
|
+
{% set header_id -%}
|
|
15
|
+
outputs-{{ data.id | replace('/', '-') | replace('.', '') | lower }}
|
|
16
|
+
{%- endset %}
|
|
17
|
+
|
|
18
|
+
{% if options.parameters_section_style == "table" %}
|
|
19
|
+
{% block table_style scoped %}
|
|
20
|
+
<p>
|
|
21
|
+
<span class="doc-section-title">Outputs:</span>
|
|
22
|
+
<a class="headerlink" href="#{{ header_id }}" title="Link to {{ data.name }} outputs">¤</a>
|
|
23
|
+
</p>
|
|
24
|
+
<table>
|
|
25
|
+
<thead>
|
|
26
|
+
<tr>
|
|
27
|
+
<th>Name</th>
|
|
28
|
+
<th>Description</th>
|
|
29
|
+
</tr>
|
|
30
|
+
</thead>
|
|
31
|
+
<tbody>
|
|
32
|
+
{% for output in outputs %}
|
|
33
|
+
{% if options.parameters_anchors %}
|
|
34
|
+
{% set anchor_id -%}
|
|
35
|
+
output-{{ data.id | replace('/', '-') | replace('.', '') | lower }}-{{ output.name | replace(' ', '-') | lower }}
|
|
36
|
+
{%- endset %}
|
|
37
|
+
{% else %}
|
|
38
|
+
{% set anchor_id = None %}
|
|
39
|
+
{% endif %}
|
|
40
|
+
<tr class="doc-section-item">
|
|
41
|
+
<td id="{{ anchor_id }}">
|
|
42
|
+
<code>{{ output.name }}</code>
|
|
43
|
+
{% if options.parameters_anchors %}
|
|
44
|
+
<a class="headerlink" href="#{{ anchor_id }}" title="Link to {{ output.name }}">¤</a>
|
|
45
|
+
{% endif %}
|
|
46
|
+
</td>
|
|
47
|
+
<td>
|
|
48
|
+
{{ output.description | convert_markdown(options.heading_level, data.id) }}
|
|
49
|
+
</td>
|
|
50
|
+
{% endfor %}
|
|
51
|
+
</tbody>
|
|
52
|
+
</table>
|
|
53
|
+
{% endblock table_style %}
|
|
54
|
+
{% elif options.parameters_section_style == "list" %}
|
|
55
|
+
{% block list_style scoped %}
|
|
56
|
+
<p>
|
|
57
|
+
<span class="doc-section-title">Outputs:</span>
|
|
58
|
+
<a class="headerlink" href="#{{ header_id }}" title="Link to {{ data.name }} outputs">¤</a>
|
|
59
|
+
</p>
|
|
60
|
+
<ul>
|
|
61
|
+
{% for output in outputs %}
|
|
62
|
+
{% set anchor_id -%}
|
|
63
|
+
output-{{ data.id | replace('/', '-') | replace('.', '') | lower }}-{{ output.name | replace(' ', '-') | lower }}
|
|
64
|
+
{%- endset %}
|
|
65
|
+
<li class="doc-section-item field-body">
|
|
66
|
+
<b><code>{{ output.name }}</code></b>
|
|
67
|
+
{% if options.parameters_anchors %}
|
|
68
|
+
<a class="headerlink" href="#{{ anchor_id }}" title="Link to {{ output.name }}">¤</a>
|
|
69
|
+
{% endif %}
|
|
70
|
+
<div class="doc-md-description">
|
|
71
|
+
{{ output.description|convert_markdown(options.heading_level, data.id) }}
|
|
72
|
+
</div>
|
|
73
|
+
</li>
|
|
74
|
+
{% endfor %}
|
|
75
|
+
</ul>
|
|
76
|
+
{% endblock list_style %}
|
|
77
|
+
{% endif %}
|
|
78
|
+
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{#- Template for secrets.
|
|
2
|
+
|
|
3
|
+
Context:
|
|
4
|
+
secrets (list of mkdocstrings_handlers.github.objects.Secret): The secrets to render.
|
|
5
|
+
data (mkdocstrings_handlers.github.objects.Workflow): The object to render.
|
|
6
|
+
config (mkdocstrings_handlers.github.config.GitHubConfig): The global configuration
|
|
7
|
+
options (dict): The local options
|
|
8
|
+
-#}
|
|
9
|
+
|
|
10
|
+
{% block logs scoped %}
|
|
11
|
+
{{ log.debug("Rendering secrets of " + data.id) }}
|
|
12
|
+
{% endblock logs %}
|
|
13
|
+
|
|
14
|
+
{% set header_id -%}
|
|
15
|
+
secrets-{{ data.id | replace('/', '-') | replace('.', '') | lower }}
|
|
16
|
+
{%- endset %}
|
|
17
|
+
|
|
18
|
+
{% if options.parameters_section_style == "table" %}
|
|
19
|
+
{% block table_style scoped %}
|
|
20
|
+
<p>
|
|
21
|
+
<span class="doc-section-title">Secrets:</span>
|
|
22
|
+
<a class="headerlink" href="#{{ header_id }}" title="Link to {{ data.name }} outputs">¤</a>
|
|
23
|
+
</p>
|
|
24
|
+
<table>
|
|
25
|
+
<thead>
|
|
26
|
+
<tr>
|
|
27
|
+
<th>Name</th>
|
|
28
|
+
<th>Description</th>
|
|
29
|
+
</tr>
|
|
30
|
+
</thead>
|
|
31
|
+
<tbody>
|
|
32
|
+
{% for secret in secrets %}
|
|
33
|
+
{% if options.parameters_anchors %}
|
|
34
|
+
{% set anchor_id -%}
|
|
35
|
+
secret-{{ data.id | replace('/', '-') | replace('.', '') | lower }}-{{ secret.name | replace(' ', '-') | lower }}
|
|
36
|
+
{%- endset %}
|
|
37
|
+
{% else %}
|
|
38
|
+
{% set anchor_id = None %}
|
|
39
|
+
{% endif %}
|
|
40
|
+
<tr class="doc-section-item">
|
|
41
|
+
<td id="{{ anchor_id }}">
|
|
42
|
+
{% if secret.required %}
|
|
43
|
+
<strong><code>{{ secret.name }}</code></strong>
|
|
44
|
+
{% else %}
|
|
45
|
+
<code>{{ secret.name }}</code>
|
|
46
|
+
{% endif %}
|
|
47
|
+
{% if options.parameters_anchors %}
|
|
48
|
+
<a class="headerlink" href="#{{ anchor_id }}" title="Link to {{ secret.name }}">¤</a>
|
|
49
|
+
{% endif %}
|
|
50
|
+
</td>
|
|
51
|
+
<td>
|
|
52
|
+
{{ secret.description | convert_markdown(options.heading_level, data.id) }}
|
|
53
|
+
</td>
|
|
54
|
+
{% endfor %}
|
|
55
|
+
</tbody>
|
|
56
|
+
</table>
|
|
57
|
+
{% endblock table_style %}
|
|
58
|
+
{% elif options.parameters_section_style == "list" %}
|
|
59
|
+
{% block list_style scoped %}
|
|
60
|
+
<p>
|
|
61
|
+
<span class="doc-section-title">Secrets:</span>
|
|
62
|
+
<a class="headerlink" href="#{{ header_id }}" title="Link to {{ data.name }} outputs">¤</a>
|
|
63
|
+
</p>
|
|
64
|
+
<ul>
|
|
65
|
+
{% for secret in secrets %}
|
|
66
|
+
{% set anchor_id -%}
|
|
67
|
+
secret-{{ data.id | replace('/', '-') | replace('.', '') | lower }}-{{ secret.name | replace(' ', '-') | lower }}
|
|
68
|
+
{%- endset %}
|
|
69
|
+
<li class="doc-section-item field-body">
|
|
70
|
+
<b><code>{{ secret.name }}</code></b>
|
|
71
|
+
{%- if secret.required %} - <em>required</em>{% endif %}
|
|
72
|
+
{% if options.parameters_anchors %}
|
|
73
|
+
<a class="headerlink" href="#{{ anchor_id }}" title="Link to {{ secret.name }}">¤</a>
|
|
74
|
+
{% endif %}
|
|
75
|
+
<div class="doc-md-description">
|
|
76
|
+
{{ secret.description|convert_markdown(options.heading_level, data.id) }}
|
|
77
|
+
</div>
|
|
78
|
+
</li>
|
|
79
|
+
{% endfor %}
|
|
80
|
+
</ul>
|
|
81
|
+
{% endblock list_style %}
|
|
82
|
+
{% endif %}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/* .gh-action-badge {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
align-items: center;
|
|
5
|
+
width: 140px;
|
|
6
|
+
margin: 15px 5px;
|
|
7
|
+
cursor: copy;
|
|
8
|
+
} */
|
|
9
|
+
|
|
10
|
+
.gh-action-badge-img {
|
|
11
|
+
width: 44px;
|
|
12
|
+
height: 44px;
|
|
13
|
+
border-radius: 50%;
|
|
14
|
+
box-shadow: 0 1px 5px rgba(27,31,35,.15);
|
|
15
|
+
display: flex;
|
|
16
|
+
justify-content: center;
|
|
17
|
+
align-items: center;
|
|
18
|
+
margin: 3px;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.gh-action-badge--white {
|
|
22
|
+
background-color: #ffffff;
|
|
23
|
+
color: #23292e;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.gh-action-badge--yellow {
|
|
27
|
+
background-color: #ffd33d;
|
|
28
|
+
color: #23292e;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.gh-action-badge--blue {
|
|
32
|
+
background-color: #0366d6;
|
|
33
|
+
color: #ffffff;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.gh-action-badge--green {
|
|
37
|
+
background-color: #28a745;
|
|
38
|
+
color: #ffffff;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.gh-action-badge--orange {
|
|
42
|
+
background-color: #f66a0a;
|
|
43
|
+
color: #ffffff;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.gh-action-badge--red {
|
|
47
|
+
background-color: #d73a49;
|
|
48
|
+
color: #ffffff;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.gh-action-badge--purple {
|
|
52
|
+
background-color: #6f42c1;
|
|
53
|
+
color: #ffffff;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.gh-action-badge--gray-dark {
|
|
57
|
+
background-color: #24292e;
|
|
58
|
+
color: #ffffff;
|
|
59
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
{#- Template for GitHub Action reusable workflow.
|
|
2
|
+
|
|
3
|
+
Context:
|
|
4
|
+
data (mkdocstrings_handlers.github.objects.Workflow): The workflow to render.
|
|
5
|
+
config (mkdocstrings_handlers.github.config.GitHubConfig): The global configuration
|
|
6
|
+
options (dict): The local options
|
|
7
|
+
-#}
|
|
8
|
+
|
|
9
|
+
{% block logs scoped %}
|
|
10
|
+
{#- Logging block.
|
|
11
|
+
|
|
12
|
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
|
|
13
|
+
-#}
|
|
14
|
+
{{ log.debug("Rendering " + data.id) }}
|
|
15
|
+
{% endblock logs %}
|
|
16
|
+
|
|
17
|
+
{% if options.show_branding %}
|
|
18
|
+
<script src="{{ config.feather_icons_source }}"></script>
|
|
19
|
+
{% endif %}
|
|
20
|
+
<div class="doc doc-object doc-workflow">
|
|
21
|
+
{% include "heading.html.jinja" with context %}
|
|
22
|
+
|
|
23
|
+
{% set signature = data.id | format_action_signature(config.repo, options) %}
|
|
24
|
+
|
|
25
|
+
{% block signature scoped %}
|
|
26
|
+
{% if options.show_signature %}
|
|
27
|
+
{% with inputs = data.inputs | order_parameters(options.parameters_order) | filter_parameters(required=True) %}
|
|
28
|
+
{% filter highlight(language="yaml", inline=False, linenums=False) %}
|
|
29
|
+
uses: {{ signature }}
|
|
30
|
+
{% if options.signature_show_permissions and data.permissions %}
|
|
31
|
+
permissions:
|
|
32
|
+
{% for scope, level in data.permissions | items %}
|
|
33
|
+
{{ scope }}: {{ level.label }}
|
|
34
|
+
{% endfor %}
|
|
35
|
+
{% endif %}
|
|
36
|
+
with:
|
|
37
|
+
{%+ for input in inputs %}{{ input.name }}: ''{% endfor +%}
|
|
38
|
+
{% if options.signature_show_secrets %}
|
|
39
|
+
{% with secrets = data.secrets | order_parameters(options.parameters_order) | filter_parameters(required=True) %}
|
|
40
|
+
secrets:
|
|
41
|
+
{%+ for secret in secrets %}{{ secret.name }}: ''{% endfor +%}
|
|
42
|
+
{% endwith %}
|
|
43
|
+
{% endif %}
|
|
44
|
+
{% endfilter %}
|
|
45
|
+
{% endwith %}
|
|
46
|
+
{% endif %}
|
|
47
|
+
{% endblock signature %}
|
|
48
|
+
|
|
49
|
+
{% block description scoped %}
|
|
50
|
+
{% if options.show_description %}
|
|
51
|
+
{{ options.description if options.description else data.description | convert_markdown(options.heading_level, data.id) }}
|
|
52
|
+
{% endif %}
|
|
53
|
+
{% endblock description %}
|
|
54
|
+
|
|
55
|
+
{% block inputs scoped %}
|
|
56
|
+
{% if options.show_inputs %}
|
|
57
|
+
{% with inputs = data.inputs | order_parameters(options.parameters_order) | filter_parameters(required=options.show_inputs_only_required) %}
|
|
58
|
+
{% include "inputs.html.jinja" with context %}
|
|
59
|
+
{% endwith %}
|
|
60
|
+
{% endif %}
|
|
61
|
+
{% endblock inputs %}
|
|
62
|
+
|
|
63
|
+
{% block secrets scoped %}
|
|
64
|
+
{% if options.show_secrets %}
|
|
65
|
+
{% with secrets = data.secrets | order_parameters(options.parameters_order) | filter_parameters(required=options.show_secrets_only_required) %}
|
|
66
|
+
{% include "secrets.html.jinja" with context %}
|
|
67
|
+
{% endwith %}
|
|
68
|
+
{% endif %}
|
|
69
|
+
{% endblock secrets %}
|
|
70
|
+
|
|
71
|
+
{% block outputs scoped %}
|
|
72
|
+
{% if options.show_outputs %}
|
|
73
|
+
{% with outputs = data.outputs | order_parameters(options.parameters_order) %}
|
|
74
|
+
{% include "outputs.html.jinja" with context %}
|
|
75
|
+
{% endwith %}
|
|
76
|
+
{% endif %}
|
|
77
|
+
{% endblock outputs %}
|
|
78
|
+
|
|
79
|
+
{% block source scoped %}
|
|
80
|
+
{% if options.show_source %}
|
|
81
|
+
<details class="quote">
|
|
82
|
+
<summary>Source of <code>{{ signature }}</code></summary>
|
|
83
|
+
{{ data.source|highlight(language="yaml", linenums=True) }}
|
|
84
|
+
</details>
|
|
85
|
+
{% endif %}
|
|
86
|
+
{% endblock %}
|
|
87
|
+
</div>
|
|
88
|
+
{% if options.show_branding %}
|
|
89
|
+
<script>feather.replace()</script>
|
|
90
|
+
{% endif %}
|