#!/usr/bin/env python3 import os import xml.etree.ElementTree as ET import re from pathlib import Path import argparse import glob def parse_pom_xml(pom_path): """ Parse a pom.xml file and extract relevant information """ try: print(f"Parsing POM file: {pom_path}") # Register the default namespace ET.register_namespace('', "http://maven.apache.org/POM/4.0.0") # Parse the XML file tree = ET.parse(pom_path) root = tree.getroot() # Define namespace for easier XPath queries ns = {'mvn': "http://maven.apache.org/POM/4.0.0"} # Extract project info artifact_id = root.find('./mvn:artifactId', ns).text group_id = root.find('./mvn:groupId', ns).text if root.find('./mvn:groupId', ns) is not None else "unknown" version = root.find('./mvn:version', ns).text if root.find('./mvn:version', ns) is not None else "unknown" name = root.find('./mvn:name', ns).text if root.find('./mvn:name', ns) is not None else artifact_id # Extract Java version java_version_elem = root.find('./mvn:properties/mvn:java.version', ns) java_version = java_version_elem.text if java_version_elem is not None else "17" # Default to Java 17 if not specified # Extract packaging type (default to jar if not specified) packaging = root.find('./mvn:packaging', ns) packaging = packaging.text if packaging is not None else "jar" # Check if Kotlin is used kotlin_version_elem = root.find('./mvn:properties/mvn:kotlin.version', ns) kotlin_version = kotlin_version_elem.text if kotlin_version_elem is not None else None # Check for Kotlin plugin or dependency kotlin_plugin = None kotlin_dep = None # Check for Kotlin plugin plugins = root.findall('.//mvn:plugin', ns) for plugin in plugins: plugin_group = plugin.find('./mvn:groupId', ns) if plugin_group is not None and plugin_group.text == 'org.jetbrains.kotlin': kotlin_plugin = plugin break # Check for Kotlin dependency deps = root.findall('.//mvn:dependency', ns) for dep in deps: dep_group = dep.find('./mvn:groupId', ns) dep_artifact = dep.find('./mvn:artifactId', ns) if (dep_group is not None and dep_group.text == 'org.jetbrains.kotlin' and dep_artifact is not None and 'kotlin-stdlib' in dep_artifact.text): kotlin_dep = dep break # Determine if this is a Kotlin project is_kotlin = kotlin_version is not None or kotlin_plugin is not None or kotlin_dep is not None # Check for source directories source_dir = None source_dirs = root.findall('.//mvn:sourceDirectory', ns) if source_dirs: source_dir = source_dirs[0].text # Check for default goal (to use the same command as IntelliJ) default_goal = None default_goal_elem = root.find('./mvn:build/mvn:defaultGoal', ns) if default_goal_elem is not None: default_goal = default_goal_elem.text return { "artifact_id": artifact_id, "group_id": group_id, "version": version, "name": name, "java_version": java_version, "packaging": packaging, "is_kotlin": is_kotlin, "kotlin_version": kotlin_version, "source_dir": source_dir, "default_goal": default_goal, "pom_path": pom_path } except Exception as e: print(f"Error parsing {pom_path}: {e}") return None def generate_gitea_workflow(pom_infos): """ Generate a Gitea workflow YAML file based on multiple POM information """ if not pom_infos: print("No valid POM files found") return None # Get the highest Java version required java_version = max([info["java_version"] for info in pom_infos]) # Check if any project uses Kotlin uses_kotlin = any(info["is_kotlin"] for info in pom_infos) # Kotlin version (if any) kotlin_version = None for info in pom_infos: if info["kotlin_version"]: kotlin_version = info["kotlin_version"] break # Construct the workflow content workflow_content = f"""name: Maven Build on: push: branches: [ main, master, dev ] pull_request: branches: [ main, master ] workflow_dispatch: jobs: build: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up JDK {java_version} uses: actions/setup-java@v3 with: distribution: 'temurin' java-version: '{java_version}' cache: 'maven' - name: Install Maven run: | if ! command -v mvn &> /dev/null; then echo "Maven not found, installing..." sudo apt-get update sudo apt-get install -y maven fi mvn --version - name: Debug Info run: | echo "Current workspace directory: $GITHUB_WORKSPACE" echo "Current directory: $(pwd)" echo "Project structure:" find . -type f -name "*.kt" | sort find . -type f -name "pom.xml" echo "Maven version: $(mvn --version)" """ # Add individual build steps for each POM for i, info in enumerate(pom_infos): # Determine the Maven command to use (same as the default goal if specified) maven_command = "clean package" if info["default_goal"]: maven_command = info["default_goal"] workflow_content += f""" - name: Build {info["name"]} ({info["artifact_id"]}) run: | echo "Building {info["artifact_id"]}" echo "Current directory: $(pwd)" # Run Maven build directly using the POM file path mvn -B {maven_command} -f "$GITHUB_WORKSPACE/pom.xml" -Dmaven.compiler.failOnError=true """ # Add artifact upload step workflow_content += f""" - name: Upload {info["artifact_id"]} artifact uses: actions/upload-artifact@v3 with: name: {info["artifact_id"]} path: target/{info['artifact_id']}-*.jar if-no-files-found: error """ return workflow_content def find_pom_files(base_dir="."): """Find all pom.xml files in the given directory and subdirectories""" return glob.glob(f"{base_dir}/**/pom.xml", recursive=True) def main(): parser = argparse.ArgumentParser(description='Generate Gitea workflow for Maven/Kotlin projects') parser.add_argument('--dir', '-d', default='.', help='Base directory to search for pom.xml files') parser.add_argument('--specific-pom', '-p', help='Path to a specific pom.xml file to process') args = parser.parse_args() pom_files = [] if args.specific_pom: pom_files = [args.specific_pom] else: pom_files = find_pom_files(args.dir) if not pom_files: print(f"No pom.xml files found in {args.dir}") return print(f"Found {len(pom_files)} pom.xml files") # Parse all POM files pom_infos = [] for pom_file in pom_files: info = parse_pom_xml(pom_file) if info: pom_infos.append(info) if not pom_infos: print("No valid POM files could be parsed") return # Generate the workflow content workflow_content = generate_gitea_workflow(pom_infos) if not workflow_content: return # Create the .gitea/workflows directory if it doesn't exist workflow_dir = Path(".gitea/workflows") workflow_dir.mkdir(parents=True, exist_ok=True) # Write the workflow file workflow_file = workflow_dir / "maven_build.yaml" with open(workflow_file, "w") as f: f.write(workflow_content) print(f"Gitea workflow generated at: {workflow_file}") print(f"This workflow will build {len(pom_infos)} Maven projects") # Print summary of detected projects print("\nDetected projects:") for info in pom_infos: kotlin_info = "with Kotlin" if info["is_kotlin"] else "Java only" build_command = info["default_goal"] if info["default_goal"] else "clean package" print( f"- {info['name']} ({info['artifact_id']}): {kotlin_info}, Java {info['java_version']}, build: {build_command}") # Create a simple direct build script as fallback with open("build.sh", "w") as f: f.write("""#!/bin/bash # Direct build script for Maven project echo "Current directory: $(pwd)" echo "Building project with Maven..." # Run Maven build using the exact pom.xml location mvn clean package -f "$(pwd)/pom.xml" echo "Build complete. JAR file should be in target/ directory." """) # Make it executable os.chmod("build.sh", 0o755) print(f"Simple build script generated at: build.sh") if __name__ == "__main__": main()