require 'octokit' require 'json' require 'google/cloud/bigquery' class ReleaseMergeReport def initialize(token:, repo:, branch_prefix:) @token = token @repo = repo @branch_prefix = branch_prefix end def report branch_counts = count_merged_pull_requests_per_branch grouped_branch_counts = group_branch_counts(branch_counts) # require 'pry' # binding.pry # Print the grouped branch counts puts 'Branches with Merged Pull Requests:' grouped_branch_counts.each do |branch, count| puts "#{branch}: #{count}" end # ENV['BQ_CREDENTIALS'] = `cat /Users/serghei.moret/.config/gcloud/application_default_credentials.json` export_to_bigquery(grouped_branch_counts) if ENV['BQ_CREDENTIALS'] grouped_branch_counts end private def count_merged_pull_requests_per_branch client = Octokit::Client.new(access_token: @token) client.auto_paginate = true tags = client.tags(@repo) branch_info = Hash.new { |hash, key| hash[key] = { count: 0, teams: [], tribes: []} } tags.each do |tag| next if !tag.name.match?(/^(v23|v24)\./) && !tag.name.match?(/^(23|24)\./) # Extract release version from the tag name release_version = tag.name.gsub('v', '') # Construct branch name with the specified prefix branch_name = "#{@branch_prefix}#{release_version}" # Count merged pull requests associated with the branch pull_requests = client.pull_requests(@repo, state: 'closed', sort: 'updated', direction: 'desc', base: branch_name) .select { |pr| pr.merged_at } pull_requests.each do |pr| branch_info[branch_name][:count] += 1 # Extract team identifiers from the pull request labels teams = pr.labels.map { |label| label.name.match(/^squad:\s*(.*)$/i)&.captures }.compact.flatten tribes = pr.labels.map { |label| label.name.match(/^tribe:\s*(.*)$/i)&.captures }.compact.flatten branch_info[branch_name][:teams].push(teams) branch_info[branch_name][:tribes].push(tribes) end branch_info[branch_name][:count] = 0 if branch_info[branch_name].nil? end branch_info end def group_branch_counts(branch_info) patch_counts = Hash.new { |hash, key| hash[key] = { count: 0, teams: [], tribes: []} } hotfix_counts = Hash.new { |hash, key| hash[key] = { count: 0, teams: [], tribes: []} } branch_info.each do |branch, info| major_minor_version, patch_version = branch.match(/^#{@branch_prefix}(\d+\.\d+)(?:\.(\d+))?/)&.captures if patch_version.nil? # Branch is a patch version patch_counts[major_minor_version][:count] += info[:count] patch_counts[major_minor_version][:teams] += info[:teams] patch_counts[major_minor_version][:tribes] += info[:tribes] elsif info[:count] > 0 # Branch is a hotfix version hotfix_counts[major_minor_version][:count] += info[:count] hotfix_counts[major_minor_version][:teams] += info[:teams] hotfix_counts[major_minor_version][:tribes] += info[:tribes] end end # Sum up the counts for hotfix versions within the same major and minor version hotfix_counts.each do |major_minor_version, hotfix_info| hotfix_counts[major_minor_version][:count] = hotfix_info[:count] end { patch_versions: patch_counts, hotfix_versions: hotfix_counts } end def export_to_bigquery(branch_counts) require "google/cloud/bigquery" require "json" creds = JSON.parse(ENV['BQ_CREDENTIALS']) bigquery = Google::Cloud::Bigquery.new( project_id: "hellofresh-android", credentials: creds ) dataset = bigquery.dataset "github_data" date = DateTime.now branch_counts[:patch_versions].each do |branch, count| # Construct JSON string for teams teams_json = count[:teams].map { |team| "'#{team}'" }.join(',') tribes_json = count[:tribes].map { |tribes| "'#{tribes}'" }.join(',') # Construct the SQL query query = <<~SQL MERGE INTO release_merges AS target USING (SELECT '#{branch}' AS release, '#{@repo}' AS platform) AS source ON target.release = source.release AND target.platform = source.platform WHEN MATCHED THEN UPDATE SET target.merge_count = #{count[:count]}, target.timestamp = '#{date}', target.contributors = ARRAY[#{teams_json}], target.contributors_tribe = ARRAY[#{tribes_json}] WHEN NOT MATCHED THEN INSERT (release, merge_count, platform, timestamp, contributors, contributors_tribe) VALUES ('#{branch}', #{count[:count]}, '#{@repo}', '#{date}', ARRAY[#{teams_json}], ARRAY[#{tribes_json}]); SQL # Execute the query dataset.query(query) # Update the date date -= 7 end branch_counts[:hotfix_versions].each do |branch, count| # Construct JSON string for teams teams_json = count[:teams].map { |team| "'#{team}'" }.join(',') tribes_json = count[:tribes].map { |tribes| "'#{tribes}'" }.join(',') # Construct the SQL query query = <<~SQL MERGE INTO release_merges AS target USING (SELECT '#{branch}' AS release, '#{@repo}' AS platform) AS source ON target.release = source.release AND target.platform = source.platform WHEN MATCHED THEN UPDATE SET target.hotfix_count = #{count[:count]}, target.contributors_hotfixes = ARRAY[#{teams_json}], target.contributors_hotfixes_tribe = ARRAY[#{tribes_json}] WHEN NOT MATCHED THEN INSERT (release, hotfix_count, platform, contributors_hotfixes, contributors_hotfixes_tribe ) VALUES ('#{branch}', #{count[:count]}, '#{@repo}', ARRAY[#{teams_json}], ARRAY[#{tribes_json}]); SQL # Execute the query dataset.query(query) end end end