diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml index 34f47806205c40046b7b28c9622a41f3e1a9222a..918c7ad8c76f0e60c5e0e1805868243167004d62 100644 --- a/app/views/layouts/nav/sidebar/_project.html.haml +++ b/app/views/layouts/nav/sidebar/_project.html.haml @@ -262,6 +262,19 @@ %strong.fly-out-top-item-name = _('Registry') + - if project_nav_tab? :packages + = nav_link(controller: %w[projects/packages/packages]) do + = link_to project_packages_path(@project) do + .nav-icon-container + = sprite_icon('disk') + %span.nav-item-name + = _('Packages') + %ul.sidebar-sub-level-items.is-fly-out-only + = nav_link(controller: %w[projects/packages/packages], html_options: { class: "fly-out-top-item" } ) do + = link_to project_packages_path(@project) do + %strong.fly-out-top-item-name + = _('Packages') + - if project_nav_tab? :wiki = nav_link(controller: :wikis) do = link_to get_project_wiki_path(@project), class: 'shortcuts-wiki' do diff --git a/config/routes/project.rb b/config/routes/project.rb index 52f899d10d52ca44df3e4666e5d5c434a12a2242..1b95c3ef4f30d48d27b44f88f77297d1387351c8 100644 --- a/config/routes/project.rb +++ b/config/routes/project.rb @@ -310,6 +310,10 @@ scope '-' do get 'archive/*id', constraints: { format: Gitlab::PathRegex.archive_formats_regex, id: /.+?/ }, to: 'repositories#archive', as: 'archive' + ## EE-specific + resources :packages, only: [:index, :show, :destroy], module: :packages + ## EE-specific + resources :jobs, only: [:index, :show], constraints: { id: /\d+/ } do collection do post :cancel_all diff --git a/doc/administration/index.md b/doc/administration/index.md index 951b5f9ac6b59d3e7d5b621696a7008cd455f37f..cfe01dbcd360a610bb319a1220347efcace9ce22 100644 --- a/doc/administration/index.md +++ b/doc/administration/index.md @@ -125,6 +125,7 @@ created in snippets, wikis, and repos. - [Default labels](../user/admin_area/labels.html): Create labels that will be automatically added to every new project. - [Restrict the use of public or internal projects](../public_access/public_access.md#restricting-the-use-of-public-or-internal-projects): Restrict the use of visibility levels for users when they create a project or a snippet. - [Custom project templates](../user/admin_area/custom_project_templates.md): Configure a set of projects to be used as custom templates when creating a new project. **[PREMIUM ONLY]** +- [Maven packages repository](maven_packages.md): Enable Maven packages repository within GitLab. ### Repository settings diff --git a/doc/administration/maven_packages.md b/doc/administration/maven_packages.md new file mode 100644 index 0000000000000000000000000000000000000000..2d2bb811f22ef7a130350dd67c56d7e9ebe83669 --- /dev/null +++ b/doc/administration/maven_packages.md @@ -0,0 +1,36 @@ +# GitLab private Maven repository administration + +> **Notes:** +- [Introduced][ee-5811] in GitLab 11.3. +- This document is about the admin guide. Learn how to use GitLab Maven + repository from [user documentation](../user/project/maven_packages.md). + +When enabled, every project in GitLab will have its own space to store Maven packages. + +## Enable the Maven repository + +**Omnibus GitLab installations** + +# TODO: Update this section once https://gitlab.com/gitlab-org/gitlab-ee/issues/7253 is resolved + +**Installations from source** + +If you have installed GitLab from source: + +1. After the installation is complete, you will have to configure the `packages` + section in `gitlab.yml` in order to enable it. + +The contents of `gitlab.yml` are: + +``` +packages: + enabled: true +``` + +where: + +| Parameter | Description | +| --------- | ----------- | +| `enabled` | `true` or `false`. Enables the packages repository in GitLab. By default this is `false`. | + +[ee-5811]: https://gitlab.com/gitlab-org/gitlab-ee/issues/5811 diff --git a/doc/user/project/index.md b/doc/user/project/index.md index 5c2bcd30dcbef42e231a7621b8878835fc08d9dd..1aeec6ec9d3e5c3c4844481ffd697c62aefd3dfe 100644 --- a/doc/user/project/index.md +++ b/doc/user/project/index.md @@ -86,6 +86,7 @@ website with GitLab Pages - [Syntax highlighting](highlighting.md): An alternative to customize your code blocks, overriding GitLab's default choice of language - [Badges](badges.md): Badges for the project overview +- [Maven packages](maven_packages.md): Your private Maven repository in GitLab ### Project's integrations diff --git a/ee/app/controllers/projects/packages/packages_controller.rb b/ee/app/controllers/projects/packages/packages_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..d2d09cc8eb9d214aa88f5d1a1bc7b7217bb06f90 --- /dev/null +++ b/ee/app/controllers/projects/packages/packages_controller.rb @@ -0,0 +1,32 @@ +module Projects + module Packages + class PackagesController < ApplicationController + before_action :verify_packages_enabled! + before_action :authorize_read_package! + before_action :authorize_destroy_package!, only: [:destroy] + + def index + @packages = project.packages.all.page(params[:page]) + end + + def show + @package = project.packages.find(params[:id]) + @package_files = @package.package_files.recent + @maven_metadatum = @package.maven_metadatum + end + + def destroy + @package = project.packages.find(params[:id]) + @package.destroy + + redirect_to project_packages_path(@project), status: 302, notice: _('Package was removed') + end + + private + + def verify_packages_enabled! + render_404 unless Gitlab.config.packages.enabled + end + end + end +end diff --git a/ee/app/helpers/ee/projects_helper.rb b/ee/app/helpers/ee/projects_helper.rb index f50e69eae9cbd420ca871e248786be40d5aecff4..66544a5acad919acc635f48808fa2d0846507a87 100644 --- a/ee/app/helpers/ee/projects_helper.rb +++ b/ee/app/helpers/ee/projects_helper.rb @@ -17,6 +17,17 @@ def sidebar_repository_paths super + %w(path_locks) end + override :get_project_nav_tabs + def get_project_nav_tabs(project, current_user) + nav_tabs = super + + if ::Gitlab.config.packages.enabled && can?(current_user, :read_package, project) + nav_tabs << :packages + end + + nav_tabs + end + override :default_url_to_repo def default_url_to_repo(project = @project) case default_clone_protocol diff --git a/ee/app/models/packages/package_file.rb b/ee/app/models/packages/package_file.rb index fb2697e7e8246b3d9a67bf6e6af783dec5ff91b9..9acf945ee0790fd1ee05dd9f32b3218e5deee59a 100644 --- a/ee/app/models/packages/package_file.rb +++ b/ee/app/models/packages/package_file.rb @@ -6,6 +6,8 @@ class Packages::PackageFile < ActiveRecord::Base validates :file, presence: true validates :file_name, presence: true + scope :recent, -> { order(id: :desc) } + mount_uploader :file, Packages::PackageFileUploader after_save :update_file_store, if: :file_changed? diff --git a/ee/app/policies/ee/project_policy.rb b/ee/app/policies/ee/project_policy.rb index 8d20b973e1095b8e5a2d9803bb98a0178667d2e6..b97e02aef20d69a282ad535a8957daf1485ec732 100644 --- a/ee/app/policies/ee/project_policy.rb +++ b/ee/app/policies/ee/project_policy.rb @@ -114,6 +114,7 @@ module ProjectPolicy enable :push_code_to_protected_branches enable :admin_path_locks enable :update_approvers + enable :destroy_package end rule { license_management_enabled & can?(:maintainer_access) }.enable :admin_software_license_policy diff --git a/ee/app/views/projects/packages/packages/index.html.haml b/ee/app/views/projects/packages/packages/index.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..97853db6a36b5e6529f78cd9db8777e0d3c7e7cc --- /dev/null +++ b/ee/app/views/projects/packages/packages/index.html.haml @@ -0,0 +1,44 @@ +- page_title _("Packages") +- can_destroy_package = can?(current_user, :destroy_package, @project) + +- if @packages.any? + .table-holder + .gl-responsive-table-row.table-row-header{ role: 'row' } + .table-section.section-30{ role: 'rowheader' } + = _('Name') + .table-section.section-20{ role: 'rowheader' } + = _('Version') + .table-section.section-20{ role: 'rowheader' } + = _('Type') + .table-section.section-20{ role: 'rowheader' } + = _('Created') + .table-section.section-10{ role: 'rowheader' } + - @packages.each do |package| + .gl-responsive-table-row + .table-section.section-30 + .table-mobile-header{ role: "rowheader" }= _("Name") + .table-mobile-content.flex-truncate-parent + = link_to package.name, project_package_path(@project, package), class: 'flex-truncate-child' + .table-section.section-20 + .table-mobile-header{ role: "rowheader" }= _("Version") + .table-mobile-content + = package.version + .table-section.section-20 + .table-mobile-header{ role: "rowheader" }= _("Type") + .table-mobile-content + = _('Maven package') + .table-section.section-20 + .table-mobile-header{ role: "rowheader" }= _("Created") + .table-mobile-content + = time_ago_with_tooltip(package.created_at) + .table-section.section-10 + .table-mobile-header{ role: "rowheader" } + .table-mobile-content + - if can_destroy_package + .pull-right + = link_to project_package_path(@project, package), method: :delete, data: { confirm: _("Are you sure?") }, class: "btn btn-grouped btn-inverted btn-remove", title: _('Delete Package') do + = icon('trash') + = paginate @packages, theme: "gitlab" +- else + .nothing-here-block + = _('No packages stored for this project.') diff --git a/ee/app/views/projects/packages/packages/show.html.haml b/ee/app/views/projects/packages/packages/show.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..05a1bf6b55029b17363e077bc80145fe2d21fb81 --- /dev/null +++ b/ee/app/views/projects/packages/packages/show.html.haml @@ -0,0 +1,75 @@ +- add_to_breadcrumbs _("Packages"), project_packages_path(@project) +- add_to_breadcrumbs @package.name, project_packages_path(@project) +- breadcrumb_title @package.version +- page_title _("Packages") + +.detail-page-header.d-flex.justify-content-between + %strong + = @package.version + + - if can?(current_user, :destroy_package, @project) + = link_to project_package_path(@project, @package), method: :delete, data: { confirm: _("Are you sure?") }, class: "btn btn-grouped btn-inverted btn-remove", title: _('Delete Package') do + = _('Delete') +.row.prepend-top-default + .col-sm-6 + .card + .card-header + %strong= _('Package information') + %ul.content-list + %li + %span.text-secondary + = _('Name') + %span.pull-right + = @package.name + %li + %span.text-secondary + = _('Version') + %span.pull-right + = @package.version + %li + %span.text-secondary + = _('Created on') + %span.pull-right + = @package.created_at.to_s(:medium) + .col-sm-6 + - if @maven_metadatum + .card + .card-header + %strong= _('Maven Metadata') + %ul.content-list + %li + %span.text-secondary + = _('Group ID') + %span.pull-right + = @maven_metadatum.app_group + %li + %span.text-secondary + = _('Artifact ID') + %span.pull-right + = @maven_metadatum.app_name + %li + %span.text-secondary + = _('Version') + %span.pull-right + = @maven_metadatum.app_version +%table.table + %thead + %tr + %th + = _('Name') + %th + = _('Size') + %th + .pull-right + = _('Created') + %tbody + - @package_files.each do |package_file| + %tr + %td + = icon('file-o fw') + = package_file.file.identifier + %td + = number_to_human_size(package_file.size, precision: 2) + %td + .pull-right + = time_ago_with_tooltip(package_file.created_at) diff --git a/ee/changelogs/unreleased/dz-add-ui-to-packages.yml b/ee/changelogs/unreleased/dz-add-ui-to-packages.yml new file mode 100644 index 0000000000000000000000000000000000000000..7c9c478e2a0a2ce424960e648a5d58d756977453 --- /dev/null +++ b/ee/changelogs/unreleased/dz-add-ui-to-packages.yml @@ -0,0 +1,5 @@ +--- +title: Add UI for GitLab private Maven repository feature +merge_request: 6781 +author: +type: added diff --git a/ee/spec/features/projects/packages_spec.rb b/ee/spec/features/projects/packages_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..bd673be8593ced52a5ee206149cc325d618e225b --- /dev/null +++ b/ee/spec/features/projects/packages_spec.rb @@ -0,0 +1,56 @@ +require 'spec_helper' + +describe 'Packages' do + let(:user) { create(:user) } + let(:project) { create(:project) } + + before do + sign_in(user) + project.add_master(user) + end + + context 'when there are no packages' do + it 'shows no packages message' do + visit_project_packages + + expect(page).to have_content 'No packages stored for this project.' + end + end + + context 'when there are packages' do + let!(:package) { create(:maven_package, project: project) } + + before do + package + + visit_project_packages + end + + it 'shows list of packages' do + expect(page).to have_content(package.name) + expect(page).to have_content(package.version) + end + + it 'shows a single package' do + click_on package.name + + expect(page).to have_content(package.name) + expect(page).to have_content(package.version) + + package.package_files.each do |package_file| + expect(page).to have_content(package_file.file_name) + end + end + + it 'removes package' do + click_link 'Delete Package' + + expect(page).to have_content 'Package was removed' + expect(page).not_to have_content(package.name) + end + end + + def visit_project_packages + visit project_packages_path(project) + end +end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 84f93b0ef3282376a79d371cab6f450f031172f6..24b252d9daa846fb42ce5b8594d1b62346ff9b49 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -735,6 +735,9 @@ msgstr "" msgid "Are you sure?" msgstr "" +msgid "Artifact ID" +msgstr "" + msgid "Artifacts" msgstr "" @@ -2319,6 +2322,9 @@ msgstr "" msgid "Created by me" msgstr "" +msgid "Created on" +msgstr "" + msgid "Created on:" msgstr "" @@ -2433,6 +2439,9 @@ msgstr "" msgid "Delete" msgstr "" +msgid "Delete Package" +msgstr "" + msgid "Delete Snippet" msgstr "" @@ -4410,6 +4419,12 @@ msgstr "" msgid "Markdown enabled" msgstr "" +msgid "Maven Metadata" +msgstr "" + +msgid "Maven package" +msgstr "" + msgid "Maximum git storage failures" msgstr "" @@ -4856,6 +4871,9 @@ msgstr "" msgid "No other labels with such name or description" msgstr "" +msgid "No packages stored for this project." +msgstr "" + msgid "No prioritised labels with such name or description" msgstr "" @@ -5104,6 +5122,15 @@ msgstr "" msgid "Owner" msgstr "" +msgid "Package information" +msgstr "" + +msgid "Package was removed" +msgstr "" + +msgid "Packages" +msgstr "" + msgid "Pages" msgstr "" @@ -6438,6 +6465,9 @@ msgstr "" msgid "Sign-up restrictions" msgstr "" +msgid "Size" +msgstr "" + msgid "Size and domain settings for static websites" msgstr "" @@ -7434,6 +7464,9 @@ msgstr "" msgid "Twitter" msgstr "" +msgid "Type" +msgstr "" + msgid "Unable to load the diff. %{button_try_again}" msgstr "" @@ -7596,6 +7629,9 @@ msgstr "" msgid "Verified" msgstr "" +msgid "Version" +msgstr "" + msgid "View epics list" msgstr ""