mirror of
https://github.com/basnijholt/adaptive-lighting.git
synced 2026-09-11 22:34:04 +02:00
Auto-generate the configuration options documentation (#498)
* Autogenerate the documentation and strings * Line limit * Split * Happy pre-commit * Split up workflows * Generate table function * raise * Add gen script * chore(docs): update TOC * Add gen script * path * Run - name: Install Home Assistant * chore(docs): update TOC * add copyright * Fix branch name * Run on PRs * dev * remove steps * use matrix * Run script * chore(docs): update TOC * Try fixing CI * fix * test * refactor * chore(docs): update TOC * fix * update * use v3 * rename * Fix input * fix pytest * fix path * paths * Change to github.head_ref * More backticks * Add extra text * chore(docs): update TOC * backticks * Update README.md --------- Co-authored-by: basnijholt <basnijholt@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
parent
ec558e5616
commit
cc8ce29a8a
7 changed files with 486 additions and 52 deletions
195
.github/update-readme.py
vendored
Normal file
195
.github/update-readme.py
vendored
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
# Copyright (c) 2023, Bas Nijholt
|
||||
# All rights reserved.
|
||||
# When using this code, please cite the original source.
|
||||
# and include the LICENSE file in your project.
|
||||
"""Automatically update Markdown files with code block output.
|
||||
|
||||
Add code blocks between <!-- START_CODE --> and <!-- END_CODE --> in your Markdown file.
|
||||
The output will be inserted between <!-- START_OUTPUT --> and <!-- END_OUTPUT -->.
|
||||
|
||||
Example:
|
||||
-------
|
||||
```
|
||||
<!-- START_CODE -->
|
||||
<!-- print('Hello, world!') -->
|
||||
<!-- END_CODE -->
|
||||
<!-- START_OUTPUT -->
|
||||
This will be replaced by the output of the code block above.
|
||||
|
||||
<!-- END_OUTPUT -->
|
||||
```
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import io
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def md_comment(text: str) -> str:
|
||||
"""Format a string as a Markdown comment."""
|
||||
return f"<!-- {text} -->"
|
||||
|
||||
|
||||
MARKERS = {
|
||||
"warning": md_comment("THIS CONTENT IS AUTOMATICALLY GENERATED"),
|
||||
"start_code": md_comment("START_CODE"),
|
||||
"end_code": md_comment("END_CODE"),
|
||||
"start_output": md_comment("START_OUTPUT"),
|
||||
"end_output": md_comment("END_OUTPUT"),
|
||||
}
|
||||
|
||||
|
||||
def remove_md_comment(commented_text: str) -> str:
|
||||
"""Remove Markdown comment tags from a string."""
|
||||
if not (commented_text.startswith("<!-- ") and commented_text.endswith(" -->")):
|
||||
raise ValueError("Invalid Markdown comment format")
|
||||
return commented_text[5:-4]
|
||||
|
||||
|
||||
def execute_code_block(code: list[str]) -> list[str]:
|
||||
"""Execute a code block and return its output as a list of strings."""
|
||||
f = io.StringIO()
|
||||
with contextlib.redirect_stdout(f):
|
||||
exec("\n".join(code)) # noqa: S102
|
||||
return f.getvalue().split("\n")
|
||||
|
||||
|
||||
def process_markdown(content: list[str]) -> list[str]:
|
||||
"""Executes code blocks in a list of Markdown-formatted strings and returns the modified list.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
content
|
||||
A list of Markdown-formatted strings.
|
||||
|
||||
Returns
|
||||
-------
|
||||
list[str]
|
||||
A modified list of Markdown-formatted strings with code block output inserted.
|
||||
"""
|
||||
assert isinstance(content, list), "Input must be a list"
|
||||
new_lines = []
|
||||
code = []
|
||||
in_code_block = in_output_block = False
|
||||
output = None
|
||||
|
||||
for line in content:
|
||||
if MARKERS["start_code"] in line:
|
||||
in_code_block = True
|
||||
elif MARKERS["start_output"] in line:
|
||||
in_output_block = True
|
||||
new_lines.extend([line, MARKERS["warning"]] + output)
|
||||
output = None
|
||||
elif MARKERS["end_output"] in line:
|
||||
in_output_block = False
|
||||
elif in_code_block:
|
||||
if MARKERS["end_code"] in line:
|
||||
in_code_block = False
|
||||
output = execute_code_block(code)
|
||||
code = []
|
||||
else:
|
||||
code.append(remove_md_comment(line))
|
||||
|
||||
if not in_output_block:
|
||||
new_lines.append(line)
|
||||
|
||||
return new_lines
|
||||
|
||||
|
||||
def update_markdown_file(filepath: Path) -> None:
|
||||
"""Rewrite a Markdown file by executing and updating code blocks."""
|
||||
with filepath.open() as f:
|
||||
original_lines = [line.rstrip("\n") for line in f.readlines()]
|
||||
|
||||
new_lines = process_markdown(original_lines)
|
||||
updated_content = "\n".join(new_lines).rstrip() + "\n"
|
||||
|
||||
with filepath.open("w") as f:
|
||||
f.write(updated_content)
|
||||
|
||||
|
||||
def test_process_markdown():
|
||||
def assert_process(input_lines, expected_output):
|
||||
output = process_markdown(input_lines)
|
||||
assert output == expected_output, f"Expected {expected_output}, got {output}"
|
||||
|
||||
# Test case 1: Single code block
|
||||
input_lines = [
|
||||
"Some text",
|
||||
MARKERS["start_code"],
|
||||
md_comment("print('Hello, world!')"),
|
||||
MARKERS["end_code"],
|
||||
MARKERS["start_output"],
|
||||
"This content will be replaced",
|
||||
MARKERS["end_output"],
|
||||
"More text",
|
||||
]
|
||||
expected_output = [
|
||||
"Some text",
|
||||
MARKERS["start_code"],
|
||||
md_comment("print('Hello, world!')"),
|
||||
MARKERS["end_code"],
|
||||
MARKERS["start_output"],
|
||||
MARKERS["warning"],
|
||||
"Hello, world!",
|
||||
"",
|
||||
MARKERS["end_output"],
|
||||
"More text",
|
||||
]
|
||||
assert_process(input_lines, expected_output)
|
||||
|
||||
# Test case 2: Two code blocks
|
||||
input_lines = [
|
||||
"Some text",
|
||||
MARKERS["start_code"],
|
||||
md_comment("print('Hello, world!')"),
|
||||
MARKERS["end_code"],
|
||||
MARKERS["start_output"],
|
||||
"This content will be replaced",
|
||||
MARKERS["end_output"],
|
||||
"More text",
|
||||
MARKERS["start_code"],
|
||||
md_comment("print('Hello again!')"),
|
||||
MARKERS["end_code"],
|
||||
MARKERS["start_output"],
|
||||
"This content will also be replaced",
|
||||
MARKERS["end_output"],
|
||||
]
|
||||
expected_output = [
|
||||
"Some text",
|
||||
MARKERS["start_code"],
|
||||
md_comment("print('Hello, world!')"),
|
||||
MARKERS["end_code"],
|
||||
MARKERS["start_output"],
|
||||
MARKERS["warning"],
|
||||
"Hello, world!",
|
||||
"",
|
||||
MARKERS["end_output"],
|
||||
"More text",
|
||||
MARKERS["start_code"],
|
||||
md_comment("print('Hello again!')"),
|
||||
MARKERS["end_code"],
|
||||
MARKERS["start_output"],
|
||||
MARKERS["warning"],
|
||||
"Hello again!",
|
||||
"",
|
||||
MARKERS["end_output"],
|
||||
]
|
||||
assert_process(input_lines, expected_output)
|
||||
|
||||
# Test case 3: No code blocks
|
||||
input_lines = [
|
||||
"Some text",
|
||||
"More text",
|
||||
]
|
||||
expected_output = [
|
||||
"Some text",
|
||||
"More text",
|
||||
]
|
||||
assert_process(input_lines, expected_output)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_process_markdown()
|
||||
update_markdown_file(Path(__file__).parent.parent / "README.md")
|
||||
8
.github/workflows/docker-build.yml
vendored
8
.github/workflows/docker-build.yml
vendored
|
|
@ -9,6 +9,11 @@ on:
|
|||
jobs:
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
platform:
|
||||
- linux/amd64
|
||||
- linux/arm64
|
||||
steps:
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
|
@ -24,6 +29,5 @@ jobs:
|
|||
with:
|
||||
# Only push on the master branch
|
||||
push: ${{ github.ref == 'refs/heads/master' }}
|
||||
# TODO: fix builds on linux/arm/v7
|
||||
platforms: linux/amd64,linux/arm64
|
||||
platforms: ${{ matrix.platform }}
|
||||
tags: ${{ secrets.DOCKERHUB_USERNAME }}/adaptive-lighting:latest
|
||||
|
|
|
|||
36
.github/workflows/install_dependencies/action.yml
vendored
Normal file
36
.github/workflows/install_dependencies/action.yml
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
name: 'Install Dependencies'
|
||||
description: 'Install Home Assistant and test dependencies'
|
||||
inputs:
|
||||
python_version:
|
||||
description: 'Python version'
|
||||
required: true
|
||||
default: '3.10'
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: ${{ github.repository }}
|
||||
ref: ${{ github.ref }}
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: home-assistant/core
|
||||
path: core
|
||||
- name: Set up Python ${{ inputs.python_version }}
|
||||
id: python
|
||||
uses: actions/setup-python@v4.1.0
|
||||
with:
|
||||
python-version: ${{ inputs.python_version }}
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
echo "::warning::### WARNING! Deprecation warnings muted with option '--use-pep517' please address this at some point in pytest.yaml. ###"
|
||||
pip install -r core/requirements.txt --use-pep517
|
||||
pip install -r core/requirements_test.txt --use-pep517
|
||||
pip install -e core/ --use-pep517
|
||||
pip install $(python test_dependencies.py) --use-pep517
|
||||
24
.github/workflows/pytest.yaml
vendored
24
.github/workflows/pytest.yaml
vendored
|
|
@ -6,7 +6,6 @@ on:
|
|||
pull_request:
|
||||
|
||||
jobs:
|
||||
|
||||
pytest:
|
||||
name: Run pytest
|
||||
runs-on: ubuntu-20.04
|
||||
|
|
@ -16,17 +15,13 @@ jobs:
|
|||
python-version: ["3.10"]
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.0.2
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.0.2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Home Assistant
|
||||
uses: ./.github/workflows/install_dependencies
|
||||
with:
|
||||
repository: home-assistant/core
|
||||
path: core
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
id: python
|
||||
uses: actions/setup-python@v4.1.0
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
python_version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Click here for troubleshooting steps if tests break again.
|
||||
run: |
|
||||
echo "::notice::### If tests fail, try these debug steps: ###"
|
||||
|
|
@ -36,13 +31,6 @@ jobs:
|
|||
echo "::notice::### 4. ERROR:homeassistant.setup:Setup failed for 'component': Unable to import component: No module named ''module'' ###"
|
||||
echo "::notice::### 5. add 'component'.'module' (without the '') from the above log into the 'required' list inside of 'test_dependencies.py' ###"
|
||||
echo "::notice::### 6. Try again! If more issues persist they should be easily solvable by reading the verbose logs now. ###"
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
echo "::warning::### WARNING! Deprecation warnings muted with option '--use-pep517' please address this at some point in pytest.yaml. ###"
|
||||
pip install -r core/requirements.txt --use-pep517
|
||||
pip install -r core/requirements_test.txt --use-pep517
|
||||
pip install -e core/ --use-pep517
|
||||
pip install $(python test_dependencies.py) --use-pep517
|
||||
- name: Run pytest
|
||||
timeout-minutes: 60
|
||||
run: |
|
||||
|
|
|
|||
44
.github/workflows/update-readme.yml
vendored
Normal file
44
.github/workflows/update-readme.yml
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
name: Update README.md
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- ".github/update-readme.py"
|
||||
- "README.md"
|
||||
- ".github/workflows/update-readme.yml"
|
||||
- "custom_components/adaptive_lighting/const.py"
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
update_readme:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Home Assistant
|
||||
uses: ./.github/workflows/install_dependencies
|
||||
with:
|
||||
python_version: "3.10"
|
||||
|
||||
- name: Install pandas and tabulate
|
||||
run: |
|
||||
pip install pandas tabulate
|
||||
|
||||
- name: Run update-readme.py
|
||||
run: python ./.github/update-readme.py
|
||||
|
||||
- name: Commit updated README.md
|
||||
run: |
|
||||
git add README.md
|
||||
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git config --local user.name "github-actions[bot]"
|
||||
git diff --quiet && git diff --staged --quiet || git commit -m "Update README.md"
|
||||
|
||||
- name: Push changes
|
||||
uses: ad-m/github-push-action@master
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
branch: ${{ github.head_ref }}
|
||||
Loading…
Add table
Add a link
Reference in a new issue