From 17db1aa90026b71974447239f26fc62eeda5c967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Schneider?= <56670304+soerenschneider@users.noreply.github.com> Date: Mon, 13 Jan 2025 14:22:09 +0100 Subject: [PATCH] validate makefile targets --- .github/workflows/validate-makefile.yaml | 25 ++++++++++++ scripts/requirements.txt | 1 + scripts/validate-makefile-targets.py | 49 ++++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 .github/workflows/validate-makefile.yaml create mode 100644 scripts/requirements.txt create mode 100644 scripts/validate-makefile-targets.py diff --git a/.github/workflows/validate-makefile.yaml b/.github/workflows/validate-makefile.yaml new file mode 100644 index 0000000..dc5b073 --- /dev/null +++ b/.github/workflows/validate-makefile.yaml @@ -0,0 +1,25 @@ +--- +name: Validate Makefile targets + +on: + push: {} + pull_request: {} + +jobs: + validate-makefile: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: '3.13' + cache: 'pip' + + - name: "Install dependencies" + run: pip install -r scripts/requirements.txt + + - name: Validate Makefile targets + run: python scripts/validate-makefile-targets.py diff --git a/scripts/requirements.txt b/scripts/requirements.txt new file mode 100644 index 0000000..07f4c7c --- /dev/null +++ b/scripts/requirements.txt @@ -0,0 +1 @@ +markdown-it-py==3.0.0 diff --git a/scripts/validate-makefile-targets.py b/scripts/validate-makefile-targets.py new file mode 100644 index 0000000..1291e50 --- /dev/null +++ b/scripts/validate-makefile-targets.py @@ -0,0 +1,49 @@ +import subprocess +import sys + +from markdown_it import MarkdownIt + +def run_make_target(target: str) -> bool: + """Reads the content of a markdown file.""" + try: + _ = subprocess.run(['make', '-n', target], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + print(f"Make command for target '{target}' completed successfully.") + return True + except subprocess.CalledProcessError as e: + print(f"Make command for target '{target}' failed.") + return False + +def read_markdown_file(filename: str): + """Reads the content of a markdown file.""" + with open(filename, 'r') as file: + return file.read() + +def extract_shell_code_blocks(markdown_text: str) -> None: + """Extracts 'shell' code blocks from the given markdown text.""" + md = MarkdownIt() + tokens = md.parse(markdown_text) + + valid_targets = True + for token in tokens: + if token.type == 'fence' and token.info == 'shell': + if not check_code_block(token.content.strip()): + valid_targets = False + return valid_targets + +def check_code_block(code: str) -> bool: + """Checks for each line of the codeblock if it is a make command. For each found make command, a check is performed.""" + targets_valid = True + for line in code.splitlines(): + if line.strip().startswith("make "): + if not run_make_target(line.strip()[5:]): + targets_valid = False + return targets_valid + +def main() -> None: + markdown_text = read_markdown_file('README.md') + if not extract_shell_code_blocks(markdown_text): + sys.exit(1) + +# Run the program +if __name__ == "__main__": + main()