diff --git a/db/fixtures/development/09_issues.rb b/db/fixtures/development/09_issues.rb index 926401d8b9e..582a5203d1d 100644 --- a/db/fixtures/development/09_issues.rb +++ b/db/fixtures/development/09_issues.rb @@ -1,23 +1,5 @@ require './spec/support/sidekiq' Gitlab::Seeder.quiet do - Project.all.each do |project| - 10.times do - label_ids = project.labels.pluck(:id).sample(3) - label_ids += project.group.labels.sample(3) if project.group - - issue_params = { - title: FFaker::Lorem.sentence(6), - description: FFaker::Lorem.sentence, - state: ['opened', 'closed'].sample, - milestone: project.milestones.sample, - assignees: [project.team.users.sample], - created_at: rand(12).months.ago, - label_ids: label_ids - } - - Issues::CreateService.new(project, project.team.users.sample, issue_params).execute - print '.' - end - end + Rake::Task["gitlab:seed:issues"].invoke end diff --git a/doc/development/rake_tasks.md b/doc/development/rake_tasks.md index dcb32c89f65..1ae69127295 100644 --- a/doc/development/rake_tasks.md +++ b/doc/development/rake_tasks.md @@ -12,6 +12,22 @@ The `setup` task is an alias for `gitlab:setup`. This tasks calls `db:reset` to create the database, calls `add_limits_mysql` that adds limits to the database schema in case of a MySQL database and finally it calls `db:seed_fu` to seed the database. Note: `db:setup` calls `db:seed` but this does nothing. +### Seeding issues for all or a given project + +You can seed issues for all or a given project with the `gitlab:seed:issues` +task: + +```shell +# All projects +bin/rake gitlab:seed:issues + +# A specific project +bin/rake "gitlab:seed:issues[group-path/project-path]" +``` + +By default, this seeds an average of 2 issues per week for the last 5 weeks per +project. + ### Automation If you're very sure that you want to **wipe the current database** and refill diff --git a/lib/quality/seeders/issues.rb b/lib/quality/seeders/issues.rb new file mode 100644 index 00000000000..4c8cb6e97cc --- /dev/null +++ b/lib/quality/seeders/issues.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +# rubocop:disable CodeReuse/ActiveRecord +module Quality + module Seeders + class Issues + DEFAULT_BACKFILL_WEEKS = 52 + DEFAULT_AVERAGE_ISSUES_PER_WEEK = 10 + + attr_reader :project, :user + + def initialize(project:) + @project = project + end + + def seed(backfill_weeks: DEFAULT_BACKFILL_WEEKS, average_issues_per_week: DEFAULT_AVERAGE_ISSUES_PER_WEEK) + created_at = backfill_weeks.to_i.weeks.ago + team = project.team.users + created_issues_count = 0 + + loop do + rand(average_issues_per_week * 2).times do + params = { + title: FFaker::Lorem.sentence(6), + description: FFaker::Lorem.sentence, + created_at: created_at + rand(6).days, + state: %w[opened closed].sample, + milestone: project.milestones.sample, + assignee_ids: Array(team.pluck(:id).sample(3)), + labels: labels.join(',') + } + issue = ::Issues::CreateService.new(project, team.sample, params).execute + + if issue.persisted? + created_issues_count += 1 + print '.' # rubocop:disable Rails/Output + end + end + + created_at += 1.week + + break if created_at > Time.now + end + + created_issues_count + end + + private + + def labels + @labels_pool ||= project.labels.limit(rand(3)).pluck(:title).tap do |labels_array| + labels_array.concat(project.group.labels.limit(rand(3)).pluck(:title)) if project.group + end + end + end + end +end +# rubocop:enable CodeReuse/ActiveRecord diff --git a/lib/tasks/gitlab/seed.rake b/lib/tasks/gitlab/seed.rake new file mode 100644 index 00000000000..155ba979b36 --- /dev/null +++ b/lib/tasks/gitlab/seed.rake @@ -0,0 +1,34 @@ +namespace :gitlab do + namespace :seed do + desc "GitLab | Seed | Seeds issues" + task :issues, [:project_full_path] => :environment do |t, args| + projects = + if args.project_full_path + project = Project.find_by_full_path(args.project_full_path) + + unless project + error_message = "Project '#{args.project_full_path}' does not exist!" + potential_projects = Project.search(args.project_full_path) + + if potential_projects.present? + error_message += " Did you mean '#{potential_projects.first.full_path}'?" + end + + puts error_message.color(:red) + exit 1 + end + + [project] + else + Project.find_each + end + + projects.each do |project| + puts "\nSeeding issues for the '#{project.full_path}' project" + seeder = Quality::Seeders::Issues.new(project: project) + issues_created = seeder.seed(backfill_weeks: 5, average_issues_per_week: 2) + puts "\n#{issues_created} issues created!" + end + end + end +end diff --git a/spec/lib/quality/seeders/issues_spec.rb b/spec/lib/quality/seeders/issues_spec.rb new file mode 100644 index 00000000000..e17414a541a --- /dev/null +++ b/spec/lib/quality/seeders/issues_spec.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Quality::Seeders::Issues do + let(:project) { create(:project) } + + subject { described_class.new(project: project) } + + describe '#seed' do + it 'seeds issues' do + issues_created = subject.seed(backfill_weeks: 1, average_issues_per_week: 1) + + expect(issues_created).to be_between(0, 2) + expect(project.issues.count).to eq(issues_created) + end + end +end