diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js index 81c1e01901e9d52b5f4cf01e17c2572d51b58c27..f60f27d1210937aa5a3c405b839b80dfe9dfc2ef 100644 --- a/app/assets/javascripts/api.js +++ b/app/assets/javascripts/api.js @@ -11,6 +11,7 @@ licensePath: "/api/:version/templates/licenses/:key", gitignorePath: "/api/:version/templates/gitignores/:key", gitlabCiYmlPath: "/api/:version/templates/gitlab_ci_ymls/:key", + dockerfilePath: "/api/:version/dockerfiles/:key", issuableTemplatePath: "/:namespace_path/:project_path/templates/:type/:key", group: function(group_id, callback) { var url = Api.buildUrl(Api.groupPath) @@ -120,6 +121,10 @@ return callback(file); }); }, + dockerfileYml: function(key, callback) { + var url = Api.buildUrl(Api.dockerfilePath).replace(':key', key); + $.get(url, callback); + }, issueTemplate: function(namespacePath, projectPath, key, type, callback) { var url = Api.buildUrl(Api.issuableTemplatePath) .replace(':key', key) diff --git a/app/assets/javascripts/blob/blob_dockerfile_selector.js.es6 b/app/assets/javascripts/blob/blob_dockerfile_selector.js.es6 new file mode 100644 index 0000000000000000000000000000000000000000..bdf9501761366aaf3c297a2b5f68059ca4abcf16 --- /dev/null +++ b/app/assets/javascripts/blob/blob_dockerfile_selector.js.es6 @@ -0,0 +1,18 @@ +/* global Api */ +/*= require blob/template_selector */ + +(() => { + const global = window.gl || (window.gl = {}); + + class BlobDockerfileSelector extends gl.TemplateSelector { + requestFile(query) { + return Api.dockerfileYml(query.name, this.requestFileSuccess.bind(this)); + } + + requestFileSuccess(file) { + return super.requestFileSuccess(file); + } + } + + global.BlobDockerfileSelector = BlobDockerfileSelector; +})(); diff --git a/app/assets/javascripts/blob/blob_dockerfile_selectors.js.es6 b/app/assets/javascripts/blob/blob_dockerfile_selectors.js.es6 new file mode 100644 index 0000000000000000000000000000000000000000..9cee79fa5d56756846ab5c01cbe46f33d1e887f7 --- /dev/null +++ b/app/assets/javascripts/blob/blob_dockerfile_selectors.js.es6 @@ -0,0 +1,27 @@ +(() => { + const global = window.gl || (window.gl = {}); + + class BlobDockerfileSelectors { + constructor({ editor, $dropdowns } = {}) { + this.editor = editor; + this.$dropdowns = $dropdowns || $('.js-dockerfile-selector'); + this.initSelectors(); + } + + initSelectors() { + const editor = this.editor; + this.$dropdowns.each((i, dropdown) => { + const $dropdown = $(dropdown); + return new gl.BlobDockerfileSelector({ + editor, + pattern: /(Dockerfile)/, + data: $dropdown.data('data'), + wrapper: $dropdown.closest('.js-dockerfile-selector-wrap'), + dropdown: $dropdown, + }); + }); + } + } + + global.BlobDockerfileSelectors = BlobDockerfileSelectors; +})(); diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js index b528e32340dc15fa14aa4783f364b759d28d5a44..fa43ff611ccbb566abf20d26b16015a7d5502ebf 100644 --- a/app/assets/javascripts/blob_edit/edit_blob.js +++ b/app/assets/javascripts/blob_edit/edit_blob.js @@ -36,6 +36,9 @@ new gl.BlobCiYamlSelectors({ editor: this.editor }); + new gl.BlobDockerfileSelectors({ + editor: this.editor + }); } EditBlob.prototype.initModePanesAndLinks = function() { diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss index 3fdb4f510fa2e621a94c28c328dac6bb885a7a53..4af267403d8841c77af6b1a5bc55d778be399d18 100644 --- a/app/assets/stylesheets/pages/editor.scss +++ b/app/assets/stylesheets/pages/editor.scss @@ -75,7 +75,8 @@ .soft-wrap-toggle, .license-selector, .gitignore-selector, - .gitlab-ci-yml-selector { + .gitlab-ci-yml-selector, + .dockerfile-selector { display: inline-block; vertical-align: top; font-family: $regular_font; @@ -105,7 +106,8 @@ .gitignore-selector, .license-selector, - .gitlab-ci-yml-selector { + .gitlab-ci-yml-selector, + .dockerfile-selector { .dropdown { line-height: 21px; } diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index 07ff6fb94889c58503a881861c64f31d3a18f805..f31d4fb897d3a237879a06c34726d3b44e1c6514 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -191,6 +191,10 @@ module BlobHelper @gitlab_ci_ymls ||= Gitlab::Template::GitlabCiYmlTemplate.dropdown_names end + def dockerfile_names + @dockerfile_names ||= Gitlab::Template::DockerfileTemplate.dropdown_names + end + def blob_editor_paths { 'relative-url-root' => Rails.application.config.relative_url_root, diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml index 4a6aa92e3f3db04685091e0882c416a59e2a3ac2..1d058daa0943301b6766f53a45f3b90d4a5c994f 100644 --- a/app/views/projects/blob/_editor.html.haml +++ b/app/views/projects/blob/_editor.html.haml @@ -21,6 +21,8 @@ = dropdown_tag("Choose a .gitignore template", options: { toggle_class: 'btn js-gitignore-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: gitignore_names } } ) .gitlab-ci-yml-selector.js-gitlab-ci-yml-selector-wrap.hidden = dropdown_tag("Choose a GitLab CI Yaml template", options: { toggle_class: 'btn js-gitlab-ci-yml-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: gitlab_ci_ymls } } ) + .dockerfile-selector.js-dockerfile-selector-wrap.hidden + = dropdown_tag("Choose a Dockerfile template", options: { toggle_class: 'btn js-dockerfile-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: dockerfile_names } } ) = button_tag class: 'soft-wrap-toggle btn', type: 'button' do %span.no-wrap = custom_icon('icon_no_wrap') diff --git a/changelogs/unreleased/dockerfile-templates.yml b/changelogs/unreleased/dockerfile-templates.yml new file mode 100644 index 0000000000000000000000000000000000000000..e4db46cdf9ac8b991ec0780e4aa6620c0f53855b --- /dev/null +++ b/changelogs/unreleased/dockerfile-templates.yml @@ -0,0 +1,4 @@ +--- +title: Add support for Dockerfile templates +merge_request: 7247 +author: diff --git a/lib/api/templates.rb b/lib/api/templates.rb index 8a53d9c0095d5355224bb19e40ce174b734b49f4..e23f99256a59e2fea3a74a1ae4c61438bab9ccce 100644 --- a/lib/api/templates.rb +++ b/lib/api/templates.rb @@ -8,6 +8,10 @@ module API gitlab_ci_ymls: { klass: Gitlab::Template::GitlabCiYmlTemplate, gitlab_version: 8.9 + }, + dockerfiles: { + klass: Gitlab::Template::DockerfileTemplate, + gitlab_version: 8.15 } }.freeze PROJECT_TEMPLATE_REGEX = @@ -51,7 +55,7 @@ module API end params do optional :popular, type: Boolean, desc: 'If passed, returns only popular licenses' - end + end get route do options = { featured: declared(params).popular.present? ? true : nil @@ -69,7 +73,7 @@ module API end params do requires :name, type: String, desc: 'The name of the template' - end + end get route, requirements: { name: /[\w\.-]+/ } do not_found!('License') unless Licensee::License.find(declared(params).name) @@ -78,7 +82,7 @@ module API present template, with: Entities::RepoLicense end end - + GLOBAL_TEMPLATE_TYPES.each do |template_type, properties| klass = properties[:klass] gitlab_version = properties[:gitlab_version] @@ -104,7 +108,7 @@ module API end params do requires :name, type: String, desc: 'The name of the template' - end + end get route do new_template = klass.find(declared(params).name) diff --git a/lib/gitlab/template/dockerfile_template.rb b/lib/gitlab/template/dockerfile_template.rb new file mode 100644 index 0000000000000000000000000000000000000000..d5d3e045a42d8db432f7436cdbdd30c2a4a581c6 --- /dev/null +++ b/lib/gitlab/template/dockerfile_template.rb @@ -0,0 +1,30 @@ +module Gitlab + module Template + class DockerfileTemplate < BaseTemplate + def content + explanation = "# This file is a template, and might need editing before it works on your project." + [explanation, super].join("\n") + end + + class << self + def extension + 'Dockerfile' + end + + def categories + { + "General" => '' + } + end + + def base_dir + Rails.root.join('vendor/dockerfile') + end + + def finder(project = nil) + Gitlab::Template::Finders::GlobalTemplateFinder.new(self.base_dir, self.extension, self.categories) + end + end + end + end +end diff --git a/spec/features/projects/files/dockerfile_dropdown_spec.rb b/spec/features/projects/files/dockerfile_dropdown_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..32f33a3ca97e2f0c8376ba90f68fd3a7803bda6c --- /dev/null +++ b/spec/features/projects/files/dockerfile_dropdown_spec.rb @@ -0,0 +1,30 @@ +require 'spec_helper' + +feature 'User wants to add a Dockerfile file', feature: true do + include WaitForAjax + + before do + user = create(:user) + project = create(:project) + project.team << [user, :master] + login_as user + visit namespace_project_new_blob_path(project.namespace, project, 'master', file_name: 'Dockerfile') + end + + scenario 'user can see Dockerfile dropdown' do + expect(page).to have_css('.dockerfile-selector') + end + + scenario 'user can pick a Dockerfile file from the dropdown', js: true do + find('.js-dockerfile-selector').click + wait_for_ajax + within '.dockerfile-selector' do + find('.dropdown-input-field').set('HTTPd') + find('.dropdown-content li', text: 'HTTPd').click + end + wait_for_ajax + + expect(page).to have_css('.dockerfile-selector .dropdown-toggle-text', text: 'HTTPd') + expect(page).to have_content('COPY ./ /usr/local/apache2/htdocs/') + end +end diff --git a/vendor/dockerfile/HTTPdDockerfile b/vendor/dockerfile/HTTPdDockerfile new file mode 100644 index 0000000000000000000000000000000000000000..2f05427323c29c19355093ef1a8d2772b4a18971 --- /dev/null +++ b/vendor/dockerfile/HTTPdDockerfile @@ -0,0 +1,3 @@ +FROM httpd:alpine + +COPY ./ /usr/local/apache2/htdocs/