diff --git a/.github/scripts/check_duplicates.py b/.github/scripts/check_duplicates.py new file mode 100644 index 00000000..9c919414 --- /dev/null +++ b/.github/scripts/check_duplicates.py @@ -0,0 +1,51 @@ +import sys + + +def find_duplicate_keys(file_path): + """ + Finds duplicate keys in a properties file and returns their occurrences. + + This function reads a properties file, identifies any keys that occur more than + once, and returns a dictionary with these keys and the line numbers of their occurrences. + + Parameters: + file_path (str): The path to the properties file to be checked. + + Returns: + dict: A dictionary where each key is a duplicated key in the file, and the value is a list + of line numbers where the key occurs. + """ + with open(file_path, "r", encoding="utf-8") as file: + lines = file.readlines() + + keys = {} + duplicates = {} + + for line_number, line in enumerate(lines, start=1): + line = line.strip() + if line and not line.startswith("#") and "=" in line: + key = line.split("=", 1)[0].strip() + if key in keys: + # If the key already exists, add the current line number + duplicates.setdefault(key, []).append(line_number) + # Also add the first instance of the key if not already done + if keys[key] not in duplicates[key]: + duplicates[key].insert(0, keys[key]) + else: + # Store the line number of the first instance of the key + keys[key] = line_number + + return duplicates + + +if __name__ == "__main__": + failed = False + for ar in sys.argv[1:]: + duplicates = find_duplicate_keys(ar) + if duplicates: + for key, lines in duplicates.items(): + lines_str = ", ".join(map(str, lines)) + print(f"{key} duplicated in {ar} on lines {lines_str}") + failed = True + if failed: + sys.exit(1) diff --git a/.github/scripts/check_tabulator.py b/.github/scripts/check_tabulator.py new file mode 100644 index 00000000..eb408ad6 --- /dev/null +++ b/.github/scripts/check_tabulator.py @@ -0,0 +1,84 @@ +"""check_tabulator.py""" +import argparse +import sys + + +def check_tabs(file_path): + """ + Checks for tabs in the specified file. + + Args: + file_path (str): The path to the file to be checked. + + Returns: + bool: True if tabs are found, False otherwise. + """ + with open(file_path, "r", encoding="utf-8") as file: + content = file.read() + + if "\t" in content: + print(f"Tab found in {file_path}") + return True + return False + + +def replace_tabs_with_spaces(file_path, replace_with=" "): + """ + Replaces tabs with a specified number of spaces in the file. + + Args: + file_path (str): The path to the file where tabs will be replaced. + replace_with (str): The character(s) to replace tabs with. Defaults to two spaces. + """ + with open(file_path, "r", encoding="utf-8") as file: + content = file.read() + + updated_content = content.replace("\t", replace_with) + + with open(file_path, "w", encoding="utf-8") as file: + file.write(updated_content) + + +def main(): + """ + Main function to replace tabs with spaces in the provided files. + The replacement character and files to check are taken from command line arguments. + """ + # Create ArgumentParser instance + parser = argparse.ArgumentParser( + description="Replace tabs in files with specified characters." + ) + + # Define optional argument `--replace_with` + parser.add_argument( + "--replace_with", + default=" ", + help="Character(s) to replace tabs with. Default is two spaces.", + ) + + # Define argument for file paths + parser.add_argument("files", metavar="FILE", nargs="+", help="Files to process.") + + # Parse arguments + args = parser.parse_args() + + # Extract replacement characters and files from the parsed arguments + replace_with = args.replace_with + files_checked = args.files + + error = False + + for file_path in files_checked: + if check_tabs(file_path): + replace_tabs_with_spaces(file_path, replace_with) + error = True + + if error: + print("Error: Originally found tabs in HTML files, now replaced.") + sys.exit(1) + + sys.exit(0) + + +if __name__ == "__main__": + main() diff --git a/.github/scripts/gradle_to_chart.py b/.github/scripts/gradle_to_chart.py new file mode 100644 index 00000000..4d7a667f --- /dev/null +++ b/.github/scripts/gradle_to_chart.py @@ -0,0 +1,67 @@ +import re +import yaml + +# Paths to the files +chart_yaml_path = "chart/stirling-pdf/Chart.yaml" +gradle_path = "build.gradle" + + +def get_chart_version(path): + """ + Reads the appVersion from Chart.yaml. + + Args: + path (str): The file path to the Chart.yaml. + + Returns: + str: The appVersion if found, otherwise an empty string. + """ + with open(path, encoding="utf-8") as file: + chart_yaml = yaml.safe_load(file) + return chart_yaml.get("appVersion", "") + + +def get_gradle_version(path): + """ + Extracts the version from build.gradle. + + Args: + path (str): The file path to the build.gradle. + + Returns: + str: The version if found, otherwise an empty string. + """ + with open(path, encoding="utf-8") as file: + for line in file: + if "version =" in line: + # Extracts the value after 'version =' + return re.search(r'version\s*=\s*[\'"](.+?)[\'"]', line).group(1) + return "" + + +def update_chart_version(path, new_version): + """ + Updates the appVersion in Chart.yaml with a new version. + + Args: + path (str): The file path to the Chart.yaml. + new_version (str): The new version to update to. + """ + with open(path, encoding="utf-8") as file: + chart_yaml = yaml.safe_load(file) + chart_yaml["appVersion"] = new_version + with open(path, "w", encoding="utf-8") as file: + yaml.safe_dump(chart_yaml, file) + + +# Main logic +chart_version = get_chart_version(chart_yaml_path) +gradle_version = get_gradle_version(gradle_path) + +if chart_version != gradle_version: + print( + f"Versions do not match. Updating Chart.yaml from {chart_version} to {gradle_version}." + ) + update_chart_version(chart_yaml_path, gradle_version) +else: + print("Versions match. No update required.") diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 74d1f8f5..9dd64aca 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,8 +3,14 @@ name: "Build repo" on: push: branches: [ "main" ] + paths-ignore: + - ".github/**" + - "**/*.md" pull_request: branches: [ "main" ] + paths-ignore: + - ".github/**" + - "**/*.md" jobs: build: diff --git a/.github/workflows/push-docker.yml b/.github/workflows/push-docker.yml index 6dff5cbb..f415e292 100644 --- a/.github/workflows/push-docker.yml +++ b/.github/workflows/push-docker.yml @@ -6,6 +6,10 @@ on: branches: - master - main + paths-ignore: + - ".github/**" + - "**/*.md" + permissions: contents: read packages: write diff --git a/.github/workflows/swagger.yml b/.github/workflows/swagger.yml index 60c7aa1d..3ac41119 100644 --- a/.github/workflows/swagger.yml +++ b/.github/workflows/swagger.yml @@ -5,6 +5,9 @@ on: push: branches: - master + paths-ignore: + - ".github/**" + - "**/*.md" jobs: push: diff --git a/.github/workflows/sync_versions.yml b/.github/workflows/sync_versions.yml new file mode 100644 index 00000000..dce4b4b4 --- /dev/null +++ b/.github/workflows/sync_versions.yml @@ -0,0 +1,51 @@ +name: Sync Versions + +on: + push: + branches: + - main + paths: + - "build.gradle" + +permissions: + contents: write + pull-requests: write + +jobs: + sync-versions: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4.1.1 + - name: Set up Python + uses: actions/setup-python@v5.0.0 + with: + python-version: '3.x' + - name: Install dependencies + run: pip install pyyaml + - name: Sync versions + run: python .github/scripts/gradle_to_chart.py + - name: Set up git config + run: | + git config --global user.email "GitHub Action " + git config --global user.name "GitHub Action " + - name: Run git add + run: | + git add . + git diff --staged --quiet || git commit -m ":floppy_disk: Sync Versions + > Made via sync_versions.yml" || echo "no changes" + - name: Create Pull Request + uses: peter-evans/create-pull-request@v6.0.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: Update files + committer: GitHub Action + author: GitHub Action + signoff: true + branch: sync_version + title: ":floppy_disk: Update Version" + body: | + Auto-generated by [create-pull-request][1] + + [1]: https://github.com/peter-evans/create-pull-request + draft: false + delete-branch: true diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..e397fc5d --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,37 @@ +repos: + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.2.1 + hooks: + - id: ruff + args: + - --fix + - --line-length=127 + files: ^((.github/scripts)/.+)?[^/]+\.py$ + - id: ruff-format + files: ^((.github/scripts)/.+)?[^/]+\.py$ + - repo: https://github.com/codespell-project/codespell + rev: v2.2.6 + hooks: + - id: codespell + args: + - --ignore-words-list= + - --skip="./.*,*.csv,*.json,*.ambr" + - --quiet-level=2 + files: \.(properties|html|css|js|py|md)$ + exclude: (.vscode|.devcontainer|src/main/resources|Dockerfile) + - repo: local + hooks: + - id: check-duplicate-properties-keys + name: Check Duplicate Properties Keys + entry: python .github/scripts/check_duplicates.py + language: python + files: ^(src)/.+\.properties$ + - repo: local + hooks: + - id: check-html-tabs + name: Check HTML for tabs + # args: ["--replace_with= "] + entry: python .github/scripts/check_tabulator.py + language: python + exclude: ^src/main/resources/static/pdfjs/ + files: ^.*(\.html|\.css|\.js)$