summaryrefslogtreecommitdiff
path: root/lib/tasks/gitlab/update_templates.rake
blob: ef6a32d6730a642873b9d855075a549ff920b84d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
namespace :gitlab do
  desc "GitLab | Update templates"
  task :update_templates do
    TEMPLATE_DATA.each { |template| update(template) }
  end

  desc "GitLab | Update project templates"
  task :update_project_templates do
    include Gitlab::ImportExport::CommandLineUtil

    if Rails.env.production?
      puts "This rake task is not meant fo production instances".red
      exit(1)
    end

    admin = User.find_by(admin: true)

    unless admin
      puts "No admin user could be found".red
      exit(1)
    end

    Gitlab::ProjectTemplate.all.each do |template|
      params = {
        import_url: template.clone_url,
        namespace_id: admin.namespace.id,
        path: template.name,
        skip_wiki: true
      }

      puts "Creating project for #{template.title}"
      project = Projects::CreateService.new(admin, params).execute

      unless project.persisted?
        puts project.errors.messages
        exit(1)
      end

      loop do
        if project.finished?
          puts "Import finished for #{template.name}"
          break
        end

        if project.failed?
          puts "Failed to import from #{project_params[:import_url]}".red
          exit(1)
        end

        puts "Waiting for the import to finish"

        sleep(5)
        project.reload
      end

      Projects::ImportExport::ExportService.new(project, admin).execute
      download_or_copy_upload(project.export_file, template.archive_path)
      Projects::DestroyService.new(admin, project).execute
      puts "Exported #{template.name}".green
    end
    puts "Done".green
  end

  def update(template)
    sub_dir = template.repo_url.match(/([A-Za-z-]+)\.git\z/)[1]
    dir = File.join(vendor_directory, sub_dir)

    unless clone_repository(template.repo_url, dir)
      puts "Cloning the #{sub_dir} templates failed".red
      return
    end

    remove_unneeded_files(dir, template.cleanup_regex)
    puts "Done".green
  end

  def clone_repository(url, directory)
    FileUtils.rm_rf(directory) if Dir.exist?(directory)

    system("git clone #{url} --depth=1 --branch=master #{directory}")
  end

  # Retain only certain files:
  # - The LICENSE, because we have to
  # - The sub dirs so we can organise the file by category
  # - The templates themself
  # - Dir.entries returns also the entries '.' and '..'
  def remove_unneeded_files(directory, regex)
    Dir.foreach(directory) do |file|
      FileUtils.rm_rf(File.join(directory, file)) unless file =~ regex
    end
  end

  private

  Template = Struct.new(:repo_url, :cleanup_regex)
  TEMPLATE_DATA = [
    Template.new(
      "https://github.com/github/gitignore.git",
      /(\.{1,2}|LICENSE|Global|\.gitignore)\z/
    ),
    Template.new(
      "https://gitlab.com/gitlab-org/gitlab-ci-yml.git",
      /(\.{1,2}|LICENSE|CONTRIBUTING.md|Pages|autodeploy|\.gitlab-ci.yml)\z/
    ),
    Template.new(
      "https://gitlab.com/gitlab-org/Dockerfile.git",
      /(\.{1,2}|LICENSE|CONTRIBUTING.md|\.Dockerfile)\z/
    )
  ].freeze

  def vendor_directory
    Rails.root.join('vendor')
  end
end