create_issues.rb (159 lines of code) (raw):
require 'gitlab'
require 'yaml'
require 'erb'
require 'date'
require_relative 'fiscal_date_helper'
require_relative 'milestone_helper'
dry_run = false
today = Date.today
project_id = ENV['CI_PROJECT_ID']
api_token = ENV['GITLAB_API_PRIVATE_TOKEN']
class IssueCreator
def initialize(today)
@today = today
end
def run(api_token, project_id)
connect(api_token)
puts 'Loading content from config/issues.yml'
@issues = YAML.load(ERB.new(File.read('config/issues.yml')).result)
puts 'Content loaded successfully.'
puts 'Walking issues to create...'
@issues['issues'].each do |issue|
if issue['day_of_month']
## Using Day of Month Value
today_date = @today.strftime('%-d')
if today_date == issue['day_of_month'].to_s
puts '* ' << issue['name'] << ' should be created on the ' << issue['day_of_month'].to_s << ' day of the month.'
puts '** Today is the ' << today_date
create(issue['name'], issue['template'], issue['scope'], "Monthly", project_id)
end
end
if issue['day_of_week']
## Using Day of week value
today_day = @today.strftime('%a')
if today_day == issue['day_of_week'].to_s
puts '* ' << issue['name'] << ' should be created every ' << issue['day_of_week'].to_s << '.'
puts '** Today is ' << today_day
create(issue['name'], issue['template'], issue['scope'], 'Weekly', project_id)
end
end
if issue['quarterly']
## Using Quarterly
fiscal_quarter_start = %w[02 05 08 11]
fiscal_quarter_end = %w[04 07 10 01]
month = @today.strftime('%m')
today_date = @today.strftime('%d')
# First Day of Quarter
if issue['quarterly'] == 'first_day_of_quarter' && today_date == '01' && (fiscal_quarter_start.include? month)
create(issue['name'], issue['template'], issue['scope'], 'Quarterly', project_id)
end
# Last Day of Quarter
if issue['quarterly'] == 'last_day_of_quarter' && today_date == '28' && (fiscal_quarter_end.include? month)
create(issue['name'], issue['template'], issue['scope'], 'Quarterly', project_id)
end
# First Day of Last Month of Quarter
if issue['quarterly'] == 'first_day_of_last_month_of_quarter' && today_date == '01' && (fiscal_quarter_end.include? month)
create(issue['name'], issue['template'], issue['scope'], 'Quarterly', project_id)
end
end
if issue['day_of_year']
## Using Yearly
days = Array(issue['day_of_year'])
if days.include? @today.yday
create(issue['name'], issue['template'], issue['scope'], issue['frequency'] || 'Yearly', project_id)
end
end
end
puts 'Run Complete.'
end
def connect(api_token)
puts 'Connecting to GitLab...'
@gitlab = Gitlab.client(
endpoint: 'https://gitlab.com/api/v4',
private_token: api_token
)
@user = @gitlab.user
puts 'Connection successful. Connected user email: ' << @user.email
end
def upcoming_milestone
@upcoming_milestone ||= MilestoneHelper.upcoming_milestone
@upcoming_milestone
end
def previous_milestone
@previous_milestone ||= MilestoneHelper.previous_milestone
@previous_milestone
end
# replace keywords MILESTONE and PREVIOUS_MILESTONE in a string for a numeric value
def replace_milestone(text = "")
text = text.gsub('<MILESTONE>', upcoming_milestone)
text = text.gsub('<PREVIOUS_MILESTONE>', previous_milestone)
text
end
def create(name, template_name, scope, frequency, project_id)
frequency_text = ''
case frequency
when 'Monthly'
frequency_text = Date::MONTHNAMES[@today.month]
when 'Weekly'
frequency_text = 'Week ' + @today.cweek.to_s
when 'Quarterly'
frequency_text = 'Quarterly'
when 'Yearly'
frequency_text = 'Yearly'
when 'Biannually'
frequency_text = 'Biannually'
end
if scope == 'all'
## implies we don't need to use an ERB template just regular issue templates
template = File.open('.gitlab/issue_templates/' << template_name).read
puts '** Template loaded...'
description = ERB.new(template, 0, '>').result(binding)
puts '** Description generated...'
description = replace_milestone(description)
issue_title = replace_milestone(name)
puts '** Milestone keywords replaced...'
@gitlab.create_issue(project_id, issue_title + ' : ' + frequency_text, { description: description, assignee_id: @user.id })
puts '** ' << issue_title << ' issue created.'
end
end
end
# Mock GitLab user and service
class UserMock
def initialize
@email = 'mockuser@gitlab.com'
@id = 1234
end
attr_accessor :email, :id
end
class GitLabMock
def initialize
@user = UserMock.new()
end
def create_issue(project, title, options)
puts 'Would have created issue:'
puts ' Project: ' + project
puts ' Title: ' + title
puts ' Content: \n' + options[:description] + '\n\n'
end
attr_accessor :user
end
# Override issue creator to use GitLab mock
class IssueCreatorTest < IssueCreator
def connect(api_token)
puts 'Connecting to GitLab...'
@gitlab = GitLabMock.new()
@user = @gitlab.user
puts 'Connection successful. Connected user email: ' << @user.email
end
end
if $PROGRAM_NAME == __FILE__
# Override with mock if we are doing a dry run
ARGV.each do |arg|
if arg == '--dry-run'
dry_run = true
api_token = 'mocktoken'
project_id = 'mockproject'
(1..12).each do |m|
# Simulate every month of the year
(1..28).each do |d|
# Simulate every day of the month
# No day_of_month in issues.yml are after the 28th which makes it simple
# to not trigger an invalid date here in this dry-run test.
today = Date::strptime(d.to_s + '-' + m.to_s + '-2020', '%d-%m-%Y')
if today
issue_creator = IssueCreatorTest.new(today)
issue_creator.run(api_token, project_id)
end
end
end
end
end
unless dry_run
issue_creator = IssueCreator.new(today)
issue_creator.run(api_token, project_id)
end
end