import datetime import gitlab import smtplib import shutil import os from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart import subprocess import requests from dotenv import load_dotenv def check_binaries(): required_binaries = ['df', 'gitlab-ctl'] missing_binaries = [binary for binary in required_binaries if not shutil.which(binary)] if missing_binaries: print(f"Error: The following binaries are missing: {', '.join(missing_binaries)}") print("Please ensure they are installed and available in the system's PATH.") exit(1) def load_api_token(): load_dotenv() # Load environment variables from .env file api_token = os.getenv('GITLAB_API_TOKEN') if not api_token: print("Error: Gitlab API token not found in .env file.") exit(1) confluence_token = os.getenv('CONFLUENCE_API_TOKEN') if not confluence_token: print("Error: Confluence API token not found in .env file.") exit(1) gitlab_url = os.getenv('GITLAB_URL') if not gitlab_url: print("Error: Gitlab URL not found in .env file.") exit(1) sender_mail = os.getenv('SENDER_MAIL') if not sender_mail: print("Error: Sender email address not found in .env file.") exit(1) recipient_email = os.getenv('RECIPIENT_MAIL') if not recipient_email: print("Error: Recipient email address not found in .env file.") exit(1) return api_token, confluence_token, gitlab_url, sender_mail, recipient_email def get_disk_space(): # Run the df command to get disk space information result = subprocess.run(['df', '-h'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) # Extract the output and parse the relevant information output_lines = result.stdout.strip().split('\n') # Find the line containing '/data' data_line = None for line in output_lines: if '/data' in line: data_line = line break if data_line is None: print("Error: /data not found in the 'df' output.") return None data_info = data_line.split() # Extract the available space (Avail) and percentage (Use%) for /data free_space_on_data = data_info[3] data_percentage = data_info[4] return f"{free_space_on_data} ({data_percentage})" def get_total_commits_last_month(gl): # Calculate the date range for the last month current_date = datetime.datetime.now() last_month_start = (current_date.replace(day=1) - datetime.timedelta(days=1)).replace(day=1) last_month_end = current_date.replace(day=1) - datetime.timedelta(days=1) # Get the total commits last month total_commits_last_month = 0 projects = gl.projects.list(all=True) for project in projects: try: commits = project.commits.list(since=last_month_start, until=last_month_end) total_commits_last_month += len(commits) except gitlab.exceptions.GitlabListError as e: if e.response_code == 404: # Repository not found for the project print(f"Warning: Repository not found for project '{project.name}'") else: # Other GitLab API error print(f"Error: GitLab API error for project '{project.name}': {e}") return total_commits_last_month def get_gitlab_version(): # Run 'gitlab-ctl' command to get GitLab version result = subprocess.run(['grep', 'gitlab-ee', '/opt/gitlab/version-manifest.txt'],stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) # Extract GitLab version from the output gitlab_version = result.stdout.strip() return gitlab_version def get_gitlab_info(api_token): # Replace 'YOUR_GITLAB_URL' and 'YOUR_PRIVATE_TOKEN' with your GitLab URL and private token print("Auth against "+gitlab_url) gl = gitlab.Gitlab(gitlab_url, api_token) gl.auth() print("Auth successful") # Get the number of projects projects = gl.projects.list(all=True) num_projects = len(projects) print(f"Number of projects: {num_projects}") # Get the number of users users = gl.users.list(all=True) num_users = len(users) print(f"Number of users: {num_users}") # Get a list of admin users admin_users = [user for user in users if hasattr(user, 'is_admin') and user.is_admin] admin_users_list = [user.name for user in admin_users] print(f"Number of Admin-Users: {len(admin_users_list)}") # Get free space on disk free_space_on_disk = get_disk_space() print(f"Free space on disk: {free_space_on_disk}") # Get the total commits last month total_commits_last_month = get_total_commits_last_month(gl) print(f"Total commits last month: {total_commits_last_month}") # Get GitLab version gitlab_version = get_gitlab_version() print(f"GitLab version: {gitlab_version}") return num_projects, num_users, admin_users_list, free_space_on_disk, total_commits_last_month, gitlab_version def send_email(sender_email, recipient_email, subject, body): # Create the email body in HTML format msg = MIMEMultipart('alternative') msg['From'] = sender_email msg['To'] = recipient_email msg['Subject'] = subject # Create a nice HTML table for the report html_table = f''' <html> <head></head> <body> <h2>Monthly GitLab Report - {datetime.datetime.now().strftime('%B %Y')}</h2> <p>Version: {body['gitlab_version']}</p> <table border="1" cellpadding="5" style="border-collapse: collapse; width: 100%;"> <tr> <th>Metrics</th> <th>Values</th> </tr> <tr> <td>Number of Projects</td> <td>{body['num_projects']}</td> </tr> <tr> <td>Number of Users</td> <td>{body['num_users']}</td> </tr> <tr> <td>List of Admin Users</td> <td> <ul> {"".join(f"<li>{admin_user}</li>" for admin_user in body['admin_users_list'])} </ul> </td> </tr> <tr> <td>Free Space on Disk</td> <td>{body['free_space_on_disk']}</td> </tr> <tr> <td>Total Commits last Month</td> <td>{body['total_commits_last_month']}</td> </tr> </table> </body> </html> ''' # Attach the HTML content to the email msg.attach(MIMEText(html_table, 'html')) with smtplib.SMTP('localhost') as server: server.sendmail(sender_email, recipient_email, msg.as_string()) def create_blog_post(confluence_url, api_token, blog_post_content): headers = { "Authorization": f"Bearer {api_token}", "Content-Type": "application/json" } blog_post_content = { "type": "blogpost", "title": "Monthly GitLab Report", "space": { "key": "SPACE_KEY" # Replace with the key of the space where you want to create the blog post }, "body": { "storage": { "value": "<h2>Monthly GitLab Report</h2><p>This is your blog post content in HTML format.</p>", "representation": "storage" } } } # Make a POST request to create the blog post response = requests.post( f"{confluence_url}/rest/api/content", headers=headers, json=blog_post_content ) if response.status_code == 200: print("Blog post created successfully!") return response.json().get("id") else: print("Failed to create the blog post.") print(f"Status code: {response.status_code}") print(f"Response: {response.text}") return None # Check if required binaries are available check_binaries() api_token, confluence_token, gitlab_url, sender_email, recipient_email = load_api_token() subject = '[gitlab.ard.de] Monthly Report - {month} {year}'.format(month=datetime.datetime.now().strftime('%B'), year=datetime.datetime.now().strftime('%Y')) # Get GitLab information num_projects, num_users, admin_users_list, free_space_on_disk, total_commits_last_month, gitlab_version = get_gitlab_info(api_token) # Compose the email body as a dictionary email_body = { 'num_projects': num_projects, 'num_users': num_users, 'admin_users_list': admin_users_list, 'free_space_on_disk': free_space_on_disk, 'total_commits_last_month': total_commits_last_month, 'gitlab_version': gitlab_version } # Send the email send_email(sender_email, recipient_email, subject, email_body) # create blog post # blog_post_id = create_blog_post(confluence_url, api_token, email_body)