From d511a8f48594d500aa6c0b990a9ab13f24fc930b Mon Sep 17 00:00:00 2001 From: Praveen Arimbrathodiyil Date: Wed, 23 Dec 2015 02:04:40 +0530 Subject: [PATCH] Imported Upstream version 8.3.0+dfsg --- .gitlab-ci.yml | 42 +- .rubocop.yml | 87 +++-- .ruby-version | 2 +- CHANGELOG | 88 ++++- CONTRIBUTING.md | 356 +++++++++++++---- GITLAB_SHELL_VERSION | 2 +- GITLAB_WORKHORSE_VERSION | 2 +- Gemfile | 53 +-- Gemfile.lock | 365 ++++++++++-------- PROCESS.md | 26 +- Procfile | 6 +- README.md | 6 +- VERSION | 2 +- app/assets/images/icon-link.png | Bin 726 -> 1128 bytes app/assets/javascripts/api.js.coffee | 31 ++ app/assets/javascripts/application.js.coffee | 26 +- app/assets/javascripts/awards_handler.coffee | 14 +- .../javascripts/copy_to_clipboard.js.coffee | 63 +-- app/assets/javascripts/dispatcher.js.coffee | 2 +- .../javascripts/dropzone_input.js.coffee | 80 +--- app/assets/javascripts/flash.js.coffee | 16 +- .../javascripts/issuable_context.js.coffee | 10 +- app/assets/javascripts/issue.js.coffee | 8 +- app/assets/javascripts/issues.js.coffee | 2 +- .../javascripts/markdown_preview.js.coffee | 87 +++++ .../javascripts/merge_request.js.coffee | 8 +- .../javascripts/merge_request_tabs.js.coffee | 29 +- .../merge_request_widget.js.coffee | 9 +- .../javascripts/new_commit_form.js.coffee | 6 +- app/assets/javascripts/notes.js.coffee | 47 ++- app/assets/javascripts/project.js.coffee | 27 +- .../javascripts/project_select.js.coffee | 39 ++ app/assets/javascripts/sidebar.js.coffee | 1 + app/assets/javascripts/user.js.coffee | 6 + app/assets/javascripts/users_select.js.coffee | 28 +- app/assets/stylesheets/framework.scss | 3 +- app/assets/stylesheets/framework/blocks.scss | 13 + app/assets/stylesheets/framework/callout.scss | 5 +- app/assets/stylesheets/framework/common.scss | 57 ++- app/assets/stylesheets/framework/files.scss | 5 +- app/assets/stylesheets/framework/forms.scss | 21 +- app/assets/stylesheets/framework/header.scss | 8 +- .../stylesheets/framework/issue_box.scss | 15 +- app/assets/stylesheets/framework/layout.scss | 11 +- app/assets/stylesheets/framework/lists.scss | 52 ++- .../stylesheets/framework/markdown_area.scss | 9 +- app/assets/stylesheets/framework/mobile.scss | 3 - .../stylesheets/framework/pagination.scss | 4 + app/assets/stylesheets/framework/panels.scss | 20 + app/assets/stylesheets/framework/selects.scss | 60 ++- app/assets/stylesheets/framework/sidebar.scss | 191 ++++----- app/assets/stylesheets/framework/tables.scss | 2 + .../stylesheets/framework/timeline.scss | 3 +- .../stylesheets/framework/typography.scss | 11 + .../stylesheets/framework/variables.scss | 2 +- app/assets/stylesheets/pages/awards.scss | 86 +++++ app/assets/stylesheets/pages/builds.scss | 9 +- app/assets/stylesheets/pages/commit.scss | 19 +- app/assets/stylesheets/pages/detail_page.scss | 33 ++ app/assets/stylesheets/pages/editor.scss | 48 +-- app/assets/stylesheets/pages/groups.scss | 7 +- app/assets/stylesheets/pages/issuable.scss | 156 +++----- app/assets/stylesheets/pages/issues.scss | 36 +- app/assets/stylesheets/pages/login.scss | 1 + .../stylesheets/pages/merge_requests.scss | 52 +-- app/assets/stylesheets/pages/note_form.scss | 10 +- app/assets/stylesheets/pages/notes.scss | 10 +- app/assets/stylesheets/pages/profile.scss | 6 - app/assets/stylesheets/pages/projects.scss | 27 +- app/assets/stylesheets/pages/snippets.scss | 50 +-- app/assets/stylesheets/pages/status.scss | 17 + app/assets/stylesheets/pages/ui_dev_kit.scss | 5 +- app/assets/stylesheets/pages/wiki.scss | 5 + app/controllers/abuse_reports_controller.rb | 2 +- .../admin/application_settings_controller.rb | 6 + app/controllers/admin/builds_controller.rb | 23 ++ .../admin/identities_controller.rb | 17 +- .../admin/impersonation_controller.rb | 16 +- .../admin/runner_projects_controller.rb | 35 ++ app/controllers/admin/runners_controller.rb | 63 +++ app/controllers/autocomplete_controller.rb | 51 ++- .../ci/admin/application_controller.rb | 10 - .../admin/application_settings_controller.rb | 31 -- app/controllers/ci/admin/builds_controller.rb | 18 - app/controllers/ci/admin/events_controller.rb | 9 - .../ci/admin/projects_controller.rb | 19 - .../ci/admin/runner_projects_controller.rb | 34 -- .../ci/admin/runners_controller.rb | 73 ---- app/controllers/ci/application_controller.rb | 18 +- app/controllers/ci/lints_controller.rb | 2 +- app/controllers/ci/projects_controller.rb | 11 +- .../ci/runner_projects_controller.rb | 34 -- app/controllers/concerns/global_milestones.rb | 2 + app/controllers/concerns/issues_action.rb | 14 + .../concerns/merge_requests_action.rb | 9 + .../dashboard/snippets_controller.rb | 3 +- app/controllers/dashboard_controller.rb | 20 +- .../groups/milestones_controller.rb | 2 +- app/controllers/groups_controller.rb | 20 +- app/controllers/passwords_controller.rb | 6 +- app/controllers/profiles_controller.rb | 1 + .../projects/application_controller.rb | 8 +- app/controllers/projects/blob_controller.rb | 12 +- .../projects/branches_controller.rb | 2 +- app/controllers/projects/builds_controller.rb | 11 +- .../projects/ci_services_controller.rb | 49 --- .../projects/ci_settings_controller.rb | 36 -- .../projects/ci_web_hooks_controller.rb | 45 --- app/controllers/projects/commit_controller.rb | 16 +- app/controllers/projects/graphs_controller.rb | 32 +- app/controllers/projects/hooks_controller.rb | 8 +- app/controllers/projects/issues_controller.rb | 6 +- .../projects/merge_requests_controller.rb | 86 +++-- app/controllers/projects/notes_controller.rb | 34 +- .../projects/project_members_controller.rb | 2 +- .../projects/protected_branches_controller.rb | 2 +- app/controllers/projects/raw_controller.rb | 41 +- .../projects/runner_projects_controller.rb | 26 ++ .../projects/runners_controller.rb | 15 +- .../projects/services_controller.rb | 9 +- app/controllers/projects/tags_controller.rb | 2 +- .../projects/triggers_controller.rb | 9 +- .../projects/variables_controller.rb | 5 +- app/controllers/projects_controller.rb | 6 +- app/controllers/snippets_controller.rb | 2 +- app/finders/issuable_finder.rb | 20 +- app/finders/milestones_finder.rb | 2 +- app/finders/projects_finder.rb | 10 +- app/helpers/application_helper.rb | 18 +- app/helpers/blob_helper.rb | 52 ++- app/helpers/branches_helper.rb | 2 +- app/helpers/button_helper.rb | 58 +++ app/helpers/ci/gitlab_helper.rb | 17 - app/helpers/ci/projects_helper.rb | 36 -- app/helpers/ci_badge_helper.rb | 13 + app/helpers/ci_status_helper.rb | 43 ++- app/helpers/clipboard_helper.rb | 8 - app/helpers/commits_helper.rb | 4 +- app/helpers/diff_helper.rb | 36 +- app/helpers/emails_helper.rb | 2 + app/helpers/external_wiki_helper.rb | 2 +- app/helpers/gitlab_markdown_helper.rb | 59 ++- app/helpers/gitlab_routing_helper.rb | 2 +- app/helpers/graph_helper.rb | 10 + app/helpers/icons_helper.rb | 22 +- app/helpers/issues_helper.rb | 33 +- app/helpers/labels_helper.rb | 2 +- app/helpers/merge_requests_helper.rb | 28 +- app/helpers/milestones_helper.rb | 2 + app/helpers/namespaces_helper.rb | 15 +- app/helpers/nav_helper.rb | 8 + app/helpers/page_layout_helper.rb | 3 +- app/helpers/projects_helper.rb | 27 +- app/helpers/runners_helper.rb | 2 +- app/helpers/selects_helper.rb | 43 ++- app/helpers/tree_helper.rb | 20 +- app/helpers/triggers_helper.rb | 4 +- app/helpers/visibility_level_helper.rb | 70 ++-- app/mailers/base_mailer.rb | 4 - app/mailers/ci/emails/builds.rb | 17 - app/mailers/ci/notify.rb | 46 --- app/mailers/emails/builds.rb | 15 + app/mailers/emails/issues.rb | 68 ++-- app/mailers/emails/notes.rb | 75 ++-- app/mailers/emails/projects.rb | 86 +---- app/mailers/notify.rb | 7 +- app/models/ability.rb | 12 +- app/models/application_setting.rb | 33 +- app/models/broadcast_message.rb | 8 +- app/models/ci/application_setting.rb | 33 -- app/models/ci/build.rb | 67 ++-- app/models/ci/commit.rb | 36 +- app/models/ci/event.rb | 27 -- app/models/ci/project.rb | 192 --------- app/models/ci/project_status.rb | 31 -- app/models/ci/runner.rb | 6 +- app/models/ci/runner_project.rb | 4 +- app/models/ci/service.rb | 105 ----- app/models/ci/trigger.rb | 2 +- app/models/ci/variable.rb | 4 +- app/models/ci/web_hook.rb | 44 --- app/models/commit.rb | 50 ++- app/models/commit_range.rb | 110 ++++-- app/models/commit_status.rb | 62 +-- app/models/concerns/issuable.rb | 13 +- app/models/concerns/mentionable.rb | 53 +-- app/models/concerns/participable.rb | 31 +- app/models/concerns/referable.rb | 23 ++ app/models/concerns/strip_attribute.rb | 34 ++ app/models/concerns/taskable.rb | 33 +- app/models/concerns/token_authenticatable.rb | 46 ++- app/models/event.rb | 2 +- app/models/global_milestone.rb | 31 +- app/models/hooks/project_hook.rb | 1 + app/models/hooks/web_hook.rb | 40 +- app/models/issue.rb | 12 + app/models/jira_issue.rb | 2 + app/models/label.rb | 6 +- app/models/lfs_object.rb | 24 ++ app/models/lfs_objects_project.rb | 11 + app/models/merge_request.rb | 88 +++-- app/models/milestone.rb | 9 +- app/models/namespace.rb | 18 +- app/models/note.rb | 38 +- app/models/project.rb | 106 +++-- app/models/project_services/bamboo_service.rb | 13 +- .../project_services/buildkite_service.rb | 2 +- .../project_services/builds_email_service.rb | 90 +++++ .../project_services/ci/hip_chat_message.rb | 73 ---- .../project_services/ci/hip_chat_service.rb | 93 ----- .../project_services/ci/mail_service.rb | 84 ---- .../project_services/ci/slack_message.rb | 92 ----- .../project_services/ci/slack_service.rb | 81 ---- .../project_services/drone_ci_service.rb | 31 +- .../project_services/external_wiki_service.rb | 6 +- .../project_services/flowdock_service.rb | 2 +- .../project_services/gemnasium_service.rb | 2 +- .../project_services/gitlab_ci_service.rb | 76 +--- .../project_services/hipchat_service.rb | 49 ++- app/models/project_services/jira_service.rb | 241 +++++++++++- app/models/project_services/slack_service.rb | 29 +- .../slack_service/base_message.rb | 3 + .../slack_service/build_message.rb | 82 ++++ .../slack_service/note_message.rb | 31 +- .../project_services/teamcity_service.rb | 10 +- app/models/repository.rb | 85 ++-- app/models/sent_notification.rb | 7 +- app/models/service.rb | 21 +- app/models/snippet.rb | 4 + app/models/user.rb | 36 +- app/models/users_star_project.rb | 2 +- app/services/ci/create_builds_service.rb | 6 +- app/services/ci/create_commit_service.rb | 28 -- .../ci/create_trigger_request_service.rb | 6 +- app/services/ci/event_service.rb | 31 -- app/services/ci/image_for_build_service.rb | 4 +- app/services/ci/register_build_service.rb | 9 +- app/services/ci/test_hook_service.rb | 7 - app/services/create_branch_service.rb | 5 +- app/services/create_commit_builds_service.rb | 42 ++ app/services/delete_branch_service.rb | 4 +- app/services/files/base_service.rb | 4 +- app/services/git_hooks_service.rb | 28 ++ app/services/git_push_service.rb | 1 + app/services/git_tag_push_service.rb | 1 + app/services/gravatar_service.rb | 4 +- app/services/issuable_base_service.rb | 49 +++ app/services/issues/close_service.rb | 5 + app/services/issues/update_service.rb | 38 +- app/services/merge_requests/merge_service.rb | 18 +- .../merge_when_build_succeeds_service.rb | 55 +++ .../merge_requests/refresh_service.rb | 8 +- app/services/merge_requests/update_service.rb | 43 +-- app/services/notes/create_service.rb | 13 - app/services/notification_service.rb | 122 +++--- app/services/projects/create_service.rb | 6 +- app/services/projects/fork_service.rb | 15 +- app/services/system_note_service.rb | 43 ++- app/validators/color_validator.rb | 20 + {lib => app/validators}/email_validator.rb | 11 +- app/validators/line_code_validator.rb | 12 + app/validators/namespace_name_validator.rb | 10 + app/validators/namespace_validator.rb | 50 +++ app/validators/url_validator.rb | 36 ++ .../application_settings/_form.html.haml | 4 +- app/views/admin/builds/_build.html.haml | 73 ++++ app/views/admin/builds/index.html.haml | 50 +++ app/views/admin/identities/index.html.haml | 1 + app/views/admin/identities/new.html.haml | 4 + app/views/admin/labels/_form.html.haml | 2 +- app/views/admin/labels/_label.html.haml | 2 +- app/views/admin/labels/edit.html.haml | 8 +- app/views/admin/labels/new.html.haml | 6 +- .../{ci => }/admin/runners/_runner.html.haml | 12 +- .../{ci => }/admin/runners/index.html.haml | 22 +- .../{ci => }/admin/runners/show.html.haml | 41 +- .../{ci => }/admin/runners/update.js.haml | 0 app/views/admin/users/_head.html.haml | 2 +- app/views/admin/users/_projects.html.haml | 13 + app/views/admin/users/edit.html.haml | 3 - app/views/admin/users/projects.html.haml | 2 +- .../application_settings/_form.html.haml | 24 -- .../admin/application_settings/show.html.haml | 3 - app/views/ci/admin/builds/_build.html.haml | 34 -- app/views/ci/admin/builds/index.html.haml | 28 -- app/views/ci/admin/events/index.html.haml | 18 - .../ci/admin/projects/_project.html.haml | 29 -- app/views/ci/admin/projects/index.html.haml | 16 - .../ci/admin/runner_projects/index.html.haml | 57 --- app/views/ci/commits/_commit.html.haml | 5 +- app/views/ci/shared/_guide.html.haml | 8 +- app/views/ci/user_sessions/new.html.haml | 7 - app/views/dashboard/_projects_head.html.haml | 5 +- app/views/dashboard/groups/index.html.haml | 4 +- app/views/dashboard/issues.html.haml | 20 +- app/views/dashboard/merge_requests.html.haml | 12 +- .../dashboard/milestones/_milestone.html.haml | 11 +- .../dashboard/milestones/index.html.haml | 10 +- app/views/dashboard/milestones/show.html.haml | 44 ++- app/views/dashboard/projects/index.html.haml | 2 +- .../dashboard/projects/starred.html.haml | 2 +- .../mailer/unlock_instructions.html.erb | 7 - .../mailer/unlock_instructions.html.haml | 10 + app/views/devise/unlocks/new.html.erb | 12 - app/views/devise/unlocks/new.html.haml | 14 + app/views/events/_commit.html.haml | 2 +- app/views/explore/projects/_filter.html.haml | 2 +- app/views/explore/projects/index.html.haml | 2 +- app/views/explore/projects/starred.html.haml | 2 +- app/views/explore/projects/trending.html.haml | 2 +- app/views/groups/edit.html.haml | 6 +- .../group_members/_group_member.html.haml | 6 +- .../groups/group_members/index.html.haml | 57 ++- app/views/groups/group_members/update.js.haml | 2 +- app/views/groups/issues.html.haml | 27 +- app/views/groups/merge_requests.html.haml | 19 +- app/views/groups/milestones/index.html.haml | 26 +- app/views/groups/milestones/new.html.haml | 3 +- app/views/groups/milestones/show.html.haml | 47 ++- app/views/groups/new.html.haml | 8 +- app/views/help/ui.html.haml | 48 ++- app/views/import/bitbucket/status.html.haml | 1 + app/views/import/fogbugz/new.html.haml | 1 + .../import/fogbugz/new_user_map.html.haml | 1 + app/views/import/fogbugz/status.html.haml | 1 + app/views/import/github/status.html.haml | 1 + app/views/import/gitlab/status.html.haml | 1 + app/views/import/gitorious/status.html.haml | 1 + app/views/import/google_code/new.html.haml | 3 +- .../import/google_code/new_user_map.html.haml | 17 +- app/views/import/google_code/status.html.haml | 1 + app/views/layouts/_page.html.haml | 10 +- app/views/layouts/admin.html.haml | 4 +- app/views/layouts/ci/_nav_admin.html.haml | 35 -- app/views/layouts/ci/_nav_project.html.haml | 12 - app/views/layouts/ci/_page.html.haml | 10 +- app/views/layouts/ci/admin.html.haml | 11 - app/views/layouts/ci/application.html.haml | 11 - app/views/layouts/devise.html.haml | 4 +- app/views/layouts/errors.html.haml | 2 +- app/views/layouts/header/_default.html.haml | 12 +- app/views/layouts/nav/_admin.html.haml | 41 +- app/views/layouts/nav/_dashboard.html.haml | 18 +- app/views/layouts/nav/_explore.html.haml | 8 +- app/views/layouts/nav/_group.html.haml | 14 +- .../layouts/nav/_group_settings.html.haml | 6 +- app/views/layouts/nav/_profile.html.haml | 20 +- app/views/layouts/nav/_project.html.haml | 50 +-- .../layouts/nav/_project_settings.html.haml | 33 +- .../notify/build_fail_email.html.haml | 6 +- .../{ci => }/notify/build_fail_email.text.erb | 2 +- .../notify/build_success_email.html.haml | 6 +- .../notify/build_success_email.text.erb | 2 +- .../notify/repository_push_email.html.haml | 28 +- .../notify/repository_push_email.text.haml | 24 +- app/views/profiles/accounts/show.html.haml | 24 +- app/views/profiles/applications.html.haml | 84 ++-- app/views/profiles/keys/_form.html.haml | 7 +- app/views/profiles/keys/_key_table.html.haml | 16 +- app/views/profiles/keys/index.html.haml | 4 +- app/views/profiles/keys/new.html.haml | 2 +- .../profiles/notifications/show.html.haml | 6 +- app/views/profiles/preferences/show.html.haml | 2 +- app/views/profiles/show.html.haml | 10 +- app/views/projects/_commit_button.html.haml | 4 +- app/views/projects/_home_panel.html.haml | 17 +- app/views/projects/_last_commit.html.haml | 2 +- app/views/projects/_md_preview.html.haml | 21 +- app/views/projects/_readme.html.haml | 25 +- app/views/projects/blame/show.html.haml | 3 +- app/views/projects/blob/_actions.html.haml | 16 +- app/views/projects/blob/_blob.html.haml | 6 +- app/views/projects/blob/_download.html.haml | 2 +- app/views/projects/blob/_editor.html.haml | 25 +- app/views/projects/blob/_new_dir.html.haml | 14 +- app/views/projects/blob/_upload.html.haml | 7 +- app/views/projects/blob/edit.html.haml | 6 +- app/views/projects/blob/new.html.haml | 5 +- app/views/projects/blob/show.html.haml | 2 +- app/views/projects/branches/_branch.html.haml | 22 +- app/views/projects/branches/_commit.html.haml | 2 +- app/views/projects/branches/index.html.haml | 2 +- app/views/projects/branches/new.html.haml | 16 +- app/views/projects/builds/index.html.haml | 16 +- app/views/projects/builds/show.html.haml | 20 +- .../projects/ci_services/_form.html.haml | 54 --- app/views/projects/ci_services/edit.html.haml | 2 - .../projects/ci_services/index.html.haml | 23 -- .../projects/ci_settings/_form.html.haml | 120 ------ .../ci_settings/_no_runners.html.haml | 8 - app/views/projects/ci_settings/edit.html.haml | 6 - .../projects/ci_web_hooks/index.html.haml | 94 ----- app/views/projects/commit/_builds.html.haml | 68 ++++ app/views/projects/commit/_ci_menu.html.haml | 4 +- .../projects/commit/_commit_box.html.haml | 12 +- app/views/projects/commit/builds.html.haml | 68 +--- app/views/projects/commit/show.html.haml | 5 +- .../commit_statuses/_commit_status.html.haml | 21 +- app/views/projects/commits/_commit.html.haml | 8 +- app/views/projects/commits/_head.html.haml | 5 + app/views/projects/commits/show.atom.builder | 2 +- app/views/projects/compare/show.html.haml | 4 +- .../projects/deploy_keys/_form.html.haml | 9 +- app/views/projects/deploy_keys/new.html.haml | 2 +- app/views/projects/diffs/_diffs.html.haml | 2 +- app/views/projects/diffs/_file.html.haml | 25 +- app/views/projects/edit.html.haml | 96 ++++- app/views/projects/empty.html.haml | 15 +- app/views/projects/graphs/_head.html.haml | 2 + app/views/projects/graphs/ci/_overall.haml | 11 +- app/views/projects/graphs/languages.html.haml | 32 ++ app/views/projects/hooks/index.html.haml | 9 +- .../projects/issues/_closed_by_box.html.haml | 5 +- .../projects/issues/_discussion.html.haml | 33 +- app/views/projects/issues/_form.html.haml | 8 +- app/views/projects/issues/_issue.html.haml | 41 +- .../projects/issues/_merge_requests.html.haml | 26 ++ app/views/projects/issues/edit.html.haml | 6 + app/views/projects/issues/new.html.haml | 4 + app/views/projects/issues/show.html.haml | 91 +++-- app/views/projects/issues/update.js.haml | 4 +- app/views/projects/labels/_form.html.haml | 10 +- app/views/projects/labels/_label.html.haml | 2 +- app/views/projects/labels/edit.html.haml | 8 +- app/views/projects/labels/index.html.haml | 1 + app/views/projects/labels/new.html.haml | 6 +- .../merge_requests/_discussion.html.haml | 29 +- .../projects/merge_requests/_form.html.haml | 3 +- .../merge_requests/_merge_request.html.haml | 71 ++-- .../merge_requests/_new_compare.html.haml | 14 +- .../merge_requests/_new_submit.html.haml | 30 +- .../projects/merge_requests/_show.html.haml | 77 ++-- .../cancel_merge_when_build_succeeds.js.haml | 2 + .../projects/merge_requests/edit.html.haml | 2 +- .../projects/merge_requests/merge.js.haml | 8 +- .../projects/merge_requests/new.html.haml | 2 +- .../merge_requests/show/_builds.html.haml | 1 + .../merge_requests/show/_commits.html.haml | 2 +- .../show/_how_to_merge.html.haml | 12 +- .../merge_requests/show/_mr_box.html.haml | 8 +- .../merge_requests/show/_mr_title.html.haml | 15 +- .../show/_participants.html.haml | 4 - .../projects/merge_requests/update.js.haml | 4 +- .../merge_requests/widget/_heading.html.haml | 39 +- .../merge_requests/widget/_merged.html.haml | 18 +- .../merge_requests/widget/_open.html.haml | 4 +- .../widget/open/_accept.html.haml | 68 +++- .../open/_merge_when_build_succeeds.html.haml | 26 ++ app/views/projects/milestones/_form.html.haml | 10 +- .../projects/milestones/_milestone.html.haml | 8 +- app/views/projects/milestones/edit.html.haml | 6 + app/views/projects/milestones/index.html.haml | 15 +- app/views/projects/milestones/new.html.haml | 6 + app/views/projects/milestones/show.html.haml | 87 +++-- app/views/projects/network/_head.html.haml | 9 +- app/views/projects/network/show.html.haml | 3 +- app/views/projects/new.html.haml | 41 +- app/views/projects/notes/_edit_form.html.haml | 5 +- app/views/projects/notes/_form.html.haml | 9 +- app/views/projects/notes/_note.html.haml | 2 +- .../projects/notes/_notes_with_form.html.haml | 2 +- .../project_members/_group_members.html.haml | 13 +- .../project_members/_project_member.html.haml | 4 +- .../projects/project_members/_team.html.haml | 16 +- .../projects/project_members/index.html.haml | 45 +-- .../protected_branches/index.html.haml | 5 +- app/views/projects/releases/edit.html.haml | 2 +- .../repositories/_download_archive.html.haml | 4 +- .../projects/repositories/_feed.html.haml | 2 +- app/views/projects/runners/_runner.html.haml | 6 +- .../runners/_shared_runners.html.haml | 10 +- .../runners/_specific_runners.html.haml | 2 +- app/views/projects/runners/edit.html.haml | 4 +- app/views/projects/services/_form.html.haml | 7 +- app/views/projects/show.html.haml | 2 +- app/views/projects/snippets/edit.html.haml | 2 +- app/views/projects/snippets/new.html.haml | 2 +- app/views/projects/snippets/show.html.haml | 4 +- app/views/projects/tags/_tag.html.haml | 12 +- app/views/projects/tags/index.html.haml | 2 +- app/views/projects/tags/new.html.haml | 23 +- app/views/projects/tags/show.html.haml | 8 +- .../projects/tree/_tree_content.html.haml | 2 +- .../projects/tree/_tree_header.html.haml | 18 +- app/views/projects/triggers/index.html.haml | 8 +- app/views/projects/variables/show.html.haml | 6 +- app/views/projects/wikis/_form.html.haml | 16 +- .../projects/wikis/_main_links.html.haml | 11 +- app/views/projects/wikis/_nav.html.haml | 25 +- app/views/projects/wikis/_new.html.haml | 4 +- app/views/projects/wikis/edit.html.haml | 24 +- app/views/projects/wikis/git_access.html.haml | 2 +- app/views/projects/wikis/pages.html.haml | 7 +- app/views/projects/wikis/show.html.haml | 12 +- app/views/shared/_clone_panel.html.haml | 24 +- app/views/shared/_confirm_modal.html.haml | 7 +- app/views/shared/_file_highlight.html.haml | 5 +- app/views/shared/_group_form.html.haml | 2 +- app/views/shared/_issues.html.haml | 7 +- app/views/shared/_merge_requests.html.haml | 7 +- app/views/shared/_milestone_expired.html.haml | 5 + app/views/shared/_new_commit_form.html.haml | 18 +- .../shared/_new_project_item_select.html.haml | 20 + app/views/shared/_project_limit.html.haml | 8 + app/views/shared/_service_settings.html.haml | 9 + app/views/shared/issuable/_context.html.haml | 50 --- app/views/shared/issuable/_filter.html.haml | 16 +- app/views/shared/issuable/_form.html.haml | 54 ++- .../shared/issuable/_participants.html.haml | 5 + app/views/shared/issuable/_sidebar.html.haml | 83 ++++ app/views/shared/snippets/_form.html.haml | 7 +- app/views/shared/snippets/_header.html.haml | 47 +-- .../sherlock/transactions/_general.html.haml | 6 + app/views/snippets/edit.html.haml | 2 +- app/views/snippets/new.html.haml | 2 +- app/views/snippets/show.html.haml | 4 +- app/views/users/show.html.haml | 2 +- app/views/votes/_votes_block.html.haml | 3 +- app/workers/build_email_worker.rb | 19 + app/workers/ci/hip_chat_notifier_worker.rb | 19 - app/workers/ci/slack_notifier_worker.rb | 10 - app/workers/ci/web_hook_worker.rb | 9 - app/workers/email_receiver_worker.rb | 2 +- app/workers/emails_on_push_worker.rb | 2 +- app/workers/merge_worker.rb | 13 +- app/workers/stuck_ci_builds_worker.rb | 3 - bin/background_jobs | 2 +- bin/ci/upgrade.rb | 0 bin/parallel-rsync-repos | 54 +++ bin/rails | 6 +- bin/rake | 9 +- bin/setup | 29 ++ bin/upgrade.rb | 0 config/application.rb | 4 + config/environment.rb | 2 +- config/environments/development.rb | 2 +- config/environments/production.rb | 6 +- config/environments/test.rb | 8 +- config/gitlab.yml.example | 2 +- config/initializers/1_settings.rb | 19 +- config/initializers/4_ci_app.rb | 2 - config/initializers/carrierwave.rb | 10 +- config/initializers/cookies_serializer.rb | 2 +- config/initializers/default_url_options.rb | 2 +- config/initializers/devise.rb | 6 +- config/initializers/omniauth.rb | 2 +- config/initializers/rack_attack.rb.example | 14 +- config/initializers/rack_lineprof.rb | 2 +- config/initializers/secret_token.rb | 8 +- config/initializers/session_store.rb | 8 +- config/initializers/sherlock.rb | 2 +- config/initializers/sidekiq.rb | 14 + config/initializers/smtp_settings.rb.sample | 2 +- config/initializers/static_files.rb | 4 +- config/locales/devise.en.yml | 1 - config/locales/sherlock.en.yml | 1 + config/routes.rb | 83 ++-- config/schedule.yml | 10 + db/migrate/20121220064453_init_schema.rb | 74 ++-- ...140122112253_create_merge_request_diffs.rb | 15 +- .../20140903115954_migrate_to_new_shell.rb | 2 + ...20151012173029_set_jira_service_api_url.rb | 50 +++ ...ge_when_build_succeeds_to_merge_request.rb | 7 + .../20151109134526_add_issues_state_index.rb | 5 + ...916_add_projects_visibility_level_index.rb | 5 + ...3162133_add_hide_project_limit_to_users.rb | 5 + ...1203162134_add_build_events_to_services.rb | 6 + .../20151209144329_migrate_ci_web_hooks.rb | 13 + .../20151209145909_migrate_ci_emails.rb | 45 +++ ...20151210030143_add_unlock_token_to_user.rb | 5 + ...istration_token_to_application_settings.rb | 5 + ...20151210125232_migrate_ci_slack_service.rb | 33 ++ ...51210125927_migrate_ci_hip_chat_service.rb | 34 ++ .../20151210125928_add_ci_to_project.rb | 11 + .../20151210125929_add_project_id_to_ci.rb | 8 + .../20151210125930_migrate_ci_to_project.rb | 38 ++ .../20151210125931_add_index_to_ci_tables.rb | 12 + .../20151210125932_drop_null_for_ci_tables.rb | 9 + db/schema.rb | 161 ++++---- doc/README.md | 13 + doc/api/groups.md | 70 +++- doc/api/merge_requests.md | 93 ++++- doc/api/notes.md | 15 +- doc/api/projects.md | 93 ++++- doc/api/settings.md | 2 +- doc/ci/README.md | 12 + doc/ci/docker/using_docker_images.md | 316 +++++++++------ doc/ci/img/builds_tab.png | Bin 0 -> 3845 bytes doc/ci/languages/README.md | 7 + doc/ci/languages/php.md | 284 ++++++++++++++ doc/ci/quick_start/README.md | 204 +++++++--- doc/ci/quick_start/build_status.png | Bin 62140 -> 0 bytes doc/ci/quick_start/commit_status.png | Bin 33492 -> 0 bytes doc/ci/quick_start/img/build_log.png | Bin 0 -> 63272 bytes doc/ci/quick_start/img/builds_status.png | Bin 0 -> 49121 bytes doc/ci/quick_start/img/new_commit.png | Bin 0 -> 9033 bytes doc/ci/quick_start/img/runners_activated.png | Bin 0 -> 27597 bytes .../img/single_commit_status_pending.png | Bin 0 -> 36431 bytes doc/ci/quick_start/img/status_pending.png | Bin 0 -> 19782 bytes doc/ci/quick_start/new_commit.png | Bin 47527 -> 0 bytes doc/ci/quick_start/projects.png | Bin 37014 -> 0 bytes doc/ci/quick_start/runners.png | Bin 123048 -> 0 bytes doc/ci/quick_start/runners_activated.png | Bin 60769 -> 0 bytes doc/ci/services/README.md | 9 + doc/ci/services/docker-services.md | 5 + doc/ci/services/mysql.md | 118 ++++++ doc/ci/services/postgres.md | 114 ++++++ doc/ci/services/redis.md | 69 ++++ doc/ci/ssh_keys/README.md | 109 ++++++ doc/ci/variables/README.md | 2 - doc/ci/yaml/README.md | 283 +++++++++----- doc/customization/issue_closing.md | 27 +- doc/development/db_dump.md | 2 +- doc/install/installation.md | 75 ++-- doc/integration/README.md | 1 + doc/integration/bitbucket.md | 2 +- doc/integration/crowd.md | 2 +- doc/integration/github.md | 2 +- doc/integration/gitlab.md | 2 +- doc/integration/google.md | 2 +- doc/integration/jira.md | 113 ++++++ doc/integration/jira_issue_reference.png | Bin 0 -> 39942 bytes doc/integration/jira_project_name.png | Bin 0 -> 60598 bytes doc/integration/jira_service.png | Bin 0 -> 59082 bytes doc/integration/jira_service_close_issue.png | Bin 0 -> 88433 bytes doc/integration/jira_service_page.png | Bin 0 -> 162449 bytes doc/integration/jira_workflow_screenshot.png | Bin 0 -> 121534 bytes doc/integration/ldap.md | 8 +- doc/integration/saml.md | 7 +- doc/integration/twitter.md | 2 +- doc/operations/moving_repositories.md | 180 +++++++++ doc/permissions/permissions.md | 7 +- doc/public_access/public_access.md | 51 ++- doc/raketasks/README.md | 3 +- doc/raketasks/backup_restore.md | 7 +- doc/raketasks/check.md | 63 +++ doc/raketasks/check_repos_output.png | Bin 0 -> 73786 bytes doc/raketasks/list_repos.md | 30 ++ doc/release/README.md | 6 +- doc/release/monthly.md | 4 +- doc/release/patch.md | 40 +- doc/security/README.md | 3 +- doc/security/user_file_uploads.md | 11 + doc/ssh/README.md | 5 +- doc/update/8.1-to-8.2.md | 7 +- doc/update/8.2-to-8.3.md | 202 ++++++++++ doc/update/patch_versions.md | 45 ++- doc/web_hooks/web_hooks.md | 18 +- doc/workflow/README.md | 2 + doc/workflow/importing/README.md | 20 +- doc/workflow/importing/migrating_from_svn.md | 79 +++- .../lfs/manage_large_binaries_with_git_lfs.md | 4 +- doc/workflow/merge_when_build_succeeds.md | 15 + .../merge_when_build_succeeds/enable.png | Bin 0 -> 151112 bytes .../merge_when_build_succeeds/status.png | Bin 0 -> 180318 bytes features/admin/groups.feature | 16 + features/admin/projects.feature | 16 + features/explore/projects.feature | 21 +- features/group/members.feature | 105 +++++ features/group/milestones.feature | 30 ++ features/groups.feature | 125 ------ features/project/active_tab.feature | 11 +- features/project/commits/branches.feature | 1 + features/project/commits/comments.feature | 1 + features/project/commits/commits.feature | 4 +- .../project/commits/diff_comments.feature | 7 + features/project/commits/tags.feature | 1 + features/project/commits/user_lookup.feature | 1 + features/project/create.feature | 2 + features/project/graph.feature | 5 + features/project/issues/award_emoji.feature | 7 +- features/project/issues/filter_labels.feature | 1 + features/project/issues/issues.feature | 6 + features/project/issues/labels.feature | 1 + features/project/issues/milestones.feature | 1 + features/project/merge_requests.feature | 21 + .../project/merge_requests/accept.feature | 20 + features/project/service.feature | 12 +- features/project/shortcuts.feature | 3 +- features/project/source/browse_files.feature | 23 +- features/project/team_management.feature | 6 +- features/steps/admin/groups.rb | 29 ++ features/steps/admin/labels.rb | 12 +- features/steps/admin/projects.rb | 37 ++ features/steps/admin/settings.rb | 2 + features/steps/dashboard/dashboard.rb | 2 +- features/steps/explore/groups.rb | 8 +- features/steps/explore/projects.rb | 13 +- features/steps/group/members.rb | 147 +++++++ features/steps/group/milestones.rb | 90 +++++ features/steps/groups.rb | 261 +------------ features/steps/profile/profile.rb | 2 +- features/steps/project/commits/commits.rb | 8 +- features/steps/project/create.rb | 1 + .../steps/project/forked_merge_requests.rb | 10 +- features/steps/project/graph.rb | 9 + features/steps/project/hooks.rb | 4 +- features/steps/project/issues/award_emoji.rb | 31 +- features/steps/project/issues/issues.rb | 18 +- features/steps/project/issues/labels.rb | 20 +- features/steps/project/issues/milestones.rb | 2 +- features/steps/project/merge_requests.rb | 54 ++- .../project/merge_requests/acceptance.rb | 39 ++ features/steps/project/project.rb | 2 +- features/steps/project/services.rb | 28 +- features/steps/project/snippets.rb | 2 +- features/steps/project/source/browse_files.rb | 63 ++- .../steps/project/source/markdown_render.rb | 6 +- features/steps/project/team_management.rb | 4 - features/steps/project/wiki.rb | 14 +- features/steps/shared/diff_note.rb | 19 +- features/steps/shared/group.rb | 8 + features/steps/shared/paths.rb | 8 +- features/steps/shared/project.rb | 2 +- features/steps/shared/project_tab.rb | 8 +- features/steps/shared/user.rb | 12 + features/steps/snippets/snippets.rb | 2 +- features/support/capybara.rb | 2 +- lib/api/api.rb | 1 + lib/api/commit_statuses.rb | 2 +- lib/api/entities.rb | 17 +- lib/api/groups.rb | 12 + lib/api/helpers.rb | 7 +- lib/api/merge_requests.rb | 76 ++-- lib/api/project_hooks.rb | 2 + lib/api/projects.rb | 25 +- lib/api/triggers.rb | 48 +++ lib/award_emoji.rb | 35 ++ lib/banzai.rb | 13 + lib/banzai/cross_project_reference.rb | 22 ++ lib/banzai/filter.rb | 10 + .../filter/abstract_reference_filter.rb | 145 +++++++ .../filter}/autolink_filter.rb | 6 +- .../filter/commit_range_reference_filter.rb | 58 +++ lib/banzai/filter/commit_reference_filter.rb | 63 +++ .../filter}/emoji_filter.rb | 6 +- .../external_issue_reference_filter.rb | 36 +- .../filter}/external_link_filter.rb | 10 +- lib/banzai/filter/issue_reference_filter.rb | 23 ++ .../filter}/label_reference_filter.rb | 27 +- lib/banzai/filter/markdown_filter.rb | 42 ++ .../filter/merge_request_reference_filter.rb | 41 ++ .../filter}/redactor_filter.rb | 13 +- .../filter}/reference_filter.rb | 103 +++-- .../filter}/reference_gatherer_filter.rb | 13 +- .../filter}/relative_link_filter.rb | 8 +- .../filter}/sanitization_filter.rb | 12 +- lib/banzai/filter/snippet_reference_filter.rb | 25 ++ .../filter}/syntax_highlight_filter.rb | 6 +- .../filter}/table_of_contents_filter.rb | 8 +- .../filter}/task_list_filter.rb | 6 +- .../filter}/upload_link_filter.rb | 6 +- .../filter}/user_reference_filter.rb | 43 ++- lib/banzai/lazy_reference.rb | 27 ++ lib/banzai/pipeline.rb | 10 + lib/banzai/pipeline/asciidoc_pipeline.rb | 13 + lib/banzai/pipeline/atom_pipeline.rb | 14 + lib/banzai/pipeline/base_pipeline.rb | 30 ++ lib/banzai/pipeline/combined_pipeline.rb | 27 ++ lib/banzai/pipeline/description_pipeline.rb | 14 + lib/banzai/pipeline/email_pipeline.rb | 13 + lib/banzai/pipeline/full_pipeline.rb | 9 + lib/banzai/pipeline/gfm_pipeline.rb | 41 ++ lib/banzai/pipeline/note_pipeline.rb | 14 + .../pipeline/plain_markdown_pipeline.rb | 13 + lib/banzai/pipeline/post_process_pipeline.rb | 20 + .../pipeline/reference_extraction_pipeline.rb | 13 + lib/banzai/pipeline/single_line_pipeline.rb | 9 + lib/banzai/reference_extractor.rb | 55 +++ lib/banzai/renderer.rb | 78 ++++ lib/ci/api/api.rb | 2 - lib/ci/api/commits.rb | 66 ---- lib/ci/api/entities.rb | 9 - lib/ci/api/helpers.rb | 10 +- lib/ci/api/projects.rb | 195 ---------- lib/ci/api/runners.rb | 15 +- lib/ci/api/triggers.rb | 2 +- lib/ci/charts.rb | 2 +- lib/ci/current_settings.rb | 22 -- lib/ci/git.rb | 5 - lib/ci/gitlab_ci_yaml_processor.rb | 70 ++-- lib/ci/scheduler.rb | 16 - lib/gitlab/asciidoc.rb | 27 +- lib/gitlab/backend/grack_auth.rb | 4 +- lib/gitlab/backend/shell.rb | 2 +- .../bitbucket_import/project_creator.rb | 3 +- lib/gitlab/blacklist.rb | 34 -- lib/gitlab/build_data_builder.rb | 64 +++ lib/gitlab/closing_issue_extractor.rb | 16 +- lib/gitlab/database.rb | 18 + lib/gitlab/diff/file.rb | 4 +- lib/gitlab/email/message/repository_push.rb | 137 +++++++ lib/gitlab/fogbugz_import/importer.rb | 2 +- lib/gitlab/fogbugz_import/project_creator.rb | 3 +- lib/gitlab/git/hook.rb | 17 + lib/gitlab/github_import/client.rb | 2 +- lib/gitlab/github_import/importer.rb | 2 +- lib/gitlab/gitlab_import/client.rb | 2 +- lib/gitlab/gitlab_import/project_creator.rb | 3 +- .../gitorious_import/project_creator.rb | 3 +- lib/gitlab/google_code_import/importer.rb | 6 +- .../google_code_import/project_creator.rb | 3 +- lib/gitlab/ldap/access.rb | 4 +- lib/gitlab/lfs/response.rb | 4 +- lib/gitlab/markdown.rb | 200 ---------- .../markdown/commit_range_reference_filter.rb | 92 ----- .../markdown/commit_reference_filter.rb | 88 ----- .../markdown/cross_project_reference.rb | 24 -- lib/gitlab/markdown/issue_reference_filter.rb | 72 ---- .../merge_request_reference_filter.rb | 74 ---- lib/gitlab/markdown/pipeline.rb | 34 ++ .../markdown/snippet_reference_filter.rb | 74 ---- lib/gitlab/o_auth/auth_hash.rb | 2 +- lib/gitlab/push_data_builder.rb | 36 +- lib/gitlab/reference_extractor.rb | 72 +--- lib/gitlab/seeder.rb | 2 +- lib/gitlab/sherlock/transaction.rb | 5 + lib/omni_auth/request_forgery_protection.rb | 63 +-- lib/rouge/formatters/html_gitlab.rb | 2 +- lib/support/init.d/gitlab | 5 +- lib/support/init.d/gitlab.default.example | 2 +- lib/support/nginx/gitlab | 140 +------ lib/support/nginx/gitlab-ssl | 143 +------ lib/tasks/ci/schedule_builds.rake | 6 - lib/tasks/flay.rake | 2 +- lib/tasks/gitlab/check.rake | 58 ++- lib/tasks/gitlab/git.rake | 55 +++ lib/tasks/gitlab/import.rake | 2 + lib/tasks/gitlab/list_repos.rake | 17 + lib/tasks/gitlab/task_helpers.rake | 20 +- lib/tasks/spec.rake | 29 +- lib/tasks/spinach.rake | 26 +- scripts/prepare_build.sh | 4 +- shared/lfs-objects/.gitkeep | 0 spec/benchmarks/finders/issues_finder_spec.rb | 55 +++ .../gitlab/markdown/reference_filter_spec.rb | 2 +- .../abuse_reports_controller_spec.rb | 36 +- .../admin/impersonation_controller_spec.rb | 19 + .../autocomplete_controller_spec.rb | 9 +- spec/controllers/commit_controller_spec.rb | 35 ++ .../groups/milestones_controller_spec.rb | 27 ++ .../merge_requests_controller_spec.rb | 24 ++ .../projects/milestones_controller_spec.rb | 5 +- .../projects/raw_controller_spec.rb | 34 ++ spec/controllers/projects_controller_spec.rb | 16 + spec/controllers/snippets_controller_spec.rb | 115 ++++++ spec/factories.rb | 3 +- spec/factories/ci/builds.rb | 4 + spec/factories/ci/commits.rb | 25 +- spec/factories/ci/events.rb | 24 -- spec/factories/ci/projects.rb | 50 --- spec/factories/ci/runner_projects.rb | 2 +- spec/factories/ci/web_hook.rb | 6 - spec/factories/commit_statuses.rb | 2 +- spec/factories/lfs_objects.rb | 12 + spec/factories/lfs_objects_projects.rb | 11 + spec/factories/merge_requests.rb | 5 + spec/factories/notes.rb | 1 + spec/factories/projects.rb | 1 + .../admin_builds_spec.rb} | 35 +- .../admin_runners_spec.rb} | 32 +- spec/features/admin/admin_users_spec.rb | 17 +- spec/features/builds_spec.rb | 34 +- spec/features/ci/admin/events_spec.rb | 20 - spec/features/ci/admin/projects_spec.rb | 19 - spec/features/ci_settings_spec.rb | 22 -- spec/features/ci_web_hooks_spec.rb | 27 -- spec/features/commits_spec.rb | 103 +++-- .../issues/filter_by_milestone_spec.rb | 4 +- spec/features/issues/note_polling_spec.rb | 16 + spec/features/issues_spec.rb | 35 +- spec/features/{ci => }/lint_spec.rb | 0 .../merge_when_build_succeeds_spec.rb | 85 ++++ spec/features/notes_on_merge_requests_spec.rb | 5 +- spec/features/password_reset_spec.rb | 26 +- spec/features/runners_spec.rb | 28 +- spec/features/security/group_access_spec.rb | 4 +- spec/features/task_lists_spec.rb | 4 +- spec/features/triggers_spec.rb | 7 +- spec/features/variables_spec.rb | 7 +- spec/finders/projects_finder_spec.rb | 17 +- spec/fixtures/markdown.md.erb | 17 + spec/helpers/application_helper_spec.rb | 25 +- spec/helpers/ci_status_helper_spec.rb | 11 +- spec/helpers/groups_helper.rb | 2 +- spec/helpers/merge_requests_helper_spec.rb | 41 +- spec/helpers/visibility_level_helper_spec.rb | 89 ++--- .../fixtures/issues_show.html.haml | 2 +- .../fixtures/merge_request_tabs.html.haml | 6 +- .../fixtures/merge_requests_show.html.haml | 2 +- .../banzai/cross_project_reference_spec.rb | 34 ++ .../lib/banzai/filter/autolink_filter_spec.rb | 112 ++++++ .../commit_range_reference_filter_spec.rb | 182 +++++++++ .../filter/commit_reference_filter_spec.rb | 163 ++++++++ spec/lib/banzai/filter/emoji_filter_spec.rb | 98 +++++ .../external_issue_reference_filter_spec.rb | 77 ++++ .../filter/external_link_filter_spec.rb | 29 ++ .../filter/issue_reference_filter_spec.rb | 209 ++++++++++ .../filter/label_reference_filter_spec.rb | 179 +++++++++ .../merge_request_reference_filter_spec.rb | 142 +++++++ .../lib/banzai/filter/redactor_filter_spec.rb | 89 +++++ .../filter/reference_gatherer_filter_spec.rb | 87 +++++ .../filter/relative_link_filter_spec.rb | 147 +++++++ .../banzai/filter/sanitization_filter_spec.rb | 197 ++++++++++ .../filter/snippet_reference_filter_spec.rb | 146 +++++++ .../filter/syntax_highlight_filter_spec.rb | 17 + .../filter/table_of_contents_filter_spec.rb | 97 +++++ .../banzai/filter/task_list_filter_spec.rb | 10 + .../banzai/filter/upload_link_filter_spec.rb | 73 ++++ .../filter/user_reference_filter_spec.rb | 147 +++++++ spec/lib/ci/ansi2html_spec.rb | 2 +- spec/lib/ci/charts_spec.rb | 2 +- spec/lib/ci/gitlab_ci_yaml_processor_spec.rb | 8 +- spec/lib/disable_email_interceptor_spec.rb | 2 +- spec/lib/extracts_path_spec.rb | 2 +- spec/lib/file_size_validator_spec.rb | 2 +- spec/lib/git_ref_validator_spec.rb | 2 +- spec/lib/gitlab/asciidoc_spec.rb | 8 +- spec/lib/gitlab/auth_spec.rb | 2 +- spec/lib/gitlab/backend/grack_auth_spec.rb | 11 +- spec/lib/gitlab/backend/shell_spec.rb | 4 +- .../gitlab/bitbucket_import/client_spec.rb | 2 +- .../bitbucket_import/project_creator_spec.rb | 2 +- spec/lib/gitlab/build_data_builder_spec.rb | 20 + .../gitlab/closing_issue_extractor_spec.rb | 55 ++- spec/lib/gitlab/color_schemes_spec.rb | 2 +- spec/lib/gitlab/database_spec.rb | 2 +- spec/lib/gitlab/diff/file_spec.rb | 2 +- spec/lib/gitlab/diff/parser_spec.rb | 2 +- .../gitlab/email/attachment_uploader_spec.rb | 2 +- .../email/message/repository_push_spec.rb | 122 ++++++ spec/lib/gitlab/email/receiver_spec.rb | 2 +- spec/lib/gitlab/email/reply_parser_spec.rb | 2 +- spec/lib/gitlab/git_access_spec.rb | 2 +- spec/lib/gitlab/git_access_wiki_spec.rb | 2 +- spec/lib/gitlab/github_import/client_spec.rb | 2 +- .../github_import/project_creator_spec.rb | 2 +- spec/lib/gitlab/gitlab_import/client_spec.rb | 2 +- .../gitlab_import/project_creator_spec.rb | 2 +- .../gitorious_import/project_creator_spec.rb | 2 +- .../gitlab/google_code_import/client_spec.rb | 2 +- .../google_code_import/importer_spec.rb | 2 +- .../project_creator_spec.rb | 2 +- spec/lib/gitlab/incoming_email_spec.rb | 2 +- spec/lib/gitlab/inline_diff_spec.rb | 2 +- spec/lib/gitlab/key_fingerprint_spec.rb | 2 +- spec/lib/gitlab/ldap/access_spec.rb | 7 +- spec/lib/gitlab/ldap/adapter_spec.rb | 2 +- spec/lib/gitlab/ldap/auth_hash_spec.rb | 2 +- spec/lib/gitlab/ldap/authentication_spec.rb | 2 +- spec/lib/gitlab/ldap/config_spec.rb | 2 +- spec/lib/gitlab/ldap/user_spec.rb | 2 +- spec/lib/gitlab/lfs/lfs_router_spec.rb | 2 +- .../gitlab/markdown/autolink_filter_spec.rb | 114 ------ .../commit_range_reference_filter_spec.rb | 145 ------- .../markdown/commit_reference_filter_spec.rb | 135 ------- .../markdown/cross_project_reference_spec.rb | 36 -- spec/lib/gitlab/markdown/emoji_filter_spec.rb | 95 ----- .../external_issue_reference_filter_spec.rb | 79 ---- .../markdown/external_link_filter_spec.rb | 31 -- .../markdown/issue_reference_filter_spec.rb | 139 ------- .../markdown/label_reference_filter_spec.rb | 144 ------- .../merge_request_reference_filter_spec.rb | 120 ------ .../gitlab/markdown/redactor_filter_spec.rb | 91 ----- .../reference_gatherer_filter_spec.rb | 89 ----- .../markdown/relative_link_filter_spec.rb | 149 ------- .../markdown/sanitization_filter_spec.rb | 199 ---------- .../markdown/snippet_reference_filter_spec.rb | 118 ------ .../markdown/syntax_highlight_filter_spec.rb | 19 - .../markdown/table_of_contents_filter_spec.rb | 99 ----- .../gitlab/markdown/task_list_filter_spec.rb | 12 - .../markdown/upload_link_filter_spec.rb | 75 ---- .../markdown/user_reference_filter_spec.rb | 122 ------ spec/lib/gitlab/markup_helper_spec.rb | 2 +- spec/lib/gitlab/note_data_builder_spec.rb | 2 +- spec/lib/gitlab/o_auth/auth_hash_spec.rb | 6 +- spec/lib/gitlab/o_auth/user_spec.rb | 2 +- spec/lib/gitlab/popen_spec.rb | 2 +- .../lib/gitlab/project_search_results_spec.rb | 2 +- spec/lib/gitlab/push_data_builder_spec.rb | 11 +- spec/lib/gitlab/reference_extractor_spec.rb | 12 +- spec/lib/gitlab/regex_spec.rb | 2 +- spec/lib/gitlab/sherlock/collection_spec.rb | 2 +- spec/lib/gitlab/sherlock/file_sample_spec.rb | 2 +- .../lib/gitlab/sherlock/line_profiler_spec.rb | 2 +- spec/lib/gitlab/sherlock/line_sample_spec.rb | 2 +- spec/lib/gitlab/sherlock/location_spec.rb | 2 +- spec/lib/gitlab/sherlock/middleware_spec.rb | 2 +- spec/lib/gitlab/sherlock/query_spec.rb | 2 +- spec/lib/gitlab/sherlock/transaction_spec.rb | 15 +- spec/lib/gitlab/sql/union_spec.rb | 2 +- spec/lib/gitlab/themes_spec.rb | 2 +- spec/lib/gitlab/upgrader_spec.rb | 2 +- spec/lib/gitlab/uploads_transfer_spec.rb | 2 +- spec/lib/gitlab/url_builder_spec.rb | 2 +- spec/lib/gitlab/version_info_spec.rb | 2 +- spec/lib/repository_cache_spec.rb | 2 +- spec/mailers/ci/notify_spec.rb | 35 -- spec/mailers/notify_spec.rb | 106 ++++- spec/models/application_setting_spec.rb | 38 +- spec/models/broadcast_message_spec.rb | 17 +- spec/models/build_spec.rb | 85 ++-- spec/models/ci/commit_spec.rb | 30 +- .../project_services/hip_chat_message_spec.rb | 39 -- .../project_services/hip_chat_service_spec.rb | 73 ---- .../ci/project_services/mail_service_spec.rb | 191 --------- .../ci/project_services/slack_message_spec.rb | 43 --- .../ci/project_services/slack_service_spec.rb | 57 --- spec/models/ci/project_spec.rb | 246 ------------ spec/models/ci/runner_project_spec.rb | 2 +- spec/models/ci/runner_spec.rb | 10 +- spec/models/ci/service_spec.rb | 48 --- spec/models/ci/trigger_spec.rb | 4 +- spec/models/ci/variable_spec.rb | 2 +- spec/models/ci/web_hook_spec.rb | 63 --- spec/models/commit_range_spec.rb | 137 ++++--- spec/models/commit_spec.rb | 34 +- spec/models/commit_status_spec.rb | 5 +- spec/models/concerns/case_sensitivity_spec.rb | 2 +- spec/models/concerns/mentionable_spec.rb | 13 + spec/models/concerns/strip_attribute_spec.rb | 20 + .../concerns/token_authenticatable_spec.rb | 57 +++ spec/models/deploy_key_spec.rb | 2 +- spec/models/deploy_keys_project_spec.rb | 2 +- spec/models/event_spec.rb | 2 +- spec/models/external_issue_spec.rb | 2 +- spec/models/external_wiki_service_spec.rb | 2 +- spec/models/generic_commit_status_spec.rb | 2 +- spec/models/global_milestone_spec.rb | 2 +- spec/models/group_spec.rb | 2 +- spec/models/hooks/project_hook_spec.rb | 2 +- spec/models/hooks/service_hook_spec.rb | 2 +- spec/models/hooks/system_hook_spec.rb | 2 +- spec/models/hooks/web_hook_spec.rb | 8 +- spec/models/issue_spec.rb | 2 +- spec/models/jira_issue_spec.rb | 30 ++ spec/models/key_spec.rb | 4 +- spec/models/label_link_spec.rb | 2 +- spec/models/label_spec.rb | 2 +- spec/models/member_spec.rb | 2 +- spec/models/members/group_member_spec.rb | 2 +- spec/models/members/project_member_spec.rb | 2 +- spec/models/merge_request_spec.rb | 79 +++- spec/models/milestone_spec.rb | 2 +- spec/models/namespace_spec.rb | 2 +- spec/models/note_spec.rb | 29 +- spec/models/project_security_spec.rb | 2 +- .../buildkite_service_spec.rb | 2 +- .../project_services/drone_ci_service_spec.rb | 2 +- .../project_services/flowdock_service_spec.rb | 2 +- .../gemnasium_service_spec.rb | 2 +- .../gitlab_ci_service_spec.rb | 57 --- .../gitlab_issue_tracker_service_spec.rb | 2 +- .../project_services/hipchat_service_spec.rb | 73 +++- .../project_services/irker_service_spec.rb | 2 +- .../project_services/jira_service_spec.rb | 126 +++++- .../project_services/pushover_service_spec.rb | 2 +- .../slack_service/build_message_spec.rb | 46 +++ .../slack_service/issue_message_spec.rb | 2 +- .../slack_service/merge_message_spec.rb | 2 +- .../slack_service/note_message_spec.rb | 10 +- .../slack_service/push_message_spec.rb | 2 +- .../project_services/slack_service_spec.rb | 2 +- spec/models/project_snippet_spec.rb | 2 +- spec/models/project_spec.rb | 102 ++++- spec/models/project_team_spec.rb | 2 +- spec/models/project_wiki_spec.rb | 2 +- spec/models/protected_branch_spec.rb | 2 +- spec/models/repository_spec.rb | 121 +++++- spec/models/service_spec.rb | 2 +- spec/models/snippet_spec.rb | 2 +- spec/models/user_spec.rb | 26 +- spec/models/wiki_page_spec.rb | 2 +- spec/requests/api/groups_spec.rb | 59 ++- spec/requests/api/labels_spec.rb | 10 +- spec/requests/api/merge_requests_spec.rb | 36 +- spec/requests/api/project_hooks_spec.rb | 12 +- spec/requests/api/projects_spec.rb | 91 ++++- spec/requests/api/services_spec.rb | 2 +- spec/requests/api/triggers_spec.rb | 80 ++++ spec/requests/api/users_spec.rb | 4 +- spec/requests/ci/api/builds_spec.rb | 40 +- spec/requests/ci/api/commits_spec.rb | 65 ---- spec/requests/ci/api/projects_spec.rb | 232 ----------- spec/requests/ci/api/runners_spec.rb | 37 +- spec/requests/ci/api/triggers_spec.rb | 21 +- .../archive_repository_service_spec.rb | 2 +- .../services/ci/create_commit_service_spec.rb | 172 --------- .../ci/create_trigger_request_service_spec.rb | 7 +- spec/services/ci/event_service_spec.rb | 34 -- .../ci/image_for_build_service_spec.rb | 10 +- .../ci/register_build_service_spec.rb | 12 +- spec/services/ci/web_hook_service_spec.rb | 37 -- .../create_commit_builds_service_spec.rb | 175 +++++++++ spec/services/create_release_service_spec.rb | 34 ++ spec/services/create_snippet_service_spec.rb | 2 +- spec/services/destroy_group_service_spec.rb | 2 +- spec/services/event_create_service_spec.rb | 2 +- spec/services/git_hooks_service_spec.rb | 53 +++ spec/services/git_push_service_spec.rb | 71 +++- spec/services/git_tag_push_service_spec.rb | 18 +- .../issues/bulk_update_service_spec.rb | 2 +- spec/services/issues/close_service_spec.rb | 6 +- spec/services/issues/create_service_spec.rb | 2 +- spec/services/issues/update_service_spec.rb | 90 ++++- .../merge_requests/close_service_spec.rb | 6 +- .../merge_requests/create_service_spec.rb | 2 +- .../merge_requests/merge_service_spec.rb | 12 +- .../merge_when_build_succeeds_service_spec.rb | 84 ++++ .../merge_requests/refresh_service_spec.rb | 8 +- .../merge_requests/reopen_service_spec.rb | 6 +- .../merge_requests/update_service_spec.rb | 59 ++- .../services/milestones/close_service_spec.rb | 2 +- .../milestones/create_service_spec.rb | 2 +- spec/services/notes/create_service_spec.rb | 2 +- spec/services/notification_service_spec.rb | 350 +++++++---------- spec/services/projects/create_service_spec.rb | 9 +- .../services/projects/destroy_service_spec.rb | 2 +- .../projects/download_service_spec.rb | 2 +- spec/services/projects/fork_service_spec.rb | 2 +- .../projects/transfer_service_spec.rb | 2 +- spec/services/projects/update_service_spec.rb | 2 +- spec/services/projects/upload_service_spec.rb | 2 +- spec/services/search_service_spec.rb | 2 +- spec/services/system_hooks_service_spec.rb | 2 +- spec/services/system_note_service_spec.rb | 89 ++++- spec/services/test_hook_service_spec.rb | 2 +- spec/services/update_release_service_spec.rb | 34 ++ spec/services/update_snippet_service_spec.rb | 4 +- spec/spec_helper.rb | 1 + spec/support/filter_spec_helper.rb | 39 +- spec/support/jira_service_helper.rb | 67 ++++ spec/support/markdown_feature.rb | 4 + spec/support/matchers/markdown_matchers.rb | 14 +- spec/support/mentionable_shared_examples.rb | 23 +- spec/support/repo_helpers.rb | 12 +- spec/support/stub_gitlab_calls.rb | 4 + spec/support/test_env.rb | 4 +- spec/support/wait_for_ajax.rb | 11 + spec/workers/build_email_worker_spec.rb | 35 ++ spec/workers/email_receiver_worker_spec.rb | 12 +- spec/workers/repository_fork_worker_spec.rb | 20 +- spec/workers/stuck_ci_builds_worker_spec.rb | 4 +- 1143 files changed, 18024 insertions(+), 13143 deletions(-) create mode 100644 app/assets/javascripts/markdown_preview.js.coffee create mode 100644 app/assets/javascripts/project_select.js.coffee create mode 100644 app/assets/stylesheets/framework/panels.scss create mode 100644 app/assets/stylesheets/pages/awards.scss create mode 100644 app/assets/stylesheets/pages/detail_page.scss create mode 100644 app/controllers/admin/builds_controller.rb create mode 100644 app/controllers/admin/runner_projects_controller.rb create mode 100644 app/controllers/admin/runners_controller.rb delete mode 100644 app/controllers/ci/admin/application_controller.rb delete mode 100644 app/controllers/ci/admin/application_settings_controller.rb delete mode 100644 app/controllers/ci/admin/builds_controller.rb delete mode 100644 app/controllers/ci/admin/events_controller.rb delete mode 100644 app/controllers/ci/admin/projects_controller.rb delete mode 100644 app/controllers/ci/admin/runner_projects_controller.rb delete mode 100644 app/controllers/ci/admin/runners_controller.rb delete mode 100644 app/controllers/ci/runner_projects_controller.rb create mode 100644 app/controllers/concerns/issues_action.rb create mode 100644 app/controllers/concerns/merge_requests_action.rb delete mode 100644 app/controllers/projects/ci_services_controller.rb delete mode 100644 app/controllers/projects/ci_settings_controller.rb delete mode 100644 app/controllers/projects/ci_web_hooks_controller.rb create mode 100644 app/controllers/projects/runner_projects_controller.rb create mode 100644 app/helpers/button_helper.rb delete mode 100644 app/helpers/ci/gitlab_helper.rb delete mode 100644 app/helpers/ci/projects_helper.rb create mode 100644 app/helpers/ci_badge_helper.rb delete mode 100644 app/helpers/clipboard_helper.rb delete mode 100644 app/mailers/ci/emails/builds.rb delete mode 100644 app/mailers/ci/notify.rb create mode 100644 app/mailers/emails/builds.rb delete mode 100644 app/models/ci/application_setting.rb delete mode 100644 app/models/ci/event.rb delete mode 100644 app/models/ci/project.rb delete mode 100644 app/models/ci/project_status.rb delete mode 100644 app/models/ci/service.rb delete mode 100644 app/models/ci/web_hook.rb create mode 100644 app/models/concerns/strip_attribute.rb create mode 100644 app/models/jira_issue.rb create mode 100644 app/models/project_services/builds_email_service.rb delete mode 100644 app/models/project_services/ci/hip_chat_message.rb delete mode 100644 app/models/project_services/ci/hip_chat_service.rb delete mode 100644 app/models/project_services/ci/mail_service.rb delete mode 100644 app/models/project_services/ci/slack_message.rb delete mode 100644 app/models/project_services/ci/slack_service.rb create mode 100644 app/models/project_services/slack_service/build_message.rb delete mode 100644 app/services/ci/create_commit_service.rb delete mode 100644 app/services/ci/event_service.rb delete mode 100644 app/services/ci/test_hook_service.rb create mode 100644 app/services/create_commit_builds_service.rb create mode 100644 app/services/git_hooks_service.rb create mode 100644 app/services/merge_requests/merge_when_build_succeeds_service.rb create mode 100644 app/validators/color_validator.rb rename {lib => app/validators}/email_validator.rb (63%) create mode 100644 app/validators/line_code_validator.rb create mode 100644 app/validators/namespace_name_validator.rb create mode 100644 app/validators/namespace_validator.rb create mode 100644 app/validators/url_validator.rb create mode 100644 app/views/admin/builds/_build.html.haml create mode 100644 app/views/admin/builds/index.html.haml create mode 100644 app/views/admin/identities/new.html.haml rename app/views/{ci => }/admin/runners/_runner.html.haml (62%) rename app/views/{ci => }/admin/runners/index.html.haml (58%) rename app/views/{ci => }/admin/runners/show.html.haml (69%) rename app/views/{ci => }/admin/runners/update.js.haml (100%) create mode 100644 app/views/admin/users/_projects.html.haml delete mode 100644 app/views/ci/admin/application_settings/_form.html.haml delete mode 100644 app/views/ci/admin/application_settings/show.html.haml delete mode 100644 app/views/ci/admin/builds/_build.html.haml delete mode 100644 app/views/ci/admin/builds/index.html.haml delete mode 100644 app/views/ci/admin/events/index.html.haml delete mode 100644 app/views/ci/admin/projects/_project.html.haml delete mode 100644 app/views/ci/admin/projects/index.html.haml delete mode 100644 app/views/ci/admin/runner_projects/index.html.haml delete mode 100644 app/views/ci/user_sessions/new.html.haml delete mode 100644 app/views/devise/mailer/unlock_instructions.html.erb create mode 100644 app/views/devise/mailer/unlock_instructions.html.haml delete mode 100644 app/views/devise/unlocks/new.html.erb create mode 100644 app/views/devise/unlocks/new.html.haml delete mode 100644 app/views/layouts/ci/_nav_admin.html.haml delete mode 100644 app/views/layouts/ci/_nav_project.html.haml delete mode 100644 app/views/layouts/ci/admin.html.haml delete mode 100644 app/views/layouts/ci/application.html.haml rename app/views/{ci => }/notify/build_fail_email.html.haml (69%) rename app/views/{ci => }/notify/build_fail_email.text.erb (74%) rename app/views/{ci => }/notify/build_success_email.html.haml (68%) rename app/views/{ci => }/notify/build_success_email.text.erb (74%) delete mode 100644 app/views/projects/ci_services/_form.html.haml delete mode 100644 app/views/projects/ci_services/edit.html.haml delete mode 100644 app/views/projects/ci_services/index.html.haml delete mode 100644 app/views/projects/ci_settings/_form.html.haml delete mode 100644 app/views/projects/ci_settings/_no_runners.html.haml delete mode 100644 app/views/projects/ci_settings/edit.html.haml delete mode 100644 app/views/projects/ci_web_hooks/index.html.haml create mode 100644 app/views/projects/commit/_builds.html.haml create mode 100644 app/views/projects/graphs/languages.html.haml create mode 100644 app/views/projects/issues/_merge_requests.html.haml create mode 100644 app/views/projects/merge_requests/cancel_merge_when_build_succeeds.js.haml create mode 100644 app/views/projects/merge_requests/show/_builds.html.haml delete mode 100644 app/views/projects/merge_requests/show/_participants.html.haml create mode 100644 app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml create mode 100644 app/views/shared/_milestone_expired.html.haml create mode 100644 app/views/shared/_new_project_item_select.html.haml create mode 100644 app/views/shared/_project_limit.html.haml delete mode 100644 app/views/shared/issuable/_context.html.haml create mode 100644 app/views/shared/issuable/_participants.html.haml create mode 100644 app/views/shared/issuable/_sidebar.html.haml create mode 100644 app/workers/build_email_worker.rb delete mode 100644 app/workers/ci/hip_chat_notifier_worker.rb delete mode 100644 app/workers/ci/slack_notifier_worker.rb delete mode 100644 app/workers/ci/web_hook_worker.rb mode change 100644 => 100755 bin/ci/upgrade.rb create mode 100755 bin/parallel-rsync-repos create mode 100755 bin/setup mode change 100644 => 100755 bin/upgrade.rb create mode 100644 config/schedule.yml create mode 100644 db/migrate/20151012173029_set_jira_service_api_url.rb create mode 100644 db/migrate/20151028152939_add_merge_when_build_succeeds_to_merge_request.rb create mode 100644 db/migrate/20151109134526_add_issues_state_index.rb create mode 100644 db/migrate/20151109134916_add_projects_visibility_level_index.rb create mode 100644 db/migrate/20151203162133_add_hide_project_limit_to_users.rb create mode 100644 db/migrate/20151203162134_add_build_events_to_services.rb create mode 100644 db/migrate/20151209144329_migrate_ci_web_hooks.rb create mode 100644 db/migrate/20151209145909_migrate_ci_emails.rb create mode 100644 db/migrate/20151210030143_add_unlock_token_to_user.rb create mode 100644 db/migrate/20151210072243_add_runners_registration_token_to_application_settings.rb create mode 100644 db/migrate/20151210125232_migrate_ci_slack_service.rb create mode 100644 db/migrate/20151210125927_migrate_ci_hip_chat_service.rb create mode 100644 db/migrate/20151210125928_add_ci_to_project.rb create mode 100644 db/migrate/20151210125929_add_project_id_to_ci.rb create mode 100644 db/migrate/20151210125930_migrate_ci_to_project.rb create mode 100644 db/migrate/20151210125931_add_index_to_ci_tables.rb create mode 100644 db/migrate/20151210125932_drop_null_for_ci_tables.rb create mode 100644 doc/ci/img/builds_tab.png create mode 100644 doc/ci/languages/README.md create mode 100644 doc/ci/languages/php.md delete mode 100644 doc/ci/quick_start/build_status.png delete mode 100644 doc/ci/quick_start/commit_status.png create mode 100644 doc/ci/quick_start/img/build_log.png create mode 100644 doc/ci/quick_start/img/builds_status.png create mode 100644 doc/ci/quick_start/img/new_commit.png create mode 100644 doc/ci/quick_start/img/runners_activated.png create mode 100644 doc/ci/quick_start/img/single_commit_status_pending.png create mode 100644 doc/ci/quick_start/img/status_pending.png delete mode 100644 doc/ci/quick_start/new_commit.png delete mode 100644 doc/ci/quick_start/projects.png delete mode 100644 doc/ci/quick_start/runners.png delete mode 100644 doc/ci/quick_start/runners_activated.png create mode 100644 doc/ci/services/README.md create mode 100644 doc/ci/services/docker-services.md create mode 100644 doc/ci/services/mysql.md create mode 100644 doc/ci/services/postgres.md create mode 100644 doc/ci/services/redis.md create mode 100644 doc/ci/ssh_keys/README.md create mode 100644 doc/integration/jira.md create mode 100644 doc/integration/jira_issue_reference.png create mode 100644 doc/integration/jira_project_name.png create mode 100644 doc/integration/jira_service.png create mode 100644 doc/integration/jira_service_close_issue.png create mode 100644 doc/integration/jira_service_page.png create mode 100644 doc/integration/jira_workflow_screenshot.png create mode 100644 doc/operations/moving_repositories.md create mode 100644 doc/raketasks/check.md create mode 100644 doc/raketasks/check_repos_output.png create mode 100644 doc/raketasks/list_repos.md create mode 100644 doc/security/user_file_uploads.md create mode 100644 doc/update/8.2-to-8.3.md create mode 100644 doc/workflow/merge_when_build_succeeds.md create mode 100644 doc/workflow/merge_when_build_succeeds/enable.png create mode 100644 doc/workflow/merge_when_build_succeeds/status.png create mode 100644 features/group/members.feature create mode 100644 features/group/milestones.feature create mode 100644 features/project/merge_requests/accept.feature create mode 100644 features/steps/group/members.rb create mode 100644 features/steps/group/milestones.rb create mode 100644 features/steps/project/merge_requests/acceptance.rb create mode 100644 lib/api/triggers.rb create mode 100644 lib/banzai.rb create mode 100644 lib/banzai/cross_project_reference.rb create mode 100644 lib/banzai/filter.rb create mode 100644 lib/banzai/filter/abstract_reference_filter.rb rename lib/{gitlab/markdown => banzai/filter}/autolink_filter.rb (98%) create mode 100644 lib/banzai/filter/commit_range_reference_filter.rb create mode 100644 lib/banzai/filter/commit_reference_filter.rb rename lib/{gitlab/markdown => banzai/filter}/emoji_filter.rb (97%) rename lib/{gitlab/markdown => banzai/filter}/external_issue_reference_filter.rb (65%) rename lib/{gitlab/markdown => banzai/filter}/external_link_filter.rb (79%) create mode 100644 lib/banzai/filter/issue_reference_filter.rb rename lib/{gitlab/markdown => banzai/filter}/label_reference_filter.rb (76%) create mode 100644 lib/banzai/filter/markdown_filter.rb create mode 100644 lib/banzai/filter/merge_request_reference_filter.rb rename lib/{gitlab/markdown => banzai/filter}/redactor_filter.rb (70%) rename lib/{gitlab/markdown => banzai/filter}/reference_filter.rb (57%) rename lib/{gitlab/markdown => banzai/filter}/reference_gatherer_filter.rb (81%) rename lib/{gitlab/markdown => banzai/filter}/relative_link_filter.rb (97%) rename lib/{gitlab/markdown => banzai/filter}/sanitization_filter.rb (93%) create mode 100644 lib/banzai/filter/snippet_reference_filter.rb rename lib/{gitlab/markdown => banzai/filter}/syntax_highlight_filter.rb (94%) rename lib/{gitlab/markdown => banzai/filter}/table_of_contents_filter.rb (93%) rename lib/{gitlab/markdown => banzai/filter}/task_list_filter.rb (91%) rename lib/{gitlab/markdown => banzai/filter}/upload_link_filter.rb (94%) rename lib/{gitlab/markdown => banzai/filter}/user_reference_filter.rb (74%) create mode 100644 lib/banzai/lazy_reference.rb create mode 100644 lib/banzai/pipeline.rb create mode 100644 lib/banzai/pipeline/asciidoc_pipeline.rb create mode 100644 lib/banzai/pipeline/atom_pipeline.rb create mode 100644 lib/banzai/pipeline/base_pipeline.rb create mode 100644 lib/banzai/pipeline/combined_pipeline.rb create mode 100644 lib/banzai/pipeline/description_pipeline.rb create mode 100644 lib/banzai/pipeline/email_pipeline.rb create mode 100644 lib/banzai/pipeline/full_pipeline.rb create mode 100644 lib/banzai/pipeline/gfm_pipeline.rb create mode 100644 lib/banzai/pipeline/note_pipeline.rb create mode 100644 lib/banzai/pipeline/plain_markdown_pipeline.rb create mode 100644 lib/banzai/pipeline/post_process_pipeline.rb create mode 100644 lib/banzai/pipeline/reference_extraction_pipeline.rb create mode 100644 lib/banzai/pipeline/single_line_pipeline.rb create mode 100644 lib/banzai/reference_extractor.rb create mode 100644 lib/banzai/renderer.rb delete mode 100644 lib/ci/api/commits.rb delete mode 100644 lib/ci/api/projects.rb delete mode 100644 lib/ci/current_settings.rb delete mode 100644 lib/ci/git.rb delete mode 100644 lib/ci/scheduler.rb delete mode 100644 lib/gitlab/blacklist.rb create mode 100644 lib/gitlab/build_data_builder.rb create mode 100644 lib/gitlab/email/message/repository_push.rb delete mode 100644 lib/gitlab/markdown.rb delete mode 100644 lib/gitlab/markdown/commit_range_reference_filter.rb delete mode 100644 lib/gitlab/markdown/commit_reference_filter.rb delete mode 100644 lib/gitlab/markdown/cross_project_reference.rb delete mode 100644 lib/gitlab/markdown/issue_reference_filter.rb delete mode 100644 lib/gitlab/markdown/merge_request_reference_filter.rb create mode 100644 lib/gitlab/markdown/pipeline.rb delete mode 100644 lib/gitlab/markdown/snippet_reference_filter.rb delete mode 100644 lib/tasks/ci/schedule_builds.rake create mode 100644 lib/tasks/gitlab/git.rake create mode 100644 lib/tasks/gitlab/list_repos.rake create mode 100644 shared/lfs-objects/.gitkeep create mode 100644 spec/benchmarks/finders/issues_finder_spec.rb create mode 100644 spec/controllers/admin/impersonation_controller_spec.rb create mode 100644 spec/controllers/groups/milestones_controller_spec.rb delete mode 100644 spec/factories/ci/events.rb delete mode 100644 spec/factories/ci/projects.rb delete mode 100644 spec/factories/ci/web_hook.rb rename spec/features/{ci/admin/builds_spec.rb => admin/admin_builds_spec.rb} (69%) rename spec/features/{ci/admin/runners_spec.rb => admin/admin_runners_spec.rb} (65%) delete mode 100644 spec/features/ci/admin/events_spec.rb delete mode 100644 spec/features/ci/admin/projects_spec.rb delete mode 100644 spec/features/ci_settings_spec.rb delete mode 100644 spec/features/ci_web_hooks_spec.rb create mode 100644 spec/features/issues/note_polling_spec.rb rename spec/features/{ci => }/lint_spec.rb (100%) create mode 100644 spec/features/merge_requests/merge_when_build_succeeds_spec.rb create mode 100644 spec/lib/banzai/cross_project_reference_spec.rb create mode 100644 spec/lib/banzai/filter/autolink_filter_spec.rb create mode 100644 spec/lib/banzai/filter/commit_range_reference_filter_spec.rb create mode 100644 spec/lib/banzai/filter/commit_reference_filter_spec.rb create mode 100644 spec/lib/banzai/filter/emoji_filter_spec.rb create mode 100644 spec/lib/banzai/filter/external_issue_reference_filter_spec.rb create mode 100644 spec/lib/banzai/filter/external_link_filter_spec.rb create mode 100644 spec/lib/banzai/filter/issue_reference_filter_spec.rb create mode 100644 spec/lib/banzai/filter/label_reference_filter_spec.rb create mode 100644 spec/lib/banzai/filter/merge_request_reference_filter_spec.rb create mode 100644 spec/lib/banzai/filter/redactor_filter_spec.rb create mode 100644 spec/lib/banzai/filter/reference_gatherer_filter_spec.rb create mode 100644 spec/lib/banzai/filter/relative_link_filter_spec.rb create mode 100644 spec/lib/banzai/filter/sanitization_filter_spec.rb create mode 100644 spec/lib/banzai/filter/snippet_reference_filter_spec.rb create mode 100644 spec/lib/banzai/filter/syntax_highlight_filter_spec.rb create mode 100644 spec/lib/banzai/filter/table_of_contents_filter_spec.rb create mode 100644 spec/lib/banzai/filter/task_list_filter_spec.rb create mode 100644 spec/lib/banzai/filter/upload_link_filter_spec.rb create mode 100644 spec/lib/banzai/filter/user_reference_filter_spec.rb create mode 100644 spec/lib/gitlab/build_data_builder_spec.rb create mode 100644 spec/lib/gitlab/email/message/repository_push_spec.rb delete mode 100644 spec/lib/gitlab/markdown/autolink_filter_spec.rb delete mode 100644 spec/lib/gitlab/markdown/commit_range_reference_filter_spec.rb delete mode 100644 spec/lib/gitlab/markdown/commit_reference_filter_spec.rb delete mode 100644 spec/lib/gitlab/markdown/cross_project_reference_spec.rb delete mode 100644 spec/lib/gitlab/markdown/emoji_filter_spec.rb delete mode 100644 spec/lib/gitlab/markdown/external_issue_reference_filter_spec.rb delete mode 100644 spec/lib/gitlab/markdown/external_link_filter_spec.rb delete mode 100644 spec/lib/gitlab/markdown/issue_reference_filter_spec.rb delete mode 100644 spec/lib/gitlab/markdown/label_reference_filter_spec.rb delete mode 100644 spec/lib/gitlab/markdown/merge_request_reference_filter_spec.rb delete mode 100644 spec/lib/gitlab/markdown/redactor_filter_spec.rb delete mode 100644 spec/lib/gitlab/markdown/reference_gatherer_filter_spec.rb delete mode 100644 spec/lib/gitlab/markdown/relative_link_filter_spec.rb delete mode 100644 spec/lib/gitlab/markdown/sanitization_filter_spec.rb delete mode 100644 spec/lib/gitlab/markdown/snippet_reference_filter_spec.rb delete mode 100644 spec/lib/gitlab/markdown/syntax_highlight_filter_spec.rb delete mode 100644 spec/lib/gitlab/markdown/table_of_contents_filter_spec.rb delete mode 100644 spec/lib/gitlab/markdown/task_list_filter_spec.rb delete mode 100644 spec/lib/gitlab/markdown/upload_link_filter_spec.rb delete mode 100644 spec/lib/gitlab/markdown/user_reference_filter_spec.rb delete mode 100644 spec/mailers/ci/notify_spec.rb delete mode 100644 spec/models/ci/project_services/hip_chat_message_spec.rb delete mode 100644 spec/models/ci/project_services/hip_chat_service_spec.rb delete mode 100644 spec/models/ci/project_services/mail_service_spec.rb delete mode 100644 spec/models/ci/project_services/slack_message_spec.rb delete mode 100644 spec/models/ci/project_services/slack_service_spec.rb delete mode 100644 spec/models/ci/project_spec.rb delete mode 100644 spec/models/ci/service_spec.rb delete mode 100644 spec/models/ci/web_hook_spec.rb create mode 100644 spec/models/concerns/strip_attribute_spec.rb create mode 100644 spec/models/concerns/token_authenticatable_spec.rb create mode 100644 spec/models/jira_issue_spec.rb delete mode 100644 spec/models/project_services/gitlab_ci_service_spec.rb create mode 100644 spec/models/project_services/slack_service/build_message_spec.rb create mode 100644 spec/requests/api/triggers_spec.rb delete mode 100644 spec/requests/ci/api/commits_spec.rb delete mode 100644 spec/requests/ci/api/projects_spec.rb delete mode 100644 spec/services/ci/create_commit_service_spec.rb delete mode 100644 spec/services/ci/event_service_spec.rb delete mode 100644 spec/services/ci/web_hook_service_spec.rb create mode 100644 spec/services/create_commit_builds_service_spec.rb create mode 100644 spec/services/create_release_service_spec.rb create mode 100644 spec/services/git_hooks_service_spec.rb create mode 100644 spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb create mode 100644 spec/services/update_release_service_spec.rb create mode 100644 spec/support/jira_service_helper.rb create mode 100644 spec/support/wait_for_ajax.rb create mode 100644 spec/workers/build_email_worker_spec.rb diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 141e7ba41d..a8da3de83f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -8,7 +8,7 @@ before_script: - touch log/application.log - touch log/test.log - bundle install --without postgres production --jobs $(nproc) "${FLAGS[@]}" - - bundle exec rake db:create RAILS_ENV=test + - bundle exec rake db:reset db:create RAILS_ENV=test spec:feature: script: @@ -24,6 +24,27 @@ spec:api: - ruby - mysql +spec:models: + script: + - RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:models + tags: + - ruby + - mysql + +spec:lib: + script: + - RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:lib + tags: + - ruby + - mysql + +spec:services: + script: + - RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:services + tags: + - ruby + - mysql + spec:benchmark: script: - RAILS_ENV=test bundle exec rake spec:benchmark @@ -39,9 +60,16 @@ spec:other: - ruby - mysql -spinach:project: +spinach:project:half: script: - - RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:project + - RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:project:half + tags: + - ruby + - mysql + +spinach:project:rest: + script: + - RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:project:rest tags: - ruby - mysql @@ -87,4 +115,12 @@ flay: tags: - ruby - mysql + +bundler:audit: + script: + - "bundle exec bundle-audit update" + - "bundle exec bundle-audit check" + tags: + - ruby + - mysql allow_failure: true diff --git a/.rubocop.yml b/.rubocop.yml index 11e4502849..89aa0591c3 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -76,7 +76,7 @@ Style/BlockEndNewline: Description: 'Put end statement of multiline block on its own line.' Enabled: true -Style/Blocks: +Style/BlockDelimiters: Description: >- Avoid using {...} for multi-line blocks (multiline chaining is always ugly). @@ -232,6 +232,10 @@ Style/EvenOdd: StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#predicate-methods' Enabled: false +Style/ExtraSpacing: + Description: 'Do not use unnecessary spacing.' + Enabled: false + Style/FileName: Description: 'Use snake_case for source file names.' StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#snake-case-files' @@ -431,6 +435,14 @@ Style/OpMethod: StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#other-arg' Enabled: false +Style/ParallelAssignment: + Description: >- + Check for simple usages of parallel assignment. + It will only warn when the number of variables + matches on both sides of the assignment. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#parallel-assignment' + Enabled: false + Style/ParenthesesAroundCondition: Description: >- Don't use parentheses around the condition of an @@ -669,6 +681,13 @@ Style/TrailingWhitespace: StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-whitespace' Enabled: false +Style/TrailingUnderscoreVariable: + Description: >- + Checks for the usage of unneeded trailing underscores at the + end of parallel variable assignment. + AllowNamedUnderscoreVariables: true + Enabled: false + Style/TrivialAccessors: Description: 'Prefer attr_* methods to trivial readers/writers.' StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#attr_family' @@ -690,11 +709,6 @@ Style/UnneededPercentQ: StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-q' Enabled: false -Style/UnneededPercentX: - Description: 'Checks for %x when `` would do.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-x' - Enabled: false - Style/VariableInterpolation: Description: >- Don't interpolate global, instance and class variables @@ -735,21 +749,37 @@ Metrics/AbcSize: Description: >- A calculated magnitude based on number of assignments, branches, and conditions. - Enabled: false - -Metrics/BlockNesting: - Description: 'Avoid excessive block nesting' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#three-is-the-number-thou-shalt-count' - Enabled: false - -Metrics/ClassLength: - Description: 'Avoid classes longer than 100 lines of code.' - Enabled: false + Enabled: true + Max: 70 Metrics/CyclomaticComplexity: Description: >- A complexity metric that is strongly correlated to the number of test cases needed to validate a method. + Enabled: true + Max: 17 + +Metrics/PerceivedComplexity: + Description: >- + A complexity metric geared towards measuring complexity for a + human reader. + Enabled: true + Max: 17 + +Metrics/ParameterLists: + Description: 'Avoid parameter lists longer than three or four parameters.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#too-many-params' + Enabled: true + Max: 8 + +Metrics/BlockNesting: + Description: 'Avoid excessive block nesting' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#three-is-the-number-thou-shalt-count' + Enabled: true + Max: 4 + +Metrics/ClassLength: + Description: 'Avoid classes longer than 100 lines of code.' Enabled: false Metrics/LineLength: @@ -762,15 +792,8 @@ Metrics/MethodLength: StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#short-methods' Enabled: false -Metrics/ParameterLists: - Description: 'Avoid parameter lists longer than three or four parameters.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#too-many-params' - Enabled: false - -Metrics/PerceivedComplexity: - Description: >- - A complexity metric geared towards measuring complexity for a - human reader. +Metrics/ModuleLength: + Description: 'Avoid modules longer than 100 lines of code.' Enabled: false #################### Lint ################################ @@ -888,7 +911,7 @@ Lint/RequireParentheses: Lint/RescueException: Description: 'Avoid rescuing the Exception class.' StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-blind-rescues' - Enabled: false + Enabled: true Lint/ShadowingOuterLocalVariable: Description: >- @@ -956,6 +979,12 @@ Rails/ActionFilter: Description: 'Enforces consistent use of action filter methods.' Enabled: true +Rails/Date: + Description: >- + Checks the correct usage of date aware methods, + such as Date.today, Date.current etc. + Enabled: false + Rails/DefaultScope: Description: 'Checks if the argument passed to default_scope is a block.' Enabled: false @@ -982,6 +1011,12 @@ Rails/ScopeArgs: Description: 'Checks the arguments of ActiveRecord scopes.' Enabled: false +Rails/TimeZone: + Description: 'Checks the correct usage of time zone aware methods.' + StyleGuide: 'https://github.com/bbatsov/rails-style-guide#time' + Reference: 'http://danilenko.org/2012/7/6/rails_timezones' + Enabled: false + Rails/Validation: Description: 'Use validates :attribute, hash of validations.' Enabled: false diff --git a/.ruby-version b/.ruby-version index 399088bf46..04b10b4f15 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.1.6 +2.1.7 diff --git a/CHANGELOG b/CHANGELOG index 49fa3d9435..d1540e9d7f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,88 @@ Please view this file on the master branch, on stable branches it's out of date. +v 8.3.0 (unreleased) + - Bump rack-attack to 4.3.1 for security fix (Stan Hu) + - API support for starred projects for authorized user (Zeger-Jan van de Weg) + - Add open_issues_count to project API (Stan Hu) + - Expand character set of usernames created by Omniauth (Corey Hinshaw) + - Add button to automatically merge a merge request when the build succeeds (Zeger-Jan van de Weg) + - Provide better diagnostic message upon project creation errors (Stan Hu) + - Bump devise to 3.5.3 to fix reset token expiring after account creation (Stan Hu) + - Remove api credentials from link to build_page + - Deprecate GitLabCiService making it to always be inactive + - Bump gollum-lib to 4.1.0 (Stan Hu) + - Fix broken group avatar upload under "New group" (Stan Hu) + - Update project repositorize size and commit count during import:repos task (Stan Hu) + - Fix API setting of 'public' attribute to false will make a project private (Stan Hu) + - Handle and report SSL errors in Web hook test (Stan Hu) + - Bump Redis requirement to 2.8 for Sidekiq 4 (Stan Hu) + - Fix: Assignee selector is empty when 'Unassigned' is selected (Jose Corcuera) + - Add rake tasks for git repository maintainance (Zeger-Jan van de Weg) + - Fix 500 error when update group member permission + - Trim leading and trailing whitespace of milestone and issueable titles (Jose Corcuera) + - Recognize issue/MR/snippet/commit links as references + - Backport JIRA features from EE to CE + - Add ignore whitespace change option to commit view + - Fire update hook from GitLab + - Allow account unlock via email + - Style warning about mentioning many people in a comment + - Fix: sort milestones by due date once again (Greg Smethells) + - Migrate all CI::Services and CI::WebHooks to Services and WebHooks + - Don't show project fork event as "imported" + - Add API endpoint to fetch merge request commits list + - Don't create CI status for refs that doesn't have .gitlab-ci.yml, even if the builds are enabled + - Expose events API with comment information and author info + - Fix: Ensure "Remove Source Branch" button is not shown when branch is being deleted. #3583 + - Run custom Git hooks when branch is created or deleted. + - Fix bug when simultaneously accepting multiple MRs results in MRs that are of "merged" status, but not merged to the target branch + - Add languages page to graphs + - Block LDAP user when they are no longer found in the LDAP server + - Improve wording on project visibility levels (Zeger-Jan van de Weg) + - Fix editing notes on a merge request diff + - Automatically select default clone protocol based on user preferences (Eirik Lygre) + - Make Network page as sub tab of Commits + - Add copy-to-clipboard button for Snippets + - Add indication to merge request list item that MR cannot be merged automatically + - Default target branch to patch-n when editing file in protected branch + - Add Builds tab to merge request detail page + - Allow milestones, issues and MRs to be created from dashboard and group indexes + - Use new style for wiki + - Use new style for milestone detail page + - Fix sidebar tooltips when collapsed + - Prevent possible XSS attack with award-emoji + - Upgraded Sidekiq to 4.x + - Accept COPYING,COPYING.lesser, and licence as license file (Zeger-Jan van de Weg) + - Fix emoji aliases problem + - Fix award-emojis Flash alert's width + - Fix deleting notes on a merge request diff + - Display referenced merge request statuses in the issue description (Greg Smethells) + - Implement new sidebar for issue and merge request pages + - Emoji picker improvements + - Suppress warning about missing `.gitlab-ci.yml` if builds are disabled + - Do not show build status unless builds are enabled and `.gitlab-ci.yml` is present + - Persist runners registration token in database + - Fix online editor should not remove newlines at the end of the file + +v 8.2.3 + - Fix application settings cache not expiring after changes (Stan Hu) + - Fix Error 500s when creating global milestones with Unicode characters (Stan Hu) + - Update documentation for "Guest" permissions + - Properly convert Emoji-only comments into Award Emojis + - Enable devise paranoid mode to prevent user enumeration attack + - Webhook payload has an added, modified and removed properties for each commit + - Fix 500 error when creating a merge request that removes a submodule + +v 8.2.2 + - Fix 404 in redirection after removing a project (Stan Hu) + - Ensure cached application settings are refreshed at startup (Stan Hu) + - Fix Error 500 when viewing user's personal projects from admin page (Stan Hu) + - Fix: Raw private snippets access workflow + - Prevent "413 Request entity too large" errors when pushing large files with LFS + - Fix: As an admin, cannot add oneself as a member to a group/project + - Fix invalid links within projects dashboard header + - Make current user the first user in assignee dropdown in issues detail page (Stan Hu) + - Fix: duplicate email notifications on issue comments + v 8.2.1 - Forcefully update builds that didn't want to update with state machine - Fix: saving GitLabCiService as Admin Template @@ -9,7 +92,7 @@ v 8.2.0 - Improved performance of rendering user profile pages and Atom feeds - Expose build artifacts path as config option - Fix grouping of contributors by email in graph. - - Remove CSS property preventing hard tabs from rendering in Chromium 45 (Stan Hu) + - Improved performance of finding issues with/without labels - Fix Drone CI service template not saving properly (Stan Hu) - Fix avatars not showing in Atom feeds and project issues when Gravatar disabled (Stan Hu) - Added a GitLab specific profiling tool called "Sherlock" (see GitLab CE merge request #1749) @@ -48,7 +131,6 @@ v 8.2.0 - Add email notification to former assignee upon unassignment (Adam Lieskovský) - New design for project graphs page - Remove deprecated dumped yaml file generated from previous job definitions - - Fix incoming email config defaults - Show specific runners from projects where user is master or owner - MR target branch is now visible on a list view when it is different from project's default one - Improve Continuous Integration graphs page @@ -131,7 +213,6 @@ v 8.1.0 - Show CI status on Your projects page and Starred projects page - Remove "Continuous Integration" page from dashboard - Add notes and SSL verification entries to hook APIs (Ben Boeckel) - - Added build artifacts - Fix grammar in admin area "labels" .nothing-here-block when no labels exist. - Move CI runners page to project settings area - Move CI variables page to project settings area @@ -207,7 +288,6 @@ v 8.0.2 - Allow AWS S3 Server-Side Encryption with Amazon S3-Managed Keys for backups (Paul Beattie) v 8.0.1 - - Remove git refs used internally by GitLab from network graph (Stan Hu) - Improve CI migration procedure and documentation v 8.0.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5d85c9f3fc..7ced7c5788 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,105 +1,245 @@ # Contribute to GitLab -Thank you for your interest in contributing to GitLab. -This guide details how contribute to GitLab in a way that is efficient for everyone. -If you have read this guide and want to know how the GitLab core-team operates please see [the GitLab contributing process](PROCESS.md). +Thank you for your interest in contributing to GitLab. This guide details how +to contribute to GitLab in a way that is efficient for everyone. + +GitLab comes into two flavors, GitLab Community Edition (CE) our free and open +source edition, and GitLab Enterprise Edition (EE) which is our commercial +edition. Throughout this guide you will see references to CE and EE for +abbreviation. + +If you have read this guide and want to know how the GitLab [core-team][] +operates please see [the GitLab contributing process](PROCESS.md). ## Contributor license agreement -By submitting code as an individual you agree to the [individual contributor license agreement](doc/legal/individual_contributor_license_agreement.md). By submitting code as an entity you agree to the [corporate contributor license agreement](doc/legal/corporate_contributor_license_agreement.md). +By submitting code as an individual you agree to the +[individual contributor license agreement](doc/legal/individual_contributor_license_agreement.md). +By submitting code as an entity you agree to the +[corporate contributor license agreement](doc/legal/corporate_contributor_license_agreement.md). ## Security vulnerability disclosure -Please report suspected security vulnerabilities in private to support@gitlab.com, also see the [disclosure section on the GitLab.com website](https://about.gitlab.com/disclosure/). Please do NOT create publicly viewable issues for suspected security vulnerabilities. +Please report suspected security vulnerabilities in private to +`support@gitlab.com`, also see the +[disclosure section on the GitLab.com website](https://about.gitlab.com/disclosure/). +Please do **NOT** create publicly viewable issues for suspected security +vulnerabilities. ## Closing policy for issues and merge requests -GitLab is a popular open source project and the capacity to deal with issues and merge requests is limited. Out of respect for our volunteers, issues and merge requests not in line with the guidelines listed in this document may be closed without notice. +GitLab is a popular open source project and the capacity to deal with issues +and merge requests is limited. Out of respect for our volunteers, issues and +merge requests not in line with the guidelines listed in this document may be +closed without notice. -Please treat our volunteers with courtesy and respect, it will go a long way towards getting your issue resolved. +Please treat our volunteers with courtesy and respect, it will go a long way +towards getting your issue resolved. -Issues and merge requests should be in English and contain appropriate language for audiences of all ages. +Issues and merge requests should be in English and contain appropriate language +for audiences of all ages. ## Helping others -Please help other GitLab users when you can. -The channnels people will reach out on can be found on the [getting help page](https://about.gitlab.com/getting-help/). -Sign up for the mailinglist, answer GitLab questions on StackOverflow or respond in the irc channel. -You can also sign up on [CodeTriage](http://www.codetriage.com/gitlabhq/gitlabhq) to help with one issue every day. +Please help other GitLab users when you can. The channels people will reach out +on can be found on the [getting help page][]. + +Sign up for the mailing list, answer GitLab questions on StackOverflow or +respond in the IRC channel. You can also sign up on [CodeTriage][] to help with +the remaining issues on the GitHub issue tracker. + +## I want to contribute! + +If you want to contribute to GitLab, but are not sure where to start, +look for [issues with the label `up-for-grabs`][up-for-grabs]. These issues +will be of reasonable size and challenge, for anyone to start contributing to +GitLab. + +This was inspired by [an article by Kent C. Dodds][medium-up-for-grabs]. ## Issue tracker -To get support for your particular problem please use the [getting help channels](https://about.gitlab.com/getting-help/). +To get support for your particular problem please use the +[getting help channels](https://about.gitlab.com/getting-help/). -The [GitLab CE issue tracker on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/issues) is only for obvious errors in the latest [stable or development release of GitLab](MAINTENANCE.md). If something is wrong but it is not a regression compared to older versions of GitLab please do not open an issue but a feature request. When submitting an issue please conform to the issue submission guidelines listed below. Not all issues will be addressed and your issue is more likely to be addressed if you submit a merge request which partially or fully addresses the issue. +The [GitLab CE issue tracker on GitLab.com][ce-tracker] is for bugs concerning +the latest GitLab release and [feature proposals](#feature-proposals). -Do not use the issue tracker for feature requests. We have a specific [feature request forum](http://feedback.gitlab.com) for this purpose. Please keep feature requests as small and simple as possible, complex ones might be edited to make them small and simple. +When submitting an issue please conform to the issue submission guidelines +listed below. Not all issues will be addressed and your issue is more likely to +be addressed if you submit a merge request which partially or fully solves +the issue. -Please send a merge request with a tested solution or a merge request with a failing test instead of opening an issue if you can. If you're unsure where to post, post to the [mailing list](https://groups.google.com/forum/#!forum/gitlabhq) or [Stack Overflow](https://stackoverflow.com/questions/tagged/gitlab) first. There are a lot of helpful GitLab users there who may be able to help you quickly. If your particular issue turns out to be a bug, it will find its way from there. +If you're unsure where to post, post to the [mailing list][google-group] or +[Stack Overflow][stackoverflow] first. There are a lot of helpful GitLab users +there who may be able to help you quickly. If your particular issue turns out +to be a bug, it will find its way from there. + +If it happens that you know the solution to an existing bug, please first +open the issue in order to keep track of it and then open the relevant merge +request that potentially fixes it. + +### Feature proposals + +To create a feature proposal for CE and CI, open an issue on the +[issue tracker of CE][ce-tracker]. + +For feature proposals for EE, open an issue on the +[issue tracker of EE][ee-tracker]. + +In order to help track the feature proposals, we have created a +[`feature proposal`][fpl] label. For the time being, users that are not members +of the project cannot add labels. You can instead ask one of the [core team][] +members to add the label `feature proposal` to the issue. + +Please keep feature proposals as small and simple as possible, complex ones +might be edited to make them small and simple. + +For changes in the interface, it can be helpful to create a mockup first. +If you want to create something yourself, consider opening an issue first to +discuss whether it is interesting to include this in GitLab. ### Issue tracker guidelines -**[Search the issues](https://gitlab.com/gitlab-org/gitlab-ce/issues)** for similar entries before submitting your own, there's a good chance somebody else had the same issue. Show your support with `:+1:` and/or join the discussion. Please submit issues in the following format (as the first post): +**[Search the issue tracker][ce-tracker]** for similar entries before +submitting your own, there's a good chance somebody else had the same issue or +feature proposal. Show your support with an award emoji and/or join the +discussion. -1. **Summary:** Summarize your issue in one sentence (what goes wrong, what did you expect to happen) -1. **Steps to reproduce:** How can we reproduce the issue -1. **Expected behavior:** Describe your issue in detail -1. **Observed behavior** -1. **Relevant logs and/or screenshots:** Please use code blocks (\`\`\`) to format console output, logs, and code as it's very hard to read otherwise. -1. **Output of checks** - * Results of GitLab [Application Check](doc/install/installation.md#check-application-status) (`sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production SANITIZE=true`); we will only investigate if the tests are passing - * Version of GitLab you are running; we will only investigate issues in the latest stable and development releases as per the [maintenance policy](MAINTENANCE.md) - * Add the last commit SHA-1 of the GitLab version you used to replicate the issue (obtainable from the help page) - * Describe your setup (use relevant parts from `sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production`) -1. **Possible fixes**: If you can, link to the line of code that might be responsible for the problem +Please submit bugs using the following template in the issue description area. +The text in the parenthesis is there to help you with what to include. Omit it +when submitting the actual issue. You can copy-paste it and then edit as you +see fit. + +``` +## Summary + +(Summarize your issue in one sentence - what goes wrong, what did you expect to happen) + +## Steps to reproduce + +(How one can reproduce the issue - this is very important) + +## Expected behavior + +(What you should see instead) + +## Relevant logs and/or screenshots + +(Paste any relevant logs - please use code blocks (```) to format console output, +logs, and code as it's very hard to read otherwise.) + +## Output of checks + +### Results of GitLab Application Check + +(For installations with omnibus-gitlab package run and paste the output of: +sudo gitlab-rake gitlab:check SANITIZE=true) + +(For installations from source run and paste the output of: +sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production SANITIZE=true) + +(we will only investigate if the tests are passing) + +### Results of GitLab Environment Info + +(For installations with omnibus-gitlab package run and paste the output of: +sudo gitlab-rake gitlab:env:info) + +(For installations from source run and paste the output of: +sudo -u git -H bundle exec rake gitlab:env:info) + +## Possible fixes + +(If you can, link to the line of code that might be responsible for the problem) + +``` ## Merge requests -We welcome merge requests with fixes and improvements to GitLab code, tests, and/or documentation. The features we would really like a merge request for are listed with the [status 'accepting merge requests' on our feature request forum](http://feedback.gitlab.com/forums/176466-general/status/796455) but other improvements are also welcome. If you want to add a new feature that is not marked it is best to first create a feedback issue (if there isn't one already) and leave a comment asking for it to be marked accepting merge requests. Please include screenshots or wireframes if the feature will also change the UI. +We welcome merge requests with fixes and improvements to GitLab code, tests, +and/or documentation. The features we would really like a merge request for are +listed with the label [`Accepting Merge Requests` on our issue tracker for CE][accepting-mrs-ce] +and [EE][accepting-mrs-ee] but other improvements are also welcome. -Merge requests can be filed either at [gitlab.com](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests) or [github.com](https://github.com/gitlabhq/gitlabhq/pulls). +If you want to add a new feature that is not labeled it is best to first create +a feedback issue (if there isn't one already) and leave a comment asking for it +to be marked as `Accepting merge requests`. Please include screenshots or +wireframes if the feature will also change the UI. -If you are new to GitLab development (or web development in general), search for the label `easyfix` ([gitlab.com](https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=easyfix), [github](https://github.com/gitlabhq/gitlabhq/labels/easyfix)). Those are issues easy to fix, marked by the GitLab core-team. If you are unsure how to proceed but want to help, mention one of the core-team members to give you a hint. +Merge requests can be filed either at [GitLab.com][gitlab-mr-tracker] or at +[github.com][github-mr-tracker]. -To start with GitLab download the [GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit) and see [Development section](doc/development/README.md) in the help file. +If you are new to GitLab development (or web development in general), see the +[I want to contribute!](#i-want-to-contribute) section to get you started with +some potentially easy issues. + +To start with GitLab development download the [GitLab Development Kit][gdk] and +see the [Development section](doc/development/README.md) for some guidelines. ### Merge request guidelines -If you can, please submit a merge request with the fix or improvements including tests. If you don't know how to fix the issue but can write a test that exposes the issue we will accept that as well. In general bug fixes that include a regression test are merged quickly while new features without proper tests are least likely to receive timely feedback. The workflow to make a merge request is as follows: +If you can, please submit a merge request with the fix or improvements +including tests. If you don't know how to fix the issue but can write a test +that exposes the issue we will accept that as well. In general bug fixes that +include a regression test are merged quickly while new features without proper +tests are least likely to receive timely feedback. The workflow to make a merge +request is as follows: 1. Fork the project into your personal space on GitLab.com 1. Create a feature branch 1. Write [tests](https://gitlab.com/gitlab-org/gitlab-development-kit#running-the-tests) and code 1. Add your changes to the [CHANGELOG](CHANGELOG) -1. If you are changing the README, some documentation or other things which have no effect on the tests, add `[ci skip]` somewhere in the commit message -1. If you have multiple commits please combine them into one commit by [squashing them](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits) -1. Push the commit to your fork +1. If you are changing the README, some documentation or other things which + have no effect on the tests, add `[ci skip]` somewhere in the commit message +1. If you have multiple commits please combine them into one commit by + [squashing them][git-squash] +1. Push the commit(s) to your fork 1. Submit a merge request (MR) to the master branch 1. The MR title should describe the change you want to make -1. The MR description should give a motive for your change and the method you used to achieve it +1. The MR description should give a motive for your change and the method you + used to achieve it 1. If the MR changes the UI it should include before and after screenshots -1. If the MR changes CSS classes please include the list of affected pages `grep css-class ./app -R` -1. Link relevant [issues](https://gitlab.com/gitlab-org/gitlab-ce/issues) and/or [feature requests](http://feedback.gitlab.com/) from the merge request description and leave a comment on them with a link back to the MR -1. Be prepared to answer questions and incorporate feedback even if requests for this arrive weeks or months after your MR submission -1. If your MR touches code that executes shell commands, make sure it adheres to the [shell command guidelines]( doc/development/shell_commands.md). -1. Also have a look at the [shell command guidelines](doc/development/shell_commands.md) if your code reads or opens files, or handles paths to files on disk. -1. If your code creates new files on disk please read the [shared files guidelines](doc/development/shared_files.md). +1. If the MR changes CSS classes please include the list of affected pages + `grep css-class ./app -R` +1. Link any relevant [issues][ce-tracker] in the merge request description and + leave a comment on them with a link back to the MR +1. Be prepared to answer questions and incorporate feedback even if requests + for this arrive weeks or months after your MR submission +1. If your MR touches code that executes shell commands, reads or opens files or + handles paths to files on disk, make sure it adheres to the + [shell command guidelines](doc/development/shell_commands.md) +1. If your code creates new files on disk please read the + [shared files guidelines](doc/development/shared_files.md). -The **official merge window** is in the beginning of the month from the 1st to the 7th day of the month. The best time to submit a MR and get feedback fast. -Before this time the GitLab B.V. team is still dealing with work that is created by the monthly release such as regressions requiring patch releases. -After the 7th it is already getting closer to the release date of the next version. This means there is less time to fix the issues created by merging large new features. +The **official merge window** is in the beginning of the month from the 1st to +the 7th day of the month. This is the best time to submit an MR and get +feedback fast. Before this time the GitLab Inc. team is still dealing with work +that is created by the monthly release such as regressions requiring patch +releases. After the 7th it is already getting closer to the release date of the +next version. This means there is less time to fix the issues created by +merging large new features. -Please keep the change in a single MR **as small as possible**. If you want to contribute a large feature think very hard what the minimum viable change is. Can you split functionality? Can you only submit the backend/API code? Can you start with a very simple UI? Can you do part of the refactor? The increased reviewability of small MR's that leads to higher code quality is more important to us than having a minimal commit log. The smaller a MR is the more likely it is it will be merged (quickly), after that you can send more MR's to enhance it. +Please keep the change in a single MR **as small as possible**. If you want to +contribute a large feature think very hard what the minimum viable change is. +Can you split the functionality? Can you only submit the backend/API code? Can +you start with a very simple UI? Can you do part of the refactor? The increased +reviewability of small MRs that leads to higher code quality is more important +to us than having a minimal commit log. The smaller an MR is the more likely it +is it will be merged (quickly). After that you can send more MRs to enhance it. -For examples of feedback on merge requests please look at already [closed merge requests](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests?assignee_id=&label_name=&milestone_id=&scope=&sort=&state=closed). If you would like quick feedback on your merge request feel free to mention one of the Merge Marshalls of [the core-team](https://about.gitlab.com/core-team/). Please ensure that your merge request meets the contribution acceptance criteria. +For examples of feedback on merge requests please look at already +[closed merge requests][]. If you would like quick feedback on your merge +request feel free to mention one of the Merge Marshalls of the [core team][]. +Please ensure that your merge request meets the contribution acceptance criteria. ## Definition of done -If you contribute to GitLab please know that changes involve more than just code. -We have the following [definition of done](http://guide.agilealliance.org/guide/definition-of-done.html). -Please ensure you support the feature you contribute through all of these steps. +If you contribute to GitLab please know that changes involve more than just +code. We have the following [definition of done][]. Please ensure you support +the feature you contribute through all of these steps. -1. Description explaning the relevancy (see following item) +1. Description explaining the relevancy (see following item) 1. Working and clean code that is commented where needed 1. Unit and integration tests that pass on the CI server 1. Documented in the /doc directory @@ -111,14 +251,16 @@ Please ensure you support the feature you contribute through all of these steps. 1. Community questions answered 1. Answers to questions radiated (in docs/wiki/etc.) -If you add a dependency in GitLab (such as an operating system package) please consider updating the following and note the applicability of each in your merge request: +If you add a dependency in GitLab (such as an operating system package) please +consider updating the following and note the applicability of each in your +merge request: 1. Note the addition in the release blog post (create one if it doesn't exist yet) https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/ 1. Upgrade guide, for example https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/7.5-to-7.6.md 1. Upgrader https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/upgrader.md#2-run-gitlab-upgrade-tool 1. Installation guide https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies 1. GitLab Development Kit https://gitlab.com/gitlab-org/gitlab-development-kit -1. Test suite https://gitlab.com/gitlab-org/gitlab-ci/blob/master/doc/examples/configure_a_runner_to_run_the_gitlab_ce_test_suite.md +1. Test suite https://gitlab.com/gitlab-org/gitlab-ce/blob/master/scripts/prepare_build.sh 1. Omnibus package creator https://gitlab.com/gitlab-org/omnibus-gitlab ## Merge request description format @@ -126,59 +268,111 @@ If you add a dependency in GitLab (such as an operating system package) please c 1. What does this MR do? 1. Are there points in the code the reviewer needs to double check? 1. Why was this MR needed? -1. What are the relevant issue numbers / [Feature requests](http://feedback.gitlab.com/)? +1. What are the relevant issue numbers? 1. Screenshots (if relevant) ## Contribution acceptance criteria 1. The change is as small as possible (see the above paragraph for details) -1. Include proper tests and make all tests pass (unless it contains a test exposing a bug in existing code) -1. All tests have to pass, if you suspect a failing CI build is unrelated to your contribution ask for tests to be restarted. See [the CI setup document](http://doc.gitlab.com/ce/development/ci_setup.html) on who you can ask for test restart. -1. Initially contains a single commit (please use `git rebase -i` to squash commits) -1. Can merge without problems (if not please merge `master`, never rebase commits pushed to the remote server) +1. Include proper tests and make all tests pass (unless it contains a test + exposing a bug in existing code) +1. If you suspect a failing CI build is unrelated to your contribution, you may + try and restart the failing CI job or ask a developer to fix the + aforementioned failing test +1. Your MR initially contains a single commit (please use `git rebase -i` to + squash commits) +1. Your changes can merge without problems (if not please merge `master`, never + rebase commits pushed to the remote server) 1. Does not break any existing functionality -1. Fixes one specific issue or implements one specific feature (do not combine things, send separate merge requests if needed) -1. Migrations should do only one thing (eg: either create a table, move data to a new table or remove an old table) to aid retrying on failure +1. Fixes one specific issue or implements one specific feature (do not combine + things, send separate merge requests if needed) +1. Migrations should do only one thing (eg: either create a table, move data to + a new table or remove an old table) to aid retrying on failure 1. Keeps the GitLab code base clean and well structured 1. Contains functionality we think other users will benefit from too 1. Doesn't add configuration options since they complicate future changes -1. Changes after submitting the merge request should be in separate commits (no squashing). You will be asked to squash when the review is over, before merging. -1. It conforms to the following style guides. - If your change touches a line that does not follow the style, - modify the entire line to follow it. This prevents linting tools from generating warnings. - Don't touch neighbouring lines. As an exception, automatic mass refactoring modifications - may leave style non-compliant. +1. Changes after submitting the merge request should be in separate commits + (no squashing). If necessary, you will be asked to squash when the review is + over, before merging. +1. It conforms to the following style guides: + * If your change touches a line that does not follow the style, modify the + entire line to follow it. This prevents linting tools from generating warnings. + * Don't touch neighbouring lines. As an exception, automatic mass + refactoring modifications may leave style non-compliant. ## Style guides 1. [Ruby](https://github.com/bbatsov/ruby-style-guide). - Important sections include [Source Code Layout](https://github.com/bbatsov/ruby-style-guide#source-code-layout) - and [Naming](https://github.com/bbatsov/ruby-style-guide#naming). Use: + Important sections include [Source Code Layout][rss-source] and + [Naming][rss-naming]. Use: - multi-line method chaining style **Option B**: dot `.` on previous line - string literal quoting style **Option A**: single quoted by default 1. [Rails](https://github.com/bbatsov/rails-style-guide) -1. [Testing](https://github.com/thoughtbot/guides/tree/master/style#testing) -1. [CoffeeScript](https://github.com/thoughtbot/guides/tree/master/style#coffeescript) -1. [Shell commands](doc/development/shell_commands.md) created by GitLab contributors to enhance security +1. [Testing](https://github.com/thoughtbot/guides/tree/master/style/testing) +1. [CoffeeScript](https://github.com/thoughtbot/guides/tree/master/style/coffeescript) +1. [Shell commands](doc/development/shell_commands.md) created by GitLab + contributors to enhance security 1. [Markdown](http://www.cirosantilli.com/markdown-styleguide) 1. [Database Migrations](doc/development/migration_style_guide.md) 1. [Documentation styleguide](doc_styleguide.md) -1. Interface text should be written subjectively instead of objectively. It should be the gitlab core team addressing a person. It should be written in present time and never use past tense (has been/was). For example instead of "prohibited this user from being saved due to the following errors:" the text should be "sorry, we could not create your account because:". Also these [excellent writing guidelines](https://github.com/NARKOZ/guides#writing). +1. Interface text should be written subjectively instead of objectively. It + should be the GitLab core team addressing a person. It should be written in + present time and never use past tense (has been/was). For example instead + of _prohibited this user from being saved due to the following errors:_ the + text should be _sorry, we could not create your account because:_ -This is also the style used by linting tools such as [RuboCop](https://github.com/bbatsov/rubocop), [PullReview](https://www.pullreview.com/) and [Hound CI](https://houndci.com). +This is also the style used by linting tools such as +[RuboCop](https://github.com/bbatsov/rubocop), +[PullReview](https://www.pullreview.com/) and [Hound CI](https://houndci.com). ## Code of conduct -As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. +As contributors and maintainers of this project, we pledge to respect all +people who contribute through reporting issues, posting feature requests, +updating documentation, submitting pull requests or patches, and other +activities. -We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. +We are committed to making participation in this project a harassment-free +experience for everyone, regardless of level of experience, gender, gender +identity and expression, sexual orientation, disability, personal appearance, +body size, race, ethnicity, age, or religion. -Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. +Examples of unacceptable behavior by participants include the use of sexual +language or imagery, derogatory comments or personal attacks, trolling, public +or private harassment, insults, or other unprofessional conduct. -Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team. +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct. Project maintainers who do not +follow the Code of Conduct may be removed from the project team. -This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. +This code of conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. -Instances of abusive, harassing, or otherwise unacceptable behavior can be reported by emailing contact@gitlab.com +Instances of abusive, harassing, or otherwise unacceptable behavior can be +reported by emailing `contact@gitlab.com`. -This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.1.0, available at [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/) +This Code of Conduct is adapted from the [Contributor Covenant][], version 1.1.0, +available at [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/). + +[core team]: https://about.gitlab.com/core-team/ +[getting help page]: https://about.gitlab.com/getting-help/ +[Codetriage]: http://www.codetriage.com/gitlabhq/gitlabhq +[up-for-grabs]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=up+for+grabs +[medium-up-for-grabs]: https://medium.com/@kentcdodds/first-timers-only-78281ea47455 +[ce-tracker]: https://gitlab.com/gitlab-org/gitlab-ce/issues +[ee-tracker]: https://gitlab.com/gitlab-org/gitlab-ee/issues +[google-group]: https://groups.google.com/forum/#!forum/gitlabhq +[stackoverflow]: https://stackoverflow.com/questions/tagged/gitlab +[fpl]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=feature+proposal +[accepting-mrs-ce]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=Accepting+Merge+Requests +[accepting-mrs-ee]: https://gitlab.com/gitlab-org/gitlab-ee/issues?label_name=Accepting+Merge+Requests +[gitlab-mr-tracker]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests +[github-mr-tracker]: https://github.com/gitlabhq/gitlabhq/pulls +[gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit +[git-squash]: https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits +[closed merge requests]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests?assignee_id=&label_name=&milestone_id=&scope=&sort=&state=closed +[definition of done]: http://guide.agilealliance.org/guide/definition-of-done.html +[Contributor Covenant]: http://contributor-covenant.org +[rss-source]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#source-code-layout +[rss-naming]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#naming diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION index 743af5e125..d48d3702ae 100644 --- a/GITLAB_SHELL_VERSION +++ b/GITLAB_SHELL_VERSION @@ -1 +1 @@ -2.6.8 +2.6.9 diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION index 2b7c5ae018..4b9fcbec10 100644 --- a/GITLAB_WORKHORSE_VERSION +++ b/GITLAB_WORKHORSE_VERSION @@ -1 +1 @@ -0.4.2 +0.5.1 diff --git a/Gemfile b/Gemfile index 8a19885bcb..26cd52e54d 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,10 @@ source "https://rubygems.org" -gem 'rails', '4.1.12' +gem 'rails', '4.2.4' +gem 'rails-deprecated_sanitizer', '~> 1.0.3' + +# Responders respond_to and respond_with +gem 'responders', '~> 2.0' # Specify a sprockets version due to security issue # See https://groups.google.com/forum/#!topic/rubyonrails-security/doAVp0YaTqY @@ -14,9 +18,9 @@ gem "mysql2", '~> 0.3.16', group: :mysql gem "pg", '~> 0.18.2', group: :postgres # Authentication libraries -gem 'devise', '~> 3.5.2' +gem 'devise', '~> 3.5.3' gem 'devise-async', '~> 0.9.0' -gem 'doorkeeper', '~> 2.1.3' +gem 'doorkeeper', '~> 2.2.0' gem 'omniauth', '~> 1.2.2' gem 'omniauth-bitbucket', '~> 0.0.2' gem 'omniauth-facebook', '~> 3.0.0' @@ -28,7 +32,7 @@ gem 'omniauth-saml', '~> 1.4.0' gem 'omniauth-shibboleth', '~> 1.2.0' gem 'omniauth-twitter', '~> 1.2.0' gem 'omniauth_crowd' -gem 'rack-oauth2', '~> 1.0.5' +gem 'rack-oauth2', '~> 1.2.1' # Two-factor authentication gem 'devise-two-factor', '~> 2.0.0' @@ -48,7 +52,7 @@ gem "gitlab_git", '~> 7.2.20' gem 'gitlab_omniauth-ldap', '~> 1.2.1', require: "omniauth-ldap" # Git Wiki -gem 'gollum-lib', '~> 4.0.2' +gem 'gollum-lib', '~> 4.1.0' # Language detection gem "github-linguist", "~> 4.7.0", require: "linguist" @@ -62,9 +66,6 @@ gem 'rack-cors', '~> 0.4.0', require: 'rack/cors' # based on human-friendly examples gem "stamp", '~> 0.6.0' -# Enumeration fields -gem 'enumerize', '~> 0.7.0' - # Pagination gem "kaminari", "~> 0.16.3" @@ -95,9 +96,13 @@ gem 'redcarpet', '~> 3.3.3' gem 'RedCloth', '~> 4.2.9' gem 'rdoc', '~>3.6' gem 'org-ruby', '~> 0.9.12' -gem 'creole', '~>0.3.6' +gem 'creole', '~> 0.5.0' gem 'wikicloth', '0.8.1' gem 'asciidoctor', '~> 1.5.2' +gem 'rouge', '~> 1.10.1' + +# See https://groups.google.com/forum/#!topic/ruby-security-ann/aSbgDiwb24s +gem 'nokogiri', '1.6.7.1' # Diffs gem 'diffy', '~> 3.0.3' @@ -118,15 +123,15 @@ gem 'acts-as-taggable-on', '~> 3.4' # Background jobs gem 'sinatra', '~> 1.4.4', require: nil -gem 'sidekiq', '3.3.0' -gem 'sidetiq', '~> 0.6.3' +gem 'sidekiq', '~> 4.0' +gem 'sidekiq-cron', '~> 0.4.0' +gem 'redis-namespace' # HTTP requests gem "httparty", '~> 0.13.3' # Colored output to console -gem "colored", '~> 1.2' -gem "colorize", '~> 0.5.8' +gem "colorize", '~> 0.7.0' # GitLab settings gem 'settingslogic', '~> 2.0.9' @@ -154,7 +159,7 @@ gem "gemnasium-gitlab-service", "~> 0.2" gem "slack-notifier", "~> 1.2.0" # Asana integration -gem 'asana', '~> 0.0.6' +gem 'asana', '~> 0.4.0' # FogBugz integration gem 'ruby-fogbugz', '~> 0.2.1' @@ -170,9 +175,10 @@ gem "underscore-rails", "~> 1.4.4" # Sanitize user input gem "sanitize", '~> 2.0' +gem 'babosa', '~> 1.0.2' # Protect against bruteforcing -gem "rack-attack", '~> 4.3.0' +gem "rack-attack", '~> 4.3.1' # Ace editor gem 'ace-rails-ap', '~> 2.0.1' @@ -187,13 +193,13 @@ gem "sass-rails", '~> 4.0.5' gem "coffee-rails", '~> 4.1.0' gem "uglifier", '~> 2.7.2' gem 'turbolinks', '~> 2.5.0' -gem 'jquery-turbolinks', '~> 2.0.1' +gem 'jquery-turbolinks', '~> 2.1.0' gem 'addressable', '~> 2.3.8' gem 'bootstrap-sass', '~> 3.0' gem 'font-awesome-rails', '~> 4.2' -gem 'gitlab_emoji', '~> 0.1' -gem 'gon', '~> 5.0.0' +gem 'gitlab_emoji', '~> 0.2.0' +gem 'gon', '~> 6.0.1' gem 'jquery-atwho-rails', '~> 1.3.2' gem 'jquery-rails', '~> 3.1.3' gem 'jquery-scrollto-rails', '~> 1.4.3' @@ -203,6 +209,7 @@ gem 'raphael-rails', '~> 2.1.2' gem 'request_store', '~> 1.2.0' gem 'select2-rails', '~> 3.5.9' gem 'virtus', '~> 1.0.1' +gem 'net-ssh', '~> 3.0.1' group :development do gem "foreman" @@ -211,9 +218,10 @@ group :development do gem "annotate", "~> 2.6.0" gem "letter_opener", '~> 1.1.2' gem 'quiet_assets', '~> 1.0.2' - gem 'rerun', '~> 0.10.0' + gem 'rerun', '~> 0.11.0' gem 'bullet', require: false gem 'rblineprof', platform: :mri, require: false + gem 'web-console', '~> 2.0' # Better errors handler gem 'better_errors', '~> 1.0.1' @@ -246,7 +254,7 @@ group :development, :test do gem 'capybara', '~> 2.4.0' gem 'capybara-screenshot', '~> 1.0.0' - gem 'poltergeist', '~> 1.6.0' + gem 'poltergeist', '~> 1.8.1' gem 'teaspoon', '~> 1.0.0' gem 'teaspoon-jasmine', '~> 2.2.0' @@ -256,11 +264,12 @@ group :development, :test do gem 'spring-commands-spinach', '~> 1.0.0' gem 'spring-commands-teaspoon', '~> 0.0.2' - gem 'rubocop', '~> 0.28.0', require: false + gem 'rubocop', '~> 0.35.0', require: false gem 'coveralls', '~> 0.8.2', require: false gem 'simplecov', '~> 0.10.0', require: false gem 'flog', require: false gem 'flay', require: false + gem 'bundler-audit', require: false gem 'benchmark-ips', require: false end @@ -269,7 +278,7 @@ group :test do gem 'shoulda-matchers', '~> 2.8.0', require: false gem 'email_spec', '~> 1.6.0' gem 'webmock', '~> 1.21.0' - gem 'test_after_commit', '~> 0.2.2' + gem 'test_after_commit', '~> 0.4.2' gem 'sham_rack' end diff --git a/Gemfile.lock b/Gemfile.lock index 99cdc2a50a..c1c01835e4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,63 +1,71 @@ GEM remote: https://rubygems.org/ specs: - CFPropertyList (2.3.1) + CFPropertyList (2.3.2) RedCloth (4.2.9) ace-rails-ap (2.0.1) - actionmailer (4.1.12) - actionpack (= 4.1.12) - actionview (= 4.1.12) + actionmailer (4.2.4) + actionpack (= 4.2.4) + actionview (= 4.2.4) + activejob (= 4.2.4) mail (~> 2.5, >= 2.5.4) - actionpack (4.1.12) - actionview (= 4.1.12) - activesupport (= 4.1.12) - rack (~> 1.5.2) + rails-dom-testing (~> 1.0, >= 1.0.5) + actionpack (4.2.4) + actionview (= 4.2.4) + activesupport (= 4.2.4) + rack (~> 1.6) rack-test (~> 0.6.2) - actionview (4.1.12) - activesupport (= 4.1.12) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (4.2.4) + activesupport (= 4.2.4) builder (~> 3.1) erubis (~> 2.7.0) - activemodel (4.1.12) - activesupport (= 4.1.12) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + activejob (4.2.4) + activesupport (= 4.2.4) + globalid (>= 0.3.0) + activemodel (4.2.4) + activesupport (= 4.2.4) builder (~> 3.1) - activerecord (4.1.12) - activemodel (= 4.1.12) - activesupport (= 4.1.12) - arel (~> 5.0.0) + activerecord (4.2.4) + activemodel (= 4.2.4) + activesupport (= 4.2.4) + arel (~> 6.0) activerecord-deprecated_finders (1.0.4) - activerecord-session_store (0.1.1) + activerecord-session_store (0.1.2) actionpack (>= 4.0.0, < 5) activerecord (>= 4.0.0, < 5) railties (>= 4.0.0, < 5) - activeresource (4.0.0) - activemodel (~> 4.0) - activesupport (~> 4.0) - rails-observers (~> 0.1.1) - activesupport (4.1.12) - i18n (~> 0.6, >= 0.6.9) + activesupport (4.2.4) + i18n (~> 0.7) json (~> 1.7, >= 1.7.7) minitest (~> 5.1) - thread_safe (~> 0.1) + thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) acts-as-taggable-on (3.5.0) activerecord (>= 3.2, < 5) addressable (2.3.8) - after_commit_queue (1.1.0) - rails (>= 3.0) + after_commit_queue (1.3.0) + activerecord (>= 3.0) annotate (2.6.10) activerecord (>= 3.2, <= 4.3) rake (~> 10.4) - arel (5.0.1.20140414130214) - asana (0.0.6) - activeresource (>= 3.2.3) - asciidoctor (1.5.2) + arel (6.0.3) + asana (0.4.0) + faraday (~> 0.9) + faraday_middleware (~> 0.9) + faraday_middleware-multi_json (~> 0.0) + oauth2 (~> 1.0) + asciidoctor (1.5.3) ast (2.1.0) astrolabe (1.3.1) parser (~> 2.2) attr_encrypted (1.3.4) encryptor (>= 1.3.0) attr_required (1.0.0) - autoprefixer-rails (5.2.1.2) + autoprefixer-rails (6.1.1) execjs json awesome_print (1.2.0) @@ -65,6 +73,7 @@ GEM descendants_tracker (~> 0.0.4) ice_nine (~> 0.11.0) thread_safe (~> 0.3, >= 0.3.1) + babosa (1.0.2) bcrypt (3.1.10) benchmark-ips (2.3.0) better_errors (1.0.1) @@ -85,12 +94,15 @@ GEM ruby_parser (~> 3.5.0) sass (~> 3.0) terminal-table (~> 1.4) - browser (1.0.0) + browser (1.0.1) builder (3.2.2) - bullet (4.14.9) + bullet (4.14.10) activesupport (>= 3.0.0) uniform_notifier (~> 1.9.0) - byebug (6.0.2) + bundler-audit (0.4.0) + bundler (~> 1.2) + thor (~> 0.18) + byebug (8.2.0) cal-heatmap-rails (0.0.1) capybara (2.4.4) mime-types (>= 1.16) @@ -105,10 +117,8 @@ GEM activemodel (>= 3.2.0) activesupport (>= 3.2.0) json (>= 1.7) - celluloid (0.16.0) - timers (~> 4.0.0) charlock_holmes (0.7.3) - chunky_png (1.3.4) + chunky_png (1.3.5) cliver (0.3.2) coderay (1.1.0) coercible (1.0.0) @@ -119,19 +129,20 @@ GEM coffee-script (2.4.1) coffee-script-source execjs - coffee-script-source (1.9.1.1) - colored (1.2) - colorize (0.5.8) + coffee-script-source (1.10.0) + colorize (0.7.7) + concurrent-ruby (1.0.0) connection_pool (2.2.0) - coveralls (0.8.2) + coveralls (0.8.9) json (~> 1.8) rest-client (>= 1.6.8, < 2) simplecov (~> 0.10.0) term-ansicolor (~> 1.3) thor (~> 0.19.1) + tins (~> 1.6.0) crack (0.4.2) safe_yaml (~> 1.0.0) - creole (0.3.8) + creole (0.5.0) d3_rails (3.5.6) railties (>= 3.1.0) daemons (1.2.3) @@ -142,7 +153,7 @@ GEM activerecord (>= 3.2.0, < 5.0) descendants_tracker (0.0.4) thread_safe (~> 0.3, >= 0.3.1) - devise (3.5.2) + devise (3.5.3) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 3.2.6, < 5) @@ -151,7 +162,7 @@ GEM warden (~> 1.2.3) devise-async (0.9.0) devise (~> 3.2) - devise-two-factor (2.0.0) + devise-two-factor (2.0.1) activesupport attr_encrypted (~> 1.3.2) devise (~> 3.5.0) @@ -160,19 +171,17 @@ GEM diff-lcs (1.2.5) diffy (3.0.7) docile (1.1.5) - domain_name (0.5.24) + domain_name (0.5.25) unf (>= 0.0.5, < 1.0.0) - doorkeeper (2.1.4) + doorkeeper (2.2.2) railties (>= 3.2) - dropzonejs-rails (0.7.1) + dropzonejs-rails (0.7.2) rails (> 3.1) email_reply_parser (0.5.8) email_spec (1.6.0) launchy (~> 2.1) mail (~> 2.2) encryptor (1.3.0) - enumerize (0.7.0) - activesupport (>= 3.2) equalizer (0.0.11) erubis (2.7.0) escape_utils (1.1.0) @@ -189,6 +198,9 @@ GEM multipart-post (>= 1.2, < 3) faraday_middleware (0.10.0) faraday (>= 0.7.4, < 0.10) + faraday_middleware-multi_json (0.0.6) + faraday_middleware + multi_json fastercsv (1.5.5) ffaker (2.0.0) ffi (1.9.10) @@ -200,7 +212,7 @@ GEM flog (4.3.2) ruby_parser (~> 3.1, > 3.1.0) sexp_processor (~> 4.4) - flowdock (0.7.0) + flowdock (0.7.1) httparty (~> 0.7) multi_json fog (1.25.0) @@ -222,13 +234,10 @@ GEM fog-core (~> 1.22) fog-json inflecto (~> 0.0.2) - fog-core (1.32.1) + fog-core (1.35.0) builder excon (~> 0.45) formatador (~> 0.2) - mime-types - net-scp (~> 1.1) - net-ssh (>= 2.1.3) fog-json (1.0.2) fog-core (~> 1.0) multi_json (~> 1.10) @@ -240,10 +249,10 @@ GEM fog-core (>= 1.21.0) fog-json fog-xml (>= 0.0.1) - fog-sakuracloud (1.0.1) + fog-sakuracloud (1.4.0) fog-core fog-json - fog-softlayer (0.4.7) + fog-softlayer (1.0.2) fog-core fog-json fog-terremark (0.1.0) @@ -258,7 +267,7 @@ GEM fog-xml (0.1.2) fog-core nokogiri (~> 1.5, >= 1.5.11) - font-awesome-rails (4.4.0.0) + font-awesome-rails (4.5.0.0) railties (>= 3.2, < 5.0) foreman (0.78.0) thor (~> 0.19.1) @@ -268,11 +277,11 @@ GEM ruby-progressbar (~> 1.4) gemnasium-gitlab-service (0.2.6) rugged (~> 0.21) - gemojione (2.0.1) + gemojione (2.1.0) json get_process_mem (0.2.0) gherkin-ruby (0.3.2) - github-linguist (4.7.0) + github-linguist (4.7.2) charlock_holmes (~> 0.7.3) escape_utils (~> 1.1.0) mime-types (>= 1.19) @@ -287,9 +296,9 @@ GEM diff-lcs (~> 1.1) mime-types (~> 1.15) posix-spawn (~> 0.3) - gitlab_emoji (0.1.1) - gemojione (~> 2.0) - gitlab_git (7.2.20) + gitlab_emoji (0.2.0) + gemojione (~> 2.1) + gitlab_git (7.2.21) activesupport (~> 4.0) charlock_holmes (~> 0.7.3) github-linguist (~> 4.7.0) @@ -300,18 +309,22 @@ GEM omniauth (~> 1.0) pyu-ruby-sasl (~> 0.0.3.1) rubyntlm (~> 0.3) + globalid (0.3.6) + activesupport (>= 4.1.0) gollum-grit_adapter (1.0.0) gitlab-grit (~> 2.7, >= 2.7.1) - gollum-lib (4.0.3) + gollum-lib (4.1.0) github-markup (~> 1.3.3) gollum-grit_adapter (~> 1.0) nokogiri (~> 1.6.4) - rouge (~> 1.10.1) + rouge (~> 1.9) sanitize (~> 2.1.0) stringex (~> 2.5.1) - gon (5.0.4) - actionpack (>= 2.3.0) + gon (6.0.1) + actionpack (>= 3.0) json + multi_json + request_store (>= 1.0) grape (0.13.0) activesupport builder @@ -333,13 +346,12 @@ GEM haml (>= 4.0.6, < 5.0) html2haml (>= 1.0.1) railties (>= 4.0.1) - hashie (3.4.2) + hashie (3.4.3) highline (1.6.21) hike (1.2.3) hipchat (1.5.2) httparty mimemagic - hitimes (1.2.3) html-pipeline (1.11.0) activesupport (>= 2) nokogiri (~> 1.4) @@ -351,40 +363,40 @@ GEM http-cookie (1.0.2) domain_name (~> 0.5) http_parser.rb (0.5.3) - httparty (0.13.5) + httparty (0.13.7) json (~> 1.8) multi_xml (>= 0.5.2) - httpclient (2.6.0.1) + httpclient (2.7.0.1) i18n (0.7.0) - ice_cube (0.11.1) ice_nine (0.11.1) inflecto (0.0.2) ipaddress (0.8.0) jquery-atwho-rails (1.3.2) - jquery-rails (3.1.3) + jquery-rails (3.1.4) railties (>= 3.0, < 5.0) thor (>= 0.14, < 2.0) jquery-scrollto-rails (1.4.3) railties (> 3.1, < 5.0) - jquery-turbolinks (2.0.2) + jquery-turbolinks (2.1.0) railties (>= 3.1.0) turbolinks jquery-ui-rails (4.2.1) railties (>= 3.2.16) json (1.8.3) - jwt (1.5.1) + jwt (1.5.2) kaminari (0.16.3) actionpack (>= 3.0.0) activesupport (>= 3.0.0) - kgio (2.9.3) + kgio (2.10.0) launchy (2.4.3) addressable (~> 2.3) letter_opener (1.1.2) launchy (~> 2.2) - listen (2.10.1) - celluloid (~> 0.16.0) + listen (3.0.5) rb-fsevent (>= 0.9.3) rb-inotify (>= 0.9) + loofah (2.0.3) + nokogiri (>= 1.5.9) macaddr (1.7.1) systemu (~> 2.6.2) mail (2.6.3) @@ -393,7 +405,7 @@ GEM method_source (0.8.2) mime-types (1.25.1) mimemagic (0.3.0) - mini_portile (0.6.2) + mini_portile2 (2.0.0) minitest (5.7.0) mousetrap-rails (1.4.6) multi_json (1.11.2) @@ -401,17 +413,15 @@ GEM multipart-post (2.0.0) mysql2 (0.3.20) nested_form (0.3.2) - net-ldap (0.11) - net-scp (1.2.1) - net-ssh (>= 2.6.5) - net-ssh (2.9.2) - netrc (0.10.3) + net-ldap (0.12.1) + net-ssh (3.0.1) + netrc (0.11.0) newrelic-grape (2.0.0) grape newrelic_rpm newrelic_rpm (3.9.4.245) - nokogiri (1.6.6.2) - mini_portile (~> 0.6.0) + nokogiri (1.6.7.1) + mini_portile2 (~> 2.0.0.rc2) nprogress-rails (0.1.6.7) oauth (0.4.7) oauth2 (1.0.0) @@ -434,12 +444,15 @@ GEM omniauth-github (1.1.2) omniauth (~> 1.0) omniauth-oauth2 (~> 1.1) - omniauth-gitlab (1.0.0) + omniauth-gitlab (1.0.1) omniauth (~> 1.0) omniauth-oauth2 (~> 1.0) - omniauth-google-oauth2 (0.2.6) - omniauth (> 1.0) - omniauth-oauth2 (~> 1.1) + omniauth-google-oauth2 (0.2.10) + addressable (~> 2.3) + jwt (~> 1.0) + multi_json (~> 1.3) + omniauth (>= 1.1.1) + omniauth-oauth2 (~> 1.3.1) omniauth-kerberos (0.3.0) omniauth-multipassword timfel-krb5-auth (~> 0.8) @@ -463,26 +476,26 @@ GEM activesupport nokogiri (>= 1.4.4) omniauth (~> 1.0) - opennebula (4.12.1) + opennebula (4.14.2) json nokogiri rbvmomi org-ruby (0.9.12) rubypants (~> 0.2) orm_adapter (0.5.0) - paranoia (2.1.3) + paranoia (2.1.4) activerecord (~> 4.0) - parser (2.2.2.6) + parser (2.2.3.0) ast (>= 1.1, < 3.0) - pg (0.18.2) - poltergeist (1.6.0) + pg (0.18.4) + poltergeist (1.8.1) capybara (~> 2.1) cliver (~> 0.3.1) multi_json (~> 1.0) websocket-driver (>= 0.2.0) posix-spawn (0.3.11) - powerpack (0.0.9) - pry (0.10.1) + powerpack (0.1.1) + pry (0.10.3) coderay (~> 1.1.0) method_source (~> 0.8.1) slop (~> 3.4) @@ -491,15 +504,15 @@ GEM pyu-ruby-sasl (0.0.3.3) quiet_assets (1.0.3) railties (>= 3.1, < 5.0) - rack (1.5.5) + rack (1.6.4) rack-accept (0.4.5) rack (>= 0.4) - rack-attack (4.3.0) + rack-attack (4.3.1) rack rack-cors (0.4.0) rack-mount (0.8.3) rack (>= 1.0.0) - rack-oauth2 (1.0.10) + rack-oauth2 (1.2.1) activesupport (>= 2.3) attr_required (>= 0.0.5) httpclient (>= 2.4) @@ -509,28 +522,35 @@ GEM rack rack-test (0.6.3) rack (>= 1.0) - rails (4.1.12) - actionmailer (= 4.1.12) - actionpack (= 4.1.12) - actionview (= 4.1.12) - activemodel (= 4.1.12) - activerecord (= 4.1.12) - activesupport (= 4.1.12) + rails (4.2.4) + actionmailer (= 4.2.4) + actionpack (= 4.2.4) + actionview (= 4.2.4) + activejob (= 4.2.4) + activemodel (= 4.2.4) + activerecord (= 4.2.4) + activesupport (= 4.2.4) bundler (>= 1.3.0, < 2.0) - railties (= 4.1.12) - sprockets-rails (~> 2.0) - rails-observers (0.1.2) - activemodel (~> 4.0) - railties (4.1.12) - actionpack (= 4.1.12) - activesupport (= 4.1.12) + railties (= 4.2.4) + sprockets-rails + rails-deprecated_sanitizer (1.0.3) + activesupport (>= 4.2.0.alpha) + rails-dom-testing (1.0.7) + activesupport (>= 4.2.0.beta, < 5.0) + nokogiri (~> 1.6.0) + rails-deprecated_sanitizer (>= 1.0.1) + rails-html-sanitizer (1.0.2) + loofah (~> 2.0) + railties (4.2.4) + actionpack (= 4.2.4) + activesupport (= 4.2.4) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) rainbow (2.0.0) raindrops (0.15.0) rake (10.4.2) raphael-rails (2.1.2) - rb-fsevent (0.9.5) + rb-fsevent (0.9.6) rb-inotify (0.9.5) ffi (>= 0.5.0) rblineprof (0.3.6) @@ -542,13 +562,13 @@ GEM rdoc (3.12.2) json (~> 1.4) redcarpet (3.3.3) - redis (3.2.1) - redis-actionpack (4.0.0) + redis (3.2.2) + redis-actionpack (4.0.1) actionpack (~> 4) redis-rack (~> 1.5.0) redis-store (~> 1.1.0) - redis-activesupport (4.1.1) - activesupport (~> 4) + redis-activesupport (4.1.5) + activesupport (>= 3, < 5) redis-store (~> 1.1.0) redis-namespace (1.5.2) redis (~> 3.0, >= 3.0.4) @@ -559,13 +579,13 @@ GEM redis-actionpack (~> 4) redis-activesupport (~> 4) redis-store (~> 1.1.0) - redis-store (1.1.6) + redis-store (1.1.7) redis (>= 2.2) - request_store (1.2.0) - rerun (0.10.0) - listen (~> 2.7, >= 2.7.3) - responders (1.1.2) - railties (>= 3.2, < 4.2) + request_store (1.2.1) + rerun (0.11.0) + listen (~> 3.0) + responders (2.1.0) + railties (>= 4.2.0, < 5) rest-client (1.8.0) http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 3.0) @@ -598,12 +618,13 @@ GEM rspec-mocks (~> 3.3.0) rspec-support (~> 3.3.0) rspec-support (3.3.0) - rubocop (0.28.0) + rubocop (0.35.1) astrolabe (~> 1.3) - parser (>= 2.2.0.pre.7, < 3.0) - powerpack (~> 0.0.6) + parser (>= 2.2.3.0, < 3.0) + powerpack (~> 0.1) rainbow (>= 1.99.1, < 3.0) - ruby-progressbar (~> 1.4) + ruby-progressbar (~> 1.7) + tins (<= 1.6.0) ruby-fogbugz (0.2.1) crack (~> 0.4) ruby-progressbar (1.7.5) @@ -617,6 +638,7 @@ GEM sexp_processor (~> 4.1) rubyntlm (0.5.2) rubypants (0.2.0) + rufus-scheduler (3.1.10) rugged (0.23.3) safe_yaml (1.0.4) sanitize (2.1.0) @@ -644,16 +666,15 @@ GEM rack shoulda-matchers (2.8.0) activesupport (>= 3.0.0) - sidekiq (3.3.0) - celluloid (>= 0.16.0) - connection_pool (>= 2.0.0) - json - redis (>= 3.0.6) - redis-namespace (>= 1.3.1) - sidetiq (0.6.3) - celluloid (>= 0.14.1) - ice_cube (= 0.11.1) - sidekiq (>= 3.0.0) + sidekiq (4.0.1) + concurrent-ruby (~> 1.0) + connection_pool (~> 2.2, >= 2.2.0) + json (~> 1.0) + redis (~> 3.2, >= 3.2.1) + sidekiq-cron (0.4.0) + redis-namespace (>= 1.5.2) + rufus-scheduler (>= 2.0.24) + sidekiq (>= 4.0.0) simple_oauth (0.1.9) simplecov (0.10.0) docile (~> 1.1.0) @@ -687,7 +708,7 @@ GEM multi_json (~> 1.0) rack (~> 1.0) tilt (~> 1.1, != 1.3.0) - sprockets-rails (2.3.2) + sprockets-rails (2.3.3) actionpack (>= 3.0) activesupport (>= 3.0) sprockets (>= 2.8, < 4.0) @@ -710,17 +731,15 @@ GEM term-ansicolor (1.3.2) tins (~> 1.0) terminal-table (1.5.2) - test_after_commit (0.2.7) + test_after_commit (0.4.2) activerecord (>= 3.2) - thin (1.6.3) + thin (1.6.4) daemons (~> 1.0, >= 1.0.9) - eventmachine (~> 1.0) + eventmachine (~> 1.0, >= 1.0.4) rack (~> 1.0) thor (0.19.1) thread_safe (0.3.5) tilt (1.4.1) - timers (4.0.4) - hitimes timfel-krb5-auth (0.8.3) tinder (1.10.1) eventmachine (~> 1.0) @@ -752,9 +771,9 @@ GEM kgio (~> 2.6) rack raindrops (~> 0.7) - unicorn-worker-killer (0.4.3) + unicorn-worker-killer (0.4.4) get_process_mem (~> 0) - unicorn (~> 4) + unicorn (>= 4, < 6) uniform_notifier (1.9.0) uuid (2.3.8) macaddr (~> 1.0) @@ -766,10 +785,15 @@ GEM equalizer (~> 0.0, >= 0.0.9) warden (1.2.3) rack (>= 1.0) + web-console (2.2.1) + activemodel (>= 4.0) + binding_of_caller (>= 0.7.2) + railties (>= 4.0) + sprockets-rails (>= 2.0, < 4.0) webmock (1.21.0) addressable (>= 2.3.6) crack (>= 0.3.2) - websocket-driver (0.6.2) + websocket-driver (0.6.3) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.2) wikicloth (0.8.1) @@ -791,10 +815,11 @@ DEPENDENCIES addressable (~> 2.3.8) after_commit_queue annotate (~> 2.6.0) - asana (~> 0.0.6) + asana (~> 0.4.0) asciidoctor (~> 1.5.2) attr_encrypted (~> 1.3.4) awesome_print (~> 1.2.0) + babosa (~> 1.0.2) benchmark-ips better_errors (~> 1.0.1) binding_of_caller (~> 0.7.2) @@ -802,6 +827,7 @@ DEPENDENCIES brakeman (= 3.0.1) browser (~> 1.0.0) bullet + bundler-audit byebug cal-heatmap-rails (~> 0.0.1) capybara (~> 2.4.0) @@ -809,22 +835,20 @@ DEPENDENCIES carrierwave (~> 0.9.0) charlock_holmes (~> 0.7.3) coffee-rails (~> 4.1.0) - colored (~> 1.2) - colorize (~> 0.5.8) + colorize (~> 0.7.0) coveralls (~> 0.8.2) - creole (~> 0.3.6) + creole (~> 0.5.0) d3_rails (~> 3.5.5) database_cleaner (~> 1.4.0) default_value_for (~> 3.0.0) - devise (~> 3.5.2) + devise (~> 3.5.3) devise-async (~> 0.9.0) devise-two-factor (~> 2.0.0) diffy (~> 3.0.3) - doorkeeper (~> 2.1.3) + doorkeeper (~> 2.2.0) dropzonejs-rails (~> 0.7.1) email_reply_parser (~> 0.5.8) email_spec (~> 1.6.0) - enumerize (~> 0.7.0) factory_girl_rails (~> 4.3.0) ffaker (~> 2.0.0) flay @@ -837,12 +861,12 @@ DEPENDENCIES github-linguist (~> 4.7.0) github-markup (~> 1.3.1) gitlab-flowdock-git-hook (~> 1.0.1) - gitlab_emoji (~> 0.1) + gitlab_emoji (~> 0.2.0) gitlab_git (~> 7.2.20) gitlab_meta (= 7.0) gitlab_omniauth-ldap (~> 1.2.1) - gollum-lib (~> 4.0.2) - gon (~> 5.0.0) + gollum-lib (~> 4.1.0) + gon (~> 6.0.1) grape (~> 0.13.0) grape-entity (~> 0.4.2) haml-rails (~> 0.9.0) @@ -852,7 +876,7 @@ DEPENDENCIES jquery-atwho-rails (~> 1.3.2) jquery-rails (~> 3.1.3) jquery-scrollto-rails (~> 1.4.3) - jquery-turbolinks (~> 2.0.1) + jquery-turbolinks (~> 2.1.0) jquery-ui-rails (~> 4.2.1) kaminari (~> 0.16.3) letter_opener (~> 1.1.2) @@ -861,8 +885,10 @@ DEPENDENCIES mousetrap-rails (~> 1.4.6) mysql2 (~> 0.3.16) nested_form (~> 0.3.2) + net-ssh (~> 3.0.1) newrelic-grape newrelic_rpm (~> 3.9.4.245) + nokogiri (= 1.6.7.1) nprogress-rails (~> 0.1.6.7) oauth2 (~> 1.0.0) octokit (~> 3.7.0) @@ -880,23 +906,27 @@ DEPENDENCIES org-ruby (~> 0.9.12) paranoia (~> 2.0) pg (~> 0.18.2) - poltergeist (~> 1.6.0) + poltergeist (~> 1.8.1) pry-rails quiet_assets (~> 1.0.2) - rack-attack (~> 4.3.0) + rack-attack (~> 4.3.1) rack-cors (~> 0.4.0) - rack-oauth2 (~> 1.0.5) - rails (= 4.1.12) + rack-oauth2 (~> 1.2.1) + rails (= 4.2.4) + rails-deprecated_sanitizer (~> 1.0.3) raphael-rails (~> 2.1.2) rblineprof rdoc (~> 3.6) redcarpet (~> 3.3.3) + redis-namespace redis-rails (~> 4.0.0) request_store (~> 1.2.0) - rerun (~> 0.10.0) + rerun (~> 0.11.0) + responders (~> 2.0) + rouge (~> 1.10.1) rqrcode-rails3 (~> 0.1.7) rspec-rails (~> 3.3.0) - rubocop (~> 0.28.0) + rubocop (~> 0.35.0) ruby-fogbugz (~> 0.2.1) sanitize (~> 2.0) sass-rails (~> 4.0.5) @@ -906,8 +936,8 @@ DEPENDENCIES settingslogic (~> 2.0.9) sham_rack shoulda-matchers (~> 2.8.0) - sidekiq (= 3.3.0) - sidetiq (~> 0.6.3) + sidekiq (~> 4.0) + sidekiq-cron (~> 0.4.0) simplecov (~> 0.10.0) sinatra (~> 1.4.4) six (~> 0.2.0) @@ -923,7 +953,7 @@ DEPENDENCIES task_list (~> 1.0.2) teaspoon (~> 1.0.0) teaspoon-jasmine (~> 2.2.0) - test_after_commit (~> 0.2.2) + test_after_commit (~> 0.4.2) thin (~> 1.6.1) tinder (~> 1.10.0) turbolinks (~> 2.5.0) @@ -934,6 +964,7 @@ DEPENDENCIES unicorn-worker-killer (~> 0.4.2) version_sorter (~> 2.0.0) virtus (~> 1.0.1) + web-console (~> 2.0) webmock (~> 1.21.0) wikicloth (= 0.8.1) diff --git a/PROCESS.md b/PROCESS.md index a4b0c83644..5f4d67bc10 100644 --- a/PROCESS.md +++ b/PROCESS.md @@ -8,7 +8,7 @@ Below we describe the contributing process to GitLab for two reasons. So that co ### Issue team - Looks for issues without [workflow labels](#how-we-handle-issues) and triages issue -- Closes invalid issues with a comment (duplicates, [feature requests](#feature-requests), [fixed in newer version](#issue-fixed-in-newer-version), [issue report for old version](#issue-report-for-old-version), not a problem in GitLab, etc.) +- Closes invalid issues with a comment (duplicates, [fixed in newer version](#issue-fixed-in-newer-version), [issue report for old version](#issue-report-for-old-version), not a problem in GitLab, etc.) - Asks for feedback from issue reporter ([invalid issue reports](#improperly-formatted-issue), [format code](#code-format), etc.) - Monitors all issues for feedback (but especially ones commented on since automatically watching them) - Closes issues with no feedback from the reporter for two weeks @@ -34,13 +34,21 @@ The most important thing is making sure valid issues receive feedback from the d ## Workflow labels -Workflow labels are purposely not very detailed since that would be hard to keep updated as you would need to re-evaluate them after every comment. We optionally use functional labels on demand when want to group related issues to get an overview (for example all issues related to RVM, to tackle them in one go) and to add details to the issue. +Workflow labels are purposely not very detailed since that would be hard to keep updated as you would need to re-evaluate them after every comment. We optionally use functional labels on demand when want to group related issues to get an overview (for example all issues related to RVM, to tackle them in one go) and to add details to the issue. - *Awaiting feedback*: Feedback pending from the reporter - *Awaiting confirmation of fix*: The issue should already be solved in **master** (generally you can avoid this workflow item and just close the issue right away) - *Attached MR*: There is a MR attached and the discussion should happen there - We need to let issues stay in sync with the MR's. We can do this with a "Closing #XXXX" or "Fixes #XXXX" comment in the MR. We can't close the issue when there is a merge request because sometimes a MR is not good and we just close the MR, then the issue must stay. -- *Awaiting developer action/feedback*: Issue needs to be fixed or clarified by a developer +- *Developer*: needs help from a developer +- *UX* needs needs help from a UX designer +- *Frontend* needs help from a Front-end engineer +- *Graphics* needs help from a Graphics designer +- *up-for-grabs* is an issue suitable for first-time contributors, of reasonable difficulty and size. Not exclusive with other labels. +- *feature proposal* is a proposal for a new feature for GitLab. People are encouraged to vote +in support or comment for further detail. Do not use `feature request`. + +Example workflow: when a UX designer provided a design but it needs frontend work they remove the UX label and add the frontend label. ## Functional labels @@ -56,7 +64,6 @@ If an issue is complex and needs the attention of a specific person, assignment - Bright orange `#eb6420`: workflow labels for core team members (attached MR, awaiting developer action/feedback) - Light blue `#82C5FF`: functional labels - Green labels `#009800`: issues that can generally be ignored. For example, issues given the following labels normally can be closed immediately: - - Feature request (see copy & paste response: [Feature requests](#feature-requests)) - Support (see copy & paste response: [Support requests and configuration questions](#support-requests-and-configuration-questions) ## Be kind @@ -69,10 +76,6 @@ Be kind to people trying to contribute. Be aware that people may be a non-native Thanks for the issue report. Please reformat your issue to conform to the issue tracker guidelines found in our \[contributing guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#issue-tracker-guidelines). -### Feature requests - -Thank you for your interest in improving GitLab. We don't use the issue tracker for feature requests. Things that are wrong but are not a regression compared to older versions of GitLab are considered feature requests and not issues. Please use the \[feature request forum\]\(http://feedback.gitlab.com/) for this purpose or create a merge request implementing this feature. Have a look at the \[contribution guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) for more information. - ### Issue report for old version Thanks for the issue report but we only support issues for the latest stable version of GitLab. I'm closing this issue but if you still experience this problem in the latest stable version, please open a new issue (but also reference the old issue(s)). Make sure to also include the necessary debugging information conforming to the issue tracker guidelines found in our \[contributing guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#issue-tracker-guidelines). @@ -107,7 +110,12 @@ This merge request has been closed because a request for more information has no ### Accepting merge requests -Is there a request on [the feature request forum](http://feedback.gitlab.com/forums/176466-general) that is similar to this? If so, can you make a comment with a link to it? Please be aware that new functionality that is not marked [accepting merge/pull requests](http://feedback.gitlab.com/forums/176466-general/status/796455) on the forum might not make it into GitLab. You might be asked to make changes and even after implementing them your feature might still be declined. If you want to reduce the chance of this happening please have a discussion in the forum first. +Is there an issue on the [issue tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues) +that is similar to this? +Could you please link it here? +Please be aware that new functionality that is not marked +[accepting merge requests](https://gitlab.com/gitlab-org/gitlab-ce/issues?milestone_id=&scope=all&sort=created_desc&state=opened&utf8=%E2%9C%93&assignee_id=&author_id=&milestone_title=&label_name=Accepting+Merge+Requests) +might not make it into GitLab. ### Only accepting merge requests with green tests diff --git a/Procfile b/Procfile index 08880b9c42..9cfdee7040 100644 --- a/Procfile +++ b/Procfile @@ -1,3 +1,7 @@ +# For DEVELOPMENT only. Production uses Runit in +# https://gitlab.com/gitlab-org/omnibus-gitlab or the init scripts in +# lib/support/init.d, which call scripts in bin/ . +# web: bundle exec unicorn_rails -p ${PORT:="3000"} -E ${RAILS_ENV:="development"} -c ${UNICORN_CONFIG:="config/unicorn.rb"} -worker: bundle exec sidekiq -q post_receive -q mailer -q archive_repo -q system_hook -q project_web_hook -q gitlab_shell -q incoming_email -q runner -q common -q default +worker: bundle exec sidekiq -q post_receive -q mailers -q archive_repo -q system_hook -q project_web_hook -q gitlab_shell -q incoming_email -q runner -q common -q default # mail_room: bundle exec mail_room -q -c config/mail_room.yml diff --git a/README.md b/README.md index 52e2d97762..3ec1d4a776 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,6 @@ There are two editions of GitLab: - GitLab Community Edition (CE) is available freely under the MIT Expat license. - GitLab Enterprise Edition (EE) includes [extra features](https://about.gitlab.com/features/#compare) that are more useful for organizations with more than 100 users. To use EE and get official support please [become a subscriber](https://about.gitlab.com/pricing/). -Included with the GitLab Omnibus Packages is [GitLab CI](https://about.gitlab.com/gitlab-ci/) that can easily build, test and deploy code. - ## Website On [about.gitlab.com](https://about.gitlab.com/) you can find more information about: @@ -71,7 +69,7 @@ GitLab is a Ruby on Rails application that runs on the following software: - Ubuntu/Debian/CentOS/RHEL - Ruby (MRI) 2.1 - Git 1.7.10+ -- Redis 2.4+ +- Redis 2.8+ - MySQL or PostgreSQL For more information please see the [architecture documentation](http://doc.gitlab.com/ce/development/architecture.html). @@ -82,7 +80,7 @@ There are a lot of [third-party applications integrating with GitLab](https://ab ## GitLab release cycle -Since 2011 a minor or major version of GitLab is released on the 22nd of every month. Patch and security releases are published when needed. New features are detailed on the [blog](https://about.gitlab.com/blog/) and in the [changelog](CHANGELOG). For more information about the release process see the [release documentation](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/release). Features that will likely be in the next releases can be found on the [feature request forum](http://feedback.gitlab.com/forums/176466-general) with the status [started](http://feedback.gitlab.com/forums/176466-general/status/796456) and [completed](http://feedback.gitlab.com/forums/176466-general/status/796457). +For more information about the release process see the [release documentation](http://doc.gitlab.com/ce/release/). ## Upgrading diff --git a/VERSION b/VERSION index 797ed2e270..9f4a0fbc18 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.2.1 \ No newline at end of file +8.3.0 \ No newline at end of file diff --git a/app/assets/images/icon-link.png b/app/assets/images/icon-link.png index 60021d5ac47686cce70570d22bad6670082caf56..7d89da97e11a0030fbab56b3d172f547ac9f896e 100644 GIT binary patch delta 1118 zcmV-k1fl!Z1?UKn8Gi%-0001Bxm5rF00d`2O+f$vv5yPND(xlykug~ z(jlQpiNYu_qFZ%}@X|F5QIH}KvO07LD$zq3Y#4a4E`1Po34aqMjXVU4xn>Gw5F!0L zxUTNJGdnZy&i2m9WgdUO_nn=2o@ZY{_`jw&iV4hN6{V;{6PmGAXeZP2h%rhbjdFHy zndiGiVO2)_+URAD1nlrCh5w8XDtK9Y7rd;H zHGY;g3Pc{;IDg1z>}0t?At(4k4x|8a)+-hI=s`e-f0VY$^Gbz$#+apm9bT_c&Ut1b zV2{@;w385FlhGR{@Dp)N;x)b|KP$ih&T7(5f-RVmKHG-4k8SvuW4y?S_UDvMv4^C;7hS&tPq;6z zjzzr8gz@pOjWH>9mkT_>q^L{w_?nFPwb7GN zVUiVrh#{Z&%nB-e8Grf3>lIXZ!7iIz;D%Q#sPVO2F$?I*jWZnLD6a=jHkE=JAK{oe z9jo#Ae1Dh%EU;0T6Q`INzlFo*f<%Y!PrJXxfWqdaq{GL|C7B&QsNjaz3fSY*60xo!+ zf-8QLfGb|5;EqoTnDO6~J#dtZsTmU?@JWFMWq-9JZ@f;$9KoHu$B!Im4~s+KlLD<4 zc)fytnDGRNrw+%Ci-HZF01>suyC~S<2~0ZSZ53?s1a1a`9~eWs4fsf^+^`V1AO*Ks zh4u$3{LTB~tu>y&Q7L@TGWZM6u`mEH;Z^={z!L?lQoC4e*=AOYe%xRTuP}}8$U_D8 zqJJ4D9U9f-by~WIPAC8DM_!#IbQf{suQsz>^7ooyB(RS4oHzD(rM$w=UY?cs%_=NO zQhV?MJ2Y!K#TFz000Ip-j0RMr1O;exUHkQm=um7W-BSpYa1Gm#SXTa1m4bhKG8>LC z-$Ef5_*6l1M|q~zb1utr!&-poRVq}nkALs^j@`sQ@w0c18m5GInvrbGpv(#$<`Z zc!_B&LZAZmID!+1giSfx>mM(EC1m0-Z@jK~#7Foz+1|R8bhk@$b%HFpDX2Hkw2Z zx|A?z5W+>c5W+>ERL~-&MTnbRrXdPa5Q0{;3pB}~G$s^gQ|*G72sFe9MHi9CXo`>) zE}|32#c%lDJMzY}z4QOA=H4fWyoKS8=BBou+#ZS-8OUawUw^81yL4cq#TBh0S1PcS z_Nia|QE9+pm9rZn0PU$DrS>XB1(r;&LNs9I%s~-rotWuM89}1=WzPX%wN8Z*0+9YC z_E%6Lo+SY7t&l1Zfc94CIvn`$dTj98DeZ$oVoL$GfB9Pp?X55>h_KanFk7qiK)c{* z8}UE`2j(7Jzkhh4rF&`zVVm_p4FjgmIltuXbp)69r?uh0`XyJi@>d9Kz@IgS0xRbI zh~0zPe9|9v3i url = Api.buildUrl(Api.group_path) @@ -44,6 +46,35 @@ ).done (namespaces) -> callback(namespaces) + # Return projects list. Filtered by query + projects: (query, callback) -> + url = Api.buildUrl(Api.projects_path) + + $.ajax( + url: url + data: + private_token: gon.api_token + search: query + per_page: 20 + dataType: "json" + ).done (projects) -> + callback(projects) + + # Return group projects list. Filtered by query + groupProjects: (group_id, query, callback) -> + url = Api.buildUrl(Api.group_projects_path) + url = url.replace(':id', group_id) + + $.ajax( + url: url + data: + private_token: gon.api_token + search: query + per_page: 20 + dataType: "json" + ).done (projects) -> + callback(projects) + buildUrl: (url) -> url = gon.relative_url_root + url if gon.relative_url_root? return url.replace(':version', gon.api_version) diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index 945ffb660e..1539eba0fa 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -135,17 +135,25 @@ $ -> ), 1 # Initialize tooltips - $('body').tooltip({ - selector: '.has_tooltip, [data-toggle="tooltip"], .page-sidebar-collapsed .nav-sidebar a' + $('body').tooltip( + selector: '.has_tooltip, [data-toggle="tooltip"]' placement: (_, el) -> $el = $(el) - if $el.attr('id') == 'js-shortcuts-home' - # Place the logo tooltip on the right when collapsed, bottom when expanded - $el.parents('header').hasClass('header-collapsed') and 'right' or 'bottom' - else - # Otherwise use the data-placement attribute, or 'bottom' if undefined - $el.data('placement') or 'bottom' - }) + $el.data('placement') || 'bottom' + ) + + $('.header-logo .home').tooltip( + placement: (_, el) -> + $el = $(el) + if $('.page-with-sidebar').hasClass('page-sidebar-collapsed') then 'right' else 'bottom' + container: 'body' + ) + + $('.page-with-sidebar').tooltip( + selector: '.sidebar-collapsed .nav-sidebar a, .sidebar-collapsed a.sidebar-user' + placement: 'right' + container: 'body' + ) # Form submitter $('.trigger-submit').on 'change', -> diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee index 09b48fe557..3ff9ba77df 100644 --- a/app/assets/javascripts/awards_handler.coffee +++ b/app/assets/javascripts/awards_handler.coffee @@ -1,11 +1,13 @@ class @AwardsHandler - constructor: (@post_emoji_url, @noteable_type, @noteable_id) -> + constructor: (@post_emoji_url, @noteable_type, @noteable_id, @aliases) -> addAward: (emoji) -> + emoji = @normilizeEmojiName(emoji) @postEmoji emoji, => @addAwardToEmojiBar(emoji) addAwardToEmojiBar: (emoji, custom_path = '') -> + emoji = @normilizeEmojiName(emoji) if @exist(emoji) if @isActive(emoji) @decrementCounter(emoji) @@ -88,4 +90,12 @@ class @AwardsHandler callback.call() findEmojiIcon: (emoji) -> - $(".icon[data-emoji='" + emoji + "']") \ No newline at end of file + $(".icon[data-emoji='" + emoji + "']") + + scrollToAwards: -> + $('body, html').animate({ + scrollTop: $('.awards').offset().top - 80 + }, 200) + + normilizeEmojiName: (emoji) -> + @aliases[emoji] || emoji diff --git a/app/assets/javascripts/copy_to_clipboard.js.coffee b/app/assets/javascripts/copy_to_clipboard.js.coffee index 9c68c5cc1b..24301e01b1 100644 --- a/app/assets/javascripts/copy_to_clipboard.js.coffee +++ b/app/assets/javascripts/copy_to_clipboard.js.coffee @@ -1,32 +1,37 @@ #= require clipboard +genericSuccess = (e) -> + showTooltip(e.trigger, 'Copied!') + + # Clear the selection and blur the trigger so it loses its border + e.clearSelection() + $(e.trigger).blur() + +# Safari doesn't support `execCommand`, so instead we inform the user to +# copy manually. +# +# See http://clipboardjs.com/#browser-support +genericError = (e) -> + if /Mac/i.test(navigator.userAgent) + key = '⌘' # Command + else + key = 'Ctrl' + + showTooltip(e.trigger, "Press #{key}-C to copy") + +showTooltip = (target, title) -> + $(target). + tooltip( + container: 'body' + html: 'true' + placement: 'auto bottom' + title: title + trigger: 'manual' + ). + tooltip('show'). + one('mouseleave', -> $(this).tooltip('hide')) + $ -> - clipboard = new Clipboard '.js-clipboard-trigger', - text: (trigger) -> - $target = $(trigger.nextElementSibling || trigger.previousElementSibling) - $target.data('clipboard-text') || $target.text().trim() - - clipboard.on 'success', (e) -> - $(e.trigger). - tooltip(trigger: 'manual', placement: 'auto bottom', title: 'Copied!'). - tooltip('show'). - one('mouseleave', -> $(this).tooltip('hide')) - - # Clear the selection and blur the trigger so it loses its border - e.clearSelection() - $(e.trigger).blur() - - # Safari doesn't support `execCommand`, so instead we inform the user to - # copy manually. - # - # See http://clipboardjs.com/#browser-support - clipboard.on 'error', (e) -> - if /Mac/i.test(navigator.userAgent) - title = "Press ⌘-C to copy" - else - title = "Press Ctrl-C to copy" - - $(e.trigger). - tooltip(trigger: 'manual', placement: 'auto bottom', html: true, title: title). - tooltip('show'). - one('mouseleave', -> $(this).tooltip('hide')) + clipboard = new Clipboard '[data-clipboard-target], [data-clipboard-text]' + clipboard.on 'success', genericSuccess + clipboard.on 'error', genericError diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index 4059fc39c6..599b4c4954 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -83,7 +83,7 @@ class Dispatcher when 'projects:project_members:index' new ProjectMembers() new UsersSelect() - when 'groups:new', 'groups:edit', 'admin:groups:edit' + when 'groups:new', 'groups:edit', 'admin:groups:edit', 'admin:groups:new' new GroupAvatar() when 'projects:tree:show' new TreeView() diff --git a/app/assets/javascripts/dropzone_input.js.coffee b/app/assets/javascripts/dropzone_input.js.coffee index 6f789e668a..30a35a0433 100644 --- a/app/assets/javascripts/dropzone_input.js.coffee +++ b/app/assets/javascripts/dropzone_input.js.coffee @@ -1,3 +1,5 @@ +#= require markdown_preview + class @DropzoneInput constructor: (form) -> Dropzone.autoDiscover = false @@ -11,17 +13,14 @@ class @DropzoneInput uploadProgress = $("
") btnAlert = "" project_uploads_path = window.project_uploads_path or null - markdown_preview_path = window.markdown_preview_path or null max_file_size = gon.max_file_size or 10 form_textarea = $(form).find("textarea.markdown-area") form_textarea.wrap "
" form_textarea.on 'paste', (event) => handlePaste(event) - form_textarea.on "input", -> - hideReferencedUsers() - form_textarea.on "blur", -> - renderMarkdown() + + $(form).setupMarkdownPreview() form_dropzone = $(form).find('.div-dropzone') form_dropzone.parent().addClass "div-dropzone-wrapper" @@ -34,42 +33,6 @@ class @DropzoneInput "opacity": 0 "display": "none" - # Preview button - $(document).off "click", ".js-md-preview-button" - $(document).on "click", ".js-md-preview-button", (e) -> - ### - Shows the Markdown preview. - - Lets the server render GFM into Html and displays it. - ### - e.preventDefault() - form = $(this).closest("form") - # toggle tabs - form.find(".js-md-write-button").parent().removeClass "active" - form.find(".js-md-preview-button").parent().addClass "active" - - # toggle content - form.find(".md-write-holder").hide() - form.find(".md-preview-holder").show() - - renderMarkdown() - - # Write button - $(document).off "click", ".js-md-write-button" - $(document).on "click", ".js-md-write-button", (e) -> - ### - Shows the Markdown textarea. - ### - e.preventDefault() - form = $(this).closest("form") - # toggle tabs - form.find(".js-md-write-button").parent().addClass "active" - form.find(".js-md-preview-button").parent().removeClass "active" - - # toggle content - form.find(".md-write-holder").show() - form.find(".md-preview-holder").hide() - dropzone = form_dropzone.dropzone( url: project_uploads_path dictDefaultMessage: "" @@ -136,41 +99,6 @@ class @DropzoneInput child = $(dropzone[0]).children("textarea") - hideReferencedUsers = -> - referencedUsers = form.find(".referenced-users") - referencedUsers.hide() - - renderReferencedUsers = (users) -> - referencedUsers = form.find(".referenced-users") - - if referencedUsers.length - if users.length >= 10 - referencedUsers.show() - referencedUsers.find(".js-referenced-users-count").text users.length - else - referencedUsers.hide() - - renderMarkdown = -> - preview = form.find(".js-md-preview") - mdText = form.find(".markdown-area").val() - if mdText.trim().length is 0 - preview.text "Nothing to preview." - hideReferencedUsers() - else - preview.text "Loading..." - $.ajax( - type: "POST", - url: markdown_preview_path, - data: { - text: mdText - }, - dataType: "json" - ).success (data) -> - preview.html data.body - preview.syntaxHighlight() - - renderReferencedUsers data.references.users - formatLink = (link) -> text = "[#{link.alt}](#{link.url})" text = "!#{text}" if link.is_image diff --git a/app/assets/javascripts/flash.js.coffee b/app/assets/javascripts/flash.js.coffee index b39ab0c447..5de012e409 100644 --- a/app/assets/javascripts/flash.js.coffee +++ b/app/assets/javascripts/flash.js.coffee @@ -1,12 +1,16 @@ class @Flash constructor: (message, type)-> - flash = $(".flash-container") - flash.html("") + @flash = $(".flash-container") + @flash.html("") - $('
', + innerDiv = $('
', class: "flash-#{type}", text: message - ).appendTo(".flash-container") + ) + innerDiv.appendTo(".flash-container") - flash.click -> $(@).fadeOut() - flash.show() + @flash.click -> $(@).fadeOut() + @flash.show() + + pinTo: (selector) -> + @flash.detach().appendTo(selector) diff --git a/app/assets/javascripts/issuable_context.js.coffee b/app/assets/javascripts/issuable_context.js.coffee index c4d3e619f5..02232698bc 100644 --- a/app/assets/javascripts/issuable_context.js.coffee +++ b/app/assets/javascripts/issuable_context.js.coffee @@ -5,9 +5,9 @@ class @IssuableContext new UsersSelect() $('select.select2').select2({width: 'resolve', dropdownAutoWidth: true}) - $(".context .inline-update").on "change", "select", -> + $(".issuable-sidebar .inline-update").on "change", "select", -> $(this).submit() - $(".context .inline-update").on "change", ".js-assignee", -> + $(".issuable-sidebar .inline-update").on "change", ".js-assignee", -> $(this).submit() $('.issuable-details').waitForImages -> @@ -21,3 +21,9 @@ class @IssuableContext @top = ($('.issuable-affix').offset().top - 70) bottom: -> @bottom = $('.footer').outerHeight(true) + + $(".edit-link").click (e) -> + block = $(@).parents('.block') + block.find('.selectbox').show() + block.find('.value').hide() + block.find('.js-select2').select2("open") diff --git a/app/assets/javascripts/issue.js.coffee b/app/assets/javascripts/issue.js.coffee index 603a16da1c..eff80bf63b 100644 --- a/app/assets/javascripts/issue.js.coffee +++ b/app/assets/javascripts/issue.js.coffee @@ -10,12 +10,12 @@ class @Issue @initTaskList() initTaskList: -> - $('.issue-details .js-task-list-container').taskList('enable') - $(document).on 'tasklist:changed', '.issue-details .js-task-list-container', @updateTaskList + $('.detail-page-description .js-task-list-container').taskList('enable') + $(document).on 'tasklist:changed', '.detail-page-description .js-task-list-container', @updateTaskList disableTaskList: -> - $('.issue-details .js-task-list-container').taskList('disable') - $(document).off 'tasklist:changed', '.issue-details .js-task-list-container' + $('.detail-page-description .js-task-list-container').taskList('disable') + $(document).off 'tasklist:changed', '.detail-page-description .js-task-list-container' # TODO (rspeicher): Make the issue description inline-editable like a note so # that we can re-use its form here diff --git a/app/assets/javascripts/issues.js.coffee b/app/assets/javascripts/issues.js.coffee index 40bb9e9cb0..ac9e022e72 100644 --- a/app/assets/javascripts/issues.js.coffee +++ b/app/assets/javascripts/issues.js.coffee @@ -29,7 +29,7 @@ $('#filter_issue_search').val($('#issue_search').val()) initSelects: -> - $("select#update_status").select2(width: 'resolve', dropdownAutoWidth: true) + $("select#update_state_event").select2(width: 'resolve', dropdownAutoWidth: true) $("select#update_assignee_id").select2(width: 'resolve', dropdownAutoWidth: true) $("select#update_milestone_id").select2(width: 'resolve', dropdownAutoWidth: true) $("select#label_name").select2(width: 'resolve', dropdownAutoWidth: true) diff --git a/app/assets/javascripts/markdown_preview.js.coffee b/app/assets/javascripts/markdown_preview.js.coffee new file mode 100644 index 0000000000..98fc8f1734 --- /dev/null +++ b/app/assets/javascripts/markdown_preview.js.coffee @@ -0,0 +1,87 @@ +# MarkdownPreview +# +# Handles toggling the "Write" and "Preview" tab clicks, rendering the preview, +# and showing a warning when more than `x` users are referenced. +# +class @MarkdownPreview + # Minimum number of users referenced before triggering a warning + referenceThreshold: 10 + + showPreview: (form) -> + preview = form.find('.js-md-preview') + mdText = form.find('textarea.markdown-area').val() + + if mdText.trim().length == 0 + preview.text('Nothing to preview.') + @hideReferencedUsers(form) + else + preview.text('Loading...') + @renderMarkdown mdText, (response) => + preview.html(response.body) + preview.syntaxHighlight() + @renderReferencedUsers(response.references.users, form) + + renderMarkdown: (text, success) -> + return unless window.markdown_preview_path + + $.ajax + type: 'POST' + url: window.markdown_preview_path + data: { text: text } + dataType: 'json' + success: success + + hideReferencedUsers: (form) -> + referencedUsers = form.find('.referenced-users') + referencedUsers.hide() + + renderReferencedUsers: (users, form) -> + referencedUsers = form.find('.referenced-users') + + if referencedUsers.length + if users.length >= @referenceThreshold + referencedUsers.show() + referencedUsers.find('.js-referenced-users-count').text(users.length) + else + referencedUsers.hide() + +markdownPreview = new MarkdownPreview() + +previewButtonSelector = '.js-md-preview-button' +writeButtonSelector = '.js-md-write-button' + +$.fn.setupMarkdownPreview = -> + $form = $(this) + + form_textarea = $form.find('textarea.markdown-area') + + form_textarea.on 'input', -> markdownPreview.hideReferencedUsers($form) + form_textarea.on 'blur', -> markdownPreview.showPreview($form) + +$(document).on 'click', previewButtonSelector, (e) -> + e.preventDefault() + + $form = $(this).closest('form') + + # toggle tabs + $form.find(writeButtonSelector).parent().removeClass('active') + $form.find(previewButtonSelector).parent().addClass('active') + + # toggle content + $form.find('.md-write-holder').hide() + $form.find('.md-preview-holder').show() + + markdownPreview.showPreview($form) + +$(document).on 'click', writeButtonSelector, (e) -> + e.preventDefault() + + $form = $(this).closest('form') + + # toggle tabs + $form.find(writeButtonSelector).parent().addClass('active') + $form.find(previewButtonSelector).parent().removeClass('active') + + # toggle content + $form.find('.md-write-holder').show() + $form.find('.md-preview-holder').hide() diff --git a/app/assets/javascripts/merge_request.js.coffee b/app/assets/javascripts/merge_request.js.coffee index b21cb7904b..9047587db8 100644 --- a/app/assets/javascripts/merge_request.js.coffee +++ b/app/assets/javascripts/merge_request.js.coffee @@ -40,12 +40,12 @@ class @MergeRequest this.$('.all-commits').removeClass 'hide' initTaskList: -> - $('.merge-request-details .js-task-list-container').taskList('enable') - $(document).on 'tasklist:changed', '.merge-request-details .js-task-list-container', @updateTaskList + $('.detail-page-description .js-task-list-container').taskList('enable') + $(document).on 'tasklist:changed', '.detail-page-description .js-task-list-container', @updateTaskList disableTaskList: -> - $('.merge-request-details .js-task-list-container').taskList('disable') - $(document).off 'tasklist:changed', '.merge-request-details .js-task-list-container' + $('.detail-page-description .js-task-list-container').taskList('disable') + $(document).off 'tasklist:changed', '.detail-page-description .js-task-list-container' # TODO (rspeicher): Make the merge request description inline-editable like a # note so that we can re-use its form here diff --git a/app/assets/javascripts/merge_request_tabs.js.coffee b/app/assets/javascripts/merge_request_tabs.js.coffee index 593a8f4213..9e2dc1250c 100644 --- a/app/assets/javascripts/merge_request_tabs.js.coffee +++ b/app/assets/javascripts/merge_request_tabs.js.coffee @@ -43,6 +43,7 @@ # class @MergeRequestTabs diffsLoaded: false + buildsLoaded: false commitsLoaded: false constructor: (@opts = {}) -> @@ -54,6 +55,12 @@ class @MergeRequestTabs bindEvents: -> $(document).on 'shown.bs.tab', '.merge-request-tabs a[data-toggle="tab"]', @tabShown + $(document).on 'click', '.js-show-tab', @showTab + + showTab: (event) => + event.preventDefault() + + @activateTab $(event.target).data('action') tabShown: (event) => $target = $(event.target) @@ -63,12 +70,14 @@ class @MergeRequestTabs @loadCommits($target.attr('href')) else if action == 'diffs' @loadDiff($target.attr('href')) + else if action == 'builds' + @loadBuilds($target.attr('href')) @setCurrentAction(action) scrollToElement: (container) -> if window.location.hash - $el = $("#{container} #{window.location.hash}") + $el = $("div#{container} #{window.location.hash}") $('body').scrollTo($el.offset().top) if $el.length # Activate a tab based on the current action @@ -101,7 +110,7 @@ class @MergeRequestTabs action = 'notes' if action == 'show' # Remove a trailing '/commits' or '/diffs' - new_state = @_location.pathname.replace(/\/(commits|diffs)(\.html)?\/?$/, '') + new_state = @_location.pathname.replace(/\/(commits|diffs|builds)(\.html)?\/?$/, '') # Append the new action if we're on a tab other than 'notes' unless action == 'notes' @@ -124,7 +133,7 @@ class @MergeRequestTabs @_get url: "#{source}.json" success: (data) => - document.getElementById('commits').innerHTML = data.html + document.querySelector("div#commits").innerHTML = data.html $('.js-timeago').timeago() @commitsLoaded = true @scrollToElement("#commits") @@ -135,10 +144,22 @@ class @MergeRequestTabs @_get url: "#{source}.json" + @_location.search success: (data) => - document.getElementById('diffs').innerHTML = data.html + document.querySelector("div#diffs").innerHTML = data.html + $('div#diffs .js-syntax-highlight').syntaxHighlight() @diffsLoaded = true @scrollToElement("#diffs") + loadBuilds: (source) -> + return if @buildsLoaded + + @_get + url: "#{source}.json" + success: (data) => + document.querySelector("div#builds").innerHTML = data.html + $('.js-timeago').timeago() + @buildsLoaded = true + @scrollToElement("#builds") + # Show or hide the loading spinner # # status - Boolean, true to show, false to hide diff --git a/app/assets/javascripts/merge_request_widget.js.coffee b/app/assets/javascripts/merge_request_widget.js.coffee index 3176e5a896..c4b63966fe 100644 --- a/app/assets/javascripts/merge_request_widget.js.coffee +++ b/app/assets/javascripts/merge_request_widget.js.coffee @@ -10,17 +10,20 @@ class @MergeRequestWidget constructor: (@opts) -> modal = $('#modal_merge_info').modal(show: false) - mergeInProgress: -> + mergeInProgress: (deleteSourceBranch = false)-> $.ajax type: 'GET' url: $('.merge-request').data('url') success: (data) => if data.state == "merged" - location.reload() + urlSuffix = if deleteSourceBranch then '?delete_source=true' else '' + + window.location.href = window.location.href + urlSuffix else if data.merge_error $('.mr-widget-body').html("

" + data.merge_error + "

") else - setTimeout(merge_request_widget.mergeInProgress, 2000) + callback = -> merge_request_widget.mergeInProgress(deleteSourceBranch) + setTimeout(callback, 2000) dataType: 'json' getMergeStatus: -> diff --git a/app/assets/javascripts/new_commit_form.js.coffee b/app/assets/javascripts/new_commit_form.js.coffee index 2e561dea3e..3c7b776155 100644 --- a/app/assets/javascripts/new_commit_form.js.coffee +++ b/app/assets/javascripts/new_commit_form.js.coffee @@ -3,7 +3,7 @@ class @NewCommitForm @newBranch = form.find('.js-new-branch') @originalBranch = form.find('.js-original-branch') @createMergeRequest = form.find('.js-create-merge-request') - @createMergeRequestFormGroup = form.find('.js-create-merge-request-form-group') + @createMergeRequestContainer = form.find('.js-create-merge-request-container') @renderDestination() @newBranch.keyup @renderDestination @@ -12,10 +12,10 @@ class @NewCommitForm different = @newBranch.val() != @originalBranch.val() if different - @createMergeRequestFormGroup.show() + @createMergeRequestContainer.show() @createMergeRequest.prop('checked', true) unless @wasDifferent else - @createMergeRequestFormGroup.hide() + @createMergeRequestContainer.hide() @createMergeRequest.prop('checked', false) @wasDifferent = different diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee index 7de7632201..35dc7829da 100644 --- a/app/assets/javascripts/notes.js.coffee +++ b/app/assets/javascripts/notes.js.coffee @@ -111,6 +111,12 @@ class @Notes Note: for rendering inline notes use renderDiscussionNote ### renderNote: (note) -> + unless note.valid + if note.award + flash = new Flash('You have already used this award emoji!', 'alert') + flash.pinTo('.header-content') + return + # render note if it not present in loaded list # or skip if rendered if @isNewNote(note) && !note.award @@ -122,6 +128,7 @@ class @Notes if note.award awards_handler.addAwardToEmojiBar(note.note, note.emoji_path) + awards_handler.scrollToAwards() ### Check if note does not exists on page @@ -141,6 +148,8 @@ class @Notes @note_ids.push(note.id) form = $("form[rel='" + note.discussion_id + "']") row = form.closest("tr") + note_html = $(note.html) + note_html.syntaxHighlight() # is this the first note of discussion? if row.is(".js-temp-notes-holder") @@ -151,14 +160,16 @@ class @Notes row.next().find(".note").remove() # Add note to 'Changes' page discussions - $(".notes[rel='" + note.discussion_id + "']").append note.html + $(".notes[rel='" + note.discussion_id + "']").append note_html # Init discussion on 'Discussion' page if it is merge request page if $('body').attr('data-page').indexOf('projects:merge_request') == 0 - $('ul.main-notes-list').append(note.discussion_with_diff_html) + discussion_html = $(note.discussion_with_diff_html) + discussion_html.syntaxHighlight() + $('ul.main-notes-list').append(discussion_html) else # append new note to all matching discussions - $(".notes[rel='" + note.discussion_id + "']").append note.html + $(".notes[rel='" + note.discussion_id + "']").append note_html # cleanup after successfully creating a diff/discussion note @removeDiscussionNoteForm(form) @@ -279,7 +290,7 @@ class @Notes $html.find('.js-task-list-container').taskList('enable') # Find the note's `li` element by ID and replace it with the updated HTML - $note_li = $("#note_#{note.id}") + $note_li = $('.note-row-' + note.id) $note_li.replaceWith($html) ### @@ -339,18 +350,26 @@ class @Notes ### removeNote: -> note = $(this).closest(".note") - notes = note.closest(".notes") + note_id = note.attr('id') - # check if this is the last note for this line - if notes.find(".note").length is 1 + $('.note[id="' + note_id + '"]').each -> + note = $(this) + notes = note.closest(".notes") + count = notes.closest(".notes_holder").find(".discussion-notes-count") - # for discussions - notes.closest(".discussion").remove() + # check if this is the last note for this line + if notes.find(".note").length is 1 - # for diff lines - notes.closest("tr").remove() + # for discussions + notes.closest(".discussion").remove() - note.remove() + # for diff lines + notes.closest("tr").remove() + else + # update notes count + count.get(0).lastChild.nodeValue = " #{notes.children().length - 1}" + + note.remove() ### Called in response to clicking the delete attachment link @@ -362,8 +381,8 @@ class @Notes note = $(this).closest(".note") note.find(".note-attachment").remove() note.find(".note-body > .note-text").show() - note.find(".js-note-attachment-delete").hide() - note.find(".note-edit-form").hide() + note.find(".note-header").show() + note.find(".current-note-edit-form").remove() ### Called when clicking on the "reply" button for a diff line. diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee index 0ea8fffce0..1f221945c0 100644 --- a/app/assets/javascripts/project.js.coffee +++ b/app/assets/javascripts/project.js.coffee @@ -1,13 +1,22 @@ class @Project constructor: -> - # Git clone panel switcher - cloneHolder = $('.git-clone-holder') - if cloneHolder.length - $('a, button', cloneHolder).click -> - $('a, button', cloneHolder).removeClass 'active' - $(@).addClass 'active' - $('#project_clone', cloneHolder).val $(@).data 'clone' - $(".clone").text("").append $(@).data 'clone' + # Git protocol switcher + $('.js-protocol-switch').click -> + return if $(@).hasClass('active') + + + # Remove the active class for all buttons (ssh, http, kerberos if shown) + $('.active').not($(@)).removeClass('active'); + # Add the active class for the clicked button + $(@).toggleClass('active') + + url = $(@).data('clone') + + # Update the input field + $('#project_clone').val(url) + + # Update the command line instructions + $('.clone').text(url) # Ref switcher $('.project-refs-select').on 'change', -> @@ -39,4 +48,4 @@ class @Project when 4 then label = ' On Mention ' $('#notifications-button').empty().append("" + label + "") $(@).parents('ul').find('li.active').removeClass 'active' - $(@).parent().addClass 'active' \ No newline at end of file + $(@).parent().addClass 'active' diff --git a/app/assets/javascripts/project_select.js.coffee b/app/assets/javascripts/project_select.js.coffee new file mode 100644 index 0000000000..0ae274f336 --- /dev/null +++ b/app/assets/javascripts/project_select.js.coffee @@ -0,0 +1,39 @@ +class @ProjectSelect + constructor: -> + $('.ajax-project-select').each (i, select) -> + @groupId = $(select).data('group-id') + @includeGroups = $(select).data('include-groups') + + placeholder = "Search for project" + placeholder += " or group" if @includeGroups + + $(select).select2 + placeholder: placeholder + minimumInputLength: 0 + query: (query) => + finalCallback = (projects) -> + data = { results: projects } + query.callback(data) + + if @includeGroups + projectsCallback = (projects) -> + groupsCallback = (groups) -> + data = groups.concat(projects) + finalCallback(data) + + Api.groups query.term, false, groupsCallback + else + projectsCallback = finalCallback + + if @groupId + Api.groupProjects @groupId, query.term, projectsCallback + else + Api.projects query.term, projectsCallback + + id: (project) -> + project.web_url + + text: (project) -> + project.name_with_namespace || project.name + + dropdownCssClass: "ajax-project-dropdown" diff --git a/app/assets/javascripts/sidebar.js.coffee b/app/assets/javascripts/sidebar.js.coffee index fb08016fba..ae59480af9 100644 --- a/app/assets/javascripts/sidebar.js.coffee +++ b/app/assets/javascripts/sidebar.js.coffee @@ -5,6 +5,7 @@ $(document).on("click", '.toggle-nav-collapse', (e) -> $('.page-with-sidebar').toggleClass("#{collapsed} #{expanded}") $('header').toggleClass("header-collapsed header-expanded") + $('.sidebar-wrapper').toggleClass("sidebar-collapsed sidebar-expanded") $('.toggle-nav-collapse i').toggleClass("fa-angle-right fa-angle-left") $.cookie("collapsed_nav", $('.page-with-sidebar').hasClass(collapsed), { path: '/' }) ) diff --git a/app/assets/javascripts/user.js.coffee b/app/assets/javascripts/user.js.coffee index d0d81f9692..ec4271b092 100644 --- a/app/assets/javascripts/user.js.coffee +++ b/app/assets/javascripts/user.js.coffee @@ -2,3 +2,9 @@ class @User constructor: -> $('.profile-groups-avatars').tooltip("placement": "top") new ProjectsList() + + $('.hide-project-limit-message').on 'click', (e) -> + path = '/' + $.cookie('hide_project_limit_message', 'false', { path: path }) + $(@).parents('.project-limit-message').remove() + e.preventDefault() diff --git a/app/assets/javascripts/users_select.js.coffee b/app/assets/javascripts/users_select.js.coffee index 9157562a5c..12abf806bf 100644 --- a/app/assets/javascripts/users_select.js.coffee +++ b/app/assets/javascripts/users_select.js.coffee @@ -32,17 +32,15 @@ class @UsersSelect if showNullUser nullUser = { name: 'Unassigned', - avatar: null, - username: 'none', id: 0 } data.results.unshift(nullUser) if showAnyUser + name = showAnyUser + name = 'Any User' if name == true anyUser = { - name: 'Any', - avatar: null, - username: 'none', + name: name, id: null } data.results.unshift(anyUser) @@ -50,7 +48,6 @@ class @UsersSelect if showEmailUser && data.results.length == 0 && query.term.match(/^[^@]+@[^@]+$/) emailUser = { name: "Invite \"#{query.term}\"", - avatar: null, username: query.term, id: query.term } @@ -58,11 +55,8 @@ class @UsersSelect query.callback(data) - initSelection: (element, callback) => - id = $(element).val() - if id != "" && id != "0" - @user(id, callback) - + initSelection: (args...) => + @initSelection(args...) formatResult: (args...) => @formatResult(args...) formatSelection: (args...) => @@ -71,16 +65,24 @@ class @UsersSelect escapeMarkup: (m) -> # we do not want to escape markup since we are displaying html in results m + initSelection: (element, callback) -> + id = $(element).val() + if id == "0" + nullUser = { name: 'Unassigned' } + callback(nullUser) + else if id != "" + @user(id, callback) + formatResult: (user) -> if user.avatar_url avatar = user.avatar_url else avatar = gon.default_avatar_url - "
+ "
#{user.name}
-
#{user.username}
+
#{user.username || ""}
" formatSelection: (user) -> diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss index 1ec9d2fd84..48a4971c8f 100644 --- a/app/assets/stylesheets/framework.scss +++ b/app/assets/stylesheets/framework.scss @@ -1,9 +1,9 @@ @import "framework/fonts"; @import "framework/variables"; @import "framework/mixins"; -@import "framework/layout"; @import 'framework/tw_bootstrap_variables'; @import 'framework/tw_bootstrap'; +@import "framework/layout"; @import "framework/avatar.scss"; @import "framework/blocks.scss"; @@ -25,6 +25,7 @@ @import "framework/markdown_area.scss"; @import "framework/mobile.scss"; @import "framework/pagination.scss"; +@import "framework/panels.scss"; @import "framework/selects.scss"; @import "framework/sidebar.scss"; @import "framework/tables.scss"; diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss index 1635df9c97..a62c0f62a4 100644 --- a/app/assets/stylesheets/framework/blocks.scss +++ b/app/assets/stylesheets/framework/blocks.scss @@ -68,6 +68,10 @@ .oneline { line-height: 42px; } + + > p:last-child { + margin-bottom: 0; + } } .cover-block { @@ -112,5 +116,14 @@ position: absolute; top: 10px; right: 10px; + + &.left { + left: 10px; + right: auto; + } } } + +.block-connector { + margin-top: -1px; +} diff --git a/app/assets/stylesheets/framework/callout.scss b/app/assets/stylesheets/framework/callout.scss index f3ce4e3c21..20a9bfb981 100644 --- a/app/assets/stylesheets/framework/callout.scss +++ b/app/assets/stylesheets/framework/callout.scss @@ -7,8 +7,8 @@ /* Common styles for all types */ .bs-callout { - margin: 20px 0; - padding: 20px; + margin: $gl-padding 0; + padding: $gl-padding; border-left: 3px solid $border-color; color: $text-color; background: $background-color; @@ -42,4 +42,3 @@ border-color: #5cA64d; color: #3c763d; } - diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index 40f4beb196..7562ef6d24 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -7,7 +7,7 @@ /** COMMON CLASSES **/ .prepend-top-10 { margin-top:10px } -.prepend-top-default { margin-top: $gl-padding; } +.prepend-top-default { margin-top: $gl-padding !important; } .prepend-top-20 { margin-top:20px } .prepend-left-10 { margin-left:10px } .prepend-left-20 { margin-left:20px } @@ -52,6 +52,10 @@ pre { } } +hr { + margin: $gl-padding 0; +} + .dropdown-menu > li > a { text-shadow: none; } @@ -64,7 +68,7 @@ pre { .dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus { background: $gl-primary; - color: #FFF + color: #FFF; } .str-truncated { @@ -329,7 +333,7 @@ table { } .well { - margin-bottom: 0; + margin-bottom: $gl-padding; } .search_box { @@ -337,10 +341,6 @@ table { text-align: center; } -.task-status { - margin-left: 10px; -} - #nprogress .spinner { top: 15px !important; right: 10px !important; @@ -379,9 +379,8 @@ table { text-align: center; margin-top: 5px; margin-bottom: $gl-padding; - height: 56px; + height: auto; margin-top: -$gl-padding; - padding-top: $gl-padding; &.no-bottom { margin-bottom: 0; @@ -390,6 +389,23 @@ table { &.no-top { margin-top: 0; } + + li a { + display: inline-block; + padding-top: $gl-padding; + padding-bottom: 11px; + margin-bottom: -1px; + } + + &.bottom-border { + border-bottom: 1px solid $border-color; + height: 57px; + } + + &.wide { + margin-left: -$gl-padding; + margin-right: -$gl-padding; + } } .center-middle-menu { @@ -433,3 +449,26 @@ table { .space-right { margin-right: 10px; } + +.alert, .progress { + margin-bottom: $gl-padding; +} + +.new-project-item-select-holder { + display: inline-block; + position: relative; + + .new-project-item-select { + position: absolute; + top: 0; + right: 0; + width: 250px !important; + visibility: hidden; + } +} + +.content-separator { + margin-left: -$gl-padding; + margin-right: -$gl-padding; + border-top: 1px solid $border-color; +} diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss index 35db00281e..cbfd4bc29b 100644 --- a/app/assets/stylesheets/framework/files.scss +++ b/app/assets/stylesheets/framework/files.scss @@ -8,7 +8,6 @@ border: none; border-top: 1px solid #E7E9EE; border-bottom: 1px solid #E7E9EE; - margin-bottom: 1em; &.readme-holder { border-bottom: 0; @@ -22,10 +21,9 @@ position: relative; background: $background-color; border-bottom: 1px solid $border-color; - text-shadow: 0 1px 1px #fff; margin: 0; text-align: left; - padding: 10px 15px; + padding: 10px $gl-padding; .file-actions { float: right; @@ -171,4 +169,3 @@ } } } - diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss index 0edfe24f19..032d343df4 100644 --- a/app/assets/stylesheets/framework/forms.scss +++ b/app/assets/stylesheets/framework/forms.scss @@ -22,9 +22,10 @@ input[type='text'].danger { } .form-actions { - padding: 17px 20px 18px; - margin-top: 18px; - margin-bottom: 18px; + margin: -$gl-padding; + margin-top: 0; + margin-bottom: -$gl-padding; + padding: $gl-padding; background-color: $background-color; border-top: 1px solid $border-color; } @@ -73,6 +74,8 @@ label { .form-control { @include box-shadow(none); + height: 42px; + padding: 8px $gl-padding; } .wiki-content { @@ -88,7 +91,19 @@ label { } .input-group { + .select2-container { + display: table-cell; + width: 200px !important; + } .input-group-addon { background-color: #f7f8fa; } + .input-group-addon:not(:first-child):not(:last-child) { + border-left: 0; + border-right: 0; + } +} + +.help-block { + margin-bottom: 0; } diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 02ea91602e..4dbbb56104 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -6,15 +6,17 @@ header { transition-duration: .3s; &.navbar-empty { + height: 58px; background: #FFF; border-bottom: 1px solid #EEE; .center-logo { - margin: 8px 0; + margin: 11px 0; text-align: center; - img { - height: 32px; + #tanuki-logo, img { + width: 36px; + height: 36px; } } } diff --git a/app/assets/stylesheets/framework/issue_box.scss b/app/assets/stylesheets/framework/issue_box.scss index 93377e45e7..fba67ba0b6 100644 --- a/app/assets/stylesheets/framework/issue_box.scss +++ b/app/assets/stylesheets/framework/issue_box.scss @@ -4,31 +4,32 @@ * */ -.issue-box { +.status-box { @include border-radius(2px); - display: inline-block; - padding: 10px $gl-padding; + display: block; + float: left; + padding: 0 $gl-padding; font-weight: normal; margin-right: 10px; font-size: $gl-font-size; - &.issue-box-closed { + &.status-box-closed { background-color: $gl-danger; color: #FFF; } - &.issue-box-merged { + &.status-box-merged { background-color: $gl-primary; color: #FFF; } - &.issue-box-open { + &.status-box-open { background-color: #019875; color: #FFF; } - &.issue-box-expired { + &.status-box-expired { background: #cea61b; color: #FFF; } diff --git a/app/assets/stylesheets/framework/layout.scss b/app/assets/stylesheets/framework/layout.scss index b91c15d891..aa5acb93cc 100644 --- a/app/assets/stylesheets/framework/layout.scss +++ b/app/assets/stylesheets/framework/layout.scss @@ -2,9 +2,13 @@ html { overflow-y: scroll; &.touch .tooltip { display: none !important; } +} - body { - padding-top: $header-height; +body { + background-color: #EAEBEC !important; + + &.navless { + background-color: white !important; } } @@ -18,7 +22,8 @@ html { } .navless-container { - margin-top: 30px; + margin-top: $header-height; + padding-top: $gl-padding * 2; } .container-limited { diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss index 45f3b5849b..1c74e525a6 100644 --- a/app/assets/stylesheets/framework/lists.scss +++ b/app/assets/stylesheets/framework/lists.scss @@ -7,7 +7,7 @@ padding: 0; list-style: none; - li { + > li { padding: 10px 15px; min-height: 20px; border-bottom: 1px solid #eee; @@ -72,13 +72,6 @@ } } -ol, ul { - &.styled { - li { - padding: 2px; - } - } -} /** light list with border-bottom between li **/ ul.bordered-list { @@ -95,8 +88,14 @@ ul.bordered-list { } } -li.task-list-item { - list-style-type: none; +ul.task-list { + li.task-list-item { + list-style-type: none; + } + + ul:not(.task-list) { + padding-left: 1.3em; + } } ul.content-list { @@ -127,3 +126,36 @@ ul.content-list { } } +.panel > .content-list { + li { + margin: 0; + } +} + +ul.controls { + padding-top: 1px; + float: right; + list-style: none; + + .btn { + padding: 10px 14px; + } + + > li { + float: left; + margin-right: 10px; + + &:last-child { + margin-right: 0; + } + + .author_link { + display: inline-block; + + .avatar-inline { + margin-left: 0; + margin-right: 0; + } + } + } +} diff --git a/app/assets/stylesheets/framework/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss index cc660529cb..4a00a197d9 100644 --- a/app/assets/stylesheets/framework/markdown_area.scss +++ b/app/assets/stylesheets/framework/markdown_area.scss @@ -73,11 +73,8 @@ } .referenced-users { - padding: 10px 0; - color: #999; - margin-left: 10px; - margin-top: 1px; - margin-right: 130px; + color: #4c4e54; + padding-top: 10px; } .md-preview-holder { @@ -90,7 +87,7 @@ .new_note, .edit_note, -.issuable-description, +.detail-page-description, .milestone-description, .wiki-content, .merge-request-form { diff --git a/app/assets/stylesheets/framework/mobile.scss b/app/assets/stylesheets/framework/mobile.scss index cea47fba19..6f44c32373 100644 --- a/app/assets/stylesheets/framework/mobile.scss +++ b/app/assets/stylesheets/framework/mobile.scss @@ -82,9 +82,6 @@ } .center-top-menu { - height: 45px; - margin-bottom: 30px; - li a { font-size: 14px; padding: 19px 10px; diff --git a/app/assets/stylesheets/framework/pagination.scss b/app/assets/stylesheets/framework/pagination.scss index 6677f94daf..2cd30491bf 100644 --- a/app/assets/stylesheets/framework/pagination.scss +++ b/app/assets/stylesheets/framework/pagination.scss @@ -32,3 +32,7 @@ } } } + +.panel > .gl-pagination { + margin: 0; +} diff --git a/app/assets/stylesheets/framework/panels.scss b/app/assets/stylesheets/framework/panels.scss new file mode 100644 index 0000000000..57b9451b26 --- /dev/null +++ b/app/assets/stylesheets/framework/panels.scss @@ -0,0 +1,20 @@ +.panel { + margin-bottom: $gl-padding; + + .panel-heading { + padding: 7px $gl-padding; + } + + .panel-body { + padding: $gl-padding; + + .form-actions { + margin: -$gl-padding; + margin-top: $gl-padding; + } + } +} + +.container-blank .panel .panel-heading { + line-height: 42px !important; +} diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss index 78fff58d23..af145191bc 100644 --- a/app/assets/stylesheets/framework/selects.scss +++ b/app/assets/stylesheets/framework/selects.scss @@ -15,6 +15,16 @@ border-left: none; padding-top: 5px; } + + .select2-chosen { + color: $gl-text-color; + } + + &.select2-default { + .select2-chosen { + color: #999; + } + } } } @@ -23,6 +33,7 @@ border: 1px solid #e7e9ed; } + .select2-drop { @include box-shadow(rgba(76, 86, 103, 0.247059) 0px 0px 1px 0px, rgba(31, 37, 50, 0.317647) 0px 2px 18px 0px); @include border-radius (0px); @@ -48,17 +59,38 @@ color: #313236; } +.select2-container-multi { + .select2-choices { + @include border-radius(2px); + border-color: $input-border; + background: white; + padding-left: $gl-padding / 2; -.select2-container-multi .select2-choices { - @include border-radius(2px); - border-color: #CCC; -} + .select2-search-field input { + padding: $gl-padding / 2; + font-size: 13px; + height: auto; + font-family: inherit; + font-size: inherit; + } -.select2-container-multi .select2-choices .select2-search-field input { - padding: 8px 14px; - font-size: 13px; - line-height: 18px; - height: auto; + .select2-search-choice { + margin: 8px 0 0 8px; + background: white; + box-shadow: none; + border-color: $input-border; + color: $gl-text-color; + line-height: 15px; + + .select2-search-choice-close { + top: 5px; + } + + &.select2-search-choice-focus { + border-color: $gl-text-color; + } + } + } } .select2-drop-active { @@ -123,10 +155,16 @@ } .user-result { + min-height: 24px; + .user-image { float: left; } - .user-name { + + &.no-username { + .user-name { + line-height: 24px; + } } } @@ -143,4 +181,4 @@ .ajax-users-dropdown { min-width: 250px !important; -} \ No newline at end of file +} diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index c1b0129c86..458af76cb7 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -1,4 +1,7 @@ .page-with-sidebar { + padding-top: $header-height; + transition-duration: .3s; + .sidebar-wrapper { position: fixed; top: 0; @@ -14,19 +17,15 @@ .sidebar-wrapper { z-index: 99; background: $background-color; - transition-duration: .3s; } .content-wrapper { - min-height: 100vh; width: 100%; padding: 20px; - background: #EAEBEC; .container-fluid { background: #FFF; padding: $gl-padding; - min-height: 90vh; &.container-blank { background: none; @@ -36,6 +35,83 @@ } } +.sidebar-wrapper { + .header-logo { + border-bottom: 1px solid transparent; + float: left; + height: $header-height; + width: $sidebar_width; + position: fixed; + z-index: 999; + overflow: hidden; + transition-duration: .3s; + + a { + float: left; + height: $header-height; + width: 100%; + padding: 11px 0 11px 22px; + overflow: hidden; + outline: none; + transition-duration: .3s; + + img { + width: 36px; + height: 36px; + } + + #tanuki-logo, img { + float: left; + } + + .gitlab-text-container { + width: 230px; + + h3 { + width: 158px; + float: left; + margin: 0; + margin-left: 14px; + font-size: 19px; + line-height: 41px; + font-weight: normal; + } + } + } + + &:hover { + background-color: #EEE; + } + } + + .sidebar-user { + padding: 9px 22px; + position: fixed; + bottom: 40px; + width: $sidebar_width; + overflow: hidden; + transition-duration: .3s; + + .username { + margin-left: 10px; + width: $sidebar_width - 2 * 10px; + font-size: 16px; + line-height: 34px; + } + } +} + + +.tanuki-shape { + transition: all 0.8s; + + &:hover { + fill: rgb(255, 255, 255); + transition: all 0.1s; + } +} + + .nav-sidebar { margin-top: 14 + $header-height; margin-bottom: 100px; @@ -62,7 +138,7 @@ color: $gray; display: block; text-decoration: none; - padding-left: 22px; + padding-left: 23px; font-weight: normal; outline: none; @@ -86,6 +162,10 @@ padding: 0px 8px; @include border-radius(6px); } + + &.back-link i { + transition-duration: .3s; + } } } } @@ -101,7 +181,6 @@ @mixin expanded-sidebar { padding-left: $sidebar_width; - transition-duration: .3s; .sidebar-wrapper { width: $sidebar_width; @@ -115,16 +194,15 @@ &.back-link { i { - visibility: hidden; + opacity: 0; } } } } } -@mixin folded-sidebar { - padding-left: 60px; - transition-duration: .3s; +@mixin collapsed-sidebar { + padding-left: $sidebar_collapsed_width; .sidebar-wrapper { width: $sidebar_collapsed_width; @@ -133,7 +211,7 @@ width: $sidebar_collapsed_width; a { - padding-left: 12px; + padding-left: ($sidebar_collapsed_width - 36) / 2; .gitlab-text-container { display: none; @@ -144,9 +222,13 @@ .nav-sidebar { width: $sidebar_collapsed_width; - li a { - span { - display: none; + li { + width: auto; + + a { + span { + display: none; + } } } } @@ -156,7 +238,7 @@ } .sidebar-user { - padding-left: 12px; + padding-left: ($sidebar_collapsed_width - 36) / 2; width: $sidebar_collapsed_width; .username { @@ -187,11 +269,11 @@ @media (max-width: $screen-md-max) { .page-sidebar-collapsed { - @include folded-sidebar; + @include collapsed-sidebar; } .page-sidebar-expanded { - @include folded-sidebar; + @include collapsed-sidebar; } .collapse-nav { @@ -201,83 +283,10 @@ @media(min-width: $screen-md-max) { .page-sidebar-collapsed { - @include folded-sidebar; + @include collapsed-sidebar; } .page-sidebar-expanded { @include expanded-sidebar; } } - -.sidebar-user { - padding: 9px 22px; - position: fixed; - bottom: 40px; - width: $sidebar_width; - overflow: hidden; - transition-duration: .3s; - - .username { - margin-left: 10px; - width: $sidebar_width - 2 * 10px; - font-size: 16px; - line-height: 34px; - } -} - -.sidebar-wrapper { - .header-logo { - border-bottom: 1px solid transparent; - float: left; - height: $header-height; - width: $sidebar_width; - overflow: hidden; - transition-duration: .3s; - - a { - float: left; - height: $header-height; - width: 100%; - padding: 10px 22px; - overflow: hidden; - outline: none; - - img { - width: 36px; - height: 36px; - } - - #tanuki-logo, img { - float: left; - } - - .gitlab-text-container { - width: 230px; - - h3 { - width: 158px; - float: left; - margin: 0; - margin-left: 14px; - font-size: 19px; - line-height: 41px; - font-weight: normal; - } - } - } - - &:hover { - background-color: #EEE; - } - } -} - - -.tanuki-shape { - transition: all 0.8s; - - &:hover { - fill: rgb(255, 255, 255); - transition: all 0.1s; - } -} diff --git a/app/assets/stylesheets/framework/tables.scss b/app/assets/stylesheets/framework/tables.scss index 66e16e8df7..793ab3d9bb 100644 --- a/app/assets/stylesheets/framework/tables.scss +++ b/app/assets/stylesheets/framework/tables.scss @@ -6,6 +6,8 @@ table { &.table { + margin-bottom: $gl-padding; + .dropdown-menu a { text-decoration: none; } diff --git a/app/assets/stylesheets/framework/timeline.scss b/app/assets/stylesheets/framework/timeline.scss index eb53c4153d..ff41e26ed8 100644 --- a/app/assets/stylesheets/framework/timeline.scss +++ b/app/assets/stylesheets/framework/timeline.scss @@ -10,8 +10,7 @@ margin-left: -$gl-padding; margin-right: -$gl-padding; color: $gl-gray; - border-bottom: 1px solid #ECEEF1; - border-right: 1px solid #ECEEF1; + border-bottom: 1px solid $border-white-light; &:target { background: $hover; diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss index ba0312ba0d..c3e4ad0ad0 100644 --- a/app/assets/stylesheets/framework/typography.scss +++ b/app/assets/stylesheets/framework/typography.scss @@ -181,6 +181,10 @@ body { line-height: 1.3; font-size: 1.25em; font-weight: 600; + + &:last-child { + margin-bottom: 0; + } } .page-title-empty { @@ -216,6 +220,7 @@ pre { .monospace { font-family: $monospace_font; + font-size: 90%; } code { @@ -256,3 +261,9 @@ textarea.js-gfm-input { .strikethrough { text-decoration: line-through; } + +h1, h2, h3, h4 { + small { + color: $gl-gray; + } +} diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 91954683c3..2ef40a6e51 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -19,7 +19,7 @@ $border-color: #dce0e6; $table-border-color: #eef0f2; $background-color: #F7F8FA; $header-height: 58px; -$fixed-layout-width: 1200px; +$fixed-layout-width: 1280px; $gl-gray: #7f8fa4; $gl-padding: 16px; $gl-avatar-size: 46px; diff --git a/app/assets/stylesheets/pages/awards.scss b/app/assets/stylesheets/pages/awards.scss new file mode 100644 index 0000000000..041b811a60 --- /dev/null +++ b/app/assets/stylesheets/pages/awards.scss @@ -0,0 +1,86 @@ +.awards { + @include clearfix; + line-height: 34px; + + .award { + @include border-radius(5px); + + border: 1px solid; + padding: 0px 10px; + float: left; + margin-right: 5px; + border-color: $border-color; + cursor: pointer; + + &:hover { + background-color: #dce0e5; + } + + &.active { + border-color: $border-gray-light; + background-color: $gray-light; + + &:hover { + background-color: #dce0e5; + } + + .counter { + font-weight: bold; + } + } + + .icon { + float: left; + margin-right: 10px; + } + + .counter { + float: left; + } + } + + .awards-controls { + margin-left: 10px; + float: left; + + .add-award { + font-size: 24px; + color: $gl-gray; + position: relative; + top: 2px; + + &:hover, + &:link { + text-decoration: none; + } + } + + .awards-menu { + padding: $gl-padding; + min-width: 214px; + + > li { + cursor: pointer; + width: 30px; + height: 30px; + text-align: center; + @include border-radius(5px); + + img { + margin-bottom: 2px; + } + + &:hover { + background-color: #ccc; + } + } + } + } + + .awards-menu{ + li { + float: left; + margin: 3px; + } + } +} diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index 74dc3e321c..3c2997c1d5 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -21,7 +21,7 @@ .autoscroll-container { position: fixed; - bottom: 10px; + bottom: 20px; right: 20px; z-index: 100; } @@ -34,7 +34,7 @@ a { display: block; - margin-bottom: 5px; + margin-bottom: 10px; } } @@ -67,9 +67,4 @@ color: #3084bb !important; } } - - .build-top-menu { - margin-top: 0; - margin-bottom: 2px; - } } diff --git a/app/assets/stylesheets/pages/commit.scss b/app/assets/stylesheets/pages/commit.scss index a0e5f7554e..17245d3be7 100644 --- a/app/assets/stylesheets/pages/commit.scss +++ b/app/assets/stylesheets/pages/commit.scss @@ -2,10 +2,6 @@ display: block; } -.commit-title{ - margin-bottom: 10px; -} - .commit-author, .commit-committer{ display: block; color: #999; @@ -41,6 +37,8 @@ .commit-box { .commit-title { margin: 0; + font-size: 23px; + color: #313236; } .commit-description { @@ -108,16 +106,3 @@ z-index: 2; } } - -.commit-ci-menu { - padding: 0; - margin: 0; - list-style: none; - margin-top: 5px; - height: 56px; - margin: -16px; - padding: 16px; - text-align: center; - margin-top: 0px; - margin-bottom: 2px; -} diff --git a/app/assets/stylesheets/pages/detail_page.scss b/app/assets/stylesheets/pages/detail_page.scss new file mode 100644 index 0000000000..0f3463a914 --- /dev/null +++ b/app/assets/stylesheets/pages/detail_page.scss @@ -0,0 +1,33 @@ +.detail-page-header { + margin: -$gl-padding; + padding: 7px $gl-padding; + margin-bottom: 0px; + border-bottom: 1px solid $border-color; + color: #5c5d5e; + font-size: 16px; + line-height: 42px; + + .author { + color: #5c5d5e; + } + + .identifier { + color: #5c5d5e; + } +} + +.detail-page-description { + .title { + margin: 0; + font-size: 23px; + color: #313236; + } + + .description { + margin-top: 6px; + + p:last-child { + margin-bottom: 0; + } + } +} diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss index e2c521af91..39d916cd33 100644 --- a/app/assets/stylesheets/pages/editor.scss +++ b/app/assets/stylesheets/pages/editor.scss @@ -19,48 +19,38 @@ color: #B94A48; } } - .commit-button-annotation { - display: inline-block; - margin: 0; - padding: 2px; - - > * { - float: left; - } - - .message { - display: inline-block; - margin: 5px 8px 0 8px; - } - } .file-title { @extend .monospace; + + line-height: 42px; + padding-top: 7px; + padding-bottom: 7px; } .editor-ref { background: $background-color; - padding: 11px 15px; + padding-right: $gl-padding; border-right: 1px solid $border-color; - display: inline-block; - margin: -5px -5px; + display: block; + float: left; margin-right: 10px; } .editor-file-name { - .new-file-name { - display: inline-block; - width: 450px; - } - - .form-control { - margin-top: -3px; - } + @extend .monospace; + + float: left; + margin-right: 10px; } - .form-actions { - margin: -$gl-padding; - margin-top: 0; - padding: $gl-padding + .new-file-name { + display: inline-block; + width: 450px; + float: left; + } + + .select2 { + float: right; } } diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss index 07a38a19fa..263993f59a 100644 --- a/app/assets/stylesheets/pages/groups.scss +++ b/app/assets/stylesheets/pages/groups.scss @@ -1,8 +1,3 @@ -.new-group-member-holder { - margin-top: 50px; - padding-top: 20px; -} - .member-search-form { float: left; } @@ -15,4 +10,4 @@ .form-control { height: 42px; } -} \ No newline at end of file +} diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 3a08ee70bc..9da273a0b6 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -24,20 +24,6 @@ } } -.issuable-context-title { - margin-bottom: 5px; - - .avatar { - margin-left: 0; - } - - label { - color: $gl-gray; - font-weight: normal; - margin-right: 4px; - } -} - .project-issuable-filter { .controls { float: right; @@ -50,33 +36,11 @@ } .issuable-details { - .page-title { - margin-top: -15px; - padding: 10px 0; - margin-bottom: 0; - color: #5c5d5e; - font-size: 16px; + section { + border-right: 1px solid $border-white-light; - .author { - color: #5c5d5e; - } - - .issue-id { - color: #5c5d5e; - } - } - - .issue-title { - margin: 0; - font-size: 23px; - color: #313236; - } - - .description { - margin-top: 6px; - - p:last-child { - margin-bottom: 0; + .issuable-discussion { + margin-right: 1px; } } } @@ -89,83 +53,65 @@ } } -.cross-project-reference { - text-align: center; - width: 100%; - - .slead { - padding: 5px; - } - - span, button { - background-color: $background-color; +.issuable-show-labels { + a { + margin-right: 5px; + margin-bottom: 5px; + display: inline-block; + .color-label { + padding: 6px 10px; + } } } -.awards { - @include clearfix; - line-height: 34px; - margin: 2px 0; +.issuable-sidebar { + .block { + @include clearfix; + padding: $gl-padding 0; + border-bottom: 1px solid #F0F0F0; - .award { - @include border-radius(5px); - - border: 1px solid; - padding: 0px 10px; - float: left; - margin: 0 5px; - border-color: $border-color; - cursor: pointer; - - &.active { - border-color: $border-gray-light; - background-color: $gray-light; - - .counter { - font-weight: bold; - } - } - - .icon { - float: left; - margin-right: 10px; - } - - .counter { - float: left; + &:last-child { + border: none; } } - .awards-controls { - margin-left: 10px; - float: left; + .title { + color: $gl-text-color; + margin-bottom: 8px; - .add-award { - font-size: 24px; + .avatar { + margin-left: 0; + } + + label { + font-weight: normal; + margin-right: 4px; + } + + .edit-link { color: $gl-gray; - position: relative; - top: 2px; - - &:hover, - &:link { - text-decoration: none; - } - } - - .awards-menu { - padding: $gl-padding; - min-width: 214px; - - > li { - margin: 5px; - } } } - .awards-menu{ - li { - float: left; - margin: 3px; + .cross-project-reference { + font-weight: bold; + color: $gl-link-color; + + button { + float: right; } } + + .selectbox { + display: none + } + + .btn-clipboard { + color: $gl-gray; + } + + .participants .avatar { + margin-top: 6px; + margin-right: 2px; + } } diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss index 41c069f0ad..a02a3a72e7 100644 --- a/app/assets/stylesheets/pages/issues.scss +++ b/app/assets/stylesheets/pages/issues.scss @@ -56,21 +56,30 @@ } } -.issue-show-labels { - a { - margin-right: 5px; - margin-bottom: 5px; - display: inline-block; - .color-label { - padding: 6px 10px; - } - } -} - form.edit-issue { margin: 0; } +.merge-requests-title { + font-size: 16px; + font-weight: 600; +} + +.merge-request-id { + display: inline-block; + width: 3em; +} + +.merge-request-info { + padding-left: 5px; +} + +.merge-request-status { + color: $gl-gray; + font-size: 15px; + font-weight: bold; +} + .merge-request, .issue { &.today { @@ -132,11 +141,6 @@ form.edit-issue { } } -.issue-closed-by-widget { - padding: 16px 0; - margin: 0px; -} - .issue-form .select2-container { width: 250px !important; } diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss index 83b866c3a6..f9c6f1b39f 100644 --- a/app/assets/stylesheets/pages/login.scss +++ b/app/assets/stylesheets/pages/login.scss @@ -19,6 +19,7 @@ h1:first-child { font-weight: normal; margin-bottom: 30px; + margin-top: 0; } img { diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index 08e4bcdf52..82effde0bf 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -4,7 +4,6 @@ */ .mr-state-widget { background: #F7F8FA; - margin-bottom: 20px; color: $gl-gray; border: 1px solid #dce0e6; @include border-radius(2px); @@ -19,6 +18,7 @@ .accept-merge-holder { .accept-action { display: inline-block; + float: left; .accept_merge_request { &.ci-pending, @@ -37,14 +37,15 @@ .accept-control { display: inline-block; + float: left; margin: 0; margin-left: 20px; padding: 5px; + padding-top: 12px; line-height: 20px; &.right { float: right; - padding-top: 12px; a { color: $gl-gray; } @@ -82,12 +83,16 @@ &.ci-error { color: $gl-danger; } + + a.monospace { + color: inherit; + } } .mr-widget-body, .ci_widget, .mr-widget-footer { - padding: 15px; + padding: $gl-padding; } .normal { @@ -116,28 +121,6 @@ } } -.merge-request .merge-request-tabs { - @include nav-menu; - margin: -$gl-padding; - padding: $gl-padding; - text-align: center; - margin-bottom: 1px; -} - -// Mobile -@media (max-width: 480px) { - .merge-request .merge-request-tabs { - margin: 0; - padding: 0; - - li { - a { - padding: 0; - } - } - } -} - .mr_source_commit, .mr_target_commit { .commit { @@ -155,7 +138,7 @@ font-family: $monospace_font; font-weight: bold; overflow: hidden; - font-size: 14px; + font-size: 90%; margin: 0 3px; } @@ -192,27 +175,12 @@ line-height: 1.1; } -.merge-request-form-info { - padding-top: 15px; -} - // hide mr close link for inline diff comment form .diff-file .close-mr-link, .diff-file .reopen-mr-link { display: none; } -.merge-request-show-labels { - a { - margin-right: 5px; - margin-bottom: 5px; - display: inline-block; - .color-label { - padding: 6px 10px; - } - } -} - .merge-request-form .select2-container { width: 250px !important; } @@ -223,7 +191,7 @@ .btn-clipboard { @extend .pull-right; - margin-right: 18px; + margin-right: 20px; margin-top: 5px; position: absolute; right: 0; diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss index 268fc995aa..4cf1a28c45 100644 --- a/app/assets/stylesheets/pages/note_form.scss +++ b/app/assets/stylesheets/pages/note_form.scss @@ -7,6 +7,7 @@ } .reply-btn { @extend .btn-primary; + margin: 10px $gl-padding; } .diff-file .diff-content { tr.line_holder:hover { @@ -38,9 +39,8 @@ } .new_note, .edit_note { - .buttons { - margin-top: 8px; - margin-bottom: 3px; + .note-form-actions { + margin-top: $gl-padding; } .note-preview-holder { @@ -79,8 +79,7 @@ padding: $gl-padding; margin-left: -$gl-padding; margin-right: -$gl-padding; - border-right: 1px solid #ECEEF1; - border-top: 1px solid #ECEEF1; + border-top: 1px solid $border-color; margin-bottom: -$gl-padding; } @@ -150,7 +149,6 @@ .discussion-reply-holder { background: $background-color; - padding: 10px 15px; border-top: 1px solid $border-color; } } diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index 1980fe0d45..4dff87abaa 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -109,13 +109,9 @@ ul.notes { } } - // Reduce left padding of first task list ul element - ul.task-list:first-child { - padding-left: 10px; - - // sub-tasks should be padded normally - ul { - padding-left: 20px; + ul.task-list { + ul:not(.task-list) { + padding-left: 1.3em; } } diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss index 1d6ca0dfc1..95fc26a608 100644 --- a/app/assets/stylesheets/pages/profile.scss +++ b/app/assets/stylesheets/pages/profile.scss @@ -5,12 +5,6 @@ } } -.btn-build-token { - float: left; - padding: 6px 20px; - margin-right: 12px; -} - .profile-avatar-form-option { hr { margin: 10px 0; diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index d3b1004002..2ded32dba1 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -5,7 +5,7 @@ font-weight: normal; } } -.no-ssh-key-message { +.no-ssh-key-message, .project-limit-message { background-color: #f28d35; margin-bottom: 16px; } @@ -18,10 +18,6 @@ } } -.project-edit-content { - padding: 7px; -} - .project-name-holder { .help-inline { vertical-align: top; @@ -30,12 +26,6 @@ } .project-home-panel { - text-align: center; - background: #f7f8fa; - margin: -$gl-padding; - padding: $gl-padding; - padding: 44px 0 17px 0; - .project-identicon-holder { margin-bottom: 16px; @@ -90,7 +80,12 @@ } .visibility-level-label { + @extend .btn; + @extend .btn-gray; + color: $gray; + cursor: default; + i { color: inherit; } @@ -100,7 +95,6 @@ display: inline-table; position: relative; top: 17px; - margin-bottom: 44px; } .project-repo-buttons { @@ -178,6 +172,11 @@ &:active { outline: none; } + + &.btn-clipboard { + padding-left: 15px; + padding-right: 15px; + } } .active { @@ -366,7 +365,7 @@ table.table.protected-branches-list tr.no-border { .project-stats { text-align: center; - margin-top: 15px; + margin-top: $gl-padding; margin-bottom: 0; padding-top: 10px; padding-bottom: 4px; @@ -552,4 +551,4 @@ pre.light-well { z-index: 100; position: relative; } -} \ No newline at end of file +} diff --git a/app/assets/stylesheets/pages/snippets.scss b/app/assets/stylesheets/pages/snippets.scss index 242783a7b7..1430d01859 100644 --- a/app/assets/stylesheets/pages/snippets.scss +++ b/app/assets/stylesheets/pages/snippets.scss @@ -27,56 +27,28 @@ } .snippet-holder { - .snippet-details { - .page-title { - margin-top: -15px; - padding: 10px 0; - margin-bottom: 0; - color: #5c5d5e; - font-size: 16px; - - .author { - color: #5c5d5e; - } - - .snippet-id { - color: #5c5d5e; - } - } - - .snippet-title { - margin: 0; - font-size: 23px; - color: #313236; - } - - @media (max-width: $screen-md-max) { - .new-snippet-link { - display: none; - } - } - - @media (max-width: $screen-sm-max) { - .creator, - .page-title .btn-close { - display: none; - } - } - } + margin-bottom: -$gl-padding; .file-holder { border-top: 0; } -} + .file-actions { + .btn-clipboard { + @extend .btn; + } + } +} .snippet-box { @include border-radius(2px); - display: inline-block; - padding: 10px $gl-padding; + display: block; + float: left; + padding: 0 $gl-padding; font-weight: normal; margin-right: 10px; font-size: $gl-font-size; border: 1px solid; + line-height: 40px; } diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss index a7d3b2197f..4b6ef03567 100644 --- a/app/assets/stylesheets/pages/status.scss +++ b/app/assets/stylesheets/pages/status.scss @@ -35,3 +35,20 @@ border-color: $gl-warning; } } + +.ci-status-icon-success { + @extend .cgreen; +} +.ci-status-icon-failed { + @extend .cred; +} +.ci-status-icon-running, +.ci-status-icon-pending { + // These are standard text color +} +.ci-status-icon-canceled, +.ci-status-icon-disabled, +.ci-status-icon-not-found, +.ci-status-icon-skipped { + @extend .cgray; +} diff --git a/app/assets/stylesheets/pages/ui_dev_kit.scss b/app/assets/stylesheets/pages/ui_dev_kit.scss index 277afa1db9..185f3622e6 100644 --- a/app/assets/stylesheets/pages/ui_dev_kit.scss +++ b/app/assets/stylesheets/pages/ui_dev_kit.scss @@ -1,9 +1,6 @@ .gitlab-ui-dev-kit { > h2 { - font-size: 27px; - border-bottom: 1px solid #CCC; - color: #666; - margin: 30px 0; + margin: 35px 0 20px; font-weight: bold; } } diff --git a/app/assets/stylesheets/pages/wiki.scss b/app/assets/stylesheets/pages/wiki.scss index dfaeba41cf..cdf514197c 100644 --- a/app/assets/stylesheets/pages/wiki.scss +++ b/app/assets/stylesheets/pages/wiki.scss @@ -4,3 +4,8 @@ margin-right: auto; padding-right: 7px; } + +.wiki-last-edit-by { + font-size: 80%; + font-weight: normal; +} diff --git a/app/controllers/abuse_reports_controller.rb b/app/controllers/abuse_reports_controller.rb index 2f4054eaa1..20bc5173f1 100644 --- a/app/controllers/abuse_reports_controller.rb +++ b/app/controllers/abuse_reports_controller.rb @@ -10,7 +10,7 @@ class AbuseReportsController < ApplicationController if @abuse_report.save if current_application_settings.admin_notification_email.present? - AbuseReportMailer.delay.notify(@abuse_report.id) + AbuseReportMailer.notify(@abuse_report.id).deliver_later end message = "Thank you for your report. A GitLab administrator will look into it shortly." diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index a9bcfc7456..9dd16f8c73 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -13,6 +13,12 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController end end + def reset_runners_token + @application_setting.reset_runners_registration_token! + flash[:notice] = 'New runners registration token has been generated!' + redirect_to admin_runners_path + end + private def set_application_setting diff --git a/app/controllers/admin/builds_controller.rb b/app/controllers/admin/builds_controller.rb new file mode 100644 index 0000000000..83d9684c70 --- /dev/null +++ b/app/controllers/admin/builds_controller.rb @@ -0,0 +1,23 @@ +class Admin::BuildsController < Admin::ApplicationController + def index + @scope = params[:scope] + @all_builds = Ci::Build + @builds = @all_builds.order('created_at DESC') + @builds = + case @scope + when 'all' + @builds + when 'finished' + @builds.finished + else + @builds.running_or_pending.reverse_order + end + @builds = @builds.page(params[:page]).per(30) + end + + def cancel_all + Ci::Build.running_or_pending.each(&:cancel) + + redirect_to admin_builds_path + end +end diff --git a/app/controllers/admin/identities_controller.rb b/app/controllers/admin/identities_controller.rb index d28614731f..e383fe38ea 100644 --- a/app/controllers/admin/identities_controller.rb +++ b/app/controllers/admin/identities_controller.rb @@ -1,6 +1,21 @@ class Admin::IdentitiesController < Admin::ApplicationController before_action :user - before_action :identity, except: :index + before_action :identity, except: [:index, :new, :create] + + def new + @identity = Identity.new + end + + def create + @identity = Identity.new(identity_params) + @identity.user_id = user.id + + if @identity.save + redirect_to admin_user_identities_path(@user), notice: 'User identity was successfully created.' + else + render :new + end + end def index @identities = @user.identities diff --git a/app/controllers/admin/impersonation_controller.rb b/app/controllers/admin/impersonation_controller.rb index 0382402afa..bf98af7861 100644 --- a/app/controllers/admin/impersonation_controller.rb +++ b/app/controllers/admin/impersonation_controller.rb @@ -5,14 +5,20 @@ class Admin::ImpersonationController < Admin::ApplicationController before_action :authorize_impersonator! def create - session[:impersonator_id] = current_user.username - session[:impersonator_return_to] = request.env['HTTP_REFERER'] + if @user.blocked? + flash[:alert] = "You cannot impersonate a blocked user" - warden.set_user(user, scope: 'user') + redirect_to admin_user_path(@user) + else + session[:impersonator_id] = current_user.username + session[:impersonator_return_to] = admin_user_path(@user) - flash[:alert] = "You are impersonating #{user.username}." + warden.set_user(user, scope: 'user') - redirect_to root_path + flash[:alert] = "You are impersonating #{user.username}." + + redirect_to root_path + end end def destroy diff --git a/app/controllers/admin/runner_projects_controller.rb b/app/controllers/admin/runner_projects_controller.rb new file mode 100644 index 0000000000..d25619d94e --- /dev/null +++ b/app/controllers/admin/runner_projects_controller.rb @@ -0,0 +1,35 @@ +class Admin::RunnerProjectsController < Admin::ApplicationController + before_action :project, only: [:create] + + def index + @runner_projects = project.runner_projects.all + @runner_project = project.runner_projects.new + end + + def create + @runner = Ci::Runner.find(params[:runner_project][:runner_id]) + + if @runner.assign_to(@project, current_user) + redirect_to admin_runner_path(@runner) + else + redirect_to admin_runner_path(@runner), alert: 'Failed adding runner to project' + end + end + + def destroy + rp = Ci::RunnerProject.find(params[:id]) + runner = rp.runner + rp.destroy + + redirect_to admin_runner_path(runner) + end + + private + + def project + @project = Project.find_with_namespace( + [params[:namespace_id], '/', params[:project_id]].join('') + ) + @project || render_404 + end +end diff --git a/app/controllers/admin/runners_controller.rb b/app/controllers/admin/runners_controller.rb new file mode 100644 index 0000000000..a701d49b84 --- /dev/null +++ b/app/controllers/admin/runners_controller.rb @@ -0,0 +1,63 @@ +class Admin::RunnersController < Admin::ApplicationController + before_action :runner, except: :index + + def index + @runners = Ci::Runner.order('id DESC') + @runners = @runners.search(params[:search]) if params[:search].present? + @runners = @runners.page(params[:page]).per(30) + @active_runners_cnt = Ci::Runner.online.count + end + + def show + @builds = @runner.builds.order('id DESC').first(30) + @projects = + if params[:search].present? + ::Project.search(params[:search]) + else + Project.all + end + @projects = @projects.where.not(id: @runner.projects.select(:id)) if @runner.projects.any? + @projects = @projects.page(params[:page]).per(30) + end + + def update + @runner.update_attributes(runner_params) + + respond_to do |format| + format.js + format.html { redirect_to admin_runner_path(@runner) } + end + end + + def destroy + @runner.destroy + + redirect_to admin_runners_path + end + + def resume + if @runner.update_attributes(active: true) + redirect_to admin_runners_path, notice: 'Runner was successfully updated.' + else + redirect_to admin_runners_path, alert: 'Runner was not updated.' + end + end + + def pause + if @runner.update_attributes(active: false) + redirect_to admin_runners_path, notice: 'Runner was successfully updated.' + else + redirect_to admin_runners_path, alert: 'Runner was not updated.' + end + end + + private + + def runner + @runner ||= Ci::Runner.find(params[:id]) + end + + def runner_params + params.require(:runner).permit(:token, :description, :tag_list, :active) + end +end diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb index 202e9da9ee..77c8dafc01 100644 --- a/app/controllers/autocomplete_controller.rb +++ b/app/controllers/autocomplete_controller.rb @@ -1,41 +1,15 @@ class AutocompleteController < ApplicationController skip_before_action :authenticate_user!, only: [:users] + before_action :find_users, only: [:users] def users - begin - @users = - if params[:project_id].present? - project = Project.find(params[:project_id]) - - if can?(current_user, :read_project, project) - project.team.users - end - elsif params[:group_id] - group = Group.find(params[:group_id]) - - if can?(current_user, :read_group, group) - group.users - end - elsif current_user - User.all - end - rescue ActiveRecord::RecordNotFound - if current_user - return render json: {}, status: 404 - end - end - - if @users.nil? && current_user.nil? - authenticate_user! - end - @users ||= User.none @users = @users.search(params[:search]) if params[:search].present? @users = @users.active @users = @users.reorder(:name) @users = @users.page(params[:page]).per(PER_PAGE) - unless params[:search].present? + if params[:search].blank? # Include current user if available to filter by "Me" if params[:current_user] && current_user @users = [*@users, current_user].uniq @@ -49,4 +23,25 @@ class AutocompleteController < ApplicationController @user = User.find(params[:id]) render json: @user, only: [:name, :username, :id], methods: [:avatar_url] end + + private + + def find_users + @users = + if params[:project_id].present? + project = Project.find(params[:project_id]) + return render_404 unless can?(current_user, :read_project, project) + + project.team.users + elsif params[:group_id].present? + group = Group.find(params[:group_id]) + return render_404 unless can?(current_user, :read_group, group) + + group.users + elsif current_user + User.all + else + User.none + end + end end diff --git a/app/controllers/ci/admin/application_controller.rb b/app/controllers/ci/admin/application_controller.rb deleted file mode 100644 index 4ec2dc9c2c..0000000000 --- a/app/controllers/ci/admin/application_controller.rb +++ /dev/null @@ -1,10 +0,0 @@ -module Ci - module Admin - class ApplicationController < Ci::ApplicationController - before_action :authenticate_user! - before_action :authenticate_admin! - - layout "ci/admin" - end - end -end diff --git a/app/controllers/ci/admin/application_settings_controller.rb b/app/controllers/ci/admin/application_settings_controller.rb deleted file mode 100644 index 71e253fac6..0000000000 --- a/app/controllers/ci/admin/application_settings_controller.rb +++ /dev/null @@ -1,31 +0,0 @@ -module Ci - class Admin::ApplicationSettingsController < Ci::Admin::ApplicationController - before_action :set_application_setting - - def show - end - - def update - if @application_setting.update_attributes(application_setting_params) - redirect_to ci_admin_application_settings_path, - notice: 'Application settings saved successfully' - else - render :show - end - end - - private - - def set_application_setting - @application_setting = Ci::ApplicationSetting.current - @application_setting ||= Ci::ApplicationSetting.create_from_defaults - end - - def application_setting_params - params.require(:application_setting).permit( - :all_broken_builds, - :add_pusher, - ) - end - end -end diff --git a/app/controllers/ci/admin/builds_controller.rb b/app/controllers/ci/admin/builds_controller.rb deleted file mode 100644 index 38abfdeafb..0000000000 --- a/app/controllers/ci/admin/builds_controller.rb +++ /dev/null @@ -1,18 +0,0 @@ -module Ci - class Admin::BuildsController < Ci::Admin::ApplicationController - def index - @scope = params[:scope] - @builds = Ci::Build.order('created_at DESC').page(params[:page]).per(30) - - @builds = - case @scope - when "pending" - @builds.pending - when "running" - @builds.running - else - @builds - end - end - end -end diff --git a/app/controllers/ci/admin/events_controller.rb b/app/controllers/ci/admin/events_controller.rb deleted file mode 100644 index 5939efff98..0000000000 --- a/app/controllers/ci/admin/events_controller.rb +++ /dev/null @@ -1,9 +0,0 @@ -module Ci - class Admin::EventsController < Ci::Admin::ApplicationController - EVENTS_PER_PAGE = 50 - - def index - @events = Ci::Event.admin.order('created_at DESC').page(params[:page]).per(EVENTS_PER_PAGE) - end - end -end diff --git a/app/controllers/ci/admin/projects_controller.rb b/app/controllers/ci/admin/projects_controller.rb deleted file mode 100644 index 5bbd0ce739..0000000000 --- a/app/controllers/ci/admin/projects_controller.rb +++ /dev/null @@ -1,19 +0,0 @@ -module Ci - class Admin::ProjectsController < Ci::Admin::ApplicationController - def index - @projects = Ci::Project.ordered_by_last_commit_date.page(params[:page]).per(30) - end - - def destroy - project.destroy - - redirect_to ci_projects_url - end - - protected - - def project - @project ||= Ci::Project.find(params[:id]) - end - end -end diff --git a/app/controllers/ci/admin/runner_projects_controller.rb b/app/controllers/ci/admin/runner_projects_controller.rb deleted file mode 100644 index e7de6eb12c..0000000000 --- a/app/controllers/ci/admin/runner_projects_controller.rb +++ /dev/null @@ -1,34 +0,0 @@ -module Ci - class Admin::RunnerProjectsController < Ci::Admin::ApplicationController - layout 'ci/project' - - def index - @runner_projects = project.runner_projects.all - @runner_project = project.runner_projects.new - end - - def create - @runner = Ci::Runner.find(params[:runner_project][:runner_id]) - - if @runner.assign_to(project, current_user) - redirect_to ci_admin_runner_path(@runner) - else - redirect_to ci_admin_runner_path(@runner), alert: 'Failed adding runner to project' - end - end - - def destroy - rp = Ci::RunnerProject.find(params[:id]) - runner = rp.runner - rp.destroy - - redirect_to ci_admin_runner_path(runner) - end - - private - - def project - @project ||= Ci::Project.find(params[:project_id]) - end - end -end diff --git a/app/controllers/ci/admin/runners_controller.rb b/app/controllers/ci/admin/runners_controller.rb deleted file mode 100644 index 0cafad2741..0000000000 --- a/app/controllers/ci/admin/runners_controller.rb +++ /dev/null @@ -1,73 +0,0 @@ -module Ci - class Admin::RunnersController < Ci::Admin::ApplicationController - before_action :runner, except: :index - - def index - @runners = Ci::Runner.order('id DESC') - @runners = @runners.search(params[:search]) if params[:search].present? - @runners = @runners.page(params[:page]).per(30) - @active_runners_cnt = Ci::Runner.online.count - end - - def show - @builds = @runner.builds.order('id DESC').first(30) - @projects = Ci::Project.all - if params[:search].present? - @gl_projects = ::Project.search(params[:search]) - @projects = @projects.where(gitlab_id: @gl_projects.select(:id)) - end - @projects = @projects.where("ci_projects.id NOT IN (?)", @runner.projects.pluck(:id)) if @runner.projects.any? - @projects = @projects.joins(:gl_project) - @projects = @projects.page(params[:page]).per(30) - end - - def update - @runner.update_attributes(runner_params) - - respond_to do |format| - format.js - format.html { redirect_to ci_admin_runner_path(@runner) } - end - end - - def destroy - @runner.destroy - - redirect_to ci_admin_runners_path - end - - def resume - if @runner.update_attributes(active: true) - redirect_to ci_admin_runners_path, notice: 'Runner was successfully updated.' - else - redirect_to ci_admin_runners_path, alert: 'Runner was not updated.' - end - end - - def pause - if @runner.update_attributes(active: false) - redirect_to ci_admin_runners_path, notice: 'Runner was successfully updated.' - else - redirect_to ci_admin_runners_path, alert: 'Runner was not updated.' - end - end - - def assign_all - Ci::Project.unassigned(@runner).all.each do |project| - @runner.assign_to(project, current_user) - end - - redirect_to ci_admin_runner_path(@runner), notice: "Runner was assigned to all projects" - end - - private - - def runner - @runner ||= Ci::Runner.find(params[:id]) - end - - def runner_params - params.require(:runner).permit(:token, :description, :tag_list, :active) - end - end -end diff --git a/app/controllers/ci/application_controller.rb b/app/controllers/ci/application_controller.rb index 848f2b4e31..c420b59c3a 100644 --- a/app/controllers/ci/application_controller.rb +++ b/app/controllers/ci/application_controller.rb @@ -4,24 +4,16 @@ module Ci "app/helpers/ci" end - helper_method :gl_project - private - def authenticate_token! - unless project.valid_token?(params[:token]) - return head(403) - end - end - def authorize_access_project! - unless can?(current_user, :read_project, gl_project) + unless can?(current_user, :read_project, project) return page_404 end end def authorize_manage_builds! - unless can?(current_user, :manage_builds, gl_project) + unless can?(current_user, :manage_builds, project) return page_404 end end @@ -31,7 +23,7 @@ module Ci end def authorize_manage_project! - unless can?(current_user, :admin_project, gl_project) + unless can?(current_user, :admin_project, project) return page_404 end end @@ -58,9 +50,5 @@ module Ci count: count } end - - def gl_project - ::Project.find(@project.gitlab_id) - end end end diff --git a/app/controllers/ci/lints_controller.rb b/app/controllers/ci/lints_controller.rb index a4f6aff49b..7ed78ff8e9 100644 --- a/app/controllers/ci/lints_controller.rb +++ b/app/controllers/ci/lints_controller.rb @@ -1,5 +1,5 @@ module Ci - class LintsController < Ci::ApplicationController + class LintsController < ApplicationController before_action :authenticate_user! def show diff --git a/app/controllers/ci/projects_controller.rb b/app/controllers/ci/projects_controller.rb index 8406399fb6..3004c2d27f 100644 --- a/app/controllers/ci/projects_controller.rb +++ b/app/controllers/ci/projects_controller.rb @@ -3,13 +3,12 @@ module Ci before_action :project, except: [:index] before_action :authenticate_user!, except: [:index, :build, :badge] before_action :authorize_access_project!, except: [:index, :badge] - before_action :authorize_manage_project!, only: [:toggle_shared_runners, :dumped_yaml] before_action :no_cache, only: [:badge] protect_from_forgery def show # Temporary compatibility with CI badges pointing to CI project page - redirect_to namespace_project_path(project.gl_project.namespace, project.gl_project) + redirect_to namespace_project_path(project.namespace, project) end # Project status badge @@ -20,16 +19,10 @@ module Ci send_file image.path, filename: image.name, disposition: 'inline', type:"image/svg+xml" end - def toggle_shared_runners - project.toggle!(:shared_runners_enabled) - - redirect_to namespace_project_runners_path(project.gl_project.namespace, project.gl_project) - end - protected def project - @project ||= Ci::Project.find(params[:id]) + @project ||= Project.find_by(ci_id: params[:id].to_i) end def no_cache diff --git a/app/controllers/ci/runner_projects_controller.rb b/app/controllers/ci/runner_projects_controller.rb deleted file mode 100644 index 9d55531336..0000000000 --- a/app/controllers/ci/runner_projects_controller.rb +++ /dev/null @@ -1,34 +0,0 @@ -module Ci - class RunnerProjectsController < Ci::ApplicationController - before_action :authenticate_user! - before_action :project - before_action :authorize_manage_project! - - def create - @runner = Ci::Runner.find(params[:runner_project][:runner_id]) - - return head(403) unless current_user.ci_authorized_runners.include?(@runner) - - path = runners_path(@project.gl_project) - - if @runner.assign_to(project, current_user) - redirect_to path - else - redirect_to path, alert: 'Failed adding runner to project' - end - end - - def destroy - runner_project = project.runner_projects.find(params[:id]) - runner_project.destroy - - redirect_to runners_path(@project.gl_project) - end - - private - - def project - @project ||= Ci::Project.find(params[:project_id]) - end - end -end diff --git a/app/controllers/concerns/global_milestones.rb b/app/controllers/concerns/global_milestones.rb index b428249acd..3e4c0e6360 100644 --- a/app/controllers/concerns/global_milestones.rb +++ b/app/controllers/concerns/global_milestones.rb @@ -2,8 +2,10 @@ module GlobalMilestones extend ActiveSupport::Concern def milestones + epoch = DateTime.parse('1970-01-01') @milestones = MilestonesFinder.new.execute(@projects, params) @milestones = GlobalMilestone.build_collection(@milestones) + @milestones = @milestones.sort_by { |x| x.due_date.nil? ? epoch : x.due_date } @milestones = Kaminari.paginate_array(@milestones).page(params[:page]).per(ApplicationController::PER_PAGE) end diff --git a/app/controllers/concerns/issues_action.rb b/app/controllers/concerns/issues_action.rb new file mode 100644 index 0000000000..effd472194 --- /dev/null +++ b/app/controllers/concerns/issues_action.rb @@ -0,0 +1,14 @@ +module IssuesAction + extend ActiveSupport::Concern + + def issues + @issues = get_issues_collection + @issues = @issues.page(params[:page]).per(ApplicationController::PER_PAGE) + @issues = @issues.preload(:author, :project) + + respond_to do |format| + format.html + format.atom { render layout: false } + end + end +end diff --git a/app/controllers/concerns/merge_requests_action.rb b/app/controllers/concerns/merge_requests_action.rb new file mode 100644 index 0000000000..f7a25111db --- /dev/null +++ b/app/controllers/concerns/merge_requests_action.rb @@ -0,0 +1,9 @@ +module MergeRequestsAction + extend ActiveSupport::Concern + + def merge_requests + @merge_requests = get_merge_requests_collection + @merge_requests = @merge_requests.page(params[:page]).per(ApplicationController::PER_PAGE) + @merge_requests = @merge_requests.preload(:author, :target_project) + end +end diff --git a/app/controllers/dashboard/snippets_controller.rb b/app/controllers/dashboard/snippets_controller.rb index f4354c6d8c..b3594d8253 100644 --- a/app/controllers/dashboard/snippets_controller.rb +++ b/app/controllers/dashboard/snippets_controller.rb @@ -1,6 +1,7 @@ class Dashboard::SnippetsController < Dashboard::ApplicationController def index - @snippets = SnippetsFinder.new.execute(current_user, + @snippets = SnippetsFinder.new.execute( + current_user, filter: :by_user, user: current_user, scope: params[:scope] diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index b2c1fa4230..087da93508 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -1,26 +1,12 @@ class DashboardController < Dashboard::ApplicationController + include IssuesAction + include MergeRequestsAction + before_action :event_filter, only: :activity before_action :projects, only: [:issues, :merge_requests] respond_to :html - def merge_requests - @merge_requests = get_merge_requests_collection - @merge_requests = @merge_requests.page(params[:page]).per(PER_PAGE) - @merge_requests = @merge_requests.preload(:author, :target_project) - end - - def issues - @issues = get_issues_collection - @issues = @issues.page(params[:page]).per(PER_PAGE) - @issues = @issues.preload(:author, :project) - - respond_to do |format| - format.html - format.atom { render layout: false } - end - end - def activity @last_push = current_user.recent_push diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index 10233222ee..0c2a350bc3 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -46,7 +46,7 @@ class Groups::MilestonesController < Groups::ApplicationController end def milestone_path(title) - group_milestone_path(@group, title.parameterize, title: title) + group_milestone_path(@group, title.to_slug.to_s, title: title) end def projects diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index fb4eb094f2..fb26a4e6fc 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -1,4 +1,7 @@ class GroupsController < Groups::ApplicationController + include IssuesAction + include MergeRequestsAction + skip_before_action :authenticate_user!, only: [:show, :issues, :merge_requests] respond_to :html before_action :group, except: [:new, :create] @@ -53,23 +56,6 @@ class GroupsController < Groups::ApplicationController end end - def merge_requests - @merge_requests = get_merge_requests_collection - @merge_requests = @merge_requests.page(params[:page]).per(PER_PAGE) - @merge_requests = @merge_requests.preload(:author, :target_project) - end - - def issues - @issues = get_issues_collection - @issues = @issues.page(params[:page]).per(PER_PAGE) - @issues = @issues.preload(:author, :project) - - respond_to do |format| - format.html - format.atom { render layout: false } - end - end - def edit end diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb index 2025158d06..f74daff3bd 100644 --- a/app/controllers/passwords_controller.rb +++ b/app/controllers/passwords_controller.rb @@ -40,7 +40,9 @@ class PasswordsController < Devise::PasswordsController def throttle_reset return unless resource && resource.recently_sent_password_reset? - redirect_to new_password_path(resource_name), - alert: I18n.t('devise.passwords.recently_reset') + # Throttle reset attempts, but return a normal message to + # avoid user enumeration attack. + redirect_to new_user_session_path, + notice: I18n.t('devise.passwords.send_paranoid_instructions') end end diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index 8da7b4d50e..28803164fc 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -70,6 +70,7 @@ class ProfilesController < Profiles::ApplicationController :email, :hide_no_password, :hide_no_ssh_key, + :hide_project_limit, :linkedin, :location, :name, diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb index d3f926b62b..dd32d50919 100644 --- a/app/controllers/projects/application_controller.rb +++ b/app/controllers/projects/application_controller.rb @@ -21,18 +21,14 @@ class Projects::ApplicationController < ApplicationController unless @repository.branch_names.include?(@ref) redirect_to( namespace_project_tree_path(@project.namespace, @project, @ref), - notice: "This action is not allowed unless you are on top of a branch" + notice: "This action is not allowed unless you are on a branch" ) end end private - def ci_enabled + def builds_enabled return render_404 unless @project.builds_enabled? end - - def ci_project - @ci_project ||= @project.ensure_gitlab_ci_project - end end diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index 31a33bfd23..6216368293 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -162,12 +162,20 @@ class Projects::BlobController < Projects::ApplicationController end def sanitized_new_branch_name - @new_branch ||= sanitize(strip_tags(params[:new_branch])) + sanitize(strip_tags(params[:new_branch])) end def editor_variables @current_branch = @ref - @new_branch = params[:new_branch].present? ? sanitized_new_branch_name : @ref + + @new_branch = + if params[:new_branch].present? + sanitized_new_branch_name + elsif ::Gitlab::GitAccess.new(current_user, @project).can_push_to_branch?(@ref) + @ref + else + @repository.next_patch_branch + end @file_path = if action_name.to_s == 'create' diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index 3ac0a75fa7..3c2849a760 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -3,7 +3,7 @@ class Projects::BranchesController < Projects::ApplicationController # Authorize before_action :require_non_empty_project before_action :authorize_download_code! - before_action :authorize_push_code!, only: [:create, :destroy] + before_action :authorize_push_code!, only: [:new, :create, :destroy] def index @sort = params[:sort] || 'name' diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb index 4638f77b88..26ba12520c 100644 --- a/app/controllers/projects/builds_controller.rb +++ b/app/controllers/projects/builds_controller.rb @@ -1,5 +1,4 @@ class Projects::BuildsController < Projects::ApplicationController - before_action :ci_project before_action :build, except: [:index, :cancel_all] before_action :authorize_manage_builds!, except: [:index, :show, :status] @@ -9,7 +8,7 @@ class Projects::BuildsController < Projects::ApplicationController def index @scope = params[:scope] - @all_builds = project.ci_builds + @all_builds = project.builds @builds = @all_builds.order('created_at DESC') @builds = case @scope @@ -24,13 +23,13 @@ class Projects::BuildsController < Projects::ApplicationController end def cancel_all - @project.ci_builds.running_or_pending.each(&:cancel) + @project.builds.running_or_pending.each(&:cancel) redirect_to namespace_project_builds_path(project.namespace, project) end def show - @builds = @ci_project.commits.find_by_sha(@build.sha).builds.order('id DESC') + @builds = @project.ci_commits.find_by_sha(@build.sha).builds.order('id DESC') @builds = @builds.where("id not in (?)", @build.id) @commit = @build.commit @@ -77,7 +76,7 @@ class Projects::BuildsController < Projects::ApplicationController private def build - @build ||= ci_project.builds.unscoped.find_by!(id: params[:id]) + @build ||= project.builds.unscoped.find_by!(id: params[:id]) end def artifacts_file @@ -85,7 +84,7 @@ class Projects::BuildsController < Projects::ApplicationController end def build_path(build) - namespace_project_build_path(build.gl_project.namespace, build.gl_project, build) + namespace_project_build_path(build.project.namespace, build.project, build) end def authorize_manage_builds! diff --git a/app/controllers/projects/ci_services_controller.rb b/app/controllers/projects/ci_services_controller.rb deleted file mode 100644 index 550a019e8e..0000000000 --- a/app/controllers/projects/ci_services_controller.rb +++ /dev/null @@ -1,49 +0,0 @@ -class Projects::CiServicesController < Projects::ApplicationController - before_action :ci_project - before_action :authorize_admin_project! - - layout "project_settings" - - def index - @ci_project.build_missing_services - @services = @ci_project.services.reload - end - - def edit - service - end - - def update - if service.update_attributes(service_params) - redirect_to edit_namespace_project_ci_service_path(@project.namespace, @project, service.to_param) - else - render 'edit' - end - end - - def test - last_build = @project.ci_builds.last - - if service.execute(last_build) - message = { notice: 'We successfully tested the service' } - else - message = { alert: 'We tried to test the service but error occurred' } - end - - redirect_back_or_default(options: message) - end - - private - - def service - @service ||= @ci_project.services.find { |service| service.to_param == params[:id] } - end - - def service_params - params.require(:service).permit( - :type, :active, :webhook, :notify_only_broken_builds, - :email_recipients, :email_only_broken_builds, :email_add_pusher, - :hipchat_token, :hipchat_room, :hipchat_server - ) - end -end diff --git a/app/controllers/projects/ci_settings_controller.rb b/app/controllers/projects/ci_settings_controller.rb deleted file mode 100644 index a263242a85..0000000000 --- a/app/controllers/projects/ci_settings_controller.rb +++ /dev/null @@ -1,36 +0,0 @@ -class Projects::CiSettingsController < Projects::ApplicationController - before_action :ci_project - before_action :authorize_admin_project! - - layout "project_settings" - - def edit - end - - def update - if ci_project.update_attributes(project_params) - Ci::EventService.new.change_project_settings(current_user, ci_project) - - redirect_to edit_namespace_project_ci_settings_path(project.namespace, project), notice: 'Project was successfully updated.' - else - render action: "edit" - end - end - - def destroy - ci_project.destroy - Ci::EventService.new.remove_project(current_user, ci_project) - project.gitlab_ci_service.update_attributes(active: false) - - redirect_to project_path(project), notice: "CI was disabled for this project" - end - - protected - - def project_params - params.require(:project).permit(:path, :timeout, :timeout_in_minutes, :default_ref, :always_build, - :polling_interval, :public, :ssh_url_to_repo, :allow_git_fetch, :email_recipients, - :email_add_pusher, :email_only_broken_builds, :coverage_regex, :shared_runners_enabled, :token, - { variables_attributes: [:id, :key, :value, :_destroy] }) - end -end diff --git a/app/controllers/projects/ci_web_hooks_controller.rb b/app/controllers/projects/ci_web_hooks_controller.rb deleted file mode 100644 index a2d470d4a6..0000000000 --- a/app/controllers/projects/ci_web_hooks_controller.rb +++ /dev/null @@ -1,45 +0,0 @@ -class Projects::CiWebHooksController < Projects::ApplicationController - before_action :ci_project - before_action :authorize_admin_project! - - layout "project_settings" - - def index - @web_hooks = @ci_project.web_hooks - @web_hook = Ci::WebHook.new - end - - def create - @web_hook = @ci_project.web_hooks.new(web_hook_params) - @web_hook.save - - if @web_hook.valid? - redirect_to namespace_project_ci_web_hooks_path(@project.namespace, @project) - else - @web_hooks = @ci_project.web_hooks.select(&:persisted?) - render :index - end - end - - def test - Ci::TestHookService.new.execute(hook, current_user) - - redirect_back_or_default(default: { action: 'index' }) - end - - def destroy - hook.destroy - - redirect_to namespace_project_ci_web_hooks_path(@project.namespace, @project) - end - - private - - def hook - @web_hook ||= @ci_project.web_hooks.find(params[:id]) - end - - def web_hook_params - params.require(:web_hook).permit(:url) - end -end diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index deefdd7666..0aaba3792b 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -31,13 +31,12 @@ class Projects::CommitController < Projects::ApplicationController end def builds - @ci_project = @project.gitlab_ci_project end def cancel_builds ci_commit.builds.running_or_pending.each(&:cancel) - redirect_to builds_namespace_project_commit_path(project.namespace, project, commit.sha) + redirect_back_or_default default: builds_namespace_project_commit_path(project.namespace, project, commit.sha) end def retry_builds @@ -47,7 +46,7 @@ class Projects::CommitController < Projects::ApplicationController end end - redirect_to builds_namespace_project_commit_path(project.namespace, project, commit.sha) + redirect_back_or_default default: builds_namespace_project_commit_path(project.namespace, project, commit.sha) end def branches @@ -67,10 +66,15 @@ class Projects::CommitController < Projects::ApplicationController end def define_show_vars - @diffs = commit.diffs + if params[:w].to_i == 1 + @diffs = commit.diffs({ ignore_whitespace_change: true }) + else + @diffs = commit.diffs + end + @notes_count = commit.notes.count - - @builds = ci_commit.builds if ci_commit + + @statuses = ci_commit.statuses if ci_commit end def authorize_manage_builds! diff --git a/app/controllers/projects/graphs_controller.rb b/app/controllers/projects/graphs_controller.rb index 418b92040b..d13ea9f34b 100644 --- a/app/controllers/projects/graphs_controller.rb +++ b/app/controllers/projects/graphs_controller.rb @@ -5,7 +5,7 @@ class Projects::GraphsController < Projects::ApplicationController before_action :require_non_empty_project before_action :assign_ref_vars before_action :authorize_download_code! - before_action :ci_enabled, only: :ci + before_action :builds_enabled, only: :ci def show respond_to do |format| @@ -25,13 +25,31 @@ class Projects::GraphsController < Projects::ApplicationController end def ci - ci_project = @project.gitlab_ci_project - @charts = {} - @charts[:week] = Ci::Charts::WeekChart.new(ci_project) - @charts[:month] = Ci::Charts::MonthChart.new(ci_project) - @charts[:year] = Ci::Charts::YearChart.new(ci_project) - @charts[:build_times] = Ci::Charts::BuildTime.new(ci_project) + @charts[:week] = Ci::Charts::WeekChart.new(project) + @charts[:month] = Ci::Charts::MonthChart.new(project) + @charts[:year] = Ci::Charts::YearChart.new(project) + @charts[:build_times] = Ci::Charts::BuildTime.new(project) + end + + def languages + @languages = Linguist::Repository.new(@repository.rugged, @repository.rugged.head.target_id).languages + total = @languages.map(&:last).sum + + @languages = @languages.map do |language| + name, share = language + color = Digest::SHA256.hexdigest(name)[0...6] + { + value: (share.to_f * 100 / total).round(2), + label: name, + color: "##{color}", + highlight: "##{color}" + } + end + + @languages.sort! do |x, y| + y[:value] <=> x[:value] + end end private diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb index c756954189..5fd4f855de 100644 --- a/app/controllers/projects/hooks_controller.rb +++ b/app/controllers/projects/hooks_controller.rb @@ -25,13 +25,12 @@ class Projects::HooksController < Projects::ApplicationController def test if !@project.empty_repo? - status = TestHookService.new.execute(hook, current_user) + status, message = TestHookService.new.execute(hook, current_user) if status flash[:notice] = 'Hook successfully executed.' else - flash[:alert] = 'Hook execution failed. '\ - 'Ensure hook URL is correct and service is up.' + flash[:alert] = "Hook execution failed: #{message}" end else flash[:alert] = 'Hook execution failed. Ensure the project has commits.' @@ -54,6 +53,7 @@ class Projects::HooksController < Projects::ApplicationController def hook_params params.require(:hook).permit(:url, :push_events, :issues_events, - :merge_requests_events, :tag_push_events, :note_events, :enable_ssl_verification) + :merge_requests_events, :tag_push_events, :note_events, + :build_events, :enable_ssl_verification) end end diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 5250a0f5e6..b59b52291f 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -58,10 +58,10 @@ class Projects::IssuesController < Projects::ApplicationController end def show - @participants = @issue.participants(current_user) @note = @project.notes.new(noteable: @issue) @notes = @issue.notes.nonawards.with_associations.fresh @noteable = @issue + @merge_requests = @issue.referenced_merge_requests respond_with(@issue) end @@ -158,12 +158,10 @@ class Projects::IssuesController < Projects::ApplicationController end def issue_params - permitted = params.require(:issue).permit( + params.require(:issue).permit( :title, :assignee_id, :position, :description, :milestone_id, :state_event, :task_num, label_ids: [] ) - params[:issue][:title].strip! if params[:issue][:title] - permitted end def bulk_update_params diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 6378a1f56b..ab5c953189 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -1,13 +1,14 @@ class Projects::MergeRequestsController < Projects::ApplicationController before_action :module_enabled before_action :merge_request, only: [ - :edit, :update, :show, :diffs, :commits, :merge, :merge_check, - :ci_status, :toggle_subscription + :edit, :update, :show, :diffs, :commits, :builds, :merge, :merge_check, + :ci_status, :toggle_subscription, :cancel_merge_when_build_succeeds ] - before_action :closes_issues, only: [:edit, :update, :show, :diffs, :commits] - before_action :validates_merge_request, only: [:show, :diffs, :commits] - before_action :define_show_vars, only: [:show, :diffs, :commits] - before_action :ensure_ref_fetched, only: [:show, :commits, :diffs] + before_action :closes_issues, only: [:edit, :update, :show, :diffs, :commits, :builds] + before_action :validates_merge_request, only: [:show, :diffs, :commits, :builds] + before_action :define_show_vars, only: [:show, :diffs, :commits, :builds] + before_action :define_widget_vars, only: [:merge, :cancel_merge_when_build_succeeds, :merge_check] + before_action :ensure_ref_fetched, only: [:show, :diffs, :commits, :builds] # Allow read any merge_request before_action :authorize_read_merge_request! @@ -79,6 +80,13 @@ class Projects::MergeRequestsController < Projects::ApplicationController end end + def builds + respond_to do |format| + format.html { render 'show' } + format.json { render json: { html: view_to_html_string('projects/merge_requests/show/_builds') } } + end + end + def new params[:merge_request] ||= ActionController::Parameters.new(source_project: @project) @merge_request = MergeRequests::BuildService.new(project, current_user, merge_request_params).execute @@ -91,20 +99,18 @@ class Projects::MergeRequestsController < Projects::ApplicationController @target_project = merge_request.target_project @source_project = merge_request.source_project - @commits = @merge_request.compare_commits + @commits = @merge_request.compare_commits.reverse @commit = @merge_request.last_commit @first_commit = @merge_request.first_commit @diffs = @merge_request.compare_diffs + + @ci_commit = @merge_request.ci_commit + @statuses = @ci_commit.statuses if @ci_commit + @note_counts = Note.where(commit_id: @commits.map(&:id)). group(:commit_id).count end - def edit - @source_project = @merge_request.source_project - @target_project = @merge_request.target_project - @target_branches = @merge_request.target_project.repository.branch_names - end - def create @target_branches ||= [] @merge_request = MergeRequests::CreateService.new(project, current_user, merge_request_params).execute @@ -118,6 +124,12 @@ class Projects::MergeRequestsController < Projects::ApplicationController end end + def edit + @source_project = @merge_request.source_project + @target_project = @merge_request.target_project + @target_branches = @merge_request.target_project.repository.branch_names + end + def update @merge_request = MergeRequests::UpdateService.new(project, current_user, merge_request_params).execute(@merge_request) @@ -141,24 +153,34 @@ class Projects::MergeRequestsController < Projects::ApplicationController end def merge_check - if @merge_request.unchecked? - @merge_request.check_if_can_be_merged - end - - closes_issues + @merge_request.check_if_can_be_merged if @merge_request.unchecked? render partial: "projects/merge_requests/widget/show.html.haml", layout: false end + def cancel_merge_when_build_succeeds + return access_denied! unless @merge_request.can_cancel_merge_when_build_succeeds?(current_user) + + MergeRequests::MergeWhenBuildSucceedsService.new(@project, current_user).cancel(@merge_request) + end + def merge return access_denied! unless @merge_request.can_be_merged_by?(current_user) - if @merge_request.mergeable? - @merge_request.update(merge_error: nil) - MergeWorker.perform_async(@merge_request.id, current_user.id, params) - @status = true + unless @merge_request.mergeable? + @status = :failed + return + end + + @merge_request.update(merge_error: nil) + + if params[:merge_when_build_succeeds].present? && @merge_request.ci_commit && @merge_request.ci_commit.active? + MergeRequests::MergeWhenBuildSucceedsService.new(@project, current_user, merge_params) + .execute(@merge_request) + @status = :merge_when_build_succeeds else - @status = false + MergeWorker.perform_async(@merge_request.id, current_user.id, params) + @status = :success end end @@ -250,8 +272,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController end def define_show_vars - @participants = @merge_request.participants(current_user) - # Build a note object for comment form @note = @project.notes.new(noteable: @merge_request) @notes = @merge_request.mr_and_commit_notes.nonawards.inc_author.fresh @@ -264,25 +284,35 @@ class Projects::MergeRequestsController < Projects::ApplicationController @merge_request_diff = @merge_request.merge_request_diff + @ci_commit = @merge_request.ci_commit + @statuses = @ci_commit.statuses if @ci_commit + if @merge_request.locked_long_ago? @merge_request.unlock_mr @merge_request.close end end + def define_widget_vars + @ci_commit = @merge_request.ci_commit + closes_issues + end + def invalid_mr # Render special view for MR with removed source or target branch render 'invalid' end def merge_request_params - permitted = params.require(:merge_request).permit( + params.require(:merge_request).permit( :title, :assignee_id, :source_project_id, :source_branch, :target_project_id, :target_branch, :milestone_id, :state_event, :description, :task_num, label_ids: [] ) - params[:merge_request][:title].strip! if params[:merge_request][:title] - permitted + end + + def merge_params + params.permit(:should_remove_source_branch, :commit_message) end # Make sure merge requests created before 8.0 diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb index 5ac18446aa..ee705f32e8 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -13,7 +13,8 @@ class Projects::NotesController < Projects::ApplicationController @notes.each do |note| notes_json[:notes] << { id: note.id, - html: note_to_html(note) + html: note_to_html(note), + valid: note.valid? } end @@ -68,7 +69,7 @@ class Projects::NotesController < Projects::ApplicationController data = { author: current_user, is_award: true, - note: note_params[:note].gsub(":", '') + note: note_params[:note].delete(":") } note = noteable.notes.find_by(data) @@ -131,16 +132,25 @@ class Projects::NotesController < Projects::ApplicationController end def render_note_json(note) - render json: { - id: note.id, - discussion_id: note.discussion_id, - html: note_to_html(note), - award: note.is_award, - emoji_path: note.is_award ? view_context.image_url(::AwardEmoji.path_to_emoji_image(note.note)) : "", - note: note.note, - discussion_html: note_to_discussion_html(note), - discussion_with_diff_html: note_to_discussion_with_diff_html(note) - } + if note.valid? + render json: { + valid: true, + id: note.id, + discussion_id: note.discussion_id, + html: note_to_html(note), + award: note.is_award, + emoji_path: note.is_award ? view_context.image_url(::AwardEmoji.path_to_emoji_image(note.note)) : "", + note: note.note, + discussion_html: note_to_discussion_html(note), + discussion_with_diff_html: note_to_discussion_with_diff_html(note) + } + else + render json: { + valid: false, + award: note.is_award, + errors: note.errors + } + end end def authorize_admin_note! diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index 07eb94e4f4..8364fc293b 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -23,7 +23,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController @group_members = @group_members.where(user_id: users) end - @group_members = @group_members.order('access_level DESC').limit(20) + @group_members = @group_members.order('access_level DESC') end @project_member = @project.project_members.new diff --git a/app/controllers/projects/protected_branches_controller.rb b/app/controllers/projects/protected_branches_controller.rb index 6b52eccebf..e49259c34b 100644 --- a/app/controllers/projects/protected_branches_controller.rb +++ b/app/controllers/projects/protected_branches_controller.rb @@ -21,7 +21,7 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController if protected_branch && protected_branch.update_attributes( - developers_can_push: params[:developers_can_push] + developers_can_push: params[:developers_can_push] ) respond_to do |format| diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb index d5ee6ac866..be7d5c187f 100644 --- a/app/controllers/projects/raw_controller.rb +++ b/app/controllers/projects/raw_controller.rb @@ -10,15 +10,13 @@ class Projects::RawController < Projects::ApplicationController @blob = @repository.blob_at(@commit.id, @path) if @blob - type = get_blob_type - headers['X-Content-Type-Options'] = 'nosniff' - send_data( - @blob.data, - type: type, - disposition: 'inline' - ) + if @blob.lfs_pointer? + send_lfs_object + else + stream_data + end else render_404 end @@ -35,4 +33,33 @@ class Projects::RawController < Projects::ApplicationController 'application/octet-stream' end end + + def stream_data + type = get_blob_type + + send_data( + @blob.data, + type: type, + disposition: 'inline' + ) + end + + def send_lfs_object + lfs_object = find_lfs_object + + if lfs_object && lfs_object.project_allowed_access?(@project) + send_file lfs_object.file.path, filename: @blob.name, disposition: 'attachment' + else + render_404 + end + end + + def find_lfs_object + lfs_object = LfsObject.find_by_oid(@blob.lfs_oid) + if lfs_object && lfs_object.file.exists? + lfs_object + else + nil + end + end end diff --git a/app/controllers/projects/runner_projects_controller.rb b/app/controllers/projects/runner_projects_controller.rb new file mode 100644 index 0000000000..e2785caa2f --- /dev/null +++ b/app/controllers/projects/runner_projects_controller.rb @@ -0,0 +1,26 @@ +class Projects::RunnerProjectsController < Projects::ApplicationController + before_action :authorize_admin_project! + + layout 'project_settings' + + def create + @runner = Ci::Runner.find(params[:runner_project][:runner_id]) + + return head(403) unless current_user.ci_authorized_runners.include?(@runner) + + path = runners_path(project) + + if @runner.assign_to(project, current_user) + redirect_to path + else + redirect_to path, alert: 'Failed adding runner to project' + end + end + + def destroy + runner_project = project.runner_projects.find(params[:id]) + runner_project.destroy + + redirect_to runners_path(project) + end +end diff --git a/app/controllers/projects/runners_controller.rb b/app/controllers/projects/runners_controller.rb index bfbcf2567f..4993b2648a 100644 --- a/app/controllers/projects/runners_controller.rb +++ b/app/controllers/projects/runners_controller.rb @@ -1,14 +1,13 @@ class Projects::RunnersController < Projects::ApplicationController - before_action :ci_project before_action :set_runner, only: [:edit, :update, :destroy, :pause, :resume, :show] before_action :authorize_admin_project! layout 'project_settings' def index - @runners = @ci_project.runners.ordered + @runners = project.runners.ordered @specific_runners = current_user.ci_authorized_runners. - where.not(id: @ci_project.runners). + where.not(id: project.runners). ordered.page(params[:page]).per(20) @shared_runners = Ci::Runner.shared.active @shared_runners_count = @shared_runners.count(:all) @@ -26,7 +25,7 @@ class Projects::RunnersController < Projects::ApplicationController end def destroy - if @runner.only_for?(@ci_project) + if @runner.only_for?(project) @runner.destroy end @@ -52,10 +51,16 @@ class Projects::RunnersController < Projects::ApplicationController def show end + def toggle_shared_runners + project.toggle!(:shared_runners_enabled) + + redirect_to namespace_project_runners_path(project.namespace, project) + end + protected def set_runner - @runner ||= @ci_project.runners.find(params[:id]) + @runner ||= project.runners.find(params[:id]) end def runner_params diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index 42dbb497e0..8b2577aebe 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -1,14 +1,17 @@ class Projects::ServicesController < Projects::ApplicationController - ALLOWED_PARAMS = [:title, :token, :type, :active, :api_key, :api_version, :subdomain, + ALLOWED_PARAMS = [:title, :token, :type, :active, :api_key, :api_url, :api_version, :subdomain, :room, :recipients, :project_url, :webhook, :user_key, :device, :priority, :sound, :bamboo_url, :username, :password, :build_key, :server, :teamcity_url, :drone_url, :build_type, :description, :issues_url, :new_issue_url, :restrict_to_branch, :channel, :colorize_messages, :channels, :push_events, :issues_events, :merge_requests_events, :tag_push_events, - :note_events, :send_from_committer_email, :disable_diffs, :external_wiki_url, + :note_events, :build_events, + :notify_only_broken_builds, :add_pusher, + :send_from_committer_email, :disable_diffs, :external_wiki_url, :notify, :color, - :server_host, :server_port, :default_irc_uri, :enable_ssl_verification] + :server_host, :server_port, :default_irc_uri, :enable_ssl_verification, + :jira_issue_transition_id] # Parameters to ignore if no value is specified FILTER_BLANK_PARAMS = [:password] diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb index cb39c2b878..280fe12cc7 100644 --- a/app/controllers/projects/tags_controller.rb +++ b/app/controllers/projects/tags_controller.rb @@ -2,7 +2,7 @@ class Projects::TagsController < Projects::ApplicationController # Authorize before_action :require_non_empty_project before_action :authorize_download_code! - before_action :authorize_push_code!, only: [:create] + before_action :authorize_push_code!, only: [:new, :create] before_action :authorize_admin_project!, only: [:destroy] def index diff --git a/app/controllers/projects/triggers_controller.rb b/app/controllers/projects/triggers_controller.rb index 782ebd01b0..30adfad1da 100644 --- a/app/controllers/projects/triggers_controller.rb +++ b/app/controllers/projects/triggers_controller.rb @@ -1,22 +1,21 @@ class Projects::TriggersController < Projects::ApplicationController - before_action :ci_project before_action :authorize_admin_project! layout 'project_settings' def index - @triggers = @ci_project.triggers + @triggers = project.triggers @trigger = Ci::Trigger.new end def create - @trigger = @ci_project.triggers.new + @trigger = project.triggers.new @trigger.save if @trigger.valid? redirect_to namespace_project_triggers_path(@project.namespace, @project) else - @triggers = @ci_project.triggers.select(&:persisted?) + @triggers = project.triggers.select(&:persisted?) render :index end end @@ -30,6 +29,6 @@ class Projects::TriggersController < Projects::ApplicationController private def trigger - @trigger ||= @ci_project.triggers.find(params[:id]) + @trigger ||= project.triggers.find(params[:id]) end end diff --git a/app/controllers/projects/variables_controller.rb b/app/controllers/projects/variables_controller.rb index d6561a45a7..10efafea9d 100644 --- a/app/controllers/projects/variables_controller.rb +++ b/app/controllers/projects/variables_controller.rb @@ -1,5 +1,4 @@ class Projects::VariablesController < Projects::ApplicationController - before_action :ci_project before_action :authorize_admin_project! layout 'project_settings' @@ -8,9 +7,7 @@ class Projects::VariablesController < Projects::ApplicationController end def update - if ci_project.update_attributes(project_params) - Ci::EventService.new.change_project_settings(current_user, ci_project) - + if project.update_attributes(project_params) redirect_to namespace_project_variables_path(project.namespace, project), notice: 'Variables were successfully updated.' else render action: 'show' diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 23453195e8..bf5e25ff89 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -123,7 +123,7 @@ class ProjectsController < ApplicationController ::Projects::DestroyService.new(@project, current_user, {}).execute flash[:alert] = "Project '#{@project.name}' was deleted." - redirect_back_or_default(default: dashboard_projects_path, options: {}) + redirect_to dashboard_projects_path rescue Projects::DestroyService::DestroyError => ex redirect_to edit_project_path(@project), alert: ex.message end @@ -210,10 +210,10 @@ class ProjectsController < ApplicationController def project_params params.require(:project).permit( - :name, :path, :description, :issues_tracker, :tag_list, + :name, :path, :description, :issues_tracker, :tag_list, :runners_token, :issues_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, :default_branch, :wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar, - :builds_enabled + :builds_enabled, :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex, ) end diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index 08f2483af3..c72df73af4 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -2,7 +2,7 @@ class SnippetsController < ApplicationController before_action :snippet, only: [:show, :edit, :destroy, :update, :raw] # Allow read snippet - before_action :authorize_read_snippet!, only: [:show] + before_action :authorize_read_snippet!, only: [:show, :raw] # Allow modify snippet before_action :authorize_update_snippet!, only: [:edit, :update] diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb index c407dfc163..3d5e8b6fbe 100644 --- a/app/finders/issuable_finder.rb +++ b/app/finders/issuable_finder.rb @@ -62,10 +62,10 @@ class IssuableFinder if project? @project = Project.find(params[:project_id]) - + unless Ability.abilities.allowed?(current_user, :read_project, @project) @project = nil - end + end else @project = nil end @@ -77,11 +77,11 @@ class IssuableFinder return @projects if defined?(@projects) if project? - project + @projects = project elsif current_user && params[:authorized_only].presence && !current_user_related? - current_user.authorized_projects + @projects = current_user.authorized_projects else - ProjectsFinder.new.execute(current_user) + @projects = ProjectsFinder.new.execute(current_user) end end @@ -190,8 +190,10 @@ class IssuableFinder def by_project(items) items = - if projects - items.of_projects(projects).references(:project) + if project? + items.of_projects(projects).references_project + elsif projects + items.merge(projects.reorder(nil)).join_project else items.none end @@ -206,7 +208,9 @@ class IssuableFinder end def sort(items) - items.sort(params[:sort]) + # Ensure we always have an explicit sort order (instead of inheriting + # multiple orders when combining ActiveRecord::Relation objects). + params[:sort] ? items.sort(params[:sort]) : items.reorder(id: :desc) end def by_assignee(items) diff --git a/app/finders/milestones_finder.rb b/app/finders/milestones_finder.rb index b704e87890..630c73c2a9 100644 --- a/app/finders/milestones_finder.rb +++ b/app/finders/milestones_finder.rb @@ -1,7 +1,7 @@ class MilestonesFinder def execute(projects, params) milestones = Milestone.of_projects(projects) - milestones = milestones.order("due_date ASC") + milestones = milestones.reorder("due_date ASC") case params[:state] when 'closed' then milestones.closed diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb index dd35c215c5..3b4e0362e0 100644 --- a/app/finders/projects_finder.rb +++ b/app/finders/projects_finder.rb @@ -23,17 +23,17 @@ class ProjectsFinder group = options[:group] if group - base, extra = group_projects(current_user, group) + segments = group_projects(current_user, group) else - base, extra = all_projects(current_user) + segments = all_projects(current_user) end - if base and extra - union = Gitlab::SQL::Union.new([base.select(:id), extra.select(:id)]) + if segments.length > 1 + union = Gitlab::SQL::Union.new(segments.map { |s| s.select(:id) }) Project.where("projects.id IN (#{union.to_sql})") else - base + segments.first end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 8ecdeaf8e7..0b00b9a070 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -61,14 +61,14 @@ module ApplicationHelper options[:class] ||= '' options[:class] << ' identicon' bg_key = project.id % 7 - style = "background-color: ##{ allowed_colors.values[bg_key] }; color: #555" + style = "background-color: ##{allowed_colors.values[bg_key]}; color: #555" content_tag(:div, class: options[:class], style: style) do project.name[0, 1].upcase end end - def avatar_icon(user_or_email = nil, size = nil) + def avatar_icon(user_or_email = nil, size = nil, scale = 2) if user_or_email.is_a?(User) user = user_or_email else @@ -78,12 +78,12 @@ module ApplicationHelper if user user.avatar_url(size) || default_avatar else - gravatar_icon(user_or_email, size) + gravatar_icon(user_or_email, size, scale) end end - def gravatar_icon(user_email = '', size = nil) - GravatarService.new.execute(user_email, size) || + def gravatar_icon(user_email = '', size = nil, scale = 2) + GravatarService.new.execute(user_email, size, scale) || default_avatar end @@ -204,12 +204,16 @@ module ApplicationHelper # Returns an HTML-safe String def time_ago_with_tooltip(time, placement: 'top', html_class: 'time_ago', skip_js: false) element = content_tag :time, time.to_s, - class: "#{html_class} js-timeago", + class: "#{html_class} js-timeago js-timeago-pending", datetime: time.getutc.iso8601, title: time.in_time_zone.stamp('Aug 21, 2011 9:23pm'), data: { toggle: 'tooltip', placement: placement, container: 'body' } - element += javascript_tag "$('.js-timeago').timeago()" unless skip_js + unless skip_js + element << javascript_tag( + "$('.js-timeago-pending').removeClass('js-timeago-pending').timeago()" + ) + end element end diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index 77d99140c4..68e5d5be60 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -30,26 +30,24 @@ module BlobHelper nil end - if blob && blob.text? - text = 'Edit' - after = options[:after] || '' - from_mr = options[:from_merge_request_id] - link_opts = {} - link_opts[:from_merge_request_id] = from_mr if from_mr - cls = 'btn btn-small' - if allowed_tree_edit?(project, ref) - link_to(text, - namespace_project_edit_blob_path(project.namespace, project, - tree_join(ref, path), - link_opts), - class: cls - ) - else - content_tag :span, text, class: cls + ' disabled' - end + after.html_safe - else - '' - end + return unless blob && blob.text? && blob_editable?(blob) + + text = 'Edit' + after = options[:after] || '' + from_mr = options[:from_merge_request_id] + link_opts = {} + link_opts[:from_merge_request_id] = from_mr if from_mr + cls = 'btn btn-small' + link_to(text, + namespace_project_edit_blob_path(project.namespace, project, + tree_join(ref, path), + link_opts), + class: cls + ) + after.html_safe + end + + def blob_editable?(blob, project = @project, ref = @ref) + !blob.lfs_pointer? && allowed_tree_edit?(project, ref) end def leave_edit_message @@ -60,7 +58,7 @@ module BlobHelper if Gitlab::MarkupHelper.previewable?(filename) 'Preview' else - 'Preview changes' + 'Preview Changes' end end @@ -71,4 +69,16 @@ module BlobHelper def blob_icon(mode, name) icon("#{file_type_icon_class('file', mode, name)} fw") end + + def blob_viewable?(blob) + blob && blob.text? && !blob.lfs_pointer? + end + + def blob_size(blob) + if blob.lfs_pointer? + blob.lfs_size + else + blob.size + end + end end diff --git a/app/helpers/branches_helper.rb b/app/helpers/branches_helper.rb index d6eaa7d57b..e39548e17e 100644 --- a/app/helpers/branches_helper.rb +++ b/app/helpers/branches_helper.rb @@ -11,7 +11,7 @@ module BranchesHelper def can_push_branch?(project, branch_name) return false unless project.repository.branch_names.include?(branch_name) - + ::Gitlab::GitAccess.new(current_user, project).can_push_to_branch?(branch_name) end end diff --git a/app/helpers/button_helper.rb b/app/helpers/button_helper.rb new file mode 100644 index 0000000000..ec0e3f409c --- /dev/null +++ b/app/helpers/button_helper.rb @@ -0,0 +1,58 @@ +module ButtonHelper + # Output a "Copy to Clipboard" button + # + # data - Data attributes passed to `content_tag` + # + # Examples: + # + # # Define the clipboard's text + # clipboard_button(clipboard_text: "Foo") + # # => "" + # + # # Define the target element + # clipboard_button(clipboard_target: "div#foo") + # # => "" + # + # See http://clipboardjs.com/#usage + def clipboard_button(data = {}) + content_tag :button, + icon('clipboard'), + class: 'btn btn-xs btn-clipboard', + data: data, + type: :button + end + + def http_clone_button(project) + klass = 'btn js-protocol-switch' + klass << ' active' if default_clone_protocol == 'http' + klass << ' has_tooltip' if current_user.try(:require_password?) + + protocol = gitlab_config.protocol.upcase + + content_tag :button, protocol, + class: klass, + data: { + clone: project.http_url_to_repo, + container: 'body', + html: 'true', + title: "Set a password on your account
to pull or push via #{protocol}" + }, + type: :button + end + + def ssh_clone_button(project) + klass = 'btn js-protocol-switch' + klass << ' active' if default_clone_protocol == 'ssh' + klass << ' has_tooltip' if current_user.try(:require_ssh_key?) + + content_tag :button, 'SSH', + class: klass, + data: { + clone: project.ssh_url_to_repo, + container: 'body', + html: 'true', + title: 'Add an SSH key to your profile
to pull or push via SSH.' + }, + type: :button + end +end diff --git a/app/helpers/ci/gitlab_helper.rb b/app/helpers/ci/gitlab_helper.rb deleted file mode 100644 index e34c8be1df..0000000000 --- a/app/helpers/ci/gitlab_helper.rb +++ /dev/null @@ -1,17 +0,0 @@ -module Ci - module GitlabHelper - def no_turbolink - { :"data-no-turbolink" => "data-no-turbolink" } - end - - def yaml_web_editor_link(project) - commits = project.commits - - if commits.any? && commits.last.ci_yaml_file - "#{project.gitlab_url}/edit/master/.gitlab-ci.yml" - else - "#{project.gitlab_url}/new/master" - end - end - end -end diff --git a/app/helpers/ci/projects_helper.rb b/app/helpers/ci/projects_helper.rb deleted file mode 100644 index fd991a4165..0000000000 --- a/app/helpers/ci/projects_helper.rb +++ /dev/null @@ -1,36 +0,0 @@ -module Ci - module ProjectsHelper - def ref_tab_class ref = nil - 'active' if ref == @ref - end - - def success_ratio(success_builds, failed_builds) - failed_builds = failed_builds.count(:all) - success_builds = success_builds.count(:all) - - return 100 if failed_builds.zero? - - ratio = (success_builds.to_f / (success_builds + failed_builds)) * 100 - ratio.to_i - end - - def markdown_badge_code(project, ref) - url = status_ci_project_url(project, ref: ref, format: 'png') - "[![build status](#{url})](#{ci_project_url(project, ref: ref)})" - end - - def html_badge_code(project, ref) - url = status_ci_project_url(project, ref: ref, format: 'png') - "" - end - - def project_uses_specific_runner?(project) - project.runners.any? - end - - def no_runners_for_project?(project) - project.runners.blank? && - Ci::Runner.shared.blank? - end - end -end diff --git a/app/helpers/ci_badge_helper.rb b/app/helpers/ci_badge_helper.rb new file mode 100644 index 0000000000..27386133e3 --- /dev/null +++ b/app/helpers/ci_badge_helper.rb @@ -0,0 +1,13 @@ +module CiBadgeHelper + def markdown_badge_code(project, ref) + url = status_ci_project_url(project, ref: ref, format: 'png') + link = namespace_project_commits_path(project.namespace, project, ref) + "[![build status](#{url})](#{link})" + end + + def html_badge_code(project, ref) + url = status_ci_project_url(project, ref: ref, format: 'png') + link = namespace_project_commits_path(project.namespace, project, ref) + "" + end +end diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb index 0ecf77bb45..d8bee21c82 100644 --- a/app/helpers/ci_status_helper.rb +++ b/app/helpers/ci_status_helper.rb @@ -1,6 +1,6 @@ module CiStatusHelper def ci_status_path(ci_commit) - project = ci_commit.gl_project + project = ci_commit.project builds_namespace_project_commit_path(project.namespace, project, ci_commit.sha) end @@ -8,22 +8,21 @@ module CiStatusHelper ci_icon_for_status(ci_commit.status) end - def ci_status_color(ci_commit) - case ci_commit.status - when 'success' - 'green' - when 'failed' - 'red' - when 'running', 'pending' - 'yellow' - else - 'gray' - end + def ci_status_label(ci_commit) + ci_label_for_status(ci_commit.status) end def ci_status_with_icon(status) content_tag :span, class: "ci-status ci-#{status}" do - ci_icon_for_status(status) + ' '.html_safe + status + ci_icon_for_status(status) + ' '.html_safe + ci_label_for_status(status) + end + end + + def ci_label_for_status(status) + if status == 'success' + 'passed' + else + status end end @@ -40,15 +39,19 @@ module CiStatusHelper 'circle' end - icon(icon_name) + icon(icon_name + ' fw') end def render_ci_status(ci_commit) - link_to ci_status_path(ci_commit), - class: "c#{ci_status_color(ci_commit)}", - title: "Build status: #{ci_commit.status}", - data: { toggle: 'tooltip', placement: 'left' } do - ci_status_icon(ci_commit) - end + link_to ci_status_icon(ci_commit), + ci_status_path(ci_commit), + class: "ci-status-link ci-status-icon-#{ci_commit.status.dasherize}", + title: "Build #{ci_status_label(ci_commit)}", + data: { toggle: 'tooltip', placement: 'left' } + end + + def no_runners_for_project?(project) + project.runners.blank? && + Ci::Runner.shared.blank? end end diff --git a/app/helpers/clipboard_helper.rb b/app/helpers/clipboard_helper.rb deleted file mode 100644 index 3c1d7569fa..0000000000 --- a/app/helpers/clipboard_helper.rb +++ /dev/null @@ -1,8 +0,0 @@ -module ClipboardHelper - def clipboard_button - content_tag :button, - icon('clipboard'), - class: 'btn btn-xs btn-clipboard js-clipboard-trigger', - type: :button - end -end diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index 9df20c9fce..590d20ac7b 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -109,7 +109,7 @@ module CommitsHelper ) elsif @path.present? return link_to( - "Browse Dir »", + "Browse Directory »", namespace_project_tree_path(project.namespace, project, tree_join(commit.id, @path)), class: "pull-right" @@ -117,7 +117,7 @@ module CommitsHelper end end link_to( - "Browse Code »", + "Browse Files »", namespace_project_tree_path(project.namespace, project, commit), class: "pull-right" ) diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index 0fd5c98658..24134310fc 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -136,33 +136,19 @@ module DiffHelper end def inline_diff_btn - params_copy = params.dup - params_copy[:view] = 'inline' - # Always use HTML to handle case where JSON diff rendered this button - params_copy.delete(:format) - - link_to url_for(params_copy), id: "inline-diff-btn", class: (diff_view == 'inline' ? 'btn active' : 'btn') do - 'Inline' - end + diff_btn('Inline', 'inline', diff_view == 'inline') end def parallel_diff_btn - params_copy = params.dup - params_copy[:view] = 'parallel' - # Always use HTML to handle case where JSON diff rendered this button - params_copy.delete(:format) - - link_to url_for(params_copy), id: "parallel-diff-btn", class: (diff_view == 'parallel' ? 'btn active' : 'btn') do - 'Side-by-side' - end + diff_btn('Side-by-side', 'parallel', diff_view == 'parallel') end def submodule_link(blob, ref, repository = @repository) tree, commit = submodule_links(blob, ref, repository) commit_id = if commit.nil? - blob.id[0..10] + Commit.truncate_sha(blob.id) else - link_to "#{blob.id[0..10]}", commit + link_to Commit.truncate_sha(blob.id), commit end [ @@ -191,4 +177,18 @@ module DiffHelper def editable_diff?(diff) !diff.deleted_file && @merge_request && @merge_request.source_project end + + private + + def diff_btn(title, name, selected) + params_copy = params.dup + params_copy[:view] = name + + # Always use HTML to handle case where JSON diff rendered this button + params_copy.delete(:format) + + link_to url_for(params_copy), id: "#{name}-diff-btn", class: (selected ? 'btn active' : 'btn') do + title + end + end end diff --git a/app/helpers/emails_helper.rb b/app/helpers/emails_helper.rb index 45788ba95a..41b5bd7be9 100644 --- a/app/helpers/emails_helper.rb +++ b/app/helpers/emails_helper.rb @@ -28,6 +28,8 @@ module EmailsHelper return "View #{action.humanize.singularize}" end end + + nil end def color_email_diff(diffcontent) diff --git a/app/helpers/external_wiki_helper.rb b/app/helpers/external_wiki_helper.rb index 838b85afdf..1f3401f290 100644 --- a/app/helpers/external_wiki_helper.rb +++ b/app/helpers/external_wiki_helper.rb @@ -1,7 +1,7 @@ module ExternalWikiHelper def get_project_wiki_path(project) external_wiki_service = project.services. - select { |service| service.to_param == 'external_wiki' }.first + find { |service| service.to_param == 'external_wiki' } if external_wiki_service.present? && external_wiki_service.active? external_wiki_service.properties['external_wiki_url'] else diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb index 6581348212..ca41657cec 100644 --- a/app/helpers/gitlab_markdown_helper.rb +++ b/app/helpers/gitlab_markdown_helper.rb @@ -20,7 +20,7 @@ module GitlabMarkdownHelper end user = current_user if defined?(current_user) - gfm_body = Gitlab::Markdown.gfm(escaped_body, project: @project, current_user: user) + gfm_body = Banzai.render(escaped_body, project: @project, current_user: user, pipeline: :single_line) fragment = Nokogiri::HTML::DocumentFragment.parse(gfm_body) if fragment.children.size == 1 && fragment.children[0].name == 'a' @@ -48,47 +48,34 @@ module GitlabMarkdownHelper def markdown(text, context = {}) return "" unless text.present? - context.reverse_merge!( - path: @path, - pipeline: :default, - project: @project, - project_wiki: @project_wiki, - ref: @ref + context[:project] ||= @project + + html = Banzai.render(text, context) + + context.merge!( + current_user: (current_user if defined?(current_user)), + + # RelativeLinkFilter + requested_path: @path, + project_wiki: @project_wiki, + ref: @ref ) - user = current_user if defined?(current_user) - - html = Gitlab::Markdown.render(text, context) - Gitlab::Markdown.post_process(html, pipeline: context[:pipeline], project: @project, user: user) - end - - # TODO (rspeicher): Remove all usages of this helper and just call `markdown` - # with a custom pipeline depending on the content being rendered - def gfm(text, options = {}) - return "" unless text.present? - - options.reverse_merge!( - path: @path, - pipeline: :default, - project: @project, - project_wiki: @project_wiki, - ref: @ref - ) - - user = current_user if defined?(current_user) - - html = Gitlab::Markdown.gfm(text, options) - Gitlab::Markdown.post_process(html, pipeline: options[:pipeline], project: @project, user: user) + Banzai.post_process(html, context) end def asciidoc(text) - Gitlab::Asciidoc.render(text, { - commit: @commit, - project: @project, - project_wiki: @project_wiki, + Gitlab::Asciidoc.render( + text, + project: @project, + current_user: (current_user if defined?(current_user)), + + # RelativeLinkFilter + project_wiki: @project_wiki, requested_path: @path, - ref: @ref - }) + ref: @ref, + commit: @commit + ) end # Return the first line of +text+, up to +max_chars+, after parsing the line diff --git a/app/helpers/gitlab_routing_helper.rb b/app/helpers/gitlab_routing_helper.rb index b0b536d464..f3fddef01c 100644 --- a/app/helpers/gitlab_routing_helper.rb +++ b/app/helpers/gitlab_routing_helper.rb @@ -6,7 +6,7 @@ # # For example instead of this: # -# namespace_project_merge_request_path(merge_request.project.namespace, merge_request.projects, merge_request) +# namespace_project_merge_request_path(merge_request.project.namespace, merge_request.project, merge_request) # # We can simply use shortcut: # diff --git a/app/helpers/graph_helper.rb b/app/helpers/graph_helper.rb index 1e372d5631..c2ab80f2e0 100644 --- a/app/helpers/graph_helper.rb +++ b/app/helpers/graph_helper.rb @@ -16,4 +16,14 @@ module GraphHelper ids = parents.map { |p| p.id } ids.zip(parent_spaces) end + + def success_ratio(success_builds, failed_builds) + failed_builds = failed_builds.count(:all) + success_builds = success_builds.count(:all) + + return 100 if failed_builds.zero? + + ratio = (success_builds.to_f / (success_builds + failed_builds)) * 100 + ratio.to_i + end end diff --git a/app/helpers/icons_helper.rb b/app/helpers/icons_helper.rb index 1cf5b96481..5724d3aabe 100644 --- a/app/helpers/icons_helper.rb +++ b/app/helpers/icons_helper.rb @@ -27,16 +27,20 @@ module IconsHelper end end - def public_icon - icon('globe fw') - end + def visibility_level_icon(level, fw: true) + name = + case level + when Gitlab::VisibilityLevel::PRIVATE + 'lock' + when Gitlab::VisibilityLevel::INTERNAL + 'shield' + else # Gitlab::VisibilityLevel::PUBLIC + 'globe' + end + + name << " fw" if fw - def internal_icon - icon('shield fw') - end - - def private_icon - icon('lock fw') + icon(name) end def file_type_icon_class(type, mode, name) diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 493f370d9a..d2186427db 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -44,25 +44,28 @@ module IssuesHelper end def bulk_update_milestone_options - options_for_select([['None (backlog)', -1]]) + - options_from_collection_for_select(project_active_milestones, 'id', - 'title', params[:milestone_id]) + milestones = project_active_milestones.to_a + milestones.unshift(Milestone::None) + + options_from_collection_for_select(milestones, 'id', 'title', params[:milestone_id]) end def milestone_options(object) - options_from_collection_for_select(object.project.milestones.active, - 'id', 'title', object.milestone_id) + milestones = object.project.milestones.active.to_a + milestones.unshift(Milestone::None) + + options_from_collection_for_select(milestones, 'id', 'title', object.milestone_id) end - def issue_box_class(item) + def status_box_class(item) if item.respond_to?(:expired?) && item.expired? - 'issue-box-expired' + 'status-box-expired' elsif item.respond_to?(:merged?) && item.merged? - 'issue-box-merged' + 'status-box-merged' elsif item.closed? - 'issue-box-closed' + 'status-box-closed' else - 'issue-box-open' + 'status-box-open' end end @@ -84,7 +87,11 @@ module IssuesHelper end def merge_requests_sentence(merge_requests) - merge_requests.map(&:to_reference).to_sentence(last_word_connector: ', or ') + # Sorting based on the `!123` or `group/project!123` reference will sort + # local merge requests first. + merge_requests.map do |merge_request| + merge_request.to_reference(@project) + end.sort.to_sentence(last_word_connector: ', or ') end def url_to_emoji(name) @@ -96,7 +103,7 @@ module IssuesHelper def emoji_author_list(notes, current_user) list = notes.map do |note| - note.author == current_user ? "me" : note.author.username + note.author == current_user ? "me" : note.author.name end list.join(", ") @@ -114,6 +121,6 @@ module IssuesHelper end end - # Required for Gitlab::Markdown::IssueReferenceFilter + # Required for Banzai::Filter::IssueReferenceFilter module_function :url_for_issue end diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb index 795fb439f2..a2c3d4d2f3 100644 --- a/app/helpers/labels_helper.rb +++ b/app/helpers/labels_helper.rb @@ -107,6 +107,6 @@ module LabelsHelper options_from_collection_for_select(grouped_labels, 'name', 'title', params[:label_name]) end - # Required for Gitlab::Markdown::LabelReferenceFilter + # Required for Banzai::Filter::LabelReferenceFilter module_function :render_colored_label, :text_color_for_bg, :escape_once end diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb index b804d4f4e3..1dd07a2a22 100644 --- a/app/helpers/merge_requests_helper.rb +++ b/app/helpers/merge_requests_helper.rb @@ -27,7 +27,16 @@ module MergeRequestsHelper end def ci_build_details_path(merge_request) - merge_request.source_project.ci_service.build_page(merge_request.last_commit.sha, merge_request.source_branch) + build_url = merge_request.source_project.ci_service.build_page(merge_request.last_commit.sha, merge_request.source_branch) + return nil unless build_url + + parsed_url = URI.parse(build_url) + + unless parsed_url.userinfo.blank? + parsed_url.userinfo = '' + end + + parsed_url.to_s end def merge_path_description(merge_request, separator) @@ -39,7 +48,11 @@ module MergeRequestsHelper end def issues_sentence(issues) - issues.map(&:to_reference).to_sentence + # Sorting based on the `#123` or `group/project#123` reference will sort + # local issues first. + issues.map do |issue| + issue.to_reference(@project) + end.sort.to_sentence end def mr_change_branches_path(merge_request) @@ -49,18 +62,21 @@ module MergeRequestsHelper source_project_id: @merge_request.source_project_id, target_project_id: @merge_request.target_project_id, source_branch: @merge_request.source_branch, - target_branch: nil - } + target_branch: @merge_request.target_branch, + }, + change_branches: true ) end def source_branch_with_namespace(merge_request) + branch = link_to(merge_request.source_branch, namespace_project_commits_path(merge_request.source_project.namespace, merge_request.source_project, merge_request.source_branch)) + if merge_request.for_fork? namespace = link_to(merge_request.source_project_namespace, project_path(merge_request.source_project)) - namespace + ":#{merge_request.source_branch}" + namespace + ":" + branch else - merge_request.source_branch + branch end end diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb index ad43892b63..a42cbcff18 100644 --- a/app/helpers/milestones_helper.rb +++ b/app/helpers/milestones_helper.rb @@ -28,7 +28,9 @@ module MilestonesHelper Milestone.where(project_id: @projects) end.active + epoch = DateTime.parse('1970-01-01') grouped_milestones = GlobalMilestone.build_collection(milestones) + grouped_milestones = grouped_milestones.sort_by { |x| x.due_date.nil? ? epoch : x.due_date } grouped_milestones.unshift(Milestone::None) grouped_milestones.unshift(Milestone::Any) diff --git a/app/helpers/namespaces_helper.rb b/app/helpers/namespaces_helper.rb index b3132a1f3b..faba418c4d 100644 --- a/app/helpers/namespaces_helper.rb +++ b/app/helpers/namespaces_helper.rb @@ -1,10 +1,10 @@ module NamespacesHelper - def namespaces_options(selected = :current_user, scope = :default) + def namespaces_options(selected = :current_user, display_path: false) groups = current_user.owned_groups + current_user.masters_groups users = [current_user.namespace] - group_opts = ["Groups", groups.sort_by(&:human_name).map {|g| [g.human_name, g.id]} ] - users_opts = [ "Users", users.sort_by(&:human_name).map {|u| [u.human_name, u.id]} ] + group_opts = ["Groups", groups.sort_by(&:human_name).map {|g| [display_path ? g.path : g.human_name, g.id]} ] + users_opts = [ "Users", users.sort_by(&:human_name).map {|u| [display_path ? u.path : u.human_name, u.id]} ] options = [] options << group_opts @@ -17,15 +17,6 @@ module NamespacesHelper grouped_options_for_select(options, selected) end - def namespace_select_tag(id, opts = {}) - css_class = "ajax-namespace-select " - css_class << "multiselect " if opts[:multiple] - css_class << (opts[:class] || '') - value = opts[:selected] || '' - - hidden_field_tag(id, value, class: css_class) - end - def namespace_icon(namespace, size = 40) if namespace.kind_of?(Group) group_icon(namespace) diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb index 9b1dd8b8e5..e6fb8670e5 100644 --- a/app/helpers/nav_helper.rb +++ b/app/helpers/nav_helper.rb @@ -4,6 +4,14 @@ module NavHelper end def nav_sidebar_class + if nav_menu_collapsed? + "sidebar-collapsed" + else + "sidebar-expanded" + end + end + + def page_sidebar_class if nav_menu_collapsed? "page-sidebar-collapsed" else diff --git a/app/helpers/page_layout_helper.rb b/app/helpers/page_layout_helper.rb index 775cf5a3dd..9bf750124b 100644 --- a/app/helpers/page_layout_helper.rb +++ b/app/helpers/page_layout_helper.rb @@ -4,7 +4,8 @@ module PageLayoutHelper @page_title.push(*titles.compact) if titles.any? - @page_title.join(" | ") + # Segments are seperated by middot + @page_title.join(" \u00b7 ") end def header_title(title = nil, title_url = nil) diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index c9cd4a0d54..777817e24a 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -21,7 +21,7 @@ module ProjectsHelper end def link_to_member(project, author, opts = {}) - default_opts = { avatar: true, name: true, size: 16, author_class: 'author' } + default_opts = { avatar: true, name: true, size: 16, author_class: 'author', title: ":name" } opts = default_opts.merge(opts) return "(deleted)" unless author @@ -39,7 +39,8 @@ module ProjectsHelper if opts[:name] link_to(author_html, user_path(author), class: "author_link").html_safe else - link_to(author_html, user_path(author), class: "author_link has_tooltip", data: { :'original-title' => sanitize(author.name) } ).html_safe + title = opts[:title].sub(":name", sanitize(author.name)) + link_to(author_html, user_path(author), class: "author_link has_tooltip", data: { :'original-title' => title, container: 'body' } ).html_safe end end @@ -173,13 +174,20 @@ module ProjectsHelper 'unknown' end - def default_url_to_repo(project = nil) - project = project || @project - current_user ? project.url_to_repo : project.http_url_to_repo + def default_url_to_repo(project = @project) + if default_clone_protocol == "ssh" + project.ssh_url_to_repo + else + project.http_url_to_repo + end end def default_clone_protocol - current_user ? "ssh" : "http" + if !current_user || current_user.require_ssh_key? + "http" + else + "ssh" + end end def project_last_activity(project) @@ -322,10 +330,9 @@ module ProjectsHelper def filename_path(project, filename) if project && blob = project.repository.send(filename) namespace_project_blob_path( - project.namespace, - project, - tree_join(project.default_branch, - blob.name) + project.namespace, + project, + tree_join(project.default_branch, blob.name) ) end end diff --git a/app/helpers/runners_helper.rb b/app/helpers/runners_helper.rb index 46eb82a354..9fb42487a7 100644 --- a/app/helpers/runners_helper.rb +++ b/app/helpers/runners_helper.rb @@ -19,7 +19,7 @@ module RunnersHelper id = "\##{runner.id}" if current_user && current_user.admin - link_to ci_admin_runner_path(runner) do + link_to admin_runner_path(runner) do display_name + id end else diff --git a/app/helpers/selects_helper.rb b/app/helpers/selects_helper.rb index 12fce8db70..05386d790c 100644 --- a/app/helpers/selects_helper.rb +++ b/app/helpers/selects_helper.rb @@ -15,12 +15,14 @@ module SelectsHelper html = { class: css_class, - 'data-placeholder' => placeholder, - 'data-null-user' => null_user, - 'data-any-user' => any_user, - 'data-email-user' => email_user, - 'data-first-user' => first_user, - 'data-current-user' => current_user + data: { + placeholder: placeholder, + null_user: null_user, + any_user: any_user, + email_user: email_user, + first_user: first_user, + current_user: current_user + } } unless opts[:scope] == :all @@ -35,8 +37,33 @@ module SelectsHelper end def groups_select_tag(id, opts = {}) - css_class = "ajax-groups-select " - css_class << "multiselect " if opts[:multiple] + opts[:class] ||= '' + opts[:class] << ' ajax-groups-select' + select2_tag(id, opts) + end + + def namespace_select_tag(id, opts = {}) + opts[:class] ||= '' + opts[:class] << ' ajax-namespace-select' + select2_tag(id, opts) + end + + def project_select_tag(id, opts = {}) + opts[:class] ||= '' + opts[:class] << ' ajax-project-select' + + unless opts.delete(:scope) == :all + if @group + opts['data-group-id'] = @group.id + end + end + + hidden_field_tag(id, opts[:selected], opts) + end + + def select2_tag(id, opts = {}) + css_class = '' + css_class << 'multiselect ' if opts[:multiple] css_class << (opts[:class] || '') value = opts[:selected] || '' diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb index 03a49e119b..f448dd0ab6 100644 --- a/app/helpers/tree_helper.rb +++ b/app/helpers/tree_helper.rb @@ -46,12 +46,26 @@ module TreeHelper File.join(*args) end + def on_top_of_branch?(project = @project, ref = @ref) + project.repository.branch_names.include?(ref) + end + def allowed_tree_edit?(project = nil, ref = nil) project ||= @project ref ||= @ref - return false unless project.repository.branch_names.include?(ref) + return false unless on_top_of_branch?(project, ref) - ::Gitlab::GitAccess.new(current_user, project).can_push_to_branch?(ref) + can?(current_user, :push_code, project) + end + + def tree_edit_branch(project = @project, ref = @ref) + if allowed_tree_edit?(project, ref) + if can_push_branch?(project, ref) + ref + else + project.repository.next_patch_branch + end + end end def tree_breadcrumbs(tree, max_links = 2) @@ -65,7 +79,7 @@ module TreeHelper part_path = File.join(part_path, part) unless part_path.empty? part_path = part if part_path.empty? - next unless parts.last(2).include?(part) if parts.count > max_links + next if parts.count > max_links && !parts.last(2).include?(part) yield(part, tree_join(@ref, part_path)) end end diff --git a/app/helpers/triggers_helper.rb b/app/helpers/triggers_helper.rb index 2a3a7e80fc..8cad994d10 100644 --- a/app/helpers/triggers_helper.rb +++ b/app/helpers/triggers_helper.rb @@ -1,5 +1,5 @@ module TriggersHelper - def ci_build_trigger_url(project_id, ref_name) - "#{Settings.gitlab_ci.url}/ci/api/v1/projects/#{project_id}/refs/#{ref_name}/trigger" + def builds_trigger_url(project_id) + "#{Settings.gitlab.url}/api/v3/projects/#{project_id}/trigger/builds" end end diff --git a/app/helpers/visibility_level_helper.rb b/app/helpers/visibility_level_helper.rb index b52cd23aba..2e69ce923a 100644 --- a/app/helpers/visibility_level_helper.rb +++ b/app/helpers/visibility_level_helper.rb @@ -12,61 +12,41 @@ module VisibilityLevelHelper # Return the description for the +level+ argument. # - # +level+ One of the Gitlab::VisibilityLevel constants - # +form_model+ Either a model object (Project, Snippet, etc.) or the name of - # a Project or Snippet class. + # +level+ One of the Gitlab::VisibilityLevel constants + # +form_model+ Either a model object (Project, Snippet, etc.) or the name of + # a Project or Snippet class. def visibility_level_description(level, form_model) - case form_model.is_a?(String) ? form_model : form_model.class.name - when 'PersonalSnippet', 'ProjectSnippet', 'Snippet' - snippet_visibility_level_description(level) - when 'Project' + case form_model + when Project project_visibility_level_description(level) + when Snippet + snippet_visibility_level_description(level, form_model) end end def project_visibility_level_description(level) - capture_haml do - haml_tag :span do - case level - when Gitlab::VisibilityLevel::PRIVATE - haml_concat "Project access must be granted explicitly for each user." - when Gitlab::VisibilityLevel::INTERNAL - haml_concat "The project can be cloned by" - haml_concat "any logged in user." - when Gitlab::VisibilityLevel::PUBLIC - haml_concat "The project can be cloned" - haml_concat "without any" - haml_concat "authentication." - end - end - end - end - - def snippet_visibility_level_description(level) - capture_haml do - haml_tag :span do - case level - when Gitlab::VisibilityLevel::PRIVATE - haml_concat "The snippet is visible only for me." - when Gitlab::VisibilityLevel::INTERNAL - haml_concat "The snippet is visible for any logged in user." - when Gitlab::VisibilityLevel::PUBLIC - haml_concat "The snippet can be accessed" - haml_concat "without any" - haml_concat "authentication." - end - end - end - end - - def visibility_level_icon(level) case level when Gitlab::VisibilityLevel::PRIVATE - private_icon + "Project access must be granted explicitly to each user." when Gitlab::VisibilityLevel::INTERNAL - internal_icon + "The project can be cloned by any logged in user." when Gitlab::VisibilityLevel::PUBLIC - public_icon + "The project can be cloned without any authentication." + end + end + + def snippet_visibility_level_description(level, snippet = nil) + case level + when Gitlab::VisibilityLevel::PRIVATE + if snippet.is_a? ProjectSnippet + "The snippet is visible only to project members." + else + "The snippet is visible only to me." + end + when Gitlab::VisibilityLevel::INTERNAL + "The snippet is visible to any logged in user." + when Gitlab::VisibilityLevel::PUBLIC + "The snippet can be accessed without any authentication." end end diff --git a/app/mailers/base_mailer.rb b/app/mailers/base_mailer.rb index aedb088918..8b83bbd93b 100644 --- a/app/mailers/base_mailer.rb +++ b/app/mailers/base_mailer.rb @@ -8,10 +8,6 @@ class BaseMailer < ActionMailer::Base default from: Proc.new { default_sender_address.format } default reply_to: Proc.new { default_reply_to_address.format } - def self.delay - delay_for(2.seconds) - end - def can? Ability.abilities.allowed?(current_user, action, subject) end diff --git a/app/mailers/ci/emails/builds.rb b/app/mailers/ci/emails/builds.rb deleted file mode 100644 index 6fb4fba85e..0000000000 --- a/app/mailers/ci/emails/builds.rb +++ /dev/null @@ -1,17 +0,0 @@ -module Ci - module Emails - module Builds - def build_fail_email(build_id, to) - @build = Ci::Build.find(build_id) - @project = @build.project - mail(to: to, subject: subject("Build failed for #{@project.name}", @build.short_sha)) - end - - def build_success_email(build_id, to) - @build = Ci::Build.find(build_id) - @project = @build.project - mail(to: to, subject: subject("Build success for #{@project.name}", @build.short_sha)) - end - end - end -end diff --git a/app/mailers/ci/notify.rb b/app/mailers/ci/notify.rb deleted file mode 100644 index 404842cf21..0000000000 --- a/app/mailers/ci/notify.rb +++ /dev/null @@ -1,46 +0,0 @@ -module Ci - class Notify < ActionMailer::Base - include Ci::Emails::Builds - - add_template_helper Ci::GitlabHelper - - default_url_options[:host] = Gitlab.config.gitlab.host - default_url_options[:protocol] = Gitlab.config.gitlab.protocol - default_url_options[:port] = Gitlab.config.gitlab.port unless Gitlab.config.gitlab_on_standard_port? - default_url_options[:script_name] = Gitlab.config.gitlab.relative_url_root - - default from: Gitlab.config.gitlab.email_from - - # Just send email with 3 seconds delay - def self.delay - delay_for(2.seconds) - end - - private - - # Formats arguments into a String suitable for use as an email subject - # - # extra - Extra Strings to be inserted into the subject - # - # Examples - # - # >> subject('Lorem ipsum') - # => "GitLab-CI | Lorem ipsum" - # - # # Automatically inserts Project name when @project is set - # >> @project = Project.last - # => # - # >> subject('Lorem ipsum') - # => "GitLab-CI | Ruby on Rails | Lorem ipsum " - # - # # Accepts multiple arguments - # >> subject('Lorem ipsum', 'Dolor sit amet') - # => "GitLab-CI | Lorem ipsum | Dolor sit amet" - def subject(*extra) - subject = "GitLab-CI" - subject << (@project ? " | #{@project.name}" : "") - subject << " | " + extra.join(' | ') if extra.present? - subject - end - end -end diff --git a/app/mailers/emails/builds.rb b/app/mailers/emails/builds.rb new file mode 100644 index 0000000000..d58609a2de --- /dev/null +++ b/app/mailers/emails/builds.rb @@ -0,0 +1,15 @@ +module Emails + module Builds + def build_fail_email(build_id, to) + @build = Ci::Build.find(build_id) + @project = @build.project + mail(to: to, subject: subject("Build failed for #{@project.name}", @build.short_sha)) + end + + def build_success_email(build_id, to) + @build = Ci::Build.find(build_id) + @project = @build.project + mail(to: to, subject: subject("Build success for #{@project.name}", @build.short_sha)) + end + end +end diff --git a/app/mailers/emails/issues.rb b/app/mailers/emails/issues.rb index 2c035fbb70..abdeefed5e 100644 --- a/app/mailers/emails/issues.rb +++ b/app/mailers/emails/issues.rb @@ -1,53 +1,49 @@ module Emails module Issues def new_issue_email(recipient_id, issue_id) - @issue = Issue.find(issue_id) - @project = @issue.project - @target_url = namespace_project_issue_url(@project.namespace, @project, @issue) - mail_new_thread(@issue, - from: sender(@issue.author_id), - to: recipient(recipient_id), - subject: subject("#{@issue.title} (##{@issue.iid})")) - - SentNotification.record(@issue, recipient_id, reply_key) + issue_mail_with_notification(issue_id, recipient_id) do + mail_new_thread(@issue, issue_thread_options(@issue.author_id, recipient_id)) + end end def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id, updated_by_user_id) - @issue = Issue.find(issue_id) - @previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id - @project = @issue.project - @target_url = namespace_project_issue_url(@project.namespace, @project, @issue) - mail_answer_thread(@issue, - from: sender(updated_by_user_id), - to: recipient(recipient_id), - subject: subject("#{@issue.title} (##{@issue.iid})")) - - SentNotification.record(@issue, recipient_id, reply_key) + issue_mail_with_notification(issue_id, recipient_id) do + @previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id + mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id)) + end end def closed_issue_email(recipient_id, issue_id, updated_by_user_id) - @issue = Issue.find issue_id - @project = @issue.project - @updated_by = User.find updated_by_user_id - @target_url = namespace_project_issue_url(@project.namespace, @project, @issue) - mail_answer_thread(@issue, - from: sender(updated_by_user_id), - to: recipient(recipient_id), - subject: subject("#{@issue.title} (##{@issue.iid})")) - - SentNotification.record(@issue, recipient_id, reply_key) + issue_mail_with_notification(issue_id, recipient_id) do + @updated_by = User.find updated_by_user_id + mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id)) + end end def issue_status_changed_email(recipient_id, issue_id, status, updated_by_user_id) - @issue = Issue.find issue_id - @issue_status = status + issue_mail_with_notification(issue_id, recipient_id) do + @issue_status = status + @updated_by = User.find updated_by_user_id + mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id)) + end + end + + private + + def issue_thread_options(sender_id, recipient_id) + { + from: sender(sender_id), + to: recipient(recipient_id), + subject: subject("#{@issue.title} (##{@issue.iid})") + } + end + + def issue_mail_with_notification(issue_id, recipient_id) + @issue = Issue.find(issue_id) @project = @issue.project - @updated_by = User.find updated_by_user_id @target_url = namespace_project_issue_url(@project.namespace, @project, @issue) - mail_answer_thread(@issue, - from: sender(updated_by_user_id), - to: recipient(recipient_id), - subject: subject("#{@issue.title} (##{@issue.iid})")) + + yield SentNotification.record(@issue, recipient_id, reply_key) end diff --git a/app/mailers/emails/notes.rb b/app/mailers/emails/notes.rb index 87ba94a583..65f37e9267 100644 --- a/app/mailers/emails/notes.rb +++ b/app/mailers/emails/notes.rb @@ -1,49 +1,54 @@ module Emails module Notes def note_commit_email(recipient_id, note_id) - @note = Note.find(note_id) - @commit = @note.noteable - @project = @note.project - @target_url = namespace_project_commit_url(@project.namespace, @project, - @commit, anchor: - "note_#{@note.id}") - mail_answer_thread(@commit, - from: sender(@note.author_id), - to: recipient(recipient_id), - subject: subject("#{@commit.title} (#{@commit.short_id})")) + note_mail_with_notification(note_id, recipient_id) do + @commit = @note.noteable + @target_url = namespace_project_commit_url(*note_target_url_options) - SentNotification.record_note(@note, recipient_id, reply_key) + mail_answer_thread(@commit, + from: sender(@note.author_id), + to: recipient(recipient_id), + subject: subject("#{@commit.title} (#{@commit.short_id})")) + end end def note_issue_email(recipient_id, note_id) - @note = Note.find(note_id) - @issue = @note.noteable - @project = @note.project - @target_url = namespace_project_issue_url(@project.namespace, @project, - @issue, anchor: - "note_#{@note.id}") - mail_answer_thread(@issue, - from: sender(@note.author_id), - to: recipient(recipient_id), - subject: subject("#{@issue.title} (##{@issue.iid})")) - - SentNotification.record_note(@note, recipient_id, reply_key) + note_mail_with_notification(note_id, recipient_id) do + @issue = @note.noteable + @target_url = namespace_project_issue_url(*note_target_url_options) + mail_answer_thread(@issue, note_thread_options(recipient_id)) + end end def note_merge_request_email(recipient_id, note_id) - @note = Note.find(note_id) - @merge_request = @note.noteable - @project = @note.project - @target_url = namespace_project_merge_request_url(@project.namespace, - @project, - @merge_request, anchor: - "note_#{@note.id}") - mail_answer_thread(@merge_request, - from: sender(@note.author_id), - to: recipient(recipient_id), - subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) + note_mail_with_notification(note_id, recipient_id) do + @merge_request = @note.noteable + @target_url = namespace_project_merge_request_url(*note_target_url_options) + mail_answer_thread(@merge_request, note_thread_options(recipient_id)) + end + end - SentNotification.record_note(@note, recipient_id, reply_key) + private + + def note_target_url_options + [@project.namespace, @project, @note.noteable, anchor: "note_#{@note.id}"] + end + + def note_thread_options(recipient_id) + { + from: sender(@note.author_id), + to: recipient(recipient_id), + subject: subject("#{@note.noteable.title} (##{@note.noteable.iid})") + } + end + + def note_mail_with_notification(note_id, recipient_id) + @note = Note.find(note_id) + @project = @note.project + + yield + + SentNotification.record(@note, recipient_id, reply_key) end end end diff --git a/app/mailers/emails/projects.rb b/app/mailers/emails/projects.rb index caba63006d..b96418679b 100644 --- a/app/mailers/emails/projects.rb +++ b/app/mailers/emails/projects.rb @@ -59,85 +59,17 @@ module Emails subject: subject("Project was moved")) end - def repository_push_email(project_id, recipient, author_id: nil, - ref: nil, - action: nil, - compare: nil, - reverse_compare: false, - send_from_committer_email: false, - disable_diffs: false) - unless author_id && ref && action - raise ArgumentError, "missing keywords: author_id, ref, action" - end + def repository_push_email(project_id, recipient, opts = {}) + @message = + Gitlab::Email::Message::RepositoryPush.new(self, project_id, recipient, opts) - @project = Project.find(project_id) - @current_user = @author = User.find(author_id) - @reverse_compare = reverse_compare - @compare = compare - @ref_name = Gitlab::Git.ref_name(ref) - @ref_type = Gitlab::Git.tag_ref?(ref) ? "tag" : "branch" - @action = action - @disable_diffs = disable_diffs + # used in notify layout + @target_url = @message.target_url - if @compare - @commits = Commit.decorate(compare.commits, @project) - @diffs = compare.diffs - end - - @action_name = - case action - when :create - "pushed new" - when :delete - "deleted" - else - "pushed to" - end - - @subject = "[Git]" - @subject << "[#{@project.path_with_namespace}]" - @subject << "[#{@ref_name}]" if action == :push - @subject << " " - - if action == :push - if @commits.length > 1 - @target_url = namespace_project_compare_url(@project.namespace, - @project, - from: Commit.new(@compare.base, @project), - to: Commit.new(@compare.head, @project)) - @subject << "Deleted " if @reverse_compare - @subject << "#{@commits.length} commits: #{@commits.first.title}" - else - @target_url = namespace_project_commit_url(@project.namespace, - @project, @commits.first) - - @subject << "Deleted 1 commit: " if @reverse_compare - @subject << @commits.first.title - end - else - unless action == :delete - @target_url = namespace_project_tree_url(@project.namespace, - @project, @ref_name) - end - - subject_action = @action_name.dup - subject_action[0] = subject_action[0].capitalize - @subject << "#{subject_action} #{@ref_type} #{@ref_name}" - end - - @disable_footer = true - - reply_to = - if send_from_committer_email && can_send_from_user_email?(@author) - @author.email - else - Gitlab.config.gitlab.email_reply_to - end - - mail(from: sender(author_id, send_from_committer_email), - reply_to: reply_to, - to: recipient, - subject: @subject) + mail(from: sender(@message.author_id, @message.send_from_committer_email?), + reply_to: @message.reply_to, + to: @message.recipient, + subject: @message.subject) end end end diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb index 50a409c375..3bbdd9cee7 100644 --- a/app/mailers/notify.rb +++ b/app/mailers/notify.rb @@ -7,6 +7,7 @@ class Notify < BaseMailer include Emails::Projects include Emails::Profile include Emails::Groups + include Emails::Builds add_template_helper MergeRequestsHelper add_template_helper EmailsHelper @@ -16,7 +17,7 @@ class Notify < BaseMailer subject: subject, body: body.html_safe, content_type: 'text/html' - ) + ) end # Splits "gitlab.corp.company.com" up into "gitlab.corp.company.com", @@ -33,13 +34,13 @@ class Notify < BaseMailer allowed_domains end - private - def can_send_from_user_email?(sender) sender_domain = sender.email.split("@").last self.class.allowed_email_domains.include?(sender_domain) end + private + # Return an email address that displays the name of the sender. # Only the displayed name changes; the actual email address is always the same. def sender(sender_id, send_from_user_email = false) diff --git a/app/models/ability.rb b/app/models/ability.rb index 07f3a56ec7..cd5ae0fb0f 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -346,12 +346,10 @@ class Ability unless group.last_owner?(target_user) can_manage = group_abilities(user, group).include?(:admin_group_member) - if can_manage && user != target_user + if can_manage rules << :update_group_member rules << :destroy_group_member - end - - if user == target_user + elsif user == target_user rules << :destroy_group_member end end @@ -367,12 +365,10 @@ class Ability unless target_user == project.owner can_manage = project_abilities(user, project).include?(:admin_project_member) - if can_manage && user != target_user + if can_manage rules << :update_project_member rules << :destroy_project_member - end - - if user == target_user + elsif user == target_user rules << :destroy_project_member end end diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index b2d5fe1558..1f4e8b3ef2 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -27,9 +27,15 @@ # admin_notification_email :string(255) # shared_runners_enabled :boolean default(TRUE), not null # max_artifacts_size :integer default(100), not null +# runners_registration_token :string(255) # class ApplicationSetting < ActiveRecord::Base + include TokenAuthenticatable + add_authentication_token_field :runners_registration_token + + CACHE_KEY = 'application_setting.last' + serialize :restricted_visibility_levels serialize :import_sources serialize :restricted_signup_domains, Array @@ -41,12 +47,12 @@ class ApplicationSetting < ActiveRecord::Base validates :home_page_url, allow_blank: true, - format: { with: /\A#{URI.regexp(%w(http https))}\z/, message: "should be a valid url" }, + url: true, if: :home_page_url_column_exist validates :after_sign_out_path, allow_blank: true, - format: { with: /\A#{URI.regexp(%w(http https))}\z/, message: "should be a valid url" } + url: true validates :admin_notification_email, allow_blank: true, @@ -72,16 +78,22 @@ class ApplicationSetting < ActiveRecord::Base end end + before_save :ensure_runners_registration_token + after_commit do - Rails.cache.write('application_setting.last', self) + Rails.cache.write(CACHE_KEY, self) end def self.current - Rails.cache.fetch('application_setting.last') do + Rails.cache.fetch(CACHE_KEY) do ApplicationSetting.last end end + def self.expire + Rails.cache.delete(CACHE_KEY) + end + def self.create_from_defaults create( default_projects_limit: Settings.gitlab['default_projects_limit'], @@ -114,13 +126,12 @@ class ApplicationSetting < ActiveRecord::Base def restricted_signup_domains_raw=(values) self.restricted_signup_domains = [] self.restricted_signup_domains = values.split( - /\s*[,;]\s* # comma or semicolon, optionally surrounded by whitespace - | # or - \s # any whitespace character - | # or - [\r\n] # any number of newline characters - /x) + /\s*[,;]\s* # comma or semicolon, optionally surrounded by whitespace + | # or + \s # any whitespace character + | # or + [\r\n] # any number of newline characters + /x) self.restricted_signup_domains.reject! { |d| d.empty? } end - end diff --git a/app/models/broadcast_message.rb b/app/models/broadcast_message.rb index 05f5e97969..ad51470616 100644 --- a/app/models/broadcast_message.rb +++ b/app/models/broadcast_message.rb @@ -16,12 +16,12 @@ class BroadcastMessage < ActiveRecord::Base include Sortable - validates :message, presence: true + validates :message, presence: true validates :starts_at, presence: true - validates :ends_at, presence: true + validates :ends_at, presence: true - validates :color, format: { with: /\A\#[0-9A-Fa-f]{3}{1,2}+\Z/ }, allow_blank: true - validates :font, format: { with: /\A\#[0-9A-Fa-f]{3}{1,2}+\Z/ }, allow_blank: true + validates :color, allow_blank: true, color: true + validates :font, allow_blank: true, color: true def self.current where("ends_at > :now AND starts_at < :now", now: Time.zone.now).last diff --git a/app/models/ci/application_setting.rb b/app/models/ci/application_setting.rb deleted file mode 100644 index 1307fa0b47..0000000000 --- a/app/models/ci/application_setting.rb +++ /dev/null @@ -1,33 +0,0 @@ -# == Schema Information -# -# Table name: ci_application_settings -# -# id :integer not null, primary key -# all_broken_builds :boolean -# add_pusher :boolean -# created_at :datetime -# updated_at :datetime -# - -module Ci - class ApplicationSetting < ActiveRecord::Base - extend Ci::Model - - after_commit do - Rails.cache.write('ci_application_setting.last', self) - end - - def self.current - Rails.cache.fetch('ci_application_setting.last') do - Ci::ApplicationSetting.last - end - end - - def self.create_from_defaults - create( - all_broken_builds: Settings.gitlab_ci['all_broken_builds'], - add_pusher: Settings.gitlab_ci['add_pusher'], - ) - end - end -end diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 52ce1b920f..6d9cdb9529 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -84,6 +84,7 @@ module Ci new_build.options = build.options new_build.commands = build.commands new_build.tag_list = build.tag_list + new_build.gl_project_id = build.gl_project_id new_build.commit_id = build.commit_id new_build.name = build.name new_build.allow_failure = build.allow_failure @@ -96,21 +97,16 @@ module Ci end state_machine :status, initial: :pending do + after_transition pending: :running do |build, transition| + build.execute_hooks + end + after_transition any => [:success, :failed, :canceled] do |build, transition| - return unless build.gl_project - - project = build.project - - if project.web_hooks? - Ci::WebHookService.new.build_end(build) - end + return unless build.project + build.update_coverage build.commit.create_next_builds(build) - project.execute_services(build) - - if project.coverage_enabled? - build.update_coverage - end + build.execute_hooks end end @@ -119,7 +115,7 @@ module Ci end def retryable? - commands.present? + project.builds_enabled? && commands.present? end def retried? @@ -132,7 +128,7 @@ module Ci end def timeout - project.timeout + project.build_timeout end def variables @@ -151,26 +147,21 @@ module Ci project.name end - def project_recipients - recipients = project.email_recipients.split(' ') - - if project.email_add_pusher? && user.present? && user.notification_email.present? - recipients << user.notification_email - end - - recipients.uniq - end - def repo_url - project.repo_url_with_auth + auth = "gitlab-ci-token:#{token}@" + project.http_url_to_repo.sub(/^https?:\/\//) do |prefix| + prefix + auth + end end def allow_git_fetch - project.allow_git_fetch + project.build_allow_git_fetch end def update_coverage - coverage = extract_coverage(trace, project.coverage_regex) + coverage_regex = project.build_coverage_regex + return unless coverage_regex + coverage = extract_coverage(trace, coverage_regex) if coverage.is_a? Numeric update_attributes(coverage: coverage) @@ -203,7 +194,7 @@ module Ci def trace trace = raw_trace if project && trace.present? - trace.gsub(project.token, 'xxxxxx') + trace.gsub(project.runners_token, 'xxxxxx') else trace end @@ -230,29 +221,29 @@ module Ci end def token - project.token + project.runners_token end def valid_token? token - project.valid_token? token + project.valid_runners_token? token end def target_url Gitlab::Application.routes.url_helpers. - namespace_project_build_url(gl_project.namespace, gl_project, self) + namespace_project_build_url(project.namespace, project, self) end def cancel_url if active? Gitlab::Application.routes.url_helpers. - cancel_namespace_project_build_path(gl_project.namespace, gl_project, self) + cancel_namespace_project_build_path(project.namespace, project, self) end end def retry_url if retryable? Gitlab::Application.routes.url_helpers. - retry_namespace_project_build_path(gl_project.namespace, gl_project, self) + retry_namespace_project_build_path(project.namespace, project, self) end end @@ -271,10 +262,18 @@ module Ci def download_url if artifacts_file.exists? Gitlab::Application.routes.url_helpers. - download_namespace_project_build_path(gl_project.namespace, gl_project, self) + download_namespace_project_build_path(project.namespace, project, self) end end + def execute_hooks + build_data = Gitlab::BuildDataBuilder.build(self) + project.execute_hooks(build_data.dup, :build_hooks) + project.execute_services(build_data.dup, :build_hooks) + end + + + private def yaml_variables diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index 971e899de8..d2a2923694 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -20,8 +20,8 @@ module Ci class Commit < ActiveRecord::Base extend Ci::Model - belongs_to :gl_project, class_name: '::Project', foreign_key: :gl_project_id - has_many :statuses, dependent: :destroy, class_name: 'CommitStatus' + belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id + has_many :statuses, class_name: 'CommitStatus' has_many :builds, class_name: 'Ci::Build' has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest' @@ -38,10 +38,6 @@ module Ci sha end - def project - @project ||= gl_project.ensure_gitlab_ci_project - end - def project_id project.id end @@ -57,7 +53,7 @@ module Ci end def valid_commit_sha - if self.sha == Ci::Git::BLANK_SHA + if self.sha == Gitlab::Git::BLANK_SHA self.errors.add(:sha, " cant be 00000000 (branch removal)") end end @@ -79,7 +75,7 @@ module Ci end def commit_data - @commit ||= gl_project.commit(sha) + @commit ||= project.commit(sha) rescue nil end @@ -165,21 +161,31 @@ module Ci status == 'canceled' end + def active? + running? || pending? + end + + def complete? + canceled? || success? || failed? + end + def duration duration_array = latest_statuses.map(&:duration).compact duration_array.reduce(:+).to_i end + def started_at + @started_at ||= statuses.order('started_at ASC').first.try(:started_at) + end + def finished_at @finished_at ||= statuses.order('finished_at DESC').first.try(:finished_at) end def coverage - if project.coverage_enabled? - coverage_array = latest_builds.map(&:coverage).compact - if coverage_array.size >= 1 - '%.2f' % (coverage_array.reduce(:+) / coverage_array.size) - end + coverage_array = latest_builds.map(&:coverage).compact + if coverage_array.size >= 1 + '%.2f' % (coverage_array.reduce(:+) / coverage_array.size) end end @@ -189,7 +195,7 @@ module Ci def config_processor return nil unless ci_yaml_file - @config_processor ||= Ci::GitlabCiYamlProcessor.new(ci_yaml_file, gl_project.path_with_namespace) + @config_processor ||= Ci::GitlabCiYamlProcessor.new(ci_yaml_file, project.path_with_namespace) rescue Ci::GitlabCiYamlProcessor::ValidationError, Psych::SyntaxError => e save_yaml_error(e.message) nil @@ -199,7 +205,7 @@ module Ci end def ci_yaml_file - gl_project.repository.blob_at(sha, '.gitlab-ci.yml').data + @ci_yaml_file ||= project.repository.blob_at(sha, '.gitlab-ci.yml').data rescue nil end diff --git a/app/models/ci/event.rb b/app/models/ci/event.rb deleted file mode 100644 index 8c39be4267..0000000000 --- a/app/models/ci/event.rb +++ /dev/null @@ -1,27 +0,0 @@ -# == Schema Information -# -# Table name: ci_events -# -# id :integer not null, primary key -# project_id :integer -# user_id :integer -# is_admin :integer -# description :text -# created_at :datetime -# updated_at :datetime -# - -module Ci - class Event < ActiveRecord::Base - extend Ci::Model - - belongs_to :project, class_name: 'Ci::Project' - - validates :description, - presence: true, - length: { in: 5..200 } - - scope :admin, ->(){ where(is_admin: true) } - scope :project_wide, ->(){ where(is_admin: false) } - end -end diff --git a/app/models/ci/project.rb b/app/models/ci/project.rb deleted file mode 100644 index 669ee1cc0d..0000000000 --- a/app/models/ci/project.rb +++ /dev/null @@ -1,192 +0,0 @@ -# == Schema Information -# -# Table name: ci_projects -# -# id :integer not null, primary key -# name :string(255) -# timeout :integer default(3600), not null -# created_at :datetime -# updated_at :datetime -# token :string(255) -# default_ref :string(255) -# path :string(255) -# always_build :boolean default(FALSE), not null -# polling_interval :integer -# public :boolean default(FALSE), not null -# ssh_url_to_repo :string(255) -# gitlab_id :integer -# allow_git_fetch :boolean default(TRUE), not null -# email_recipients :string(255) default(""), not null -# email_add_pusher :boolean default(TRUE), not null -# email_only_broken_builds :boolean default(TRUE), not null -# skip_refs :string(255) -# coverage_regex :string(255) -# shared_runners_enabled :boolean default(FALSE) -# generated_yaml_config :text -# - -module Ci - class Project < ActiveRecord::Base - extend Ci::Model - - include Ci::ProjectStatus - - belongs_to :gl_project, class_name: '::Project', foreign_key: :gitlab_id - - has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject' - has_many :runners, through: :runner_projects, class_name: 'Ci::Runner' - has_many :web_hooks, dependent: :destroy, class_name: 'Ci::WebHook' - has_many :events, dependent: :destroy, class_name: 'Ci::Event' - has_many :variables, dependent: :destroy, class_name: 'Ci::Variable' - has_many :triggers, dependent: :destroy, class_name: 'Ci::Trigger' - - # Project services - has_many :services, dependent: :destroy, class_name: 'Ci::Service' - has_one :hip_chat_service, dependent: :destroy, class_name: 'Ci::HipChatService' - has_one :slack_service, dependent: :destroy, class_name: 'Ci::SlackService' - has_one :mail_service, dependent: :destroy, class_name: 'Ci::MailService' - - accepts_nested_attributes_for :variables, allow_destroy: true - - delegate :name_with_namespace, :path_with_namespace, :web_url, :http_url_to_repo, :ssh_url_to_repo, to: :gl_project - - # - # Validations - # - validates_presence_of :timeout, :token, :default_ref, :gitlab_id - - validates_uniqueness_of :gitlab_id - - validates :polling_interval, - presence: true, - if: ->(project) { project.always_build.present? } - - before_validation :set_default_values - - class << self - include Ci::CurrentSettings - - def unassigned(runner) - joins("LEFT JOIN #{Ci::RunnerProject.table_name} ON #{Ci::RunnerProject.table_name}.project_id = #{Ci::Project.table_name}.id " \ - "AND #{Ci::RunnerProject.table_name}.runner_id = #{runner.id}"). - where("#{Ci::RunnerProject.table_name}.project_id" => nil) - end - - def ordered_by_last_commit_date - last_commit_subquery = "(SELECT gl_project_id, MAX(committed_at) committed_at FROM #{Ci::Commit.table_name} GROUP BY gl_project_id)" - joins("LEFT JOIN #{last_commit_subquery} AS last_commit ON #{Ci::Project.table_name}.gitlab_id = last_commit.gl_project_id"). - joins(:gl_project). - order("CASE WHEN last_commit.committed_at IS NULL THEN 1 ELSE 0 END, last_commit.committed_at DESC") - end - end - - def name - name_with_namespace - end - - def path - path_with_namespace - end - - def gitlab_url - web_url - end - - def any_runners?(&block) - if runners.active.any?(&block) - return true - end - - shared_runners_enabled && Ci::Runner.shared.active.any?(&block) - end - - def set_default_values - self.token = SecureRandom.hex(15) if self.token.blank? - self.default_ref ||= 'master' - end - - def tracked_refs - @tracked_refs ||= default_ref.split(",").map { |ref| ref.strip } - end - - def valid_token? token - self.token && self.token == token - end - - def no_running_builds? - # Get running builds not later than 3 days ago to ignore hangs - builds.running.where("updated_at > ?", 3.days.ago).empty? - end - - def email_notification? - email_add_pusher || email_recipients.present? - end - - def web_hooks? - web_hooks.any? - end - - def services? - services.any? - end - - def timeout_in_minutes - timeout / 60 - end - - def timeout_in_minutes=(value) - self.timeout = value.to_i * 60 - end - - def coverage_enabled? - coverage_regex.present? - end - - # Build a clone-able repo url - # using http and basic auth - def repo_url_with_auth - auth = "gitlab-ci-token:#{token}@" - http_url_to_repo.sub(/^https?:\/\//) do |prefix| - prefix + auth - end - end - - def available_services_names - %w(slack mail hip_chat) - end - - def build_missing_services - available_services_names.each do |service_name| - service = services.find { |service| service.to_param == service_name } - - # If service is available but missing in db - # we should create an instance. Ex `create_gitlab_ci_service` - self.send :"create_#{service_name}_service" if service.nil? - end - end - - def execute_services(data) - services.each do |service| - - # Call service hook only if it is active - begin - service.execute(data) if service.active && service.can_execute?(data) - rescue => e - logger.error(e) - end - end - end - - def setup_finished? - commits.any? - end - - def commits - gl_project.ci_commits.ordered - end - - def builds - gl_project.ci_builds - end - end -end diff --git a/app/models/ci/project_status.rb b/app/models/ci/project_status.rb deleted file mode 100644 index 2d35aeac22..0000000000 --- a/app/models/ci/project_status.rb +++ /dev/null @@ -1,31 +0,0 @@ -module Ci - module ProjectStatus - def status - last_commit.status if last_commit - end - - def broken? - last_commit.failed? if last_commit - end - - def success? - last_commit.success? if last_commit - end - - def broken_or_success? - broken? || success? - end - - def last_commit - @last_commit ||= commits.last if commits.any? - end - - def last_commit_date - last_commit.try(:created_at) - end - - def human_status - status - end - end -end diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb index 8971048581..38b20cd7fa 100644 --- a/app/models/ci/runner.rb +++ b/app/models/ci/runner.rb @@ -25,7 +25,7 @@ module Ci has_many :builds, class_name: 'Ci::Build' has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject' - has_many :projects, through: :runner_projects, class_name: 'Ci::Project' + has_many :projects, through: :runner_projects, class_name: '::Project', foreign_key: :gl_project_id has_one :last_build, ->() { order('id DESC') }, class_name: 'Ci::Build' @@ -45,10 +45,6 @@ module Ci query: "%#{query.try(:downcase)}%") end - def gl_projects_ids - projects.select(:gitlab_id) - end - def set_default_values self.token = SecureRandom.hex(15) if self.token.blank? end diff --git a/app/models/ci/runner_project.rb b/app/models/ci/runner_project.rb index 3f4fc43873..93d9be144e 100644 --- a/app/models/ci/runner_project.rb +++ b/app/models/ci/runner_project.rb @@ -14,8 +14,8 @@ module Ci extend Ci::Model belongs_to :runner, class_name: 'Ci::Runner' - belongs_to :project, class_name: 'Ci::Project' + belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id - validates_uniqueness_of :runner_id, scope: :project_id + validates_uniqueness_of :runner_id, scope: :gl_project_id end end diff --git a/app/models/ci/service.rb b/app/models/ci/service.rb deleted file mode 100644 index 8063c51e82..0000000000 --- a/app/models/ci/service.rb +++ /dev/null @@ -1,105 +0,0 @@ -# == Schema Information -# -# Table name: ci_services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# - -# To add new service you should build a class inherited from Service -# and implement a set of methods -module Ci - class Service < ActiveRecord::Base - extend Ci::Model - - serialize :properties, JSON - - default_value_for :active, false - - after_initialize :initialize_properties - - belongs_to :project, class_name: 'Ci::Project' - - validates :project_id, presence: true - - def activated? - active - end - - def category - :common - end - - def initialize_properties - self.properties = {} if properties.nil? - end - - def title - # implement inside child - end - - def description - # implement inside child - end - - def help - # implement inside child - end - - def to_param - # implement inside child - end - - def fields - # implement inside child - [] - end - - def can_test? - project.builds.any? - end - - def can_execute?(build) - true - end - - def execute(build) - # implement inside child - end - - # Provide convenient accessor methods - # for each serialized property. - def self.prop_accessor(*args) - args.each do |arg| - class_eval %{ - def #{arg} - (properties || {})['#{arg}'] - end - - def #{arg}=(value) - self.properties ||= {} - self.properties['#{arg}'] = value - end - } - end - end - - def self.boolean_accessor(*args) - self.prop_accessor(*args) - - args.each do |arg| - class_eval %{ - def #{arg}? - ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include?(#{arg}) - end - } - end - end - end -end diff --git a/app/models/ci/trigger.rb b/app/models/ci/trigger.rb index b73c35d5ae..23516709a4 100644 --- a/app/models/ci/trigger.rb +++ b/app/models/ci/trigger.rb @@ -16,7 +16,7 @@ module Ci acts_as_paranoid - belongs_to :project, class_name: 'Ci::Project' + belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest' validates_presence_of :token diff --git a/app/models/ci/variable.rb b/app/models/ci/variable.rb index b3d2b809e0..56759d3e50 100644 --- a/app/models/ci/variable.rb +++ b/app/models/ci/variable.rb @@ -15,10 +15,10 @@ module Ci class Variable < ActiveRecord::Base extend Ci::Model - belongs_to :project, class_name: 'Ci::Project' + belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id validates_presence_of :key - validates_uniqueness_of :key, scope: :project_id + validates_uniqueness_of :key, scope: :gl_project_id attr_encrypted :value, mode: :per_attribute_iv_and_salt, key: Gitlab::Application.secrets.db_key_base end diff --git a/app/models/ci/web_hook.rb b/app/models/ci/web_hook.rb deleted file mode 100644 index 7ca16a1bde..0000000000 --- a/app/models/ci/web_hook.rb +++ /dev/null @@ -1,44 +0,0 @@ -# == Schema Information -# -# Table name: ci_web_hooks -# -# id :integer not null, primary key -# url :string(255) not null -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# - -module Ci - class WebHook < ActiveRecord::Base - extend Ci::Model - - include HTTParty - - belongs_to :project, class_name: 'Ci::Project' - - # HTTParty timeout - default_timeout 10 - - validates :url, presence: true, - format: { with: URI::regexp(%w(http https)), message: "should be a valid url" } - - def execute(data) - parsed_url = URI.parse(url) - if parsed_url.userinfo.blank? - Ci::WebHook.post(url, body: data.to_json, headers: { "Content-Type" => "application/json" }, verify: false) - else - post_url = url.gsub("#{parsed_url.userinfo}@", "") - auth = { - username: URI.decode(parsed_url.user), - password: URI.decode(parsed_url.password), - } - Ci::WebHook.post(post_url, - body: data.to_json, - headers: { "Content-Type" => "application/json" }, - verify: false, - basic_auth: auth) - end - end - end -end diff --git a/app/models/commit.rb b/app/models/commit.rb index 492f6be1ce..0ba7b584d9 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -7,7 +7,7 @@ class Commit include Referable include StaticModel - attr_mentionable :safe_message + attr_mentionable :safe_message, pipeline: :single_line participant :author, :committer, :notes attr_accessor :project @@ -78,11 +78,23 @@ class Commit }x end + def self.link_reference_pattern + super("commit", /(?\h{6,40})/) + end + def to_reference(from_project = nil) if cross_project_reference?(from_project) - "#{project.to_reference}@#{id}" + project.to_reference + self.class.reference_prefix + self.id else - id + self.id + end + end + + def reference_link_text(from_project = nil) + if cross_project_reference?(from_project) + project.to_reference + self.class.reference_prefix + self.short_id + else + self.short_id end end @@ -135,10 +147,10 @@ class Commit description.present? end - def hook_attrs + def hook_attrs(with_changed_files: false) path_with_namespace = project.path_with_namespace - { + data = { id: id, message: safe_message, timestamp: committed_date.xmlschema, @@ -148,6 +160,12 @@ class Commit email: author_email } } + + if with_changed_files + data.merge!(repo_changes) + end + + data end # Discover issues should be closed when this commit is pushed to a project's @@ -157,11 +175,11 @@ class Commit end def author - @author ||= User.find_by_any_email(author_email) + @author ||= User.find_by_any_email(author_email.downcase) end def committer - @committer ||= User.find_by_any_email(committer_email) + @committer ||= User.find_by_any_email(committer_email.downcase) end def parents @@ -196,4 +214,22 @@ class Commit def status ci_commit.try(:status) || :not_found end + + private + + def repo_changes + changes = { added: [], modified: [], removed: [] } + + diffs.each do |diff| + if diff.deleted_file + changes[:removed] << diff.old_path + elsif diff.renamed_file || diff.new_file + changes[:added] << diff.new_path + else + changes[:modified] << diff.new_path + end + end + + changes + end end diff --git a/app/models/commit_range.rb b/app/models/commit_range.rb index 86fc9eb01a..14e7971fa0 100644 --- a/app/models/commit_range.rb +++ b/app/models/commit_range.rb @@ -2,36 +2,38 @@ # # Examples: # -# range = CommitRange.new('f3f85602...e86e1013') +# range = CommitRange.new('f3f85602...e86e1013', project) # range.exclude_start? # => false # range.reference_title # => "Commits f3f85602 through e86e1013" # range.to_s # => "f3f85602...e86e1013" # -# range = CommitRange.new('f3f856029bc5f966c5a7ee24cf7efefdd20e6019..e86e1013709735be5bb767e2b228930c543f25ae') +# range = CommitRange.new('f3f856029bc5f966c5a7ee24cf7efefdd20e6019..e86e1013709735be5bb767e2b228930c543f25ae', project) # range.exclude_start? # => true # range.reference_title # => "Commits f3f85602^ through e86e1013" # range.to_param # => {from: "f3f856029bc5f966c5a7ee24cf7efefdd20e6019^", to: "e86e1013709735be5bb767e2b228930c543f25ae"} # range.to_s # => "f3f85602..e86e1013" # -# # Assuming `project` is a Project with a repository containing both commits: -# range.project = project +# # Assuming the specified project has a repository containing both commits: # range.valid_commits? # => true # class CommitRange include ActiveModel::Conversion include Referable - attr_reader :sha_from, :notation, :sha_to + attr_reader :commit_from, :notation, :commit_to + attr_reader :ref_from, :ref_to # Optional Project model attr_accessor :project - # See `exclude_start?` - attr_reader :exclude_start - - # The beginning and ending SHAs can be between 6 and 40 hex characters, and + # The beginning and ending refs can be named or SHAs, and # the range notation can be double- or triple-dot. - PATTERN = /\h{6,40}\.{2,3}\h{6,40}/ + REF_PATTERN = /[0-9a-zA-Z][0-9a-zA-Z_.-]*[0-9a-zA-Z\^]/ + PATTERN = /#{REF_PATTERN}\.{2,3}#{REF_PATTERN}/ + + # In text references, the beginning and ending refs can only be SHAs + # between 6 and 40 hex characters. + STRICT_PATTERN = /\h{6,40}\.{2,3}\h{6,40}/ def self.reference_prefix '@' @@ -43,27 +45,40 @@ class CommitRange def self.reference_pattern %r{ (?:#{Project.reference_pattern}#{reference_prefix})? - (?#{PATTERN}) + (?#{STRICT_PATTERN}) }x end + def self.link_reference_pattern + super("compare", /(?#{PATTERN})/) + end + # Initialize a CommitRange # # range_string - The String commit range. # project - An optional Project model. # # Raises ArgumentError if `range_string` does not match `PATTERN`. - def initialize(range_string, project = nil) + def initialize(range_string, project) + @project = project + range_string.strip! - unless range_string.match(/\A#{PATTERN}\z/) + unless range_string =~ /\A#{PATTERN}\z/ raise ArgumentError, "invalid CommitRange string format: #{range_string}" end - @exclude_start = !range_string.include?('...') - @sha_from, @notation, @sha_to = range_string.split(/(\.{2,3})/, 2) + @ref_from, @notation, @ref_to = range_string.split(/(\.{2,3})/, 2) - @project = project + if project.valid_repo? + @commit_from = project.commit(@ref_from) + @commit_to = project.commit(@ref_to) + end + + if valid_commits? + @ref_from = Commit.truncate_sha(sha_from) if sha_from.start_with?(@ref_from) + @ref_to = Commit.truncate_sha(sha_to) if sha_to.start_with?(@ref_to) + end end def inspect @@ -71,15 +86,24 @@ class CommitRange end def to_s - "#{sha_from[0..7]}#{notation}#{sha_to[0..7]}" + sha_from + notation + sha_to end + alias_method :id, :to_s + def to_reference(from_project = nil) - # Not using to_s because we want the full SHAs - reference = sha_from + notation + sha_to + if cross_project_reference?(from_project) + project.to_reference + self.class.reference_prefix + self.id + else + self.id + end + end + + def reference_link_text(from_project = nil) + reference = ref_from + notation + ref_to if cross_project_reference?(from_project) - reference = project.to_reference + '@' + reference + reference = project.to_reference + self.class.reference_prefix + reference end reference @@ -87,46 +111,58 @@ class CommitRange # Returns a String for use in a link's title attribute def reference_title - "Commits #{suffixed_sha_from} through #{sha_to}" + "Commits #{sha_start} through #{sha_to}" end # Return a Hash of parameters for passing to a URL helper # # See `namespace_project_compare_url` def to_param - { from: suffixed_sha_from, to: sha_to } + { from: sha_start, to: sha_to } end def exclude_start? - exclude_start + @notation == '..' end # Check if both the starting and ending commit IDs exist in a project's # repository - # - # project - An optional Project to check (default: `project`) - def valid_commits?(project = project) - return nil unless project.present? - return false unless project.valid_repo? - - commit_from.present? && commit_to.present? + def valid_commits? + commit_start.present? && commit_end.present? end def persisted? true end - def commit_from - @commit_from ||= project.repository.commit(suffixed_sha_from) + def sha_from + return nil unless @commit_from + + @commit_from.id end - def commit_to - @commit_to ||= project.repository.commit(sha_to) + def sha_to + return nil unless @commit_to + + @commit_to.id end - private + def sha_start + return nil unless sha_from - def suffixed_sha_from - sha_from + (exclude_start? ? '^' : '') + exclude_start? ? sha_from + '^' : sha_from end + + def commit_start + return nil unless sha_start + + if exclude_start? + @commit_start ||= project.commit(sha_start) + else + commit_from + end + end + + alias_method :sha_end, :sha_to + alias_method :commit_end, :commit_to end diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index e70f4d3718..21c5c87bc3 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -1,39 +1,36 @@ # == Schema Information # -# Table name: ci_builds -# -# id :integer not null, primary key -# project_id :integer -# status :string(255) -# finished_at :datetime -# trace :text -# created_at :datetime -# updated_at :datetime -# started_at :datetime -# runner_id :integer -# coverage :float -# commit_id :integer -# commands :text -# job_id :integer -# name :string(255) -# deploy :boolean default(FALSE) -# options :text -# allow_failure :boolean default(FALSE), not null -# stage :string(255) -# trigger_request_id :integer -# stage_idx :integer -# tag :boolean -# ref :string(255) -# user_id :integer -# type :string(255) -# target_url :string(255) -# description :string(255) -# artifacts_file :text +# project_id integer +# status string +# finished_at datetime +# trace text +# created_at datetime +# updated_at datetime +# started_at datetime +# runner_id integer +# coverage float +# commit_id integer +# commands text +# job_id integer +# name string +# deploy boolean default: false +# options text +# allow_failure boolean default: false, null: false +# stage string +# trigger_request_id integer +# stage_idx integer +# tag boolean +# ref string +# user_id integer +# type string +# target_url string +# description string # class CommitStatus < ActiveRecord::Base self.table_name = 'ci_builds' + belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id belongs_to :commit, class_name: 'Ci::Commit' belongs_to :user @@ -79,6 +76,10 @@ class CommitStatus < ActiveRecord::Base build.update_attributes finished_at: Time.now end + after_transition [:pending, :running] => :success do |build, transition| + MergeRequests::MergeWhenBuildSucceedsService.new(build.commit.project, nil).trigger(build) + end + state :pending, value: 'pending' state :running, value: 'running' state :failed, value: 'failed' @@ -86,8 +87,7 @@ class CommitStatus < ActiveRecord::Base state :canceled, value: 'canceled' end - delegate :sha, :short_sha, :gl_project, - to: :commit, prefix: false + delegate :sha, :short_sha, to: :commit, prefix: false # TODO: this should be removed with all references def before_sha diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index b54145ba1b..f56fd3e02d 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -8,6 +8,7 @@ module Issuable extend ActiveSupport::Concern include Participable include Mentionable + include StripAttribute included do belongs_to :author, class_name: "User" @@ -35,6 +36,9 @@ module Issuable scope :order_milestone_due_desc, -> { joins(:milestone).reorder('milestones.due_date DESC, milestones.id DESC') } scope :order_milestone_due_asc, -> { joins(:milestone).reorder('milestones.due_date ASC, milestones.id ASC') } + scope :join_project, -> { joins(:project) } + scope :references_project, -> { references(:project) } + delegate :name, :email, to: :author, @@ -46,8 +50,10 @@ module Issuable allow_nil: true, prefix: true - attr_mentionable :title, :description + attr_mentionable :title, pipeline: :single_line + attr_mentionable :description, cache: true participant :author, :assignee, :notes_with_associations + strip_attributes :title end module ClassMethods @@ -158,4 +164,9 @@ module Issuable def notes_with_associations notes.includes(:author, :project) end + + def updated_tasks + Taskable.get_updated_tasks(old_content: previous_changes['description'].first, + new_content: description) + end end diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb index 193c91f174..1fdcda9752 100644 --- a/app/models/concerns/mentionable.rb +++ b/app/models/concerns/mentionable.rb @@ -10,8 +10,9 @@ module Mentionable module ClassMethods # Indicate which attributes of the Mentionable to search for GFM references. - def attr_mentionable(*attrs) - mentionable_attrs.concat(attrs.map(&:to_s)) + def attr_mentionable(attr, options = {}) + attr = attr.to_s + mentionable_attrs << [attr, options] end # Accessor for attributes marked mentionable. @@ -22,7 +23,7 @@ module Mentionable included do if self < Participable - participant ->(current_user) { mentioned_users(current_user, load_lazy_references: false) } + participant ->(current_user) { mentioned_users(current_user) } end end @@ -37,38 +38,46 @@ module Mentionable "#{friendly_name} #{to_reference(from_project)}" end - # Construct a String that contains possible GFM references. - def mentionable_text - self.class.mentionable_attrs.map { |attr| send(attr) }.compact.join("\n\n") - end - # The GFM reference to this Mentionable, which shouldn't be included in its #references. def local_reference self end - def all_references(current_user = self.author, text = self.mentionable_text, load_lazy_references: true) - ext = Gitlab::ReferenceExtractor.new(self.project, current_user, load_lazy_references: load_lazy_references) - ext.analyze(text) + def all_references(current_user = self.author, text = nil) + ext = Gitlab::ReferenceExtractor.new(self.project, current_user) + + if text + ext.analyze(text) + else + self.class.mentionable_attrs.each do |attr, options| + text = send(attr) + options[:cache_key] = [self, attr] if options.delete(:cache) && self.persisted? + ext.analyze(text, options) + end + end + ext end - def mentioned_users(current_user = nil, load_lazy_references: true) - all_references(current_user, load_lazy_references: load_lazy_references).users + def mentioned_users(current_user = nil) + all_references(current_user).users end # Extract GFM references to other Mentionables from this Mentionable. Always excludes its #local_reference. - def referenced_mentionables(current_user = self.author, text = self.mentionable_text, load_lazy_references: true) - return [] if text.blank? + def referenced_mentionables(current_user = self.author, text = nil) + refs = all_references(current_user, text) + refs = (refs.issues + refs.merge_requests + refs.commits) - refs = all_references(current_user, text, load_lazy_references: load_lazy_references) - (refs.issues + refs.merge_requests + refs.commits) - [local_reference] + # We're using this method instead of Array diffing because that requires + # both of the object's `hash` values to be the same, which may not be the + # case for otherwise identical Commit objects. + refs.reject { |ref| ref == local_reference } end - # Create a cross-reference Note for each GFM reference to another Mentionable found in +mentionable_text+. - def create_cross_references!(author = self.author, without = [], text = self.mentionable_text) + # Create a cross-reference Note for each GFM reference to another Mentionable found in the +mentionable_attrs+. + def create_cross_references!(author = self.author, without = [], text = nil) refs = referenced_mentionables(author, text) - + # We're using this method instead of Array diffing because that requires # both of the object's `hash` values to be the same, which may not be the # case for otherwise identical Commit objects. @@ -106,12 +115,12 @@ module Mentionable def detect_mentionable_changes source = (changes.present? ? changes : previous_changes).dup - mentionable = self.class.mentionable_attrs + mentionable = self.class.mentionable_attrs.map { |attr, options| attr } # Only include changed fields that are mentionable source.select { |key, val| mentionable.include?(key) } end - + # Determine whether or not a cross-reference Note has already been created between this Mentionable and # the specified target. def cross_reference_exists?(target) diff --git a/app/models/concerns/participable.rb b/app/models/concerns/participable.rb index 85367f89f4..fc6f83b918 100644 --- a/app/models/concerns/participable.rb +++ b/app/models/concerns/participable.rb @@ -37,21 +37,22 @@ module Participable # Be aware that this method makes a lot of sql queries. # Save result into variable if you are going to reuse it inside same request - def participants(current_user = self.author, load_lazy_references: true) - participants = self.class.participant_attrs.flat_map do |attr| - value = - if attr.respond_to?(:call) - instance_exec(current_user, &attr) - else - send(attr) - end + def participants(current_user = self.author) + participants = + Gitlab::ReferenceExtractor.lazily do + self.class.participant_attrs.flat_map do |attr| + value = + if attr.respond_to?(:call) + instance_exec(current_user, &attr) + else + send(attr) + end - participants_for(value, current_user) - end.compact.uniq - - if load_lazy_references - participants = Gitlab::Markdown::ReferenceFilter::LazyReference.load(participants).uniq + participants_for(value, current_user) + end.compact.uniq + end + unless Gitlab::ReferenceExtractor.lazy? participants.select! do |user| user.can?(:read_project, project) end @@ -64,12 +65,12 @@ module Participable def participants_for(value, current_user = nil) case value - when User, Gitlab::Markdown::ReferenceFilter::LazyReference + when User, Banzai::LazyReference [value] when Enumerable, ActiveRecord::Relation value.flat_map { |v| participants_for(v, current_user) } when Participable - value.participants(current_user, load_lazy_references: false) + value.participants(current_user) end end end diff --git a/app/models/concerns/referable.rb b/app/models/concerns/referable.rb index cced66cc1e..ce064f675a 100644 --- a/app/models/concerns/referable.rb +++ b/app/models/concerns/referable.rb @@ -21,6 +21,10 @@ module Referable '' end + def reference_link_text(from_project = nil) + to_reference(from_project) + end + module ClassMethods # The character that prefixes the actual reference identifier # @@ -44,6 +48,25 @@ module Referable def reference_pattern raise NotImplementedError, "#{self} does not implement #{__method__}" end + + def link_reference_pattern(route, pattern) + %r{ + (? + #{Regexp.escape(Gitlab.config.gitlab.url)} + \/#{Project.reference_pattern} + \/#{Regexp.escape(route)} + \/#{pattern} + (? + (\/[a-z0-9_=-]+)* + )? + (? + \?[a-z0-9_=-]+ + (&[a-z0-9_=-]+)* + )? + (?\#[a-z0-9_-]+)? + ) + }x + end end private diff --git a/app/models/concerns/strip_attribute.rb b/app/models/concerns/strip_attribute.rb new file mode 100644 index 0000000000..8806ebe897 --- /dev/null +++ b/app/models/concerns/strip_attribute.rb @@ -0,0 +1,34 @@ +# == Strip Attribute module +# +# Contains functionality to clean attributes before validation +# +# Usage: +# +# class Milestone < ActiveRecord::Base +# strip_attributes :title +# end +# +# +module StripAttribute + extend ActiveSupport::Concern + + module ClassMethods + def strip_attributes(*attrs) + strip_attrs.concat(attrs) + end + + def strip_attrs + @strip_attrs ||= [] + end + end + + included do + before_validation :strip_attributes + end + + def strip_attributes + self.class.strip_attrs.each do |attr| + self[attr].strip! if self[attr] && self[attr].respond_to?(:strip!) + end + end +end diff --git a/app/models/concerns/taskable.rb b/app/models/concerns/taskable.rb index 660e58b876..df2a9e3e84 100644 --- a/app/models/concerns/taskable.rb +++ b/app/models/concerns/taskable.rb @@ -7,14 +7,39 @@ require 'task_list/filter' # # Used by MergeRequest and Issue module Taskable + COMPLETED = 'completed'.freeze + INCOMPLETE = 'incomplete'.freeze + ITEM_PATTERN = / + ^ + (?:\s*[-+*]|(?:\d+\.))? # optional list prefix + \s* # optional whitespace prefix + (\[\s\]|\[[xX]\]) # checkbox + (\s.+) # followed by whitespace and some text. + /x + + def self.get_tasks(content) + content.to_s.scan(ITEM_PATTERN).map do |checkbox, label| + # ITEM_PATTERN strips out the hyphen, but Item requires it. Rabble rabble. + TaskList::Item.new("- #{checkbox}", label.strip) + end + end + + def self.get_updated_tasks(old_content:, new_content:) + old_tasks, new_tasks = get_tasks(old_content), get_tasks(new_content) + + new_tasks.select.with_index do |new_task, i| + old_task = old_tasks[i] + next unless old_task + + new_task.source == old_task.source && new_task.complete? != old_task.complete? + end + end + # Called by `TaskList::Summary` def task_list_items return [] if description.blank? - @task_list_items ||= description.scan(TaskList::Filter::ItemPattern).collect do |item| - # ItemPattern strips out the hyphen, but Item requires it. Rabble rabble. - TaskList::Item.new("- #{item}") - end + @task_list_items ||= Taskable.get_tasks(description) end def tasks diff --git a/app/models/concerns/token_authenticatable.rb b/app/models/concerns/token_authenticatable.rb index 9b88ec1cc3..488ff8c31b 100644 --- a/app/models/concerns/token_authenticatable.rb +++ b/app/models/concerns/token_authenticatable.rb @@ -1,31 +1,43 @@ module TokenAuthenticatable extend ActiveSupport::Concern - module ClassMethods - def find_by_authentication_token(authentication_token = nil) - if authentication_token - where(authentication_token: authentication_token).first + class_methods do + def authentication_token_fields + @token_fields || [] + end + + private + + def add_authentication_token_field(token_field) + @token_fields = [] unless @token_fields + @token_fields << token_field + + define_singleton_method("find_by_#{token_field}") do |token| + find_by(token_field => token) if token + end + + define_method("ensure_#{token_field}") do + current_token = read_attribute(token_field) + if current_token.blank? + write_attribute(token_field, generate_token_for(token_field)) + else + current_token + end + end + + define_method("reset_#{token_field}!") do + write_attribute(token_field, generate_token_for(token_field)) + save! end end end - def ensure_authentication_token - if authentication_token.blank? - self.authentication_token = generate_authentication_token - end - end - - def reset_authentication_token! - self.authentication_token = generate_authentication_token - save - end - private - def generate_authentication_token + def generate_token_for(token_field) loop do token = Devise.friendly_token - break token unless self.class.unscoped.where(authentication_token: token).first + break token unless self.class.unscoped.find_by(token_field => token) end end end diff --git a/app/models/event.rb b/app/models/event.rb index 9afd223bce..01d008035a 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -201,7 +201,7 @@ class Event < ActiveRecord::Base elsif commented? "commented on" elsif created_project? - if project.import? + if project.external_import? "imported" else "created" diff --git a/app/models/global_milestone.rb b/app/models/global_milestone.rb index 1321ccd963..8bfc79d88f 100644 --- a/app/models/global_milestone.rb +++ b/app/models/global_milestone.rb @@ -16,7 +16,15 @@ class GlobalMilestone end def safe_title - @title.parameterize + @title.to_slug.to_s + end + + def expired? + if due_date + due_date.past? + else + false + end end def projects @@ -98,4 +106,25 @@ class GlobalMilestone def complete? total_items_count == closed_items_count end + + def due_date + return @due_date if defined?(@due_date) + + @due_date = + if @milestones.all? { |x| x.due_date == @milestones.first.due_date } + @milestones.first.due_date + else + nil + end + end + + def expires_at + if due_date + if due_date.past? + "expired at #{due_date.stamp("Aug 21, 2011")}" + else + "expires at #{due_date.stamp("Aug 21, 2011")}" + end + end + end end diff --git a/app/models/hooks/project_hook.rb b/app/models/hooks/project_hook.rb index 337b309712..2263805777 100644 --- a/app/models/hooks/project_hook.rb +++ b/app/models/hooks/project_hook.rb @@ -25,4 +25,5 @@ class ProjectHook < WebHook scope :issue_hooks, -> { where(issues_events: true) } scope :note_hooks, -> { where(note_events: true) } scope :merge_request_hooks, -> { where(merge_requests_events: true) } + scope :build_hooks, -> { where(build_events: true) } end diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb index d6c6f415c4..40eb0e20b4 100644 --- a/app/models/hooks/web_hook.rb +++ b/app/models/hooks/web_hook.rb @@ -26,42 +26,44 @@ class WebHook < ActiveRecord::Base default_value_for :note_events, false default_value_for :merge_requests_events, false default_value_for :tag_push_events, false + default_value_for :build_events, false default_value_for :enable_ssl_verification, true # HTTParty timeout default_timeout Gitlab.config.gitlab.webhook_timeout - validates :url, presence: true, - format: { with: /\A#{URI.regexp(%w(http https))}\z/, message: "should be a valid url" } + validates :url, presence: true, url: true def execute(data, hook_name) parsed_url = URI.parse(url) if parsed_url.userinfo.blank? - WebHook.post(url, - body: data.to_json, - headers: { - "Content-Type" => "application/json", - "X-Gitlab-Event" => hook_name.singularize.titleize - }, - verify: enable_ssl_verification) + response = WebHook.post(url, + body: data.to_json, + headers: { + "Content-Type" => "application/json", + "X-Gitlab-Event" => hook_name.singularize.titleize + }, + verify: enable_ssl_verification) else post_url = url.gsub("#{parsed_url.userinfo}@", "") auth = { username: URI.decode(parsed_url.user), password: URI.decode(parsed_url.password), } - WebHook.post(post_url, - body: data.to_json, - headers: { - "Content-Type" => "application/json", - "X-Gitlab-Event" => hook_name.singularize.titleize - }, - verify: enable_ssl_verification, - basic_auth: auth) + response = WebHook.post(post_url, + body: data.to_json, + headers: { + "Content-Type" => "application/json", + "X-Gitlab-Event" => hook_name.singularize.titleize + }, + verify: enable_ssl_verification, + basic_auth: auth) end - rescue SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED, Net::OpenTimeout => e + + [response.code == 200, ActionView::Base.full_sanitizer.sanitize(response.to_s)] + rescue SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::ECONNREFUSED, Net::OpenTimeout => e logger.error("WebHook Error => #{e}") - false + [false, e.to_s] end def async_execute(data, hook_name) diff --git a/app/models/issue.rb b/app/models/issue.rb index 7218310803..80ecd15077 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -69,6 +69,10 @@ class Issue < ActiveRecord::Base }x end + def self.link_reference_pattern + super("issues", /(?\d+)/) + end + def to_reference(from_project = nil) reference = "#{self.class.reference_prefix}#{iid}" @@ -79,6 +83,14 @@ class Issue < ActiveRecord::Base reference end + def referenced_merge_requests + Gitlab::ReferenceExtractor.lazily do + [self, *notes].flat_map do |note| + note.all_references.merge_requests + end + end.sort_by(&:iid) + end + # Reset issue events cache # # Since we do cache @event we need to reset cache in special cases: diff --git a/app/models/jira_issue.rb b/app/models/jira_issue.rb new file mode 100644 index 0000000000..5b21aac5e4 --- /dev/null +++ b/app/models/jira_issue.rb @@ -0,0 +1,2 @@ +class JiraIssue < ExternalIssue +end diff --git a/app/models/label.rb b/app/models/label.rb index b306aecbac..220da10a6a 100644 --- a/app/models/label.rb +++ b/app/models/label.rb @@ -17,7 +17,7 @@ class Label < ActiveRecord::Base # Requests that have no label assigned. LabelStruct = Struct.new(:title, :name) None = LabelStruct.new('No Label', 'No Label') - Any = LabelStruct.new('Any', '') + Any = LabelStruct.new('Any Label', '') DEFAULT_COLOR = '#428BCA' @@ -27,9 +27,7 @@ class Label < ActiveRecord::Base has_many :label_links, dependent: :destroy has_many :issues, through: :label_links, source: :target, source_type: 'Issue' - validates :color, - format: { with: /\A#[0-9A-Fa-f]{6}\Z/ }, - allow_blank: false + validates :color, color: true, allow_blank: false validates :project, presence: true, unless: Proc.new { |service| service.template? } # Don't allow '?', '&', and ',' for label titles diff --git a/app/models/lfs_object.rb b/app/models/lfs_object.rb index 3c1426f59d..86b1b7e2f9 100644 --- a/app/models/lfs_object.rb +++ b/app/models/lfs_object.rb @@ -1,3 +1,15 @@ +# == Schema Information +# +# Table name: lfs_objects +# +# id :integer not null, primary key +# oid :string(255) not null +# size :integer not null +# created_at :datetime +# updated_at :datetime +# file :string(255) +# + class LfsObject < ActiveRecord::Base has_many :lfs_objects_projects, dependent: :destroy has_many :projects, through: :lfs_objects_projects @@ -5,4 +17,16 @@ class LfsObject < ActiveRecord::Base validates :oid, presence: true, uniqueness: true mount_uploader :file, LfsObjectUploader + + def storage_project(project) + if project && project.forked? + storage_project(project.forked_from_project) + else + project + end + end + + def project_allowed_access?(project) + projects.exists?(storage_project(project).id) + end end diff --git a/app/models/lfs_objects_project.rb b/app/models/lfs_objects_project.rb index 0fd5f089db..890736bfc8 100644 --- a/app/models/lfs_objects_project.rb +++ b/app/models/lfs_objects_project.rb @@ -1,3 +1,14 @@ +# == Schema Information +# +# Table name: lfs_objects_projects +# +# id :integer not null, primary key +# lfs_object_id :integer not null +# project_id :integer not null +# created_at :datetime +# updated_at :datetime +# + class LfsObjectsProject < ActiveRecord::Base belongs_to :project belongs_to :lfs_object diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 942a052876..ac25d38eb6 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -2,25 +2,28 @@ # # Table name: merge_requests # -# id :integer not null, primary key -# target_branch :string(255) not null -# source_branch :string(255) not null -# source_project_id :integer not null -# author_id :integer -# assignee_id :integer -# title :string(255) -# created_at :datetime -# updated_at :datetime -# milestone_id :integer -# state :string(255) -# merge_status :string(255) -# target_project_id :integer not null -# iid :integer -# description :text -# position :integer default(0) -# locked_at :datetime -# updated_by_id :integer -# merge_error :string(255) +# id :integer not null, primary key +# target_branch :string(255) not null +# source_branch :string(255) not null +# source_project_id :integer not null +# author_id :integer +# assignee_id :integer +# title :string(255) +# created_at :datetime +# updated_at :datetime +# milestone_id :integer +# state :string(255) +# merge_status :string(255) +# target_project_id :integer not null +# iid :integer +# description :text +# position :integer default(0) +# locked_at :datetime +# updated_by_id :integer +# merge_error :string(255) +# merge_params :text (serialized to hash) +# merge_when_build_succeeds :boolean default(false), not null +# merge_user_id :integer # require Rails.root.join("app/models/commit") @@ -35,9 +38,12 @@ class MergeRequest < ActiveRecord::Base belongs_to :target_project, foreign_key: :target_project_id, class_name: "Project" belongs_to :source_project, foreign_key: :source_project_id, class_name: "Project" + belongs_to :merge_user, class_name: "User" has_one :merge_request_diff, dependent: :destroy + serialize :merge_params, Hash + after_create :create_merge_request_diff after_update :update_merge_request_diff @@ -121,6 +127,7 @@ class MergeRequest < ActiveRecord::Base validates :source_branch, presence: true validates :target_project, presence: true validates :target_branch, presence: true + validates :merge_user, presence: true, if: :merge_when_build_succeeds? validate :validate_branches validate :validate_fork @@ -134,6 +141,9 @@ class MergeRequest < ActiveRecord::Base scope :closed, -> { with_state(:closed) } scope :closed_and_merged, -> { with_states(:closed, :merged) } + scope :join_project, -> { joins(:target_project) } + scope :references_project, -> { references(:target_project) } + def self.reference_prefix '!' end @@ -148,6 +158,10 @@ class MergeRequest < ActiveRecord::Base }x end + def self.link_reference_pattern + super("merge_requests", /(?\d+)/) + end + def to_reference(from_project = nil) reference = "#{self.class.reference_prefix}#{iid}" @@ -180,9 +194,7 @@ class MergeRequest < ActiveRecord::Base similar_mrs = similar_mrs.where('id not in (?)', self.id) if self.id if similar_mrs.any? errors.add :validate_branches, - "Cannot Create: This merge request already exists: #{ - similar_mrs.pluck(:title) - }" + "Cannot Create: This merge request already exists: #{similar_mrs.pluck(:title)}" end end end @@ -251,6 +263,16 @@ class MergeRequest < ActiveRecord::Base end end + def can_cancel_merge_when_build_succeeds?(current_user) + can_be_merged_by?(current_user) || self.author == current_user + end + + def can_remove_source_branch?(current_user) + !source_project.protected_branch?(source_branch) && + !source_project.root_ref?(source_branch) && + Ability.abilities.allowed?(current_user, :push_code, source_project) + end + def mr_and_commit_notes # Fetch comments only from last 100 commits commits_for_notes_limit = 100 @@ -288,7 +310,7 @@ class MergeRequest < ActiveRecord::Base work_in_progress: work_in_progress? } - unless last_commit.nil? + if last_commit attrs.merge!(last_commit: last_commit.hook_attrs) end @@ -313,7 +335,7 @@ class MergeRequest < ActiveRecord::Base issues = commits.flat_map { |c| c.closes_issues(current_user) } issues.push(*Gitlab::ClosingIssueExtractor.new(project, current_user). closed_by_message(description)) - issues.uniq.sort_by(&:id) + issues.uniq(&:id) else [] end @@ -386,6 +408,16 @@ class MergeRequest < ActiveRecord::Base message end + def reset_merge_when_build_succeeds + return unless merge_when_build_succeeds? + + self.merge_when_build_succeeds = false + self.merge_user = nil + self.merge_params = nil + + self.save + end + # Return array of possible target branches # depends on target project of MR def target_branches @@ -473,8 +505,10 @@ class MergeRequest < ActiveRecord::Base end def ci_commit - if last_commit and source_project - source_project.ci_commit(last_commit.id) - end + @ci_commit ||= source_project.ci_commit(last_commit.id) if last_commit && source_project + end + + def broken? + self.commits.blank? || branch_missing? || cannot_be_merged? end end diff --git a/app/models/milestone.rb b/app/models/milestone.rb index 2ff16e2825..d8c7536cd3 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -16,12 +16,13 @@ class Milestone < ActiveRecord::Base # Represents a "No Milestone" state used for filtering Issues and Merge # Requests that have no milestone assigned. - MilestoneStruct = Struct.new(:title, :name) - None = MilestoneStruct.new('No Milestone', 'No Milestone') - Any = MilestoneStruct.new('Any', '') + MilestoneStruct = Struct.new(:title, :name, :id) + None = MilestoneStruct.new('No Milestone', 'No Milestone', 0) + Any = MilestoneStruct.new('Any Milestone', '', -1) include InternalId include Sortable + include StripAttribute belongs_to :project has_many :issues @@ -35,6 +36,8 @@ class Milestone < ActiveRecord::Base validates :title, presence: true validates :project, presence: true + strip_attributes :title + state_machine :state, initial: :active do event :close do transition active: :closed diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 20b92e68d6..adafabbec0 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -23,19 +23,17 @@ class Namespace < ActiveRecord::Base validates :owner, presence: true, unless: ->(n) { n.type == "Group" } validates :name, - presence: true, uniqueness: true, length: { within: 0..255 }, - format: { with: Gitlab::Regex.namespace_name_regex, - message: Gitlab::Regex.namespace_name_regex_message } + namespace_name: true, + presence: true, + uniqueness: true validates :description, length: { within: 0..255 } validates :path, - uniqueness: { case_sensitive: false }, - presence: true, length: { within: 1..255 }, - exclusion: { in: Gitlab::Blacklist.path }, - format: { with: Gitlab::Regex.namespace_regex, - message: Gitlab::Regex.namespace_regex_message } + namespace: true, + presence: true, + uniqueness: { case_sensitive: false } delegate :name, to: :owner, allow_nil: true, prefix: true @@ -47,7 +45,7 @@ class Namespace < ActiveRecord::Base class << self def by_path(path) - where('lower(path) = :value', value: path.downcase).first + find_by('lower(path) = :value', value: path.downcase) end # Case insensetive search for namespace by path or name @@ -150,6 +148,6 @@ class Namespace < ActiveRecord::Base end def find_fork_of(project) - projects.joins(:forked_project_link).where('forked_project_links.forked_from_project_id = ?', project.id).first + projects.joins(:forked_project_link).find_by('forked_project_links.forked_from_project_id = ?', project.id) end end diff --git a/app/models/note.rb b/app/models/note.rb index 1c6345e735..8c5b5836f9 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -16,6 +16,7 @@ # system :boolean default(FALSE), not null # st_diff :text # updated_by_id :integer +# is_award :boolean default(FALSE), not null # require 'carrierwave/orm/activerecord' @@ -28,7 +29,7 @@ class Note < ActiveRecord::Base default_value_for :system, false - attr_mentionable :note + attr_mentionable :note, cache: true, pipeline: :note participant :author belongs_to :project @@ -39,9 +40,12 @@ class Note < ActiveRecord::Base delegate :name, to: :project, prefix: true delegate :name, :email, to: :author, prefix: true + before_validation :set_award! + validates :note, :project, presence: true validates :note, uniqueness: { scope: [:author, :noteable_type, :noteable_id] }, if: ->(n) { n.is_award } - validates :line_code, format: { with: /\A[a-z0-9]+_\d+_\d+\Z/ }, allow_blank: true + validates :note, inclusion: { in: Emoji.emojis_names }, if: ->(n) { n.is_award } + validates :line_code, line_code: true, allow_blank: true # Attachments are deprecated and are handled by Markdown uploader validates :attachment, file_size: { maximum: :max_attachment_size } @@ -346,6 +350,34 @@ class Note < ActiveRecord::Base end def editable? - !system? + !system? && !is_award + end + + # Checks if note is an award added as a comment + # + # If note is an award, this method sets is_award to true + # and changes content of the note to award name. + # + # Method is executed as a before_validation callback. + # + def set_award! + return unless awards_supported? && contains_emoji_only? + self.is_award = true + self.note = award_emoji_name + end + + private + + def awards_supported? + noteable.kind_of?(Issue) || noteable.is_a?(MergeRequest) + end + + def contains_emoji_only? + note =~ /\A#{Banzai::Filter::EmojiFilter.emoji_pattern}\s?\Z/ + end + + def award_emoji_name + original_name = note.match(Banzai::Filter::EmojiFilter.emoji_pattern)[1] + AwardEmoji.normilize_emoji_name(original_name) end end diff --git a/app/models/project.rb b/app/models/project.rb index f0a4b6aae7..b28a7ca429 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -28,6 +28,7 @@ # import_type :string(255) # import_source :string(255) # commit_count :integer default(0) +# import_error :text # require 'carrierwave/orm/activerecord' @@ -42,9 +43,8 @@ class Project < ActiveRecord::Base include Sortable include AfterCommitQueue include CaseSensitivity - + extend Gitlab::ConfigHelper - extend Enumerize UNKNOWN_IMPORT_URL = 'http://unknown.git' @@ -56,6 +56,7 @@ class Project < ActiveRecord::Base default_value_for :wiki_enabled, gitlab_config_features.wiki default_value_for :wall_enabled, false default_value_for :snippets_enabled, gitlab_config_features.snippets + default_value_for(:shared_runners_enabled) { current_application_settings.shared_runners_enabled } # set last_activity_at to the same as created_at after_create :set_last_activity_at @@ -77,10 +78,10 @@ class Project < ActiveRecord::Base # Project services has_many :services - has_one :gitlab_ci_service, dependent: :destroy has_one :campfire_service, dependent: :destroy has_one :drone_ci_service, dependent: :destroy has_one :emails_on_push_service, dependent: :destroy + has_one :builds_email_service, dependent: :destroy has_one :irker_service, dependent: :destroy has_one :pivotaltracker_service, dependent: :destroy has_one :hipchat_service, dependent: :destroy @@ -121,14 +122,21 @@ class Project < ActiveRecord::Base has_many :deploy_keys, through: :deploy_keys_projects has_many :users_star_projects, dependent: :destroy has_many :starrers, through: :users_star_projects, source: :user - has_many :ci_commits, dependent: :destroy, class_name: 'Ci::Commit', foreign_key: :gl_project_id - has_many :ci_builds, through: :ci_commits, source: :builds, dependent: :destroy, class_name: 'Ci::Build' has_many :releases, dependent: :destroy has_many :lfs_objects_projects, dependent: :destroy has_many :lfs_objects, through: :lfs_objects_projects has_one :import_data, dependent: :destroy, class_name: "ProjectImportData" - has_one :gitlab_ci_project, dependent: :destroy, class_name: "Ci::Project", foreign_key: :gitlab_id + + has_many :commit_statuses, dependent: :destroy, class_name: 'CommitStatus', foreign_key: :gl_project_id + has_many :ci_commits, dependent: :destroy, class_name: 'Ci::Commit', foreign_key: :gl_project_id + has_many :builds, class_name: 'Ci::Build', foreign_key: :gl_project_id # the builds are created from the commit_statuses + has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject', foreign_key: :gl_project_id + has_many :runners, through: :runner_projects, source: :runner, class_name: 'Ci::Runner' + has_many :variables, dependent: :destroy, class_name: 'Ci::Variable', foreign_key: :gl_project_id + has_many :triggers, dependent: :destroy, class_name: 'Ci::Trigger', foreign_key: :gl_project_id + + accepts_nested_attributes_for :variables, allow_destroy: true delegate :name, to: :owner, allow_nil: true, prefix: true delegate :members, to: :team, prefix: true @@ -153,7 +161,7 @@ class Project < ActiveRecord::Base validates_uniqueness_of :name, scope: :namespace_id validates_uniqueness_of :path, scope: :namespace_id validates :import_url, - format: { with: /\A#{URI.regexp(%w(ssh git http https))}\z/, message: 'should be a valid url' }, + url: { protocols: %w(ssh git http https) }, if: :external_import? validates :star_count, numericality: { greater_than_or_equal_to: 0 } validate :check_limit, on: :create @@ -161,6 +169,11 @@ class Project < ActiveRecord::Base if: ->(project) { project.avatar.present? && project.avatar_changed? } validates :avatar, file_size: { maximum: 200.kilobytes.to_i } + before_validation :set_runners_token_token + def set_runners_token_token + self.runners_token = SecureRandom.hex(15) if self.runners_token.blank? + end + mount_uploader :avatar, AvatarUploader # Scopes @@ -252,10 +265,14 @@ class Project < ActiveRecord::Base joins(:namespace). iwhere('namespaces.path' => namespace_path) - projects.where('projects.path' => project_path).take || + projects.find_by('projects.path' => project_path) || projects.iwhere('projects.path' => project_path).take end + def find_by_ci_id(id) + find_by(ci_id: id.to_i) + end + def visibility_levels Gitlab::VisibilityLevel.options end @@ -433,7 +450,7 @@ class Project < ActiveRecord::Base end def external_issue_tracker - @external_issues_tracker ||= external_issues_trackers.select(&:activated?).first + @external_issues_tracker ||= external_issues_trackers.find(&:activated?) end def can_have_issues_tracker_id? @@ -479,7 +496,11 @@ class Project < ActiveRecord::Base end def ci_service - @ci_service ||= ci_services.select(&:activated?).first + @ci_service ||= ci_services.find(&:activated?) + end + + def jira_tracker? + issues_tracker.to_param == 'jira' end def avatar_type @@ -530,7 +551,7 @@ class Project < ActiveRecord::Base end def project_member_by_name_or_email(name = nil, email = nil) - user = users.where('name like ? or email like ?', name, email).first + user = users.find_by('name like ? or email like ?', name, email) project_members.where(user: user) if user end @@ -662,6 +683,7 @@ class Project < ActiveRecord::Base gitlab_shell.mv_repository("#{old_path_with_namespace}.wiki", "#{new_path_with_namespace}.wiki") send_move_instructions(old_path_with_namespace) reset_events_cache + @repository = nil rescue # Returning false does not rollback after_* transaction but gives # us information about failing some of tasks @@ -704,7 +726,7 @@ class Project < ActiveRecord::Base end def project_member(user) - project_members.where(user_id: user).first + project_members.find_by(user_id: user) end def default_branch @@ -781,6 +803,10 @@ class Project < ActiveRecord::Base false end + def jira_tracker_active? + jira_tracker? && jira_service.active + end + def ci_commit(sha) ci_commits.find_by(sha: sha) end @@ -789,28 +815,6 @@ class Project < ActiveRecord::Base ci_commit(sha) || ci_commits.create(sha: sha) end - def ensure_gitlab_ci_project - gitlab_ci_project || create_gitlab_ci_project( - shared_runners_enabled: current_application_settings.shared_runners_enabled - ) - end - - # TODO: this should be migrated to Project table, - # the same as issues_enabled - def builds_enabled - gitlab_ci_service && gitlab_ci_service.active - end - - def builds_enabled? - builds_enabled - end - - def builds_enabled=(value) - service = gitlab_ci_service || create_gitlab_ci_service - service.active = value - service.save - end - def enable_ci self.builds_enabled = true end @@ -824,4 +828,38 @@ class Project < ActiveRecord::Base forked_project_link.destroy end end + + def any_runners?(&block) + if runners.active.any?(&block) + return true + end + + shared_runners_enabled? && Ci::Runner.shared.active.any?(&block) + end + + def valid_runners_token? token + self.runners_token && self.runners_token == token + end + + # TODO (ayufan): For now we use runners_token (backward compatibility) + # In 8.4 every build will have its own individual token valid for time of build + def valid_build_token? token + self.builds_enabled? && self.runners_token && self.runners_token == token + end + + def build_coverage_enabled? + build_coverage_regex.present? + end + + def build_timeout_in_minutes + build_timeout / 60 + end + + def build_timeout_in_minutes=(value) + self.build_timeout = value.to_i * 60 + end + + def open_issues_count + issues.opened.count + end end diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb index d31b12f539..aa8746beb8 100644 --- a/app/models/project_services/bamboo_service.rb +++ b/app/models/project_services/bamboo_service.rb @@ -23,19 +23,14 @@ class BambooService < CiService prop_accessor :bamboo_url, :build_key, :username, :password - validates :bamboo_url, - presence: true, - format: { with: /\A#{URI.regexp}\z/ }, - if: :activated? + validates :bamboo_url, presence: true, url: true, if: :activated? validates :build_key, presence: true, if: :activated? validates :username, presence: true, - if: ->(service) { service.password? }, - if: :activated? + if: ->(service) { service.activated? && service.password } validates :password, presence: true, - if: ->(service) { service.username? }, - if: :activated? + if: ->(service) { service.activated? && service.username } attr_accessor :response @@ -84,7 +79,7 @@ class BambooService < CiService def supported_events %w(push) end - + def build_info(sha) url = URI.parse("#{bamboo_url}/rest/api/latest/result?label=#{sha}") diff --git a/app/models/project_services/buildkite_service.rb b/app/models/project_services/buildkite_service.rb index 40058b53df..199ee3a9d0 100644 --- a/app/models/project_services/buildkite_service.rb +++ b/app/models/project_services/buildkite_service.rb @@ -37,7 +37,7 @@ class BuildkiteService < CiService def compose_service_hook hook = service_hook || build_service_hook hook.url = webhook_url - hook.enable_ssl_verification = enable_ssl_verification + hook.enable_ssl_verification = !!enable_ssl_verification hook.save end diff --git a/app/models/project_services/builds_email_service.rb b/app/models/project_services/builds_email_service.rb new file mode 100644 index 0000000000..8247c79fc3 --- /dev/null +++ b/app/models/project_services/builds_email_service.rb @@ -0,0 +1,90 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# template :boolean default(FALSE) +# push_events :boolean default(TRUE) +# issues_events :boolean default(TRUE) +# merge_requests_events :boolean default(TRUE) +# tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null +# + +class BuildsEmailService < Service + prop_accessor :recipients + boolean_accessor :add_pusher + boolean_accessor :notify_only_broken_builds + validates :recipients, presence: true, if: :activated? + + def initialize_properties + if properties.nil? + self.properties = {} + self.notify_only_broken_builds = true + end + end + + def title + 'Builds emails' + end + + def description + 'Email the builds status to a list of recipients.' + end + + def to_param + 'builds_email' + end + + def supported_events + %w(build) + end + + def execute(push_data) + return unless supported_events.include?(push_data[:object_kind]) + + if should_build_be_notified?(push_data) + BuildEmailWorker.perform_async( + push_data[:build_id], + all_recipients(push_data), + push_data, + ) + end + end + + def fields + [ + { type: 'textarea', name: 'recipients', placeholder: 'Emails separated by comma' }, + { type: 'checkbox', name: 'add_pusher', label: 'Add pusher to recipients list' }, + { type: 'checkbox', name: 'notify_only_broken_builds' }, + ] + end + + def should_build_be_notified?(data) + case data[:build_status] + when 'success' + !notify_only_broken_builds? + when 'failed' + true + else + false + end + end + + def all_recipients(data) + all_recipients = recipients.split(',') + + if add_pusher? && data[:user][:email] + all_recipients << "#{data[:user][:email]}" + end + + all_recipients + end +end diff --git a/app/models/project_services/ci/hip_chat_message.rb b/app/models/project_services/ci/hip_chat_message.rb deleted file mode 100644 index d89466b689..0000000000 --- a/app/models/project_services/ci/hip_chat_message.rb +++ /dev/null @@ -1,73 +0,0 @@ -module Ci - class HipChatMessage - include Gitlab::Application.routes.url_helpers - - attr_reader :build - - def initialize(build) - @build = build - end - - def to_s - lines = Array.new - lines.push("#{project.name} - ") - lines.push("Commit ##{commit.id}
") - lines.push("#{commit.short_sha} #{commit.git_author_name} - #{commit.git_commit_message}
") - lines.push("#{humanized_status(commit_status)} in #{commit.duration} second(s).") - lines.join('') - end - - def status_color(build_or_commit=nil) - build_or_commit ||= commit_status - case build_or_commit - when :success - 'green' - when :failed, :canceled - 'red' - else # :pending, :running or unknown - 'yellow' - end - end - - def notify? - [:failed, :canceled].include?(commit_status) - end - - - private - - def commit - build.commit - end - - def project - commit.project - end - - def build_status - build.status.to_sym - end - - def commit_status - commit.status.to_sym - end - - def humanized_status(build_or_commit=nil) - build_or_commit ||= commit_status - case build_or_commit - when :pending - "Pending" - when :running - "Running" - when :failed - "Failed" - when :success - "Successful" - when :canceled - "Canceled" - else - "Unknown" - end - end - end -end diff --git a/app/models/project_services/ci/hip_chat_service.rb b/app/models/project_services/ci/hip_chat_service.rb deleted file mode 100644 index 0df03890ef..0000000000 --- a/app/models/project_services/ci/hip_chat_service.rb +++ /dev/null @@ -1,93 +0,0 @@ -# == Schema Information -# -# Table name: ci_services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# - -module Ci - class HipChatService < Ci::Service - prop_accessor :hipchat_token, :hipchat_room, :hipchat_server - boolean_accessor :notify_only_broken_builds - validates :hipchat_token, presence: true, if: :activated? - validates :hipchat_room, presence: true, if: :activated? - default_value_for :notify_only_broken_builds, true - - def title - "HipChat" - end - - def description - "Private group chat, video chat, instant messaging for teams" - end - - def help - end - - def to_param - 'hip_chat' - end - - def fields - [ - { type: 'text', name: 'hipchat_token', label: 'Token', placeholder: '' }, - { type: 'text', name: 'hipchat_room', label: 'Room', placeholder: '' }, - { type: 'text', name: 'hipchat_server', label: 'Server', placeholder: 'https://hipchat.example.com', help: 'Leave blank for default' }, - { type: 'checkbox', name: 'notify_only_broken_builds', label: 'Notify only broken builds' } - ] - end - - def can_execute?(build) - return if build.allow_failure? - - commit = build.commit - return unless commit - return unless commit.latest_builds.include? build - - case commit.status.to_sym - when :failed - true - when :success - true unless notify_only_broken_builds? - else - false - end - end - - def execute(build) - msg = Ci::HipChatMessage.new(build) - opts = default_options.merge( - token: hipchat_token, - room: hipchat_room, - server: server_url, - color: msg.status_color, - notify: msg.notify? - ) - Ci::HipChatNotifierWorker.perform_async(msg.to_s, opts) - end - - private - - def default_options - { - service_name: 'GitLab CI', - message_format: 'html' - } - end - - def server_url - if hipchat_server.blank? - 'https://api.hipchat.com' - else - hipchat_server - end - end - end -end diff --git a/app/models/project_services/ci/mail_service.rb b/app/models/project_services/ci/mail_service.rb deleted file mode 100644 index d31dd6899c..0000000000 --- a/app/models/project_services/ci/mail_service.rb +++ /dev/null @@ -1,84 +0,0 @@ -# == Schema Information -# -# Table name: ci_services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# - -module Ci - class MailService < Ci::Service - delegate :email_recipients, :email_recipients=, - :email_add_pusher, :email_add_pusher=, - :email_only_broken_builds, :email_only_broken_builds=, to: :project, prefix: false - - before_save :update_project - - default_value_for :active, true - - def title - 'Mail' - end - - def description - 'Email notification' - end - - def to_param - 'mail' - end - - def fields - [ - { type: 'text', name: 'email_recipients', label: 'Recipients', help: 'Whitespace-separated list of recipient addresses' }, - { type: 'checkbox', name: 'email_add_pusher', label: 'Add pusher to recipients list' }, - { type: 'checkbox', name: 'email_only_broken_builds', label: 'Notify only broken builds' } - ] - end - - def can_execute?(build) - return if build.allow_failure? - - # it doesn't make sense to send emails for retried builds - commit = build.commit - return unless commit - return unless commit.latest_builds.include?(build) - - case build.status.to_sym - when :failed - true - when :success - true unless email_only_broken_builds - else - false - end - end - - def execute(build) - build.project_recipients.each do |recipient| - case build.status.to_sym - when :success - mailer.build_success_email(build.id, recipient) - when :failed - mailer.build_fail_email(build.id, recipient) - end - end - end - - private - - def update_project - project.save! - end - - def mailer - Ci::Notify.delay - end - end -end diff --git a/app/models/project_services/ci/slack_message.rb b/app/models/project_services/ci/slack_message.rb deleted file mode 100644 index 1a6ff8e34c..0000000000 --- a/app/models/project_services/ci/slack_message.rb +++ /dev/null @@ -1,92 +0,0 @@ -require 'slack-notifier' - -module Ci - class SlackMessage - include Gitlab::Application.routes.url_helpers - - def initialize(commit) - @commit = commit - end - - def pretext - '' - end - - def color - attachment_color - end - - def fallback - format(attachment_message) - end - - def attachments - fields = [] - - commit.latest_builds.each do |build| - next if build.allow_failure? - next unless build.failed? - fields << { - title: build.name, - value: "Build <#{namespace_project_build_url(build.gl_project.namespace, build.gl_project, build)}|\##{build.id}> failed in #{build.duration.to_i} second(s)." - } - end - - [{ - text: attachment_message, - color: attachment_color, - fields: fields - }] - end - - private - - attr_reader :commit - - def attachment_message - out = "<#{ci_project_url(project)}|#{project_name}>: " - out << "Commit <#{builds_namespace_project_commit_url(commit.gl_project.namespace, commit.gl_project, commit.sha)}|\##{commit.id}> " - out << "(<#{commit_sha_link}|#{commit.short_sha}>) " - out << "of <#{commit_ref_link}|#{commit.ref}> " - out << "by #{commit.git_author_name} " if commit.git_author_name - out << "#{commit_status} in " - out << "#{commit.duration} second(s)" - end - - def format(string) - Slack::Notifier::LinkFormatter.format(string) - end - - def project - commit.project - end - - def project_name - project.name - end - - def commit_sha_link - "#{project.gitlab_url}/commit/#{commit.sha}" - end - - def commit_ref_link - "#{project.gitlab_url}/commits/#{commit.ref}" - end - - def attachment_color - if commit.success? - 'good' - else - 'danger' - end - end - - def commit_status - if commit.success? - 'succeeded' - else - 'failed' - end - end - end -end diff --git a/app/models/project_services/ci/slack_service.rb b/app/models/project_services/ci/slack_service.rb deleted file mode 100644 index 7064bfe78d..0000000000 --- a/app/models/project_services/ci/slack_service.rb +++ /dev/null @@ -1,81 +0,0 @@ -# == Schema Information -# -# Table name: ci_services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# - -module Ci - class SlackService < Ci::Service - prop_accessor :webhook - boolean_accessor :notify_only_broken_builds - validates :webhook, presence: true, if: :activated? - - default_value_for :notify_only_broken_builds, true - - def title - 'Slack' - end - - def description - 'A team communication tool for the 21st century' - end - - def to_param - 'slack' - end - - def help - 'Visit https://www.slack.com/services/new/incoming-webhook. Then copy link and save project!' unless webhook.present? - end - - def fields - [ - { type: 'text', name: 'webhook', label: 'Webhook URL', placeholder: '' }, - { type: 'checkbox', name: 'notify_only_broken_builds', label: 'Notify only broken builds' } - ] - end - - def can_execute?(build) - return if build.allow_failure? - - commit = build.commit - return unless commit - return unless commit.latest_builds.include?(build) - - case commit.status.to_sym - when :failed - true - when :success - true unless notify_only_broken_builds? - else - false - end - end - - def execute(build) - message = Ci::SlackMessage.new(build.commit) - options = default_options.merge( - color: message.color, - fallback: message.fallback, - attachments: message.attachments - ) - Ci::SlackNotifierWorker.perform_async(webhook, message.pretext, options) - end - - private - - def default_options - { - username: 'GitLab CI' - } - end - end -end diff --git a/app/models/project_services/drone_ci_service.rb b/app/models/project_services/drone_ci_service.rb index 127684bd27..08e5ccb385 100644 --- a/app/models/project_services/drone_ci_service.rb +++ b/app/models/project_services/drone_ci_service.rb @@ -19,14 +19,11 @@ # class DroneCiService < CiService - + prop_accessor :drone_url, :token, :enable_ssl_verification - validates :drone_url, - presence: true, - format: { with: /\A#{URI.regexp(%w(http https))}\z/, message: "should be a valid url" }, if: :activated? - validates :token, - presence: true, - if: :activated? + + validates :drone_url, presence: true, url: true, if: :activated? + validates :token, presence: true, if: :activated? after_save :compose_service_hook, if: :activated? @@ -34,7 +31,7 @@ class DroneCiService < CiService hook = service_hook || build_service_hook # If using a service template, project may not be available hook.url = [drone_url, "/api/hook", "?owner=#{project.namespace.path}", "&name=#{project.path}", "&access_token=#{token}"].join if project - hook.enable_ssl_verification = enable_ssl_verification + hook.enable_ssl_verification = !!enable_ssl_verification hook.save end @@ -58,16 +55,16 @@ class DroneCiService < CiService end def merge_request_status_path(iid, sha = nil, ref = nil) - url = [drone_url, - "gitlab/#{project.namespace.path}/#{project.path}/pulls/#{iid}", + url = [drone_url, + "gitlab/#{project.namespace.path}/#{project.path}/pulls/#{iid}", "?access_token=#{token}"] URI.join(*url).to_s end def commit_status_path(sha, ref) - url = [drone_url, - "gitlab/#{project.namespace.path}/#{project.path}/commits/#{sha}", + url = [drone_url, + "gitlab/#{project.namespace.path}/#{project.path}/commits/#{sha}", "?branch=#{URI::encode(ref.to_s)}&access_token=#{token}"] URI.join(*url).to_s @@ -114,15 +111,15 @@ class DroneCiService < CiService end def merge_request_page(iid, sha, ref) - url = [drone_url, + url = [drone_url, "gitlab/#{project.namespace.path}/#{project.path}/redirect/pulls/#{iid}"] URI.join(*url).to_s end def commit_page(sha, ref) - url = [drone_url, - "gitlab/#{project.namespace.path}/#{project.path}/redirect/commits/#{sha}", + url = [drone_url, + "gitlab/#{project.namespace.path}/#{project.path}/redirect/commits/#{sha}", "?branch=#{URI::encode(ref.to_s)}"] URI.join(*url).to_s @@ -163,10 +160,10 @@ class DroneCiService < CiService end def push_valid?(data) - opened_merge_requests = project.merge_requests.opened.where(source_project_id: project.id, + opened_merge_requests = project.merge_requests.opened.where(source_project_id: project.id, source_branch: Gitlab::Git.ref_name(data[:ref])) - opened_merge_requests.empty? && data[:total_commits_count] > 0 && + opened_merge_requests.empty? && data[:total_commits_count] > 0 && !Gitlab::Git.blank_ref?(data[:after]) end diff --git a/app/models/project_services/external_wiki_service.rb b/app/models/project_services/external_wiki_service.rb index 9c46af7e72..74c57949b4 100644 --- a/app/models/project_services/external_wiki_service.rb +++ b/app/models/project_services/external_wiki_service.rb @@ -22,10 +22,8 @@ class ExternalWikiService < Service include HTTParty prop_accessor :external_wiki_url - validates :external_wiki_url, - presence: true, - format: { with: /\A#{URI.regexp}\z/ }, - if: :activated? + + validates :external_wiki_url, presence: true, url: true, if: :activated? def title 'External Wiki' diff --git a/app/models/project_services/flowdock_service.rb b/app/models/project_services/flowdock_service.rb index 27fc19379f..15c7c907f7 100644 --- a/app/models/project_services/flowdock_service.rb +++ b/app/models/project_services/flowdock_service.rb @@ -58,6 +58,6 @@ class FlowdockService < Service repo_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}", commit_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/commit/%s", diff_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/compare/%s...%s", - ) + ) end end diff --git a/app/models/project_services/gemnasium_service.rb b/app/models/project_services/gemnasium_service.rb index 91ef267ad7..202fee042e 100644 --- a/app/models/project_services/gemnasium_service.rb +++ b/app/models/project_services/gemnasium_service.rb @@ -57,6 +57,6 @@ class GemnasiumService < Service token: token, api_key: api_key, repo: project.repository.path_to_repo - ) + ) end end diff --git a/app/models/project_services/gitlab_ci_service.rb b/app/models/project_services/gitlab_ci_service.rb index c5657b5070..b64d97ce75 100644 --- a/app/models/project_services/gitlab_ci_service.rb +++ b/app/models/project_services/gitlab_ci_service.rb @@ -18,77 +18,11 @@ # note_events :boolean default(TRUE), not null # +# TODO(ayufan): The GitLabCiService is deprecated and the type should be removed when the database entries are removed class GitlabCiService < CiService - include Gitlab::Application.routes.url_helpers - - after_save :compose_service_hook, if: :activated? - after_save :ensure_gitlab_ci_project, if: :activated? - - def compose_service_hook - hook = service_hook || build_service_hook - hook.save - end - - def ensure_gitlab_ci_project - return unless project - project.ensure_gitlab_ci_project - end - - def supported_events - %w(push tag_push) - end - - def execute(data) - return unless supported_events.include?(data[:object_kind]) - - ci_project = project.gitlab_ci_project - if ci_project - current_user = User.find_by(id: data[:user_id]) - Ci::CreateCommitService.new.execute(ci_project, current_user, data) - end - end - - def token - if project.gitlab_ci_project.present? - project.gitlab_ci_project.token - end - end - - def get_ci_commit(sha, ref) - Ci::Project.find(project.gitlab_ci_project).commits.find_by_sha!(sha) - end - - def commit_status(sha, ref) - get_ci_commit(sha, ref).status - rescue ActiveRecord::RecordNotFound - :error - end - - def commit_coverage(sha, ref) - get_ci_commit(sha, ref).coverage - rescue ActiveRecord::RecordNotFound - :error - end - - def build_page(sha, ref) - if project.gitlab_ci_project.present? - builds_namespace_project_commit_url(project.namespace, project, sha) - end - end - - def title - 'GitLab CI' - end - - def description - 'Continuous integration server from GitLab' - end - - def to_param - 'gitlab_ci' - end - - def fields - [] + # We override the active accessor to always make GitLabCiService disabled + # Otherwise the GitLabCiService can be picked, but should never be since it's deprecated + def active + false end end diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb index af2840a57f..1e1686a11c 100644 --- a/app/models/project_services/hipchat_service.rb +++ b/app/models/project_services/hipchat_service.rb @@ -22,8 +22,16 @@ class HipchatService < Service MAX_COMMITS = 3 prop_accessor :token, :room, :server, :notify, :color, :api_version + boolean_accessor :notify_only_broken_builds validates :token, presence: true, if: :activated? + def initialize_properties + if properties.nil? + self.properties = {} + self.notify_only_broken_builds = true + end + end + def title 'HipChat' end @@ -45,12 +53,13 @@ class HipchatService < Service { type: 'text', name: 'api_version', placeholder: 'Leave blank for default (v2)' }, { type: 'text', name: 'server', - placeholder: 'Leave blank for default. https://hipchat.example.com' } + placeholder: 'Leave blank for default. https://hipchat.example.com' }, + { type: 'checkbox', name: 'notify_only_broken_builds' }, ] end def supported_events - %w(push issue merge_request note tag_push) + %w(push issue merge_request note tag_push build) end def execute(data) @@ -94,6 +103,8 @@ class HipchatService < Service create_merge_request_message(data) unless is_update?(data) when "note" create_note_message(data) + when "build" + create_build_message(data) if should_build_be_notified?(data) end end @@ -235,6 +246,20 @@ class HipchatService < Service message end + def create_build_message(data) + ref_type = data[:tag] ? 'tag' : 'branch' + ref = data[:ref] + sha = data[:sha] + user_name = data[:commit][:author_name] + status = data[:commit][:status] + duration = data[:commit][:duration] + + branch_link = "#{ref}" + commit_link = "#{Commit.truncate_sha(sha)}" + + "#{project_link}: Commit #{commit_link} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status(status)} in #{duration} second(s)" + end + def project_name project.name_with_namespace.gsub(/\s/, '') end @@ -250,4 +275,24 @@ class HipchatService < Service def is_update?(data) data[:object_attributes][:action] == 'update' end + + def humanized_status(status) + case status + when 'success' + 'passed' + else + status + end + end + + def should_build_be_notified?(data) + case data[:commit][:status] + when 'success' + !notify_only_broken_builds? + when 'failed' + true + else + false + end + end end diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb index 35e30b1cb0..e216f406e1 100644 --- a/app/models/project_services/jira_service.rb +++ b/app/models/project_services/jira_service.rb @@ -19,9 +19,24 @@ # class JiraService < IssueTrackerService + include HTTParty include Gitlab::Application.routes.url_helpers - prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url + DEFAULT_API_VERSION = 2 + + prop_accessor :username, :password, :api_url, :jira_issue_transition_id, + :title, :description, :project_url, :issues_url, :new_issue_url + + before_validation :set_api_url, :set_jira_issue_transition_id + + before_update :reset_password + + def reset_password + # don't reset the password if a new one is provided + if api_url_changed? && !password_touched? + self.password = nil + end + end def help line1 = 'Setting `project_url`, `issues_url` and `new_issue_url` will '\ @@ -54,4 +69,228 @@ class JiraService < IssueTrackerService def to_param 'jira' end + + def fields + super.push( + { type: 'text', name: 'api_url', placeholder: 'https://jira.example.com/rest/api/2' }, + { type: 'text', name: 'username', placeholder: '' }, + { type: 'password', name: 'password', placeholder: '' }, + { type: 'text', name: 'jira_issue_transition_id', placeholder: '2' } + ) + end + + def execute(push, issue = nil) + if issue.nil? + # No specific issue, that means + # we just want to test settings + test_settings + else + close_issue(push, issue) + end + end + + def create_cross_reference_note(mentioned, noteable, author) + issue_name = mentioned.id + project = self.project + noteable_name = noteable.class.name.underscore.downcase + noteable_id = if noteable.is_a?(Commit) + noteable.id + else + noteable.iid + end + + entity_url = build_entity_url(noteable_name.to_sym, noteable_id) + + data = { + user: { + name: author.name, + url: resource_url(user_path(author)), + }, + project: { + name: project.path_with_namespace, + url: resource_url(namespace_project_path(project.namespace, project)) + }, + entity: { + name: noteable_name.humanize.downcase, + url: entity_url + } + } + + add_comment(data, issue_name) + end + + def test_settings + result = JiraService.get( + jira_api_test_url, + headers: { + 'Content-Type' => 'application/json', + 'Authorization' => "Basic #{auth}" + } + ) + + case result.code + when 201, 200 + Rails.logger.info("#{self.class.name} SUCCESS #{result.code}: Successfully connected to #{api_url}.") + true + else + Rails.logger.info("#{self.class.name} ERROR #{result.code}: #{result.parsed_response}") + false + end + rescue Errno::ECONNREFUSED => e + Rails.logger.info "#{self.class.name} ERROR: #{e.message}. API URL: #{api_url}." + false + end + + private + + def build_api_url_from_project_url + server = URI(project_url) + default_ports = [["http",80],["https",443]].include?([server.scheme,server.port]) + server_url = "#{server.scheme}://#{server.host}" + server_url.concat(":#{server.port}") unless default_ports + "#{server_url}/rest/api/#{DEFAULT_API_VERSION}" + rescue + "" # looks like project URL was not valid + end + + def set_api_url + self.api_url = build_api_url_from_project_url if self.api_url.blank? + end + + def set_jira_issue_transition_id + self.jira_issue_transition_id ||= "2" + end + + def close_issue(entity, issue) + commit_id = if entity.is_a?(Commit) + entity.id + elsif entity.is_a?(MergeRequest) + entity.last_commit.id + end + commit_url = build_entity_url(:commit, commit_id) + + # Depending on the JIRA project's workflow, a comment during transition + # may or may not be allowed. Split the operation in to two calls so the + # comment always works. + transition_issue(issue) + add_issue_solved_comment(issue, commit_id, commit_url) + end + + def transition_issue(issue) + message = { + transition: { + id: jira_issue_transition_id + } + } + send_message(close_issue_url(issue.iid), message.to_json) + end + + def add_issue_solved_comment(issue, commit_id, commit_url) + comment = { + body: "Issue solved with [#{commit_id}|#{commit_url}]." + } + + send_message(comment_url(issue.iid), comment.to_json) + end + + def add_comment(data, issue_name) + url = comment_url(issue_name) + user_name = data[:user][:name] + user_url = data[:user][:url] + entity_name = data[:entity][:name] + entity_url = data[:entity][:url] + project_name = data[:project][:name] + + message = { + body: "[#{user_name}|#{user_url}] mentioned this issue in [a #{entity_name} of #{project_name}|#{entity_url}]." + } + + unless existing_comment?(issue_name, message[:body]) + send_message(url, message.to_json) + end + end + + + def auth + require 'base64' + Base64.urlsafe_encode64("#{self.username}:#{self.password}") + end + + def send_message(url, message) + result = JiraService.post( + url, + body: message, + headers: { + 'Content-Type' => 'application/json', + 'Authorization' => "Basic #{auth}" + } + ) + + message = case result.code + when 201, 200, 204 + "#{self.class.name} SUCCESS #{result.code}: Successfully posted to #{url}." + when 401 + "#{self.class.name} ERROR 401: Unauthorized. Check the #{self.username} credentials and JIRA access permissions and try again." + else + "#{self.class.name} ERROR #{result.code}: #{result.parsed_response}" + end + + Rails.logger.info(message) + message + rescue URI::InvalidURIError, Errno::ECONNREFUSED => e + Rails.logger.info "#{self.class.name} ERROR: #{e.message}. Hostname: #{url}." + end + + def existing_comment?(issue_name, new_comment) + result = JiraService.get( + comment_url(issue_name), + headers: { + 'Content-Type' => 'application/json', + 'Authorization' => "Basic #{auth}" + } + ) + + case result.code + when 201, 200 + existing_comments = JSON.parse(result.body)['comments'] + + if existing_comments.present? + return existing_comments.map { |comment| comment['body'].include?(new_comment) }.any? + end + end + + false + rescue JSON::ParserError + false + end + + def resource_url(resource) + "#{Settings.gitlab['url'].chomp("/")}#{resource}" + end + + def build_entity_url(entity_name, entity_id) + resource_url( + polymorphic_url( + [ + self.project.namespace.becomes(Namespace), + self.project, + entity_name + ], + id: entity_id, + routing_type: :path + ) + ) + end + + def close_issue_url(issue_name) + "#{self.api_url}/issue/#{issue_name}/transitions" + end + + def comment_url(issue_name) + "#{self.api_url}/issue/#{issue_name}/comment" + end + + def jira_api_test_url + "#{self.api_url}/myself" + end end diff --git a/app/models/project_services/slack_service.rb b/app/models/project_services/slack_service.rb index 7cd5e89250..375b4534d0 100644 --- a/app/models/project_services/slack_service.rb +++ b/app/models/project_services/slack_service.rb @@ -20,8 +20,16 @@ class SlackService < Service prop_accessor :webhook, :username, :channel + boolean_accessor :notify_only_broken_builds validates :webhook, presence: true, if: :activated? + def initialize_properties + if properties.nil? + self.properties = {} + self.notify_only_broken_builds = true + end + end + def title 'Slack' end @@ -45,12 +53,13 @@ class SlackService < Service { type: 'text', name: 'webhook', placeholder: 'https://hooks.slack.com/services/...' }, { type: 'text', name: 'username', placeholder: 'username' }, - { type: 'text', name: 'channel', placeholder: '#channel' } + { type: 'text', name: 'channel', placeholder: '#channel' }, + { type: 'checkbox', name: 'notify_only_broken_builds' }, ] end def supported_events - %w(push issue merge_request note tag_push) + %w(push issue merge_request note tag_push build) end def execute(data) @@ -78,6 +87,8 @@ class SlackService < Service MergeMessage.new(data) unless is_update?(data) when "note" NoteMessage.new(data) + when "build" + BuildMessage.new(data) if should_build_be_notified?(data) end opt = {} @@ -86,7 +97,7 @@ class SlackService < Service if message notifier = Slack::Notifier.new(webhook, opt) - notifier.ping(message.pretext, attachments: message.attachments) + notifier.ping(message.pretext, attachments: message.attachments, fallback: message.fallback) end end @@ -103,9 +114,21 @@ class SlackService < Service def is_update?(data) data[:object_attributes][:action] == 'update' end + + def should_build_be_notified?(data) + case data[:commit][:status] + when 'success' + !notify_only_broken_builds? + when 'failed' + true + else + false + end + end end require "slack_service/issue_message" require "slack_service/push_message" require "slack_service/merge_message" require "slack_service/note_message" +require "slack_service/build_message" diff --git a/app/models/project_services/slack_service/base_message.rb b/app/models/project_services/slack_service/base_message.rb index aa00d6061a..f118282468 100644 --- a/app/models/project_services/slack_service/base_message.rb +++ b/app/models/project_services/slack_service/base_message.rb @@ -10,6 +10,9 @@ class SlackService format(message) end + def fallback + end + def attachments raise NotImplementedError end diff --git a/app/models/project_services/slack_service/build_message.rb b/app/models/project_services/slack_service/build_message.rb new file mode 100644 index 0000000000..c124cad4af --- /dev/null +++ b/app/models/project_services/slack_service/build_message.rb @@ -0,0 +1,82 @@ +class SlackService + class BuildMessage < BaseMessage + attr_reader :sha + attr_reader :ref_type + attr_reader :ref + attr_reader :status + attr_reader :project_name + attr_reader :project_url + attr_reader :user_name + attr_reader :duration + + def initialize(params, commit = true) + @sha = params[:sha] + @ref_type = params[:tag] ? 'tag' : 'branch' + @ref = params[:ref] + @project_name = params[:project_name] + @project_url = params[:project_url] + @status = params[:commit][:status] + @user_name = params[:commit][:author_name] + @duration = params[:commit][:duration] + end + + def pretext + '' + end + + def fallback + format(message) + end + + def attachments + [{ text: format(message), color: attachment_color }] + end + + private + + def message + "#{project_link}: Commit #{commit_link} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status} in #{duration} second(s)" + end + + def format(string) + Slack::Notifier::LinkFormatter.format(string) + end + + def humanized_status + case status + when 'success' + 'passed' + else + status + end + end + + def attachment_color + if status == 'success' + 'good' + else + 'danger' + end + end + + def branch_url + "#{project_url}/commits/#{ref}" + end + + def branch_link + "[#{ref}](#{branch_url})" + end + + def project_link + "[#{project_name}](#{project_url})" + end + + def commit_url + "#{project_url}/commit/#{sha}/builds" + end + + def commit_link + "[#{Commit.truncate_sha(sha)}](#{commit_url})" + end + end +end diff --git a/app/models/project_services/slack_service/note_message.rb b/app/models/project_services/slack_service/note_message.rb index 074478b292..b15d9a1467 100644 --- a/app/models/project_services/slack_service/note_message.rb +++ b/app/models/project_services/slack_service/note_message.rb @@ -45,30 +45,27 @@ class SlackService def create_commit_note(commit) commit_sha = commit[:id] commit_sha = Commit.truncate_sha(commit_sha) - commit_link = "[commit #{commit_sha}](#{@note_url})" - title = format_title(commit[:message]) - @message = "#{@user_name} commented on #{commit_link} in #{project_link}: *#{title}*" + commented_on_message( + "[commit #{commit_sha}](#{@note_url})", + format_title(commit[:message])) end def create_issue_note(issue) - issue_iid = issue[:iid] - note_link = "[issue ##{issue_iid}](#{@note_url})" - title = format_title(issue[:title]) - @message = "#{@user_name} commented on #{note_link} in #{project_link}: *#{title}*" + commented_on_message( + "[issue ##{issue[:iid]}](#{@note_url})", + format_title(issue[:title])) end def create_merge_note(merge_request) - merge_request_id = merge_request[:iid] - merge_request_link = "[merge request ##{merge_request_id}](#{@note_url})" - title = format_title(merge_request[:title]) - @message = "#{@user_name} commented on #{merge_request_link} in #{project_link}: *#{title}*" + commented_on_message( + "[merge request ##{merge_request[:iid]}](#{@note_url})", + format_title(merge_request[:title])) end def create_snippet_note(snippet) - snippet_id = snippet[:id] - snippet_link = "[snippet ##{snippet_id}](#{@note_url})" - title = format_title(snippet[:title]) - @message = "#{@user_name} commented on #{snippet_link} in #{project_link}: *#{title}*" + commented_on_message( + "[snippet ##{snippet[:id]}](#{@note_url})", + format_title(snippet[:title])) end def description_message @@ -78,5 +75,9 @@ class SlackService def project_link "[#{@project_name}](#{@project_url})" end + + def commented_on_message(target_link, title) + @message = "#{@user_name} commented on #{target_link} in #{project_link}: *#{title}*" + end end end diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb index 0b02246125..a63700693d 100644 --- a/app/models/project_services/teamcity_service.rb +++ b/app/models/project_services/teamcity_service.rb @@ -23,16 +23,14 @@ class TeamcityService < CiService prop_accessor :teamcity_url, :build_type, :username, :password - validates :teamcity_url, - presence: true, - format: { with: /\A#{URI.regexp}\z/ }, if: :activated? + validates :teamcity_url, presence: true, url: true, if: :activated? validates :build_type, presence: true, if: :activated? validates :username, presence: true, - if: ->(service) { service.password? }, if: :activated? + if: ->(service) { service.activated? && service.password } validates :password, presence: true, - if: ->(service) { service.username? }, if: :activated? + if: ->(service) { service.activated? && service.username } attr_accessor :response @@ -147,6 +145,6 @@ class TeamcityService < CiService '', headers: { 'Content-type' => 'application/xml' }, basic_auth: auth - ) + ) end end diff --git a/app/models/repository.rb b/app/models/repository.rb index c183610346..2c25f4ce45 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -1,7 +1,6 @@ require 'securerandom' class Repository - class PreReceiveError < StandardError; end class CommitError < StandardError; end include Gitlab::ShellAdapter @@ -101,17 +100,26 @@ class Repository end def find_branch(name) - branches.find { |branch| branch.name == name } + raw_repository.branches.find { |branch| branch.name == name } end def find_tag(name) - tags.find { |tag| tag.name == name } + raw_repository.tags.find { |tag| tag.name == name } end - def add_branch(branch_name, ref) - expire_branches_cache + def add_branch(user, branch_name, target) + oldrev = Gitlab::Git::BLANK_SHA + ref = Gitlab::Git::BRANCH_REF_PREFIX + branch_name + target = commit(target).try(:id) - gitlab_shell.add_branch(path_with_namespace, branch_name, ref) + return false unless target + + GitHooksService.new.execute(user, path_to_repo, oldrev, target, ref) do + rugged.branches.create(branch_name, target) + end + + expire_branches_cache + find_branch(branch_name) end def add_tag(tag_name, ref, message = nil) @@ -120,10 +128,20 @@ class Repository gitlab_shell.add_tag(path_with_namespace, tag_name, ref, message) end - def rm_branch(branch_name) + def rm_branch(user, branch_name) expire_branches_cache - gitlab_shell.rm_branch(path_with_namespace, branch_name) + branch = find_branch(branch_name) + oldrev = branch.try(:target) + newrev = Gitlab::Git::BLANK_SHA + ref = Gitlab::Git::BRANCH_REF_PREFIX + branch_name + + GitHooksService.new.execute(user, path_to_repo, oldrev, newrev, ref) do + rugged.branches.delete(branch_name) + end + + expire_branches_cache + true end def rm_tag(tag_name) @@ -253,9 +271,25 @@ class Repository def license cache.fetch(:license) do - tree(:head).blobs.find do |file| - file.name =~ /\Alicense/i + licenses = tree(:head).blobs.find_all do |file| + file.name =~ /\A(copying|license|licence)/i + end + + preferences = [ + /\Alicen[sc]e\z/i, # LICENSE, LICENCE + /\Alicen[sc]e\./i, # LICENSE.md, LICENSE.txt + /\Acopying\z/i, # COPYING + /\Acopying\.(?!lesser)/i, # COPYING.txt + /Acopying.lesser/i # COPYING.LESSER + ] + + license = nil + preferences.each do |r| + license = licenses.find { |l| l.name =~ r } + break if license end + + license end end @@ -311,6 +345,17 @@ class Repository commit(sha) end + def next_patch_branch + patch_branch_ids = self.branch_names.map do |n| + result = n.match(/\Apatch-([0-9]+)\z/) + result[1].to_i if result + end.compact + + highest_patch_branch_id = patch_branch_ids.max || 0 + + "patch-#{highest_patch_branch_id + 1}" + end + # Remove archives older than 2 hours def branches_sorted_by(value) case value @@ -550,7 +595,6 @@ class Repository def commit_with_hooks(current_user, branch) oldrev = Gitlab::Git::BLANK_SHA ref = Gitlab::Git::BRANCH_REF_PREFIX + branch - gl_id = Gitlab::ShellEnv.gl_id(current_user) was_empty = empty? # Create temporary ref @@ -569,11 +613,7 @@ class Repository raise CommitError.new('Failed to create commit') end - # Run GitLab pre-receive hook - pre_receive_hook = Gitlab::Git::Hook.new('pre-receive', path_to_repo) - status = pre_receive_hook.trigger(gl_id, oldrev, newrev, ref) - - if status + GitHooksService.new.execute(current_user, path_to_repo, oldrev, newrev, ref) do if was_empty # Create branch rugged.references.create(ref, newrev) @@ -588,16 +628,11 @@ class Repository raise CommitError.new('Commit was rejected because branch received new push') end end - - # Run GitLab post receive hook - post_receive_hook = Gitlab::Git::Hook.new('post-receive', path_to_repo) - post_receive_hook.trigger(gl_id, oldrev, newrev, ref) - else - # Remove tmp ref and return error to user - rugged.references.delete(tmp_ref) - - raise PreReceiveError.new('Commit was rejected by pre-receive hook') end + rescue GitHooksService::PreReceiveError + # Remove tmp ref and return error to user + rugged.references.delete(tmp_ref) + raise end private diff --git a/app/models/sent_notification.rb b/app/models/sent_notification.rb index 3eed5c16e4..f36eda1531 100644 --- a/app/models/sent_notification.rb +++ b/app/models/sent_notification.rb @@ -17,12 +17,11 @@ class SentNotification < ActiveRecord::Base belongs_to :noteable, polymorphic: true belongs_to :recipient, class_name: "User" - validate :project, :recipient, :reply_key, presence: true - validate :reply_key, uniqueness: true - + validates :project, :recipient, :reply_key, presence: true + validates :reply_key, uniqueness: true validates :noteable_id, presence: true, unless: :for_commit? validates :commit_id, presence: true, if: :for_commit? - validates :line_code, format: { with: /\A[a-z0-9]+_\d+_\d+\Z/ }, allow_blank: true + validates :line_code, line_code: true, allow_blank: true class << self def reply_key diff --git a/app/models/service.rb b/app/models/service.rb index d610abd168..d3bf7f0ebd 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -30,6 +30,7 @@ class Service < ActiveRecord::Base default_value_for :merge_requests_events, true default_value_for :tag_push_events, true default_value_for :note_events, true + default_value_for :build_events, true after_initialize :initialize_properties @@ -40,13 +41,14 @@ class Service < ActiveRecord::Base validates :project_id, presence: true, unless: Proc.new { |service| service.template? } - scope :visible, -> { where.not(type: 'GitlabIssueTrackerService') } + scope :visible, -> { where.not(type: ['GitlabIssueTrackerService', 'GitlabCiService']) } scope :push_hooks, -> { where(push_events: true, active: true) } scope :tag_push_hooks, -> { where(tag_push_events: true, active: true) } scope :issue_hooks, -> { where(issues_events: true, active: true) } scope :merge_request_hooks, -> { where(merge_requests_events: true, active: true) } scope :note_hooks, -> { where(note_events: true, active: true) } + scope :build_hooks, -> { where(build_events: true, active: true) } def activated? active @@ -133,6 +135,21 @@ class Service < ActiveRecord::Base end end + # Provide convenient boolean accessor methods + # for each serialized property. + # Also keep track of updated properties in a similar way as ActiveModel::Dirty + def self.boolean_accessor(*args) + self.prop_accessor(*args) + + args.each do |arg| + class_eval %{ + def #{arg}? + ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include?(#{arg}) + end + } + end + end + # Returns a hash of the properties that have been assigned a new value since last save, # indicating their original values (attr => original value). # ActiveRecord does not provide a mechanism to track changes in serialized keys, @@ -163,6 +180,7 @@ class Service < ActiveRecord::Base assembla bamboo buildkite + builds_email campfire custom_issue_tracker drone_ci @@ -170,7 +188,6 @@ class Service < ActiveRecord::Base external_wiki flowdock gemnasium - gitlab_ci hipchat irker jira diff --git a/app/models/snippet.rb b/app/models/snippet.rb index b0831982aa..f876be7a4c 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -65,6 +65,10 @@ class Snippet < ActiveRecord::Base }x end + def self.link_reference_pattern + super("snippets", /(?\d+)/) + end + def to_reference(from_project = nil) reference = "#{self.class.reference_prefix}#{id}" diff --git a/app/models/user.rb b/app/models/user.rb index 9374f01f99..df87f3b79b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -26,6 +26,7 @@ # bio :string(255) # failed_attempts :integer default(0) # locked_at :datetime +# unlock_token :string(255) # username :string(255) # can_create_group :boolean default(TRUE), not null # can_create_team :boolean default(TRUE), not null @@ -56,6 +57,7 @@ # project_view :integer default(0) # consumed_timestep :integer # layout :integer default(0) +# hide_project_limit :boolean default(FALSE) # require 'carrierwave/orm/activerecord' @@ -68,8 +70,10 @@ class User < ActiveRecord::Base include Gitlab::CurrentSettings include Referable include Sortable - include TokenAuthenticatable include CaseSensitivity + include TokenAuthenticatable + + add_authentication_token_field :authentication_token default_value_for :admin, false default_value_for :can_create_group, gitlab_config.default_can_create_group @@ -133,7 +137,7 @@ class User < ActiveRecord::Base has_many :assigned_merge_requests, dependent: :destroy, foreign_key: :assignee_id, class_name: "MergeRequest" has_many :oauth_applications, class_name: 'Doorkeeper::Application', as: :owner, dependent: :destroy has_one :abuse_report, dependent: :destroy - has_many :ci_builds, dependent: :nullify, class_name: 'Ci::Build' + has_many :builds, dependent: :nullify, class_name: 'Ci::Build' # @@ -148,11 +152,9 @@ class User < ActiveRecord::Base validates :bio, length: { maximum: 255 }, allow_blank: true validates :projects_limit, presence: true, numericality: { greater_than_or_equal_to: 0 } validates :username, + namespace: true, presence: true, - uniqueness: { case_sensitive: false }, - exclusion: { in: Gitlab::Blacklist.path }, - format: { with: Gitlab::Regex.namespace_regex, - message: Gitlab::Regex.namespace_regex_message } + uniqueness: { case_sensitive: false } validates :notification_level, inclusion: { in: Notification.notification_levels }, presence: true validate :namespace_uniq, if: ->(user) { user.username_changed? } @@ -219,9 +221,9 @@ class User < ActiveRecord::Base def find_for_database_authentication(warden_conditions) conditions = warden_conditions.dup if login = conditions.delete(:login) - where(conditions).where(["lower(username) = :value OR lower(email) = :value", { value: login.downcase }]).first + where(conditions).find_by("lower(username) = :value OR lower(email) = :value", value: login.downcase) else - where(conditions).first + find_by(conditions) end end @@ -284,7 +286,7 @@ class User < ActiveRecord::Base end def by_username_or_id(name_or_id) - where('users.username = ? OR users.id = ?', name_or_id.to_s, name_or_id.to_i).first + find_by('users.username = ? OR users.id = ?', name_or_id.to_s, name_or_id.to_i) end def build_user(attrs = {}) @@ -637,11 +639,11 @@ class User < ActiveRecord::Base email.start_with?('temp-email-for-oauth') end - def avatar_url(size = nil) + def avatar_url(size = nil, scale = 2) if avatar.present? [gitlab_config.url, avatar.url].join else - GravatarService.new.execute(email, size) + GravatarService.new.execute(email, size, scale) end end @@ -690,7 +692,7 @@ class User < ActiveRecord::Base end def starred?(project) - starred_projects.exists?(project) + starred_projects.exists?(project.id) end def toggle_star(project) @@ -770,10 +772,9 @@ class User < ActiveRecord::Base def ci_authorized_runners @ci_authorized_runners ||= begin - runner_ids = Ci::RunnerProject.joins(:project). - where("ci_projects.gitlab_id IN (#{ci_projects_union.to_sql})"). + runner_ids = Ci::RunnerProject. + where("ci_runner_projects.gl_project_id IN (#{ci_projects_union.to_sql})"). select(:runner_id) - Ci::Runner.specific.where(id: runner_ids) end end @@ -794,4 +795,9 @@ class User < ActiveRecord::Base Gitlab::SQL::Union.new([personal_projects.select(:id), groups.select(:id), other.select(:id)]) end + + # Added according to https://github.com/plataformatec/devise/blob/7df57d5081f9884849ca15e4fde179ef164a575f/README.md#activejob-integration + def send_devise_notification(notification, *args) + devise_mailer.send(notification, self, *args).deliver_later + end end diff --git a/app/models/users_star_project.rb b/app/models/users_star_project.rb index 3d49cb0594..413f3f485a 100644 --- a/app/models/users_star_project.rb +++ b/app/models/users_star_project.rb @@ -10,7 +10,7 @@ # class UsersStarProject < ActiveRecord::Base - belongs_to :project, counter_cache: :star_count + belongs_to :project, counter_cache: :star_count, touch: true belongs_to :user validates :user, presence: true diff --git a/app/services/ci/create_builds_service.rb b/app/services/ci/create_builds_service.rb index 912eb6258a..ad901f2da5 100644 --- a/app/services/ci/create_builds_service.rb +++ b/app/services/ci/create_builds_service.rb @@ -29,9 +29,11 @@ module Ci build_attrs.merge!(ref: ref, tag: tag, trigger_request: trigger_request, - user: user) + user: user, + project: commit.project) - commit.builds.create!(build_attrs) + build = commit.builds.create!(build_attrs) + build.execute_hooks end end end diff --git a/app/services/ci/create_commit_service.rb b/app/services/ci/create_commit_service.rb deleted file mode 100644 index 479a2d6def..0000000000 --- a/app/services/ci/create_commit_service.rb +++ /dev/null @@ -1,28 +0,0 @@ -module Ci - class CreateCommitService - def execute(project, user, params) - sha = params[:checkout_sha] || params[:after] - origin_ref = params[:ref] - - unless origin_ref && sha.present? - return false - end - - ref = origin_ref.gsub(/\Arefs\/(tags|heads)\//, '') - - # Skip branch removal - if sha == Ci::Git::BLANK_SHA - return false - end - - tag = origin_ref.start_with?('refs/tags/') - commit = project.gl_project.ensure_ci_commit(sha) - unless commit.skip_ci? - commit.update_committed! - commit.create_builds(ref, tag, user) - end - - commit - end - end -end diff --git a/app/services/ci/create_trigger_request_service.rb b/app/services/ci/create_trigger_request_service.rb index 4b86cb0a1f..b3dfc70722 100644 --- a/app/services/ci/create_trigger_request_service.rb +++ b/app/services/ci/create_trigger_request_service.rb @@ -1,13 +1,13 @@ module Ci class CreateTriggerRequestService def execute(project, trigger, ref, variables = nil) - commit = project.gl_project.commit(ref) + commit = project.commit(ref) return unless commit # check if ref is tag - tag = project.gl_project.repository.find_tag(ref).present? + tag = project.repository.find_tag(ref).present? - ci_commit = project.gl_project.ensure_ci_commit(commit.sha) + ci_commit = project.ensure_ci_commit(commit.sha) trigger_request = trigger.trigger_requests.create!( variables: variables, diff --git a/app/services/ci/event_service.rb b/app/services/ci/event_service.rb deleted file mode 100644 index 3f4e02dd26..0000000000 --- a/app/services/ci/event_service.rb +++ /dev/null @@ -1,31 +0,0 @@ -module Ci - class EventService - def remove_project(user, project) - create( - description: "Project \"#{project.name}\" has been removed by #{user.username}", - user_id: user.id, - is_admin: true - ) - end - - def create_project(user, project) - create( - description: "Project \"#{project.name}\" has been created by #{user.username}", - user_id: user.id, - is_admin: true - ) - end - - def change_project_settings(user, project) - create( - project_id: project.id, - user_id: user.id, - description: "User \"#{user.username}\" updated projects settings" - ) - end - - def create(*args) - Ci::Event.create!(*args) - end - end -end diff --git a/app/services/ci/image_for_build_service.rb b/app/services/ci/image_for_build_service.rb index b8d2419303..f469b13e90 100644 --- a/app/services/ci/image_for_build_service.rb +++ b/app/services/ci/image_for_build_service.rb @@ -4,10 +4,10 @@ module Ci sha = params[:sha] sha ||= if params[:ref] - project.gl_project.commit(params[:ref]).try(:sha) + project.commit(params[:ref]).try(:sha) end - commit = project.commits.ordered.find_by(sha: sha) + commit = project.ci_commits.ordered.find_by(sha: sha) image_name = image_for_commit(commit) image_path = Rails.root.join('public/ci', image_name) diff --git a/app/services/ci/register_build_service.rb b/app/services/ci/register_build_service.rb index 7beb098659..4ff268a6f0 100644 --- a/app/services/ci/register_build_service.rb +++ b/app/services/ci/register_build_service.rb @@ -8,10 +8,10 @@ module Ci builds = if current_runner.shared? # don't run projects which have not enables shared runners - builds.joins(commit: { gl_project: :gitlab_ci_project }).where(ci_projects: { shared_runners_enabled: true }) + builds.joins(:project).where(projects: { builds_enabled: true, shared_runners_enabled: true }) else # do run projects which are only assigned to this runner - builds.joins(:commit).where(ci_commits: { gl_project_id: current_runner.gl_projects_ids }) + builds.where(project: current_runner.projects.where(builds_enabled: true)) end builds = builds.order('created_at ASC') @@ -20,10 +20,9 @@ module Ci build.can_be_served?(current_runner) end - if build # In case when 2 runners try to assign the same build, second runner will be declined - # with StateMachine::InvalidTransition in run! method. + # with StateMachines::InvalidTransition in run! method. build.with_lock do build.runner_id = current_runner.id build.save! @@ -33,7 +32,7 @@ module Ci build - rescue StateMachine::InvalidTransition + rescue StateMachines::InvalidTransition nil end end diff --git a/app/services/ci/test_hook_service.rb b/app/services/ci/test_hook_service.rb deleted file mode 100644 index 3a17596aae..0000000000 --- a/app/services/ci/test_hook_service.rb +++ /dev/null @@ -1,7 +0,0 @@ -module Ci - class TestHookService - def execute(hook, current_user) - Ci::WebHookService.new.build_end(hook.project.commits.last.last_build) - end - end -end diff --git a/app/services/create_branch_service.rb b/app/services/create_branch_service.rb index cf7ae4345f..de18f3bc55 100644 --- a/app/services/create_branch_service.rb +++ b/app/services/create_branch_service.rb @@ -13,8 +13,7 @@ class CreateBranchService < BaseService return error('Branch already exists') end - repository.add_branch(branch_name, ref) - new_branch = repository.find_branch(branch_name) + new_branch = repository.add_branch(current_user, branch_name, ref) if new_branch push_data = build_push_data(project, current_user, new_branch) @@ -27,6 +26,8 @@ class CreateBranchService < BaseService else error('Invalid reference name') end + rescue GitHooksService::PreReceiveError + error('Branch creation was rejected by Git hook') end def success(branch) diff --git a/app/services/create_commit_builds_service.rb b/app/services/create_commit_builds_service.rb new file mode 100644 index 0000000000..31b407efeb --- /dev/null +++ b/app/services/create_commit_builds_service.rb @@ -0,0 +1,42 @@ +class CreateCommitBuildsService + def execute(project, user, params) + return false unless project.builds_enabled? + + sha = params[:checkout_sha] || params[:after] + origin_ref = params[:ref] + + unless origin_ref && sha.present? + return false + end + + ref = Gitlab::Git.ref_name(origin_ref) + + # Skip branch removal + if sha == Gitlab::Git::BLANK_SHA + return false + end + + commit = project.ci_commit(sha) + unless commit + commit = project.ci_commits.new(sha: sha) + + # Skip creating ci_commit when no gitlab-ci.yml is found + unless commit.ci_yaml_file + return false + end + + # Create a new ci_commit + commit.save! + end + + # Skip creating builds for commits that have [ci skip] + unless commit.skip_ci? + # Create builds for commit + tag = Gitlab::Git.tag_ref?(origin_ref) + commit.update_committed! + commit.create_builds(ref, tag, user) + end + + commit + end +end diff --git a/app/services/delete_branch_service.rb b/app/services/delete_branch_service.rb index b19b112a0c..22bf9dd935 100644 --- a/app/services/delete_branch_service.rb +++ b/app/services/delete_branch_service.rb @@ -24,7 +24,7 @@ class DeleteBranchService < BaseService return error('You dont have push access to repo', 405) end - if repository.rm_branch(branch_name) + if repository.rm_branch(current_user, branch_name) push_data = build_push_data(branch) EventCreateService.new.push(project, current_user, push_data) @@ -35,6 +35,8 @@ class DeleteBranchService < BaseService else error('Failed to remove branch') end + rescue GitHooksService::PreReceiveError + error('Branch deletion was rejected by Git hook') end def error(message, return_code = 400) diff --git a/app/services/files/base_service.rb b/app/services/files/base_service.rb index 008833eed8..9a67b16094 100644 --- a/app/services/files/base_service.rb +++ b/app/services/files/base_service.rb @@ -26,7 +26,7 @@ module Files else error("Something went wrong. Your changes were not committed") end - rescue Repository::CommitError, Repository::PreReceiveError, ValidationError => ex + rescue Repository::CommitError, GitHooksService::PreReceiveError, ValidationError => ex error(ex.message) end @@ -53,7 +53,7 @@ module Files unless project.empty_repo? unless repository.branch_names.include?(@current_branch) - raise_error("You can only create files if you are on top of a branch") + raise_error("You can only create or edit files when you are on a branch") end if @current_branch != @target_branch diff --git a/app/services/git_hooks_service.rb b/app/services/git_hooks_service.rb new file mode 100644 index 0000000000..8f5c3393df --- /dev/null +++ b/app/services/git_hooks_service.rb @@ -0,0 +1,28 @@ +class GitHooksService + PreReceiveError = Class.new(StandardError) + + def execute(user, repo_path, oldrev, newrev, ref) + @repo_path = repo_path + @user = Gitlab::ShellEnv.gl_id(user) + @oldrev = oldrev + @newrev = newrev + @ref = ref + + %w(pre-receive update).each do |hook_name| + unless run_hook(hook_name) + raise PreReceiveError.new("Git operation was rejected by #{hook_name} hook") + end + end + + yield + + run_hook('post-receive') + end + + private + + def run_hook(name) + hook = Gitlab::Git::Hook.new(name, @repo_path) + hook.trigger(@user, @oldrev, @newrev, @ref) + end +end diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index f11690aa3f..d7ea30bc31 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -61,6 +61,7 @@ class GitPushService EventCreateService.new.push(project, user, @push_data) project.execute_hooks(@push_data.dup, :push_hooks) project.execute_services(@push_data.dup, :push_hooks) + CreateCommitBuildsService.new.execute(project, @user, @push_data) ProjectCacheWorker.perform_async(project.id) end diff --git a/app/services/git_tag_push_service.rb b/app/services/git_tag_push_service.rb index 1cc42b0b0a..4144c7111d 100644 --- a/app/services/git_tag_push_service.rb +++ b/app/services/git_tag_push_service.rb @@ -10,6 +10,7 @@ class GitTagPushService EventCreateService.new.push(project, user, @push_data) project.execute_hooks(@push_data.dup, :tag_push_hooks) project.execute_services(@push_data.dup, :tag_push_hooks) + CreateCommitBuildsService.new.execute(project, @user, @push_data) ProjectCacheWorker.perform_async(project.id) true diff --git a/app/services/gravatar_service.rb b/app/services/gravatar_service.rb index 4bee0c26a6..433ecc2df3 100644 --- a/app/services/gravatar_service.rb +++ b/app/services/gravatar_service.rb @@ -1,13 +1,13 @@ class GravatarService include Gitlab::CurrentSettings - def execute(email, size = nil) + def execute(email, size = nil, scale = 2) if current_application_settings.gravatar_enabled? && email.present? size = 40 if size.nil? || size <= 0 sprintf gravatar_url, hash: Digest::MD5.hexdigest(email.strip.downcase), - size: size, + size: size * scale, email: email.strip end end diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb index 15b3825f96..2556f06e2d 100644 --- a/app/services/issuable_base_service.rb +++ b/app/services/issuable_base_service.rb @@ -27,7 +27,16 @@ class IssuableBaseService < BaseService old_branch, new_branch) end + def create_task_status_note(issuable) + issuable.updated_tasks.each do |task| + SystemNoteService.change_task_status(issuable, issuable.project, current_user, task) + end + end + def filter_params(issuable_ability_name = :issue) + params[:assignee_id] = "" if params[:assignee_id] == IssuableFinder::NONE + params[:milestone_id] = "" if params[:milestone_id] == IssuableFinder::NONE + ability = :"admin_#{issuable_ability_name}" unless can?(current_user, ability, project) @@ -36,4 +45,44 @@ class IssuableBaseService < BaseService params.delete(:assignee_id) end end + + def update(issuable) + change_state(issuable) + filter_params + old_labels = issuable.labels.to_a + + if params.present? && issuable.update_attributes(params.merge(updated_by: current_user)) + issuable.reset_events_cache + handle_common_system_notes(issuable, old_labels: old_labels) + handle_changes(issuable) + issuable.create_new_cross_references!(current_user) + execute_hooks(issuable, 'update') + end + + issuable + end + + def change_state(issuable) + case params.delete(:state_event) + when 'reopen' + reopen_service.new(project, current_user, {}).execute(issuable) + when 'close' + close_service.new(project, current_user, {}).execute(issuable) + end + end + + def handle_common_system_notes(issuable, options = {}) + if issuable.previous_changes.include?('title') + create_title_change_note(issuable, issuable.previous_changes['title'].first) + end + + if issuable.previous_changes.include?('description') && issuable.tasks? + create_task_status_note(issuable) + end + + old_labels = options[:old_labels] + if old_labels && (issuable.labels != old_labels) + create_labels_note(issuable, issuable.labels - old_labels, old_labels - issuable.labels) + end + end end diff --git a/app/services/issues/close_service.rb b/app/services/issues/close_service.rb index 3d85f97b7e..a1a20e4768 100644 --- a/app/services/issues/close_service.rb +++ b/app/services/issues/close_service.rb @@ -1,6 +1,11 @@ module Issues class CloseService < Issues::BaseService def execute(issue, commit = nil) + if project.jira_tracker? && project.jira_service.active + project.jira_service.execute(commit, issue) + return issue + end + if project.default_issues_tracker? && issue.close event_service.close_issue(issue, current_user) create_note(issue, commit) diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb index aa1fd79d22..a55a04dd5e 100644 --- a/app/services/issues/update_service.rb +++ b/app/services/issues/update_service.rb @@ -1,33 +1,7 @@ module Issues class UpdateService < Issues::BaseService def execute(issue) - case params.delete(:state_event) - when 'reopen' - Issues::ReopenService.new(project, current_user, {}).execute(issue) - when 'close' - Issues::CloseService.new(project, current_user, {}).execute(issue) - end - - params[:assignee_id] = "" if params[:assignee_id] == IssuableFinder::NONE - params[:milestone_id] = "" if params[:milestone_id] == IssuableFinder::NONE - - filter_params - old_labels = issue.labels.to_a - - if params.present? && issue.update_attributes(params.merge(updated_by: current_user)) - issue.reset_events_cache - - if issue.labels != old_labels - create_labels_note( - issue, issue.labels - old_labels, old_labels - issue.labels) - end - - handle_changes(issue) - issue.create_new_cross_references!(current_user) - execute_hooks(issue, 'update') - end - - issue + update(issue) end def handle_changes(issue) @@ -39,10 +13,14 @@ module Issues create_assignee_note(issue) notification_service.reassigned_issue(issue, current_user) end + end - if issue.previous_changes.include?('title') - create_title_change_note(issue, issue.previous_changes['title'].first) - end + def reopen_service + Issues::ReopenService + end + + def close_service + Issues::CloseService end end end diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb index 7963af127e..cabc3d8fab 100644 --- a/app/services/merge_requests/merge_service.rb +++ b/app/services/merge_requests/merge_service.rb @@ -6,15 +6,12 @@ module MergeRequests # Executed when you do merge via GitLab UI # class MergeService < MergeRequests::BaseService - attr_reader :merge_request, :commit_message + attr_reader :merge_request - def execute(merge_request, commit_message) - @commit_message = commit_message + def execute(merge_request) @merge_request = merge_request - unless @merge_request.mergeable? - return error('Merge request is not mergeable') - end + return error('Merge request is not mergeable') unless @merge_request.mergeable? merge_request.in_locked_state do if commit @@ -32,13 +29,13 @@ module MergeRequests committer = repository.user_to_committer(current_user) options = { - message: commit_message, + message: params[:commit_message] || merge_request.merge_commit_message, author: committer, committer: committer } repository.merge(current_user, merge_request.source_sha, merge_request.target_branch, options) - rescue Exception => e + rescue StandardError => e merge_request.update(merge_error: "Something went wrong during merge") Rails.logger.error(e.message) return false @@ -46,6 +43,11 @@ module MergeRequests def after_merge MergeRequests::PostMergeService.new(project, current_user).execute(merge_request) + + if params[:should_remove_source_branch] + DeleteBranchService.new(@merge_request.source_project, current_user). + execute(merge_request.source_branch) + end end end end diff --git a/app/services/merge_requests/merge_when_build_succeeds_service.rb b/app/services/merge_requests/merge_when_build_succeeds_service.rb new file mode 100644 index 0000000000..5cf7404a49 --- /dev/null +++ b/app/services/merge_requests/merge_when_build_succeeds_service.rb @@ -0,0 +1,55 @@ +module MergeRequests + class MergeWhenBuildSucceedsService < MergeRequests::BaseService + # Marks the passed `merge_request` to be merged when the build succeeds or + # updates the params for the automatic merge + def execute(merge_request) + merge_request.merge_params.merge!(params) + + # The service is also called when the merge params are updated. + already_approved = merge_request.merge_when_build_succeeds? + + unless already_approved + merge_request.merge_when_build_succeeds = true + merge_request.merge_user = @current_user + + SystemNoteService.merge_when_build_succeeds(merge_request, @project, @current_user, merge_request.last_commit) + end + + merge_request.save + end + + # Triggers the automatic merge of merge_request once the build succeeds + def trigger(build) + merge_requests = merge_request_from(build) + + merge_requests.each do |merge_request| + next unless merge_request.merge_when_build_succeeds? + + if merge_request.ci_commit && merge_request.ci_commit.success? && merge_request.mergeable? + MergeWorker.perform_async(merge_request.id, merge_request.merge_user_id, merge_request.merge_params) + end + end + end + + # Cancels the automatic merge + def cancel(merge_request) + if merge_request.merge_when_build_succeeds? && merge_request.open? + merge_request.reset_merge_when_build_succeeds + SystemNoteService.cancel_merge_when_build_succeeds(merge_request, @project, @current_user) + + success + else + error("Can't cancel the automatic merge", 406) + end + end + + private + + def merge_request_from(build) + merge_requests = @project.origin_merge_requests.opened.where(source_branch: build.ref).to_a + merge_requests += @project.fork_merge_requests.opened.where(source_branch: build.ref).to_a + + merge_requests.uniq.select(&:source_project) + end + end +end diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb index e180edb4bf..8b3d56c2b4 100644 --- a/app/services/merge_requests/refresh_service.rb +++ b/app/services/merge_requests/refresh_service.rb @@ -11,6 +11,7 @@ module MergeRequests # empty diff during a manual merge close_merge_requests reload_merge_requests + reset_merge_when_build_succeeds # Leave a system note if a branch was deleted/added if branch_added? || branch_removed? @@ -57,7 +58,6 @@ module MergeRequests merge_requests = filter_merge_requests(merge_requests) merge_requests.each do |merge_request| - if merge_request.source_branch == @branch_name || force_push? merge_request.reload_code merge_request.mark_as_unchecked @@ -76,6 +76,10 @@ module MergeRequests end end + def reset_merge_when_build_succeeds + merge_requests_for_source_branch.each(&:reset_merge_when_build_succeeds) + end + def find_new_commits if branch_added? @commits = [] @@ -108,7 +112,7 @@ module MergeRequests merge_requests_for_source_branch.each do |merge_request| SystemNoteService.change_branch_presence( - merge_request, merge_request.project, @current_user, + merge_request, merge_request.project, @current_user, :source, @branch_name, presence) end end diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb index d2849e5193..5ff2cc03dd 100644 --- a/app/services/merge_requests/update_service.rb +++ b/app/services/merge_requests/update_service.rb @@ -11,36 +11,7 @@ module MergeRequests params.except!(:target_project_id) params.except!(:source_branch) - case params.delete(:state_event) - when 'reopen' - MergeRequests::ReopenService.new(project, current_user, {}).execute(merge_request) - when 'close' - MergeRequests::CloseService.new(project, current_user, {}).execute(merge_request) - end - - params[:assignee_id] = "" if params[:assignee_id] == IssuableFinder::NONE - params[:milestone_id] = "" if params[:milestone_id] == IssuableFinder::NONE - - filter_params - old_labels = merge_request.labels.to_a - - if params.present? && merge_request.update_attributes(params.merge(updated_by: current_user)) - merge_request.reset_events_cache - - if merge_request.labels != old_labels - create_labels_note( - merge_request, - merge_request.labels - old_labels, - old_labels - merge_request.labels - ) - end - - handle_changes(merge_request) - merge_request.create_new_cross_references!(current_user) - execute_hooks(merge_request, 'update') - end - - merge_request + update(merge_request) end def handle_changes(merge_request) @@ -59,14 +30,18 @@ module MergeRequests notification_service.reassigned_merge_request(merge_request, current_user) end - if merge_request.previous_changes.include?('title') - create_title_change_note(merge_request, merge_request.previous_changes['title'].first) - end - if merge_request.previous_changes.include?('target_branch') || merge_request.previous_changes.include?('source_branch') merge_request.mark_as_unchecked end end + + def reopen_service + MergeRequests::ReopenService + end + + def close_service + MergeRequests::CloseService + end end end diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb index dbff58dfb9..a8486e6a5a 100644 --- a/app/services/notes/create_service.rb +++ b/app/services/notes/create_service.rb @@ -5,11 +5,6 @@ module Notes note.author = current_user note.system = false - if contains_emoji_only?(params[:note]) - note.is_award = true - note.note = emoji_name(params[:note]) - end - if note.save notification_service.new_note(note) @@ -33,13 +28,5 @@ module Notes note.project.execute_hooks(note_data, :note_hooks) note.project.execute_services(note_data, :note_hooks) end - - def contains_emoji_only?(note) - note =~ /\A:[-_+[:alnum:]]*:\s?\z/ - end - - def emoji_name(note) - note.match(/\A:([-_+[:alnum:]]*):\s?/)[1] - end end end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index dc78f85105..bdf7b3ad2b 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -13,14 +13,14 @@ class NotificationService # even if user disabled notifications def new_key(key) if key.user - mailer.new_ssh_key_email(key.id) + mailer.new_ssh_key_email(key.id).deliver_later end end # Always notify user about email added to profile def new_email(email) if email.user - mailer.new_email_email(email.id) + mailer.new_email_email(email.id).deliver_later end end @@ -79,17 +79,27 @@ class NotificationService end def merge_mr(merge_request, current_user) - close_resource_email(merge_request, merge_request.target_project, current_user, 'merged_merge_request_email') + close_resource_email( + merge_request, + merge_request.target_project, + current_user, + 'merged_merge_request_email' + ) end def reopen_mr(merge_request, current_user) - reopen_resource_email(merge_request, merge_request.target_project, current_user, 'merge_request_status_email', 'reopened') + reopen_resource_email( + merge_request, + merge_request.target_project, + current_user, 'merge_request_status_email', + 'reopened' + ) end # Notify new user with email after creation def new_user(user, token = nil) # Don't email omniauth created users - mailer.new_user_email(user.id, token) unless user.identities.any? + mailer.new_user_email(user.id, token).deliver_later unless user.identities.any? end # Notify users on new note in system @@ -114,7 +124,7 @@ class NotificationService end # Add all users participating in the thread (author, assignee, comment authors) - participants = + participants = if target.respond_to?(:participants) target.participants(note.author) else @@ -135,53 +145,63 @@ class NotificationService recipients = reject_unsubscribed_users(recipients, note.noteable) recipients.delete(note.author) + recipients = recipients.uniq # build notify method like 'note_commit_email' notify_method = "note_#{note.noteable_type.underscore}_email".to_sym - recipients.each do |recipient| - mailer.send(notify_method, recipient.id, note.id) + mailer.send(notify_method, recipient.id, note.id).deliver_later end end def invite_project_member(project_member, token) - mailer.project_member_invited_email(project_member.id, token) + mailer.project_member_invited_email(project_member.id, token).deliver_later end def accept_project_invite(project_member) - mailer.project_invite_accepted_email(project_member.id) + mailer.project_invite_accepted_email(project_member.id).deliver_later end def decline_project_invite(project_member) - mailer.project_invite_declined_email(project_member.project.id, project_member.invite_email, project_member.access_level, project_member.created_by_id) + mailer.project_invite_declined_email( + project_member.project.id, + project_member.invite_email, + project_member.access_level, + project_member.created_by_id + ).deliver_later end def new_project_member(project_member) - mailer.project_access_granted_email(project_member.id) + mailer.project_access_granted_email(project_member.id).deliver_later end def update_project_member(project_member) - mailer.project_access_granted_email(project_member.id) + mailer.project_access_granted_email(project_member.id).deliver_later end def invite_group_member(group_member, token) - mailer.group_member_invited_email(group_member.id, token) + mailer.group_member_invited_email(group_member.id, token).deliver_later end def accept_group_invite(group_member) - mailer.group_invite_accepted_email(group_member.id) + mailer.group_invite_accepted_email(group_member.id).deliver_later end def decline_group_invite(group_member) - mailer.group_invite_declined_email(group_member.group.id, group_member.invite_email, group_member.access_level, group_member.created_by_id) + mailer.group_invite_declined_email( + group_member.group.id, + group_member.invite_email, + group_member.access_level, + group_member.created_by_id + ).deliver_later end def new_group_member(group_member) - mailer.group_access_granted_email(group_member.id) + mailer.group_access_granted_email(group_member.id).deliver_later end def update_group_member(group_member) - mailer.group_access_granted_email(group_member.id) + mailer.group_access_granted_email(group_member.id).deliver_later end def project_was_moved(project, old_path_with_namespace) @@ -189,7 +209,11 @@ class NotificationService recipients = reject_muted_users(recipients, project) recipients.each do |recipient| - mailer.project_was_moved_email(project.id, recipient.id, old_path_with_namespace) + mailer.project_was_moved_email( + project.id, + recipient.id, + old_path_with_namespace + ).deliver_later end end @@ -277,35 +301,25 @@ class NotificationService # Remove users with disabled notifications from array # Also remove duplications and nil recipients def reject_muted_users(users, project = nil) - users = users.to_a.compact.uniq - users = users.reject(&:blocked?) - - users.reject do |user| - next user.notification.disabled? unless project - - member = project.project_members.find_by(user_id: user.id) - - if !member && project.group - member = project.group.group_members.find_by(user_id: user.id) - end - - # reject users who globally disabled notification and has no membership - next user.notification.disabled? unless member - - # reject users who disabled notification in project - next true if member.notification.disabled? - - # reject users who have N_GLOBAL in project and disabled in global settings - member.notification.global? && user.notification.disabled? - end + reject_users(users, :disabled?, project) end # Remove users with notification level 'Mentioned' def reject_mention_users(users, project = nil) + reject_users(users, :mention?, project) + end + + # Reject users which method_name from notification object returns true. + # + # Example: + # reject_users(users, :watch?, project) + # + def reject_users(users, method_name, project = nil) users = users.to_a.compact.uniq + users = users.reject(&:blocked?) users.reject do |user| - next user.notification.mention? unless project + next user.notification.send(method_name) unless project member = project.project_members.find_by(user_id: user.id) @@ -314,19 +328,19 @@ class NotificationService end # reject users who globally set mention notification and has no membership - next user.notification.mention? unless member + next user.notification.send(method_name) unless member # reject users who set mention notification in project - next true if member.notification.mention? + next true if member.notification.send(method_name) # reject users who have N_MENTION in project and disabled in global settings - member.notification.global? && user.notification.mention? + member.notification.global? && user.notification.send(method_name) end end def reject_unsubscribed_users(recipients, target) return recipients unless target.respond_to? :subscriptions - + recipients.reject do |user| subscription = target.subscriptions.find_by_user_id(user.id) subscription && !subscription.subscribed @@ -344,12 +358,12 @@ class NotificationService recipients end end - + def new_resource_email(target, project, method) recipients = build_recipients(target, project, target.author) recipients.each do |recipient| - mailer.send(method, recipient.id, target.id) + mailer.send(method, recipient.id, target.id).deliver_later end end @@ -357,7 +371,7 @@ class NotificationService recipients = build_recipients(target, project, current_user) recipients.each do |recipient| - mailer.send(method, recipient.id, target.id, current_user.id) + mailer.send(method, recipient.id, target.id, current_user.id).deliver_later end end @@ -368,7 +382,13 @@ class NotificationService recipients = build_recipients(target, project, current_user, [previous_assignee]) recipients.each do |recipient| - mailer.send(method, recipient.id, target.id, previous_assignee_id, current_user.id) + mailer.send( + method, + recipient.id, + target.id, + previous_assignee_id, + current_user.id + ).deliver_later end end @@ -376,7 +396,7 @@ class NotificationService recipients = build_recipients(target, project, current_user) recipients.each do |recipient| - mailer.send(method, recipient.id, target.id, status, current_user.id) + mailer.send(method, recipient.id, target.id, status, current_user.id).deliver_later end end @@ -398,7 +418,7 @@ class NotificationService end def mailer - Notify.delay + Notify end def previous_record(object, attribute) diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index 700a1db04d..a6820183be 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -64,8 +64,10 @@ module Projects after_create_actions if @project.persisted? @project - rescue - @project.errors.add(:base, "Can't save project. Please try again later") + rescue => e + message = "Unable to save project: #{e.message}" + Rails.logger.error(message) + @project.errors.add(:base, message) if @project @project end diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb index 5da1c7afd9..0577ae778d 100644 --- a/app/services/projects/fork_service.rb +++ b/app/services/projects/fork_service.rb @@ -7,6 +7,8 @@ module Projects description: @project.description, name: @project.name, path: @project.path, + shared_runners_enabled: @project.shared_runners_enabled, + builds_enabled: @project.builds_enabled, namespace_id: @params[:namespace].try(:id) || current_user.namespace.id } @@ -15,19 +17,6 @@ module Projects end new_project = CreateService.new(current_user, new_params).execute - - if new_project.persisted? - if @project.builds_enabled? - new_project.enable_ci - - settings = @project.gitlab_ci_project.attributes.select do |attr_name, value| - ["public", "shared_runners_enabled", "allow_git_fetch"].include? attr_name - end - - new_project.gitlab_ci_project.update(settings) - end - end - new_project end end diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb index 708c2f0048..98a71cbf1a 100644 --- a/app/services/system_note_service.rb +++ b/app/services/system_note_service.rb @@ -125,7 +125,21 @@ class SystemNoteService # Returns the created Note object def self.change_status(noteable, project, author, status, source) body = "Status changed to #{status}" - body += " by #{source.gfm_reference}" if source + body += " by #{source.gfm_reference(project)}" if source + + create_note(noteable: noteable, project: project, author: author, note: body) + end + + # Called when 'merge when build succeeds' is executed + def self.merge_when_build_succeeds(noteable, project, author, last_commit) + body = "Enabled an automatic merge when the build for #{last_commit.to_reference(project)} succeeds" + + create_note(noteable: noteable, project: project, author: author, note: body) + end + + # Called when 'merge when build succeeds' is canceled + def self.cancel_merge_when_build_succeeds(noteable, project, author) + body = "Canceled the automatic merge" create_note(noteable: noteable, project: project, author: author, note: body) end @@ -227,9 +241,14 @@ class SystemNoteService note_options.merge!(noteable: noteable) end - create_note(note_options) + if noteable.is_a?(ExternalIssue) + noteable.project.issues_tracker.create_cross_reference_note(noteable, mentioner, author) + else + create_note(note_options) + end end + def self.cross_reference?(note_text) note_text.start_with?(cross_reference_note_prefix) end @@ -245,7 +264,7 @@ class SystemNoteService # # Returns Boolean def self.cross_reference_disallowed?(noteable, mentioner) - return true if noteable.is_a?(ExternalIssue) + return true if noteable.is_a?(ExternalIssue) && !noteable.project.jira_tracker_active? return false unless mentioner.is_a?(MergeRequest) return false unless noteable.is_a?(Commit) @@ -341,4 +360,22 @@ class SystemNoteService "* #{commit_ids} - #{commits_text} from branch `#{branch}`\n" end + + # Called when the status of a Task has changed + # + # noteable - Noteable object. + # project - Project owning noteable + # author - User performing the change + # new_task - TaskList::Item object. + # + # Example Note text: + # + # "Soandso marked the task Whatever as completed." + # + # Returns the created Note object + def self.change_task_status(noteable, project, author, new_task) + status_label = new_task.complete? ? Taskable::COMPLETED : Taskable::INCOMPLETE + body = "Marked the task **#{new_task.source}** as #{status_label}" + create_note(noteable: noteable, project: project, author: author, note: body) + end end diff --git a/app/validators/color_validator.rb b/app/validators/color_validator.rb new file mode 100644 index 0000000000..571d0007aa --- /dev/null +++ b/app/validators/color_validator.rb @@ -0,0 +1,20 @@ +# ColorValidator +# +# Custom validator for web color codes. It requires the leading hash symbol and +# will accept RGB triplet or hexadecimal formats. +# +# Example: +# +# class User < ActiveRecord::Base +# validates :background_color, allow_blank: true, color: true +# end +# +class ColorValidator < ActiveModel::EachValidator + PATTERN = /\A\#[0-9A-Fa-f]{3}{1,2}+\Z/.freeze + + def validate_each(record, attribute, value) + unless value =~ PATTERN + record.errors.add(attribute, "must be a valid color code") + end + end +end diff --git a/lib/email_validator.rb b/app/validators/email_validator.rb similarity index 63% rename from lib/email_validator.rb rename to app/validators/email_validator.rb index f509f0a584..b35af10080 100644 --- a/lib/email_validator.rb +++ b/app/validators/email_validator.rb @@ -1,3 +1,5 @@ +# EmailValidator +# # Based on https://github.com/balexand/email_validator # # Extended to use only strict mode with following allowed characters: @@ -6,15 +8,10 @@ # See http://www.remote.org/jochen/mail/info/chars.html # class EmailValidator < ActiveModel::EachValidator - @@default_options = {} - - def self.default_options - @@default_options - end + PATTERN = /\A\s*([-a-z0-9+._']{1,64})@((?:[-a-z0-9]+\.)+[a-z]{2,})\s*\z/i.freeze def validate_each(record, attribute, value) - options = @@default_options.merge(self.options) - unless value =~ /\A\s*([-a-z0-9+._']{1,64})@((?:[-a-z0-9]+\.)+[a-z]{2,})\s*\z/i + unless value =~ PATTERN record.errors.add(attribute, options[:message] || :invalid) end end diff --git a/app/validators/line_code_validator.rb b/app/validators/line_code_validator.rb new file mode 100644 index 0000000000..ed29e5aeb6 --- /dev/null +++ b/app/validators/line_code_validator.rb @@ -0,0 +1,12 @@ +# LineCodeValidator +# +# Custom validator for GitLab line codes. +class LineCodeValidator < ActiveModel::EachValidator + PATTERN = /\A[a-z0-9]+_\d+_\d+\z/.freeze + + def validate_each(record, attribute, value) + unless value =~ PATTERN + record.errors.add(attribute, "must be a valid line code") + end + end +end diff --git a/app/validators/namespace_name_validator.rb b/app/validators/namespace_name_validator.rb new file mode 100644 index 0000000000..2e51af2982 --- /dev/null +++ b/app/validators/namespace_name_validator.rb @@ -0,0 +1,10 @@ +# NamespaceNameValidator +# +# Custom validator for GitLab namespace name strings. +class NamespaceNameValidator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + unless value =~ Gitlab::Regex.namespace_name_regex + record.errors.add(attribute, Gitlab::Regex.namespace_name_regex_message) + end + end +end diff --git a/app/validators/namespace_validator.rb b/app/validators/namespace_validator.rb new file mode 100644 index 0000000000..10e35ce665 --- /dev/null +++ b/app/validators/namespace_validator.rb @@ -0,0 +1,50 @@ +# NamespaceValidator +# +# Custom validator for GitLab namespace values. +# +# Values are checked for formatting and exclusion from a list of reserved path +# names. +class NamespaceValidator < ActiveModel::EachValidator + RESERVED = %w( + admin + all + assets + ci + dashboard + files + groups + help + hooks + issues + merge_requests + notes + profile + projects + public + repository + s + search + services + snippets + teams + u + unsubscribes + users + ).freeze + + def validate_each(record, attribute, value) + unless value =~ Gitlab::Regex.namespace_regex + record.errors.add(attribute, Gitlab::Regex.namespace_regex_message) + end + + if reserved?(value) + record.errors.add(attribute, "#{value} is a reserved name") + end + end + + private + + def reserved?(value) + RESERVED.include?(value) + end +end diff --git a/app/validators/url_validator.rb b/app/validators/url_validator.rb new file mode 100644 index 0000000000..2848b9cd33 --- /dev/null +++ b/app/validators/url_validator.rb @@ -0,0 +1,36 @@ +# UrlValidator +# +# Custom validator for URLs. +# +# By default, only URLs for the HTTP(S) protocols will be considered valid. +# Provide a `:protocols` option to configure accepted protocols. +# +# Example: +# +# class User < ActiveRecord::Base +# validates :personal_url, url: true +# +# validates :ftp_url, url: { protocols: %w(ftp) } +# +# validates :git_url, url: { protocols: %w(http https ssh git) } +# end +# +class UrlValidator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + unless valid_url?(value) + record.errors.add(attribute, "must be a valid URL") + end + end + + private + + def default_options + @default_options ||= { protocols: %w(http https) } + end + + def valid_url?(value) + options = default_options.merge(self.options) + + value =~ /\A#{URI.regexp(options[:protocols])}\z/ + end +end diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index ddaf0e0e8f..6c35536694 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -14,11 +14,11 @@ .form-group.project-visibility-level-holder = f.label :default_project_visibility, class: 'control-label col-sm-2' .col-sm-10 - = render('shared/visibility_radios', model_method: :default_project_visibility, form: f, selected_level: @application_setting.default_project_visibility, form_model: 'Project') + = render('shared/visibility_radios', model_method: :default_project_visibility, form: f, selected_level: @application_setting.default_project_visibility, form_model: Project) .form-group.project-visibility-level-holder = f.label :default_snippet_visibility, class: 'control-label col-sm-2' .col-sm-10 - = render('shared/visibility_radios', model_method: :default_snippet_visibility, form: f, selected_level: @application_setting.default_snippet_visibility, form_model: 'Snippet') + = render('shared/visibility_radios', model_method: :default_snippet_visibility, form: f, selected_level: @application_setting.default_snippet_visibility, form_model: PersonalSnippet) .form-group = f.label :restricted_visibility_levels, class: 'control-label col-sm-2' .col-sm-10 diff --git a/app/views/admin/builds/_build.html.haml b/app/views/admin/builds/_build.html.haml new file mode 100644 index 0000000000..6936e61434 --- /dev/null +++ b/app/views/admin/builds/_build.html.haml @@ -0,0 +1,73 @@ +- project = build.project +%tr.build + %td.status + = ci_status_with_icon(build.status) + + %td.build-link + - if build.target_url + = link_to build.target_url do + %strong Build ##{build.id} + - else + %strong Build ##{build.id} + + - if build.show_warning? + %i.fa.fa-warning.text-warning + + %td + - if project + = link_to project.name_with_namespace, admin_namespace_project_path(project.namespace, project), class: "monospace" + + %td + = link_to build.short_sha, namespace_project_commit_path(project.namespace, project, build.sha), class: "monospace" + + %td + - if build.ref + = link_to build.ref, namespace_project_commits_path(project.namespace, project, build.ref) + - else + .light none + + %td + - if build.try(:runner) + = runner_link(build.runner) + - else + .light none + + %td + #{build.stage} / #{build.name} + + .pull-right + - if build.tags.any? + - build.tags.each do |tag| + %span.label.label-primary + = tag + - if build.try(:trigger_request) + %span.label.label-info triggered + - if build.try(:allow_failure) + %span.label.label-danger allowed to fail + + %td.duration + - if build.duration + #{duration_in_words(build.finished_at, build.started_at)} + + %td.timestamp + - if build.finished_at + %span #{time_ago_with_tooltip(build.finished_at)} + + - if defined?(coverage) && coverage + %td.coverage + - if build.try(:coverage) + #{build.coverage}% + + %td + .pull-right + - if current_user && can?(current_user, :download_build_artifacts, project) && build.download_url + = link_to build.download_url, title: 'Download artifacts' do + %i.fa.fa-download + - if current_user && can?(current_user, :manage_builds, build.project) + - if build.active? + - if build.cancel_url + = link_to build.cancel_url, method: :post, title: 'Cancel' do + %i.fa.fa-remove.cred + - elsif defined?(allow_retry) && allow_retry && build.retry_url + = link_to build.retry_url, method: :post, title: 'Retry' do + %i.fa.fa-repeat diff --git a/app/views/admin/builds/index.html.haml b/app/views/admin/builds/index.html.haml new file mode 100644 index 0000000000..55da06a7fe --- /dev/null +++ b/app/views/admin/builds/index.html.haml @@ -0,0 +1,50 @@ +.project-issuable-filter + .controls + .pull-left.hidden-xs + - if @all_builds.running_or_pending.any? + = link_to 'Cancel all', cancel_all_admin_builds_path, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post + + %ul.center-top-menu + %li{class: ('active' if @scope.nil?)} + = link_to admin_builds_path do + Running + %span.badge.js-running-count= @all_builds.running_or_pending.count(:id) + + %li{class: ('active' if @scope == 'finished')} + = link_to admin_builds_path(scope: :finished) do + Finished + %span.badge.js-running-count= @all_builds.finished.count(:id) + + %li{class: ('active' if @scope == 'all')} + = link_to admin_builds_path(scope: :all) do + All + %span.badge.js-totalbuilds-count= @all_builds.count(:id) + +.gray-content-block + #{(@scope || 'running').capitalize} builds + +%ul.content-list + - if @builds.blank? + %li + .nothing-here-block No builds to show + - else + .table-holder + %table.table.builds + %thead + %tr + %th Status + %th Build ID + %th Project + %th Commit + %th Ref + %th Runner + %th Name + %th Duration + %th Finished at + %th + + - @builds.each do |build| + = render "admin/builds/build", build: build + + = paginate @builds, theme: 'gitlab' + diff --git a/app/views/admin/identities/index.html.haml b/app/views/admin/identities/index.html.haml index 8358a14445..741d111fb7 100644 --- a/app/views/admin/identities/index.html.haml +++ b/app/views/admin/identities/index.html.haml @@ -1,6 +1,7 @@ - page_title "Identities", @user.name, "Users" = render 'admin/users/head' += link_to 'New Identity', new_admin_user_identity_path, class: 'pull-right btn btn-new' - if @identities.present? .table-holder %table.table diff --git a/app/views/admin/identities/new.html.haml b/app/views/admin/identities/new.html.haml new file mode 100644 index 0000000000..e30bf0ef0e --- /dev/null +++ b/app/views/admin/identities/new.html.haml @@ -0,0 +1,4 @@ +- page_title "New Identity" +%h3.page-title New identity +%hr += render 'form' diff --git a/app/views/admin/labels/_form.html.haml b/app/views/admin/labels/_form.html.haml index a5ace4e7a3..eaa94ed9e3 100644 --- a/app/views/admin/labels/_form.html.haml +++ b/app/views/admin/labels/_form.html.haml @@ -12,7 +12,7 @@ .col-sm-10 = f.text_field :title, class: "form-control", required: true .form-group - = f.label :color, "Background Color", class: 'control-label' + = f.label :color, "Background color", class: 'control-label' .col-sm-10 .input-group .input-group-addon.label-color-preview   diff --git a/app/views/admin/labels/_label.html.haml b/app/views/admin/labels/_label.html.haml index 596e06243d..e3ccbf6c3a 100644 --- a/app/views/admin/labels/_label.html.haml +++ b/app/views/admin/labels/_label.html.haml @@ -2,4 +2,4 @@ = render_colored_label(label) .pull-right = link_to 'Edit', edit_admin_label_path(label), class: 'btn btn-sm' - = link_to 'Remove', admin_label_path(label), class: 'btn btn-sm btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Remove this label? Are you sure?"} + = link_to 'Delete', admin_label_path(label), class: 'btn btn-sm btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Delete this label? Are you sure?"} diff --git a/app/views/admin/labels/edit.html.haml b/app/views/admin/labels/edit.html.haml index 45c62a7625..309aedcede 100644 --- a/app/views/admin/labels/edit.html.haml +++ b/app/views/admin/labels/edit.html.haml @@ -1,9 +1,5 @@ - page_title "Edit", @label.name, "Labels" -%h3 - Edit label - %span.light #{@label.name} -.back-link - = link_to admin_labels_path do - ← To labels list +%h3.page-title + Edit Label %hr = render 'form' diff --git a/app/views/admin/labels/new.html.haml b/app/views/admin/labels/new.html.haml index 8d298ad20f..0135ad0723 100644 --- a/app/views/admin/labels/new.html.haml +++ b/app/views/admin/labels/new.html.haml @@ -1,7 +1,5 @@ - page_title "New Label" -%h3 New label -.back-link - = link_to admin_labels_path do - ← To labels list +%h3.page-title + New Label %hr = render 'form' diff --git a/app/views/ci/admin/runners/_runner.html.haml b/app/views/admin/runners/_runner.html.haml similarity index 62% rename from app/views/ci/admin/runners/_runner.html.haml rename to app/views/admin/runners/_runner.html.haml index 701782d26b..6745e58dec 100644 --- a/app/views/ci/admin/runners/_runner.html.haml +++ b/app/views/admin/runners/_runner.html.haml @@ -8,14 +8,14 @@ %span.label.label-danger paused %td - = link_to ci_admin_runner_path(runner) do + = link_to admin_runner_path(runner) do = runner.short_sha %td .runner-description = runner.description %span (#{link_to 'edit', '#', class: 'edit-runner-link'}) .runner-description-form.hide - = form_for [:ci, :admin, runner], remote: true, html: { class: 'form-inline' } do |f| + = form_for [:admin, runner], remote: true, html: { class: 'form-inline' } do |f| .form-group = f.text_field :description, class: 'form-control' = f.submit 'Save', class: 'btn' @@ -38,11 +38,11 @@ Never %td .pull-right - = link_to 'Edit', ci_admin_runner_path(runner), class: 'btn btn-sm' + = link_to 'Edit', admin_runner_path(runner), class: 'btn btn-sm'   - if runner.active? - = link_to 'Pause', [:pause, :ci, :admin, runner], data: { confirm: "Are you sure?" }, method: :get, class: 'btn btn-danger btn-sm' + = link_to 'Pause', [:pause, :admin, runner], data: { confirm: "Are you sure?" }, method: :get, class: 'btn btn-danger btn-sm' - else - = link_to 'Resume', [:resume, :ci, :admin, runner], method: :get, class: 'btn btn-success btn-sm' - = link_to 'Remove', [:ci, :admin, runner], data: { confirm: "Are you sure?" }, method: :delete, class: 'btn btn-danger btn-sm' + = link_to 'Resume', [:resume, :admin, runner], method: :get, class: 'btn btn-success btn-sm' + = link_to 'Remove', [:admin, runner], data: { confirm: "Are you sure?" }, method: :delete, class: 'btn btn-danger btn-sm' diff --git a/app/views/ci/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml similarity index 58% rename from app/views/ci/admin/runners/index.html.haml rename to app/views/admin/runners/index.html.haml index bacaccfbff..c5fb3c9550 100644 --- a/app/views/ci/admin/runners/index.html.haml +++ b/app/views/admin/runners/index.html.haml @@ -1,6 +1,20 @@ %p.lead - %span To register a new runner you should enter the following registration token. With this token the runner will request a unique runner token and use that for future communication. - %code #{GitlabCi::REGISTRATION_TOKEN} + %span + To register a new runner you should enter the following registration token. + With this token the runner will request a unique runner token and use that for future communication. + Registration token is + %code{ id: 'runners-token' } #{current_application_settings.ensure_runners_registration_token} + +.bs-callout.clearfix + .pull-left + %p + You can reset runners registration token by pressing a button below. + %p + = button_to reset_runners_token_admin_application_settings_path, + method: :put, class: 'btn btn-default', + data: { confirm: 'Are you sure you want to reset registration token?' } do + = icon('refresh') + Reset runners registration token .bs-callout %p @@ -25,7 +39,7 @@ .append-bottom-20.clearfix .pull-left - = form_tag ci_admin_runners_path, id: 'runners-search', class: 'form-inline', method: :get do + = form_tag admin_runners_path, id: 'runners-search', class: 'form-inline', method: :get do .form-group = search_field_tag :search, params[:search], class: 'form-control', placeholder: 'Runner description or token', spellcheck: false = submit_tag 'Search', class: 'btn' @@ -49,5 +63,5 @@ %th - @runners.each do |runner| - = render "ci/admin/runners/runner", runner: runner + = render "admin/runners/runner", runner: runner = paginate @runners diff --git a/app/views/ci/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml similarity index 69% rename from app/views/ci/admin/runners/show.html.haml rename to app/views/admin/runners/show.html.haml index 1498db46a8..8700b4820c 100644 --- a/app/views/ci/admin/runners/show.html.haml +++ b/app/views/admin/runners/show.html.haml @@ -22,7 +22,7 @@ %h4 This runner will process builds only from ASSIGNED projects %p You can't make this a shared runner. %hr -= form_for @runner, url: ci_admin_runner_path(@runner), html: { class: 'form-horizontal' } do |f| += form_for @runner, url: admin_runner_path(@runner), html: { class: 'form-horizontal' } do |f| .form-group = label_tag :token, class: 'control-label' do Token @@ -37,7 +37,7 @@ = label_tag :tag_list, class: 'control-label' do Tags .col-sm-10 - = f.text_field :tag_list, class: 'form-control' + = f.text_field :tag_list, value: @runner.tag_list.to_s, class: 'form-control' .help-block You can setup builds to only use runners with specific tags .form-actions = f.submit 'Save', class: 'btn btn-save' @@ -53,29 +53,24 @@ %th - @runner.runner_projects.each do |runner_project| - project = runner_project.project - - if project.gl_project + - if project %tr.alert-info %td %strong - = project.name + = project.name_with_namespace %td .pull-right - = link_to 'Disable', [:ci, :admin, project, runner_project], method: :delete, class: 'btn btn-danger btn-xs' + = link_to 'Disable', [:admin, project.namespace.becomes(Namespace), project, runner_project], method: :delete, class: 'btn btn-danger btn-xs' %table.table %thead %tr %th Project %th - .pull-right - = link_to 'Assign to all', assign_all_ci_admin_runner_path(@runner), - class: 'btn btn-sm assign-all-runner', - title: 'Assign runner to all projects', - method: :put %tr %td - = form_tag ci_admin_runner_path(@runner), id: 'runner-projects-search', class: 'form-inline', method: :get do + = form_tag admin_runner_path(@runner), id: 'runner-projects-search', class: 'form-inline', method: :get do .form-group = search_field_tag :search, params[:search], class: 'form-control', spellcheck: false = submit_tag 'Search', class: 'btn' @@ -84,44 +79,44 @@ - @projects.each do |project| %tr %td - = project.name + = project.name_with_namespace %td .pull-right - = form_for [:ci, :admin, project, project.runner_projects.new] do |f| + = form_for [:admin, project.namespace.becomes(Namespace), project, project.runner_projects.new] do |f| = f.hidden_field :runner_id, value: @runner.id = f.submit 'Enable', class: 'btn btn-xs' = paginate @projects .col-md-6 %h4 Recent builds served by this runner - %table.builds.runner-builds + %table.table.builds.runner-builds %thead %tr - %th Build ID + %th Build %th Status %th Project %th Commit %th Finished at - @builds.each do |build| - - gl_project = build.gl_project + - project = build.project %tr.build %td.id - - if gl_project - = link_to namespace_project_build_path(gl_project.namespace, gl_project, build) do - = build.id + - if project + = link_to namespace_project_build_path(project.namespace, project, build) do + %strong ##{build.id} - else - = build.id + %strong ##{build.id} %td.status = ci_status_with_icon(build.status) %td.status - - if gl_project - = gl_project.name_with_namespace + - if project + = project.name_with_namespace %td.build-link - - if gl_project + - if project = link_to ci_status_path(build.commit) do %strong #{build.commit.short_sha} diff --git a/app/views/ci/admin/runners/update.js.haml b/app/views/admin/runners/update.js.haml similarity index 100% rename from app/views/ci/admin/runners/update.js.haml rename to app/views/admin/runners/update.js.haml diff --git a/app/views/admin/users/_head.html.haml b/app/views/admin/users/_head.html.haml index 8d1cab4137..5e17b01816 100644 --- a/app/views/admin/users/_head.html.haml +++ b/app/views/admin/users/_head.html.haml @@ -6,7 +6,7 @@ %span.cred (Admin) .pull-right - - unless @user == current_user + - unless @user == current_user || @user.blocked? = link_to 'Impersonate', impersonate_admin_user_path(@user), method: :post, class: "btn btn-grouped btn-info" = link_to edit_admin_user_path(@user), class: "btn btn-grouped" do %i.fa.fa-pencil-square-o diff --git a/app/views/admin/users/_projects.html.haml b/app/views/admin/users/_projects.html.haml new file mode 100644 index 0000000000..a126a858ea --- /dev/null +++ b/app/views/admin/users/_projects.html.haml @@ -0,0 +1,13 @@ +- if local_assigns.has_key?(:contributed_projects) && contributed_projects.present? + .panel.panel-default.contributed-projects + .panel-heading Projects contributed to + = render 'shared/projects/list', + projects: contributed_projects.sort_by(&:star_count).reverse, + projects_limit: 5, stars: true, avatar: false + +- if local_assigns.has_key?(:projects) && projects.present? + .panel.panel-default + .panel-heading Personal projects + = render 'shared/projects/list', + projects: projects.sort_by(&:star_count).reverse, + projects_limit: 10, stars: true, avatar: false diff --git a/app/views/admin/users/edit.html.haml b/app/views/admin/users/edit.html.haml index a8837d74dd..3b6fd71500 100644 --- a/app/views/admin/users/edit.html.haml +++ b/app/views/admin/users/edit.html.haml @@ -1,8 +1,5 @@ - page_title "Edit", @user.name, "Users" %h3.page-title Edit user: #{@user.name} -.back-link - = link_to admin_user_path(@user) do - ← Back to user page %hr = render 'form' diff --git a/app/views/admin/users/projects.html.haml b/app/views/admin/users/projects.html.haml index 0d7a1a25a8..b655b2a15f 100644 --- a/app/views/admin/users/projects.html.haml +++ b/app/views/admin/users/projects.html.haml @@ -14,7 +14,7 @@ .row .col-md-6 - if @personal_projects.present? - = render 'users/projects', projects: @personal_projects + = render 'admin/users/projects', projects: @personal_projects - else .nothing-here-block This user has no personal projects. diff --git a/app/views/ci/admin/application_settings/_form.html.haml b/app/views/ci/admin/application_settings/_form.html.haml deleted file mode 100644 index 634c9daa47..0000000000 --- a/app/views/ci/admin/application_settings/_form.html.haml +++ /dev/null @@ -1,24 +0,0 @@ -= form_for @application_setting, url: ci_admin_application_settings_path, html: { class: 'form-horizontal fieldset-form' } do |f| - - if @application_setting.errors.any? - #error_explanation - .alert.alert-danger - - @application_setting.errors.full_messages.each do |msg| - %p= msg - - %fieldset - %legend Default Project Settings - .form-group - .col-sm-offset-2.col-sm-10 - .checkbox - = f.label :all_broken_builds do - = f.check_box :all_broken_builds - Send emails only on broken builds - .form-group - .col-sm-offset-2.col-sm-10 - .checkbox - = f.label :add_pusher do - = f.check_box :add_pusher - Add pusher to recipients list - - .form-actions - = f.submit 'Save', class: 'btn btn-primary' diff --git a/app/views/ci/admin/application_settings/show.html.haml b/app/views/ci/admin/application_settings/show.html.haml deleted file mode 100644 index 7ef0aa89ed..0000000000 --- a/app/views/ci/admin/application_settings/show.html.haml +++ /dev/null @@ -1,3 +0,0 @@ -%h3.page-title Settings -%hr -= render 'form' diff --git a/app/views/ci/admin/builds/_build.html.haml b/app/views/ci/admin/builds/_build.html.haml deleted file mode 100644 index 2df5871321..0000000000 --- a/app/views/ci/admin/builds/_build.html.haml +++ /dev/null @@ -1,34 +0,0 @@ -- gl_project = build.project.gl_project -- if build.commit && build.project - %tr.build - %td.build-link - = link_to namespace_project_build_path(gl_project.namespace, gl_project, build) do - %strong #{build.id} - - %td.status - = ci_status_with_icon(build.status) - - %td.commit-link - = link_to ci_status_path(build.commit) do - %strong #{build.commit.short_sha} - - %td.runner - - if build.runner - = link_to build.runner.id, ci_admin_runner_path(build.runner) - - %td.build-project - = truncate build.project.name, length: 30 - - %td.build-message - %span= truncate(build.commit.git_commit_message, length: 30) - - %td.build-branch - %span= truncate(build.ref, length: 25) - - %td.duration - - if build.duration - #{duration_in_words(build.finished_at, build.started_at)} - - %td.timestamp - - if build.finished_at - %span #{time_ago_in_words build.finished_at} ago diff --git a/app/views/ci/admin/builds/index.html.haml b/app/views/ci/admin/builds/index.html.haml deleted file mode 100644 index d23119162c..0000000000 --- a/app/views/ci/admin/builds/index.html.haml +++ /dev/null @@ -1,28 +0,0 @@ -%ul.nav.nav-tabs.append-bottom-20 - %li{class: ("active" if @scope.nil?)} - = link_to 'All builds', ci_admin_builds_path - - %li{class: ("active" if @scope == "pending")} - = link_to "Pending", ci_admin_builds_path(scope: :pending) - - %li{class: ("active" if @scope == "running")} - = link_to "Running", ci_admin_builds_path(scope: :running) - - -%table.builds - %thead - %tr - %th Build - %th Status - %th Commit - %th Runner - %th Project - %th Message - %th Branch - %th Duration - %th Finished at - - - @builds.each do |build| - = render "ci/admin/builds/build", build: build - -= paginate @builds diff --git a/app/views/ci/admin/events/index.html.haml b/app/views/ci/admin/events/index.html.haml deleted file mode 100644 index 5a5b4dc7c3..0000000000 --- a/app/views/ci/admin/events/index.html.haml +++ /dev/null @@ -1,18 +0,0 @@ -.table-holder - %table.table - %thead - %tr - %th User ID - %th Description - %th When - - @events.each do |event| - %tr - %td - = event.user_id - %td - = event.description - %td.light - = time_ago_in_words event.updated_at - ago - -= paginate @events diff --git a/app/views/ci/admin/projects/_project.html.haml b/app/views/ci/admin/projects/_project.html.haml deleted file mode 100644 index a342d6e1cf..0000000000 --- a/app/views/ci/admin/projects/_project.html.haml +++ /dev/null @@ -1,29 +0,0 @@ -- last_commit = project.commits.last -%tr - %td - = project.id - %td - = link_to [:ci, project] do - %strong= project.name - %td - - if last_commit - = ci_status_with_icon(last_commit.status) - - if project.last_commit_date - · - = time_ago_in_words project.last_commit_date - ago - - else - No builds yet - %td - - if project.public - %i.fa.fa-globe - Public - - else - %i.fa.fa-lock - Private - %td - = project.commits.count - %td - = link_to [:ci, :admin, project], method: :delete, class: 'btn btn-danger btn-sm' do - %i.fa.fa-remove - Remove diff --git a/app/views/ci/admin/projects/index.html.haml b/app/views/ci/admin/projects/index.html.haml deleted file mode 100644 index 0da8547924..0000000000 --- a/app/views/ci/admin/projects/index.html.haml +++ /dev/null @@ -1,16 +0,0 @@ -.table-holder - %table.table - %thead - %tr - %th ID - %th Name - %th Last build - %th Access - %th Builds - %th - - - @projects.each do |project| - = render "ci/admin/projects/project", project: project - -= paginate @projects - diff --git a/app/views/ci/admin/runner_projects/index.html.haml b/app/views/ci/admin/runner_projects/index.html.haml deleted file mode 100644 index 6b4e3b2cb3..0000000000 --- a/app/views/ci/admin/runner_projects/index.html.haml +++ /dev/null @@ -1,57 +0,0 @@ -%p.lead - To register a new runner visit #{link_to 'this page ', ci_runners_path} - -.row - .col-md-8 - %h5 Activated: - %table.table - %tr - %th Runner ID - %th Runner Description - %th Last build - %th Builds Stats - %th Registered - %th - - - @runner_projects.each do |runner_project| - - runner = runner_project.runner - - builds = runner.builds.where(project_id: @project.id) - %tr - %td - %span.badge.badge-info= runner.id - %td - = runner.display_name - %td - - last_build = builds.last - - if last_build - = link_to last_build.short_sha, [last_build.project, last_build] - - else - unknown - %td - %span.badge.badge-success - #{builds.success.count} - %span / - %span.badge.badge-important - #{builds.failed.count} - %td - #{time_ago_in_words(runner_project.created_at)} ago - %td - = link_to 'Disable', [:ci, @project, runner_project], data: { confirm: "Are you sure?" }, method: :delete, class: 'btn btn-danger btn-sm right' - .col-md-4 - %h5 Available - %table.table - %tr - %th ID - %th Token - %th - - - (Ci::Runner.all - @project.runners).each do |runner| - %tr - %td - = runner.id - %td - = runner.token - %td - = form_for [:ci, @project, @runner_project] do |f| - = f.hidden_field :runner_id, value: runner.id - = f.submit 'Add', class: 'btn btn-sm' diff --git a/app/views/ci/commits/_commit.html.haml b/app/views/ci/commits/_commit.html.haml index b24a3b826c..11163813f3 100644 --- a/app/views/ci/commits/_commit.html.haml +++ b/app/views/ci/commits/_commit.html.haml @@ -27,7 +27,6 @@ - if commit.finished_at %span #{time_ago_in_words commit.finished_at} ago - - if commit.project.coverage_enabled? + - if commit.coverage %td.coverage - - if commit.coverage - #{commit.coverage}% + #{commit.coverage}% diff --git a/app/views/ci/shared/_guide.html.haml b/app/views/ci/shared/_guide.html.haml index db2d7f2f4b..09e7e65352 100644 --- a/app/views/ci/shared/_guide.html.haml +++ b/app/views/ci/shared/_guide.html.haml @@ -4,12 +4,10 @@ %ol %li Add at least one runner to the project. - Go to #{link_to 'Runners page', runners_path(@project.gl_project), target: :blank} for instructions. + Go to #{link_to 'Runners page', runners_path(@project), target: :blank} for instructions. %li - Put the .gitlab-ci.yml in the root of your repository. Examples can be found in #{link_to "Configuring project (.gitlab-ci.yml)", "http://doc.gitlab.com/ci/yaml/README.html", target: :blank}. + Put the .gitlab-ci.yml in the root of your repository. Examples can be found in + #{link_to "Configuring project (.gitlab-ci.yml)", "http://doc.gitlab.com/ci/yaml/README.html", target: :blank}. You can also test your .gitlab-ci.yml in the #{link_to "Lint", ci_lint_path} - %li - Visit #{link_to 'GitLab project settings', @project.gitlab_url + "/services/gitlab_ci/edit", target: :blank} - and press the "Test settings" button. %li Return to this page and refresh it, it should show a new build. diff --git a/app/views/ci/user_sessions/new.html.haml b/app/views/ci/user_sessions/new.html.haml deleted file mode 100644 index b8d9a1d708..0000000000 --- a/app/views/ci/user_sessions/new.html.haml +++ /dev/null @@ -1,7 +0,0 @@ -.login-block - %h2 Login using GitLab account - %p.light - Make sure you have an account on the GitLab server - = link_to GitlabCi.config.gitlab_server.url, GitlabCi.config.gitlab_server.url, no_turbolink - %hr - = link_to "Login with GitLab", auth_ci_user_sessions_path(state: params[:state]), no_turbolink.merge( class: 'btn btn-login btn-success' ) diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml index ed480b8caf..2e77afb752 100644 --- a/app/views/dashboard/_projects_head.html.haml +++ b/app/views/dashboard/_projects_head.html.haml @@ -1,5 +1,8 @@ += content_for :flash_message do + = render 'shared/project_limit' + %ul.center-top-menu - = nav_link(path: ['projects#index', 'root#index']) do + = nav_link(page: [dashboard_projects_path, root_path]) do = link_to dashboard_projects_path, title: 'Home', class: 'shortcuts-activity', data: {placement: 'right'} do Your Projects = nav_link(page: starred_dashboard_projects_path) do diff --git a/app/views/dashboard/groups/index.html.haml b/app/views/dashboard/groups/index.html.haml index f3f3f58111..d5b7e729e7 100644 --- a/app/views/dashboard/groups/index.html.haml +++ b/app/views/dashboard/groups/index.html.haml @@ -8,8 +8,8 @@ = link_to new_group_path, class: "btn btn-new" do %i.fa.fa-plus New Group - .title Welcome to the groups! - Group members have access to all group projects. + .oneline + Group members have access to all group projects. %ul.content-list - @group_members.each do |group_member| diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml index cd602e897b..2d3da01178 100644 --- a/app/views/dashboard/issues.html.haml +++ b/app/views/dashboard/issues.html.haml @@ -4,14 +4,20 @@ - if current_user = auto_discovery_link_tag(:atom, issues_dashboard_url(format: :atom, private_token: current_user.private_token), title: "#{current_user.name} issues") +.project-issuable-filter + .controls + .pull-left + - if current_user + .hidden-xs.pull-left + = link_to issues_dashboard_url(format: :atom, private_token: current_user.private_token), class: 'btn' do + %i.fa.fa-rss -.append-bottom-20 - .pull-right - - if current_user - .hidden-xs.pull-left.prepend-top-20 - = link_to issues_dashboard_url(format: :atom, private_token: current_user.private_token), class: '' do - %i.fa.fa-rss + = render 'shared/new_project_item_select', path: 'issues/new', label: "New Issue" = render 'shared/issuable/filter', type: :issues -= render 'shared/issues' +.gray-content-block.second-block + List all issues from all projects you have access to. + +.prepend-top-default + = render 'shared/issues' diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml index d1f332fa0d..c5a5ec21f7 100644 --- a/app/views/dashboard/merge_requests.html.haml +++ b/app/views/dashboard/merge_requests.html.haml @@ -1,6 +1,14 @@ - page_title "Merge Requests" - header_title "Merge Requests", merge_requests_dashboard_path(assignee_id: current_user.id) -.append-bottom-20 +.project-issuable-filter + .controls + = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New Merge Request" + = render 'shared/issuable/filter', type: :merge_requests -= render 'shared/merge_requests' + +.gray-content-block.second-block + List all merge requests from all projects you have access to. + +.prepend-top-default + = render 'shared/merge_requests' diff --git a/app/views/dashboard/milestones/_milestone.html.haml b/app/views/dashboard/milestones/_milestone.html.haml index 55080d6b3f..7c882a3270 100644 --- a/app/views/dashboard/milestones/_milestone.html.haml +++ b/app/views/dashboard/milestones/_milestone.html.haml @@ -16,7 +16,10 @@ = milestone_progress_bar(milestone) .row .col-sm-6 - - milestone.milestones.each do |milestone| - = link_to milestone_path(milestone) do - %span.label.label-gray - = milestone.project.name_with_namespace + .expiration + = render 'shared/milestone_expired', milestone: milestone + .projects + - milestone.milestones.each do |milestone| + = link_to milestone_path(milestone) do + %span.label.label-gray + = milestone.project.name_with_namespace diff --git a/app/views/dashboard/milestones/index.html.haml b/app/views/dashboard/milestones/index.html.haml index 635251e237..bec1692a4d 100644 --- a/app/views/dashboard/milestones/index.html.haml +++ b/app/views/dashboard/milestones/index.html.haml @@ -1,12 +1,14 @@ - page_title "Milestones" -- header_title "Milestones", dashboard_milestones_path +- header_title "Milestones", dashboard_milestones_path +.project-issuable-filter + .controls + = render 'shared/new_project_item_select', path: 'milestones/new', label: "New Milestone", include_groups: true -= render 'shared/milestones_filter' + = render 'shared/milestones_filter' .gray-content-block - .oneline - List all milestones from all projects you have access to. + List all milestones from all projects you have access to. .milestones %ul.content-list diff --git a/app/views/dashboard/milestones/show.html.haml b/app/views/dashboard/milestones/show.html.haml index 83077a398b..4316c358dc 100644 --- a/app/views/dashboard/milestones/show.html.haml +++ b/app/views/dashboard/milestones/show.html.haml @@ -1,19 +1,23 @@ - page_title @milestone.title, "Milestones" -%h4.page-title - .issue-box{ class: "issue-box-#{@milestone.closed? ? 'closed' : 'open'}" } +- header_title "Milestones", dashboard_milestones_path + +.detail-page-header + .status-box{ class: "status-box-#{@milestone.closed? ? 'closed' : 'open'}" } - if @milestone.closed? Closed - else Open - Milestone #{@milestone.title} + %span.identifier + Milestone #{@milestone.title} + +.detail-page-description.gray-content-block.second-block + %h2.title + = markdown escape_once(@milestone.title), pipeline: :single_line -%hr - if @milestone.complete? && @milestone.active? - .alert.alert-success + .alert.alert-success.prepend-top-default %span All issues for this milestone are closed. You may close the milestone now. -.description - .table-holder %table.table %thead @@ -44,7 +48,7 @@ #{@milestone.open_items_count} open = milestone_progress_bar(@milestone) -%ul.nav.nav-tabs +%ul.center-top-menu.no-top.no-bottom %li.active = link_to '#tab-issues', 'data-toggle' => 'tab' do Issues @@ -58,25 +62,39 @@ Participants %span.badge= @milestone.participants.count - .pull-right - = link_to 'Browse Issues', issues_dashboard_path(milestone_title: @milestone.title), class: "btn edit-milestone-link btn-grouped" - .tab-content .tab-pane.active#tab-issues - .row + .gray-content-block.middle-block + .pull-right + = link_to 'Browse Issues', issues_dashboard_path(milestone_title: @milestone.title), class: "btn btn-grouped" + + .oneline + All issues in this milestone + + .row.prepend-top-default .col-md-6 = render 'issues', title: "Open", issues: @milestone.opened_issues .col-md-6 = render 'issues', title: "Closed", issues: @milestone.closed_issues .tab-pane#tab-merge-requests - .row + .gray-content-block.middle-block + .pull-right + = link_to 'Browse Merge Requests', merge_requests_dashboard_path(milestone_title: @milestone.title), class: "btn btn-grouped" + + .oneline + All merge requests in this milestone + + .row.prepend-top-default .col-md-6 = render 'merge_requests', title: "Open", merge_requests: @milestone.opened_merge_requests .col-md-6 = render 'merge_requests', title: "Closed", merge_requests: @milestone.closed_merge_requests .tab-pane#tab-participants + .gray-content-block.middle-block + .oneline + All participants to this milestone %ul.bordered-list - @milestone.participants.each do |user| %li diff --git a/app/views/dashboard/projects/index.html.haml b/app/views/dashboard/projects/index.html.haml index 7a16b811f6..53abf274bd 100644 --- a/app/views/dashboard/projects/index.html.haml +++ b/app/views/dashboard/projects/index.html.haml @@ -3,7 +3,7 @@ = auto_discovery_link_tag(:atom, dashboard_projects_url(format: :atom, private_token: current_user.private_token), title: "All activity") - page_title "Projects" -- header_title "Projects", root_path +- header_title "Projects", dashboard_projects_path = render 'dashboard/projects_head' diff --git a/app/views/dashboard/projects/starred.html.haml b/app/views/dashboard/projects/starred.html.haml index f75f2e0a32..70705923d4 100644 --- a/app/views/dashboard/projects/starred.html.haml +++ b/app/views/dashboard/projects/starred.html.haml @@ -1,5 +1,5 @@ - page_title "Starred Projects" -- header_title "Projects", projects_path +- header_title "Projects", dashboard_projects_path = render 'dashboard/projects_head' diff --git a/app/views/devise/mailer/unlock_instructions.html.erb b/app/views/devise/mailer/unlock_instructions.html.erb deleted file mode 100644 index 79d6c761d8..0000000000 --- a/app/views/devise/mailer/unlock_instructions.html.erb +++ /dev/null @@ -1,7 +0,0 @@ -

Hello <%= @resource.email %>!

- -

Your account has been locked due to an excessive amount of unsuccessful sign in attempts.

- -

Click the link below to unlock your account:

- -

<%= link_to 'Unlock your account', unlock_url(@resource, unlock_token: @token) %>

diff --git a/app/views/devise/mailer/unlock_instructions.html.haml b/app/views/devise/mailer/unlock_instructions.html.haml new file mode 100644 index 0000000000..52b327e20c --- /dev/null +++ b/app/views/devise/mailer/unlock_instructions.html.haml @@ -0,0 +1,10 @@ +%p +Hello #{@resource.name}! + +%p + Your GitLab account has been locked due to an excessive amount of unsuccessful + sign in attempts. Your account will automatically unlock in + = time_ago_in_words(Devise.unlock_in.from_now) + or you may click the link below to unlock now. + +%p= link_to 'Unlock your account', unlock_url(@resource, unlock_token: @token) diff --git a/app/views/devise/unlocks/new.html.erb b/app/views/devise/unlocks/new.html.erb deleted file mode 100644 index f9277d1673..0000000000 --- a/app/views/devise/unlocks/new.html.erb +++ /dev/null @@ -1,12 +0,0 @@ -

Resend unlock instructions

- -<%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %> - <%= devise_error_messages! %> - -
<%= f.label :email %>
- <%= f.email_field :email %>
- -
<%= f.submit "Resend unlock instructions" %>
-<% end %> - -<%= render partial: "devise/shared/links" %> diff --git a/app/views/devise/unlocks/new.html.haml b/app/views/devise/unlocks/new.html.haml new file mode 100644 index 0000000000..49c087c064 --- /dev/null +++ b/app/views/devise/unlocks/new.html.haml @@ -0,0 +1,14 @@ +.login-box + .login-heading + %h3 Resend unlock email + .login-body + = form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| + .devise-errors + = devise_error_messages! + .clearfix.append-bottom-20 + = f.email_field :email, class: 'form-control', placeholder: 'Email', autofocus: 'autofocus', autocapitalize: 'off', autocorrect: 'off' + .clearfix + = f.submit 'Resend unlock instructions', class: 'btn btn-success' + +.clearfix.prepend-top-20 + = render 'devise/shared/sign_in_link' diff --git a/app/views/events/_commit.html.haml b/app/views/events/_commit.html.haml index ad63841ccf..4ba8b84fd9 100644 --- a/app/views/events/_commit.html.haml +++ b/app/views/events/_commit.html.haml @@ -2,4 +2,4 @@ .commit-row-title = link_to truncate_sha(commit[:id]), namespace_project_commit_path(project.namespace, project, commit[:id]), class: "commit_short_id", alt: '' · - = gfm event_commit_title(commit[:message]), project: project + = markdown event_commit_title(commit[:message]), project: project, pipeline: :single_line diff --git a/app/views/explore/projects/_filter.html.haml b/app/views/explore/projects/_filter.html.haml index 2761272aa8..28b12c8dca 100644 --- a/app/views/explore/projects/_filter.html.haml +++ b/app/views/explore/projects/_filter.html.haml @@ -3,7 +3,7 @@ .form-group = search_field_tag :search, params[:search], placeholder: "Filter by name", class: "form-control search-text-input", id: "projects_search", spellcheck: false .form-group - = button_tag 'Search', class: "btn btn-success" + = button_tag 'Search', class: "btn" .pull-right.hidden-sm.hidden-xs - if current_user diff --git a/app/views/explore/projects/index.html.haml b/app/views/explore/projects/index.html.haml index 67e38ca312..76bdd68fd7 100644 --- a/app/views/explore/projects/index.html.haml +++ b/app/views/explore/projects/index.html.haml @@ -1,5 +1,5 @@ - page_title "Projects" -- header_title "Projects", root_path +- header_title "Projects", dashboard_projects_path - if current_user = render 'dashboard/projects_head' diff --git a/app/views/explore/projects/starred.html.haml b/app/views/explore/projects/starred.html.haml index 596cb0a96c..e30c363322 100644 --- a/app/views/explore/projects/starred.html.haml +++ b/app/views/explore/projects/starred.html.haml @@ -1,5 +1,5 @@ - page_title "Projects" -- header_title "Projects", root_path +- header_title "Projects", dashboard_projects_path - if current_user = render 'dashboard/projects_head' diff --git a/app/views/explore/projects/trending.html.haml b/app/views/explore/projects/trending.html.haml index 5ea6d81c5b..1412b19acd 100644 --- a/app/views/explore/projects/trending.html.haml +++ b/app/views/explore/projects/trending.html.haml @@ -1,5 +1,5 @@ - page_title "Projects" -- header_title "Projects", root_path +- header_title "Projects", dashboard_projects_path - if current_user = render 'dashboard/projects_head' diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml index 57308a661c..8daac58596 100644 --- a/app/views/groups/edit.html.haml +++ b/app/views/groups/edit.html.haml @@ -3,8 +3,7 @@ .panel.panel-default .panel-heading - %strong= @group.name - group settings: + Group settings .panel-body = form_for @group, html: { multipart: true, class: "form-horizontal" }, authenticity_token: true do |f| - if @group.errors.any? @@ -45,4 +44,5 @@ %br %strong Removed group can not be restored! - = link_to 'Remove Group', @group, data: {confirm: 'Removed group can not be restored! Are you sure?'}, method: :delete, class: "btn btn-remove" + .form-actions + = link_to 'Remove Group', @group, data: {confirm: 'Removed group can not be restored! Are you sure?'}, method: :delete, class: "btn btn-remove" diff --git a/app/views/groups/group_members/_group_member.html.haml b/app/views/groups/group_members/_group_member.html.haml index be94b1abc1..a79a0fcdc8 100644 --- a/app/views/groups/group_members/_group_member.html.haml +++ b/app/views/groups/group_members/_group_member.html.haml @@ -4,7 +4,7 @@ %li{class: "#{dom_class(member)} js-toggle-container", id: dom_id(member)} %span{class: ("list-item-name" if show_controls)} - if member.user - = image_tag avatar_icon(user, 16), class: "avatar s16", alt: '' + = image_tag avatar_icon(user, 24), class: "avatar s24", alt: '' %strong = link_to user.name, user_path(user) %span.cgray= user.username @@ -14,7 +14,7 @@ %label.label.label-danger %strong Blocked - else - = image_tag avatar_icon(member.invite_email, 16), class: "avatar s16", alt: '' + = image_tag avatar_icon(member.invite_email, 24), class: "avatar s24", alt: '' %strong = member.invite_email %span.cgray @@ -30,7 +30,7 @@ - if should_user_see_group_roles?(current_user, @group) %span.pull-right - %strong= member.human_access + %strong.member-access-level= member.human_access - if show_controls - if can?(current_user, :update_group_member, member) = button_tag class: "btn-xs btn js-toggle-button", diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml index d4ad33a8bf..335bf03607 100644 --- a/app/views/groups/group_members/index.html.haml +++ b/app/views/groups/group_members/index.html.haml @@ -1,38 +1,35 @@ - page_title "Members" - header_title group_title(@group, "Members", group_group_members_path(@group)) -- if should_user_see_group_roles?(current_user, @group) - %p.light - Members of group have access to all group projects. - Read more about permissions - %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink" - - -.clearfix.js-toggle-container - = form_tag group_group_members_path(@group), method: :get, class: 'form-inline member-search-form' do - .form-group - = search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control search-text-input', spellcheck: false } - = button_tag 'Search', class: 'btn' +- @blank_container = true +.group-members-page - if current_user && current_user.can?(:admin_group_member, @group) - .pull-right - = button_tag class: 'btn btn-new js-toggle-button', type: 'button' do - Add members - %i.fa.fa-chevron-down + .panel.panel-default + .panel-heading + Add new user to group + .panel-body + - if should_user_see_group_roles?(current_user, @group) + %p.light + Members of group have access to all group projects. + .new-group-member-holder + = render "new_group_member" - .js-toggle-content.hide.new-group-member-holder - = render "new_group_member" - -.panel.panel-default.prepend-top-20 - .panel-heading - %strong #{@group.name} - group members - %small - (#{@members.total_count}) - %ul.well-list - - @members.each do |member| - = render 'groups/group_members/group_member', member: member, show_controls: true - -= paginate @members, theme: 'gitlab' + .panel.panel-default + .panel-heading + %strong #{@group.name} + group members + %small + (#{@members.total_count}) + .pull-right + = form_tag group_group_members_path(@group), method: :get, class: 'form-inline member-search-form' do + .form-group + = search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control', spellcheck: false } + = button_tag class: 'btn', title: 'Search' do + = icon("search") + %ul.content-list + - @members.each do |member| + = render 'groups/group_members/group_member', member: member, show_controls: true + = paginate @members, theme: 'gitlab' :javascript $('form.member-search-form').on('submit', function(event) { diff --git a/app/views/groups/group_members/update.js.haml b/app/views/groups/group_members/update.js.haml index 5bad48abaf..df726e2b2b 100644 --- a/app/views/groups/group_members/update.js.haml +++ b/app/views/groups/group_members/update.js.haml @@ -1,2 +1,2 @@ :plain - $("##{dom_id(@member)}").replaceWith('#{escape_javascript(render(@member, member: @member, show_controls: true))}'); + $("##{dom_id(@group_member)}").replaceWith('#{escape_javascript(render(@group_member, member: @group_member, show_controls: true))}'); diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml index 08d97e418a..90ade1e168 100644 --- a/app/views/groups/issues.html.haml +++ b/app/views/groups/issues.html.haml @@ -4,21 +4,24 @@ - if current_user = auto_discovery_link_tag(:atom, issues_group_url(@group, format: :atom, private_token: current_user.private_token), title: "#{@group.name} issues") +.project-issuable-filter + .controls + .pull-left + - if current_user + .hidden-xs.pull-left + = link_to issues_group_url(@group, format: :atom, private_token: current_user.private_token), class: 'btn' do + %i.fa.fa-rss + = render 'shared/new_project_item_select', path: 'issues/new', label: "New Issue" + + = render 'shared/issuable/filter', type: :issues -= render 'shared/issuable/filter', type: :issues .gray-content-block.second-block - .pull-right - - if current_user - .hidden-xs.pull-left - = link_to issues_group_url(@group, format: :atom, private_token: current_user.private_token) do - %i.fa.fa-rss - %div - Only issues from - %strong #{@group.name} - group are listed here. - - if current_user - To see all issues you should visit #{link_to 'dashboard', issues_dashboard_path} page. + Only issues from + %strong #{@group.name} + group are listed here. + - if current_user + To see all issues you should visit #{link_to 'dashboard', issues_dashboard_path} page. .prepend-top-default = render 'shared/issues' diff --git a/app/views/groups/merge_requests.html.haml b/app/views/groups/merge_requests.html.haml index 425ad8331b..f662f5a8c1 100644 --- a/app/views/groups/merge_requests.html.haml +++ b/app/views/groups/merge_requests.html.haml @@ -1,13 +1,18 @@ - page_title "Merge Requests" - header_title group_title(@group, "Merge Requests", merge_requests_group_path(@group)) -= render 'shared/issuable/filter', type: :merge_requests +.project-issuable-filter + .controls + = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New Merge Request" + + = render 'shared/issuable/filter', type: :merge_requests + .gray-content-block.second-block - %div - Only merge requests from - %strong #{@group.name} - group are listed here. - - if current_user - To see all merge requests you should visit #{link_to 'dashboard', merge_requests_dashboard_path} page. + Only merge requests from + %strong #{@group.name} + group are listed here. + - if current_user + To see all merge requests you should visit #{link_to 'dashboard', merge_requests_dashboard_path} page. + .prepend-top-default = render 'shared/merge_requests' diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index 84ec77c618..b221d3a89a 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -1,18 +1,22 @@ - page_title "Milestones" - header_title group_title(@group, "Milestones", group_milestones_path(@group)) -= render 'shared/milestones_filter' -.gray-content-block - - if can?(current_user, :admin_milestones, @group) - .pull-right - %span.pull-right.hidden-xs - = link_to new_group_milestone_path(@group), class: "btn btn-new" do - New Milestone +.project-issuable-filter + .controls + - if can?(current_user, :admin_milestones, @group) + .pull-right + %span.pull-right.hidden-xs + = link_to new_group_milestone_path(@group), class: "btn btn-new" do + = icon('plus') + New Milestone + + = render 'shared/milestones_filter' + +.gray-content-block + Only milestones from + %strong #{@group.name} + group are listed here. - .oneline - Only milestones from - %strong #{@group.name} - group are listed here. .milestones %ul.content-list - if @milestones.blank? diff --git a/app/views/groups/milestones/new.html.haml b/app/views/groups/milestones/new.html.haml index 800bac4ef0..3894a0ece7 100644 --- a/app/views/groups/milestones/new.html.haml +++ b/app/views/groups/milestones/new.html.haml @@ -14,8 +14,7 @@ .form-group = f.label :title, "Title", class: "control-label" .col-sm-10 - = f.text_field :title, maxlength: 255, class: "form-control js-quick-submit", required: true - %p.hint Required + = f.text_field :title, maxlength: 255, class: "form-control js-quick-submit", required: true, autofocus: true .form-group.milestone-description = f.label :description, "Description", class: "control-label" .col-sm-10 diff --git a/app/views/groups/milestones/show.html.haml b/app/views/groups/milestones/show.html.haml index d161259e4a..d063b257b5 100644 --- a/app/views/groups/milestones/show.html.haml +++ b/app/views/groups/milestones/show.html.haml @@ -1,27 +1,29 @@ - page_title @milestone.title, "Milestones" = render "header_title" -%h4.page-title - .issue-box{ class: "issue-box-#{@milestone.closed? ? 'closed' : 'open'}" } +.detail-page-header + .status-box{ class: "status-box-#{@milestone.closed? ? 'closed' : 'open'}" } - if @milestone.closed? Closed - else Open - Milestone #{@milestone.title} + %span.identifier + Milestone #{@milestone.title} .pull-right - if can?(current_user, :admin_milestones, @group) - if @milestone.active? - = link_to 'Close Milestone', group_milestone_path(@group, @milestone.safe_title, title: @milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-sm btn-close" + = link_to 'Close Milestone', group_milestone_path(@group, @milestone.safe_title, title: @milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-grouped btn-close" - else - = link_to 'Reopen Milestone', group_milestone_path(@group, @milestone.safe_title, title: @milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-sm btn-grouped btn-reopen" + = link_to 'Reopen Milestone', group_milestone_path(@group, @milestone.safe_title, title: @milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-grouped btn-reopen" + +.detail-page-description.gray-content-block.second-block + %h2.title + = markdown escape_once(@milestone.title), pipeline: :single_line -%hr - if @milestone.complete? && @milestone.active? - .alert.alert-success + .alert.alert-success.prepend-top-default %span All issues for this milestone are closed. You may close the milestone now. -.description - .table-holder %table.table %thead @@ -52,7 +54,7 @@ #{@milestone.open_items_count} open = milestone_progress_bar(@milestone) -%ul.nav.nav-tabs +%ul.center-top-menu.no-top.no-bottom %li.active = link_to '#tab-issues', 'data-toggle' => 'tab' do Issues @@ -66,25 +68,40 @@ Participants %span.badge= @milestone.participants.count - .pull-right - = link_to 'Browse Issues', issues_group_path(@group, milestone_title: @milestone.title), class: "btn edit-milestone-link btn-grouped" - .tab-content .tab-pane.active#tab-issues - .row + .gray-content-block.middle-block + .pull-right + = link_to 'Browse Issues', issues_group_path(@group, milestone_title: @milestone.title), class: "btn btn-grouped" + + .oneline + All issues in this milestone + + .row.prepend-top-default .col-md-6 = render 'issues', title: "Open", issues: @milestone.opened_issues .col-md-6 = render 'issues', title: "Closed", issues: @milestone.closed_issues .tab-pane#tab-merge-requests - .row + .gray-content-block.middle-block + .pull-right + = link_to 'Browse Merge Requests', merge_requests_group_path(@group, milestone_title: @milestone.title), class: "btn btn-grouped" + + .oneline + All merge requests in this milestone + + .row.prepend-top-default .col-md-6 = render 'merge_requests', title: "Open", merge_requests: @milestone.opened_merge_requests .col-md-6 = render 'merge_requests', title: "Closed", merge_requests: @milestone.closed_merge_requests .tab-pane#tab-participants + .gray-content-block.middle-block + .oneline + All participants to this milestone + %ul.bordered-list - @milestone.participants.each do |user| %li diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml index 0665cdf387..4bc31cabea 100644 --- a/app/views/groups/new.html.haml +++ b/app/views/groups/new.html.haml @@ -1,5 +1,10 @@ - page_title 'New Group' -- header_title 'New Group' +- header_title "Groups", dashboard_groups_path + +%h3.page-title + New Group +%hr + = form_for @group, html: { class: 'group-form form-horizontal' } do |f| - if @group.errors.any? .alert.alert-danger @@ -18,3 +23,4 @@ .form-actions = f.submit 'Create group', class: "btn btn-create", tabindex: 3 + = link_to 'Cancel', dashboard_groups_path, class: 'btn btn-cancel' diff --git a/app/views/help/ui.html.haml b/app/views/help/ui.html.haml index 2169a821fb..d9ffda884c 100644 --- a/app/views/help/ui.html.haml +++ b/app/views/help/ui.html.haml @@ -31,11 +31,9 @@ %h2#blocks Blocks - %h3 + %h4 %code .gray-content-block - - .gray-content-block.middle-block %h4 Normal block inside content = lorem @@ -45,9 +43,28 @@ = lorem + %h4 + %code .cover-block + %br + .cover-block + .avatar-holder + = image_tag avatar_icon('admin@example.com', 90), class: "avatar s90", alt: '' + .cover-title + John Smith + + .cover-desc + = lorem + + .cover-controls + = link_to '#', class: 'btn btn-gray' do + = icon('pencil') +   + = link_to '#', class: 'btn btn-gray' do + = icon('rss') + %h2#lists Lists - %h3 + %h4 %code .content-list %ul.content-list %li @@ -57,7 +74,7 @@ %li One item - %h3 + %h4 %code .well-list %ul.well-list %li @@ -67,7 +84,7 @@ %li One item - %h3 + %h4 %code .panel .well-list .panel.panel-default @@ -80,7 +97,7 @@ %li One item - %h3 + %h4 %code .bordered-list %ul.bordered-list %li @@ -121,7 +138,7 @@ %h2#navs Navigation - %h3 + %h4 %code .center-top-menu .example %ul.center-top-menu @@ -130,7 +147,7 @@ %li %a Closed - %h3 + %h4 %code .btn-group.btn-group-next .example %div.btn-group.btn-group-next @@ -138,7 +155,7 @@ %a.btn Closed - %h3 + %h4 %code .nav.nav-tabs .example %ul.nav.nav-tabs @@ -204,7 +221,7 @@ %h2#forms Forms - %h3 + %h4 %code form.horizontal-form %form.form-horizontal @@ -226,7 +243,7 @@ .col-sm-offset-2.col-sm-10 %button.btn.btn-default{:type => "submit"} Sign in - %h3 + %h4 %code form %form @@ -243,7 +260,7 @@ %button.btn.btn-default{:type => "submit"} Sign in %h2#file File - %h3 + %h4 %code .file-holder - blob = Snippet.new(content: "Wow\nSuch\nFile") @@ -254,13 +271,12 @@ .file-actions .btn-group %a.btn Edit - %a.btn Remove + %a.btn.btn-danger Remove .file-contenta.code = render 'shared/file_highlight', blob: blob - %h2#markdown Markdown - %h3 + %h4 %code .md or .wiki and others Markdown rendering has a bit different css and presented in next UI elements: diff --git a/app/views/import/bitbucket/status.html.haml b/app/views/import/bitbucket/status.html.haml index 1f09a27e2d..aec2e836c9 100644 --- a/app/views/import/bitbucket/status.html.haml +++ b/app/views/import/bitbucket/status.html.haml @@ -1,4 +1,5 @@ - page_title "Bitbucket import" +- header_title "Projects", root_path %h3.page-title %i.fa.fa-bitbucket Import projects from Bitbucket diff --git a/app/views/import/fogbugz/new.html.haml b/app/views/import/fogbugz/new.html.haml index e1bb88ca4e..5515fad6f4 100644 --- a/app/views/import/fogbugz/new.html.haml +++ b/app/views/import/fogbugz/new.html.haml @@ -1,4 +1,5 @@ - page_title "FogBugz Import" +- header_title "Projects", root_path %h3.page-title %i.fa.fa-bug Import projects from FogBugz diff --git a/app/views/import/fogbugz/new_user_map.html.haml b/app/views/import/fogbugz/new_user_map.html.haml index bc3c90294e..07338736ba 100644 --- a/app/views/import/fogbugz/new_user_map.html.haml +++ b/app/views/import/fogbugz/new_user_map.html.haml @@ -1,4 +1,5 @@ - page_title 'User map', 'FogBugz import' +- header_title "Projects", root_path %h3.page-title %i.fa.fa-bug Import projects from FogBugz diff --git a/app/views/import/fogbugz/status.html.haml b/app/views/import/fogbugz/status.html.haml index b902006597..6ee16c8be4 100644 --- a/app/views/import/fogbugz/status.html.haml +++ b/app/views/import/fogbugz/status.html.haml @@ -1,4 +1,5 @@ - page_title "FogBugz import" +- header_title "Projects", root_path %h3.page-title %i.fa.fa-bug Import projects from FogBugz diff --git a/app/views/import/github/status.html.haml b/app/views/import/github/status.html.haml index 0699321c8c..1416ee5bd5 100644 --- a/app/views/import/github/status.html.haml +++ b/app/views/import/github/status.html.haml @@ -1,4 +1,5 @@ - page_title "GitHub import" +- header_title "Projects", root_path %h3.page-title %i.fa.fa-github Import projects from GitHub diff --git a/app/views/import/gitlab/status.html.haml b/app/views/import/gitlab/status.html.haml index f4a2b33af2..911a55eb85 100644 --- a/app/views/import/gitlab/status.html.haml +++ b/app/views/import/gitlab/status.html.haml @@ -1,4 +1,5 @@ - page_title "GitLab.com import" +- header_title "Projects", root_path %h3.page-title %i.fa.fa-heart Import projects from GitLab.com diff --git a/app/views/import/gitorious/status.html.haml b/app/views/import/gitorious/status.html.haml index 71752d21ef..6b0fa1edf8 100644 --- a/app/views/import/gitorious/status.html.haml +++ b/app/views/import/gitorious/status.html.haml @@ -1,4 +1,5 @@ - page_title "Gitorious import" +- header_title "Projects", root_path %h3.page-title %i.icon-gitorious.icon-gitorious-big Import projects from Gitorious.org diff --git a/app/views/import/google_code/new.html.haml b/app/views/import/google_code/new.html.haml index 9c64e0a009..5d2f149cd5 100644 --- a/app/views/import/google_code/new.html.haml +++ b/app/views/import/google_code/new.html.haml @@ -1,4 +1,5 @@ - page_title "Google Code import" +- header_title "Projects", root_path %h3.page-title %i.fa.fa-google Import projects from Google Code @@ -6,7 +7,7 @@ = form_tag callback_import_google_code_path, class: 'form-horizontal', multipart: true do %p - Follow the steps below to export your Google Code project data. + Follow the steps below to export your Google Code project data. In the next step, you'll be able to select the projects you want to import. %ol %li diff --git a/app/views/import/google_code/new_user_map.html.haml b/app/views/import/google_code/new_user_map.html.haml index e53ebda7dc..0738b3db1e 100644 --- a/app/views/import/google_code/new_user_map.html.haml +++ b/app/views/import/google_code/new_user_map.html.haml @@ -1,4 +1,5 @@ - page_title "User map", "Google Code import" +- header_title "Projects", root_path %h3.page-title %i.fa.fa-google Import projects from Google Code @@ -8,31 +9,31 @@ %p Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import. - %p + %p The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of :. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side. %ul %li %strong Default: Directly import the Google Code email address or username %p - "johnsmith@example.com": "johnsm...@example.com" - will add "By johnsm...@example.com" to all issues and comments originally created by johnsmith@example.com. + "johnsmith@example.com": "johnsm...@example.com" + will add "By johnsm...@example.com" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy. %li %strong Map a Google Code user to a GitLab user %p - "johnsmith@example.com": "@johnsmith" - will add "By @johnsmith" to all issues and comments originally created by johnsmith@example.com, + "johnsmith@example.com": "@johnsmith" + will add "By @johnsmith" to all issues and comments originally created by johnsmith@example.com, and will set @johnsmith as the assignee on all issues originally assigned to johnsmith@example.com. %li %strong Map a Google Code user to a full name %p - "johnsmith@example.com": "John Smith" + "johnsmith@example.com": "John Smith" will add "By John Smith" to all issues and comments originally created by johnsmith@example.com. %li %strong Map a Google Code user to a full email address %p - "johnsmith@example.com": "johnsmith@example.com" - will add "By johnsmith@example.com" to all issues and comments originally created by johnsmith@example.com. + "johnsmith@example.com": "johnsmith@example.com" + will add "By johnsmith@example.com" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address. .form-group diff --git a/app/views/import/google_code/status.html.haml b/app/views/import/google_code/status.html.haml index 8c64fd27e6..175ef6921c 100644 --- a/app/views/import/google_code/status.html.haml +++ b/app/views/import/google_code/status.html.haml @@ -1,4 +1,5 @@ - page_title "Google Code import" +- header_title "Projects", root_path %h3.page-title %i.fa.fa-google Import projects from Google Code diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml index 352b8040cf..ec7cd79bc5 100644 --- a/app/views/layouts/_page.html.haml +++ b/app/views/layouts/_page.html.haml @@ -1,8 +1,8 @@ -.page-with-sidebar{ class: nav_sidebar_class } +.page-with-sidebar{ class: page_sidebar_class } = render "layouts/broadcast" - .sidebar-wrapper.nicescroll + .sidebar-wrapper.nicescroll{ class: nav_sidebar_class } .header-logo - = link_to root_path, class: 'home', title: 'Dashboard', id: 'js-shortcuts-home', data: {toggle: 'tooltip', placement: 'bottom'} do + = link_to root_path, class: 'home', title: 'Dashboard', id: 'js-shortcuts-home' do = brand_header_logo .gitlab-text-container %h3 GitLab @@ -17,8 +17,8 @@ .collapse-nav = render partial: 'layouts/collapse_button' - if current_user - = link_to current_user, class: 'sidebar-user' do - = image_tag avatar_icon(current_user, 60), alt: 'User activity', class: 'avatar avatar s36' + = link_to current_user, class: 'sidebar-user', title: "Profile" do + = image_tag avatar_icon(current_user, 60), alt: 'Profile', class: 'avatar avatar s36' .username = current_user.username .content-wrapper diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml index 1c738719bd..6591c52bdb 100644 --- a/app/views/layouts/admin.html.haml +++ b/app/views/layouts/admin.html.haml @@ -1,5 +1,5 @@ -- page_title "Admin area" -- header_title "Admin area", admin_root_path +- page_title "Admin Area" +- header_title "Admin Area", admin_root_path - sidebar "admin" = render template: "layouts/application" diff --git a/app/views/layouts/ci/_nav_admin.html.haml b/app/views/layouts/ci/_nav_admin.html.haml deleted file mode 100644 index dcda04a463..0000000000 --- a/app/views/layouts/ci/_nav_admin.html.haml +++ /dev/null @@ -1,35 +0,0 @@ -%ul.nav.nav-sidebar - = nav_link do - = link_to admin_root_path, title: 'Back to admin', data: {placement: 'right'}, class: 'back-link' do - = icon('caret-square-o-left fw') - %span - Back to admin - - %li.separate-item - = nav_link path: 'projects#index' do - = link_to ci_admin_projects_path do - = icon('list-alt fw') - %span - Projects - = nav_link path: 'events#index' do - = link_to ci_admin_events_path do - = icon('book fw') - %span - Events - = nav_link path: ['runners#index', 'runners#show'] do - = link_to ci_admin_runners_path do - = icon('cog fw') - %span - Runners - %span.count= Ci::Runner.count(:all) - = nav_link path: 'builds#index' do - = link_to ci_admin_builds_path do - = icon('link fw') - %span - Builds - %span.count= Ci::Build.count(:all) - = nav_link(controller: :application_settings, html_options: { class: 'separate-item'}) do - = link_to ci_admin_application_settings_path do - = icon('cogs fw') - %span - Settings diff --git a/app/views/layouts/ci/_nav_project.html.haml b/app/views/layouts/ci/_nav_project.html.haml deleted file mode 100644 index f094edbfa8..0000000000 --- a/app/views/layouts/ci/_nav_project.html.haml +++ /dev/null @@ -1,12 +0,0 @@ -%ul.nav.nav-sidebar - = nav_link do - = link_to project_path(@project.gl_project), title: 'Back to project', data: {placement: 'right'}, class: 'back-link' do - = icon('caret-square-o-left fw') - %span - Back to project - %li.separate-item - = nav_link path: 'events#index' do - = link_to ci_project_events_path(@project) do - = icon('book fw') - %span - Events diff --git a/app/views/layouts/ci/_page.html.haml b/app/views/layouts/ci/_page.html.haml index ab3e29c3f4..7e90af21b2 100644 --- a/app/views/layouts/ci/_page.html.haml +++ b/app/views/layouts/ci/_page.html.haml @@ -1,8 +1,8 @@ -.page-with-sidebar{ class: nav_sidebar_class } +.page-with-sidebar{ class: page_sidebar_class } = render "layouts/broadcast" - .sidebar-wrapper.nicescroll + .sidebar-wrapper.nicescroll{ class: nav_sidebar_class } .header-logo - = link_to root_path, class: 'home', title: 'Dashboard', id: 'js-shortcuts-home', data: {toggle: 'tooltip', placement: 'bottom'} do + = link_to root_path, class: 'home', title: 'Dashboard', id: 'js-shortcuts-home' do = brand_header_logo .gitlab-text-container %h3 GitLab @@ -14,8 +14,8 @@ .collapse-nav = render partial: 'layouts/collapse_button' - if current_user - = link_to current_user, class: 'sidebar-user' do - = image_tag avatar_icon(current_user, 60), alt: 'User activity', class: 'avatar avatar s36' + = link_to current_user, class: 'sidebar-user', title: "Profile" do + = image_tag avatar_icon(current_user, 60), alt: 'Profile', class: 'avatar avatar s36' .username = current_user.username .content-wrapper diff --git a/app/views/layouts/ci/admin.html.haml b/app/views/layouts/ci/admin.html.haml deleted file mode 100644 index c8cb185d28..0000000000 --- a/app/views/layouts/ci/admin.html.haml +++ /dev/null @@ -1,11 +0,0 @@ -!!! 5 -%html{ lang: "en"} - = render 'layouts/head' - %body{class: "ci-body #{user_application_theme}", 'data-page' => body_data_page} - - header_title = "Admin area" - - if current_user - = render "layouts/header/default", title: header_title - - else - = render "layouts/header/public", title: header_title - - = render 'layouts/ci/page', sidebar: 'nav_admin' diff --git a/app/views/layouts/ci/application.html.haml b/app/views/layouts/ci/application.html.haml deleted file mode 100644 index 38023468d0..0000000000 --- a/app/views/layouts/ci/application.html.haml +++ /dev/null @@ -1,11 +0,0 @@ -!!! 5 -%html{ lang: "en"} - = render 'layouts/head' - %body{class: "ci-body #{user_application_theme}", 'data-page' => body_data_page} - - header_title = "Continuous Integration" - - if current_user - = render "layouts/header/default", title: header_title - - else - = render "layouts/header/public", title: header_title - - = render 'layouts/ci/page' diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml index 95e077c339..f08cb0a542 100644 --- a/app/views/layouts/devise.html.haml +++ b/app/views/layouts/devise.html.haml @@ -1,13 +1,13 @@ !!! 5 %html{ lang: "en"} = render "layouts/head" - %body.ui_charcoal.login-page.application + %body.ui_charcoal.login-page.application.navless = render "layouts/header/empty" = render "layouts/broadcast" .container.navless-container .content = render "layouts/flash" - .row.prepend-top-20 + .row .col-sm-5.pull-right = yield .col-sm-7.brand-holder.pull-left diff --git a/app/views/layouts/errors.html.haml b/app/views/layouts/errors.html.haml index 2af265a229..915acc4612 100644 --- a/app/views/layouts/errors.html.haml +++ b/app/views/layouts/errors.html.haml @@ -1,7 +1,7 @@ !!! 5 %html{ lang: "en"} = render "layouts/head" - %body{class: "#{user_application_theme} application"} + %body{class: "#{user_application_theme} application navless"} = render "layouts/header/empty" .container.navless-container = render "layouts/flash" diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index 3ca30d3baa..3892ef8eef 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -11,27 +11,27 @@ %li.hidden-sm.hidden-xs = render 'layouts/search' %li.visible-sm.visible-xs - = link_to search_path, title: 'Search', data: {toggle: 'tooltip', placement: 'bottom'} do + = link_to search_path, title: 'Search', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do = icon('search') - if session[:impersonator_id] %li.impersonation - = link_to stop_impersonation_admin_users_path, method: :delete, title: 'Stop impersonation', data: { toggle: 'tooltip', placement: 'bottom' } do + = link_to stop_impersonation_admin_users_path, method: :delete, title: 'Stop Impersonation', data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do = icon('user-secret fw') - if current_user.is_admin? %li - = link_to admin_root_path, title: 'Admin area', data: {toggle: 'tooltip', placement: 'bottom'} do + = link_to admin_root_path, title: 'Admin Area', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do = icon('wrench fw') - if current_user.can_create_project? %li - = link_to new_project_path, title: 'New project', data: {toggle: 'tooltip', placement: 'bottom'} do + = link_to new_project_path, title: 'New project', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do = icon('plus fw') - if Gitlab::Sherlock.enabled? %li = link_to sherlock_transactions_path, title: 'Sherlock Transactions', - data: {toggle: 'tooltip', placement: 'bottom'} do + data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do = icon('tachometer fw') %li - = link_to destroy_user_session_path, class: 'logout', method: :delete, title: 'Sign out', data: {toggle: 'tooltip', placement: 'bottom'} do + = link_to destroy_user_session_path, class: 'logout', method: :delete, title: 'Sign out', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do = icon('sign-out') %h1.title= title diff --git a/app/views/layouts/nav/_admin.html.haml b/app/views/layouts/nav/_admin.html.haml index 2079feeeab..c60ac5eefa 100644 --- a/app/views/layouts/nav/_admin.html.haml +++ b/app/views/layouts/nav/_admin.html.haml @@ -5,78 +5,85 @@ %span Overview = nav_link(controller: [:admin, :projects]) do - = link_to admin_namespaces_projects_path, title: 'Projects', data: {placement: 'right'} do + = link_to admin_namespaces_projects_path, title: 'Projects' do = icon('cube fw') %span Projects = nav_link(controller: :users) do - = link_to admin_users_path, title: 'Users', data: {placement: 'right'} do + = link_to admin_users_path, title: 'Users' do = icon('user fw') %span Users = nav_link(controller: :groups) do - = link_to admin_groups_path, title: 'Groups', data: {placement: 'right'} do + = link_to admin_groups_path, title: 'Groups' do = icon('group fw') %span Groups = nav_link(controller: :deploy_keys) do - = link_to admin_deploy_keys_path, title: 'Deploy Keys', data: {placement: 'right'} do + = link_to admin_deploy_keys_path, title: 'Deploy Keys' do = icon('key fw') %span Deploy Keys - = nav_link do - = link_to ci_admin_projects_path, title: 'Continuous Integration', data: {placement: 'right'} do - = icon('building fw') + = nav_link path: ['runners#index', 'runners#show'] do + = link_to admin_runners_path do + = icon('cog fw') %span - Continuous Integration + Runners + %span.count= Ci::Runner.count(:all) + = nav_link path: 'builds#index' do + = link_to admin_builds_path do + = icon('link fw') + %span + Builds + %span.count= Ci::Build.count(:all) = nav_link(controller: :logs) do - = link_to admin_logs_path, title: 'Logs', data: {placement: 'right'} do + = link_to admin_logs_path, title: 'Logs' do = icon('file-text fw') %span Logs = nav_link(controller: :broadcast_messages) do - = link_to admin_broadcast_messages_path, title: 'Broadcast Messages', data: {placement: 'right'} do + = link_to admin_broadcast_messages_path, title: 'Messages' do = icon('bullhorn fw') %span Messages = nav_link(controller: :hooks) do - = link_to admin_hooks_path, title: 'Hooks', data: {placement: 'right'} do + = link_to admin_hooks_path, title: 'Hooks' do = icon('external-link fw') %span Hooks = nav_link(controller: :background_jobs) do - = link_to admin_background_jobs_path, title: 'Background Jobs', data: {placement: 'right'} do + = link_to admin_background_jobs_path, title: 'Background Jobs' do = icon('cog fw') %span Background Jobs = nav_link(controller: :applications) do - = link_to admin_applications_path, title: 'Applications', data: {placement: 'right'} do + = link_to admin_applications_path, title: 'Applications' do = icon('cloud fw') %span Applications = nav_link(controller: :services) do - = link_to admin_application_settings_services_path, title: 'Service Templates', data: {placement: 'right'} do + = link_to admin_application_settings_services_path, title: 'Service Templates' do = icon('copy fw') %span Service Templates = nav_link(controller: :labels) do - = link_to admin_labels_path, title: 'Labels', data: {placement: 'right'} do + = link_to admin_labels_path, title: 'Labels' do = icon('tags fw') %span Labels = nav_link(controller: :abuse_reports) do - = link_to admin_abuse_reports_path, title: "Abuse reports" do + = link_to admin_abuse_reports_path, title: "Abuse Reports" do = icon('exclamation-circle fw') %span Abuse Reports %span.count= AbuseReport.count(:all) = nav_link(controller: :application_settings, html_options: { class: 'separate-item'}) do - = link_to admin_application_settings_path, title: 'Settings', data: {placement: 'right'} do + = link_to admin_application_settings_path, title: 'Settings' do = icon('cogs fw') %span Settings diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml index b1a1d53184..da69883130 100644 --- a/app/views/layouts/nav/_dashboard.html.haml +++ b/app/views/layouts/nav/_dashboard.html.haml @@ -1,50 +1,50 @@ %ul.nav.nav-sidebar = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: {class: 'home'}) do - = link_to dashboard_projects_path, title: 'Projects', data: {placement: 'right'} do + = link_to dashboard_projects_path, title: 'Projects' do = icon('home fw') %span Projects = nav_link(path: 'dashboard#activity') do - = link_to activity_dashboard_path, class: 'shortcuts-activity', title: 'Activity', data: {placement: 'right'} do + = link_to activity_dashboard_path, class: 'shortcuts-activity', title: 'Activity' do = icon('dashboard fw') %span Activity = nav_link(controller: :groups) do - = link_to dashboard_groups_path, title: 'Groups', data: {placement: 'right'} do + = link_to dashboard_groups_path, title: 'Groups' do = icon('group fw') %span Groups = nav_link(controller: :milestones) do - = link_to dashboard_milestones_path, title: 'Milestones', data: {placement: 'right'} do + = link_to dashboard_milestones_path, title: 'Milestones' do = icon('clock-o fw') %span Milestones = nav_link(path: 'dashboard#issues') do - = link_to assigned_issues_dashboard_path, title: 'Issues', class: 'shortcuts-issues', data: {placement: 'right'} do + = link_to assigned_issues_dashboard_path, title: 'Issues', class: 'shortcuts-issues' do = icon('exclamation-circle fw') %span Issues %span.count= current_user.assigned_issues.opened.count = nav_link(path: 'dashboard#merge_requests') do - = link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'shortcuts-merge_requests', data: {placement: 'right'} do + = link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'shortcuts-merge_requests' do = icon('tasks fw') %span Merge Requests %span.count= current_user.assigned_merge_requests.opened.count = nav_link(controller: :snippets) do - = link_to dashboard_snippets_path, title: 'Your snippets', data: {placement: 'right'} do + = link_to dashboard_snippets_path, title: 'Snippets' do = icon('clipboard fw') %span Snippets = nav_link(controller: :help) do - = link_to help_path, title: 'Help', data: {placement: 'right'} do + = link_to help_path, title: 'Help' do = icon('question-circle fw') %span Help %li.separate-item = nav_link(controller: :profile) do - = link_to profile_path, title: 'Profile settings', data: {placement: 'bottom'} do + = link_to profile_path, title: 'Profile Settings', data: {placement: 'bottom'} do = icon('user fw') %span Profile Settings diff --git a/app/views/layouts/nav/_explore.html.haml b/app/views/layouts/nav/_explore.html.haml index 21e565972a..48039ca291 100644 --- a/app/views/layouts/nav/_explore.html.haml +++ b/app/views/layouts/nav/_explore.html.haml @@ -1,21 +1,21 @@ %ul.nav.nav-sidebar = nav_link(path: ['dashboard#show', 'root#show', 'projects#trending', 'projects#starred', 'projects#index'], html_options: {class: 'home'}) do - = link_to explore_root_path, title: 'Projects', data: {placement: 'right'} do + = link_to explore_root_path, title: 'Projects' do = icon('home fw') %span Projects = nav_link(controller: :groups) do - = link_to explore_groups_path, title: 'Groups', data: {placement: 'right'} do + = link_to explore_groups_path, title: 'Groups' do = icon('group fw') %span Groups = nav_link(controller: :snippets) do - = link_to explore_snippets_path, title: 'Snippets', data: {placement: 'right'} do + = link_to explore_snippets_path, title: 'Snippets' do = icon('clipboard fw') %span Snippets = nav_link(controller: :help) do - = link_to help_path, title: 'Help', data: {placement: 'right'} do + = link_to help_path, title: 'Help' do = icon('question-circle fw') %span Help diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml index 319352876b..68da8d5de2 100644 --- a/app/views/layouts/nav/_group.html.haml +++ b/app/views/layouts/nav/_group.html.haml @@ -1,6 +1,6 @@ %ul.nav.nav-sidebar = nav_link do - = link_to root_path, title: 'Go to dashboard', data: {placement: 'right'}, class: 'back-link' do + = link_to root_path, title: 'Go to dashboard', class: 'back-link' do = icon('caret-square-o-left fw') %span Go to dashboard @@ -8,39 +8,39 @@ %li.separate-item = nav_link(path: 'groups#show', html_options: {class: 'home'}) do - = link_to group_path(@group), title: 'Home', data: {placement: 'right'} do + = link_to group_path(@group), title: 'Home' do = icon('dashboard fw') %span Group - if can?(current_user, :read_group, @group) - if current_user = nav_link(controller: [:group, :milestones]) do - = link_to group_milestones_path(@group), title: 'Milestones', data: {placement: 'right'} do + = link_to group_milestones_path(@group), title: 'Milestones' do = icon('clock-o fw') %span Milestones = nav_link(path: 'groups#issues') do - = link_to issues_group_path(@group), title: 'Issues', data: {placement: 'right'} do + = link_to issues_group_path(@group), title: 'Issues' do = icon('exclamation-circle fw') %span Issues - if current_user %span.count= Issue.opened.of_group(@group).count = nav_link(path: 'groups#merge_requests') do - = link_to merge_requests_group_path(@group), title: 'Merge Requests', data: {placement: 'right'} do + = link_to merge_requests_group_path(@group), title: 'Merge Requests' do = icon('tasks fw') %span Merge Requests - if current_user %span.count= MergeRequest.opened.of_group(@group).count = nav_link(controller: [:group_members]) do - = link_to group_group_members_path(@group), title: 'Members', data: {placement: 'right'} do + = link_to group_group_members_path(@group), title: 'Members' do = icon('users fw') %span Members - if can?(current_user, :admin_group, @group) = nav_link(html_options: { class: "separate-item" }) do - = link_to edit_group_path(@group), title: 'Settings', data: {placement: 'right'} do + = link_to edit_group_path(@group), title: 'Settings' do = icon ('cogs fw') %span Settings diff --git a/app/views/layouts/nav/_group_settings.html.haml b/app/views/layouts/nav/_group_settings.html.haml index c8411521f3..56a92fe910 100644 --- a/app/views/layouts/nav/_group_settings.html.haml +++ b/app/views/layouts/nav/_group_settings.html.haml @@ -1,6 +1,6 @@ %ul.nav.nav-sidebar = nav_link do - = link_to group_path(@group), title: 'Go to group', data: {placement: 'right'}, class: 'back-link' do + = link_to group_path(@group), title: 'Go to group', class: 'back-link' do = icon('caret-square-o-left fw') %span Go to group @@ -9,12 +9,12 @@ %ul.sidebar-subnav = nav_link(path: 'groups#edit') do - = link_to edit_group_path(@group), title: 'Group Settings', data: {placement: 'right'} do + = link_to edit_group_path(@group), title: 'Group Settings' do = icon ('pencil-square-o fw') %span Group Settings = nav_link(path: 'groups#projects') do - = link_to projects_group_path(@group), title: 'Projects', data: {placement: 'right'} do + = link_to projects_group_path(@group), title: 'Projects' do = icon('folder fw') %span Projects diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml index 0f3a793e30..64b30783c0 100644 --- a/app/views/layouts/nav/_profile.html.haml +++ b/app/views/layouts/nav/_profile.html.haml @@ -1,6 +1,6 @@ %ul.nav.nav-sidebar = nav_link do - = link_to root_path, title: 'Go to dashboard', data: {placement: 'right'}, class: 'back-link' do + = link_to root_path, title: 'Go to dashboard', class: 'back-link' do = icon('caret-square-o-left fw') %span Go to dashboard @@ -8,52 +8,52 @@ %li.separate-item = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do - = link_to profile_path, title: 'Profile', data: {placement: 'right'} do + = link_to profile_path, title: 'Profile Settings' do = icon('user fw') %span Profile Settings = nav_link(controller: [:accounts, :two_factor_auths]) do - = link_to profile_account_path, title: 'Account', data: {placement: 'right'} do + = link_to profile_account_path, title: 'Account' do = icon('gear fw') %span Account = nav_link(path: ['profiles#applications', 'applications#edit', 'applications#show', 'applications#new', 'applications#create']) do - = link_to applications_profile_path, title: 'Applications', data: {placement: 'right'} do + = link_to applications_profile_path, title: 'Applications' do = icon('cloud fw') %span Applications = nav_link(controller: :emails) do - = link_to profile_emails_path, title: 'Emails', data: {placement: 'right'} do + = link_to profile_emails_path, title: 'Emails' do = icon('envelope-o fw') %span Emails %span.count= current_user.emails.count + 1 - unless current_user.ldap_user? = nav_link(controller: :passwords) do - = link_to edit_profile_password_path, title: 'Password', data: {placement: 'right'} do + = link_to edit_profile_password_path, title: 'Password' do = icon('lock fw') %span Password = nav_link(controller: :notifications) do - = link_to profile_notifications_path, title: 'Notifications', data: {placement: 'right'} do + = link_to profile_notifications_path, title: 'Notifications' do = icon('inbox fw') %span Notifications = nav_link(controller: :keys) do - = link_to profile_keys_path, title: 'SSH Keys', data: {placement: 'right'} do + = link_to profile_keys_path, title: 'SSH Keys' do = icon('key fw') %span SSH Keys %span.count= current_user.keys.count = nav_link(controller: :preferences) do - = link_to profile_preferences_path, title: 'Preferences', data: {placement: 'right'} do + = link_to profile_preferences_path, title: 'Preferences' do -# TODO (rspeicher): Better icon? = icon('image fw') %span Preferences = nav_link(path: 'profiles#audit_log') do - = link_to audit_log_profile_path, title: 'Audit Log', data: {placement: 'right'} do + = link_to audit_log_profile_path, title: 'Audit Log' do = icon('history fw') %span Audit Log diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml index 2b91d7721f..c0d6202863 100644 --- a/app/views/layouts/nav/_project.html.haml +++ b/app/views/layouts/nav/_project.html.haml @@ -1,13 +1,13 @@ %ul.nav.nav-sidebar - if @project.group = nav_link do - = link_to group_path(@project.group), title: 'Go to group', data: {placement: 'right'}, class: 'back-link' do + = link_to group_path(@project.group), title: 'Go to group', class: 'back-link' do = icon('caret-square-o-left fw') %span Go to group - else = nav_link do - = link_to root_path, title: 'Go to dashboard', data: {placement: 'right'}, class: 'back-link' do + = link_to root_path, title: 'Go to dashboard', class: 'back-link' do = icon('caret-square-o-left fw') %span Go to dashboard @@ -15,61 +15,54 @@ %li.separate-item = nav_link(path: 'projects#show', html_options: {class: 'home'}) do - = link_to project_path(@project), title: 'Project', class: 'shortcuts-project', data: {placement: 'right'} do + = link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do = icon('home fw') %span Project = nav_link(path: 'projects#activity') do - = link_to activity_project_path(@project), title: 'Project Activity', class: 'shortcuts-project-activity', data: {placement: 'right'} do + = link_to activity_project_path(@project), title: 'Activity', class: 'shortcuts-project-activity' do = icon('dashboard fw') %span Activity - if project_nav_tab? :files = nav_link(controller: %w(tree blob blame edit_tree new_tree)) do - = link_to project_files_path(@project), title: 'Files', class: 'shortcuts-tree', data: {placement: 'right'} do + = link_to project_files_path(@project), title: 'Files', class: 'shortcuts-tree' do = icon('files-o fw') %span Files - if project_nav_tab? :commits - = nav_link(controller: %w(commit commits compare repositories tags branches releases)) do - = link_to project_commits_path(@project), title: 'Commits', class: 'shortcuts-commits', data: {placement: 'right'} do + = nav_link(controller: %w(commit commits compare repositories tags branches releases network)) do + = link_to project_commits_path(@project), title: 'Commits', class: 'shortcuts-commits' do = icon('history fw') %span Commits - if project_nav_tab? :builds = nav_link(controller: %w(builds)) do - = link_to project_builds_path(@project), title: 'Builds', class: 'shortcuts-builds', data: {placement: 'right'} do + = link_to project_builds_path(@project), title: 'Builds', class: 'shortcuts-builds' do = icon('cubes fw') %span Builds - %span.count.builds_counter= @project.ci_builds.running_or_pending.count(:all) - - - if project_nav_tab? :network - = nav_link(controller: %w(network)) do - = link_to namespace_project_network_path(@project.namespace, @project, current_ref), title: 'Network', class: 'shortcuts-network', data: {placement: 'right'} do - = icon('code-fork fw') - %span - Network + %span.count.builds_counter= @project.builds.running_or_pending.count(:all) - if project_nav_tab? :graphs = nav_link(controller: %w(graphs)) do - = link_to namespace_project_graph_path(@project.namespace, @project, current_ref), title: 'Graphs', class: 'shortcuts-graphs', data: {placement: 'right'} do + = link_to namespace_project_graph_path(@project.namespace, @project, current_ref), title: 'Graphs', class: 'shortcuts-graphs' do = icon('area-chart fw') %span Graphs - if project_nav_tab? :milestones = nav_link(controller: :milestones) do - = link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones', data: {placement: 'right'} do + = link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones' do = icon('clock-o fw') %span Milestones - if project_nav_tab? :issues = nav_link(controller: :issues) do - = link_to url_for_project_issues(@project, only_path: true), title: 'Issues', class: 'shortcuts-issues', data: {placement: 'right'} do + = link_to url_for_project_issues(@project, only_path: true), title: 'Issues', class: 'shortcuts-issues' do = icon('exclamation-circle fw') %span Issues @@ -78,7 +71,7 @@ - if project_nav_tab? :merge_requests = nav_link(controller: :merge_requests) do - = link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests', class: 'shortcuts-merge_requests', data: {placement: 'right'} do + = link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do = icon('tasks fw') %span Merge Requests @@ -86,35 +79,42 @@ - if project_nav_tab? :settings = nav_link(controller: [:project_members, :teams]) do - = link_to namespace_project_project_members_path(@project.namespace, @project), title: 'Members', class: 'team-tab tab', data: {placement: 'right'} do + = link_to namespace_project_project_members_path(@project.namespace, @project), title: 'Members', class: 'team-tab tab' do = icon('users fw') %span Members - if project_nav_tab? :labels = nav_link(controller: :labels) do - = link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels', data: {placement: 'right'} do + = link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels' do = icon('tags fw') %span Labels - if project_nav_tab? :wiki = nav_link(controller: :wikis) do - = link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki', data: {placement: 'right'} do + = link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki' do = icon('book fw') %span Wiki - if project_nav_tab? :snippets = nav_link(controller: :snippets) do - = link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets', data: {placement: 'right'} do + = link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets' do = icon('clipboard fw') %span Snippets - if project_nav_tab? :settings = nav_link(html_options: {class: "#{project_tab_class} separate-item"}) do - = link_to edit_project_path(@project), title: 'Settings', data: {placement: 'right'} do + = link_to edit_project_path(@project), title: 'Settings' do = icon('cogs fw') %span Settings + + -# Global shortcut to network page for compatibility + - if project_nav_tab? :network + %li.hidden + = link_to namespace_project_network_path(@project.namespace, @project, current_ref), title: 'Network', class: 'shortcuts-network' do + Network + diff --git a/app/views/layouts/nav/_project_settings.html.haml b/app/views/layouts/nav/_project_settings.html.haml index 377a99e719..970da78a5c 100644 --- a/app/views/layouts/nav/_project_settings.html.haml +++ b/app/views/layouts/nav/_project_settings.html.haml @@ -1,6 +1,6 @@ %ul.nav.nav-sidebar = nav_link do - = link_to project_path(@project), title: 'Go to project', data: {placement: 'right'}, class: 'back-link' do + = link_to project_path(@project), title: 'Go to project', class: 'back-link' do = icon('caret-square-o-left fw') %span Go to project @@ -9,59 +9,44 @@ %ul.sidebar-subnav = nav_link(path: 'projects#edit') do - = link_to edit_project_path(@project), title: 'Project Settings', data: {placement: 'right'} do + = link_to edit_project_path(@project), title: 'Project Settings' do = icon('pencil-square-o fw') %span Project Settings = nav_link(controller: :deploy_keys) do - = link_to namespace_project_deploy_keys_path(@project.namespace, @project), title: 'Deploy Keys', data: {placement: 'right'} do + = link_to namespace_project_deploy_keys_path(@project.namespace, @project), title: 'Deploy Keys' do = icon('key fw') %span Deploy Keys = nav_link(controller: :hooks) do - = link_to namespace_project_hooks_path(@project.namespace, @project), title: 'Web Hooks', data: {placement: 'right'} do + = link_to namespace_project_hooks_path(@project.namespace, @project), title: 'Web Hooks' do = icon('link fw') %span Web Hooks = nav_link(controller: :services) do - = link_to namespace_project_services_path(@project.namespace, @project), title: 'Services', data: {placement: 'right'} do + = link_to namespace_project_services_path(@project.namespace, @project), title: 'Services' do = icon('cogs fw') %span Services = nav_link(controller: :protected_branches) do - = link_to namespace_project_protected_branches_path(@project.namespace, @project), title: 'Protected Branches', data: {placement: 'right'} do + = link_to namespace_project_protected_branches_path(@project.namespace, @project), title: 'Protected Branches' do = icon('lock fw') %span Protected Branches - if @project.builds_enabled? = nav_link(controller: :runners) do - = link_to namespace_project_runners_path(@project.namespace, @project), title: 'Runners', data: {placement: 'right'} do + = link_to namespace_project_runners_path(@project.namespace, @project), title: 'Runners' do = icon('cog fw') %span Runners = nav_link(controller: :variables) do - = link_to namespace_project_variables_path(@project.namespace, @project) do + = link_to namespace_project_variables_path(@project.namespace, @project), title: 'Variables' do = icon('code fw') %span Variables = nav_link path: 'triggers#index' do - = link_to namespace_project_triggers_path(@project.namespace, @project) do + = link_to namespace_project_triggers_path(@project.namespace, @project), title: 'Triggers' do = icon('retweet fw') %span Triggers - = nav_link path: 'ci_web_hooks#index' do - = link_to namespace_project_ci_web_hooks_path(@project.namespace, @project) do - = icon('link fw') - %span - CI Web Hooks - = nav_link path: 'ci_settings#edit' do - = link_to edit_namespace_project_ci_settings_path(@project.namespace, @project) do - = icon('building fw') - %span - CI Settings - = nav_link controller: 'ci_services' do - = link_to namespace_project_ci_services_path(@project.namespace, @project) do - = icon('share fw') - %span - CI Services diff --git a/app/views/ci/notify/build_fail_email.html.haml b/app/views/notify/build_fail_email.html.haml similarity index 69% rename from app/views/ci/notify/build_fail_email.html.haml rename to app/views/notify/build_fail_email.html.haml index b0aaea8907..f4e9749e5c 100644 --- a/app/views/ci/notify/build_fail_email.html.haml +++ b/app/views/notify/build_fail_email.html.haml @@ -1,13 +1,13 @@ - content_for :header do %h1{style: "background: #c40834; color: #FFF; font: normal 20px Helvetica, Arial, sans-serif; margin: 0; padding: 5px 10px; line-height: 32px; font-size: 16px;"} - GitLab CI (build failed) + GitLab (build failed) %h3 Project: = link_to ci_project_url(@project) do = @project.name %p - Commit: #{link_to @build.short_sha, namespace_project_commit_path(@build.gl_project.namespace, @build.gl_project, @build.sha)} + Commit: #{link_to @build.short_sha, namespace_project_commit_url(@build.project.namespace, @build.project, @build.sha)} %p Author: #{@build.commit.git_author_name} %p @@ -20,4 +20,4 @@ Message: #{@build.commit.git_commit_message} %p - Build details: #{link_to "Build #{@build.id}", namespace_project_build_url(@build.gl_project.namespace, @build.gl_project, @build)} + Build details: #{link_to "Build #{@build.id}", namespace_project_build_url(@build.project.namespace, @build.project, @build)} diff --git a/app/views/ci/notify/build_fail_email.text.erb b/app/views/notify/build_fail_email.text.erb similarity index 74% rename from app/views/ci/notify/build_fail_email.text.erb rename to app/views/notify/build_fail_email.text.erb index 17a3b9b1d3..675acea60a 100644 --- a/app/views/ci/notify/build_fail_email.text.erb +++ b/app/views/notify/build_fail_email.text.erb @@ -8,4 +8,4 @@ Stage: <%= @build.stage %> Job: <%= @build.name %> Message: <%= @build.commit.git_commit_message %> -Url: <%= namespace_project_build_url(@build.gl_project.namespace, @build.gl_project, @build) %> +Url: <%= namespace_project_build_url(@build.project.namespace, @build.project, @build) %> diff --git a/app/views/ci/notify/build_success_email.html.haml b/app/views/notify/build_success_email.html.haml similarity index 68% rename from app/views/ci/notify/build_success_email.html.haml rename to app/views/notify/build_success_email.html.haml index 24c439e50e..8b004d34cc 100644 --- a/app/views/ci/notify/build_success_email.html.haml +++ b/app/views/notify/build_success_email.html.haml @@ -1,6 +1,6 @@ - content_for :header do %h1{style: "background: #38CF5B; color: #FFF; font: normal 20px Helvetica, Arial, sans-serif; margin: 0; padding: 5px 10px; line-height: 32px; font-size: 16px;"} - GitLab CI (build successful) + GitLab (build successful) %h3 Project: @@ -8,7 +8,7 @@ = @project.name %p - Commit: #{link_to @build.short_sha, namespace_project_commit_path(@build.gl_project.namespace, @build.gl_project, @build.sha)} + Commit: #{link_to @build.short_sha, namespace_project_commit_url(@build.project.namespace, @build.project, @build.sha)} %p Author: #{@build.commit.git_author_name} %p @@ -21,4 +21,4 @@ Message: #{@build.commit.git_commit_message} %p - Build details: #{link_to "Build #{@build.id}", namespace_project_build_url(@build.gl_project.namespace, @build.gl_project, @build)} + Build details: #{link_to "Build #{@build.id}", namespace_project_build_url(@build.project.namespace, @build.project, @build)} diff --git a/app/views/ci/notify/build_success_email.text.erb b/app/views/notify/build_success_email.text.erb similarity index 74% rename from app/views/ci/notify/build_success_email.text.erb rename to app/views/notify/build_success_email.text.erb index bc8b978c3d..747da44aca 100644 --- a/app/views/ci/notify/build_success_email.text.erb +++ b/app/views/notify/build_success_email.text.erb @@ -8,4 +8,4 @@ Stage: <%= @build.stage %> Job: <%= @build.name %> Message: <%= @build.commit.git_commit_message %> -Url: <%= namespace_project_build_url(@build.gl_project.namespace, @build.gl_project, @build) %> +Url: <%= namespace_project_build_url(@build.project.namespace, @build.project, @build) %> diff --git a/app/views/notify/repository_push_email.html.haml b/app/views/notify/repository_push_email.html.haml index 12f83aae04..4361f67a74 100644 --- a/app/views/notify/repository_push_email.html.haml +++ b/app/views/notify/repository_push_email.html.haml @@ -1,30 +1,32 @@ -%h3 #{@author.name} #{@action_name} #{@ref_type} #{@ref_name} at #{link_to @project.name_with_namespace, namespace_project_url(@project.namespace, @project)} +%h3 + #{@message.author_name} #{@message.action_name} #{@message.ref_type} #{@message.ref_name} + at #{link_to(@message.project_name_with_namespace, namespace_project_url(@message.project_namespace, @message.project))} -- if @compare - - if @reverse_compare +- if @message.compare + - if @message.reverse_compare? %p %strong WARNING: The push did not contain any new commits, but force pushed to delete the commits and changes below. %h4 - = @reverse_compare ? "Deleted commits:" : "Commits:" + = @message.reverse_compare? ? "Deleted commits:" : "Commits:" %ul - - @commits.each do |commit| + - @message.commits.each do |commit| %li - %strong #{link_to commit.short_id, namespace_project_commit_url(@project.namespace, @project, commit)} + %strong #{link_to(commit.short_id, namespace_project_commit_url(@message.project_namespace, @message.project, commit))} %div %span by #{commit.author_name} %i at #{commit.committed_date.strftime("%Y-%m-%dT%H:%M:%SZ")} %pre.commit-message = commit.safe_message - %h4 #{pluralize @diffs.count, "changed file"}: + %h4 #{pluralize @message.diffs_count, "changed file"}: %ul - - @diffs.each_with_index do |diff, i| + - @message.diffs.each_with_index do |diff, i| %li.file-stats - %a{href: "#{@target_url if @disable_diffs}#diff-#{i}" } + %a{href: "#{@message.target_url if @message.disable_diffs?}#diff-#{i}" } - if diff.deleted_file %span.deleted-file − @@ -40,11 +42,11 @@ - else = diff.new_path - - unless @disable_diffs + - unless @message.disable_diffs? %h4 Changes: - - @diffs.each_with_index do |diff, i| + - @message.diffs.each_with_index do |diff, i| %li{id: "diff-#{i}"} - %a{href: @target_url + "#diff-#{i}"} + %a{href: @message.target_url + "#diff-#{i}"} - if diff.deleted_file %strong = diff.old_path @@ -62,5 +64,5 @@ = color_email_diff(diff.diff) %br - - if @compare.timeout + - if @message.compare_timeout %h5 Huge diff. To prevent performance issues changes are hidden diff --git a/app/views/notify/repository_push_email.text.haml b/app/views/notify/repository_push_email.text.haml index 97a176ed2a..aa0e263b6d 100644 --- a/app/views/notify/repository_push_email.text.haml +++ b/app/views/notify/repository_push_email.text.haml @@ -1,21 +1,21 @@ -#{@author.name} #{@action_name} #{@ref_type} #{@ref_name} at #{@project.name_with_namespace} -- if @compare +#{@message.author_name} #{@message.action_name} #{@message.ref_type} #{@message.ref_name} at #{@message.project_name_with_namespace} +- if @message.compare \ \ - - if @reverse_compare + - if @message.reverse_compare? WARNING: The push did not contain any new commits, but force pushed to delete the commits and changes below. \ \ - = @reverse_compare ? "Deleted commits:" : "Commits:" - - @commits.each do |commit| + = @message.reverse_compare? ? "Deleted commits:" : "Commits:" + - @message.commits.each do |commit| #{commit.short_id} by #{commit.author_name} at #{commit.committed_date.strftime("%Y-%m-%dT%H:%M:%SZ")} #{commit.safe_message} \- - - - - \ \ - #{pluralize @diffs.count, "changed file"}: + #{pluralize @message.diffs_count, "changed file"}: \ - - @diffs.each do |diff| + - @message.diffs.each do |diff| - if diff.deleted_file \- − #{diff.old_path} - elsif diff.renamed_file @@ -24,11 +24,11 @@ \- + #{diff.new_path} - else \- #{diff.new_path} - - unless @disable_diffs + - unless @message.disable_diffs? \ \ Changes: - - @diffs.each do |diff| + - @message.diffs.each do |diff| \ \===================================== - if diff.deleted_file @@ -39,11 +39,11 @@ = diff.new_path \===================================== != diff.diff - - if @compare.timeout + - if @message.compare_timeout \ \ Huge diff. To prevent performance issues it was hidden - - if @target_url + - if @message.target_url \ \ - View it on GitLab: #{@target_url} + View it on GitLab: #{@message.target_url} diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml index cd7b1b0fe0..17e47c622c 100644 --- a/app/views/profiles/accounts/show.html.haml +++ b/app/views/profiles/accounts/show.html.haml @@ -23,11 +23,14 @@ %p.cgray - if current_user.private_token = text_field_tag "token", current_user.private_token, class: "form-control" - %div - = f.submit 'Reset private token', data: { confirm: "Are you sure?" }, class: "btn btn-default btn-build-token" - else %span You don`t have one yet. Click generate to fix it. - = f.submit 'Generate', class: "btn btn-default btn-build-token" + + .form-actions + - if current_user.private_token + = f.submit 'Reset private token', data: { confirm: "Are you sure?" }, class: "btn btn-default" + - else + = f.submit 'Generate', class: "btn btn-default" - unless current_user.ldap_user? .panel.panel-default @@ -54,7 +57,8 @@ %p Each time you log in you’ll be required to provide your username and password as usual, plus a randomly-generated code from your phone. - %div + + .form-actions = link_to 'Enable Two-factor Authentication', new_profile_two_factor_auth_path, class: 'btn btn-success' - if button_based_providers.any? @@ -81,15 +85,16 @@ %p Changing your username will change path to all personal projects! %div - = f.text_field :username, required: true, class: 'form-control' + .input-group + .input-group-addon + = "#{root_url}u/" + = f.text_field :username, required: true, class: 'form-control'   .loading-gif.hide %p = icon('spinner spin') Saving new username - %p.light - = user_url(@user) - %div + .form-actions = f.submit 'Save username', class: "btn btn-warning" - if signup_enabled? @@ -104,7 +109,8 @@ - rp = current_user.personal_projects.count - unless rp.zero? %li #{pluralize rp, 'personal project'} will be removed and cannot be restored - = link_to 'Delete account', user_registration_path, data: { confirm: "REMOVE #{current_user.name}? Are you sure?" }, method: :delete, class: "btn btn-remove" + .form-actions + = link_to 'Delete account', user_registration_path, data: { confirm: "REMOVE #{current_user.name}? Are you sure?" }, method: :delete, class: "btn btn-remove" - else - if @user.solo_owned_groups.present? %p diff --git a/app/views/profiles/applications.html.haml b/app/views/profiles/applications.html.haml index 2342936a5d..0436c2213d 100644 --- a/app/views/profiles/applications.html.haml +++ b/app/views/profiles/applications.html.haml @@ -15,24 +15,25 @@ .pull-right = link_to 'New Application', new_oauth_application_path, class: 'btn btn-success' - if @applications.any? - %table.table.table-striped - %thead - %tr - %th Name - %th Callback URL - %th Clients - %th - %th - %tbody - - @applications.each do |application| - %tr{:id => "application_#{application.id}"} - %td= link_to application.name, oauth_application_path(application) - %td - - application.redirect_uri.split.each do |uri| - %div= uri - %td= application.access_tokens.count - %td= link_to 'Edit', edit_oauth_application_path(application), class: 'btn btn-link btn-sm' - %td= render 'doorkeeper/applications/delete_form', application: application + .table-holder + %table.table.table-striped + %thead + %tr + %th Name + %th Callback URL + %th Clients + %th + %th + %tbody + - @applications.each do |application| + %tr{:id => "application_#{application.id}"} + %td= link_to application.name, oauth_application_path(application) + %td + - application.redirect_uri.split.each do |uri| + %div= uri + %td= application.access_tokens.count + %td= link_to 'Edit', edit_oauth_application_path(application), class: 'btn btn-link btn-sm' + %td= render 'doorkeeper/applications/delete_form', application: application .oauth-authorized-applications.prepend-top-20 - if user_oauth_applications? @@ -40,29 +41,30 @@ Authorized applications - if @authorized_tokens.any? - %table.table.table-striped - %thead - %tr - %th Name - %th Authorized At - %th Scope - %th - %tbody - - @authorized_apps.each do |app| - - token = app.authorized_tokens.order('created_at desc').first - %tr{:id => "application_#{app.id}"} - %td= app.name - %td= token.created_at - %td= token.scopes - %td= render 'doorkeeper/authorized_applications/delete_form', application: app - - @authorized_anonymous_tokens.each do |token| + .table-holder + %table.table.table-striped + %thead %tr - %td - Anonymous - %div.help-block - %em Authorization was granted by entering your username and password in the application. - %td= token.created_at - %td= token.scopes - %td= render 'doorkeeper/authorized_applications/delete_form', token: token + %th Name + %th Authorized At + %th Scope + %th + %tbody + - @authorized_apps.each do |app| + - token = app.authorized_tokens.order('created_at desc').first + %tr{:id => "application_#{app.id}"} + %td= app.name + %td= token.created_at + %td= token.scopes + %td= render 'doorkeeper/authorized_applications/delete_form', application: app + - @authorized_anonymous_tokens.each do |token| + %tr + %td + Anonymous + %div.help-block + %em Authorization was granted by entering your username and password in the application. + %td= token.created_at + %td= token.scopes + %td= render 'doorkeeper/authorized_applications/delete_form', token: token - else %p.light You don't have any authorized applications diff --git a/app/views/profiles/keys/_form.html.haml b/app/views/profiles/keys/_form.html.haml index b76a5b636a..2a8800de60 100644 --- a/app/views/profiles/keys/_form.html.haml +++ b/app/views/profiles/keys/_form.html.haml @@ -1,5 +1,5 @@ %div - = form_for [:profile, @key], html: { class: 'form-horizontal' } do |f| + = form_for [:profile, @key], html: { class: 'form-horizontal js-requires-input' } do |f| - if @key.errors.any? .alert.alert-danger %ul @@ -9,12 +9,11 @@ .form-group = f.label :key, class: 'control-label' .col-sm-10 - = f.text_area :key, class: "form-control", rows: 8 + = f.text_area :key, class: "form-control", rows: 8, autofocus: true, required: true .form-group = f.label :title, class: 'control-label' - .col-sm-10= f.text_field :title, class: "form-control" + .col-sm-10= f.text_field :title, class: "form-control", required: true .form-actions = f.submit 'Add key', class: "btn btn-create" = link_to "Cancel", profile_keys_path, class: "btn btn-cancel" - diff --git a/app/views/profiles/keys/_key_table.html.haml b/app/views/profiles/keys/_key_table.html.haml index ef0075aad3..8c9d546af4 100644 --- a/app/views/profiles/keys/_key_table.html.haml +++ b/app/views/profiles/keys/_key_table.html.haml @@ -1,6 +1,6 @@ - is_admin = defined?(admin) ? true : false -.panel.panel-default - - if @keys.any? +- if @keys.any? + .table-holder %table.table %thead.panel-heading %tr @@ -11,9 +11,9 @@ %tbody - @keys.each do |key| = render 'profiles/keys/key', key: key, is_admin: is_admin - - else - .nothing-here-block - - if is_admin - User has no ssh keys - - else - There are no SSH keys with access to your account. +- else + .nothing-here-block + - if is_admin + User has no ssh keys + - else + There are no SSH keys with access to your account. diff --git a/app/views/profiles/keys/index.html.haml b/app/views/profiles/keys/index.html.haml index 14adba1c79..17a4195030 100644 --- a/app/views/profiles/keys/index.html.haml +++ b/app/views/profiles/keys/index.html.haml @@ -3,7 +3,9 @@ .gray-content-block.top-block .pull-right - = link_to "Add SSH Key", new_profile_key_path, class: "btn btn-new" + = link_to new_profile_key_path, class: "btn btn-new" do + = icon('plus') + Add SSH Key .oneline Before you can add an SSH key you need to = link_to "generate it.", help_page_path("ssh", "README") diff --git a/app/views/profiles/keys/new.html.haml b/app/views/profiles/keys/new.html.haml index 2bf207a322..11166dc6d9 100644 --- a/app/views/profiles/keys/new.html.haml +++ b/app/views/profiles/keys/new.html.haml @@ -9,7 +9,7 @@ $('#key_key').on('focusout', function(){ var title = $('#key_title'), val = $('#key_key').val(), - comment = val.match(/^\S+ \S+ (.+)$/); + comment = val.match(/^\S+ \S+ (.+)\n?$/); if( comment && comment.length > 1 && title.val() == '' ){ $('#key_title').val( comment[1] ); diff --git a/app/views/profiles/notifications/show.html.haml b/app/views/profiles/notifications/show.html.haml index 8eebd96b67..0bcadc965f 100644 --- a/app/views/profiles/notifications/show.html.haml +++ b/app/views/profiles/notifications/show.html.haml @@ -50,12 +50,10 @@ Watch %p You will receive notifications for any activity - .form-actions + .gray-content-block = f.submit 'Save changes', class: "btn btn-create" -.clearfix - %hr -.row.all-notifications +.row.all-notifications.prepend-top-default .col-md-6 %p You can also specify notification level per group or per project. diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml index cc41d7dd81..877589dc39 100644 --- a/app/views/profiles/preferences/show.html.haml +++ b/app/views/profiles/preferences/show.html.haml @@ -54,4 +54,4 @@ .help-block Choose what content you want to see on a project's home page. .panel-footer - = f.submit 'Save', class: 'btn btn-save' + = f.submit 'Save changes', class: 'btn btn-save' diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml index ac7355dde1..9459d8a629 100644 --- a/app/views/profiles/show.html.haml +++ b/app/views/profiles/show.html.haml @@ -43,7 +43,7 @@ .form-group = f.label :public_email, class: "control-label" .col-sm-10 - = f.select :public_email, options_for_select(@user.all_emails, selected: @user.public_email), {include_blank: 'Do not show in profile'}, class: "form-control" + = f.select :public_email, options_for_select(@user.all_emails, selected: @user.public_email), {include_blank: 'Do not show on profile'}, class: "select2" %span.help-block This email will be displayed on your public profile. .form-group = f.label :skype, class: "control-label" @@ -96,8 +96,6 @@ = link_to 'Remove avatar', profile_avatar_path, data: { confirm: "Avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar" - .row - .col-md-7 - .form-group - .col-sm-offset-2.col-sm-10 - = f.submit 'Save changes', class: "btn btn-success" + .form-actions + = f.submit 'Save changes', class: "btn btn-success" + = link_to "Cancel", user_path(current_user), class: "btn btn-cancel" diff --git a/app/views/projects/_commit_button.html.haml b/app/views/projects/_commit_button.html.haml index 35f7e7bb34..2fd3d9e1be 100644 --- a/app/views/projects/_commit_button.html.haml +++ b/app/views/projects/_commit_button.html.haml @@ -1,6 +1,4 @@ .form-actions - .commit-button-annotation - = button_tag 'Commit Changes', - class: 'btn commit-btn js-commit-button btn-create' + = button_tag 'Commit Changes', class: 'btn commit-btn js-commit-button btn-create' = link_to 'Cancel', cancel_path, class: 'btn btn-cancel', data: {confirm: leave_edit_message} diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index 88d54bf6f2..c1669ac046 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -1,5 +1,5 @@ - empty_repo = @project.empty_repo? -.project-home-panel.clearfix{:class => ("empty-project" if empty_repo)} +.project-home-panel.cover-block.clearfix{:class => ("empty-project" if empty_repo)} .project-identicon-holder = project_icon(@project, alt: '', class: 'project-avatar avatar s90') .project-home-desc @@ -12,8 +12,19 @@ Forked from = link_to project_path(forked_from_project) do = forked_from_project.namespace.try(:name) + .cover-controls.left + .visibility-level-label.has_tooltip{title: project_visibility_level_description(@project.visibility_level), data: { container: 'body' } } + = visibility_level_icon(@project.visibility_level, fw: false) + = visibility_level_label(@project.visibility_level) - + .cover-controls + - if can?(current_user, :admin_project, @project) + = link_to edit_project_path(@project), class: 'btn btn-gray' do + = icon('pencil') + - if current_user +   + = link_to namespace_project_path(@project.namespace, @project, format: :atom, private_token: current_user.private_token), class: 'btn btn-gray' do + = icon('rss') .project-repo-buttons .split-one @@ -21,7 +32,7 @@ = render 'projects/buttons/fork' = render "shared/clone_panel" - + .split-repo-buttons = render "projects/buttons/download" = render 'projects/buttons/dropdown' diff --git a/app/views/projects/_last_commit.html.haml b/app/views/projects/_last_commit.html.haml index 7e1ee2b7fc..386d72e778 100644 --- a/app/views/projects/_last_commit.html.haml +++ b/app/views/projects/_last_commit.html.haml @@ -3,7 +3,7 @@ - if ci_commit = link_to ci_status_path(ci_commit), class: "ci-status ci-#{ci_commit.status}" do = ci_status_icon(ci_commit) - = ci_commit.status + = ci_status_label(ci_commit) = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id" = link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit), class: "commit-row-message" diff --git a/app/views/projects/_md_preview.html.haml b/app/views/projects/_md_preview.html.haml index 7b21095ea3..54c818baaf 100644 --- a/app/views/projects/_md_preview.html.haml +++ b/app/views/projects/_md_preview.html.haml @@ -5,20 +5,21 @@ %a.js-md-write-button(href="#md-write-holder" tabindex="-1") Write %li - %a.js-md-preview-button(href="md-preview-holder" tabindex="-1") + %a.js-md-preview-button(href="#md-preview-holder" tabindex="-1") Preview - - if defined?(referenced_users) && referenced_users - %span.referenced-users.pull-left.hide - = icon('exclamation-triangle') - You are about to add - %strong - %span.js-referenced-users-count 0 - people - to the discussion. Proceed with caution. - %div .md-write-holder = yield .md.md-preview-holder.hide .js-md-preview{class: (preview_class if defined?(preview_class))} + + - if defined?(referenced_users) && referenced_users + %div.referenced-users.hide + %span + = icon('exclamation-triangle') + You are about to add + %strong + %span.js-referenced-users-count 0 + people + to the discussion. Proceed with caution. diff --git a/app/views/projects/_readme.html.haml b/app/views/projects/_readme.html.haml index b5ef0aca54..d1191928d4 100644 --- a/app/views/projects/_readme.html.haml +++ b/app/views/projects/_readme.html.haml @@ -7,15 +7,16 @@ = cache(readme_cache_key) do = render_readme(readme) - else - %h3.page-title - This project does not have README yet - - if can?(current_user, :push_code, @project) - %p.slead - A - %code README - file contains information about other files in a repository and is commonly - distributed with computer software, forming part of its documentation. - %br - We recommend you to - = link_to "add README", new_readme_path, class: 'underlined-link' - file to the repository and GitLab will render it here instead of this message. + .gray-content-block.second-block.center + %h3.page-title + This project does not have README yet + - if can?(current_user, :push_code, @project) + %p + A + %code README + file contains information about other files in a repository and is commonly + distributed with computer software, forming part of its documentation. + %p + We recommend you to + = link_to "add README", new_readme_path, class: 'underlined-link' + file to the repository and GitLab will render it here instead of this message. diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml index 6518c4173e..8d9ec068a4 100644 --- a/app/views/projects/blame/show.html.haml +++ b/app/views/projects/blame/show.html.haml @@ -6,7 +6,7 @@ #tree-holder.tree-holder .file-holder .file-title - %i.fa.fa-file + = blob_icon @blob.mode, @blob.name %strong = @path %small= number_to_human_size @blob.size @@ -43,4 +43,3 @@ - blame_group[:lines].each do |line| :erb <%= highlight(@blob.name, line, nowrap: true, continue: true).html_safe %> - diff --git a/app/views/projects/blob/_actions.html.haml b/app/views/projects/blob/_actions.html.haml index ba3e0c3c59..b1df8d1993 100644 --- a/app/views/projects/blob/_actions.html.haml +++ b/app/views/projects/blob/_actions.html.haml @@ -1,9 +1,8 @@ .btn-group.tree-btn-group - = edit_blob_link(@project, @ref, @path) = link_to 'Raw', namespace_project_raw_path(@project.namespace, @project, @id), class: 'btn btn-sm', target: '_blank' -# only show normal/blame view links for text files - - if @blob.text? + - if blob_viewable?(@blob) - if current_page? namespace_project_blame_path(@project.namespace, @project, @id) = link_to 'Normal View', namespace_project_blob_path(@project.namespace, @project, @id), class: 'btn btn-sm' @@ -12,11 +11,16 @@ class: 'btn btn-sm' unless @blob.empty? = link_to 'History', namespace_project_commits_path(@project.namespace, @project, @id), class: 'btn btn-sm' - - if @ref != @commit.sha - = link_to 'Permalink', namespace_project_blob_path(@project.namespace, @project, - tree_join(@commit.sha, @path)), class: 'btn btn-sm' + = link_to 'Permalink', namespace_project_blob_path(@project.namespace, @project, + tree_join(@commit.sha, @path)), class: 'btn btn-sm' -- if allowed_tree_edit? +- if blob_editable?(@blob) .btn-group{ role: "group" } + = edit_blob_link(@project, @ref, @path) %button.btn.btn-default{ 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal' } Replace %button.btn.btn-remove{ 'data-target' => '#modal-remove-blob', 'data-toggle' => 'modal' } Delete +- elsif !on_top_of_branch? + .btn-group{ role: "group" } + %button.btn.btn-default.disabled.has_tooltip{title: "You can only edit files when you are on a branch.", data: {container: 'body'}} Edit + %button.btn.btn-default.disabled.has_tooltip{title: "You can only replace files when you are on a branch.", data: {container: 'body'}} Replace + %button.btn.btn-remove.disabled.has_tooltip{title: "You can only delete files when you are on a branch.", data: {container: 'body'}} Delete diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml index 42f632b38e..2a3315da3d 100644 --- a/app/views/projects/blob/_blob.html.haml +++ b/app/views/projects/blob/_blob.html.haml @@ -29,10 +29,12 @@ %strong = blob.name %small - = number_to_human_size(blob.size) + = number_to_human_size(blob_size(blob)) .file-actions.hidden-xs = render "actions" - - if blob.text? + - if blob.lfs_pointer? + = render "download", blob: blob + - elsif blob.text? = render "text", blob: blob - elsif blob.image? = render "image", blob: blob diff --git a/app/views/projects/blob/_download.html.haml b/app/views/projects/blob/_download.html.haml index f2c5e95ecf..7908fcae3d 100644 --- a/app/views/projects/blob/_download.html.haml +++ b/app/views/projects/blob/_download.html.haml @@ -4,4 +4,4 @@ %h1.light %i.fa.fa-download %h4 - Download (#{number_to_human_size blob.size}) + Download (#{number_to_human_size blob_size(blob)}) diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml index f1ad0c3c40..10b0281373 100644 --- a/app/views/projects/blob/_editor.html.haml +++ b/app/views/projects/blob/_editor.html.haml @@ -1,23 +1,22 @@ -.file-holder.file - .file-title +.file-holder.file.append-bottom-default + .file-title.clearfix .editor-ref - %i.fa.fa-code-fork + = icon('code-fork') = ref %span.editor-file-name - - if @path - %span.monospace - = @path + = @path - - if current_action?(:new) || current_action?(:create) + - if current_action?(:new) || current_action?(:create) + %span.editor-file-name \/ - = text_field_tag 'file_name', params[:file_name], placeholder: "File name", - required: true, class: 'form-control new-file-name js-quick-submit' - .pull-right - = select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'form-control' + = text_field_tag 'file_name', params[:file_name], placeholder: "File name", + required: true, class: 'form-control new-file-name js-quick-submit' + + .pull-right + = select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'select2' .file-content.code - %pre.js-edit-mode-pane#editor - = params[:content] || local_assigns[:blob_data] + %pre.js-edit-mode-pane#editor #{params[:content] || local_assigns[:blob_data]} - if local_assigns[:path] .js-edit-mode-pane#preview.hide .center diff --git a/app/views/projects/blob/_new_dir.html.haml b/app/views/projects/blob/_new_dir.html.haml index 13b5ffd17f..fc6c9f5fd0 100644 --- a/app/views/projects/blob/_new_dir.html.haml +++ b/app/views/projects/blob/_new_dir.html.haml @@ -5,19 +5,17 @@ %a.close{href: "#", "data-dismiss" => "modal"} × %h3.page-title Create New Directory .modal-body - = form_tag namespace_project_create_dir_path(@project.namespace, @project, @id), method: :post, remote: false, class: 'form-horizontal js-create-dir-form' do + = form_tag namespace_project_create_dir_path(@project.namespace, @project, @id), method: :post, remote: false, class: 'form-horizontal js-create-dir-form js-requires-input' do .form-group - = label_tag :dir_name, 'Directory Name', class: 'control-label' + = label_tag :dir_name, 'Directory name', class: 'control-label' .col-sm-10 - = text_field_tag :dir_name, params[:dir_name], placeholder: "Directory name", required: true, class: 'form-control' + = text_field_tag :dir_name, params[:dir_name], required: true, class: 'form-control' = render 'shared/new_commit_form', placeholder: "Add new directory" - .form-group - .col-sm-offset-2.col-sm-10 - = submit_tag "Create directory", class: 'btn btn-primary btn-create' - = link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal" + .form-actions + = submit_tag "Create directory", class: 'btn btn-create' + = link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal" :javascript - disableButtonIfAnyEmptyField($(".js-create-dir-form"), ".form-control", ".btn-create"); new NewCommitForm($('.js-create-dir-form')) diff --git a/app/views/projects/blob/_upload.html.haml b/app/views/projects/blob/_upload.html.haml index 3bb61f0c94..ecc90a30e7 100644 --- a/app/views/projects/blob/_upload.html.haml +++ b/app/views/projects/blob/_upload.html.haml @@ -16,10 +16,9 @@ = render 'shared/new_commit_form', placeholder: placeholder - .form-group - .col-sm-offset-2.col-sm-10 - = button_tag button_title, class: 'btn btn-small btn-primary btn-upload-file', id: 'submit-all' - = link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal" + .form-actions + = button_tag button_title, class: 'btn btn-small btn-create btn-upload-file', id: 'submit-all' + = link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal" :javascript disableButtonIfEmptyField($('.js-upload-blob-form').find('.js-commit-message'), '.btn-upload-file'); diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml index 5674516525..a47fe7ede8 100644 --- a/app/views/projects/blob/edit.html.haml +++ b/app/views/projects/blob/edit.html.haml @@ -5,12 +5,12 @@ %ul.center-top-menu.no-bottom.js-edit-mode %li.active = link_to '#editor' do - %i.fa.fa-edit - Edit file + = icon('edit') + Edit File %li = link_to '#preview', 'data-preview-url' => namespace_project_preview_blob_path(@project.namespace, @project, @id) do - %i.fa.fa-eye + = icon('eye') = editing_preview_title(@blob.name) = form_tag(namespace_project_update_blob_path(@project.namespace, @project, @id), method: :put, class: 'form-horizontal js-requires-input js-edit-blob-form') do diff --git a/app/views/projects/blob/new.html.haml b/app/views/projects/blob/new.html.haml index 1ff6800545..167fa61518 100644 --- a/app/views/projects/blob/new.html.haml +++ b/app/views/projects/blob/new.html.haml @@ -1,9 +1,8 @@ - page_title "New File", @path.presence, @ref = render "header_title" -.gray-content-block.top-block - %h3.page-title - Create New File +%h3.page-title + New File .file-editor = form_tag(namespace_project_create_blob_path(@project.namespace, @project, @id), method: :post, class: 'form-horizontal js-new-blob-form js-requires-input') do diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml index b7276868ce..3f8d11ed8c 100644 --- a/app/views/projects/blob/show.html.haml +++ b/app/views/projects/blob/show.html.haml @@ -6,7 +6,7 @@ %div#tree-holder.tree-holder = render 'blob', blob: @blob -- if allowed_tree_edit? +- if blob_editable?(@blob) = render 'projects/blob/remove' - title = "Replace #{@blob.name}" diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index cc0ec9483d..5081bae680 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -3,17 +3,17 @@ %div = link_to namespace_project_tree_path(@project.namespace, @project, branch.name) do %strong.str-truncated= branch.name -   - - if branch.name == @repository.root_ref - %span.label.label-primary default - - elsif @repository.merged_to_root_ref? branch.name - %span.label.label-info.has_tooltip(title="Merged into #{@repository.root_ref}") - merged +   + - if branch.name == @repository.root_ref + %span.label.label-primary default + - elsif @repository.merged_to_root_ref? branch.name + %span.label.label-info.has_tooltip(title="Merged into #{@repository.root_ref}") + merged - - if @project.protected_branch? branch.name - %span.label.label-success - %i.fa.fa-lock - protected + - if @project.protected_branch? branch.name + %span.label.label-success + %i.fa.fa-lock + protected .controls.hidden-xs - if create_mr_button?(@repository.root_ref, branch.name) = link_to create_mr_path(@repository.root_ref, branch.name), class: 'btn btn-grouped btn-xs' do @@ -26,7 +26,7 @@ Compare - if can_remove_branch?(@project, branch.name) - = link_to namespace_project_branch_path(@project.namespace, @project, branch.name), class: 'btn btn-grouped btn-xs btn-remove remove-row', method: :delete, data: { confirm: 'Removed branch cannot be restored. Are you sure?'}, remote: true do + = link_to namespace_project_branch_path(@project.namespace, @project, branch.name), class: 'btn btn-grouped btn-xs btn-remove remove-row has_tooltip', title: "Delete branch", method: :delete, data: { confirm: "Deleting the '#{branch.name}' branch cannot be undone. Are you sure?", container: 'body' }, remote: true do = icon("trash-o") - if commit diff --git a/app/views/projects/branches/_commit.html.haml b/app/views/projects/branches/_commit.html.haml index 22d77dda93..9fe65cbb10 100644 --- a/app/views/projects/branches/_commit.html.haml +++ b/app/views/projects/branches/_commit.html.haml @@ -1,5 +1,5 @@ .branch-commit - = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit-id" + = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit-id monospace" · %span.str-truncated = link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit.id), class: "commit-row-message" diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml index 03ade02a0c..204def6079 100644 --- a/app/views/projects/branches/index.html.haml +++ b/app/views/projects/branches/index.html.haml @@ -5,7 +5,7 @@ .pull-right - if can? current_user, :push_code, @project = link_to new_namespace_project_branch_path(@project.namespace, @project), class: 'btn btn-create' do - %i.fa.fa-add-sign + = icon('plus') New branch   .dropdown.inline diff --git a/app/views/projects/branches/new.html.haml b/app/views/projects/branches/new.html.haml index f5577042ca..31943a2407 100644 --- a/app/views/projects/branches/new.html.haml +++ b/app/views/projects/branches/new.html.haml @@ -6,25 +6,27 @@ %button{ type: "button", class: "close", "data-dismiss" => "alert"} × = @error %h3.page-title - %i.fa.fa-code-fork - New branch + New Branch +%hr + = form_tag namespace_project_branches_path, method: :post, id: "new-branch-form", class: "form-horizontal js-requires-input" do .form-group - = label_tag :branch_name, 'Name for new branch', class: 'control-label' + = label_tag :branch_name, nil, class: 'control-label' .col-sm-10 - = text_field_tag :branch_name, params[:branch_name], placeholder: 'enter new branch name', required: true, tabindex: 1, class: 'form-control' + = text_field_tag :branch_name, params[:branch_name], required: true, tabindex: 1, autofocus: true, class: 'form-control' .form-group = label_tag :ref, 'Create from', class: 'control-label' .col-sm-10 - = text_field_tag :ref, params[:ref], placeholder: 'existing branch name, tag or commit SHA', required: true, tabindex: 2, class: 'form-control' + = text_field_tag :ref, params[:ref] || @project.default_branch, required: true, tabindex: 2, class: 'form-control' + .help-block Existing branch name, tag, or commit SHA .form-actions = button_tag 'Create branch', class: 'btn btn-create', tabindex: 3 = link_to 'Cancel', namespace_project_branches_path(@project.namespace, @project), class: 'btn btn-cancel' :javascript - var availableTags = #{@project.repository.ref_names.to_json}; + var availableRefs = #{@project.repository.ref_names.to_json}; $("#ref").autocomplete({ - source: availableTags, + source: availableRefs, minLength: 1 }); diff --git a/app/views/projects/builds/index.html.haml b/app/views/projects/builds/index.html.haml index dab7164153..1a26908ab1 100644 --- a/app/views/projects/builds/index.html.haml +++ b/app/views/projects/builds/index.html.haml @@ -3,26 +3,29 @@ .project-issuable-filter .controls - - if @ci_project && current_user && can?(current_user, :manage_builds, @project) + - if can?(current_user, :manage_builds, @project) .pull-left.hidden-xs - if @all_builds.running_or_pending.any? - = link_to 'Cancel all', cancel_all_namespace_project_builds_path(@project.namespace, @project), data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post + = link_to 'Cancel running', cancel_all_namespace_project_builds_path(@project.namespace, @project), data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post %ul.center-top-menu %li{class: ('active' if @scope.nil?)} = link_to project_builds_path(@project) do Running - %span.badge.js-running-count= @all_builds.running_or_pending.count(:id) + %span.badge.js-running-count + = number_with_delimiter(@all_builds.running_or_pending.count(:id)) %li{class: ('active' if @scope == 'finished')} = link_to project_builds_path(@project, scope: :finished) do Finished - %span.badge.js-running-count= @all_builds.finished.count(:id) + %span.badge.js-running-count + = number_with_delimiter(@all_builds.finished.count(:id)) %li{class: ('active' if @scope == 'all')} = link_to project_builds_path(@project, scope: :all) do All - %span.badge.js-totalbuilds-count= @all_builds.count(:id) + %span.badge.js-totalbuilds-count + = number_with_delimiter(@all_builds.count(:id)) .gray-content-block #{(@scope || 'running').capitalize} builds from this project @@ -37,7 +40,7 @@ %thead %tr %th Status - %th Build ID + %th Runner %th Commit %th Ref %th Stage @@ -50,4 +53,3 @@ = render 'projects/commit_statuses/commit_status', commit_status: build, commit_sha: true, stage: true, allow_retry: true = paginate @builds, theme: 'gitlab' - diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index 907e1ce10b..20a5b6a66e 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -1,17 +1,16 @@ -- page_title "#{@build.name} (#{@build.id})", "Builds" +- page_title "#{@build.name} (##{@build.id})", "Builds" = render "header_title" .build-page - .gray-content-block + .gray-content-block.top-block Build ##{@build.id} for commit - %strong.monospace - = link_to @build.commit.short_sha, ci_status_path(@build.commit) + %strong.monospace= link_to @build.commit.short_sha, ci_status_path(@build.commit) from = link_to @build.ref, namespace_project_commits_path(@project.namespace, @project, @build.ref) #up-build-trace - if @commit.matrix_for_ref?(@build.ref) - %ul.center-top-menu.build-top-menu + %ul.center-top-menu.no-top.no-bottom - @commit.latest_builds_for_ref(@build.ref).each do |build| %li{class: ('active' if build == @build) } = link_to namespace_project_build_path(@project.namespace, @project, build) do @@ -22,7 +21,6 @@ - else = build.id - - if @build.retried? %li.active %a @@ -31,7 +29,7 @@ %i.fa.fa-warning This build was retried. - .gray-content-block.second-block + .gray-content-block.middle-block .build-head .clearfix = ci_status_with_icon(@build.status) @@ -58,7 +56,7 @@ %br Go to - = link_to namespace_project_runners_path(@build.gl_project.namespace, @build.gl_project) do + = link_to namespace_project_runners_path(@build.project.namespace, @build.project) do Runners page .row.prepend-top-default @@ -115,7 +113,7 @@ %p %span.attr-name Runner: - if @build.runner && current_user && current_user.admin - = link_to "##{@build.runner.id}", ci_admin_runner_path(@build.runner.id) + = link_to "##{@build.runner.id}", admin_runner_path(@build.runner.id) - elsif @build.runner \##{@build.runner.id} @@ -140,7 +138,7 @@ %h4.title Commit .pull-right - %small + %small = link_to @build.commit.short_sha, ci_status_path(@build.commit), class: "monospace" %p %span.attr-name Branch: @@ -162,7 +160,7 @@ - if @builds.present? .build-widget - %h4.title #{pluralize(@builds.count(:id), "other build")} for + %h4.title #{pluralize(@builds.count(:id), "other build")} for = succeed ":" do = link_to @build.commit.short_sha, ci_status_path(@build.commit), class: "monospace" %table.table.builds diff --git a/app/views/projects/ci_services/_form.html.haml b/app/views/projects/ci_services/_form.html.haml deleted file mode 100644 index 397832e56d..0000000000 --- a/app/views/projects/ci_services/_form.html.haml +++ /dev/null @@ -1,54 +0,0 @@ -%h3.page-title - = @service.title - = boolean_to_icon @service.activated? - -%p= @service.description - - -%hr - -= form_for(@service, as: :service, url: namespace_project_ci_service_path(@project.namespace, @project, @service.to_param), method: :put, html: { class: 'form-horizontal' }) do |f| - - if @service.errors.any? - .alert.alert-danger - %ul - - @service.errors.full_messages.each do |msg| - %li= msg - - - if @service.help.present? - .bs-callout - = @service.help - - .form-group - = f.label :active, "Active", class: "control-label" - .col-sm-10 - = f.check_box :active - - - @service.fields.each do |field| - - name = field[:name] - - label = field[:label] || name - - value = @service.send(name) - - type = field[:type] - - placeholder = field[:placeholder] - - choices = field[:choices] - - default_choice = field[:default_choice] - - help = field[:help] - - .form-group - = f.label label, class: "control-label" - .col-sm-10 - - if type == 'text' - = f.text_field name, class: "form-control", placeholder: placeholder - - elsif type == 'textarea' - = f.text_area name, rows: 5, class: "form-control", placeholder: placeholder - - elsif type == 'checkbox' - = f.check_box name - - elsif type == 'select' - = f.select name, options_for_select(choices, value ? value : default_choice), {}, { class: "form-control" } - - if help - .light #{help} - - .form-actions - = f.submit 'Save', class: 'btn btn-save' -   - - if @service.valid? && @service.activated? && @service.can_test? - = link_to 'Test settings', test_namespace_project_ci_service_path(@project.namespace, @project, @service.to_param), class: 'btn' diff --git a/app/views/projects/ci_services/edit.html.haml b/app/views/projects/ci_services/edit.html.haml deleted file mode 100644 index dacb6b4f6f..0000000000 --- a/app/views/projects/ci_services/edit.html.haml +++ /dev/null @@ -1,2 +0,0 @@ -- page_title @service.title, "CI Services" -= render 'form' diff --git a/app/views/projects/ci_services/index.html.haml b/app/views/projects/ci_services/index.html.haml deleted file mode 100644 index 3f26c7851d..0000000000 --- a/app/views/projects/ci_services/index.html.haml +++ /dev/null @@ -1,23 +0,0 @@ -- page_title "CI Services" -%h3.page-title Project services -%p.light Project services allow you to integrate GitLab CI with other applications - -%table.table - %thead - %tr - %th - %th Service - %th Description - %th Last edit - - @services.sort_by(&:title).each do |service| - %tr - %td - = boolean_to_icon service.activated? - %td - = link_to edit_namespace_project_ci_service_path(@project.namespace, @project, service.to_param) do - %strong= service.title - %td - = service.description - %td.light - = time_ago_in_words service.updated_at - ago diff --git a/app/views/projects/ci_settings/_form.html.haml b/app/views/projects/ci_settings/_form.html.haml deleted file mode 100644 index ee6b8885e2..0000000000 --- a/app/views/projects/ci_settings/_form.html.haml +++ /dev/null @@ -1,120 +0,0 @@ -%h3.page-title - CI settings -%hr -.bs-callout.help-callout - %p - If you want to test your .gitlab-ci.yml, you can use special tool - #{link_to "Lint", ci_lint_path} - %p - Edit your - #{link_to ".gitlab-ci.yml using web-editor", yaml_web_editor_link(@ci_project)} - -- unless @project.empty_repo? - %p - Paste build status image for #{@repository.root_ref} with next link - = link_to '#', class: 'badge-codes-toggle btn btn-default btn-xs' do - Status Badge - .badge-codes-block.bs-callout.bs-callout-info.hide - %p - Status badge for - %span.label.label-info #{@ref} - branch - %div - %label Markdown: - = text_field_tag 'badge_md', markdown_badge_code(@ci_project, @repository.root_ref), readonly: true, class: 'form-control' - %label Html: - = text_field_tag 'badge_html', html_badge_code(@ci_project, @repository.root_ref), readonly: true, class: 'form-control' - -= nested_form_for @ci_project, url: namespace_project_ci_settings_path(@project.namespace, @project), html: { class: 'form-horizontal' } do |f| - - if @ci_project.errors.any? - #error_explanation - %p.lead= "#{pluralize(@ci_project.errors.count, "error")} prohibited this project from being saved:" - .alert.alert-error - %ul - - @ci_project.errors.full_messages.each do |msg| - %li= msg - - %fieldset - %legend Build settings - .form-group - = label_tag nil, class: 'control-label' do - Get code - .col-sm-10 - %p Get recent application code using the following command: - .radio - = label_tag do - = f.radio_button :allow_git_fetch, 'false' - %strong git clone - .light Slower but makes sure you have a clean dir before every build - .radio - = label_tag do - = f.radio_button :allow_git_fetch, 'true' - %strong git fetch - .light Faster - .form-group - = f.label :timeout_in_minutes, 'Timeout', class: 'control-label' - .col-sm-10 - = f.number_field :timeout_in_minutes, class: 'form-control', min: '0' - .light per build in minutes - - - %fieldset - %legend Build Schedule - .form-group - = f.label :always_build, 'Schedule build', class: 'control-label' - .col-sm-10 - .checkbox - = f.label :always_build do - = f.check_box :always_build - %span.light Repeat last build after X hours if no builds - .form-group - = f.label :polling_interval, "Build interval", class: 'control-label' - .col-sm-10 - = f.number_field :polling_interval, placeholder: '5', min: '0', class: 'form-control' - .light In hours - - %fieldset - %legend Project settings - .form-group - = f.label :default_ref, "Make tabs for the following branches", class: 'control-label' - .col-sm-10 - = f.text_field :default_ref, class: 'form-control', placeholder: 'master, stable' - .light You will be able to filter builds by the following branches - .form-group - = f.label :public, 'Public mode', class: 'control-label' - .col-sm-10 - .checkbox - = f.label :public do - = f.check_box :public - %span.light Anyone can see project and builds - .form-group - = f.label :coverage_regex, "Test coverage parsing", class: 'control-label' - .col-sm-10 - .input-group - %span.input-group-addon / - = f.text_field :coverage_regex, class: 'form-control', placeholder: '\(\d+.\d+\%\) covered' - %span.input-group-addon / - .light We will use this regular expression to find test coverage output in build trace. Leave blank if you want to disable this feature - .bs-callout.bs-callout-info - %p Below are examples of regex for existing tools: - %ul - %li - Simplecov (Ruby) - - %code \(\d+.\d+\%\) covered - %li - pytest-cov (Python) - - %code \d+\%\s*$ - %li - phpunit --coverage-text --colors=never (PHP) - - %code ^\s*Lines:\s*\d+.\d+\% - - %fieldset - %legend Advanced settings - .form-group - = f.label :token, "CI token", class: 'control-label' - .col-sm-10 - = f.text_field :token, class: 'form-control', placeholder: 'xEeFCaDAB89' - - .form-actions - = f.submit 'Save changes', class: 'btn btn-save' - - unless @ci_project.new_record? - = link_to 'Remove Project', ci_project_path(@ci_project), method: :delete, data: { confirm: 'Project will be removed. Are you sure?' }, class: 'btn btn-danger pull-right' diff --git a/app/views/projects/ci_settings/_no_runners.html.haml b/app/views/projects/ci_settings/_no_runners.html.haml deleted file mode 100644 index 1374e6680f..0000000000 --- a/app/views/projects/ci_settings/_no_runners.html.haml +++ /dev/null @@ -1,8 +0,0 @@ -.alert.alert-danger - %p - There are NO runners to build this project. - %br - You can add Specific runner for this project on Runners page - - - if current_user.admin - or add Shared runner for whole application in admin area. diff --git a/app/views/projects/ci_settings/edit.html.haml b/app/views/projects/ci_settings/edit.html.haml deleted file mode 100644 index acc912d459..0000000000 --- a/app/views/projects/ci_settings/edit.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -- page_title "CI Settings" - -- if no_runners_for_project?(@ci_project) - = render 'no_runners' - -= render 'form' diff --git a/app/views/projects/ci_web_hooks/index.html.haml b/app/views/projects/ci_web_hooks/index.html.haml deleted file mode 100644 index 2998fb08ff..0000000000 --- a/app/views/projects/ci_web_hooks/index.html.haml +++ /dev/null @@ -1,94 +0,0 @@ -- page_title "CI Web Hooks" -%h3.page-title - CI Web hooks - -%p.light - Web Hooks can be used for binding events when build completed. - -%hr.clearfix - -= form_for @web_hook, url: namespace_project_ci_web_hooks_path(@project.namespace, @project), html: { class: 'form-horizontal' } do |f| - -if @web_hook.errors.any? - .alert.alert-danger - - @web_hook.errors.full_messages.each do |msg| - %p= msg - .form-group - = f.label :url, "URL", class: 'control-label' - .col-sm-10 - = f.text_field :url, class: "form-control", placeholder: 'http://example.com/trigger-ci.json' - .form-actions - = f.submit "Add Web Hook", class: "btn btn-create" - --if @web_hooks.any? - %h4 Activated web hooks (#{@web_hooks.count}) - .table-holder - %table.table - - @web_hooks.each do |hook| - %tr - %td - .clearfix - %span.monospace= hook.url - %td - .pull-right - - if @ci_project.commits.any? - = link_to 'Test Hook', test_namespace_project_ci_web_hook_path(@project.namespace, @project, hook), class: "btn btn-sm btn-grouped" - = link_to 'Remove', namespace_project_ci_web_hook_path(@project.namespace, @project, hook), data: { confirm: 'Are you sure?'}, method: :delete, class: "btn btn-remove btn-sm btn-grouped" - -%h4 Web Hook data example - -:erb -
-    
-      {
-        "build_id": 2,
-        "build_name":"rspec_linux"
-        "build_status": "failed",
-        "build_started_at": "2014-05-05T18:01:02.563Z",
-        "build_finished_at": "2014-05-05T18:01:07.611Z",
-        "project_id": 1,
-        "project_name": "Brightbox \/ Brightbox Cli",
-        "gitlab_url": "http:\/\/localhost:3000\/brightbox\/brightbox-cli",
-        "ref": "master",
-        "sha": "a26cf5de9ed9827746d4970872376b10d9325f40",
-        "before_sha": "34f57f6ba3ed0c21c5e361bbb041c3591411176c",
-        "push_data": {
-          "before": "34f57f6ba3ed0c21c5e361bbb041c3591411176c",
-          "after": "a26cf5de9ed9827746d4970872376b10d9325f40",
-          "ref": "refs\/heads\/master",
-          "user_id": 1,
-          "user_name": "Administrator",
-          "project_id": 5,
-          "repository": {
-            "name": "Brightbox Cli",
-            "url": "dzaporozhets@localhost:brightbox\/brightbox-cli.git",
-            "description": "Voluptatibus quae error consectetur voluptas dolores vel excepturi possimus.",
-            "homepage": "http:\/\/localhost:3000\/brightbox\/brightbox-cli"
-          },
-          "commits": [
-            {
-              "id": "a26cf5de9ed9827746d4970872376b10d9325f40",
-              "message": "Release v1.2.2",
-              "timestamp": "2014-04-22T16:46:42+03:00",
-              "url": "http:\/\/localhost:3000\/brightbox\/brightbox-cli\/commit\/a26cf5de9ed9827746d4970872376b10d9325f40",
-              "author": {
-                "name": "Paul Thornthwaite",
-                "email": "tokengeek@gmail.com"
-              }
-            },
-            {
-              "id": "34f57f6ba3ed0c21c5e361bbb041c3591411176c",
-              "message": "Fix server user data update\n\nIncorrect condition was being used so Base64 encoding option was having\nopposite effect from desired.",
-              "timestamp": "2014-04-11T18:17:26+03:00",
-              "url": "http:\/\/localhost:3000\/brightbox\/brightbox-cli\/commit\/34f57f6ba3ed0c21c5e361bbb041c3591411176c",
-              "author": {
-                "name": "Paul Thornthwaite",
-                "email": "tokengeek@gmail.com"
-              }
-            }
-          ],
-          "total_commits_count": 2,
-          "ci_yaml_file":"rspec_linux:\r\n  script: ls\r\n"
-        }
-      }
-    
-  
diff --git a/app/views/projects/commit/_builds.html.haml b/app/views/projects/commit/_builds.html.haml new file mode 100644 index 0000000000..329aaa0bb8 --- /dev/null +++ b/app/views/projects/commit/_builds.html.haml @@ -0,0 +1,68 @@ +.gray-content-block.middle-block + .pull-right + - if can?(current_user, :manage_builds, @ci_commit.project) + - if @ci_commit.builds.latest.failed.any?(&:retryable?) + = link_to "Retry failed", retry_builds_namespace_project_commit_path(@ci_commit.project.namespace, @ci_commit.project, @ci_commit.sha), class: 'btn btn-grouped btn-primary', method: :post + + - if @ci_commit.builds.running_or_pending.any? + = link_to "Cancel running", cancel_builds_namespace_project_commit_path(@ci_commit.project.namespace, @ci_commit.project, @ci_commit.sha), data: { confirm: 'Are you sure?' }, class: 'btn btn-grouped btn-danger', method: :post + + .oneline + = pluralize @statuses.count(:id), "build" + - if defined?(link_to_commit) && link_to_commit + for commit + = link_to @ci_commit.short_sha, namespace_project_commit_path(@ci_commit.project.namespace, @ci_commit.project, @ci_commit.sha), class: "monospace" + - if @ci_commit.duration > 0 + in + = time_interval_in_words @ci_commit.duration + +- if @ci_commit.yaml_errors.present? + .bs-callout.bs-callout-danger + %h4 Found errors in your .gitlab-ci.yml: + %ul + - @ci_commit.yaml_errors.split(",").each do |error| + %li= error + You can also test your .gitlab-ci.yml in the #{link_to "Lint", ci_lint_path} + +- if @ci_commit.project.builds_enabled? && !@ci_commit.ci_yaml_file + .bs-callout.bs-callout-warning + \.gitlab-ci.yml not found in this commit + +.table-holder + %table.table.builds + %thead + %tr + %th Status + %th Build ID + %th Ref + %th Stage + %th Name + %th Duration + %th Finished at + - if @ci_commit.project.build_coverage_enabled? + %th Coverage + %th + - @ci_commit.refs.each do |ref| + = render partial: "projects/commit_statuses/commit_status", collection: @ci_commit.statuses.for_ref(ref).latest.ordered, + locals: { coverage: @ci_commit.project.build_coverage_enabled?, stage: true, allow_retry: true } + +- if @ci_commit.retried.any? + .gray-content-block.second-block + Retried builds + + .table-holder + %table.table.builds + %thead + %tr + %th Status + %th Build ID + %th Ref + %th Stage + %th Name + %th Duration + %th Finished at + - if @ci_commit.project.build_coverage_enabled? + %th Coverage + %th + = render partial: "projects/commit_statuses/commit_status", collection: @ci_commit.retried, + locals: { coverage: @ci_commit.project.build_coverage_enabled?, stage: true } diff --git a/app/views/projects/commit/_ci_menu.html.haml b/app/views/projects/commit/_ci_menu.html.haml index c73ba74f5e..f74f8b427e 100644 --- a/app/views/projects/commit/_ci_menu.html.haml +++ b/app/views/projects/commit/_ci_menu.html.haml @@ -1,4 +1,4 @@ -%ul.center-top-menu.commit-ci-menu +%ul.center-top-menu.no-top.no-bottom.commit-ci-menu = nav_link(path: 'commit#show') do = link_to namespace_project_commit_path(@project.namespace, @project, @commit.id) do Changes @@ -6,4 +6,4 @@ = nav_link(path: 'commit#builds') do = link_to builds_namespace_project_commit_path(@project.namespace, @project, @commit.id) do Builds - %span.badge= @builds.count(:id) + %span.badge= @statuses.count diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml index 776768537d..ddb77fd796 100644 --- a/app/views/projects/commit/_commit_box.html.haml +++ b/app/views/projects/commit/_commit_box.html.haml @@ -13,13 +13,15 @@ - unless @commit.parents.length > 1 %li= link_to "Email Patches", namespace_project_commit_path(@project.namespace, @project, @commit, format: :patch) %li= link_to "Plain Diff", namespace_project_commit_path(@project.namespace, @project, @commit, format: :diff) - = link_to namespace_project_tree_path(@project.namespace, @project, @commit), class: "btn btn-primary btn-grouped" do - %span Browse Code » + = link_to namespace_project_tree_path(@project.namespace, @project, @commit), class: "btn btn-grouped" do + = icon('files-o') + Browse Files %div %p %span.light Commit = link_to @commit.id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace" + = clipboard_button(clipboard_text: @commit.id) .commit-info-row %span.light Authored by %strong @@ -43,17 +45,17 @@ = link_to ci_status_path(@ci_commit), class: "ci-status ci-#{@ci_commit.status}" do = ci_status_icon(@ci_commit) build: - = @ci_commit.status + = ci_status_label(@ci_commit) .commit-info-row.branches %i.fa.fa-spinner.fa-spin .commit-box.gray-content-block.middle-block %h3.commit-title - = gfm escape_once(@commit.title) + = markdown escape_once(@commit.title), pipeline: :single_line - if @commit.description.present? %pre.commit-description - = preserve(gfm(escape_once(@commit.description))) + = preserve(markdown(escape_once(@commit.description), pipeline: :single_line)) :javascript $(".commit-info-row.branches").load("#{branches_namespace_project_commit_path(@project.namespace, @project, @commit.id)}"); diff --git a/app/views/projects/commit/builds.html.haml b/app/views/projects/commit/builds.html.haml index 00cf9c7610..99d62503a9 100644 --- a/app/views/projects/commit/builds.html.haml +++ b/app/views/projects/commit/builds.html.haml @@ -3,70 +3,4 @@ = render "commit_box" = render "ci_menu" - -- if @ci_commit.yaml_errors.present? - .bs-callout.bs-callout-danger - %h4 Found errors in your .gitlab-ci.yml: - %ul - - @ci_commit.yaml_errors.split(",").each do |error| - %li= error - -- unless @ci_commit.ci_yaml_file - .bs-callout.bs-callout-warning - \.gitlab-ci.yml not found in this commit - -.gray-content-block.second-block - Latest builds - - .pull-right - - if @ci_commit.duration > 0 - %i.fa.fa-time - #{time_interval_in_words @ci_commit.duration} - -   - - - if @ci_project && current_user && can?(current_user, :manage_builds, @project) - - if @ci_commit.builds.latest.failed.any?(&:retryable?) - = link_to "Retry failed", retry_builds_namespace_project_commit_path(@project.namespace, @project, @commit.sha), class: 'btn btn-xs btn-primary', method: :post - - - if @ci_commit.builds.running_or_pending.any? - = link_to "Cancel running", cancel_builds_namespace_project_commit_path(@project.namespace, @project, @commit.sha), class: 'btn btn-xs btn-danger', method: :post - -.table-holder - %table.table.builds - %thead - %tr - %th Status - %th Build ID - %th Ref - %th Stage - %th Name - %th Duration - %th Finished at - - if @ci_project && @ci_project.coverage_enabled? - %th Coverage - %th - - @ci_commit.refs.each do |ref| - = render partial: "projects/commit_statuses/commit_status", collection: @ci_commit.statuses.for_ref(ref).latest.ordered, - locals: { coverage: @ci_project.try(:coverage_enabled?), stage: true, allow_retry: true } - -- if @ci_commit.retried.any? - .gray-content-block.second-block - Retried builds - - .table-holder - %table.table.builds - %thead - %tr - %th Status - %th Build ID - %th Ref - %th Stage - %th Name - %th Duration - %th Finished at - - if @ci_project && @ci_project.coverage_enabled? - %th Coverage - %th - = render partial: "projects/commit_statuses/commit_status", collection: @ci_commit.retried, - locals: { coverage: @ci_project.try(:coverage_enabled?), stage: true } += render "builds" diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml index 85e203cbe5..069b8b1f16 100644 --- a/app/views/projects/commit/show.html.haml +++ b/app/views/projects/commit/show.html.haml @@ -1,6 +1,9 @@ - page_title "#{@commit.title} (#{@commit.short_id})", "Commits" = render "projects/commits/header_title" = render "commit_box" -= render "ci_menu" if @ci_commit +- if @ci_commit + = render "ci_menu" +- else + %div.block-connector = render "projects/diffs/diffs", diffs: @diffs, project: @project = render "projects/notes/notes_with_form" diff --git a/app/views/projects/commit_statuses/_commit_status.html.haml b/app/views/projects/commit_statuses/_commit_status.html.haml index 9a0e7bff3f..74a05df24d 100644 --- a/app/views/projects/commit_statuses/_commit_status.html.haml +++ b/app/views/projects/commit_statuses/_commit_status.html.haml @@ -1,24 +1,29 @@ %tr.commit_status %td.status - = ci_status_with_icon(commit_status.status) + - if commit_status.target_url + = link_to commit_status.target_url, class: "ci-status ci-#{commit_status.status}" do + = ci_icon_for_status(commit_status.status) + = commit_status.status + - else + = ci_status_with_icon(commit_status.status) %td.commit_status-link - if commit_status.target_url = link_to commit_status.target_url do - %strong Build ##{commit_status.id} + %strong ##{commit_status.id} - else - %strong Build ##{commit_status.id} + %strong ##{commit_status.id} - if commit_status.show_warning? %i.fa.fa-warning.text-warning - if defined?(commit_sha) && commit_sha %td - = link_to commit_status.short_sha, namespace_project_commit_path(@project.namespace, @project, commit_status.sha), class: "monospace" - + = link_to commit_status.short_sha, namespace_project_commit_path(commit_status.project.namespace, commit_status.project, commit_status.sha), class: "monospace" + %td - if commit_status.ref - = link_to commit_status.ref, namespace_project_commits_path(@project.namespace, @project, commit_status.ref) + = link_to commit_status.ref, namespace_project_commits_path(commit_status.project.namespace, commit_status.project, commit_status.ref) - else .light none @@ -61,10 +66,10 @@ %td .pull-right - - if current_user && can?(current_user, :download_build_artifacts, @project) && commit_status.download_url + - if current_user && can?(current_user, :download_build_artifacts, commit_status.project) && commit_status.download_url = link_to commit_status.download_url, title: 'Download artifacts' do %i.fa.fa-download - - if current_user && can?(current_user, :manage_builds, commit_status.gl_project) + - if current_user && can?(current_user, :manage_builds, commit_status.project) - if commit_status.active? - if commit_status.cancel_url = link_to commit_status.cancel_url, method: :post, title: 'Cancel' do diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml index 805be332e6..28b82dd31f 100644 --- a/app/views/projects/commits/_commit.html.haml +++ b/app/views/projects/commits/_commit.html.haml @@ -9,7 +9,7 @@ - cache_key.push(ci_commit.status) if ci_commit = cache(cache_key) do - %li.commit.js-toggle-container + %li.commit.js-toggle-container{ id: "commit-#{commit.short_id}" } .commit-row-title %strong.str-truncated = link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit.id), class: "commit-row-message" @@ -20,8 +20,8 @@ - if ci_commit = render_ci_status(ci_commit)   - = clipboard_button - = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id", data: {clipboard_text: commit.id} + = clipboard_button(clipboard_text: commit.id) + = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id" .notes_count - if note_count > 0 @@ -32,7 +32,7 @@ - if commit.description? .commit-row-description.js-toggle-content %pre - = preserve(gfm(escape_once(commit.description))) + = preserve(markdown(escape_once(commit.description), pipeline: :single_line)) .commit-row-info = commit_author_link(commit, avatar: true, size: 24) diff --git a/app/views/projects/commits/_head.html.haml b/app/views/projects/commits/_head.html.haml index f11a41cfd7..fcccb002d7 100644 --- a/app/views/projects/commits/_head.html.haml +++ b/app/views/projects/commits/_head.html.haml @@ -3,6 +3,11 @@ = link_to namespace_project_commits_path(@project.namespace, @project, current_ref) do Commits %span.badge= number_with_delimiter(@repository.commit_count) + + = nav_link(controller: %w(network)) do + = link_to namespace_project_network_path(@project.namespace, @project, current_ref) do + Network + = nav_link(controller: :compare) do = link_to namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: current_ref) do Compare diff --git a/app/views/projects/commits/show.atom.builder b/app/views/projects/commits/show.atom.builder index 268b9b815e..7ffa731719 100644 --- a/app/views/projects/commits/show.atom.builder +++ b/app/views/projects/commits/show.atom.builder @@ -17,7 +17,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.name commit.author_name xml.email commit.author_email end - xml.summary gfm(commit.description) + xml.summary markdown(commit.description, pipeline: :single_line) end end end diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml index 39755efd2f..51088a7dea 100644 --- a/app/views/projects/compare/show.html.haml +++ b/app/views/projects/compare/show.html.haml @@ -7,11 +7,11 @@ = render "form" - if @commits.present? - .prepend-top-20 + .prepend-top-default = render "projects/commits/commit_list" = render "projects/diffs/diffs", diffs: @diffs, project: @project - else - .light-well.prepend-top-20 + .light-well.prepend-top-default .center %h4 There isn't anything to compare. diff --git a/app/views/projects/deploy_keys/_form.html.haml b/app/views/projects/deploy_keys/_form.html.haml index 91675b3738..5e182af266 100644 --- a/app/views/projects/deploy_keys/_form.html.haml +++ b/app/views/projects/deploy_keys/_form.html.haml @@ -1,5 +1,5 @@ %div - = form_for [@project.namespace.becomes(Namespace), @project, @key], url: namespace_project_deploy_keys_path, html: { class: 'deploy-key-form form-horizontal' } do |f| + = form_for [@project.namespace.becomes(Namespace), @project, @key], url: namespace_project_deploy_keys_path, html: { class: 'deploy-key-form form-horizontal js-requires-input' } do |f| -if @key.errors.any? .alert.alert-danger %ul @@ -8,16 +8,15 @@ .form-group = f.label :title, class: "control-label" - .col-sm-10= f.text_field :title, class: 'form-control' + .col-sm-10= f.text_field :title, class: 'form-control', autofocus: true, required: true .form-group = f.label :key, class: "control-label" .col-sm-10 %p.light Paste a machine public key here. Read more about how to generate it = link_to "here", help_page_path("ssh", "README") - = f.text_area :key, class: "form-control thin_area", rows: 5 + = f.text_area :key, class: "form-control thin_area", rows: 5, required: true .form-actions - = f.submit 'Create', class: "btn-create btn" + = f.submit 'Create Deploy Key', class: "btn-create btn" = link_to "Cancel", namespace_project_deploy_keys_path(@project.namespace, @project), class: "btn btn-cancel" - diff --git a/app/views/projects/deploy_keys/new.html.haml b/app/views/projects/deploy_keys/new.html.haml index 01c810aee1..01fab3008a 100644 --- a/app/views/projects/deploy_keys/new.html.haml +++ b/app/views/projects/deploy_keys/new.html.haml @@ -1,5 +1,5 @@ - page_title "New Deploy Key" -%h3.page-title New Deploy key +%h3.page-title New Deploy Key %hr = render 'form' diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml index 416fb4da07..f9d661d59d 100644 --- a/app/views/projects/diffs/_diffs.html.haml +++ b/app/views/projects/diffs/_diffs.html.haml @@ -3,7 +3,7 @@ - diff_files = safe_diff_files(diffs) -.gray-content-block.second-block.oneline-block +.gray-content-block.middle-block.oneline-block .inline-parallel-buttons .btn-group = inline_diff_btn diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml index c745b4e69b..327e7d9245 100644 --- a/app/views/projects/diffs/_file.html.haml +++ b/app/views/projects/diffs/_file.html.haml @@ -2,22 +2,29 @@ .diff-header{id: "file-path-#{hexdigest(diff_file.file_path)}"} - if diff_file.diff.submodule? %span - - submodule_item = project.repository.blob_at(@commit.id, diff_file.file_path) - = submodule_link(submodule_item, @commit.id, project.repository) + = icon('archive fw') + %strong + = submodule_link(blob, @commit.id, project.repository) - else %span + = blob_icon blob.mode, blob.name + = link_to "#diff-#{i}" do + %strong + = diff_file.new_path + - if diff_file.deleted_file - = "#{diff_file.old_path} deleted" + deleted - elsif diff_file.renamed_file - = "#{diff_file.old_path} renamed to #{diff_file.new_path}" - - else - = diff_file.new_path + renamed from + %strong + = diff_file.old_path - if diff_file.mode_changed? - %span.file-mode= "#{diff_file.diff.a_mode} → #{diff_file.diff.b_mode}" + %small + = "#{diff_file.diff.a_mode} → #{diff_file.diff.b_mode}" .diff-controls - - if blob.text? + - if blob_viewable?(blob) = link_to '#', class: 'js-toggle-diff-comments btn btn-sm active has_tooltip', title: "Toggle comments for this file" do %i.fa.fa-comments   @@ -32,7 +39,7 @@ .diff-content.diff-wrap-lines -# Skipp all non non-supported blobs - return unless blob.respond_to?('text?') - - if blob.text? + - if blob_viewable?(blob) - if diff_view == 'parallel' = render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob, index: i - else diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 3ebc175648..650629ef1b 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -14,7 +14,7 @@ = f.label :name, class: 'control-label' do Project name .col-sm-10 - = f.text_field :name, placeholder: "Example Project", class: "form-control", id: "project_name_edit" + = f.text_field :name, class: "form-control", id: "project_name_edit" .form-group @@ -22,12 +22,12 @@ Project description %span.light (optional) .col-sm-10 - = f.text_area :description, placeholder: "Awesome project", class: "form-control", rows: 3, maxlength: 250 + = f.text_area :description, class: "form-control", rows: 3, maxlength: 250 - - if @project.repository.exists? && @project.repository.branch_names.any? + - unless @project.empty_repo? .form-group = f.label :default_branch, "Default Branch", class: 'control-label' - .col-sm-10= f.select(:default_branch, @repository.branch_names, {}, {class: 'select2 select-wide'}) + .col-sm-10= f.select(:default_branch, @project.repository.branch_names, {}, {class: 'select2 select-wide'}) = render 'shared/visibility_level', f: f, visibility_level: @project.visibility_level, can_change_visibility_level: can_change_visibility_level?(@project, current_user), form_model: @project @@ -35,7 +35,7 @@ .form-group = f.label :tag_list, "Tags", class: 'control-label' .col-sm-10 - = f.text_field :tag_list, maxlength: 2000, class: "form-control" + = f.text_field :tag_list, value: @project.tag_list.to_s, maxlength: 2000, class: "form-control" %p.help-block Separate tags with commas. %fieldset.features @@ -112,6 +112,62 @@ %hr = link_to 'Remove avatar', namespace_project_avatar_path(@project.namespace, @project), data: { confirm: "Project avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar" + %fieldset.features + %legend + Continuous Integration + .form-group + .col-sm-offset-2.col-sm-10 + %p Get recent application code using the following command: + .radio + = f.label :build_allow_git_fetch do + = f.radio_button :build_allow_git_fetch, 'false' + %strong git clone + %br + %span.descr Slower but makes sure you have a clean dir before every build + .radio + = f.label :build_allow_git_fetch do + = f.radio_button :build_allow_git_fetch, 'true' + %strong git fetch + %br + %span.descr Faster + .form-group + = f.label :build_timeout_in_minutes, 'Timeout', class: 'control-label' + .col-sm-10 + = f.number_field :build_timeout_in_minutes, class: 'form-control', min: '0' + %p.help-block per build in minutes + .form-group + = f.label :build_coverage_regex, "Test coverage parsing", class: 'control-label' + .col-sm-10 + .input-group + %span.input-group-addon / + = f.text_field :build_coverage_regex, class: 'form-control', placeholder: '\(\d+.\d+\%\) covered' + %span.input-group-addon / + %p.help-block + We will use this regular expression to find test coverage output in build trace. + Leave blank if you want to disable this feature + .bs-callout.bs-callout-info + %p Below are examples of regex for existing tools: + %ul + %li + Simplecov (Ruby) - + %code \(\d+.\d+\%\) covered + %li + pytest-cov (Python) - + %code \d+\%\s*$ + %li + phpunit --coverage-text --colors=never (PHP) - + %code ^\s*Lines:\s*\d+.\d+\% + + + %fieldset.features + %legend + Advanced settings + .form-group + = f.label :runners_token, "CI token", class: 'control-label' + .col-sm-10 + = f.text_field :runners_token, class: "form-control", placeholder: 'xEeFCaDAB89' + %p.help-block The secure token used to checkout project. + .form-actions = f.submit 'Save changes', class: "btn btn-save" @@ -130,9 +186,11 @@ The project can be committed to. %br %strong Once active this project shows up in the search and on the dashboard. - = link_to 'Unarchive', unarchive_namespace_project_path(@project.namespace, @project), - data: { confirm: "Are you sure that you want to unarchive this project?\nWhen this project is unarchived it is active and can be committed to again." }, - method: :post, class: "btn btn-success" + + .form-actions + = link_to 'Unarchive project', unarchive_namespace_project_path(@project.namespace, @project), + data: { confirm: "Are you sure that you want to unarchive this project?\nWhen this project is unarchived it is active and can be committed to again." }, + method: :post, class: "btn btn-success" - else .panel.panel-warning .panel-heading @@ -144,9 +202,11 @@ It is hidden from the dashboard and doesn't show up in searches. %br %strong Archived projects cannot be committed to! - = link_to 'Archive', archive_namespace_project_path(@project.namespace, @project), - data: { confirm: "Are you sure that you want to archive this project?\nAn archived project cannot be committed to." }, - method: :post, class: "btn btn-warning" + + .form-actions + = link_to 'Archive project', archive_namespace_project_path(@project.namespace, @project), + data: { confirm: "Are you sure that you want to archive this project?\nAn archived project cannot be committed to." }, + method: :post, class: "btn btn-warning" - else .nothing-here-block Only the project owner can archive a project @@ -160,7 +220,7 @@ Project name .col-sm-9 .form-group - = f.text_field :name, placeholder: "Example Project", class: "form-control" + = f.text_field :name, class: "form-control" .form-group = f.label :path, class: 'control-label' do %span Path @@ -170,12 +230,11 @@ .input-group-addon #{URI.join(root_url, @project.namespace.path)}/ = f.text_field :path, class: 'form-control' - %span.input-group-addon .git %ul %li Be careful. Renaming a project's repository can have unintended side effects. %li You will need to update your local repositories to point to the new location. .form-actions - = f.submit 'Rename', class: "btn btn-warning" + = f.submit 'Rename project', class: "btn btn-warning" - if can?(current_user, :change_namespace, @project) .panel.panel-default.panel.panel-danger @@ -194,7 +253,7 @@ %li You can only transfer the project to namespaces you manage. %li You will need to update your local repositories to point to the new location. .form-actions - = f.submit 'Transfer', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => transfer_project_message(@project) } + = f.submit 'Transfer project', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => transfer_project_message(@project) } - else .nothing-here-block Only the project owner can transfer a project @@ -209,7 +268,8 @@ #{link_to @project.forked_from_project.name_with_namespace, project_path(@project.forked_from_project)}. %br %strong Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source. - = button_to 'Remove fork relationship', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_fork_project_message(@project) } + .form-actions + = button_to 'Remove fork relationship', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_fork_project_message(@project) } - else .nothing-here-block Only the project owner can remove the fork relationship. @@ -222,8 +282,8 @@ Removing the project will delete its repository and all related resources including issues, merge requests etc. %br %strong Removed projects cannot be restored! - - = button_to 'Remove project', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_project_message(@project) } + .form-actions + = button_to 'Remove project', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_project_message(@project) } - else .nothing-here-block Only the project owner can remove a project. diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml index c3858e78ca..503d156661 100644 --- a/app/views/projects/empty.html.haml +++ b/app/views/projects/empty.html.haml @@ -1,21 +1,20 @@ -.alert_holder += content_for :flash_message do - if current_user && can?(current_user, :download_code, @project) = render 'shared/no_ssh' = render 'shared/no_password' = render "home_panel" -.gray-content-block.center +.gray-content-block.second-block.center %h3.page-title The repository for this project is empty - - if can?(current_user, :download_code, @project) + - if can?(current_user, :push_code, @project) %p If you already have files you can push them using command line instructions below. - %br - - if can?(current_user, :push_code, @project) - Otherwise you can start with - = link_to "adding README", new_readme_path, class: 'underlined-link' - file to this project. + %p + Otherwise you can start with + = link_to "adding README", new_readme_path, class: 'underlined-link' + file to this project. - if can?(current_user, :download_code, @project) .prepend-top-20 diff --git a/app/views/projects/graphs/_head.html.haml b/app/views/projects/graphs/_head.html.haml index 03d0733f91..a47643bd09 100644 --- a/app/views/projects/graphs/_head.html.haml +++ b/app/views/projects/graphs/_head.html.haml @@ -3,6 +3,8 @@ = link_to 'Contributors', namespace_project_graph_path = nav_link(action: :commits) do = link_to 'Commits', commits_namespace_project_graph_path + = nav_link(action: :languages) do + = link_to 'Languages', languages_namespace_project_graph_path - if @project.builds_enabled? = nav_link(action: :ci) do = link_to ci_namespace_project_graph_path do diff --git a/app/views/projects/graphs/ci/_overall.haml b/app/views/projects/graphs/ci/_overall.haml index cf4285a267..4b12e5f2da 100644 --- a/app/views/projects/graphs/ci/_overall.haml +++ b/app/views/projects/graphs/ci/_overall.haml @@ -1,20 +1,19 @@ -- ci_project = @project.gitlab_ci_project %h4 Overall stats %ul %li Total: - %strong= pluralize ci_project.builds.count(:all), 'build' + %strong= pluralize @project.builds.count(:all), 'build' %li Successful: - %strong= pluralize ci_project.builds.success.count(:all), 'build' + %strong= pluralize @project.builds.success.count(:all), 'build' %li Failed: - %strong= pluralize ci_project.builds.failed.count(:all), 'build' + %strong= pluralize @project.builds.failed.count(:all), 'build' %li Success ratio: %strong - #{success_ratio(ci_project.builds.success, ci_project.builds.failed)}% + #{success_ratio(@project.builds.success, @project.builds.failed)}% %li Commits covered: %strong - = ci_project.commits.count(:all) + = @project.ci_commits.count(:all) diff --git a/app/views/projects/graphs/languages.html.haml b/app/views/projects/graphs/languages.html.haml new file mode 100644 index 0000000000..a7fab5b6d7 --- /dev/null +++ b/app/views/projects/graphs/languages.html.haml @@ -0,0 +1,32 @@ +- page_title "Languages", "Graphs" += render "header_title" += render 'head' + +.gray-content-block.append-bottom-default + .oneline + Programming languages used in this repository + +.row + .col-md-8 + %canvas#languages-chart{ height: 400 } + .col-md-4 + %ul.bordered-list + - @languages.each do |language| + %li + %span{ style: "color: #{language[:color]}" } + = icon('circle') +   + = language[:label] + .pull-right + = language[:value] + \% + +:javascript + var data = #{@languages.to_json}; + var ctx = $("#languages-chart").get(0).getContext("2d"); + var options = { + scaleOverlay: true, + responsive: true, + maintainAspectRatio: false + } + var myPieChart = new Chart(ctx).Pie(data, options); diff --git a/app/views/projects/hooks/index.html.haml b/app/views/projects/hooks/index.html.haml index 3702aeaecb..b18d9197d0 100644 --- a/app/views/projects/hooks/index.html.haml +++ b/app/views/projects/hooks/index.html.haml @@ -55,6 +55,13 @@ %strong Merge Request events %p.light This url will be triggered when a merge request is created + %div + = f.check_box :build_events, class: 'pull-left' + .prepend-left-20 + = f.label :build_events, class: 'list-label' do + %strong Build events + %p.light + This url will be triggered when the build status changes .form-group = f.label :enable_ssl_verification, "SSL verification", class: 'control-label checkbox' .col-sm-10 @@ -78,7 +85,7 @@ .clearfix %span.monospace= hook.url %p - - %w(push_events tag_push_events issues_events note_events merge_requests_events).each do |trigger| + - %w(push_events tag_push_events issues_events note_events merge_requests_events build_events).each do |trigger| - if hook.send(trigger) %span.label.label-gray= trigger.titleize SSL Verification: #{hook.enable_ssl_verification ? "enabled" : "disabled"} diff --git a/app/views/projects/issues/_closed_by_box.html.haml b/app/views/projects/issues/_closed_by_box.html.haml index aef352029d..de415ae51a 100644 --- a/app/views/projects/issues/_closed_by_box.html.haml +++ b/app/views/projects/issues/_closed_by_box.html.haml @@ -1,3 +1,2 @@ -.issue-closed-by-widget - = icon('check') - This issue will be closed automatically when merge request #{gfm(merge_requests_sentence(@closed_by_merge_requests.sort))} is accepted. +.issue-closed-by-widget.gray-content-block.second-block.white + This issue will be closed automatically when merge request #{markdown(merge_requests_sentence(@closed_by_merge_requests), pipeline: :gfm)} is accepted. diff --git a/app/views/projects/issues/_discussion.html.haml b/app/views/projects/issues/_discussion.html.haml index 020952dd00..86d3dc546b 100644 --- a/app/views/projects/issues/_discussion.html.haml +++ b/app/views/projects/issues/_discussion.html.haml @@ -5,34 +5,5 @@ - else = link_to 'Close Issue', issue_path(@issue, issue: {state_event: :close}, status_only: true), method: :put, class: 'btn btn-grouped btn-close js-note-target-close', title: 'Close Issue' -= render 'shared/show_aside' - -.gray-content-block.second-block.oneline-block - .row - .col-md-9 - .votes-holder.pull-right - #votes= render 'votes/votes_block', votable: @issue - .participants - %span= pluralize(@participants.count, 'participant') - - @participants.each do |participant| - = link_to_member(@project, participant, name: false, size: 24) - .col-md-3 - .input-group.cross-project-reference - %span.slead.has_tooltip{title: 'Cross-project reference'} - = cross_project_reference(@project, @issue) - = clipboard_button - -.row - %section.col-md-9 - .voting_notes#notes= render 'projects/notes/notes_with_form' - %aside.col-md-3 - .issuable-affix - .context - = render 'shared/issuable/context', issuable: @issue - - - if @issue.labels.any? - .issuable-context-title - %label Labels - .issue-show-labels - - @issue.labels.each do |label| - = link_to_label(label) +#notes + = render 'projects/notes/notes_with_form' diff --git a/app/views/projects/issues/_form.html.haml b/app/views/projects/issues/_form.html.haml index f39bb7d257..6588d9bdbe 100644 --- a/app/views/projects/issues/_form.html.haml +++ b/app/views/projects/issues/_form.html.haml @@ -1,9 +1,5 @@ -%div.issue-form-holder - %h3.page-title= @issue.new_record? ? "Create Issue" : "Edit Issue ##{@issue.iid}" - %hr - - = form_for [@project.namespace.becomes(Namespace), @project, @issue], html: { class: 'form-horizontal issue-form gfm-form' } do |f| - = render 'shared/issuable/form', f: f, issuable: @issue += form_for [@project.namespace.becomes(Namespace), @project, @issue], html: { class: 'form-horizontal issue-form gfm-form js-requires-input' } do |f| + = render 'shared/issuable/form', f: f, issuable: @issue :javascript $('.assign-to-me-link').on('click', function(e){ diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml index d7657ee7e4..f9cf4910df 100644 --- a/app/views/projects/issues/_issue.html.haml +++ b/app/views/projects/issues/_issue.html.haml @@ -6,35 +6,42 @@ .issue-title %span.issue-title-text = link_to_gfm issue.title, issue_path(issue), class: "row_title" - .issue-labels - - issue.labels.each do |label| - = link_to_label(label, project: issue.project) - .pull-right.light + %ul.controls.light - if issue.closed? - %span + %li CLOSED + - if issue.assignee - = link_to_member(@project, issue.assignee, name: false) + %li + = link_to_member(@project, issue.assignee, name: false, title: "Assigned to :name") + - note_count = issue.notes.user.count - if note_count > 0 -   - %span - %i.fa.fa-comments - = note_count + %li + = link_to issue_path(issue) + "#notes" do + = icon('comments') + = note_count - else -   - %span.issue-no-comments - %i.fa.fa-comments - = 0 + %li + = link_to issue_path(issue) + "#notes", class: "issue-no-comments" do + = icon('comments') + = note_count .issue-info - = "#{issue.to_reference} opened #{time_ago_with_tooltip(issue.created_at, placement: 'bottom')} by #{link_to_member(@project, issue.author, avatar: false)}".html_safe + #{issue.to_reference} · + opened #{time_ago_with_tooltip(issue.created_at, placement: 'bottom')} + by #{link_to_member(@project, issue.author, avatar: false)} - if issue.milestone   - %span - %i.fa.fa-clock-o + = link_to namespace_project_issues_path(issue.project.namespace, issue.project, milestone_title: issue.milestone.title) do + = icon('clock-o') = issue.milestone.title + - if issue.labels.any? +   + - issue.labels.each do |label| + = link_to_label(label, project: issue.project) - if issue.tasks? +   %span.task-status = issue.task_status diff --git a/app/views/projects/issues/_merge_requests.html.haml b/app/views/projects/issues/_merge_requests.html.haml new file mode 100644 index 0000000000..254968e4f6 --- /dev/null +++ b/app/views/projects/issues/_merge_requests.html.haml @@ -0,0 +1,26 @@ +-if @merge_requests.any? + %h2.merge-requests-title + = pluralize(@merge_requests.count, 'Related Merge Request') + %ul.bordered-list + - has_any_ci = @merge_requests.any?(&:ci_commit) + - @merge_requests.each do |merge_request| + %li + %span.merge-request-ci-status + - if merge_request.ci_commit + = render_ci_status(merge_request.ci_commit) + - elsif has_any_ci + = icon('blank fw') + %span.merge-request-id + \##{merge_request.iid} + %span.merge-request-info + %strong + = link_to_gfm merge_request.title, merge_request_path(merge_request), class: "row_title" + - unless @issue.project.id == merge_request.target_project.id + in + - project = merge_request.target_project + = link_to project.name_with_namespace, namespace_project_path(project.namespace, project) + %span.merge-request-status.prepend-left-10 + - if merge_request.merged? + MERGED + - elsif merge_request.closed? + CLOSED diff --git a/app/views/projects/issues/edit.html.haml b/app/views/projects/issues/edit.html.haml index 53b6f0879c..20216297d2 100644 --- a/app/views/projects/issues/edit.html.haml +++ b/app/views/projects/issues/edit.html.haml @@ -1,2 +1,8 @@ - page_title "Edit", "#{@issue.title} (##{@issue.iid})", "Issues" += render "header_title" + +%h3.page-title + Edit Issue ##{@issue.iid} +%hr + = render "form" diff --git a/app/views/projects/issues/new.html.haml b/app/views/projects/issues/new.html.haml index 153447baa1..b317a0c1cf 100644 --- a/app/views/projects/issues/new.html.haml +++ b/app/views/projects/issues/new.html.haml @@ -1,4 +1,8 @@ - page_title "New Issue" = render "header_title" +%h3.page-title + New Issue +%hr + = render "form" diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index f01bf2505d..2fe6f88b2a 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -2,51 +2,68 @@ = render "header_title" .issue - .issue-details.issuable-details - .page-title - .issue-box{ class: issue_box_class(@issue) } + .detail-page-header + .status-box{ class: status_box_class(@issue) } + - if @issue.closed? + Closed + - else + Open + %span.identifier + Issue ##{@issue.iid} + %span.creator + · + opened by #{link_to_member(@project, @issue.author, size: 24)} + · + = time_ago_with_tooltip(@issue.created_at, placement: 'bottom', html_class: 'issue_created_ago') + - if @issue.updated_at != @issue.created_at + %span + · + = icon('edit', title: 'edited') + = time_ago_with_tooltip(@issue.updated_at, placement: 'bottom', html_class: 'issue_edited_ago') + + .pull-right + - if can?(current_user, :create_issue, @project) + = link_to new_namespace_project_issue_path(@project.namespace, @project), class: 'btn btn-grouped new-issue-link', title: 'New Issue', id: 'new_issue_link' do + = icon('plus') + New Issue + - if can?(current_user, :update_issue, @issue) - if @issue.closed? - Closed + = link_to 'Reopen', issue_path(@issue, issue: {state_event: :reopen}, status_only: true), method: :put, class: 'btn btn-grouped btn-reopen' - else - Open - %span.issue-id Issue ##{@issue.iid} - %span.creator - · created by #{link_to_member(@project, @issue.author, size: 24)} - · - = time_ago_with_tooltip(@issue.created_at, placement: 'bottom', html_class: 'issue_created_ago') - - if @issue.updated_at != @issue.created_at - %span - · - = icon('edit', title: 'edited') - = time_ago_with_tooltip(@issue.updated_at, placement: 'bottom', html_class: 'issue_edited_ago') + = link_to 'Close', issue_path(@issue, issue: {state_event: :close}, status_only: true), method: :put, class: 'btn btn-grouped btn-close', title: 'Close Issue' - .pull-right - - if can?(current_user, :create_issue, @project) - = link_to new_namespace_project_issue_path(@project.namespace, @project), class: 'btn btn-grouped new-issue-link', title: 'New Issue', id: 'new_issue_link' do - = icon('plus') - New Issue - - if can?(current_user, :update_issue, @issue) - - if @issue.closed? - = link_to 'Reopen', issue_path(@issue, issue: {state_event: :reopen}, status_only: true), method: :put, class: 'btn btn-grouped btn-reopen' - - else - = link_to 'Close', issue_path(@issue, issue: {state_event: :close}, status_only: true), method: :put, class: 'btn btn-grouped btn-close', title: 'Close Issue' + = link_to edit_namespace_project_issue_path(@project.namespace, @project, @issue), class: 'btn btn-grouped issuable-edit' do + = icon('pencil-square-o') + Edit - = link_to edit_namespace_project_issue_path(@project.namespace, @project, @issue), class: 'btn btn-grouped issuable-edit' do - = icon('pencil-square-o') - Edit - - .gray-content-block.middle-block - %h2.issue-title - = gfm escape_once(@issue.title) + .issue-details.issuable-details + .detail-page-description.gray-content-block.second-block + %h2.title + = markdown escape_once(@issue.title), pipeline: :single_line %div - if @issue.description.present? .description{class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : ''} .wiki = preserve do - = markdown(@issue.description) + = markdown(@issue.description, cache_key: [@issue, "description"]) %textarea.hidden.js-task-list-field = @issue.description - - if @closed_by_merge_requests.present? - = render 'projects/issues/closed_by_box' - .issue-discussion - = render 'projects/issues/discussion' + + .merge-requests + = render 'merge_requests' + + .gray-content-block.second-block.oneline-block + = render 'votes/votes_block', votable: @issue + + - if @closed_by_merge_requests.present? + = render 'projects/issues/closed_by_box' + + .row + %section.col-md-9 + .issuable-discussion + = render 'projects/issues/discussion' + + %aside.col-md-3 + = render 'shared/issuable/sidebar', issuable: @issue + + = render 'shared/show_aside' diff --git a/app/views/projects/issues/update.js.haml b/app/views/projects/issues/update.js.haml index b7735aaf3c..2f0f3fcfb0 100644 --- a/app/views/projects/issues/update.js.haml +++ b/app/views/projects/issues/update.js.haml @@ -1,3 +1,3 @@ -$('.context').html("#{escape_javascript(render 'shared/issuable/context', issuable: @issue)}"); -$('.context').effect('highlight') +$('.issuable-sidebar').html("#{escape_javascript(render 'shared/issuable/sidebar', issuable: @issue)}"); +$('.issuable-sidebar').parent().effect('highlight') new Issue(); diff --git a/app/views/projects/labels/_form.html.haml b/app/views/projects/labels/_form.html.haml index 4cf13492e9..5ce2a7b985 100644 --- a/app/views/projects/labels/_form.html.haml +++ b/app/views/projects/labels/_form.html.haml @@ -10,9 +10,9 @@ .form-group = f.label :title, class: 'control-label' .col-sm-10 - = f.text_field :title, class: "form-control js-quick-submit", required: true + = f.text_field :title, class: "form-control js-quick-submit", required: true, autofocus: true .form-group - = f.label :color, "Background Color", class: 'control-label' + = f.label :color, "Background color", class: 'control-label' .col-sm-10 .input-group .input-group-addon.label-color-preview   @@ -28,6 +28,8 @@   .form-actions - = f.submit 'Save', class: 'btn btn-save js-save-button' + - if @label.persisted? + = f.submit 'Save changes', class: 'btn btn-save js-save-button' + - else + = f.submit 'Create Label', class: 'btn btn-create js-save-button' = link_to "Cancel", namespace_project_labels_path(@project.namespace, @project), class: 'btn btn-cancel' - diff --git a/app/views/projects/labels/_label.html.haml b/app/views/projects/labels/_label.html.haml index c6ebfa281a..b70a9fc9fe 100644 --- a/app/views/projects/labels/_label.html.haml +++ b/app/views/projects/labels/_label.html.haml @@ -7,4 +7,4 @@ - if can? current_user, :admin_label, @project = link_to 'Edit', edit_namespace_project_label_path(@project.namespace, @project, label), class: 'btn btn-sm' - = link_to 'Remove', namespace_project_label_path(@project.namespace, @project, label), class: 'btn btn-sm btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Remove this label? Are you sure?"} + = link_to 'Delete', namespace_project_label_path(@project.namespace, @project, label), class: 'btn btn-sm btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Remove this label? Are you sure?"} diff --git a/app/views/projects/labels/edit.html.haml b/app/views/projects/labels/edit.html.haml index bc4ab0ca27..675a805e12 100644 --- a/app/views/projects/labels/edit.html.haml +++ b/app/views/projects/labels/edit.html.haml @@ -1,11 +1,7 @@ - page_title "Edit", @label.name, "Labels" = render "header_title" -%h3 - Edit label - %span.light #{@label.name} -.back-link - = link_to namespace_project_labels_path(@project.namespace, @project) do - ← To labels list +%h3.page-title + Edit Label %hr = render 'form' diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml index fb784ee5f4..9081bcfe9b 100644 --- a/app/views/projects/labels/index.html.haml +++ b/app/views/projects/labels/index.html.haml @@ -4,6 +4,7 @@ .gray-content-block.top-block - if can? current_user, :admin_label, @project = link_to new_namespace_project_label_path(@project.namespace, @project), class: "pull-right btn btn-new" do + = icon('plus') New label .oneline Labels can be applied to issues and merge requests. diff --git a/app/views/projects/labels/new.html.haml b/app/views/projects/labels/new.html.haml index 342ad4f3f9..e20fd7d689 100644 --- a/app/views/projects/labels/new.html.haml +++ b/app/views/projects/labels/new.html.haml @@ -1,9 +1,7 @@ - page_title "New Label" = render "header_title" -%h3 New label -.back-link - = link_to namespace_project_labels_path(@project.namespace, @project) do - ← To labels list +%h3.page-title + New Label %hr = render 'form' diff --git a/app/views/projects/merge_requests/_discussion.html.haml b/app/views/projects/merge_requests/_discussion.html.haml index cb75bd8c5b..399e9cc1e1 100644 --- a/app/views/projects/merge_requests/_discussion.html.haml +++ b/app/views/projects/merge_requests/_discussion.html.haml @@ -5,31 +5,4 @@ - if @merge_request.closed? = link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: "btn btn-grouped btn-reopen reopen-mr-link js-note-target-reopen", title: "Reopen merge request" -= render 'shared/show_aside' - -.gray-content-block.second-block.oneline-block - .row - .col-md-9 - .votes-holder.pull-right - #votes= render 'votes/votes_block', votable: @merge_request - = render "projects/merge_requests/show/participants" - .col-md-3 - .input-group.cross-project-reference - %span.slead.has_tooltip{title: 'Cross-project reference'} - = cross_project_reference(@project, @merge_request) - = clipboard_button - -.row - %section.col-md-9 - = render "projects/notes/notes_with_form" - %aside.col-md-3 - .issuable-affix - .context - = render 'shared/issuable/context', issuable: @merge_request - - - if @merge_request.labels.any? - .issuable-context-title - %label Labels - .merge-request-show-labels - - @merge_request.labels.each do |label| - = link_to_label(label) +#notes= render "projects/notes/notes_with_form" diff --git a/app/views/projects/merge_requests/_form.html.haml b/app/views/projects/merge_requests/_form.html.haml index 9cf389dbe3..3e4ab09c6d 100644 --- a/app/views/projects/merge_requests/_form.html.haml +++ b/app/views/projects/merge_requests/_form.html.haml @@ -1,6 +1,5 @@ = form_for [@project.namespace.becomes(Namespace), @project, @merge_request], html: { class: 'merge-request-form form-horizontal gfm-form js-requires-input' } do |f| - .merge-request-form-info - = render 'shared/issuable/form', f: f, issuable: @merge_request + = render 'shared/issuable/form', f: f, issuable: @merge_request :javascript $('.assign-to-me-link').on('click', function(e){ diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml index 83e8ad1198..105c731c7e 100644 --- a/app/views/projects/merge_requests/_merge_request.html.haml +++ b/app/views/projects/merge_requests/_merge_request.html.haml @@ -1,50 +1,61 @@ -- ci_commit = merge_request.ci_commit %li{ class: mr_css_classes(merge_request) } .merge-request-title %span.merge-request-title-text = link_to_gfm merge_request.title, merge_request_path(merge_request), class: "row_title" - .merge-request-labels - - merge_request.labels.each do |label| - = link_to_label(label, project: merge_request.project) - .pull-right.light - - if ci_commit - = render_ci_status(ci_commit) + %ul.controls.light - if merge_request.merged? - %span - %i.fa.fa-check + %li MERGED - elsif merge_request.closed? - %span - %i.fa.fa-ban + %li + = icon('ban') CLOSED - - note_count = merge_request.mr_and_commit_notes.user.count + + - if merge_request.ci_commit + %li + = render_ci_status(merge_request.ci_commit) + + - if merge_request.open? && merge_request.broken? + %li + = link_to merge_request_path(merge_request), class: "has_tooltip", title: "Cannot be merged automatically", data: {container: 'body'} do + = icon('exclamation-triangle') + - if merge_request.assignee -   - = link_to_member(merge_request.source_project, merge_request.assignee, name: false) + %li + = link_to_member(merge_request.source_project, merge_request.assignee, name: false, title: "Assigned to :name") + + - note_count = merge_request.mr_and_commit_notes.user.count - if note_count > 0 -   - %span - %i.fa.fa-comments - = note_count + %li + = link_to merge_request_path(merge_request) + "#notes" do + = icon('comments') + = note_count - else -   - %span.merge-request-no-comments - %i.fa.fa-comments - = 0 + %li + = link_to merge_request_path(merge_request) + "#notes", class: "merge-request-no-comments" do + = icon('comments') + = note_count .merge-request-info - = "##{merge_request.iid} opened #{time_ago_with_tooltip(merge_request.created_at, placement: 'bottom')} by #{link_to_member(@project, merge_request.author, avatar: false)}".html_safe - - if merge_request.milestone_id? -   - %span - %i.fa.fa-clock-o - = merge_request.milestone.title + \##{merge_request.iid} · + opened #{time_ago_with_tooltip(merge_request.created_at, placement: 'bottom')} + by #{link_to_member(@project, merge_request.author, avatar: false)} - if merge_request.target_project.default_branch != merge_request.target_branch   - %span - %i.fa.fa-code-fork + = link_to namespace_project_commits_path(merge_request.project.namespace, merge_request.project, merge_request.target_branch) do + = icon('code-fork') = merge_request.target_branch + - if merge_request.milestone +   + = link_to namespace_project_merge_requests_path(merge_request.project.namespace, merge_request.project, milestone_title: merge_request.milestone.title) do + = icon('clock-o') + = merge_request.milestone.title + - if merge_request.labels.any? +   + - merge_request.labels.each do |label| + = link_to_label(label, project: merge_request.project) - if merge_request.tasks? +   %span.task-status = merge_request.task_status diff --git a/app/views/projects/merge_requests/_new_compare.html.haml b/app/views/projects/merge_requests/_new_compare.html.haml index d9eff1f932..236a545c84 100644 --- a/app/views/projects/merge_requests/_new_compare.html.haml +++ b/app/views/projects/merge_requests/_new_compare.html.haml @@ -1,4 +1,5 @@ -%p.lead Compare branches for new Merge Request +%h3.page-title + New Merge Request = form_for [@project.namespace.becomes(Namespace), @project, @merge_request], url: new_namespace_project_merge_request_path(@project.namespace, @project), method: :get, html: { class: "merge-request-form form-inline js-requires-input" } do |f| .hide.alert.alert-danger.mr-compare-errors @@ -10,7 +11,7 @@ .panel-body = f.select(:source_project_id, [[@merge_request.source_project_path,@merge_request.source_project.id]] , {}, { class: 'source_project select2 span3', disabled: @merge_request.persisted?, required: true })   - = f.select(:source_branch, @merge_request.source_branches, { include_blank: "Select branch" }, {class: 'source_branch select2 span2', required: true}) + = f.select(:source_branch, @merge_request.source_branches, { include_blank: true }, { class: 'source_branch select2 span2', required: true, data: { placeholder: "Select source branch" } }) .panel-footer .mr_source_commit @@ -22,7 +23,7 @@ - projects = @project.forked_from_project.nil? ? [@project] : [@project, @project.forked_from_project] = f.select(:target_project_id, options_from_collection_for_select(projects, 'id', 'path_with_namespace', f.object.target_project_id), {}, { class: 'target_project select2 span3', disabled: @merge_request.persisted?, required: true })   - = f.select(:target_branch, @merge_request.target_branches, { include_blank: "Select branch" }, {class: 'target_branch select2 span2', required: true}) + = f.select(:target_branch, @merge_request.target_branches, { include_blank: true }, { class: 'target_branch select2 span2', required: true, data: { placeholder: "Select target branch" } }) .panel-footer .mr_target_commit @@ -37,7 +38,7 @@ %h4 Compare failed %p We can't compare selected branches. It may be because of huge diff. Please try again or select different branches. - else - .light-well.append-bottom-10 + .light-well.append-bottom-default .center %h4 There isn't anything to merge. @@ -51,8 +52,8 @@ are the same. - %div - = f.submit 'Compare branches', class: "btn btn-new mr-compare-btn" + .form-actions + = f.submit 'Compare branches and continue', class: "btn btn-new mr-compare-btn" :javascript var source_branch = $("#merge_request_source_branch") @@ -86,4 +87,3 @@ return; } }); - diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml index 6244d3ba0b..a14943b15d 100644 --- a/app/views/projects/merge_requests/_new_submit.html.haml +++ b/app/views/projects/merge_requests/_new_submit.html.haml @@ -1,5 +1,5 @@ %h3.page-title - New merge request + New Merge Request %p.slead - source_title, target_title = format_mr_branch_names(@merge_request) From @@ -11,27 +11,31 @@ = link_to 'Change branches', mr_change_branches_path(@merge_request) %hr = form_for [@project.namespace.becomes(Namespace), @project, @merge_request], html: { class: 'merge-request-form form-horizontal gfm-form js-requires-input' } do |f| - .merge-request-form-info - = render 'shared/issuable/form', f: f, issuable: @merge_request - = f.hidden_field :source_project_id - = f.hidden_field :source_branch - = f.hidden_field :target_project_id - = f.hidden_field :target_branch + = render 'shared/issuable/form', f: f, issuable: @merge_request + = f.hidden_field :source_project_id + = f.hidden_field :source_branch + = f.hidden_field :target_project_id + = f.hidden_field :target_branch .mr-compare.merge-request - %ul.merge-request-tabs + %ul.merge-request-tabs.center-top-menu.no-top.no-bottom %li.commits-tab - = link_to url_for(params), data: {target: '#commits', action: 'commits', toggle: 'tab'} do + = link_to url_for(params), data: {target: 'div#commits', action: 'commits', toggle: 'tab'} do Commits %span.badge= @commits.size + - if @ci_commit + %li.builds-tab.active + = link_to url_for(params), data: {target: 'div#builds', action: 'builds', toggle: 'tab'} do + Builds + %span.badge= @statuses.size %li.diffs-tab.active - = link_to url_for(params), data: {target: '#diffs', action: 'diffs', toggle: 'tab'} do + = link_to url_for(params), data: {target: 'div#diffs', action: 'diffs', toggle: 'tab'} do Changes %span.badge= @diffs.size .tab-content #commits.commits.tab-pane - = render "projects/commits/commits", project: @project + = render "projects/merge_requests/show/commits" #diffs.diffs.tab-pane.active - if @diffs.present? = render "projects/diffs/diffs", diffs: @diffs, project: @project @@ -43,6 +47,9 @@ .alert.alert-danger %h4 This comparison includes a huge diff. %p To preserve performance the line changes are not shown. + - if @ci_commit + #builds.builds.tab-pane + = render "projects/merge_requests/show/builds" :javascript $('.assign-to-me-link').on('click', function(e){ @@ -57,4 +64,3 @@ diffs_loaded: true, commits_loaded: true }); - diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index eeaa72ed21..e9ffbd06be 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -5,10 +5,11 @@ - fluid_layout true .merge-request{'data-url' => merge_request_path(@merge_request)} + = render "projects/merge_requests/show/mr_title" + .merge-request-details.issuable-details - = render "projects/merge_requests/show/mr_title" = render "projects/merge_requests/show/mr_box" - .append-bottom-20.mr-source-target.prepend-top-default + .append-bottom-default.mr-source-target.prepend-top-default - if @merge_request.open? .pull-right - if @merge_request.source_branch_exists? @@ -26,44 +27,62 @@ %li= link_to "Plain Diff", merge_request_path(@merge_request, format: :diff) .normal %span Request to merge - %span.label-branch #{source_branch_with_namespace(@merge_request)} + %span.label-branch= source_branch_with_namespace(@merge_request) %span into - %span.label-branch #{@merge_request.target_branch} + = link_to namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch), class: "label-branch" do + = @merge_request.target_branch = render "projects/merge_requests/show/how_to_merge" = render "projects/merge_requests/widget/show.html.haml" - - if @merge_request.open? && @merge_request.can_be_merged? - .light.append-bottom-20 + - if @merge_request.open? && @merge_request.source_branch_exists? && @merge_request.can_be_merged? && @merge_request.can_be_merged_by?(current_user) + .light.prepend-top-default You can also accept this merge request manually using the = succeed '.' do = link_to "command line", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal" - - if @commits.present? - %ul.merge-request-tabs - %li.notes-tab - = link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: '#notes', action: 'notes', toggle: 'tab'} do - Discussion - %span.badge= @merge_request.mr_and_commit_notes.user.count - %li.commits-tab - = link_to commits_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: '#commits', action: 'commits', toggle: 'tab'} do - Commits - %span.badge= @commits.size - %li.diffs-tab - = link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: '#diffs', action: 'diffs', toggle: 'tab'} do - Changes - %span.badge= @merge_request.diffs.size + - if @commits.present? + %ul.merge-request-tabs.center-top-menu.no-top.no-bottom + %li.notes-tab + = link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#notes', action: 'notes', toggle: 'tab'} do + Discussion + %span.badge= @merge_request.mr_and_commit_notes.user.count + %li.commits-tab + = link_to commits_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#commits', action: 'commits', toggle: 'tab'} do + Commits + %span.badge= @commits.size + - if @ci_commit + %li.builds-tab + = link_to builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: '#builds', action: 'builds', toggle: 'tab'} do + Builds + %span.badge= @statuses.size + %li.diffs-tab + = link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#diffs', action: 'diffs', toggle: 'tab'} do + Changes + %span.badge= @merge_request.diffs.size - .tab-content - #notes.notes.tab-pane.voting_notes - = render "projects/merge_requests/discussion" - #commits.commits.tab-pane - - # This tab is always loaded via AJAX - #diffs.diffs.tab-pane - - # This tab is always loaded via AJAX + .tab-content + #notes.notes.tab-pane.voting_notes + .gray-content-block.second-block.oneline-block + = render 'votes/votes_block', votable: @merge_request - .mr-loading-status - = spinner + .row + %section.col-md-9 + .issuable-discussion + = render "projects/merge_requests/discussion" + %aside.col-md-3 + = render 'shared/issuable/sidebar', issuable: @merge_request + = render 'shared/show_aside' + + #commits.commits.tab-pane + - # This tab is always loaded via AJAX + #builds.builds.tab-pane + - # This tab is always loaded via AJAX + #diffs.diffs.tab-pane + - # This tab is always loaded via AJAX + + .mr-loading-status + = spinner :javascript var merge_request; diff --git a/app/views/projects/merge_requests/cancel_merge_when_build_succeeds.js.haml b/app/views/projects/merge_requests/cancel_merge_when_build_succeeds.js.haml new file mode 100644 index 0000000000..eab5be488b --- /dev/null +++ b/app/views/projects/merge_requests/cancel_merge_when_build_succeeds.js.haml @@ -0,0 +1,2 @@ +:plain + $('.mr-widget-body').html("#{escape_javascript(render('projects/merge_requests/widget/open/accept'))}"); diff --git a/app/views/projects/merge_requests/edit.html.haml b/app/views/projects/merge_requests/edit.html.haml index 303ca0a880..fc62bb5bce 100644 --- a/app/views/projects/merge_requests/edit.html.haml +++ b/app/views/projects/merge_requests/edit.html.haml @@ -2,6 +2,6 @@ = render "header_title" %h3.page-title - = "Edit merge request ##{@merge_request.iid}" + Edit Merge Request ##{@merge_request.iid} %hr = render 'form' diff --git a/app/views/projects/merge_requests/merge.js.haml b/app/views/projects/merge_requests/merge.js.haml index 33321651e3..92ce479d46 100644 --- a/app/views/projects/merge_requests/merge.js.haml +++ b/app/views/projects/merge_requests/merge.js.haml @@ -1,6 +1,10 @@ -- if @status +- case @status +- when :success :plain - merge_request_widget.mergeInProgress(); + merge_request_widget.mergeInProgress(#{params[:should_remove_source_branch] == '1'}); +- when :merge_when_build_succeeds + :plain + $('.mr-widget-body').html("#{escape_javascript(render('projects/merge_requests/widget/open/merge_when_build_succeeds'))}"); - else :plain $('.mr-widget-body').html("#{escape_javascript(render('projects/merge_requests/widget/open/reload'))}"); diff --git a/app/views/projects/merge_requests/new.html.haml b/app/views/projects/merge_requests/new.html.haml index 9fdde80c6d..d259968030 100644 --- a/app/views/projects/merge_requests/new.html.haml +++ b/app/views/projects/merge_requests/new.html.haml @@ -1,7 +1,7 @@ - page_title "New Merge Request" = render "header_title" -- if @merge_request.can_be_created +- if @merge_request.can_be_created && !params[:change_branches] = render 'new_submit' - else = render 'new_compare' diff --git a/app/views/projects/merge_requests/show/_builds.html.haml b/app/views/projects/merge_requests/show/_builds.html.haml new file mode 100644 index 0000000000..307a75d02c --- /dev/null +++ b/app/views/projects/merge_requests/show/_builds.html.haml @@ -0,0 +1 @@ += render "projects/commit/builds", link_to_commit: true diff --git a/app/views/projects/merge_requests/show/_commits.html.haml b/app/views/projects/merge_requests/show/_commits.html.haml index 478054db51..7f904ec42a 100644 --- a/app/views/projects/merge_requests/show/_commits.html.haml +++ b/app/views/projects/merge_requests/show/_commits.html.haml @@ -1,4 +1,4 @@ -.gray-content-block.second-block.oneline-block +.gray-content-block.middle-block.oneline-block = icon("sort-amount-desc") Most recent commits displayed first diff --git a/app/views/projects/merge_requests/show/_how_to_merge.html.haml b/app/views/projects/merge_requests/show/_how_to_merge.html.haml index 98f0357ce4..877cc3d744 100644 --- a/app/views/projects/merge_requests/show/_how_to_merge.html.haml +++ b/app/views/projects/merge_requests/show/_how_to_merge.html.haml @@ -8,8 +8,8 @@ %p %strong Step 1. Fetch and check out the branch for this merge request - = clipboard_button - %pre.dark + = clipboard_button(clipboard_target: 'pre#merge-info-1') + %pre.dark#merge-info-1 - if @merge_request.for_fork? :preserve git fetch #{h @merge_request.source_project.http_url_to_repo} #{h @merge_request.source_branch} @@ -25,8 +25,8 @@ %p %strong Step 3. Merge the branch and fix any conflicts that come up - = clipboard_button - %pre.dark + = clipboard_button(clipboard_target: 'pre#merge-info-3') + %pre.dark#merge-info-3 - if @merge_request.for_fork? :preserve git checkout #{h @merge_request.target_branch} @@ -38,8 +38,8 @@ %p %strong Step 4. Push the result of the merge to GitLab - = clipboard_button - %pre.dark + = clipboard_button(clipboard_target: 'pre#merge-info-4') + %pre.dark#merge-info-4 :preserve git push origin #{h @merge_request.target_branch} - unless @merge_request.can_be_merged_by?(current_user) diff --git a/app/views/projects/merge_requests/show/_mr_box.html.haml b/app/views/projects/merge_requests/show/_mr_box.html.haml index b4f62a7589..0f81e5e891 100644 --- a/app/views/projects/merge_requests/show/_mr_box.html.haml +++ b/app/views/projects/merge_requests/show/_mr_box.html.haml @@ -1,12 +1,12 @@ -.gray-content-block.middle-block - %h2.issue-title - = gfm escape_once(@merge_request.title) +.detail-page-description.gray-content-block.second-block + %h2.title + = markdown escape_once(@merge_request.title), pipeline: :single_line %div - if @merge_request.description.present? .description{class: can?(current_user, :update_merge_request, @merge_request) ? 'js-task-list-container' : ''} .wiki = preserve do - = markdown(@merge_request.description) + = markdown(@merge_request.description, cache_key: [@merge_request, "description"]) %textarea.hidden.js-task-list-field = @merge_request.description diff --git a/app/views/projects/merge_requests/show/_mr_title.html.haml b/app/views/projects/merge_requests/show/_mr_title.html.haml index 2bf9cd597a..473124480a 100644 --- a/app/views/projects/merge_requests/show/_mr_title.html.haml +++ b/app/views/projects/merge_requests/show/_mr_title.html.haml @@ -1,10 +1,11 @@ -.page-title - .issue-box{ class: issue_box_class(@merge_request) } +.detail-page-header + .status-box{ class: status_box_class(@merge_request) } = @merge_request.state_human_name - %span.issue-id Merge Request ##{@merge_request.iid} + %span.identifier + Merge Request ##{@merge_request.iid} %span.creator · - created by #{link_to_member(@project, @merge_request.author, size: 24)} + opened by #{link_to_member(@project, @merge_request.author, size: 24)} · = time_ago_with_tooltip(@merge_request.created_at) - if @merge_request.updated_at != @merge_request.created_at @@ -16,9 +17,9 @@ .issue-btn-group.pull-right - if can?(current_user, :update_merge_request, @merge_request) - if @merge_request.open? - = link_to 'Close', merge_request_path(@merge_request, merge_request: { state_event: :close }), method: :put, class: "btn btn-grouped btn-close", title: "Close merge request" - = link_to edit_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), class: "btn btn-grouped issuable-edit", id: "edit_merge_request" do + = link_to 'Close', merge_request_path(@merge_request, merge_request: { state_event: :close }), method: :put, class: 'btn btn-grouped btn-close', title: 'Close merge request' + = link_to edit_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), class: 'btn btn-grouped issuable-edit', id: 'edit_merge_request' do %i.fa.fa-pencil-square-o Edit - if @merge_request.closed? - = link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: "btn btn-grouped btn-reopen reopen-mr-link", title: "Close merge request" + = link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: 'btn btn-grouped btn-reopen reopen-mr-link', title: 'Reopen merge request' diff --git a/app/views/projects/merge_requests/show/_participants.html.haml b/app/views/projects/merge_requests/show/_participants.html.haml deleted file mode 100644 index c67afe963e..0000000000 --- a/app/views/projects/merge_requests/show/_participants.html.haml +++ /dev/null @@ -1,4 +0,0 @@ -.participants - %span #{@participants.count} participants - - @participants.each do |participant| - = link_to_member(@project, participant, name: false, size: 24) diff --git a/app/views/projects/merge_requests/update.js.haml b/app/views/projects/merge_requests/update.js.haml index 25583b2cc6..93db65ddf7 100644 --- a/app/views/projects/merge_requests/update.js.haml +++ b/app/views/projects/merge_requests/update.js.haml @@ -1,3 +1,3 @@ -$('.context').html("#{escape_javascript(render 'shared/issuable/context', issuable: @merge_request)}"); -$('.context').effect('highlight') +$('.issuable-sidebar').html("#{escape_javascript(render 'shared/issuable/sidebar', issuable: @merge_request)}"); +$('.issuable-sidebar').parent().effect('highlight') merge_request = new MergeRequest(); diff --git a/app/views/projects/merge_requests/widget/_heading.html.haml b/app/views/projects/merge_requests/widget/_heading.html.haml index ba5ad22bca..b05ab86921 100644 --- a/app/views/projects/merge_requests/widget/_heading.html.haml +++ b/app/views/projects/merge_requests/widget/_heading.html.haml @@ -1,30 +1,33 @@ -- ci_commit = @merge_request.ci_commit -- if ci_commit - - status = ci_commit.status +- if @ci_commit .mr-widget-heading - .ci_widget{class: "ci-#{status}"} - = ci_status_icon(ci_commit) - %span CI build #{status} - for #{@merge_request.last_commit_short_sha}. + .ci_widget{class: "ci-#{@ci_commit.status}"} + = ci_status_icon(@ci_commit) + %span + Build + = ci_status_label(@ci_commit) + for + = succeed "." do + = link_to @ci_commit.short_sha, namespace_project_commit_path(@merge_request.source_project.namespace, @merge_request.source_project, @ci_commit.sha), class: "monospace" %span.ci-coverage - = link_to "View build details", ci_status_path(ci_commit) + = link_to "View details", builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), class: "js-show-tab", data: {action: 'builds'} - elsif @merge_request.has_ci? - # Compatibility with old CI integrations (ex jenkins) when you request status from CI server via AJAX - # Remove in later versions when services like Jenkins will set CI status via Commit status API .mr-widget-heading - - [:success, :skipped, :canceled, :failed, :running, :pending].each do |status| + - %w[success skipped canceled failed running pending].each do |status| .ci_widget{class: "ci-#{status}", style: "display:none"} - - if status == :success - - status = "passed" - = icon("check-circle") - - else - = icon("circle") - %span CI build #{status} - for #{@merge_request.last_commit_short_sha}. + = ci_icon_for_status(status) + %span + CI build + = ci_label_for_status(status) + for + - commit = @merge_request.last_commit + = succeed "." do + = link_to commit.short_id, namespace_project_commit_path(@merge_request.source_project.namespace, @merge_request.source_project, commit), class: "monospace" %span.ci-coverage - - if ci_build_details_path(@merge_request) - = link_to "View build details", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink" + - if details_path = ci_build_details_path(@merge_request) + = link_to "View details", details_path, :"data-no-turbolink" => "data-no-turbolink" .ci_widget = icon("spinner spin") diff --git a/app/views/projects/merge_requests/widget/_merged.html.haml b/app/views/projects/merge_requests/widget/_merged.html.haml index a788fcea23..d1d602eecd 100644 --- a/app/views/projects/merge_requests/widget/_merged.html.haml +++ b/app/views/projects/merge_requests/widget/_merged.html.haml @@ -7,18 +7,16 @@ by #{link_to_member(@project, @merge_request.merge_event.author, avatar: true)} #{time_ago_with_tooltip(@merge_request.merge_event.created_at)} %div - - if !@merge_request.source_branch_exists? - = succeed '.' do - The changes were merged into - %span.label-branch= @merge_request.target_branch + - if !@merge_request.source_branch_exists? || (params[:delete_source] == 'true') + The changes were merged into + #{link_to @merge_request.target_branch, namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch), class: "label-branch"}. The source branch has been removed. - - elsif can_remove_branch?(@merge_request.source_project, @merge_request.source_branch) + - elsif @merge_request.can_remove_source_branch?(current_user) .remove_source_branch_widget %p - = succeed '.' do - The changes were merged into - %span.label-branch= @merge_request.target_branch + The changes were merged into + #{link_to @merge_request.target_branch, namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch), class: "label-branch"}. You can remove the source branch now. = link_to namespace_project_branch_path(@merge_request.source_project.namespace, @merge_request.source_project, @merge_request.source_branch), remote: true, method: :delete, class: "btn btn-primary btn-sm remove_source_branch" do %i.fa.fa-times @@ -31,7 +29,7 @@ .remove_source_branch_in_progress.hide %p = icon('spinner spin') - Removing source branch '#{@merge_request.source_branch}'. Please wait. This page will be automatically reload. + Removing source branch '#{@merge_request.source_branch}'. Please wait, this page will be automatically reloaded. :javascript $('.remove_source_branch').on('click', function() { @@ -48,5 +46,3 @@ $('.remove_source_branch_in_progress').hide(); $('.remove_source_branch_widget.failed').show(); }); - - diff --git a/app/views/projects/merge_requests/widget/_open.html.haml b/app/views/projects/merge_requests/widget/_open.html.haml index 0aad9bb3e8..55dbae598d 100644 --- a/app/views/projects/merge_requests/widget/_open.html.haml +++ b/app/views/projects/merge_requests/widget/_open.html.haml @@ -13,6 +13,8 @@ = render 'projects/merge_requests/widget/open/conflicts' - elsif @merge_request.work_in_progress? = render 'projects/merge_requests/widget/open/wip' + - elsif @merge_request.merge_when_build_succeeds? + = render 'projects/merge_requests/widget/open/merge_when_build_succeeds' - elsif !@merge_request.can_be_merged_by?(current_user) = render 'projects/merge_requests/widget/open/not_allowed' - elsif @merge_request.can_be_merged? @@ -24,4 +26,4 @@ %i.fa.fa-check Accepting this merge request will close #{"issue".pluralize(@closes_issues.size)} = succeed '.' do - != gfm(issues_sentence(@closes_issues)) + != markdown issues_sentence(@closes_issues), pipeline: :gfm diff --git a/app/views/projects/merge_requests/widget/open/_accept.html.haml b/app/views/projects/merge_requests/widget/open/_accept.html.haml index 9b31014b58..d9a1730a8b 100644 --- a/app/views/projects/merge_requests/widget/open/_accept.html.haml +++ b/app/views/projects/merge_requests/widget/open/_accept.html.haml @@ -1,28 +1,60 @@ -- status_class = @merge_request.ci_commit ? " ci-#{@merge_request.ci_commit.status}" : nil +- status_class = @ci_commit ? " ci-#{@ci_commit.status}" : nil = form_for [:merge, @project.namespace.becomes(Namespace), @project, @merge_request], remote: true, method: :post, html: { class: 'accept-mr-form js-requires-input' } do |f| = hidden_field_tag :authenticity_token, form_authenticity_token .accept-merge-holder.clearfix.js-toggle-container - .accept-action - = f.button class: "btn btn-create accept_merge_request#{status_class}" do - Accept Merge Request - - if can_remove_branch?(@merge_request.source_project, @merge_request.source_branch) && !@merge_request.for_fork? - .accept-control.checkbox - = label_tag :should_remove_source_branch, class: "remove_source_checkbox" do - = check_box_tag :should_remove_source_branch - Remove source branch - .accept-control.right - = link_to "#", class: "modify-merge-commit-link js-toggle-button" do - = icon('edit') - Modify commit message - .js-toggle-content.hide.prepend-top-20 + .clearfix + .accept-action + - if @ci_commit && @ci_commit.active? + %span.btn-group + = button_tag class: "btn btn-create js-merge-button merge_when_build_succeeds" do + Merge When Build Succeeds + = button_tag class: "btn btn-success dropdown-toggle", 'data-toggle' => 'dropdown' do + %span.caret + %span.sr-only + Select Merge Moment + %ul.js-merge-dropdown.dropdown-menu.dropdown-menu-right{ role: 'menu' } + %li + = link_to "#", class: "merge_when_build_succeeds" do + = icon('check fw') + Merge When Build Succeeds + %li + = link_to "#", class: "accept_merge_request" do + = icon('warning fw') + Merge Immediately + - else + = f.button class: "btn btn-create btn-grouped js-merge-button accept_merge_request #{status_class}" do + Accept Merge Request + - if @merge_request.can_remove_source_branch?(current_user) + .accept-control.checkbox + = label_tag :should_remove_source_branch, class: "remove_source_checkbox" do + = check_box_tag :should_remove_source_branch + Remove source branch + .accept-control.right + = link_to "#", class: "modify-merge-commit-link js-toggle-button" do + = icon('edit') + Modify commit message + .js-toggle-content.hide.prepend-top-default = render 'shared/commit_message_container', params: params, text: @merge_request.merge_commit_message, rows: 14, hint: true + = hidden_field_tag :merge_when_build_succeeds, "", autocomplete: "off" + :javascript - $('.accept-mr-form').on('ajax:before', function() { - var btn = $('.accept_merge_request'); - btn.disable(); - btn.html(" Merge in progress"); + $('.accept-mr-form').on('ajax:send', function() { + $(".accept-mr-form :input").disable(); + }); + + $('.accept_merge_request').on('click', function() { + $('.js-merge-button').html(" Merge in progress"); + }); + + $('.merge_when_build_succeeds').on('click', function() { + $("#merge_when_build_succeeds").val("1"); + }); + + $('.js-merge-dropdown a').on('click', function(e) { + e.preventDefault(); + $(this).closest("form").submit(); }); diff --git a/app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml b/app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml new file mode 100644 index 0000000000..2168294c68 --- /dev/null +++ b/app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml @@ -0,0 +1,26 @@ +%h4 + Set by #{link_to_member(@project, @merge_request.merge_user, avatar: true)} + to be merged automatically when the build succeeds. +%div + - should_remove_source_branch = @merge_request.merge_params["should_remove_source_branch"].present? + %p + = succeed '.' do + The changes will be merged into + %span.label-branch= @merge_request.target_branch + - if should_remove_source_branch + The source branch will be removed. + - else + The source branch will not be removed. + + - remove_source_branch_button = @merge_request.can_remove_source_branch?(current_user) && !should_remove_source_branch && @merge_request.merge_user == current_user + - user_can_cancel_automatic_merge = @merge_request.can_cancel_merge_when_build_succeeds?(current_user) + - if remove_source_branch_button || user_can_cancel_automatic_merge + .clearfix.prepend-top-10 + - if remove_source_branch_button + = link_to merge_namespace_project_merge_request_path(@merge_request.target_project.namespace, @merge_request.target_project, @merge_request, merge_when_build_succeeds: true, should_remove_source_branch: true), remote: true, method: :post, class: "btn btn-grouped btn-primary btn-sm remove_source_branch" do + = icon('times') + Remove Source Branch When Merged + + - if user_can_cancel_automatic_merge + = link_to cancel_merge_when_build_succeeds_namespace_project_merge_request_path(@merge_request.target_project.namespace, @merge_request.target_project, @merge_request), remote: true, method: :post, class: "btn btn-grouped btn-warning btn-sm" do + Cancel Automatic Merge diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml index 24879b19d2..39aa2437e1 100644 --- a/app/views/projects/milestones/_form.html.haml +++ b/app/views/projects/milestones/_form.html.haml @@ -1,10 +1,3 @@ -%h3.page-title= @milestone.new_record? ? "New Milestone" : "Edit Milestone ##{@milestone.iid}" -.back-link - = link_to namespace_project_milestones_path(@project.namespace, @project) do - ← To milestones - -%hr - = form_for [@project.namespace.becomes(Namespace), @project, @milestone], html: {class: 'form-horizontal milestone-form gfm-form js-requires-input'} do |f| -if @milestone.errors.any? .alert.alert-danger @@ -16,8 +9,7 @@ .form-group = f.label :title, "Title", class: "control-label" .col-sm-10 - = f.text_field :title, maxlength: 255, class: "form-control js-quick-submit", required: true - %p.hint Required + = f.text_field :title, maxlength: 255, class: "form-control js-quick-submit", required: true, autofocus: true .form-group.milestone-description = f.label :description, "Description", class: "control-label" .col-sm-10 diff --git a/app/views/projects/milestones/_milestone.html.haml b/app/views/projects/milestones/_milestone.html.haml index 5e93d55b1f..d6a44c9f0a 100644 --- a/app/views/projects/milestones/_milestone.html.haml +++ b/app/views/projects/milestones/_milestone.html.haml @@ -18,11 +18,7 @@ .row .col-sm-6 - - if milestone.expired? and not milestone.closed? - %span.cred (Expired) - - if milestone.expires_at - %span - = milestone.expires_at + = render 'shared/milestone_expired', milestone: milestone .col-sm-6 - if can?(current_user, :admin_milestone, milestone.project) and milestone.active? = link_to edit_namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone), class: "btn btn-xs edit-milestone-link btn-grouped" do @@ -31,4 +27,4 @@ = link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, milestone, milestone: {state_event: :close }), method: :put, remote: true, class: "btn btn-xs btn-close" = link_to namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-xs btn-remove" do %i.fa.fa-trash-o - Remove + Delete diff --git a/app/views/projects/milestones/edit.html.haml b/app/views/projects/milestones/edit.html.haml index e9dc0b7746..43f8863163 100644 --- a/app/views/projects/milestones/edit.html.haml +++ b/app/views/projects/milestones/edit.html.haml @@ -1,3 +1,9 @@ - page_title "Edit", @milestone.title, "Milestones" = render "header_title" + +%h3.page-title + Edit Milestone ##{@milestone.iid} + +%hr + = render "form" diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml index a207385bd4..114b06457a 100644 --- a/app/views/projects/milestones/index.html.haml +++ b/app/views/projects/milestones/index.html.haml @@ -1,15 +1,18 @@ - page_title "Milestones" = render "header_title" -= render 'shared/milestones_filter' -.gray-content-block - .pull-right - - if can? current_user, :admin_milestone, @project + +.project-issuable-filter + .controls + - if can?(current_user, :admin_milestone, @project) = link_to new_namespace_project_milestone_path(@project.namespace, @project), class: "pull-right btn btn-new", title: "New Milestone" do %i.fa.fa-plus New Milestone - .oneline - Milestone allows you to group issues and set due date for it + + = render 'shared/milestones_filter' + +.gray-content-block + Milestone allows you to group issues and set due date for it .milestones %ul.content-list diff --git a/app/views/projects/milestones/new.html.haml b/app/views/projects/milestones/new.html.haml index 9ba9acb6f7..0d016f7831 100644 --- a/app/views/projects/milestones/new.html.haml +++ b/app/views/projects/milestones/new.html.haml @@ -1,3 +1,9 @@ - page_title "New Milestone" = render "header_title" + +%h3.page-title + New Milestone + +%hr + = render "form" diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml index 3a898dfbcf..7e73ae274e 100644 --- a/app/views/projects/milestones/show.html.haml +++ b/app/views/projects/milestones/show.html.haml @@ -1,46 +1,50 @@ - page_title @milestone.title, "Milestones" = render "header_title" -%h4.page-title - .issue-box{ class: issue_box_class(@milestone) } +.detail-page-header + .status-box{ class: status_box_class(@milestone) } - if @milestone.closed? Closed - elsif @milestone.expired? Expired - else Open - Milestone ##{@milestone.iid} - %small.creator - = @milestone.expires_at + %span.identifier + Milestone ##{@milestone.iid} + - if @milestone.expires_at + %span.creator + · + = @milestone.expires_at .pull-right - if can?(current_user, :admin_milestone, @project) - = link_to edit_namespace_project_milestone_path(@project.namespace, @project, @milestone), class: "btn btn-grouped" do - %i.fa.fa-pencil-square-o - Edit - if @milestone.active? = link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-close btn-grouped" - else = link_to 'Reopen Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn btn-reopen btn-grouped" + = link_to namespace_project_milestone_path(@project.namespace, @project, @milestone), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-grouped btn-remove" do %i.fa.fa-trash-o - Remove + Delete + + = link_to edit_namespace_project_milestone_path(@project.namespace, @project, @milestone), class: "btn btn-grouped" do + %i.fa.fa-pencil-square-o + Edit + +.detail-page-description.gray-content-block.second-block + %h2.title + = markdown escape_once(@milestone.title), pipeline: :single_line + %div + - if @milestone.description.present? + .description + .wiki + = preserve do + = markdown @milestone.description -%hr - if @milestone.issues.any? && @milestone.can_be_closed? - .alert.alert-success + .alert.alert-success.prepend-top-default %span All issues for this milestone are closed. You may close milestone now. -%h3.issue-title - = gfm escape_once(@milestone.title) -%div - - if @milestone.description.present? - .description - .wiki - = preserve do - = markdown @milestone.description - -%hr -.context +.context.prepend-top-default %p.lead Progress: #{@milestone.closed_items_count} closed @@ -51,8 +55,7 @@ %span.pull-right= @milestone.expires_at = milestone_progress_bar(@milestone) - -%ul.nav.nav-tabs +%ul.center-top-menu.no-top.no-bottom %li.active = link_to '#tab-issues', 'data-toggle' => 'tab' do Issues @@ -66,17 +69,21 @@ Participants %span.badge= @users.count - .pull-right - - if can?(current_user, :create_issue, @project) - = link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { milestone_id: @milestone.id }), class: "btn btn-grouped", title: "New Issue" do - %i.fa.fa-plus - New Issue - - if can?(current_user, :read_issue, @project) - = link_to 'Browse Issues', namespace_project_issues_path(@milestone.project.namespace, @milestone.project, milestone_title: @milestone.title), class: "btn edit-milestone-link btn-grouped" - .tab-content .tab-pane.active#tab-issues - .row + .gray-content-block.middle-block + .pull-right + - if can?(current_user, :create_issue, @project) + = link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { milestone_id: @milestone.id }), class: "btn btn-grouped", title: "New Issue" do + %i.fa.fa-plus + New Issue + - if can?(current_user, :read_issue, @project) + = link_to 'Browse Issues', namespace_project_issues_path(@milestone.project.namespace, @milestone.project, milestone_title: @milestone.title), class: "btn btn-grouped" + + .oneline + All issues in this milestone + + .row.prepend-top-default .col-md-4 = render('issues', title: 'Unstarted Issues (open and unassigned)', issues: @issues.opened.unassigned, id: 'unassigned') .col-md-4 @@ -85,7 +92,15 @@ = render('issues', title: 'Completed Issues (closed)', issues: @issues.closed, id: 'closed') .tab-pane#tab-merge-requests - .row + .gray-content-block.middle-block + .pull-right + - if can?(current_user, :read_merge_request, @project) + = link_to 'Browse Merge Requests', namespace_project_merge_requests_path(@milestone.project.namespace, @milestone.project, milestone_title: @milestone.title), class: "btn btn-grouped" + + .oneline + All merge requests in this milestone + + .row.prepend-top-default .col-md-3 = render('merge_requests', title: 'Work in progress (open and unassigned)', merge_requests: @merge_requests.opened.unassigned, id: 'unassigned') .col-md-3 @@ -100,6 +115,10 @@ = render 'merge_request', merge_request: merge_request .tab-pane#tab-participants + .gray-content-block.middle-block + .oneline + All participants to this milestone + %ul.bordered-list - @users.each do |user| %li diff --git a/app/views/projects/network/_head.html.haml b/app/views/projects/network/_head.html.haml index 415c98ec6a..28a617538b 100644 --- a/app/views/projects/network/_head.html.haml +++ b/app/views/projects/network/_head.html.haml @@ -1,3 +1,6 @@ -.append-bottom-20 - = render partial: 'shared/ref_switcher', locals: {destination: 'graph'} - .pull-right.visible-lg.light You can move around the graph by using the arrow keys. +.gray-content-block.append-bottom-default + .tree-ref-holder + = render partial: 'shared/ref_switcher', locals: {destination: 'graph'} + + .oneline + You can move around the graph by using the arrow keys. diff --git a/app/views/projects/network/show.html.haml b/app/views/projects/network/show.html.haml index 16005161df..8065663ca2 100644 --- a/app/views/projects/network/show.html.haml +++ b/app/views/projects/network/show.html.haml @@ -1,5 +1,6 @@ - page_title "Network", @ref -= header_title project_title(@project, "Network", namespace_project_network_path(@project.namespace, @project, current_ref)) += render "projects/commits/header_title" += render "projects/commits/head" = render "head" .project-network .controls diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index c9d1fc3da2..2523311213 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -1,5 +1,10 @@ - page_title 'New Project' -- header_title 'New Project' +- header_title "Projects", root_path + +%h3.page-title + New Project +%hr + .project-edit-container .project-edit-errors = render 'projects/errors' @@ -11,16 +16,21 @@ Project path .col-sm-10 .input-group - = f.text_field :path, placeholder: "my-awesome-project", class: "form-control", tabindex: 1, autofocus: true, required: true - .input-group-addon - \.git + - if current_user.can_select_namespace? + .input-group-addon + = root_url + = f.select :namespace_id, namespaces_options(params[:namespace_id] || :current_user, display_path: true), {}, {class: 'select2', tabindex: 1} + .input-group-addon + \/ + - else + .input-group-addon + #{root_url}#{current_user.username}/ + = f.text_field :path, placeholder: "my-awesome-project", class: "form-control", tabindex: 2, autofocus: true, required: true - - if current_user.can_select_namespace? - .form-group - = f.label :namespace_id, class: 'control-label' do - %span Namespace - .col-sm-10 - = f.select :namespace_id, namespaces_options(params[:namespace_id] || :current_user), {}, {class: 'select2', tabindex: 2} + - if current_user.can_create_group? + .help-block + Want to house several dependent projects under the same namespace? + = link_to "Create a group", new_group_path - if import_sources_enabled? .project-import.js-toggle-container @@ -90,19 +100,12 @@ Description %span.light (optional) .col-sm-10 - = f.text_area :description, placeholder: "Awesome project", class: "form-control", rows: 3, maxlength: 250, tabindex: 3 + = f.text_area :description, class: "form-control", rows: 3, maxlength: 250, tabindex: 3 = render 'shared/visibility_level', f: f, visibility_level: default_project_visibility, can_change_visibility_level: true, form_model: @project .form-actions = f.submit 'Create project', class: "btn btn-create project-submit", tabindex: 4 - - - if current_user.can_create_group? - .pull-right - .light.inline - .space-right - Need a group for several dependent projects? - = link_to new_group_path, class: "btn" do - Create a group + = link_to 'Cancel', dashboard_projects_path, class: 'btn btn-cancel' .save-project-loader.hide .center diff --git a/app/views/projects/notes/_edit_form.html.haml b/app/views/projects/notes/_edit_form.html.haml index a21c019986..3ccda1b381 100644 --- a/app/views/projects/notes/_edit_form.html.haml +++ b/app/views/projects/notes/_edit_form.html.haml @@ -6,6 +6,5 @@ = render 'projects/notes/hints' .note-form-actions - .buttons - = f.submit 'Save Comment', class: 'btn btn-primary btn-save btn-grouped js-comment-button' - = link_to 'Cancel', '#', class: 'btn btn-cancel note-edit-cancel' + = f.submit 'Save Comment', class: 'btn btn-primary btn-save btn-grouped js-comment-button' + = link_to 'Cancel', '#', class: 'btn btn-cancel note-edit-cancel' diff --git a/app/views/projects/notes/_form.html.haml b/app/views/projects/notes/_form.html.haml index 5dd84317e3..88e711ab53 100644 --- a/app/views/projects/notes/_form.html.haml +++ b/app/views/projects/notes/_form.html.haml @@ -12,8 +12,7 @@ = render 'projects/notes/hints' .error-alert - .note-form-actions - .buttons.clearfix - = f.submit 'Add Comment', class: "btn btn-green comment-btn btn-grouped js-comment-button" - = yield(:note_actions) - %a.btn.grouped.js-close-discussion-note-form Cancel + .note-form-actions.clearfix + = f.submit 'Add Comment', class: "btn btn-create comment-btn btn-grouped js-comment-button" + = yield(:note_actions) + %a.btn.btn-cancel.js-close-discussion-note-form Cancel diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml index dd0abc8c74..922535e5c4 100644 --- a/app/views/projects/notes/_note.html.haml +++ b/app/views/projects/notes/_note.html.haml @@ -38,7 +38,7 @@ .note-body{class: note_editable?(note) ? 'js-task-list-container' : ''} .note-text = preserve do - = markdown(note.note, {no_header_anchors: true}) + = markdown(note.note, pipeline: :note, cache_key: [note, "note"]) - if note_editable?(note) = render 'projects/notes/edit_form', note: note diff --git a/app/views/projects/notes/_notes_with_form.html.haml b/app/views/projects/notes/_notes_with_form.html.haml index 99c1b0fa43..eb378b4260 100644 --- a/app/views/projects/notes/_notes_with_form.html.haml +++ b/app/views/projects/notes/_notes_with_form.html.haml @@ -7,4 +7,4 @@ = render "projects/notes/form", view: diff_view :javascript - new Notes("#{namespace_project_notes_path(namespace_id: @project.namespace, target_id: @noteable.id, target_type: @noteable.class.name.underscore)}", #{@notes.map(&:id).to_json}, #{Time.now.to_i}, "#{diff_view}") + var notes = new Notes("#{namespace_project_notes_path(namespace_id: @project.namespace, target_id: @noteable.id, target_type: @noteable.class.name.underscore)}", #{@notes.map(&:id).to_json}, #{Time.now.to_i}, "#{diff_view}") diff --git a/app/views/projects/project_members/_group_members.html.haml b/app/views/projects/project_members/_group_members.html.haml index 43e92437cf..1c2458fa14 100644 --- a/app/views/projects/project_members/_group_members.html.haml +++ b/app/views/projects/project_members/_group_members.html.haml @@ -4,12 +4,13 @@ group members %small (#{members.count}) - .panel-head-actions - = link_to group_group_members_path(@group), class: 'btn btn-sm' do - %i.fa.fa-pencil-square-o - Edit group members - %ul.well-list - - members.each do |member| + - if can?(current_user, :admin_group_member, @group) + .pull-right + = link_to group_group_members_path(@group), class: 'btn' do + = icon('pencil-square-o') + Manage group members + %ul.content-list + - members.limit(20).each do |member| = render 'groups/group_members/group_member', member: member, show_controls: false - if members.count > 20 %li diff --git a/app/views/projects/project_members/_project_member.html.haml b/app/views/projects/project_members/_project_member.html.haml index f07cd97e63..05bf3a7ef6 100644 --- a/app/views/projects/project_members/_project_member.html.haml +++ b/app/views/projects/project_members/_project_member.html.haml @@ -4,7 +4,7 @@ %li{class: "#{dom_class(member)} js-toggle-container project_member_row access-#{member.human_access.downcase}", id: dom_id(member)} %span.list-item-name - if member.user - = image_tag avatar_icon(user, 16), class: "avatar s16", alt: '' + = image_tag avatar_icon(user, 24), class: "avatar s24", alt: '' %strong = link_to user.name, user_path(user) %span.cgray= user.username @@ -14,7 +14,7 @@ %label.label.label-danger %strong Blocked - else - = image_tag avatar_icon(member.invite_email, 16), class: "avatar s16", alt: '' + = image_tag avatar_icon(member.invite_email, 24), class: "avatar s24", alt: '' %strong = member.invite_email %span.cgray diff --git a/app/views/projects/project_members/_team.html.haml b/app/views/projects/project_members/_team.html.haml index b807fb2cc9..ccddab13aa 100644 --- a/app/views/projects/project_members/_team.html.haml +++ b/app/views/projects/project_members/_team.html.haml @@ -1,9 +1,21 @@ -.panel.panel-default.prepend-top-20 +.panel.panel-default .panel-heading %strong #{@project.name} project members %small (#{members.count}) - %ul.well-list + .pull-right + = form_tag namespace_project_project_members_path(@project.namespace, @project), method: :get, class: 'form-inline member-search-form' do + .form-group + = search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control', spellcheck: false } + = button_tag class: 'btn', title: 'Search' do + = icon("search") + %ul.content-list - members.each do |project_member| = render 'project_member', member: project_member + +:javascript + $('form.member-search-form').on('submit', function (event) { + event.preventDefault(); + Turbolinks.visit(this.action + '?' + $(this).serialize()); + }); diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml index 9fc4be583c..29225a3636 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -1,36 +1,21 @@ - page_title "Members" = render "header_title" +- @blank_container = true -.gray-content-block.top-block - .clearfix.js-toggle-container - = form_tag namespace_project_project_members_path(@project.namespace, @project), method: :get, class: 'form-inline member-search-form' do - .form-group - = search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control search-text-input', spellcheck: false } - = button_tag 'Search', class: 'btn' - - - if can?(current_user, :admin_project_member, @project) - %span.pull-right - = button_tag class: 'btn btn-new btn-grouped js-toggle-button', type: 'button' do - Add members - %i.fa.fa-chevron-down - = link_to import_namespace_project_project_members_path(@project.namespace, @project), class: "btn btn-grouped", title: "Import members from another project" do - Import members - - .js-toggle-content.hide.new-group-member-holder +.project-members-page + - if can?(current_user, :admin_project_member, @project) + .panel.panel-default + .panel-heading + Add new user to project + .pull-right + = link_to import_namespace_project_project_members_path(@project.namespace, @project), class: "btn btn-grouped", title: "Import members from another project" do + Import members + .panel-body + %p.light + Users with access to this project are listed below. = render "new_project_member" -%p.prepend-top-default.light - Users with access to this project are listed below. - Read more about project permissions - %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink" + = render "team", members: @project_members -= render "team", members: @project_members - -- if @group - = render "group_members", members: @group_members - -:javascript - $('form.member-search-form').on('submit', function (event) { - event.preventDefault(); - Turbolinks.visit(this.action + '?' + $(this).serialize()); - }); + - if @group + = render "group_members", members: @group_members diff --git a/app/views/projects/protected_branches/index.html.haml b/app/views/projects/protected_branches/index.html.haml index 52b3a50c1e..cfd7e1534c 100644 --- a/app/views/projects/protected_branches/index.html.haml +++ b/app/views/projects/protected_branches/index.html.haml @@ -3,7 +3,7 @@ %p.light Keep stable branches secure and force developers to use Merge Requests %hr -.well.append-bottom-20 +.well %p Protected branches are designed to %ul %li prevent pushes from everybody except #{link_to "masters", help_page_path("permissions", "permissions"), class: "vlink"} @@ -22,7 +22,7 @@ .form-group = f.label :name, "Branch", class: 'control-label' .col-sm-10 - = f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , {include_blank: "Select branch"}, {class: "select2"}) + = f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , {include_blank: true}, {class: "select2", data: {placeholder: "Select branch"}}) .form-group .col-sm-offset-2.col-sm-10 .checkbox @@ -33,4 +33,3 @@ .form-actions = f.submit 'Protect', class: "btn-create btn" = render 'branches_list' - diff --git a/app/views/projects/releases/edit.html.haml b/app/views/projects/releases/edit.html.haml index f516b65ecd..bc80f2f29a 100644 --- a/app/views/projects/releases/edit.html.haml +++ b/app/views/projects/releases/edit.html.haml @@ -14,6 +14,6 @@ = render 'projects/zen', f: f, attr: :description, classes: 'description js-quick-submit form-control' = render 'projects/notes/hints' .error-alert - .prepend-top-default + .form-actions.prepend-top-default = f.submit 'Save changes', class: 'btn btn-save' = link_to "Cancel", namespace_project_tag_path(@project.namespace, @project, @tag.name), class: "btn btn-default btn-cancel" diff --git a/app/views/projects/repositories/_download_archive.html.haml b/app/views/projects/repositories/_download_archive.html.haml index 07c24950ee..b9486a9b49 100644 --- a/app/views/projects/repositories/_download_archive.html.haml +++ b/app/views/projects/repositories/_download_archive.html.haml @@ -3,10 +3,10 @@ - split_button = split_button || false - if split_button == true %span.btn-group{class: btn_class} - = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'zip'), class: 'btn btn-success col-xs-10', rel: 'nofollow' do + = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'zip'), class: 'btn col-xs-10', rel: 'nofollow' do %i.fa.fa-download %span Download zip - %a.col-xs-2.btn.btn-success.dropdown-toggle{ 'data-toggle' => 'dropdown' } + %a.col-xs-2.btn.dropdown-toggle{ 'data-toggle' => 'dropdown' } %span.caret %span.sr-only Select Archive Format diff --git a/app/views/projects/repositories/_feed.html.haml b/app/views/projects/repositories/_feed.html.haml index f3526ad074..6ca919f7f8 100644 --- a/app/views/projects/repositories/_feed.html.haml +++ b/app/views/projects/repositories/_feed.html.haml @@ -12,7 +12,7 @@ = link_to namespace_project_commits_path(@project.namespace, @project, commit.id) do %code= commit.short_id = image_tag avatar_icon(commit.author_email), class: "", width: 16, alt: '' - = gfm escape_once(truncate(commit.title, length: 40)) + = markdown escape_once(truncate(commit.title, length: 40)), pipeline: :single_line %td %span.pull-right.cgray = time_ago_with_tooltip(commit.committed_date) diff --git a/app/views/projects/runners/_runner.html.haml b/app/views/projects/runners/_runner.html.haml index e6b8a2e6fe..47ec420189 100644 --- a/app/views/projects/runners/_runner.html.haml +++ b/app/views/projects/runners/_runner.html.haml @@ -15,10 +15,10 @@ - if runner.belongs_to_one_project? = link_to 'Remove runner', runner_path(runner), data: { confirm: "Are you sure?" }, method: :delete, class: 'btn btn-danger btn-sm' - else - - runner_project = @ci_project.runner_projects.find_by(runner_id: runner) - = link_to 'Disable for this project', [:ci, @ci_project, runner_project], data: { confirm: "Are you sure?" }, method: :delete, class: 'btn btn-danger btn-sm' + - runner_project = @project.runner_projects.find_by(runner_id: runner) + = link_to 'Disable for this project', namespace_project_runner_project_path(@project.namespace, @project, runner_project), data: { confirm: "Are you sure?" }, method: :delete, class: 'btn btn-danger btn-sm' - elsif runner.specific? - = form_for [:ci, @ci_project, @ci_project.runner_projects.new] do |f| + = form_for [@project.namespace.becomes(Namespace), @project, @project.runner_projects.new] do |f| = f.hidden_field :runner_id, value: runner.id = f.submit 'Enable for this project', class: 'btn btn-sm' .pull-right diff --git a/app/views/projects/runners/_shared_runners.html.haml b/app/views/projects/runners/_shared_runners.html.haml index 316ea747b1..6a37f444bb 100644 --- a/app/views/projects/runners/_shared_runners.html.haml +++ b/app/views/projects/runners/_shared_runners.html.haml @@ -3,17 +3,17 @@ .bs-callout.bs-callout-warning GitLab Runners do not offer secure isolation between projects that they do builds for. You are TRUSTING all GitLab users who can push code to project A, B or C to run shell scripts on the machine hosting runner X. %hr - - if @ci_project.shared_runners_enabled - = link_to toggle_shared_runners_ci_project_path(@ci_project), class: 'btn btn-warning', method: :post do + - if @project.shared_runners_enabled? + = link_to toggle_shared_runners_namespace_project_runners_path(@project.namespace, @project), class: 'btn btn-warning', method: :post do Disable shared runners - else - = link_to toggle_shared_runners_ci_project_path(@ci_project), class: 'btn btn-success', method: :post do + = link_to toggle_shared_runners_namespace_project_runners_path(@project.namespace, @project), class: 'btn btn-success', method: :post do Enable shared runners   for this project - if @shared_runners_count.zero? - This application has no shared runners yet. - Please use specific runners or ask administrator to create one + This GitLab server does not provide any shared runners yet. + Please use specific runners or ask the administrator to create one. - else %h4.underlined-title Available shared runners - #{@shared_runners_count} %ul.bordered-list.available-shared-runners diff --git a/app/views/projects/runners/_specific_runners.html.haml b/app/views/projects/runners/_specific_runners.html.haml index c13625c7e4..30cd1263a1 100644 --- a/app/views/projects/runners/_specific_runners.html.haml +++ b/app/views/projects/runners/_specific_runners.html.haml @@ -12,7 +12,7 @@ %code #{ci_root_url(only_path: false)} %li Use the following registration token during setup: - %code #{@ci_project.token} + %code #{@project.runners_token} %li Start runner! diff --git a/app/views/projects/runners/edit.html.haml b/app/views/projects/runners/edit.html.haml index dde9e448cb..eba03028af 100644 --- a/app/views/projects/runners/edit.html.haml +++ b/app/views/projects/runners/edit.html.haml @@ -23,7 +23,7 @@ = label_tag :tag_list, class: 'control-label' do Tags .col-sm-10 - = f.text_field :tag_list, class: 'form-control' + = f.text_field :tag_list, value: @runner.tag_list.to_s, class: 'form-control' .help-block You can setup jobs to only use runners with specific tags .form-actions - = f.submit 'Save', class: 'btn btn-save' + = f.submit 'Save changes', class: 'btn btn-save' diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml index e1823b5119..1b70880043 100644 --- a/app/views/projects/services/_form.html.haml +++ b/app/views/projects/services/_form.html.haml @@ -4,18 +4,15 @@ %p= @service.description -.back-link - = link_to namespace_project_services_path(@project.namespace, @project) do - ← to services - %hr = form_for(@service, as: :service, url: namespace_project_service_path(@project.namespace, @project, @service.to_param), method: :put, html: { class: 'form-horizontal' }) do |form| = render 'shared/service_settings', form: form .form-actions - = form.submit 'Save', class: 'btn btn-save' + = form.submit 'Save changes', class: 'btn btn-save'   - if @service.valid? && @service.activated? - disabled = @service.can_test? ? '':'disabled' = link_to 'Test settings', test_namespace_project_service_path(@project.namespace, @project, @service.to_param), class: "btn #{disabled}" + = link_to "Cancel", namespace_project_services_path(@project.namespace, @project), class: "btn btn-cancel" diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index 585caf674c..9c7a5584da 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -11,7 +11,7 @@ = render "home_panel" -.project-stats.gray-content-block +.project-stats.gray-content-block.second-block %ul.nav.nav-pills %li = link_to namespace_project_commits_path(@project.namespace, @project, current_ref) do diff --git a/app/views/projects/snippets/edit.html.haml b/app/views/projects/snippets/edit.html.haml index e69f2d9970..dc3ea1fcf1 100644 --- a/app/views/projects/snippets/edit.html.haml +++ b/app/views/projects/snippets/edit.html.haml @@ -2,6 +2,6 @@ = render "header_title" %h3.page-title - Edit snippet + Edit Snippet %hr = render "shared/snippets/form", url: namespace_project_snippet_path(@project.namespace, @project, @snippet), visibility_level: @snippet.visibility_level diff --git a/app/views/projects/snippets/new.html.haml b/app/views/projects/snippets/new.html.haml index 67cd69fd21..e57237991b 100644 --- a/app/views/projects/snippets/new.html.haml +++ b/app/views/projects/snippets/new.html.haml @@ -2,6 +2,6 @@ = render "header_title" %h3.page-title - New snippet + New Snippet %hr = render "shared/snippets/form", url: namespace_project_snippets_path(@project.namespace, @project, @snippet), visibility_level: default_snippet_visibility diff --git a/app/views/projects/snippets/show.html.haml b/app/views/projects/snippets/show.html.haml index 5d706942f2..7c599563ce 100644 --- a/app/views/projects/snippets/show.html.haml +++ b/app/views/projects/snippets/show.html.haml @@ -10,8 +10,8 @@ %strong = @snippet.file_name .file-actions.hidden-xs - .btn-group.tree-btn-group - = link_to 'Raw', raw_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-sm", target: "_blank" + = clipboard_button(clipboard_target: ".blob-content[data-blob-id='#{@snippet.id}']") + = link_to 'Raw', raw_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-sm", target: "_blank" = render 'shared/snippets/blob' diff --git a/app/views/projects/tags/_tag.html.haml b/app/views/projects/tags/_tag.html.haml index e2c5178185..28b706c5c7 100644 --- a/app/views/projects/tags/_tag.html.haml +++ b/app/views/projects/tags/_tag.html.haml @@ -11,11 +11,17 @@ = strip_gpg_signature(tag.message) .controls - = link_to edit_namespace_project_tag_release_path(@project.namespace, @project, tag.name), class: 'btn-grouped btn' do - = icon("pencil") - - if can? current_user, :download_code, @project + - if can?(current_user, :download_code, @project) = render 'projects/tags/download', ref: tag.name, project: @project + - if can?(current_user, :push_code, @project) + = link_to edit_namespace_project_tag_release_path(@project.namespace, @project, tag.name), class: 'btn-grouped btn has_tooltip', title: "Edit release notes" do + = icon("pencil") + + - if can?(current_user, :admin_project, @project) + = link_to namespace_project_tag_path(@project.namespace, @project, tag.name), class: 'btn btn-grouped btn-xs btn-remove remove-row has_tooltip', title: "Delete tag", method: :delete, data: { confirm: "Deleting the '#{tag.name}' tag cannot be undone. Are you sure?", container: 'body' }, remote: true do + = icon("trash-o") + - if commit = render 'projects/branches/commit', commit: commit, project: @project - else diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml index 85d76eae3b..760347de0a 100644 --- a/app/views/projects/tags/index.html.haml +++ b/app/views/projects/tags/index.html.haml @@ -6,7 +6,7 @@ - if can? current_user, :push_code, @project .pull-right = link_to new_namespace_project_tag_path(@project.namespace, @project), class: 'btn btn-create new-tag-btn' do - %i.fa.fa-add-sign + = icon('plus') New tag .oneline Tags give the ability to mark specific points in history as being important diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml index 86aa15dc5b..3a2f75feca 100644 --- a/app/views/projects/tags/new.html.haml +++ b/app/views/projects/tags/new.html.haml @@ -7,24 +7,24 @@ = @error %h3.page-title - New git tag + New Tag %hr -= form_tag namespace_project_tags_path, method: :post, id: "new-tag-form", class: "form-horizontal gfm-form tag-form" do += form_tag namespace_project_tags_path, method: :post, id: "new-tag-form", class: "form-horizontal gfm-form tag-form js-requires-input" do .form-group - = label_tag :tag_name, 'Name for new tag', class: 'control-label' + = label_tag :tag_name, nil, class: 'control-label' .col-sm-10 - = text_field_tag :tag_name, params[:tag_name], placeholder: 'v3.0.1', required: true, tabindex: 1, class: 'form-control' + = text_field_tag :tag_name, params[:tag_name], required: true, tabindex: 1, autofocus: true, class: 'form-control' .form-group = label_tag :ref, 'Create from', class: 'control-label' .col-sm-10 - = text_field_tag :ref, params[:ref], placeholder: 'master', required: true, tabindex: 2, class: 'form-control' + = text_field_tag :ref, params[:ref] || @project.default_branch, required: true, tabindex: 2, class: 'form-control' .help-block Branch name or commit SHA .form-group - = label_tag :message, 'Message', class: 'control-label' + = label_tag :message, nil, class: 'control-label' .col-sm-10 - = text_field_tag :message, nil, placeholder: 'Enter message.', required: false, tabindex: 3, class: 'form-control' - .help-block (Optional) Entering a message will create an annotated tag. + = text_field_tag :message, nil, required: false, tabindex: 3, class: 'form-control' + .help-block Optionally, enter a message to create an annotated tag. %hr .form-group = label_tag :release_description, 'Release notes', class: 'control-label' @@ -32,16 +32,15 @@ = render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do = render 'projects/zen', attr: :release_description, classes: 'description js-quick-submit form-control' = render 'projects/notes/hints' - .help-block (Optional) You can add release notes to your tag. It will be stored in the GitLab database and shown on the tags page + .help-block Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page. .form-actions = button_tag 'Create tag', class: 'btn btn-create', tabindex: 3 = link_to 'Cancel', namespace_project_tags_path(@project.namespace, @project), class: 'btn btn-cancel' :javascript - disableButtonIfAnyEmptyField($("#new-tag-form"), ".form-control", ".btn-create"); - var availableTags = #{@project.repository.ref_names.to_json}; + var availableRefs = #{@project.repository.ref_names.to_json}; $("#ref").autocomplete({ - source: availableTags, + source: availableRefs, minLength: 1 }); diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml index ebe3718afc..b594d4f1f2 100644 --- a/app/views/projects/tags/show.html.haml +++ b/app/views/projects/tags/show.html.haml @@ -5,17 +5,17 @@ .gray-content-block .pull-right - if can?(current_user, :push_code, @project) - = link_to edit_namespace_project_tag_release_path(@project.namespace, @project, @tag.name), class: 'btn-grouped btn', title: 'Edit release notes' do + = link_to edit_namespace_project_tag_release_path(@project.namespace, @project, @tag.name), class: 'btn-grouped btn has_tooltip', title: 'Edit release notes' do = icon("pencil") - = link_to namespace_project_tree_path(@project.namespace, @project, @tag.name), class: 'btn btn-grouped', title: 'Browse source code' do + = link_to namespace_project_tree_path(@project.namespace, @project, @tag.name), class: 'btn btn-grouped has_tooltip', title: 'Browse files' do = icon('files-o') - = link_to namespace_project_commits_path(@project.namespace, @project, @tag.name), class: 'btn btn-grouped', title: 'Browse commits' do + = link_to namespace_project_commits_path(@project.namespace, @project, @tag.name), class: 'btn btn-grouped has_tooltip', title: 'Browse commits' do = icon('history') - if can? current_user, :download_code, @project = render 'projects/tags/download', ref: @tag.name, project: @project - if can?(current_user, :admin_project, @project) .pull-right - = link_to namespace_project_tag_path(@project.namespace, @project, @tag.name), class: 'btn btn-remove remove-row grouped', method: :delete, data: { confirm: 'Removed tag cannot be restored. Are you sure?'} do + = link_to namespace_project_tag_path(@project.namespace, @project, @tag.name), class: 'btn btn-remove remove-row grouped has_tooltip', title: "Delete tag", method: :delete, data: { confirm: "Deleting the '#{@tag.name}' tag cannot be undone. Are you sure?" } do %i.fa.fa-trash-o .title %strong= @tag.name diff --git a/app/views/projects/tree/_tree_content.html.haml b/app/views/projects/tree/_tree_content.html.haml index c64e684df2..1bc90edd8f 100644 --- a/app/views/projects/tree/_tree_content.html.haml +++ b/app/views/projects/tree/_tree_content.html.haml @@ -12,7 +12,7 @@ %i.fa.fa-angle-right   %small.light - = link_to @commit.short_id, namespace_project_commit_path(@project.namespace, @project, @commit) + = link_to @commit.short_id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace" – = truncate(@commit.title, length: 50) = link_to 'History', namespace_project_commits_path(@project.namespace, @project, @id), class: 'pull-right' diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml index 1115ca6b4c..89b072cea9 100644 --- a/app/views/projects/tree/_tree_header.html.haml +++ b/app/views/projects/tree/_tree_header.html.haml @@ -14,19 +14,31 @@ - if allowed_tree_edit? %li %span.dropdown - %a.dropdown-toggle.btn.add-to-tree{href: '#', "data-toggle" => "dropdown"} + %a.dropdown-toggle.btn.btn-sm.add-to-tree{href: '#', "data-toggle" => "dropdown"} = icon('plus') %ul.dropdown-menu %li = link_to namespace_project_new_blob_path(@project.namespace, @project, @id), title: 'Create file', id: 'new-file-link' do = icon('pencil fw') - Create file + New file %li = link_to '#modal-upload-blob', { 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal'} do = icon('file fw') Upload file - %li.divider %li = link_to '#modal-create-new-dir', { 'data-target' => '#modal-create-new-dir', 'data-toggle' => 'modal'} do = icon('folder fw') New directory + %li.divider + %li + = link_to new_namespace_project_branch_path(@project.namespace, @project) do + = icon('code-fork fw') + New branch + %li + = link_to new_namespace_project_tag_path(@project.namespace, @project) do + = icon('tags fw') + New tag + - elsif !on_top_of_branch? + %li + %span.btn.btn-sm.add-to-tree.disabled.has_tooltip{title: "You can only add files when you are on a branch.", data: {container: 'body'}} + = icon('plus') diff --git a/app/views/projects/triggers/index.html.haml b/app/views/projects/triggers/index.html.haml index b3ad79a200..bd346c4b8e 100644 --- a/app/views/projects/triggers/index.html.haml +++ b/app/views/projects/triggers/index.html.haml @@ -36,7 +36,8 @@ :plain curl -X POST \ -F token=TOKEN \ - #{ci_build_trigger_url(@ci_project.id, 'REF_NAME')} + -F ref=REF_NAME \ + #{builds_trigger_url(@project.id)} %h3 Use .gitlab-ci.yml @@ -51,7 +52,7 @@ trigger: type: deploy script: - - "curl -X POST -F token=TOKEN #{ci_build_trigger_url(@ci_project.id, 'REF_NAME')}" + - "curl -X POST -F token=TOKEN -F ref=REF_NAME #{builds_trigger_url(@project.id)}" %h3 Pass build variables @@ -65,5 +66,6 @@ :plain curl -X POST \ -F token=TOKEN \ + -F "ref=REF_NAME" \ -F "variables[RUN_NIGHTLY_BUILD]=true" \ - #{ci_build_trigger_url(@ci_project.id, 'REF_NAME')} + #{builds_trigger_url(@project.id)} diff --git a/app/views/projects/variables/show.html.haml b/app/views/projects/variables/show.html.haml index e052da1ac4..e80dffc1ce 100644 --- a/app/views/projects/variables/show.html.haml +++ b/app/views/projects/variables/show.html.haml @@ -10,13 +10,13 @@ %hr -= nested_form_for @ci_project, url: url_for(controller: 'projects/variables', action: 'update'), html: { class: 'form-horizontal' } do |f| += nested_form_for @project, url: url_for(controller: 'projects/variables', action: 'update'), html: { class: 'form-horizontal' } do |f| - if @project.errors.any? #error_explanation - %p.lead= "#{pluralize(@ci_project.errors.count, "error")} prohibited this project from being saved:" + %p.lead= "#{pluralize(@project.errors.count, "error")} prohibited this project from being saved:" .alert.alert-error %ul - - @ci_project.errors.full_messages.each do |msg| + - @project.errors.full_messages.each do |msg| %li= msg = f.fields_for :variables do |variable_form| diff --git a/app/views/projects/wikis/_form.html.haml b/app/views/projects/wikis/_form.html.haml index 9c94c43e74..1d257818dc 100644 --- a/app/views/projects/wikis/_form.html.haml +++ b/app/views/projects/wikis/_form.html.haml @@ -1,4 +1,4 @@ -= form_for [@project.namespace.becomes(Namespace), @project, @page], method: @page.persisted? ? :put : :post, html: { class: 'form-horizontal wiki-form gfm-form' } do |f| += form_for [@project.namespace.becomes(Namespace), @project, @page], method: @page.persisted? ? :put : :post, html: { class: 'form-horizontal wiki-form gfm-form prepend-top-default' } do |f| -if @page.errors.any? #error_explanation .alert.alert-danger @@ -11,14 +11,7 @@ .col-sm-10 = f.select :format, options_for_select(ProjectWiki::MARKUPS, {selected: @page.format}), {}, class: "form-control" - .row - .col-sm-offset-2.col-sm-10 - %p.cgray - To link to a (new) page you can just type - %code [Link Title](page-slug) - \. - - .form-group.wiki-content + .form-group = f.label :content, class: 'control-label' .col-sm-10 = render layout: 'projects/md_preview', locals: { preview_class: "md-preview" } do @@ -27,6 +20,11 @@ .clearfix .error-alert + + .help-block + To link to a (new) page, simply type + %code [Link Title](page-slug) + \. .form-group = f.label :commit_message, class: 'control-label' .col-sm-10= f.text_field :message, class: 'form-control', rows: 18 diff --git a/app/views/projects/wikis/_main_links.html.haml b/app/views/projects/wikis/_main_links.html.haml index 14f2582225..29bf5d62ab 100644 --- a/app/views/projects/wikis/_main_links.html.haml +++ b/app/views/projects/wikis/_main_links.html.haml @@ -1,9 +1,4 @@ %span.pull-right - - if can?(current_user, :create_wiki, @project) - = link_to '#modal-new-wiki', class: "add-new-wiki btn btn-new btn-grouped", "data-toggle" => "modal" do - %i.fa.fa-plus - New Page - - if (@page && @page.persisted?) = link_to namespace_project_wiki_history_path(@project.namespace, @project, @page), class: "btn btn-grouped" do Page History @@ -11,5 +6,7 @@ = link_to namespace_project_wiki_edit_path(@project.namespace, @project, @page), class: "btn btn-grouped" do %i.fa.fa-pencil-square-o Edit - -= render 'projects/wikis/new' + - if can?(current_user, :admin_wiki, @project) + = link_to namespace_project_wiki_path(@project.namespace, @project, @page), data: { confirm: "Are you sure you want to delete this page?"}, method: :delete, class: "btn btn-remove" do + = icon('trash') + Delete diff --git a/app/views/projects/wikis/_nav.html.haml b/app/views/projects/wikis/_nav.html.haml index fffb4eb31a..e6e6ad5bc4 100644 --- a/app/views/projects/wikis/_nav.html.haml +++ b/app/views/projects/wikis/_nav.html.haml @@ -1,10 +1,19 @@ -%ul.center-top-menu - = nav_link(html_options: {class: params[:id] == 'home' ? 'active' : '' }) do - = link_to 'Home', namespace_project_wiki_path(@project.namespace, @project, :home) +.project-issuable-filter + .controls + - if can?(current_user, :create_wiki, @project) + = link_to '#modal-new-wiki', class: "add-new-wiki btn btn-new", "data-toggle" => "modal" do + %i.fa.fa-plus + New Page - = nav_link(path: 'wikis#pages') do - = link_to 'Pages', namespace_project_wiki_pages_path(@project.namespace, @project) + = render 'projects/wikis/new' - = nav_link(path: 'wikis#git_access') do - = link_to namespace_project_wikis_git_access_path(@project.namespace, @project) do - Git Access + %ul.center-top-menu + = nav_link(html_options: {class: params[:id] == 'home' ? 'active' : '' }) do + = link_to 'Home', namespace_project_wiki_path(@project.namespace, @project, :home) + + = nav_link(path: 'wikis#pages') do + = link_to 'Pages', namespace_project_wiki_pages_path(@project.namespace, @project) + + = nav_link(path: 'wikis#git_access') do + = link_to namespace_project_wikis_git_access_path(@project.namespace, @project) do + Git Access diff --git a/app/views/projects/wikis/_new.html.haml b/app/views/projects/wikis/_new.html.haml index dace172438..f0547e9c05 100644 --- a/app/views/projects/wikis/_new.html.haml +++ b/app/views/projects/wikis/_new.html.haml @@ -12,5 +12,5 @@ The page slug is invalid. Please don't use characters other then: a-z 0-9 _ - and / %p.hint Please don't use spaces. - .modal-footer - = link_to 'Build', '#', class: 'build-new-wiki btn btn-create' + .form-actions + = link_to 'Create Page', '#', class: 'build-new-wiki btn btn-create' diff --git a/app/views/projects/wikis/edit.html.haml b/app/views/projects/wikis/edit.html.haml index 0b709c3695..23f64fbbd1 100644 --- a/app/views/projects/wikis/edit.html.haml +++ b/app/views/projects/wikis/edit.html.haml @@ -1,16 +1,16 @@ -- page_title "Edit", @page.title, "Wiki" +- page_title "Edit", @page.title.capitalize, "Wiki" = render "header_title" = render 'nav' -.pull-right - = render 'main_links' -%h3.page-title - Editing - - %span.light #{@page.title} -%hr -= render 'form' +.gray-content-block + .pull-right + = render 'main_links' -.pull-right - - if @page.persisted? && can?(current_user, :admin_wiki, @project) - = link_to namespace_project_wiki_path(@project.namespace, @project, @page), data: { confirm: "Are you sure you want to delete this page?"}, method: :delete, class: "btn btn-sm btn-remove" do - Delete this page + %h3.page-title.oneline + %span.light Edit Page + - if @page.persisted? + = link_to @page.title, namespace_project_wiki_path(@project.namespace, @project, @page) + - else + = @page.title + += render 'form' diff --git a/app/views/projects/wikis/git_access.html.haml b/app/views/projects/wikis/git_access.html.haml index 6417ef4a38..11c8c4f0eb 100644 --- a/app/views/projects/wikis/git_access.html.haml +++ b/app/views/projects/wikis/git_access.html.haml @@ -5,7 +5,7 @@ .gray-content-block .row .col-sm-6 - %h3.page-title + %h3.page-title.oneline Git access for %strong= @project_wiki.path_with_namespace diff --git a/app/views/projects/wikis/pages.html.haml b/app/views/projects/wikis/pages.html.haml index d179a1abec..aae1ad69ad 100644 --- a/app/views/projects/wikis/pages.html.haml +++ b/app/views/projects/wikis/pages.html.haml @@ -1,11 +1,10 @@ -- page_title "All Pages", "Wiki" +- page_title "Pages", "Wiki" = render "header_title" = render 'nav' .gray-content-block - = render 'main_links' - %h3.page-title - All Pages + All pages in this wiki are listed below. + %ul.content-list - @wiki_pages.each do |wiki_page| %li diff --git a/app/views/projects/wikis/show.html.haml b/app/views/projects/wikis/show.html.haml index 55fbf5a8b6..309d40f52b 100644 --- a/app/views/projects/wikis/show.html.haml +++ b/app/views/projects/wikis/show.html.haml @@ -5,11 +5,12 @@ .gray-content-block = render 'main_links' - %h3.page-title + %h3.page-title.oneline = @page.title.capitalize - .wiki-last-edit-by - Last edited by #{@page.commit.author.name} #{time_ago_with_tooltip(@page.commit.authored_date)} + %span.wiki-last-edit-by + · + last edited by #{@page.commit.author.name} #{time_ago_with_tooltip(@page.commit.authored_date)} - if @page.historical? .warning_message @@ -21,8 +22,3 @@ .wiki = preserve do = render_wiki_content(@page) - -.gray-content-block.footer-block - .wiki-last-edit-by - Last edited by #{@page.commit.author.name} #{time_ago_with_tooltip(@page.commit.authored_date)} - diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml index 8bcb24ae9d..edb5778f42 100644 --- a/app/views/shared/_clone_panel.html.haml +++ b/app/views/shared/_clone_panel.html.haml @@ -2,25 +2,9 @@ .git-clone-holder.input-group .input-group-addon.git-protocols .input-group-btn - %button{ | - type: 'button', | - class: "btn #{ 'active' if default_clone_protocol == 'ssh' }#{ ' has_tooltip' if current_user && current_user.require_ssh_key? }", | - :"data-clone" => project.ssh_url_to_repo, | - :"data-title" => "Add an SSH key to your profile
to pull or push via SSH.", - :"data-html" => "true", - :"data-container" => "body"} - SSH + = ssh_clone_button(project) .input-group-btn - %button{ | - type: 'button', | - class: "btn #{ 'active' if default_clone_protocol == 'http' }#{ ' has_tooltip' if current_user && current_user.require_password? }", | - :"data-clone" => project.http_url_to_repo, | - :"data-title" => "Set a password on your account
to pull or push via #{gitlab_config.protocol.upcase}.", - :"data-html" => "true", - :"data-container" => "body"} - = gitlab_config.protocol.upcase + = http_clone_button(project) = text_field_tag :project_clone, default_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true - - if project.kind_of?(Project) - .input-group-addon.has_tooltip{title: "#{visibility_level_label(project.visibility_level)} project", data: { container: "body" } } - .visibility-level-label - = visibility_level_icon(project.visibility_level) + .input-group-btn + = clipboard_button(clipboard_target: '#project_clone') diff --git a/app/views/shared/_confirm_modal.html.haml b/app/views/shared/_confirm_modal.html.haml index 5f51b0d450..34241cd8aa 100644 --- a/app/views/shared/_confirm_modal.html.haml +++ b/app/views/shared/_confirm_modal.html.haml @@ -3,7 +3,8 @@ .modal-content .modal-header %a.close{href: "#", "data-dismiss" => "modal"} × - %h4 Confirmation required + %h3.page-title + Confirmation required .modal-body %p.cred.lead.js-confirm-text @@ -14,9 +15,9 @@ %br Please type %code.js-confirm-danger-match #{phrase} - to proceed or close this modal to cancel + to proceed or close this modal to cancel. .form-group = text_field_tag 'confirm_name_input', '', class: 'form-control js-confirm-danger-input' - .form-group + .form-actions = submit_tag 'Confirm', class: "btn btn-danger js-confirm-danger-submit" diff --git a/app/views/shared/_file_highlight.html.haml b/app/views/shared/_file_highlight.html.haml index 57c3aff3e1..2bc98983d6 100644 --- a/app/views/shared/_file_highlight.html.haml +++ b/app/views/shared/_file_highlight.html.haml @@ -8,5 +8,6 @@ %a{href: "#L#{i}", id: "L#{i}", 'data-line-number' => i} %i.fa.fa-link = i - :preserve - #{highlight(blob.name, blob.data)} + .blob-content{data: {blob_id: blob.id}} + :preserve + #{highlight(blob.name, blob.data)} diff --git a/app/views/shared/_group_form.html.haml b/app/views/shared/_group_form.html.haml index c0a9923348..67072b9fc2 100644 --- a/app/views/shared/_group_form.html.haml +++ b/app/views/shared/_group_form.html.haml @@ -23,7 +23,7 @@ %li It will change the git path to repositories under this group. .form-group.group-description-holder - = f.label :description, 'Details', class: 'control-label' + = f.label :description, class: 'control-label' .col-sm-10 = f.text_area :description, maxlength: 250, class: 'form-control js-gfm-input', rows: 4 diff --git a/app/views/shared/_issues.html.haml b/app/views/shared/_issues.html.haml index 0dbb6a0439..4b4c9e9eab 100644 --- a/app/views/shared/_issues.html.haml +++ b/app/views/shared/_issues.html.haml @@ -3,8 +3,10 @@ .panel.panel-default.panel-small - project = group[0] .panel-heading - = link_to_project project - = link_to 'show all', namespace_project_issues_path(project.namespace, project), class: 'pull-right' + = link_to project.name_with_namespace, namespace_project_issues_path(project.namespace, project) + - if can?(current_user, :create_issue, project) + .pull-right + = link_to 'New issue', new_namespace_project_issue_path(project.namespace, project) %ul.well-list.issues-list - group[1].each do |issue| @@ -12,4 +14,3 @@ = paginate @issues, theme: "gitlab" - else .nothing-here-block No issues to show - diff --git a/app/views/shared/_merge_requests.html.haml b/app/views/shared/_merge_requests.html.haml index c02c5af008..be17a511b2 100644 --- a/app/views/shared/_merge_requests.html.haml +++ b/app/views/shared/_merge_requests.html.haml @@ -3,8 +3,11 @@ .panel.panel-default.panel-small - project = group[0] .panel-heading - = link_to_project project - = link_to 'show all', namespace_project_merge_requests_path(project.namespace, project), class: 'pull-right' + = link_to project.name_with_namespace, namespace_project_merge_requests_path(project.namespace, project) + - if can?(current_user, :create_merge_request, project) + .pull-right + = link_to 'New merge request', new_namespace_project_merge_request_path(project.namespace, project) + %ul.well-list.mr-list - group[1].each do |merge_request| = render 'projects/merge_requests/merge_request', merge_request: merge_request diff --git a/app/views/shared/_milestone_expired.html.haml b/app/views/shared/_milestone_expired.html.haml new file mode 100644 index 0000000000..b8eef15fbe --- /dev/null +++ b/app/views/shared/_milestone_expired.html.haml @@ -0,0 +1,5 @@ +- if milestone.expired? and not milestone.closed? + %span.cred (Expired) +- if milestone.expires_at + %span + = milestone.expires_at diff --git a/app/views/shared/_new_commit_form.html.haml b/app/views/shared/_new_commit_form.html.haml index 8636341c60..111219f206 100644 --- a/app/views/shared/_new_commit_form.html.haml +++ b/app/views/shared/_new_commit_form.html.haml @@ -2,17 +2,15 @@ - unless @project.empty_repo? .form-group.branch - = label_tag 'branch', class: 'control-label' do - Branch + = label_tag 'new_branch', 'Target branch', class: 'control-label' .col-sm-10 - = text_field_tag 'new_branch', @new_branch || @ref, class: "form-control js-new-branch" + = text_field_tag 'new_branch', @new_branch || tree_edit_branch, required: true, class: "form-control js-new-branch" - .form-group.js-create-merge-request-form-group - .col-sm-offset-2.col-sm-10 - .checkbox - - nonce = SecureRandom.hex - = label_tag "create_merge_request-#{nonce}" do - = check_box_tag 'create_merge_request', 1, true, class: 'js-create-merge-request', id: "create_merge_request-#{nonce}" - Start a new merge request with this commit + .js-create-merge-request-container + .checkbox + - nonce = SecureRandom.hex + = label_tag "create_merge_request-#{nonce}" do + = check_box_tag 'create_merge_request', 1, true, class: 'js-create-merge-request', id: "create_merge_request-#{nonce}" + Start a new merge request with these changes = hidden_field_tag 'original_branch', @ref, class: 'js-original-branch' diff --git a/app/views/shared/_new_project_item_select.html.haml b/app/views/shared/_new_project_item_select.html.haml new file mode 100644 index 0000000000..c4431d6692 --- /dev/null +++ b/app/views/shared/_new_project_item_select.html.haml @@ -0,0 +1,20 @@ +- if @projects.any? + .prepend-left-10.new-project-item-select-holder + = project_select_tag :project_path, class: "new-project-item-select", data: { include_groups: local_assigns[:include_groups] } + %a.btn.btn-new.new-project-item-select-button + = icon('plus') + = local_assigns[:label] + %b.caret + + :javascript + $('.new-project-item-select-button').on('click', function() { + $('.new-project-item-select').select2('open'); + }); + + var relativePath = '#{local_assigns[:path]}'; + + $('.new-project-item-select').on('click', function() { + window.location = $(this).val() + '/' + relativePath; + }); + + new ProjectSelect() diff --git a/app/views/shared/_project_limit.html.haml b/app/views/shared/_project_limit.html.haml new file mode 100644 index 0000000000..960ff00b49 --- /dev/null +++ b/app/views/shared/_project_limit.html.haml @@ -0,0 +1,8 @@ +- if cookies[:hide_project_limit_message].blank? && !current_user.hide_project_limit && !current_user.can_create_project? + .project-limit-message.alert.alert-warning.hidden-xs + You won't be able to create new projects because you have reached your project limit. + + .pull-right + = link_to "Don't show again", profile_path(user: {hide_project_limit: true}), method: :put, class: 'alert-link' + | + = link_to 'Remind later', '#', class: 'hide-project-limit-message alert-link' diff --git a/app/views/shared/_service_settings.html.haml b/app/views/shared/_service_settings.html.haml index 16a98a7233..28d6f421fe 100644 --- a/app/views/shared/_service_settings.html.haml +++ b/app/views/shared/_service_settings.html.haml @@ -59,6 +59,15 @@ %strong Merge Request events %p.light This url will be triggered when a merge request is created + - if @service.supported_events.include?("build") + %div + = form.check_box :build_events, class: 'pull-left' + .prepend-left-20 + = form.label :build_events, class: 'list-label' do + %strong Build events + %p.light + This url will be triggered when a build status changes + - @service.fields.each do |field| - type = field[:type] diff --git a/app/views/shared/issuable/_context.html.haml b/app/views/shared/issuable/_context.html.haml deleted file mode 100644 index be66256c7b..0000000000 --- a/app/views/shared/issuable/_context.html.haml +++ /dev/null @@ -1,50 +0,0 @@ -= form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, html: {class: 'issuable-context-form inline-update js-issuable-update'} do |f| - %div.prepend-top-20 - .issuable-context-title - %label - Assignee: - - if issuable.assignee - %strong= link_to_member(@project, issuable.assignee, size: 24) - - else - none - .issuable-context-selectbox - - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) - = users_select_tag("#{issuable.class.table_name.singularize}[assignee_id]", placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: issuable.assignee_id, project: @target_project, null_user: true, current_user: true) - - %div.prepend-top-20.clearfix - .issuable-context-title - %label - Milestone: - - if issuable.milestone - %span.back-to-milestone - = link_to namespace_project_milestone_path(@project.namespace, @project, issuable.milestone) do - %strong - = icon('clock-o') - = issuable.milestone.title - - else - none - .issuable-context-selectbox - - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) - = f.select(:milestone_id, milestone_options(issuable), { include_blank: 'Select milestone' }, {class: 'select2 select2-compact js-select2 js-milestone'}) - = hidden_field_tag :issuable_context - = f.submit class: 'btn hide' - - - if current_user - - subscribed = issuable.subscribed?(current_user) - %div.prepend-top-20.clearfix - .issuable-context-title - %label - Subscription: - %button.btn.btn-block.subscribe-button{:type => 'button'} - = icon('eye') - %span= subscribed ? 'Unsubscribe' : 'Subscribe' - - subscribtion_status = subscribed ? 'subscribed' : 'unsubscribed' - .subscription-status{data: {status: subscribtion_status}} - .description-block.unsubscribed{class: ( 'hidden' if subscribed )} - You're not receiving notifications from this thread. - .description-block.subscribed{class: ( 'hidden' unless subscribed )} - You're receiving notifications because you're subscribed to this thread. - -:javascript - new Subscription("#{toggle_subscription_path(issuable)}"); - new IssuableContext(); diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml index d1231438ee..ac6c248ccf 100644 --- a/app/views/shared/issuable/_filter.html.haml +++ b/app/views/shared/issuable/_filter.html.haml @@ -31,11 +31,11 @@ .issues-other-filters .filter-item.inline = users_select_tag(:assignee_id, selected: params[:assignee_id], - placeholder: 'Assignee', class: 'trigger-submit', any_user: true, null_user: true, first_user: true, current_user: true) + placeholder: 'Assignee', class: 'trigger-submit', any_user: "Any Assignee", null_user: true, first_user: true, current_user: true) .filter-item.inline = users_select_tag(:author_id, selected: params[:author_id], - placeholder: 'Author', class: 'trigger-submit', any_user: true, first_user: true, current_user: true) + placeholder: 'Author', class: 'trigger-submit', any_user: "Any Author", first_user: true, current_user: true) .filter-item.inline.milestone-filter = select_tag('milestone_title', projects_milestones_options, @@ -53,12 +53,16 @@ - if controller.controller_name == 'issues' .issues_bulk_update.hide = form_tag bulk_update_namespace_project_issues_path(@project.namespace, @project), method: :post do - = select_tag('update[state_event]', options_for_select([['Open', 'reopen'], ['Closed', 'close']]), prompt: "Status", class: 'form-control') - = users_select_tag('update[assignee_id]', placeholder: 'Assignee', null_user: true, first_user: true, current_user: true) - = select_tag('update[milestone_id]', bulk_update_milestone_options, prompt: "Milestone") + .filter-item.inline + = select_tag('update[state_event]', options_for_select([['Open', 'reopen'], ['Closed', 'close']]), include_blank: true, data: { placeholder: "Status" }) + .filter-item.inline + = users_select_tag('update[assignee_id]', placeholder: 'Assignee', null_user: true, first_user: true, current_user: true) + .filter-item.inline + = select_tag('update[milestone_id]', bulk_update_milestone_options, include_blank: true, data: { placeholder: "Milestone" }) = hidden_field_tag 'update[issues_ids]', [] = hidden_field_tag :state_event, params[:state_event] - = button_tag "Update issues", class: "btn update_selected_issues btn-save" + .filter-item.inline + = button_tag "Update issues", class: "btn update_selected_issues btn-save" :javascript new UsersSelect(); diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml index 0fc74d7d2b..90dc006248 100644 --- a/app/views/shared/issuable/_form.html.haml +++ b/app/views/shared/issuable/_form.html.haml @@ -6,8 +6,7 @@ %span= msg %br .form-group - = f.label :title, class: 'control-label' do - %strong= 'Title *' + = f.label :title, class: 'control-label' .col-sm-10 = f.text_field :title, maxlength: 255, autofocus: true, autocomplete: 'off', class: 'form-control pad js-gfm-input js-quick-submit', required: true @@ -20,7 +19,7 @@ - else Start the title with [WIP] or WIP: to prevent a Work In Progress merge request from being merged before it's ready. -.form-group.issuable-description +.form-group.detail-page-description = f.label :description, 'Description', class: 'control-label' .col-sm-10 @@ -30,29 +29,25 @@ = render 'projects/notes/hints' .clearfix .error-alert - %hr - if can?(current_user, :"admin_#{issuable.to_ability_name}", issuable.project) + %hr .form-group .issue-assignee - = f.label :assignee_id, class: 'control-label' do - %i.fa.fa-user - Assign to + = f.label :assignee_id, "Assignee", class: 'control-label' .col-sm-10 = users_select_tag("#{issuable.class.model_name.param_key}[assignee_id]", - placeholder: 'Select a user', class: 'custom-form-control', null_user: true, + placeholder: 'Select assignee', class: 'custom-form-control', null_user: true, selected: issuable.assignee_id, project: @target_project || @project, - first_user: true, current_user: true) + first_user: true, current_user: true, include_blank: true)   = link_to 'Assign to me', '#', class: 'btn assign-to-me-link' .form-group .issue-milestone - = f.label :milestone_id, class: 'control-label' do - %i.fa.fa-clock-o - Milestone + = f.label :milestone_id, "Milestone", class: 'control-label' .col-sm-10 - if milestone_options(issuable).present? = f.select(:milestone_id, milestone_options(issuable), - { include_blank: 'Select milestone' }, { class: 'select2' }) + { include_blank: true }, { class: 'select2', data: { placeholder: 'Select milestone' } }) - else .prepend-top-10 %span.light No open milestones available. @@ -60,13 +55,11 @@ - if can? current_user, :admin_milestone, issuable.project = link_to 'Create new milestone', new_namespace_project_milestone_path(issuable.project.namespace, issuable.project), target: :blank .form-group - = f.label :label_ids, class: 'control-label' do - %i.fa.fa-tag - Labels + = f.label :label_ids, "Labels", class: 'control-label' .col-sm-10 - if issuable.project.labels.any? = f.collection_select :label_ids, issuable.project.labels.all, :id, :name, - { selected: issuable.label_ids }, multiple: true, class: 'select2' + { selected: issuable.label_ids }, multiple: true, class: 'select2', data: { placeholder: "Select labels" } - else .prepend-top-10 %span.light No labels yet. @@ -78,31 +71,30 @@ %hr - if @merge_request.new_record? .form-group - = f.label :source_branch, class: 'control-label' do - %i.fa.fa-code-fork - Source Branch + = f.label :source_branch, class: 'control-label' .col-sm-10 = f.select(:source_branch, [@merge_request.source_branch], { }, { class: 'source_branch select2 span2', disabled: true }) .form-group - = f.label :target_branch, class: 'control-label' do - %i.fa.fa-code-fork - Target Branch + = f.label :target_branch, class: 'control-label' .col-sm-10 - = f.select(:target_branch, @merge_request.target_branches, { include_blank: "Select branch" }, { class: 'target_branch select2 span2', disabled: @merge_request.new_record? }) + = f.select(:target_branch, @merge_request.target_branches, { include_blank: true }, { class: 'target_branch select2 span2', disabled: @merge_request.new_record?, data: {placeholder: "Select branch"} }) - if @merge_request.new_record? %p.help-block = link_to 'Change branches', mr_change_branches_path(@merge_request) -.form-actions - - if !issuable.project.empty_repo? && (guide_url = contribution_guide_path(issuable.project)) && !issuable.persisted? - %p - Please review the - %strong #{link_to 'guidelines for contribution', guide_url} - to this repository. +- is_footer = !(issuable.is_a?(MergeRequest) && issuable.new_record?) +.gray-content-block{class: (is_footer ? "footer-block" : "middle-block")} - if issuable.new_record? - = f.submit "Submit new #{issuable.class.model_name.human.downcase}", class: 'btn btn-create' + = f.submit "Submit #{issuable.class.model_name.human.downcase}", class: 'btn btn-create' - else = f.submit 'Save changes', class: 'btn btn-save' + + - if !issuable.persisted? && !issuable.project.empty_repo? && (guide_url = contribution_guide_path(issuable.project)) + .inline.prepend-left-10 + Please review the + %strong #{link_to 'contribution guidelines', guide_url} + for this project. + - if issuable.new_record? - cancel_project = issuable.source_project - else diff --git a/app/views/shared/issuable/_participants.html.haml b/app/views/shared/issuable/_participants.html.haml new file mode 100644 index 0000000000..da6bacbb74 --- /dev/null +++ b/app/views/shared/issuable/_participants.html.haml @@ -0,0 +1,5 @@ +.block.participants + .title + = pluralize participants.count, "participant" + - participants.each do |participant| + = link_to_member(@project, participant, name: false, size: 24) diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml new file mode 100644 index 0000000000..79c5cc7f40 --- /dev/null +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -0,0 +1,83 @@ +.issuable-sidebar.issuable-affix + = form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, html: {class: 'issuable-context-form inline-update js-issuable-update'} do |f| + .block.assignee + .title + %label + Assignee + - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) + .pull-right + = link_to 'Edit', '#', class: 'edit-link' + .value + - if issuable.assignee + %strong= link_to_member(@project, issuable.assignee, size: 24) + - else + .light None + + .selectbox + = users_select_tag("#{issuable.class.table_name.singularize}[assignee_id]", placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: issuable.assignee_id, project: @target_project, null_user: true, current_user: true, first_user: true) + + .block.milestone + .title + %label + Milestone + - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) + .pull-right + = link_to 'Edit', '#', class: 'edit-link' + .value + - if issuable.milestone + %span.back-to-milestone + = link_to namespace_project_milestone_path(@project.namespace, @project, issuable.milestone) do + %strong + = icon('clock-o') + = issuable.milestone.title + - else + .light None + .selectbox + = f.select(:milestone_id, milestone_options(issuable), { include_blank: true }, { class: 'select2 select2-compact js-select2 js-milestone', data: { placeholder: 'Select milestone' }}) + = hidden_field_tag :issuable_context + = f.submit class: 'btn hide' + + - if issuable.project.labels.any? + .block + .title + %label Labels + - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) + .pull-right + = link_to 'Edit', '#', class: 'edit-link' + .value.issuable-show-labels + - if issuable.labels.any? + - issuable.labels.each do |label| + = link_to_label(label) + - else + .light None + .selectbox + = f.collection_select :label_ids, issuable.project.labels.all, :id, :name, + { selected: issuable.label_ids }, multiple: true, class: 'select2 js-select2', data: { placeholder: "Select labels" } + + .block + .title + Cross-project reference + .cross-project-reference + %span#cross-project-reference + = cross_project_reference(@project, issuable) + = clipboard_button(clipboard_target: 'span#cross-project-reference') + + = render "shared/issuable/participants", participants: issuable.participants(current_user) + + - if current_user + - subscribed = issuable.subscribed?(current_user) + .block.light + .title + %label.light Notifications + - subscribtion_status = subscribed ? 'subscribed' : 'unsubscribed' + %button.btn.btn-block.btn-gray.subscribe-button{:type => 'button'} + %span= subscribed ? 'Unsubscribe' : 'Subscribe' + .subscription-status{data: {status: subscribtion_status}} + .unsubscribed{class: ( 'hidden' if subscribed )} + You're not receiving notifications from this thread. + .subscribed{class: ( 'hidden' unless subscribed )} + You're receiving notifications because you're subscribed to this thread. + + :javascript + new Subscription("#{toggle_subscription_path(issuable)}"); + new IssuableContext(); diff --git a/app/views/shared/snippets/_form.html.haml b/app/views/shared/snippets/_form.html.haml index 913b674484..1041eccd1d 100644 --- a/app/views/shared/snippets/_form.html.haml +++ b/app/views/shared/snippets/_form.html.haml @@ -1,5 +1,5 @@ .snippet-form-holder - = form_for @snippet, url: url, html: { class: "form-horizontal snippet-form" } do |f| + = form_for @snippet, url: url, html: { class: "form-horizontal snippet-form js-requires-input" } do |f| - if @snippet.errors.any? .alert.alert-danger %ul @@ -8,7 +8,8 @@ .form-group = f.label :title, class: 'control-label' - .col-sm-10= f.text_field :title, placeholder: "Example Snippet", class: 'form-control', required: true + .col-sm-10 + = f.text_field :title, class: 'form-control', required: true, autofocus: true = render 'shared/visibility_level', f: f, visibility_level: visibility_level, can_change_visibility_level: true, form_model: @snippet @@ -27,7 +28,7 @@ - if @snippet.new_record? = f.submit 'Create snippet', class: "btn-create btn" - else - = f.submit 'Save', class: "btn-save btn" + = f.submit 'Save changes', class: "btn-save btn" - if @snippet.project_id = link_to "Cancel", namespace_project_snippets_path(@project.namespace, @project), class: "btn btn-cancel" diff --git a/app/views/shared/snippets/_header.html.haml b/app/views/shared/snippets/_header.html.haml index 0a4a790ec5..aa5acee9c1 100644 --- a/app/views/shared/snippets/_header.html.haml +++ b/app/views/shared/snippets/_header.html.haml @@ -1,24 +1,25 @@ -.snippet-details - .page-title - .snippet-box{class: visibility_level_color(@snippet.visibility_level)} - = visibility_level_icon(@snippet.visibility_level) - = visibility_level_label(@snippet.visibility_level) - %span.snippet-id Snippet ##{@snippet.id} - %span.creator - · created by #{link_to_member(@project, @snippet.author, size: 24)} - · - = time_ago_with_tooltip(@snippet.created_at, placement: 'bottom', html_class: 'snippet_updated_ago') - - if @snippet.updated_at != @snippet.created_at - %span - · - = icon('edit', title: 'edited') - = time_ago_with_tooltip(@snippet.updated_at, placement: 'bottom', html_class: 'snippet_edited_ago') +.detail-page-header + .snippet-box.has_tooltip{class: visibility_level_color(@snippet.visibility_level), title: snippet_visibility_level_description(@snippet.visibility_level, @snippet), data: { container: 'body' }} + = visibility_level_icon(@snippet.visibility_level, fw: false) + = visibility_level_label(@snippet.visibility_level) + %span.identifier + Snippet ##{@snippet.id} + %span.creator + · created by #{link_to_member(@project, @snippet.author, size: 24)} + · + = time_ago_with_tooltip(@snippet.created_at, placement: 'bottom', html_class: 'snippet_updated_ago') + - if @snippet.updated_at != @snippet.created_at + %span + · + = icon('edit', title: 'edited') + = time_ago_with_tooltip(@snippet.updated_at, placement: 'bottom', html_class: 'snippet_edited_ago') - .pull-right - - if @snippet.project_id? - = render "projects/snippets/actions" - - else - = render "snippets/actions" - .gray-content-block.middle-block - %h2.snippet-title - = gfm escape_once(@snippet.title) + .pull-right + - if @snippet.project_id? + = render "projects/snippets/actions" + - else + = render "snippets/actions" + +.detail-page-description.gray-content-block.second-block + %h2.title + = markdown escape_once(@snippet.title), pipeline: :single_line diff --git a/app/views/sherlock/transactions/_general.html.haml b/app/views/sherlock/transactions/_general.html.haml index 4287a0c320..8533b130da 100644 --- a/app/views/sherlock/transactions/_general.html.haml +++ b/app/views/sherlock/transactions/_general.html.haml @@ -25,6 +25,12 @@ %strong = @transaction.duration.round(2) = t('sherlock.seconds') + %li + %span.light + #{t('sherlock.query_time')} + %strong + = @transaction.query_duration.round(2) + = t('sherlock.seconds') %li %span.light #{t('sherlock.finished_at')}: diff --git a/app/views/snippets/edit.html.haml b/app/views/snippets/edit.html.haml index 1a38003566..82f44a9a5c 100644 --- a/app/views/snippets/edit.html.haml +++ b/app/views/snippets/edit.html.haml @@ -1,5 +1,5 @@ - page_title "Edit", @snippet.title, "Snippets" %h3.page-title - Edit snippet + Edit Snippet %hr = render 'shared/snippets/form', url: snippet_path(@snippet), visibility_level: @snippet.visibility_level diff --git a/app/views/snippets/new.html.haml b/app/views/snippets/new.html.haml index a74d5e792a..79e2392490 100644 --- a/app/views/snippets/new.html.haml +++ b/app/views/snippets/new.html.haml @@ -1,5 +1,5 @@ - page_title "New Snippet" %h3.page-title - New snippet + New Snippet %hr = render "shared/snippets/form", url: snippets_path(@snippet), visibility_level: default_snippet_visibility diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml index 69d8899d4c..a2b3656877 100644 --- a/app/views/snippets/show.html.haml +++ b/app/views/snippets/show.html.haml @@ -9,6 +9,6 @@ %strong = @snippet.file_name .file-actions.hidden-xs - .btn-group.tree-btn-group - = link_to 'Raw', raw_snippet_path(@snippet), class: "btn btn-sm", target: "_blank" + = clipboard_button(clipboard_target: ".blob-content[data-blob-id='#{@snippet.id}']") + = link_to 'Raw', raw_snippet_path(@snippet), class: "btn btn-sm", target: "_blank" = render 'shared/snippets/blob' diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index d5a92cb816..b7a7eb4e6f 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -73,7 +73,7 @@ .user-calendar-activities -%ul.center-middle-menu +%ul.center-top-menu.no-top.no-bottom.bottom-border.wide %li.active = link_to "#activity", 'data-toggle' => 'tab' do Activity diff --git a/app/views/votes/_votes_block.html.haml b/app/views/votes/_votes_block.html.haml index 7eb27c12d3..6071f1484c 100644 --- a/app/views/votes/_votes_block.html.haml +++ b/app/views/votes/_votes_block.html.haml @@ -19,7 +19,8 @@ post_emoji_url = "#{award_toggle_namespace_project_notes_path(@project.namespace, @project)}" noteable_type = "#{votable.class.name.underscore}" noteable_id = "#{votable.id}" - window.awards_handler = new AwardsHandler(post_emoji_url, noteable_type, noteable_id) + aliases = #{AwardEmoji::ALIASES.to_json} + window.awards_handler = new AwardsHandler(post_emoji_url, noteable_type, noteable_id, aliases) $(".awards-menu li").click (e)-> emoji = $(this).data("emoji") diff --git a/app/workers/build_email_worker.rb b/app/workers/build_email_worker.rb new file mode 100644 index 0000000000..1c7a04a66a --- /dev/null +++ b/app/workers/build_email_worker.rb @@ -0,0 +1,19 @@ +class BuildEmailWorker + include Sidekiq::Worker + + def perform(build_id, recipients, push_data) + recipients.each do |recipient| + begin + case push_data['build_status'] + when 'success' + Notify.build_success_email(build_id, recipient).deliver_now + when 'failed' + Notify.build_fail_email(build_id, recipient).deliver_now + end + # These are input errors and won't be corrected even if Sidekiq retries + rescue Net::SMTPFatalError, Net::SMTPSyntaxError => e + logger.info("Failed to send e-mail for project '#{push_data['project_name']}' to #{recipient}: #{e}") + end + end + end +end diff --git a/app/workers/ci/hip_chat_notifier_worker.rb b/app/workers/ci/hip_chat_notifier_worker.rb deleted file mode 100644 index ebb43570e2..0000000000 --- a/app/workers/ci/hip_chat_notifier_worker.rb +++ /dev/null @@ -1,19 +0,0 @@ -module Ci - class HipChatNotifierWorker - include Sidekiq::Worker - - def perform(message, options={}) - room = options.delete('room') - token = options.delete('token') - server = options.delete('server') - name = options.delete('service_name') - client_opts = { - api_version: 'v2', - server_url: server - } - - client = HipChat::Client.new(token, client_opts) - client[room].send(name, message, options.symbolize_keys) - end - end -end diff --git a/app/workers/ci/slack_notifier_worker.rb b/app/workers/ci/slack_notifier_worker.rb deleted file mode 100644 index 3bbb9b4bec..0000000000 --- a/app/workers/ci/slack_notifier_worker.rb +++ /dev/null @@ -1,10 +0,0 @@ -module Ci - class SlackNotifierWorker - include Sidekiq::Worker - - def perform(webhook_url, message, options={}) - notifier = Slack::Notifier.new(webhook_url) - notifier.ping(message, options) - end - end -end diff --git a/app/workers/ci/web_hook_worker.rb b/app/workers/ci/web_hook_worker.rb deleted file mode 100644 index 0bb8384557..0000000000 --- a/app/workers/ci/web_hook_worker.rb +++ /dev/null @@ -1,9 +0,0 @@ -module Ci - class WebHookWorker - include Sidekiq::Worker - - def perform(hook_id, data) - Ci::WebHook.find(hook_id).execute data - end - end -end diff --git a/app/workers/email_receiver_worker.rb b/app/workers/email_receiver_worker.rb index 5a921a73fe..f2649e38eb 100644 --- a/app/workers/email_receiver_worker.rb +++ b/app/workers/email_receiver_worker.rb @@ -46,6 +46,6 @@ class EmailReceiverWorker return end - EmailRejectionMailer.delay.rejection(reason, raw, can_retry) + EmailRejectionMailer.rejection(reason, raw, can_retry).deliver_later end end diff --git a/app/workers/emails_on_push_worker.rb b/app/workers/emails_on_push_worker.rb index 916a99bb27..c4d8595d45 100644 --- a/app/workers/emails_on_push_worker.rb +++ b/app/workers/emails_on_push_worker.rb @@ -53,7 +53,7 @@ class EmailsOnPushWorker reverse_compare: reverse_compare, send_from_committer_email: send_from_committer_email, disable_diffs: disable_diffs - ).deliver + ).deliver_now # These are input errors and won't be corrected even if Sidekiq retries rescue Net::SMTPFatalError, Net::SMTPSyntaxError => e logger.info("Failed to send e-mail for project '#{project.name_with_namespace}' to #{recipient}: #{e}") diff --git a/app/workers/merge_worker.rb b/app/workers/merge_worker.rb index 5d1a8555b7..c87c0a252b 100644 --- a/app/workers/merge_worker.rb +++ b/app/workers/merge_worker.rb @@ -8,16 +8,7 @@ class MergeWorker current_user = User.find(current_user_id) merge_request = MergeRequest.find(merge_request_id) - result = MergeRequests::MergeService.new(merge_request.target_project, current_user). - execute(merge_request, params[:commit_message]) - - if result[:status] == :success && params[:should_remove_source_branch].present? - DeleteBranchService.new(merge_request.source_project, current_user). - execute(merge_request.source_branch) - - merge_request.source_project.repository.expire_branch_names - end - - result + MergeRequests::MergeService.new(merge_request.target_project, current_user, params). + execute(merge_request) end end diff --git a/app/workers/stuck_ci_builds_worker.rb b/app/workers/stuck_ci_builds_worker.rb index 4e5eddbaba..ca594e77e7 100644 --- a/app/workers/stuck_ci_builds_worker.rb +++ b/app/workers/stuck_ci_builds_worker.rb @@ -1,11 +1,8 @@ class StuckCiBuildsWorker include Sidekiq::Worker - include Sidetiq::Schedulable BUILD_STUCK_TIMEOUT = 1.day - recurrence { daily } - def perform Rails.logger.info 'Cleaning stuck builds' diff --git a/bin/background_jobs b/bin/background_jobs index d4578f6a22..5c85fb339e 100755 --- a/bin/background_jobs +++ b/bin/background_jobs @@ -37,7 +37,7 @@ start_no_deamonize() start_sidekiq() { - bundle exec sidekiq -q post_receive -q mailer -q archive_repo -q system_hook -q project_web_hook -q gitlab_shell -q incoming_email -q runner -q common -q default -e $RAILS_ENV -P $sidekiq_pidfile $@ >> $sidekiq_logfile 2>&1 + bundle exec sidekiq -q post_receive -q mailers -q archive_repo -q system_hook -q project_web_hook -q gitlab_shell -q incoming_email -q runner -q common -q default -e $RAILS_ENV -P $sidekiq_pidfile $@ >> $sidekiq_logfile 2>&1 } load_ok() diff --git a/bin/ci/upgrade.rb b/bin/ci/upgrade.rb old mode 100644 new mode 100755 diff --git a/bin/parallel-rsync-repos b/bin/parallel-rsync-repos new file mode 100755 index 0000000000..21921148fa --- /dev/null +++ b/bin/parallel-rsync-repos @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +# this script should run as the 'git' user, not root, because 'root' should not +# own intermediate directories created by rsync. +# +# Example invocation: +# find /var/opt/gitlab/git-data/repositories -maxdepth 2 | \ +# parallel-rsync-repos transfer-success.log /var/opt/gitlab/git-data/repositories /mnt/gitlab/repositories +# +# You can also rsync to a remote destination. +# +# parallel-rsync-repos transfer-success.log /var/opt/gitlab/git-data/repositories user@host:/mnt/gitlab/repositories +# +# If you need to pass extra options to rsync, set the RSYNC variable +# +# env RSYNC='rsync --rsh="foo bar"' parallel-rsync-repos transfer-success.log /src dest +# + +LOGFILE=$1 +SRC=$2 +DEST=$3 + +if [ -z "$LOGFILE" ] || [ -z "$SRC" ] || [ -z "$DEST" ] ; then + echo "Usage: $0 LOGFILE SRC DEST" + exit 1 +fi + +if [ -z "$JOBS" ] ; then + JOBS=10 +fi + +if [ -z "$RSYNC" ] ; then + RSYNC=rsync +fi + +if ! cd $SRC ; then + echo "cd $SRC failed" + exit 1 +fi + +rsyncjob() { + relative_dir="./${1#$SRC}" + + if ! $RSYNC --delete --relative -a "$relative_dir" "$DEST" ; then + echo "rsync $1 failed" + return 1 + fi + + echo "$1" >> $LOGFILE +} + +export LOGFILE SRC DEST RSYNC +export -f rsyncjob + +parallel -j$JOBS --progress rsyncjob diff --git a/bin/rails b/bin/rails index 7feb6a30e6..5191e6927a 100755 --- a/bin/rails +++ b/bin/rails @@ -1,8 +1,4 @@ #!/usr/bin/env ruby -begin - load File.expand_path("../spring", __FILE__) -rescue LoadError -end -APP_PATH = File.expand_path('../../config/application', __FILE__) +APP_PATH = File.expand_path('../../config/application', __FILE__) require_relative '../config/boot' require 'rails/commands' diff --git a/bin/rake b/bin/rake index 0fb4e07e13..17240489f6 100755 --- a/bin/rake +++ b/bin/rake @@ -1,7 +1,4 @@ #!/usr/bin/env ruby -begin - load File.expand_path("../spring", __FILE__) -rescue LoadError -end -require 'bundler/setup' -load Gem.bin_path('rake', 'rake') +require_relative '../config/boot' +require 'rake' +Rake.application.run diff --git a/bin/setup b/bin/setup new file mode 100755 index 0000000000..acdb2c1389 --- /dev/null +++ b/bin/setup @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +require 'pathname' + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +Dir.chdir APP_ROOT do + # This script is a starting point to setup your application. + # Add necessary setup steps to this file: + + puts "== Installing dependencies ==" + system "gem install bundler --conservative" + system "bundle check || bundle install" + + # puts "\n== Copying sample files ==" + # unless File.exist?("config/database.yml") + # system "cp config/database.yml.sample config/database.yml" + # end + + puts "\n== Preparing database ==" + system "bin/rake db:setup" + + puts "\n== Removing old logs and tempfiles ==" + system "rm -f log/*" + system "rm -rf tmp/cache" + + puts "\n== Restarting application server ==" + system "touch tmp/restart.txt" +end diff --git a/bin/upgrade.rb b/bin/upgrade.rb old mode 100644 new mode 100755 diff --git a/config/application.rb b/config/application.rb index bfa2a809dd..d255ff0719 100644 --- a/config/application.rb +++ b/config/application.rb @@ -99,6 +99,10 @@ module Gitlab redis_config_hash[:expires_in] = 2.weeks # Cache should not grow forever config.cache_store = :redis_store, redis_config_hash + config.active_record.raise_in_transactional_callbacks = true + + config.active_job.queue_adapter = :sidekiq + # This is needed for gitlab-shell ENV['GITLAB_PATH_OUTSIDE_HOOK'] = ENV['PATH'] end diff --git a/config/environment.rb b/config/environment.rb index 3b186a9d57..df3006d349 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -2,4 +2,4 @@ require File.expand_path('../application', __FILE__) # Initialize the rails application -Gitlab::Application.initialize! +Rails.application.initialize! diff --git a/config/environments/development.rb b/config/environments/development.rb index 827a110c24..c22722c606 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,4 +1,4 @@ -Gitlab::Application.configure do +Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb # In the development environment your application's code is reloaded on diff --git a/config/environments/production.rb b/config/environments/production.rb index 3316ece387..909526605a 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,4 +1,4 @@ -Gitlab::Application.configure do +Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb # Code is not reloaded between requests @@ -9,7 +9,7 @@ Gitlab::Application.configure do config.action_controller.perform_caching = true # Disable Rails's static asset server (Apache or nginx will already do this) - config.serve_static_assets = false + config.serve_static_files = false # Compress JavaScripts and CSS. config.assets.js_compressor = :uglifier @@ -32,7 +32,7 @@ Gitlab::Application.configure do # config.force_ssl = true # See everything in the log (default is :info) - # config.log_level = :debug + config.log_level = :info # Suppress 'Rendered template ...' messages in the log # source: http://stackoverflow.com/a/16369363 diff --git a/config/environments/test.rb b/config/environments/test.rb index 955540837d..d6842affa6 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,4 +1,4 @@ -Gitlab::Application.configure do +Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb # The test environment is used exclusively to run your application's @@ -7,8 +7,10 @@ Gitlab::Application.configure do # and recreated between test runs. Don't rely on the data there! config.cache_classes = false + config.cache_store = :null_store + # Configure static asset server for tests with Cache-Control for performance - config.serve_static_assets = true + config.serve_static_files = true config.static_cache_control = "public, max-age=3600" # Show full error reports and disable caching @@ -32,4 +34,6 @@ Gitlab::Application.configure do config.eager_load = false config.cache_store = :null_store + + config.active_job.queue_adapter = :test end diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 1da42ab38f..db378118f8 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -76,7 +76,7 @@ production: &base # This happens when the commit is pushed or merged into the default branch of a project. # When not specified the default issue_closing_pattern as specified below will be used. # Tip: you can test your closing pattern at http://rubular.com. - # issue_closing_pattern: '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?) +(?:(?:issues? +)?#\d+(?:(?:, *| +and +)?))+)' + # issue_closing_pattern: '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?) +(?:(?:issues? +)?%{issue_ref}(?:(?:, *| +and +)?))+)' ## Default project features settings default_projects_features: diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index b162b8a83f..d3d27c762a 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -33,13 +33,15 @@ class Settings < Settingslogic end def build_gitlab_shell_ssh_path_prefix + user_host = "#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}" + if gitlab_shell.ssh_port != 22 - "ssh://#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}:#{gitlab_shell.ssh_port}/" + "ssh://#{user_host}:#{gitlab_shell.ssh_port}/" else if gitlab_shell.ssh_host.include? ':' - "[#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}]:" + "[#{user_host}]:" else - "#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}:" + "#{user_host}:" end end end @@ -162,7 +164,7 @@ Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled']. Settings.gitlab['twitter_sharing_enabled'] ||= true if Settings.gitlab['twitter_sharing_enabled'].nil? Settings.gitlab['restricted_visibility_levels'] = Settings.send(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], []) Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil? -Settings.gitlab['issue_closing_pattern'] = '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?|[Rr]esolv(?:e[sd]?|ing)) +(?:(?:issues? +)?#\d+(?:(?:, *| +and +)?))+)' if Settings.gitlab['issue_closing_pattern'].nil? +Settings.gitlab['issue_closing_pattern'] = '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?|[Rr]esolv(?:e[sd]?|ing)) +(?:(?:issues? +)?%{issue_ref}(?:(?:, *| +and +)?)|([A-Z]*-\d*))+)' if Settings.gitlab['issue_closing_pattern'].nil? Settings.gitlab['default_projects_features'] ||= {} Settings.gitlab['webhook_timeout'] ||= 10 Settings.gitlab['max_attachment_size'] ||= 10 @@ -293,3 +295,12 @@ if Rails.env.test? Settings.gitlab['default_can_create_group'] = true Settings.gitlab['default_can_create_team'] = false end + +# Force a refresh of application settings at startup +begin + ApplicationSetting.expire + Ci::ApplicationSetting.expire +rescue + # Gracefully handle when Redis is not available. For example, + # omnibus may fail here during assets:precompile. +end diff --git a/config/initializers/4_ci_app.rb b/config/initializers/4_ci_app.rb index cac8edb32b..d252e40310 100644 --- a/config/initializers/4_ci_app.rb +++ b/config/initializers/4_ci_app.rb @@ -1,8 +1,6 @@ module GitlabCi VERSION = Gitlab::VERSION REVISION = Gitlab::REVISION - - REGISTRATION_TOKEN = SecureRandom.hex(10) def self.config Settings diff --git a/config/initializers/carrierwave.rb b/config/initializers/carrierwave.rb index bfb8656df5..df28d30d75 100644 --- a/config/initializers/carrierwave.rb +++ b/config/initializers/carrierwave.rb @@ -31,11 +31,11 @@ if File.exists?(aws_file) if Rails.env.test? Fog.mock! connection = ::Fog::Storage.new( - aws_access_key_id: AWS_CONFIG['access_key_id'], - aws_secret_access_key: AWS_CONFIG['secret_access_key'], - provider: 'AWS', - region: AWS_CONFIG['region'] - ) + aws_access_key_id: AWS_CONFIG['access_key_id'], + aws_secret_access_key: AWS_CONFIG['secret_access_key'], + provider: 'AWS', + region: AWS_CONFIG['region'] + ) connection.directories.create(key: AWS_CONFIG['bucket']) end end diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb index 43adac8b2c..54516e3f23 100644 --- a/config/initializers/cookies_serializer.rb +++ b/config/initializers/cookies_serializer.rb @@ -1,3 +1,3 @@ # Be sure to restart your server when you modify this file. -Gitlab::Application.config.action_dispatch.cookies_serializer = :hybrid +Rails.application.config.action_dispatch.cookies_serializer = :hybrid diff --git a/config/initializers/default_url_options.rb b/config/initializers/default_url_options.rb index f9f88f95db..8fd27b1d88 100644 --- a/config/initializers/default_url_options.rb +++ b/config/initializers/default_url_options.rb @@ -8,4 +8,4 @@ unless Gitlab.config.gitlab_on_standard_port? default_url_options[:port] = Gitlab.config.gitlab.port end -Gitlab::Application.routes.default_url_options = default_url_options +Rails.application.routes.default_url_options = default_url_options diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 29506970af..2a09a4d373 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -60,7 +60,7 @@ Devise.setup do |config| # It will change confirmation, password recovery and other workflows # to behave the same regardless if the e-mail provided was right or wrong. # Does not affect registerable. - # config.paranoid = true + config.paranoid = true # ==> Configuration for :database_authenticatable # For bcrypt, this is the cost for hashing the password and defaults to 10. If @@ -121,14 +121,14 @@ Devise.setup do |config| config.lock_strategy = :failed_attempts # Defines which key will be used when locking and unlocking an account - # config.unlock_keys = [ :email ] + config.unlock_keys = [ :email ] # Defines which strategy will be used to unlock an account. # :email = Sends an unlock link to the user email # :time = Re-enables login after a certain amount of time (see :unlock_in below) # :both = Enables both strategies # :none = No unlock strategy. You should handle unlocking by yourself. - config.unlock_strategy = :time + config.unlock_strategy = :both # Number of authentication tries before locking an account if lock_strategy # is failed attempts. diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb index 70ed10e827..4c164119ff 100644 --- a/config/initializers/omniauth.rb +++ b/config/initializers/omniauth.rb @@ -16,7 +16,7 @@ OmniAuth.config.allowed_request_methods = [:post] #In case of auto sign-in, the GET method is used (users don't get to click on a button) OmniAuth.config.allowed_request_methods << :get if Gitlab.config.omniauth.auto_sign_in_with_provider.present? OmniAuth.config.before_request_phase do |env| - OmniAuth::RequestForgeryProtection.new(env).call + OmniAuth::RequestForgeryProtection.call(env) end if Gitlab.config.omniauth.enabled diff --git a/config/initializers/rack_attack.rb.example b/config/initializers/rack_attack.rb.example index 2155ea1456..b1bbcca1d6 100644 --- a/config/initializers/rack_attack.rb.example +++ b/config/initializers/rack_attack.rb.example @@ -4,13 +4,13 @@ # If you change this file in a Merge Request, please also create a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests paths_to_be_protected = [ - "#{Gitlab::Application.config.relative_url_root}/users/password", - "#{Gitlab::Application.config.relative_url_root}/users/sign_in", - "#{Gitlab::Application.config.relative_url_root}/api/#{API::API.version}/session.json", - "#{Gitlab::Application.config.relative_url_root}/api/#{API::API.version}/session", - "#{Gitlab::Application.config.relative_url_root}/users", - "#{Gitlab::Application.config.relative_url_root}/users/confirmation", - "#{Gitlab::Application.config.relative_url_root}/unsubscribes/" + "#{Rails.application.config.relative_url_root}/users/password", + "#{Rails.application.config.relative_url_root}/users/sign_in", + "#{Rails.application.config.relative_url_root}/api/#{API::API.version}/session.json", + "#{Rails.application.config.relative_url_root}/api/#{API::API.version}/session", + "#{Rails.application.config.relative_url_root}/users", + "#{Rails.application.config.relative_url_root}/users/confirmation", + "#{Rails.application.config.relative_url_root}/unsubscribes/" ] diff --git a/config/initializers/rack_lineprof.rb b/config/initializers/rack_lineprof.rb index f0c006d811..22e77a32c6 100644 --- a/config/initializers/rack_lineprof.rb +++ b/config/initializers/rack_lineprof.rb @@ -2,7 +2,7 @@ # with darker backgrounds. This patch tweaks the colors a bit so the output is # actually readable. if Rails.env.development? and RUBY_ENGINE == 'ruby' and ENV['ENABLE_LINEPROF'] - Gitlab::Application.config.middleware.use(Rack::Lineprof) + Rails.application.config.middleware.use(Rack::Lineprof) module Rack class Lineprof diff --git a/config/initializers/secret_token.rb b/config/initializers/secret_token.rb index 1b518c3bec..dae3a4a9a9 100644 --- a/config/initializers/secret_token.rb +++ b/config/initializers/secret_token.rb @@ -22,15 +22,15 @@ def find_secure_token end end -Gitlab::Application.config.secret_token = find_secure_token -Gitlab::Application.config.secret_key_base = find_secure_token +Rails.application.config.secret_token = find_secure_token +Rails.application.config.secret_key_base = find_secure_token # CI def generate_new_secure_token SecureRandom.hex(64) end -if Gitlab::Application.secrets.db_key_base.blank? +if Rails.application.secrets.db_key_base.blank? warn "Missing `db_key_base` for '#{Rails.env}' environment. The secrets will be generated and stored in `config/secrets.yml`" all_secrets = YAML.load_file('config/secrets.yml') if File.exist?('config/secrets.yml') @@ -46,5 +46,5 @@ if Gitlab::Application.secrets.db_key_base.blank? file.write(YAML.dump(all_secrets)) end - Gitlab::Application.secrets.db_key_base = env_secrets['db_key_base'] + Rails.application.secrets.db_key_base = env_secrets['db_key_base'] end diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb index f30178ff71..0fc725842b 100644 --- a/config/initializers/session_store.rb +++ b/config/initializers/session_store.rb @@ -10,14 +10,16 @@ rescue Settings.gitlab['session_expire_delay'] ||= 10080 end -unless Rails.env.test? +if Rails.env.test? + Gitlab::Application.config.session_store :cookie_store, key: "_gitlab_session" +else Gitlab::Application.config.session_store( :redis_store, # Using the cookie_store would enable session replay attacks. - servers: Gitlab::Application.config.cache_store[1].merge(namespace: 'session:gitlab'), # re-use the Redis config from the Rails cache store + servers: Rails.application.config.cache_store[1].merge(namespace: 'session:gitlab'), # re-use the Redis config from the Rails cache store key: '_gitlab_session', secure: Gitlab.config.gitlab.https, httponly: true, expire_after: Settings.gitlab['session_expire_delay'] * 60, - path: (Gitlab::Application.config.relative_url_root.nil?) ? '/' : Gitlab::Application.config.relative_url_root + path: (Rails.application.config.relative_url_root.nil?) ? '/' : Gitlab::Application.config.relative_url_root ) end diff --git a/config/initializers/sherlock.rb b/config/initializers/sherlock.rb index 42b0d78c85..8f2ababb71 100644 --- a/config/initializers/sherlock.rb +++ b/config/initializers/sherlock.rb @@ -1,5 +1,5 @@ if Gitlab::Sherlock.enabled? - Gitlab::Application.configure do |config| + Rails.application.configure do |config| config.middleware.use(Gitlab::Sherlock::Middleware) end end diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index e856499732..2e3a71912e 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -17,6 +17,20 @@ Sidekiq.configure_server do |config| chain.add Gitlab::SidekiqMiddleware::ArgumentsLogger if ENV['SIDEKIQ_LOG_ARGUMENTS'] chain.add Gitlab::SidekiqMiddleware::MemoryKiller if ENV['SIDEKIQ_MEMORY_KILLER_MAX_RSS'] end + + # Sidekiq-cron: load recurring jobs from schedule.yml + schedule_file = 'config/schedule.yml' + if File.exists?(schedule_file) + Sidekiq::Cron::Job.load_from_hash YAML.load_file(schedule_file) + end + + # Database pool should be at least `sidekiq_concurrency` + 2 + # For more info, see: https://github.com/mperham/sidekiq/blob/master/4.0-Upgrade.md + config = ActiveRecord::Base.configurations[Rails.env] || + Rails.application.config.database_configuration[Rails.env] + config['pool'] = Sidekiq.options[:concurrency] + 2 + ActiveRecord::Base.establish_connection(config) + Rails.logger.debug("Connection Pool size for Sidekiq Server is now: #{ActiveRecord::Base.connection.pool.instance_variable_get('@size')}") end Sidekiq.configure_client do |config| diff --git a/config/initializers/smtp_settings.rb.sample b/config/initializers/smtp_settings.rb.sample index 25ec247a09..ec182502d4 100644 --- a/config/initializers/smtp_settings.rb.sample +++ b/config/initializers/smtp_settings.rb.sample @@ -8,7 +8,7 @@ # If you change this file in a Merge Request, please also create a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests if Rails.env.production? - Gitlab::Application.config.action_mailer.delivery_method = :smtp + Rails.application.config.action_mailer.delivery_method = :smtp ActionMailer::Base.smtp_settings = { address: "email.server.com", diff --git a/config/initializers/static_files.rb b/config/initializers/static_files.rb index e6d5600edb..d6dbf8b9fb 100644 --- a/config/initializers/static_files.rb +++ b/config/initializers/static_files.rb @@ -1,6 +1,6 @@ -app = Gitlab::Application +app = Rails.application -if app.config.serve_static_assets +if app.config.serve_static_files # The `ActionDispatch::Static` middleware intercepts requests for static files # by checking if they exist in the `/public` directory. # We're replacing it with our `Gitlab::Middleware::Static` that does the same, diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml index 22070e37f0..bd4c3ebc69 100644 --- a/config/locales/devise.en.yml +++ b/config/locales/devise.en.yml @@ -30,7 +30,6 @@ en: success: "Successfully authenticated from %{kind} account." passwords: no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided." - recently_reset: "Instructions about how to reset your password have already been sent recently. Please wait a few minutes to try again." send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes." send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes." updated: "Your password has been changed successfully. You are now signed in." diff --git a/config/locales/sherlock.en.yml b/config/locales/sherlock.en.yml index 683b09dc32..f24b825f58 100644 --- a/config/locales/sherlock.en.yml +++ b/config/locales/sherlock.en.yml @@ -35,3 +35,4 @@ en: events: Events percent: '%' count: Count + query_time: Query Time diff --git a/config/routes.rb b/config/routes.rb index ac81a2aac7..b9242327de 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,7 +1,8 @@ require 'sidekiq/web' +require 'sidekiq/cron/web' require 'api/api' -Gitlab::Application.routes.draw do +Rails.application.routes.draw do if Gitlab::Sherlock.enabled? namespace :sherlock do resources :transactions, only: [:index, :show] do @@ -23,43 +24,10 @@ Gitlab::Application.routes.draw do resource :lint, only: [:show, :create] resources :projects do - collection do - post :add - get :disabled - end - member do get :status, to: 'projects#badge' get :integration - post :toggle_shared_runners end - - resources :runner_projects, only: [:create, :destroy] - end - - resource :user_sessions do - get :auth - get :callback - end - - namespace :admin do - resources :runners, only: [:index, :show, :update, :destroy] do - member do - put :assign_all - get :resume - get :pause - end - end - - resources :events, only: [:index] - - resources :projects do - resources :runner_projects - end - - resources :builds, only: :index - - resource :application_settings, only: [:show, :update] end root to: 'projects#index' @@ -220,7 +188,7 @@ Gitlab::Application.routes.draw do namespace :admin do resources :users, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } do resources :keys, only: [:show, :destroy] - resources :identities, only: [:index, :edit, :update, :destroy] + resources :identities, except: [:show] delete 'stop_impersonation' => 'impersonation#destroy', on: :collection @@ -270,15 +238,31 @@ Gitlab::Application.routes.draw do member do put :transfer end + + resources :runner_projects end end resource :application_settings, only: [:show, :update] do resources :services + put :reset_runners_token end resources :labels + resources :runners, only: [:index, :show, :update, :destroy] do + member do + get :resume + get :pause + end + end + + resources :builds, only: :index do + collection do + post :cancel_all + end + end + root to: 'dashboard#index' end @@ -368,7 +352,7 @@ Gitlab::Application.routes.draw do end resource :avatar, only: [:destroy] - resources :milestones, only: [:index, :show, :update, :new, :create] + resources :milestones, constraints: { id: /[^\/]+/ }, only: [:index, :show, :update, :new, :create] end end @@ -457,7 +441,7 @@ Gitlab::Application.routes.draw do scope do post( - '/create_dir/*id', + '/create_dir/*id', to: 'tree#create_dir', constraints: { id: /.+/ }, as: 'create_dir' @@ -499,6 +483,7 @@ Gitlab::Application.routes.draw do member do get :commits get :ci + get :languages end end @@ -568,10 +553,12 @@ Gitlab::Application.routes.draw do resources :merge_requests, constraints: { id: /\d+/ }, except: [:destroy] do member do - get :diffs get :commits - post :merge + get :diffs + get :builds get :merge_check + post :merge + post :cancel_merge_when_build_succeeds get :ci_status post :toggle_subscription end @@ -591,18 +578,6 @@ Gitlab::Application.routes.draw do resources :protected_branches, only: [:index, :create, :update, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } resource :variables, only: [:show, :update] resources :triggers, only: [:index, :create, :destroy] - resource :ci_settings, only: [:edit, :update, :destroy] - resources :ci_web_hooks, only: [:index, :create, :destroy] do - member do - get :test - end - end - - resources :ci_services, constraints: { id: /[^\/]+/ }, only: [:index, :edit, :update] do - member do - get :test - end - end resources :builds, only: [:index, :show] do collection do @@ -681,7 +656,13 @@ Gitlab::Application.routes.draw do get :resume get :pause end + + collection do + post :toggle_shared_runners + end end + + resources :runner_projects, only: [:create, :destroy] end end end diff --git a/config/schedule.yml b/config/schedule.yml new file mode 100644 index 0000000000..993a95fef5 --- /dev/null +++ b/config/schedule.yml @@ -0,0 +1,10 @@ +# Here is a list of jobs that are scheduled to run periodically. +# We use a UNIX cron notation to specify execution schedule. +# +# Please read here for more information: +# https://github.com/ondrejbartas/sidekiq-cron#adding-cron-job + +stuck_ci_builds_worker: + cron: "0 0 * * *" + class: "StuckCiBuildsWorker" + queue: "default" diff --git a/db/migrate/20121220064453_init_schema.rb b/db/migrate/20121220064453_init_schema.rb index 90f5eb08e8..d7644b6847 100644 --- a/db/migrate/20121220064453_init_schema.rb +++ b/db/migrate/20121220064453_init_schema.rb @@ -1,6 +1,6 @@ class InitSchema < ActiveRecord::Migration def up - + create_table "events", force: true do |t| t.string "target_type" t.integer "target_id" @@ -12,14 +12,14 @@ class InitSchema < ActiveRecord::Migration t.integer "action" t.integer "author_id" end - + add_index "events", ["action"], name: "index_events_on_action", using: :btree add_index "events", ["author_id"], name: "index_events_on_author_id", using: :btree add_index "events", ["created_at"], name: "index_events_on_created_at", using: :btree add_index "events", ["project_id"], name: "index_events_on_project_id", using: :btree add_index "events", ["target_id"], name: "index_events_on_target_id", using: :btree add_index "events", ["target_type"], name: "index_events_on_target_type", using: :btree - + create_table "issues", force: true do |t| t.string "title" t.integer "assignee_id" @@ -33,7 +33,7 @@ class InitSchema < ActiveRecord::Migration t.text "description" t.integer "milestone_id" end - + add_index "issues", ["assignee_id"], name: "index_issues_on_assignee_id", using: :btree add_index "issues", ["author_id"], name: "index_issues_on_author_id", using: :btree add_index "issues", ["closed"], name: "index_issues_on_closed", using: :btree @@ -41,7 +41,7 @@ class InitSchema < ActiveRecord::Migration add_index "issues", ["milestone_id"], name: "index_issues_on_milestone_id", using: :btree add_index "issues", ["project_id"], name: "index_issues_on_project_id", using: :btree add_index "issues", ["title"], name: "index_issues_on_title", using: :btree - + create_table "keys", force: true do |t| t.integer "user_id" t.datetime "created_at" @@ -51,11 +51,11 @@ class InitSchema < ActiveRecord::Migration t.string "identifier" t.integer "project_id" end - + add_index "keys", ["identifier"], name: "index_keys_on_identifier", using: :btree add_index "keys", ["project_id"], name: "index_keys_on_project_id", using: :btree add_index "keys", ["user_id"], name: "index_keys_on_user_id", using: :btree - + create_table "merge_requests", force: true do |t| t.string "target_branch", null: false t.string "source_branch", null: false @@ -66,13 +66,13 @@ class InitSchema < ActiveRecord::Migration t.boolean "closed", default: false, null: false t.datetime "created_at" t.datetime "updated_at" - t.text "st_commits", limit: 2147483647 - t.text "st_diffs", limit: 2147483647 + t.text "st_commits" + t.text "st_diffs" t.boolean "merged", default: false, null: false t.integer "state", default: 1, null: false t.integer "milestone_id" end - + add_index "merge_requests", ["assignee_id"], name: "index_merge_requests_on_assignee_id", using: :btree add_index "merge_requests", ["author_id"], name: "index_merge_requests_on_author_id", using: :btree add_index "merge_requests", ["closed"], name: "index_merge_requests_on_closed", using: :btree @@ -82,7 +82,7 @@ class InitSchema < ActiveRecord::Migration add_index "merge_requests", ["source_branch"], name: "index_merge_requests_on_source_branch", using: :btree add_index "merge_requests", ["target_branch"], name: "index_merge_requests_on_target_branch", using: :btree add_index "merge_requests", ["title"], name: "index_merge_requests_on_title", using: :btree - + create_table "milestones", force: true do |t| t.string "title", null: false t.integer "project_id", null: false @@ -92,10 +92,10 @@ class InitSchema < ActiveRecord::Migration t.datetime "created_at" t.datetime "updated_at" end - + add_index "milestones", ["due_date"], name: "index_milestones_on_due_date", using: :btree add_index "milestones", ["project_id"], name: "index_milestones_on_project_id", using: :btree - + create_table "namespaces", force: true do |t| t.string "name", null: false t.string "path", null: false @@ -104,12 +104,12 @@ class InitSchema < ActiveRecord::Migration t.datetime "updated_at" t.string "type" end - + add_index "namespaces", ["name"], name: "index_namespaces_on_name", using: :btree add_index "namespaces", ["owner_id"], name: "index_namespaces_on_owner_id", using: :btree add_index "namespaces", ["path"], name: "index_namespaces_on_path", using: :btree add_index "namespaces", ["type"], name: "index_namespaces_on_type", using: :btree - + create_table "notes", force: true do |t| t.text "note" t.string "noteable_type" @@ -122,13 +122,13 @@ class InitSchema < ActiveRecord::Migration t.string "commit_id" t.integer "noteable_id" end - + add_index "notes", ["commit_id"], name: "index_notes_on_commit_id", using: :btree add_index "notes", ["created_at"], name: "index_notes_on_created_at", using: :btree add_index "notes", ["noteable_type"], name: "index_notes_on_noteable_type", using: :btree add_index "notes", ["project_id", "noteable_type"], name: "index_notes_on_project_id_and_noteable_type", using: :btree add_index "notes", ["project_id"], name: "index_notes_on_project_id", using: :btree - + create_table "projects", force: true do |t| t.string "name" t.string "path" @@ -144,17 +144,17 @@ class InitSchema < ActiveRecord::Migration t.boolean "wiki_enabled", default: true, null: false t.integer "namespace_id" end - + add_index "projects", ["namespace_id"], name: "index_projects_on_namespace_id", using: :btree add_index "projects", ["owner_id"], name: "index_projects_on_owner_id", using: :btree - + create_table "protected_branches", force: true do |t| t.integer "project_id", null: false t.string "name", null: false t.datetime "created_at" t.datetime "updated_at" end - + create_table "services", force: true do |t| t.string "type" t.string "title" @@ -165,9 +165,9 @@ class InitSchema < ActiveRecord::Migration t.boolean "active", default: false, null: false t.string "project_url" end - + add_index "services", ["project_id"], name: "index_services_on_project_id", using: :btree - + create_table "snippets", force: true do |t| t.string "title" t.text "content" @@ -178,11 +178,11 @@ class InitSchema < ActiveRecord::Migration t.string "file_name" t.datetime "expires_at" end - + add_index "snippets", ["created_at"], name: "index_snippets_on_created_at", using: :btree add_index "snippets", ["expires_at"], name: "index_snippets_on_expires_at", using: :btree add_index "snippets", ["project_id"], name: "index_snippets_on_project_id", using: :btree - + create_table "taggings", force: true do |t| t.integer "tag_id" t.integer "taggable_id" @@ -192,14 +192,14 @@ class InitSchema < ActiveRecord::Migration t.string "context" t.datetime "created_at" end - + add_index "taggings", ["tag_id"], name: "index_taggings_on_tag_id", using: :btree add_index "taggings", ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context", using: :btree - + create_table "tags", force: true do |t| t.string "name" end - + create_table "user_team_project_relationships", force: true do |t| t.integer "project_id" t.integer "user_team_id" @@ -207,7 +207,7 @@ class InitSchema < ActiveRecord::Migration t.datetime "created_at" t.datetime "updated_at" end - + create_table "user_team_user_relationships", force: true do |t| t.integer "user_id" t.integer "user_team_id" @@ -216,7 +216,7 @@ class InitSchema < ActiveRecord::Migration t.datetime "created_at" t.datetime "updated_at" end - + create_table "user_teams", force: true do |t| t.string "name" t.string "path" @@ -224,7 +224,7 @@ class InitSchema < ActiveRecord::Migration t.datetime "created_at" t.datetime "updated_at" end - + create_table "users", force: true do |t| t.string "email", default: "", null: false t.string "encrypted_password", default: "", null: false @@ -255,7 +255,7 @@ class InitSchema < ActiveRecord::Migration t.string "provider" t.string "username" end - + add_index "users", ["admin"], name: "index_users_on_admin", using: :btree add_index "users", ["blocked"], name: "index_users_on_blocked", using: :btree add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree @@ -263,7 +263,7 @@ class InitSchema < ActiveRecord::Migration add_index "users", ["name"], name: "index_users_on_name", using: :btree add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree add_index "users", ["username"], name: "index_users_on_username", using: :btree - + create_table "users_projects", force: true do |t| t.integer "user_id", null: false t.integer "project_id", null: false @@ -271,11 +271,11 @@ class InitSchema < ActiveRecord::Migration t.datetime "updated_at" t.integer "project_access", default: 0, null: false end - + add_index "users_projects", ["project_access"], name: "index_users_projects_on_project_access", using: :btree add_index "users_projects", ["project_id"], name: "index_users_projects_on_project_id", using: :btree add_index "users_projects", ["user_id"], name: "index_users_projects_on_user_id", using: :btree - + create_table "web_hooks", force: true do |t| t.string "url" t.integer "project_id" @@ -284,7 +284,7 @@ class InitSchema < ActiveRecord::Migration t.string "type", default: "ProjectHook" t.integer "service_id" end - + create_table "wikis", force: true do |t| t.string "title" t.text "content" @@ -294,10 +294,10 @@ class InitSchema < ActiveRecord::Migration t.string "slug" t.integer "user_id" end - + add_index "wikis", ["project_id"], name: "index_wikis_on_project_id", using: :btree add_index "wikis", ["slug"], name: "index_wikis_on_slug", using: :btree - + end def down diff --git a/db/migrate/20140122112253_create_merge_request_diffs.rb b/db/migrate/20140122112253_create_merge_request_diffs.rb index ef592305a2..f34e30925d 100644 --- a/db/migrate/20140122112253_create_merge_request_diffs.rb +++ b/db/migrate/20140122112253_create_merge_request_diffs.rb @@ -1,12 +1,21 @@ class CreateMergeRequestDiffs < ActiveRecord::Migration - def change + def up create_table :merge_request_diffs do |t| t.string :state, null: false, default: 'collected' - t.text :st_commits, null: true, limit: 2147483647 - t.text :st_diffs, null: true, limit: 2147483647 + t.text :st_commits, null: true + t.text :st_diffs, null: true t.integer :merge_request_id, null: false t.timestamps end + + if ActiveRecord::Base.configurations[Rails.env]['adapter'] =~ /^mysql/ + change_column :merge_request_diffs, :st_commits, :text, limit: 2147483647 + change_column :merge_request_diffs, :st_diffs, :text, limit: 2147483647 + end + end + + def down + drop_table :merge_request_diffs end end diff --git a/db/migrate/20140903115954_migrate_to_new_shell.rb b/db/migrate/20140903115954_migrate_to_new_shell.rb index 2d83210951..54cbe48960 100644 --- a/db/migrate/20140903115954_migrate_to_new_shell.rb +++ b/db/migrate/20140903115954_migrate_to_new_shell.rb @@ -1,5 +1,7 @@ class MigrateToNewShell < ActiveRecord::Migration def change + return if Rails.env.test? + gitlab_shell_path = Gitlab.config.gitlab_shell.path if system("#{gitlab_shell_path}/bin/create-hooks") puts 'Repositories updated with new hooks' diff --git a/db/migrate/20151012173029_set_jira_service_api_url.rb b/db/migrate/20151012173029_set_jira_service_api_url.rb new file mode 100644 index 0000000000..2af99e0db0 --- /dev/null +++ b/db/migrate/20151012173029_set_jira_service_api_url.rb @@ -0,0 +1,50 @@ +class SetJiraServiceApiUrl < ActiveRecord::Migration + # This migration can be performed online without errors, but some Jira API calls may be missed + # when doing so because api_url is not yet available. + + def build_api_url_from_project_url(project_url, api_version) + # this is the exact logic previously used to build the Jira API URL from project_url + server = URI(project_url) + default_ports = [80, 443].include?(server.port) + server_url = "#{server.scheme}://#{server.host}" + server_url.concat(":#{server.port}") unless default_ports + "#{server_url}/rest/api/#{api_version}" + end + + def get_api_version_from_api_url(api_url) + match = /\/rest\/api\/(?\w+)$/.match(api_url) + match && match['api_version'] + end + + def change + reversible do |dir| + select_all("SELECT id, properties FROM services WHERE services.type IN ('JiraService')").each do |jira_service| + id = jira_service["id"] + properties = JSON.parse(jira_service["properties"]) + properties_was = properties.clone + + dir.up do + # remove api_version and set api_url + if properties['api_version'].present? && properties['project_url'].present? + begin + properties['api_url'] ||= build_api_url_from_project_url(properties['project_url'], properties['api_version']) + rescue + # looks like project_url was not a valid URL. Do nothing. + end + end + properties.delete('api_version') if properties.include?('api_version') + end + + dir.down do + # remove api_url and set api_version (default to '2') + properties['api_version'] ||= get_api_version_from_api_url(properties['api_url']) || '2' + properties.delete('api_url') if properties.include?('api_url') + end + + if properties != properties_was + execute("UPDATE services SET properties = '#{quote_string(properties.to_json)}' WHERE id = #{id}") + end + end + end + end +end diff --git a/db/migrate/20151028152939_add_merge_when_build_succeeds_to_merge_request.rb b/db/migrate/20151028152939_add_merge_when_build_succeeds_to_merge_request.rb new file mode 100644 index 0000000000..ceb52f0c22 --- /dev/null +++ b/db/migrate/20151028152939_add_merge_when_build_succeeds_to_merge_request.rb @@ -0,0 +1,7 @@ +class AddMergeWhenBuildSucceedsToMergeRequest < ActiveRecord::Migration + def change + add_column :merge_requests, :merge_params, :text + add_column :merge_requests, :merge_when_build_succeeds, :boolean, default: false, null: false + add_column :merge_requests, :merge_user_id, :integer + end +end diff --git a/db/migrate/20151109134526_add_issues_state_index.rb b/db/migrate/20151109134526_add_issues_state_index.rb new file mode 100644 index 0000000000..1c4d2e3017 --- /dev/null +++ b/db/migrate/20151109134526_add_issues_state_index.rb @@ -0,0 +1,5 @@ +class AddIssuesStateIndex < ActiveRecord::Migration + def change + add_index :issues, :state + end +end diff --git a/db/migrate/20151109134916_add_projects_visibility_level_index.rb b/db/migrate/20151109134916_add_projects_visibility_level_index.rb new file mode 100644 index 0000000000..600b4bafd9 --- /dev/null +++ b/db/migrate/20151109134916_add_projects_visibility_level_index.rb @@ -0,0 +1,5 @@ +class AddProjectsVisibilityLevelIndex < ActiveRecord::Migration + def change + add_index :projects, :visibility_level + end +end diff --git a/db/migrate/20151203162133_add_hide_project_limit_to_users.rb b/db/migrate/20151203162133_add_hide_project_limit_to_users.rb new file mode 100644 index 0000000000..6ffadfa189 --- /dev/null +++ b/db/migrate/20151203162133_add_hide_project_limit_to_users.rb @@ -0,0 +1,5 @@ +class AddHideProjectLimitToUsers < ActiveRecord::Migration + def change + add_column :users, :hide_project_limit, :boolean, default: false + end +end diff --git a/db/migrate/20151203162134_add_build_events_to_services.rb b/db/migrate/20151203162134_add_build_events_to_services.rb new file mode 100644 index 0000000000..a84be7db3f --- /dev/null +++ b/db/migrate/20151203162134_add_build_events_to_services.rb @@ -0,0 +1,6 @@ +class AddBuildEventsToServices < ActiveRecord::Migration + def up + add_column :services, :build_events, :boolean, default: false, null: false + add_column :web_hooks, :build_events, :boolean, default: false, null: false + end +end diff --git a/db/migrate/20151209144329_migrate_ci_web_hooks.rb b/db/migrate/20151209144329_migrate_ci_web_hooks.rb new file mode 100644 index 0000000000..825ba1973f --- /dev/null +++ b/db/migrate/20151209144329_migrate_ci_web_hooks.rb @@ -0,0 +1,13 @@ +class MigrateCiWebHooks < ActiveRecord::Migration + include Gitlab::Database + + def up + execute( + 'INSERT INTO web_hooks (url, project_id, type, created_at, updated_at, push_events, issues_events, merge_requests_events, tag_push_events, note_events, build_events) ' \ + "SELECT ci_web_hooks.url, projects.id, 'ProjectHook', ci_web_hooks.created_at, ci_web_hooks.updated_at, " \ + "#{false_value}, #{false_value}, #{false_value}, #{false_value}, #{false_value}, #{true_value} FROM ci_web_hooks " \ + 'JOIN ci_projects ON ci_web_hooks.project_id = ci_projects.id ' \ + 'JOIN projects ON ci_projects.gitlab_id = projects.id' + ) + end +end diff --git a/db/migrate/20151209145909_migrate_ci_emails.rb b/db/migrate/20151209145909_migrate_ci_emails.rb new file mode 100644 index 0000000000..7f330a2cf0 --- /dev/null +++ b/db/migrate/20151209145909_migrate_ci_emails.rb @@ -0,0 +1,45 @@ +class MigrateCiEmails < ActiveRecord::Migration + include Gitlab::Database + + def up + # This inserts a new service: BuildsEmailService + # It "manually" constructs the properties (JSON-encoded) + # Migrating all ci_projects e-mail related columns + execute( + 'INSERT INTO services (project_id, type, created_at, updated_at, active, push_events, issues_events, merge_requests_events, tag_push_events, note_events, build_events, properties) ' \ + "SELECT projects.id, 'BuildsEmailService', ci_services.created_at, ci_services.updated_at, " \ + "#{true_value}, #{false_value}, #{false_value}, #{false_value}, #{false_value}, #{false_value}, #{true_value}, " \ + "CONCAT('{\"notify_only_broken_builds\":\"', #{convert_bool('ci_projects.email_only_broken_builds')}, " \ + "'\",\"add_pusher\":\"', #{convert_bool('ci_projects.email_add_pusher')}, " \ + "'\",\"recipients\":\"', #{escape_text('ci_projects.email_recipients')}, " \ + "'\"}') " \ + 'FROM ci_services ' \ + 'JOIN ci_projects ON ci_services.project_id = ci_projects.id ' \ + 'JOIN projects ON ci_projects.gitlab_id = projects.id ' \ + "WHERE ci_services.type = 'Ci::MailService' AND ci_services.active" + ) + end + + def down + end + + # This function escapes double-quotes and slash + def escape_text(name) + if Gitlab::Database.postgresql? + "REPLACE(REPLACE(#{name}, '\\', '\\\\'), '\"', '\\\"')" + else + "REPLACE(REPLACE(#{name}, '\\\\', '\\\\\\\\'), '\\\"', '\\\\\\\"')" + end + end + + # This function returns 0 or 1 for column + def convert_bool(name) + if Gitlab::Database.postgresql? + # PostgreSQL uses BOOLEAN type + "CASE WHEN #{name} IS TRUE THEN '1' ELSE '0' END" + else + # MySQL uses TINYINT + "#{name}" + end + end +end diff --git a/db/migrate/20151210030143_add_unlock_token_to_user.rb b/db/migrate/20151210030143_add_unlock_token_to_user.rb new file mode 100644 index 0000000000..0ea66ba65d --- /dev/null +++ b/db/migrate/20151210030143_add_unlock_token_to_user.rb @@ -0,0 +1,5 @@ +class AddUnlockTokenToUser < ActiveRecord::Migration + def change + add_column :users, :unlock_token, :string + end +end diff --git a/db/migrate/20151210072243_add_runners_registration_token_to_application_settings.rb b/db/migrate/20151210072243_add_runners_registration_token_to_application_settings.rb new file mode 100644 index 0000000000..00f88180e4 --- /dev/null +++ b/db/migrate/20151210072243_add_runners_registration_token_to_application_settings.rb @@ -0,0 +1,5 @@ +class AddRunnersRegistrationTokenToApplicationSettings < ActiveRecord::Migration + def change + add_column :application_settings, :runners_registration_token, :string + end +end diff --git a/db/migrate/20151210125232_migrate_ci_slack_service.rb b/db/migrate/20151210125232_migrate_ci_slack_service.rb new file mode 100644 index 0000000000..f14efa3e95 --- /dev/null +++ b/db/migrate/20151210125232_migrate_ci_slack_service.rb @@ -0,0 +1,33 @@ +class MigrateCiSlackService < ActiveRecord::Migration + include Gitlab::Database + + def up + properties_query = 'SELECT properties FROM ci_services ' \ + 'JOIN ci_projects ON ci_services.project_id=ci_projects.id ' \ + "WHERE ci_projects.gitlab_id=services.project_id AND ci_services.type='Ci::SlackService' AND ci_services.active " \ + 'LIMIT 1' + + active_query = 'SELECT 1 FROM ci_services ' \ + 'JOIN ci_projects ON ci_services.project_id=ci_projects.id ' \ + "WHERE ci_projects.gitlab_id=services.project_id AND ci_services.type='Ci::SlackService' AND ci_services.active " \ + 'LIMIT 1' + + # We update the service since services are always generated for project, even if they are inactive + # Activate service and migrate properties if currently the service is not active + execute( + "UPDATE services SET properties=(#{properties_query}), active=#{true_value}, " \ + "push_events=#{false_value}, issues_events=#{false_value}, merge_requests_events=#{false_value}, " \ + "tag_push_events=#{false_value}, note_events=#{false_value}, build_events=#{true_value} " \ + "WHERE NOT services.active AND services.type='SlackService' AND (#{active_query}) IS NOT NULL" + ) + + # Tick only build_events if the service is already active + execute( + "UPDATE services SET build_events=#{true_value} " \ + "WHERE services.active AND services.type='SlackService' AND (#{active_query}) IS NOT NULL" + ) + end + + def down + end +end diff --git a/db/migrate/20151210125927_migrate_ci_hip_chat_service.rb b/db/migrate/20151210125927_migrate_ci_hip_chat_service.rb new file mode 100644 index 0000000000..b9e0432357 --- /dev/null +++ b/db/migrate/20151210125927_migrate_ci_hip_chat_service.rb @@ -0,0 +1,34 @@ +class MigrateCiHipChatService < ActiveRecord::Migration + include Gitlab::Database + + def up + # From properties strip `hipchat_` key + properties_query = "SELECT REPLACE(properties, '\"hipchat_', '\"') FROM ci_services " \ + 'JOIN ci_projects ON ci_services.project_id=ci_projects.id ' \ + "WHERE ci_projects.gitlab_id=services.project_id AND ci_services.type='Ci::HipChatService' AND ci_services.active " \ + 'LIMIT 1' + + active_query = 'SELECT 1 FROM ci_services ' \ + 'JOIN ci_projects ON ci_services.project_id=ci_projects.id ' \ + "WHERE ci_projects.gitlab_id=services.project_id AND ci_services.type='Ci::HipChatService' AND ci_services.active " \ + 'LIMIT 1' + + # We update the service since services are always generated for project, even if they are inactive + # Activate service and migrate properties if currently the service is not active + execute( + "UPDATE services SET properties=(#{properties_query}), active=#{true_value}, " \ + "push_events=#{false_value}, issues_events=#{false_value}, merge_requests_events=#{false_value}, " \ + "tag_push_events=#{false_value}, note_events=#{false_value}, build_events=#{true_value} " \ + "WHERE NOT services.active AND services.type='HipchatService' AND (#{active_query}) IS NOT NULL" + ) + + # Tick only build_events if the service is already active + execute( + "UPDATE services SET build_events=#{true_value} " \ + "WHERE services.active AND services.type='HipchatService' AND (#{active_query}) IS NOT NULL" + ) + end + + def down + end +end diff --git a/db/migrate/20151210125928_add_ci_to_project.rb b/db/migrate/20151210125928_add_ci_to_project.rb new file mode 100644 index 0000000000..8a65abab63 --- /dev/null +++ b/db/migrate/20151210125928_add_ci_to_project.rb @@ -0,0 +1,11 @@ +class AddCiToProject < ActiveRecord::Migration + def up + add_column :projects, :ci_id, :integer + add_column :projects, :builds_enabled, :boolean, default: true, null: false + add_column :projects, :shared_runners_enabled, :boolean, default: true, null: false + add_column :projects, :runners_token, :string + add_column :projects, :build_coverage_regex, :string + add_column :projects, :build_allow_git_fetch, :boolean, default: true, null: false + add_column :projects, :build_timeout, :integer, default: 3600, null: false + end +end diff --git a/db/migrate/20151210125929_add_project_id_to_ci.rb b/db/migrate/20151210125929_add_project_id_to_ci.rb new file mode 100644 index 0000000000..5d1cf54357 --- /dev/null +++ b/db/migrate/20151210125929_add_project_id_to_ci.rb @@ -0,0 +1,8 @@ +class AddProjectIdToCi < ActiveRecord::Migration + def up + add_column :ci_builds, :gl_project_id, :integer + add_column :ci_runner_projects, :gl_project_id, :integer + add_column :ci_triggers, :gl_project_id, :integer + add_column :ci_variables, :gl_project_id, :integer + end +end diff --git a/db/migrate/20151210125930_migrate_ci_to_project.rb b/db/migrate/20151210125930_migrate_ci_to_project.rb new file mode 100644 index 0000000000..7527899786 --- /dev/null +++ b/db/migrate/20151210125930_migrate_ci_to_project.rb @@ -0,0 +1,38 @@ +class MigrateCiToProject < ActiveRecord::Migration + def up + migrate_project_id_for_table('ci_runner_projects') + migrate_project_id_for_table('ci_triggers') + migrate_project_id_for_table('ci_variables') + migrate_project_id_for_builds + + migrate_project_column('id', 'ci_id') + migrate_project_column('shared_runners_enabled', 'shared_runners_enabled') + migrate_project_column('token', 'runners_token') + migrate_project_column('coverage_regex', 'build_coverage_regex') + migrate_project_column('allow_git_fetch', 'build_allow_git_fetch') + migrate_project_column('timeout', 'build_timeout') + migrate_ci_service + end + + def migrate_project_id_for_table(table) + subquery = "SELECT gitlab_id FROM ci_projects WHERE ci_projects.id = #{table}.project_id" + execute("UPDATE #{table} SET gl_project_id=(#{subquery}) WHERE gl_project_id IS NULL") + end + + def migrate_project_id_for_builds + subquery = 'SELECT gl_project_id FROM ci_commits WHERE ci_commits.id = ci_builds.commit_id' + execute("UPDATE ci_builds SET gl_project_id=(#{subquery}) WHERE gl_project_id IS NULL") + end + + def migrate_project_column(column, new_column = nil) + new_column ||= column + subquery = "SELECT ci_projects.#{column} FROM ci_projects WHERE projects.id = ci_projects.gitlab_id " \ + 'ORDER BY ci_projects.updated_at DESC LIMIT 1' + execute("UPDATE projects SET #{new_column}=(#{subquery}) WHERE (#{subquery}) IS NOT NULL") + end + + def migrate_ci_service + subquery = "SELECT active FROM services WHERE projects.id = services.project_id AND type='GitlabCiService' LIMIT 1" + execute("UPDATE projects SET builds_enabled=(#{subquery}) WHERE (#{subquery}) IS NOT NULL") + end +end diff --git a/db/migrate/20151210125931_add_index_to_ci_tables.rb b/db/migrate/20151210125931_add_index_to_ci_tables.rb new file mode 100644 index 0000000000..9fedb5d612 --- /dev/null +++ b/db/migrate/20151210125931_add_index_to_ci_tables.rb @@ -0,0 +1,12 @@ +class AddIndexToCiTables < ActiveRecord::Migration + def up + add_index :ci_builds, :gl_project_id + add_index :ci_runner_projects, :gl_project_id + add_index :ci_triggers, :gl_project_id + add_index :ci_variables, :gl_project_id + add_index :projects, :runners_token + add_index :projects, :builds_enabled + add_index :projects, [:builds_enabled, :shared_runners_enabled] + add_index :projects, [:ci_id] + end +end diff --git a/db/migrate/20151210125932_drop_null_for_ci_tables.rb b/db/migrate/20151210125932_drop_null_for_ci_tables.rb new file mode 100644 index 0000000000..0b007430b0 --- /dev/null +++ b/db/migrate/20151210125932_drop_null_for_ci_tables.rb @@ -0,0 +1,9 @@ +class DropNullForCiTables < ActiveRecord::Migration + def up + remove_index :ci_variables, :project_id + remove_index :ci_runner_projects, :project_id + change_column_null :ci_triggers, :project_id, true + change_column_null :ci_variables, :project_id, true + change_column_null :ci_runner_projects, :project_id, true + end +end diff --git a/db/schema.rb b/db/schema.rb index 80e9405f6f..60b42f7a47 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,12 +11,12 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20151118162244) do +ActiveRecord::Schema.define(version: 20151210125932) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" - create_table "abuse_reports", force: true do |t| + create_table "abuse_reports", force: :cascade do |t| t.integer "reporter_id" t.integer "user_id" t.text "message" @@ -24,7 +24,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do t.datetime "updated_at" end - create_table "application_settings", force: true do |t| + create_table "application_settings", force: :cascade do |t| t.integer "default_projects_limit" t.boolean "signup_enabled" t.boolean "signin_enabled" @@ -49,9 +49,10 @@ ActiveRecord::Schema.define(version: 20151118162244) do t.string "admin_notification_email" t.boolean "shared_runners_enabled", default: true, null: false t.integer "max_artifacts_size", default: 100, null: false + t.string "runners_registration_token" end - create_table "audit_events", force: true do |t| + create_table "audit_events", force: :cascade do |t| t.integer "author_id", null: false t.string "type", null: false t.integer "entity_id", null: false @@ -65,7 +66,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "audit_events", ["entity_id", "entity_type"], name: "index_audit_events_on_entity_id_and_entity_type", using: :btree add_index "audit_events", ["type"], name: "index_audit_events_on_type", using: :btree - create_table "broadcast_messages", force: true do |t| + create_table "broadcast_messages", force: :cascade do |t| t.text "message", null: false t.datetime "starts_at" t.datetime "ends_at" @@ -76,14 +77,14 @@ ActiveRecord::Schema.define(version: 20151118162244) do t.string "font" end - create_table "ci_application_settings", force: true do |t| + create_table "ci_application_settings", force: :cascade do |t| t.boolean "all_broken_builds" t.boolean "add_pusher" t.datetime "created_at" t.datetime "updated_at" end - create_table "ci_builds", force: true do |t| + create_table "ci_builds", force: :cascade do |t| t.integer "project_id" t.string "status" t.datetime "finished_at" @@ -110,6 +111,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do t.string "target_url" t.string "description" t.text "artifacts_file" + t.integer "gl_project_id" end add_index "ci_builds", ["commit_id", "stage_idx", "created_at"], name: "index_ci_builds_on_commit_id_and_stage_idx_and_created_at", using: :btree @@ -117,13 +119,14 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "ci_builds", ["commit_id", "type", "name", "ref"], name: "index_ci_builds_on_commit_id_and_type_and_name_and_ref", using: :btree add_index "ci_builds", ["commit_id", "type", "ref"], name: "index_ci_builds_on_commit_id_and_type_and_ref", using: :btree add_index "ci_builds", ["commit_id"], name: "index_ci_builds_on_commit_id", using: :btree + add_index "ci_builds", ["gl_project_id"], name: "index_ci_builds_on_gl_project_id", using: :btree add_index "ci_builds", ["project_id", "commit_id"], name: "index_ci_builds_on_project_id_and_commit_id", using: :btree add_index "ci_builds", ["project_id"], name: "index_ci_builds_on_project_id", using: :btree add_index "ci_builds", ["runner_id"], name: "index_ci_builds_on_runner_id", using: :btree add_index "ci_builds", ["status"], name: "index_ci_builds_on_status", using: :btree add_index "ci_builds", ["type"], name: "index_ci_builds_on_type", using: :btree - create_table "ci_commits", force: true do |t| + create_table "ci_commits", force: :cascade do |t| t.integer "project_id" t.string "ref" t.string "sha" @@ -144,7 +147,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "ci_commits", ["project_id"], name: "index_ci_commits_on_project_id", using: :btree add_index "ci_commits", ["sha"], name: "index_ci_commits_on_sha", using: :btree - create_table "ci_events", force: true do |t| + create_table "ci_events", force: :cascade do |t| t.integer "project_id" t.integer "user_id" t.integer "is_admin" @@ -157,7 +160,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "ci_events", ["is_admin"], name: "index_ci_events_on_is_admin", using: :btree add_index "ci_events", ["project_id"], name: "index_ci_events_on_project_id", using: :btree - create_table "ci_jobs", force: true do |t| + create_table "ci_jobs", force: :cascade do |t| t.integer "project_id", null: false t.text "commands" t.boolean "active", default: true, null: false @@ -174,7 +177,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "ci_jobs", ["deleted_at"], name: "index_ci_jobs_on_deleted_at", using: :btree add_index "ci_jobs", ["project_id"], name: "index_ci_jobs_on_project_id", using: :btree - create_table "ci_projects", force: true do |t| + create_table "ci_projects", force: :cascade do |t| t.string "name" t.integer "timeout", default: 3600, null: false t.datetime "created_at" @@ -200,17 +203,18 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "ci_projects", ["gitlab_id"], name: "index_ci_projects_on_gitlab_id", using: :btree add_index "ci_projects", ["shared_runners_enabled"], name: "index_ci_projects_on_shared_runners_enabled", using: :btree - create_table "ci_runner_projects", force: true do |t| - t.integer "runner_id", null: false - t.integer "project_id", null: false + create_table "ci_runner_projects", force: :cascade do |t| + t.integer "runner_id", null: false + t.integer "project_id" t.datetime "created_at" t.datetime "updated_at" + t.integer "gl_project_id" end - add_index "ci_runner_projects", ["project_id"], name: "index_ci_runner_projects_on_project_id", using: :btree + add_index "ci_runner_projects", ["gl_project_id"], name: "index_ci_runner_projects_on_gl_project_id", using: :btree add_index "ci_runner_projects", ["runner_id"], name: "index_ci_runner_projects_on_runner_id", using: :btree - create_table "ci_runners", force: true do |t| + create_table "ci_runners", force: :cascade do |t| t.string "token" t.datetime "created_at" t.datetime "updated_at" @@ -225,7 +229,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do t.string "architecture" end - create_table "ci_services", force: true do |t| + create_table "ci_services", force: :cascade do |t| t.string "type" t.string "title" t.integer "project_id", null: false @@ -237,7 +241,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "ci_services", ["project_id"], name: "index_ci_services_on_project_id", using: :btree - create_table "ci_sessions", force: true do |t| + create_table "ci_sessions", force: :cascade do |t| t.string "session_id", null: false t.text "data" t.datetime "created_at" @@ -247,7 +251,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "ci_sessions", ["session_id"], name: "index_ci_sessions_on_session_id", using: :btree add_index "ci_sessions", ["updated_at"], name: "index_ci_sessions_on_updated_at", using: :btree - create_table "ci_taggings", force: true do |t| + create_table "ci_taggings", force: :cascade do |t| t.integer "tag_id" t.integer "taggable_id" t.string "taggable_type" @@ -260,14 +264,14 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "ci_taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "ci_taggings_idx", unique: true, using: :btree add_index "ci_taggings", ["taggable_id", "taggable_type", "context"], name: "index_ci_taggings_on_taggable_id_and_taggable_type_and_context", using: :btree - create_table "ci_tags", force: true do |t| + create_table "ci_tags", force: :cascade do |t| t.string "name" t.integer "taggings_count", default: 0 end add_index "ci_tags", ["name"], name: "index_ci_tags_on_name", unique: true, using: :btree - create_table "ci_trigger_requests", force: true do |t| + create_table "ci_trigger_requests", force: :cascade do |t| t.integer "trigger_id", null: false t.text "variables" t.datetime "created_at" @@ -275,35 +279,38 @@ ActiveRecord::Schema.define(version: 20151118162244) do t.integer "commit_id" end - create_table "ci_triggers", force: true do |t| + create_table "ci_triggers", force: :cascade do |t| t.string "token" - t.integer "project_id", null: false + t.integer "project_id" t.datetime "deleted_at" t.datetime "created_at" t.datetime "updated_at" + t.integer "gl_project_id" end add_index "ci_triggers", ["deleted_at"], name: "index_ci_triggers_on_deleted_at", using: :btree + add_index "ci_triggers", ["gl_project_id"], name: "index_ci_triggers_on_gl_project_id", using: :btree - create_table "ci_variables", force: true do |t| - t.integer "project_id", null: false + create_table "ci_variables", force: :cascade do |t| + t.integer "project_id" t.string "key" t.text "value" t.text "encrypted_value" t.string "encrypted_value_salt" t.string "encrypted_value_iv" + t.integer "gl_project_id" end - add_index "ci_variables", ["project_id"], name: "index_ci_variables_on_project_id", using: :btree + add_index "ci_variables", ["gl_project_id"], name: "index_ci_variables_on_gl_project_id", using: :btree - create_table "ci_web_hooks", force: true do |t| + create_table "ci_web_hooks", force: :cascade do |t| t.string "url", null: false t.integer "project_id", null: false t.datetime "created_at" t.datetime "updated_at" end - create_table "deploy_keys_projects", force: true do |t| + create_table "deploy_keys_projects", force: :cascade do |t| t.integer "deploy_key_id", null: false t.integer "project_id", null: false t.datetime "created_at" @@ -312,7 +319,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "deploy_keys_projects", ["project_id"], name: "index_deploy_keys_projects_on_project_id", using: :btree - create_table "emails", force: true do |t| + create_table "emails", force: :cascade do |t| t.integer "user_id", null: false t.string "email", null: false t.datetime "created_at" @@ -322,7 +329,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "emails", ["email"], name: "index_emails_on_email", unique: true, using: :btree add_index "emails", ["user_id"], name: "index_emails_on_user_id", using: :btree - create_table "events", force: true do |t| + create_table "events", force: :cascade do |t| t.string "target_type" t.integer "target_id" t.string "title" @@ -341,7 +348,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "events", ["target_id"], name: "index_events_on_target_id", using: :btree add_index "events", ["target_type"], name: "index_events_on_target_type", using: :btree - create_table "forked_project_links", force: true do |t| + create_table "forked_project_links", force: :cascade do |t| t.integer "forked_to_project_id", null: false t.integer "forked_from_project_id", null: false t.datetime "created_at" @@ -350,7 +357,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "forked_project_links", ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree - create_table "identities", force: true do |t| + create_table "identities", force: :cascade do |t| t.string "extern_uid" t.string "provider" t.integer "user_id" @@ -361,7 +368,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "identities", ["created_at", "id"], name: "index_identities_on_created_at_and_id", using: :btree add_index "identities", ["user_id"], name: "index_identities_on_user_id", using: :btree - create_table "issues", force: true do |t| + create_table "issues", force: :cascade do |t| t.string "title" t.integer "assignee_id" t.integer "author_id" @@ -384,9 +391,10 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "issues", ["milestone_id"], name: "index_issues_on_milestone_id", using: :btree add_index "issues", ["project_id", "iid"], name: "index_issues_on_project_id_and_iid", unique: true, using: :btree add_index "issues", ["project_id"], name: "index_issues_on_project_id", using: :btree + add_index "issues", ["state"], name: "index_issues_on_state", using: :btree add_index "issues", ["title"], name: "index_issues_on_title", using: :btree - create_table "keys", force: true do |t| + create_table "keys", force: :cascade do |t| t.integer "user_id" t.datetime "created_at" t.datetime "updated_at" @@ -400,7 +408,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "keys", ["created_at", "id"], name: "index_keys_on_created_at_and_id", using: :btree add_index "keys", ["user_id"], name: "index_keys_on_user_id", using: :btree - create_table "label_links", force: true do |t| + create_table "label_links", force: :cascade do |t| t.integer "label_id" t.integer "target_id" t.string "target_type" @@ -411,7 +419,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "label_links", ["label_id"], name: "index_label_links_on_label_id", using: :btree add_index "label_links", ["target_id", "target_type"], name: "index_label_links_on_target_id_and_target_type", using: :btree - create_table "labels", force: true do |t| + create_table "labels", force: :cascade do |t| t.string "title" t.string "color" t.integer "project_id" @@ -422,7 +430,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "labels", ["project_id"], name: "index_labels_on_project_id", using: :btree - create_table "lfs_objects", force: true do |t| + create_table "lfs_objects", force: :cascade do |t| t.string "oid", null: false t.integer "size", null: false t.datetime "created_at" @@ -432,7 +440,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "lfs_objects", ["oid"], name: "index_lfs_objects_on_oid", unique: true, using: :btree - create_table "lfs_objects_projects", force: true do |t| + create_table "lfs_objects_projects", force: :cascade do |t| t.integer "lfs_object_id", null: false t.integer "project_id", null: false t.datetime "created_at" @@ -441,7 +449,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "lfs_objects_projects", ["project_id"], name: "index_lfs_objects_projects_on_project_id", using: :btree - create_table "members", force: true do |t| + create_table "members", force: :cascade do |t| t.integer "access_level", null: false t.integer "source_id", null: false t.string "source_type", null: false @@ -463,7 +471,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "members", ["type"], name: "index_members_on_type", using: :btree add_index "members", ["user_id"], name: "index_members_on_user_id", using: :btree - create_table "merge_request_diffs", force: true do |t| + create_table "merge_request_diffs", force: :cascade do |t| t.string "state" t.text "st_commits" t.text "st_diffs" @@ -474,10 +482,10 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "merge_request_diffs", ["merge_request_id"], name: "index_merge_request_diffs_on_merge_request_id", unique: true, using: :btree - create_table "merge_requests", force: true do |t| - t.string "target_branch", null: false - t.string "source_branch", null: false - t.integer "source_project_id", null: false + create_table "merge_requests", force: :cascade do |t| + t.string "target_branch", null: false + t.string "source_branch", null: false + t.integer "source_project_id", null: false t.integer "author_id" t.integer "assignee_id" t.string "title" @@ -486,13 +494,16 @@ ActiveRecord::Schema.define(version: 20151118162244) do t.integer "milestone_id" t.string "state" t.string "merge_status" - t.integer "target_project_id", null: false + t.integer "target_project_id", null: false t.integer "iid" t.text "description" - t.integer "position", default: 0 + t.integer "position", default: 0 t.datetime "locked_at" t.integer "updated_by_id" t.string "merge_error" + t.text "merge_params" + t.boolean "merge_when_build_succeeds", default: false, null: false + t.integer "merge_user_id" end add_index "merge_requests", ["assignee_id"], name: "index_merge_requests_on_assignee_id", using: :btree @@ -506,7 +517,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "merge_requests", ["target_project_id", "iid"], name: "index_merge_requests_on_target_project_id_and_iid", unique: true, using: :btree add_index "merge_requests", ["title"], name: "index_merge_requests_on_title", using: :btree - create_table "milestones", force: true do |t| + create_table "milestones", force: :cascade do |t| t.string "title", null: false t.integer "project_id", null: false t.text "description" @@ -522,7 +533,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "milestones", ["project_id", "iid"], name: "index_milestones_on_project_id_and_iid", unique: true, using: :btree add_index "milestones", ["project_id"], name: "index_milestones_on_project_id", using: :btree - create_table "namespaces", force: true do |t| + create_table "namespaces", force: :cascade do |t| t.string "name", null: false t.string "path", null: false t.integer "owner_id" @@ -541,7 +552,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "namespaces", ["public"], name: "index_namespaces_on_public", using: :btree add_index "namespaces", ["type"], name: "index_namespaces_on_type", using: :btree - create_table "notes", force: true do |t| + create_table "notes", force: :cascade do |t| t.text "note" t.string "noteable_type" t.integer "author_id" @@ -570,7 +581,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "notes", ["project_id"], name: "index_notes_on_project_id", using: :btree add_index "notes", ["updated_at"], name: "index_notes_on_updated_at", using: :btree - create_table "oauth_access_grants", force: true do |t| + create_table "oauth_access_grants", force: :cascade do |t| t.integer "resource_owner_id", null: false t.integer "application_id", null: false t.string "token", null: false @@ -583,7 +594,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "oauth_access_grants", ["token"], name: "index_oauth_access_grants_on_token", unique: true, using: :btree - create_table "oauth_access_tokens", force: true do |t| + create_table "oauth_access_tokens", force: :cascade do |t| t.integer "resource_owner_id" t.integer "application_id" t.string "token", null: false @@ -598,7 +609,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "oauth_access_tokens", ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id", using: :btree add_index "oauth_access_tokens", ["token"], name: "index_oauth_access_tokens_on_token", unique: true, using: :btree - create_table "oauth_applications", force: true do |t| + create_table "oauth_applications", force: :cascade do |t| t.string "name", null: false t.string "uid", null: false t.string "secret", null: false @@ -613,12 +624,12 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "oauth_applications", ["owner_id", "owner_type"], name: "index_oauth_applications_on_owner_id_and_owner_type", using: :btree add_index "oauth_applications", ["uid"], name: "index_oauth_applications_on_uid", unique: true, using: :btree - create_table "project_import_data", force: true do |t| + create_table "project_import_data", force: :cascade do |t| t.integer "project_id" t.text "data" end - create_table "projects", force: true do |t| + create_table "projects", force: :cascade do |t| t.string "name" t.string "path" t.text "description" @@ -643,20 +654,30 @@ ActiveRecord::Schema.define(version: 20151118162244) do t.integer "star_count", default: 0, null: false t.string "import_type" t.string "import_source" - t.integer "commit_count", default: 0 - t.boolean "merge_requests_ff_only_enabled", default: false - t.text "issues_template" + t.integer "commit_count", default: 0 t.text "import_error" + t.integer "ci_id" + t.boolean "builds_enabled", default: true, null: false + t.boolean "shared_runners_enabled", default: true, null: false + t.string "runners_token" + t.string "build_coverage_regex" + t.boolean "build_allow_git_fetch", default: true, null: false + t.integer "build_timeout", default: 3600, null: false end + add_index "projects", ["builds_enabled", "shared_runners_enabled"], name: "index_projects_on_builds_enabled_and_shared_runners_enabled", using: :btree + add_index "projects", ["builds_enabled"], name: "index_projects_on_builds_enabled", using: :btree + add_index "projects", ["ci_id"], name: "index_projects_on_ci_id", using: :btree add_index "projects", ["created_at", "id"], name: "index_projects_on_created_at_and_id", using: :btree add_index "projects", ["creator_id"], name: "index_projects_on_creator_id", using: :btree add_index "projects", ["last_activity_at"], name: "index_projects_on_last_activity_at", using: :btree add_index "projects", ["namespace_id"], name: "index_projects_on_namespace_id", using: :btree add_index "projects", ["path"], name: "index_projects_on_path", using: :btree + add_index "projects", ["runners_token"], name: "index_projects_on_runners_token", using: :btree add_index "projects", ["star_count"], name: "index_projects_on_star_count", using: :btree + add_index "projects", ["visibility_level"], name: "index_projects_on_visibility_level", using: :btree - create_table "protected_branches", force: true do |t| + create_table "protected_branches", force: :cascade do |t| t.integer "project_id", null: false t.string "name", null: false t.datetime "created_at" @@ -666,7 +687,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "protected_branches", ["project_id"], name: "index_protected_branches_on_project_id", using: :btree - create_table "releases", force: true do |t| + create_table "releases", force: :cascade do |t| t.string "tag" t.text "description" t.integer "project_id" @@ -677,7 +698,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "releases", ["project_id", "tag"], name: "index_releases_on_project_id_and_tag", using: :btree add_index "releases", ["project_id"], name: "index_releases_on_project_id", using: :btree - create_table "sent_notifications", force: true do |t| + create_table "sent_notifications", force: :cascade do |t| t.integer "project_id" t.integer "noteable_id" t.string "noteable_type" @@ -689,7 +710,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "sent_notifications", ["reply_key"], name: "index_sent_notifications_on_reply_key", unique: true, using: :btree - create_table "services", force: true do |t| + create_table "services", force: :cascade do |t| t.string "type" t.string "title" t.integer "project_id" @@ -703,13 +724,14 @@ ActiveRecord::Schema.define(version: 20151118162244) do t.boolean "merge_requests_events", default: true t.boolean "tag_push_events", default: true t.boolean "note_events", default: true, null: false + t.boolean "build_events", default: false, null: false end add_index "services", ["created_at", "id"], name: "index_services_on_created_at_and_id", using: :btree add_index "services", ["project_id"], name: "index_services_on_project_id", using: :btree add_index "services", ["template"], name: "index_services_on_template", using: :btree - create_table "snippets", force: true do |t| + create_table "snippets", force: :cascade do |t| t.string "title" t.text "content" t.integer "author_id", null: false @@ -729,7 +751,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "snippets", ["project_id"], name: "index_snippets_on_project_id", using: :btree add_index "snippets", ["visibility_level"], name: "index_snippets_on_visibility_level", using: :btree - create_table "subscriptions", force: true do |t| + create_table "subscriptions", force: :cascade do |t| t.integer "user_id" t.integer "subscribable_id" t.string "subscribable_type" @@ -740,7 +762,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "subscriptions", ["subscribable_id", "subscribable_type", "user_id"], name: "subscriptions_user_id_and_ref_fields", unique: true, using: :btree - create_table "taggings", force: true do |t| + create_table "taggings", force: :cascade do |t| t.integer "tag_id" t.integer "taggable_id" t.string "taggable_type" @@ -753,14 +775,14 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "taggings_idx", unique: true, using: :btree add_index "taggings", ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context", using: :btree - create_table "tags", force: true do |t| + create_table "tags", force: :cascade do |t| t.string "name" t.integer "taggings_count", default: 0 end add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree - create_table "users", force: true do |t| + create_table "users", force: :cascade do |t| t.string "email", default: "", null: false t.string "encrypted_password", default: "", null: false t.string "reset_password_token" @@ -814,6 +836,8 @@ ActiveRecord::Schema.define(version: 20151118162244) do t.integer "project_view", default: 0 t.integer "consumed_timestep" t.integer "layout", default: 0 + t.boolean "hide_project_limit", default: false + t.string "unlock_token" end add_index "users", ["admin"], name: "index_users_on_admin", using: :btree @@ -826,7 +850,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree add_index "users", ["username"], name: "index_users_on_username", using: :btree - create_table "users_star_projects", force: true do |t| + create_table "users_star_projects", force: :cascade do |t| t.integer "project_id", null: false t.integer "user_id", null: false t.datetime "created_at" @@ -837,7 +861,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do add_index "users_star_projects", ["user_id", "project_id"], name: "index_users_star_projects_on_user_id_and_project_id", unique: true, using: :btree add_index "users_star_projects", ["user_id"], name: "index_users_star_projects_on_user_id", using: :btree - create_table "web_hooks", force: true do |t| + create_table "web_hooks", force: :cascade do |t| t.string "url" t.integer "project_id" t.datetime "created_at" @@ -850,6 +874,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do t.boolean "tag_push_events", default: false t.boolean "note_events", default: false, null: false t.boolean "enable_ssl_verification", default: true + t.boolean "build_events", default: false, null: false end add_index "web_hooks", ["created_at", "id"], name: "index_web_hooks_on_created_at_and_id", using: :btree diff --git a/doc/README.md b/doc/README.md index 58ab5dd08e..8bac00f2f2 100644 --- a/doc/README.md +++ b/doc/README.md @@ -7,6 +7,7 @@ - [GitLab Basics](gitlab-basics/README.md) Find step by step how to start working on your commandline and on GitLab. - [Importing to GitLab](workflow/importing/README.md). - [Markdown](markdown/markdown.md) GitLab's advanced formatting system. +- [Migrating from SVN](migration/README.md) Convert a SVN repository to Git and GitLab - [Permissions](permissions/permissions.md) Learn what each role in a project (guest/reporter/developer/master/owner) can do. - [Profile Settings](profile/README.md) - [Project Services](project_services/project_services.md) Integrate a project with external services, such as CI and chat. @@ -24,9 +25,21 @@ - [Using Docker Images](ci/docker/using_docker_images.md) - [Using Docker Build](ci/docker/using_docker_build.md) - [Using Variables](ci/variables/README.md) +- [Using SSH keys](ci/ssh_keys/README.md) - [User permissions](ci/permissions/README.md) - [API](ci/api/README.md) +### CI Languages + ++ [Testing PHP](ci/languages/php.md) + +### CI Services + ++ [Using MySQL](ci/services/mysql.md) ++ [Using PostgreSQL](ci/services/postgres.md) ++ [Using Redis](ci/services/redis.md) ++ [Using Other Services](ci/docker/using_docker_images.md#how-to-use-other-images-as-services) + ### CI Examples - [Test and deploy Ruby applications to Heroku](ci/examples/test-and-deploy-ruby-application-to-heroku.md) diff --git a/doc/api/groups.md b/doc/api/groups.md index 0b9f6406d8..808675d860 100644 --- a/doc/api/groups.md +++ b/doc/api/groups.md @@ -1,6 +1,6 @@ # Groups -## List project groups +## List groups Get a list of groups. (As user: my groups, as admin: all groups) @@ -21,6 +21,70 @@ GET /groups You can search for groups by name or path, see below. + +## List a group's projects + +Get a list of projects in this group. + +``` +GET /groups/:id/projects +``` + +Parameters: + +- `archived` (optional) - if passed, limit by archived status +- `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at` +- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc` +- `search` (optional) - Return list of authorized projects according to a search criteria +- `ci_enabled_first` - Return projects ordered by ci_enabled flag. Projects with enabled GitLab CI go first + +```json +[ + { + "id": 4, + "description": null, + "default_branch": "master", + "public": false, + "visibility_level": 0, + "ssh_url_to_repo": "git@example.com:diaspora/diaspora-client.git", + "http_url_to_repo": "http://example.com/diaspora/diaspora-client.git", + "web_url": "http://example.com/diaspora/diaspora-client", + "tag_list": [ + "example", + "disapora client" + ], + "owner": { + "id": 3, + "name": "Diaspora", + "created_at": "2013-09-30T13: 46: 02Z" + }, + "name": "Diaspora Client", + "name_with_namespace": "Diaspora / Diaspora Client", + "path": "diaspora-client", + "path_with_namespace": "diaspora/diaspora-client", + "issues_enabled": true, + "merge_requests_enabled": true, + "builds_enabled": true, + "wiki_enabled": true, + "snippets_enabled": false, + "created_at": "2013-09-30T13: 46: 02Z", + "last_activity_at": "2013-09-30T13: 46: 02Z", + "creator_id": 3, + "namespace": { + "created_at": "2013-09-30T13: 46: 02Z", + "description": "", + "id": 3, + "name": "Diaspora", + "owner_id": 1, + "path": "diaspora", + "updated_at": "2013-09-30T13: 46: 02Z" + }, + "archived": false, + "avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png" + } +] +``` + ## Details of a group Get all details of a group. @@ -186,7 +250,7 @@ To get more (up to 100), pass the following as an argument to the API call: /groups?per_page=100 ``` -And to switch pages add: +And to switch pages add: ``` /groups?per_page=100&page=2 -``` \ No newline at end of file +``` diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index 0cef09d5b2..366a1f8abe 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -101,6 +101,43 @@ Parameters: } ``` +## Get single MR commits + +Get a list of merge request commits. + +``` +GET /projects/:id/merge_request/:merge_request_id/commits +``` + +Parameters: + +- `id` (required) - The ID of a project +- `merge_request_id` (required) - The ID of MR + + +```json +[ + { + "id": "ed899a2f4b50b4370feeea94676502b42383c746", + "short_id": "ed899a2f4b5", + "title": "Replace sanitize with escape once", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dzaporozhets@sphereconsultinginc.com", + "created_at": "2012-09-20T11:50:22+03:00", + "message": "Replace sanitize with escape once" + }, + { + "id": "6104942438c14ec7bd21c6cd5bd995272b3faff6", + "short_id": "6104942438c", + "title": "Sanitize for network graph", + "author_name": "randx", + "author_email": "dmitriy.zaporozhets@gmail.com", + "created_at": "2012-09-20T09:06:12+03:00", + "message": "Sanitize for network graph" + } +] +``` + ## Get single MR changes Shows information about the merge request including its files and changes. @@ -159,7 +196,7 @@ Parameters: "updated_at": "2015-02-02T19:49:26.013Z", "due_date": null }, - "files": [ + "changes": [ { "old_path": "VERSION", "new_path": "VERSION", @@ -298,9 +335,57 @@ PUT /projects/:id/merge_request/:merge_request_id/merge Parameters: -- `id` (required) - The ID of a project -- `merge_request_id` (required) - ID of MR -- `merge_commit_message` (optional) - Custom merge commit message +- `id` (required) - The ID of a project +- `merge_request_id` (required) - ID of MR +- `merge_commit_message` (optional) - Custom merge commit message +- `should_remove_source_branch` (optional) - if `true` removes the source branch +- `merged_when_build_succeeds` (optional) - if `true` the MR is merge when the build succeeds + +```json +{ + "id": 1, + "target_branch": "master", + "source_branch": "test1", + "project_id": 3, + "title": "test1", + "state": "merged", + "upvotes": 0, + "downvotes": 0, + "author": { + "id": 1, + "username": "admin", + "email": "admin@example.com", + "name": "Administrator", + "state": "active", + "created_at": "2012-04-29T08:46:00Z" + }, + "assignee": { + "id": 1, + "username": "admin", + "email": "admin@example.com", + "name": "Administrator", + "state": "active", + "created_at": "2012-04-29T08:46:00Z" + } +} +``` + +## Cancel Merge When Build Succeeds + +If successful you'll get `200 OK`. + +If you don't have permissions to accept this merge request - you'll get a 401 + +If the merge request is already merged or closed - you get 405 and error message 'Method Not Allowed' + +In case the merge request is not set to be merged when the build succeeds, you'll also get a 406 error. +``` +PUT /projects/:id/merge_request/:merge_request_id/cancel_merge_when_build_succeeds +``` +Parameters: + +- `id` (required) - The ID of a project +- `merge_request_id` (required) - ID of MR ```json { diff --git a/doc/api/notes.md b/doc/api/notes.md index e7f299c099..4d7ef288df 100644 --- a/doc/api/notes.md +++ b/doc/api/notes.md @@ -35,7 +35,9 @@ Parameters: "created_at": "2013-10-02T09:22:45Z", "system": true, "upvote": false, - "downvote": false + "downvote": false, + "noteable_id": 377, + "noteable_type": "Issue" }, { "id": 305, @@ -52,7 +54,9 @@ Parameters: "created_at": "2013-10-02T09:56:03Z", "system": true, "upvote": false, - "downvote": false + "downvote": false, + "noteable_id": 121, + "noteable_type": "Issue" } ] ``` @@ -219,7 +223,12 @@ Parameters: "state": "active", "created_at": "2013-09-30T13:46:01Z" }, - "created_at": "2013-10-02T08:57:14Z" + "created_at": "2013-10-02T08:57:14Z", + "system": false, + "upvote": false, + "downvote": false, + "noteable_id": 2, + "noteable_type": "MergeRequest" } ``` diff --git a/doc/api/projects.md b/doc/api/projects.md index 755cc6525c..658e65c6f0 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -32,7 +32,6 @@ Parameters: - `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at` - `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc` - `search` (optional) - Return list of authorized projects according to a search criteria -- `ci_enabled_first` - Return projects ordered by ci_enabled flag. Projects with enabled GitLab CI go first ```json [ @@ -59,6 +58,7 @@ Parameters: "path": "diaspora-client", "path_with_namespace": "diaspora/diaspora-client", "issues_enabled": true, + "open_issues_count": 1, "merge_requests_enabled": true, "builds_enabled": true, "wiki_enabled": true, @@ -101,6 +101,7 @@ Parameters: "path": "puppet", "path_with_namespace": "brightbox/puppet", "issues_enabled": true, + "open_issues_count": 1, "merge_requests_enabled": true, "builds_enabled": true, "wiki_enabled": true, @@ -137,7 +138,21 @@ Parameters: - `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at` - `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc` - `search` (optional) - Return list of authorized projects according to a search criteria -- `ci_enabled_first` - Return projects ordered by ci_enabled flag. Projects with enabled GitLab CI go first + +### List starred projects + +Get a list of projects which are starred by the authenticated user. + +``` +GET /projects/starred +``` + +Parameters: + +- `archived` (optional) - if passed, limit by archived status +- `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at` +- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc` +- `search` (optional) - Return list of authorized projects according to a search criteria ### List ALL projects @@ -153,7 +168,6 @@ Parameters: - `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at` - `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc` - `search` (optional) - Return list of authorized projects according to a search criteria -- `ci_enabled_first` - Return projects ordered by ci_enabled flag. Projects with enabled GitLab CI go first ### Get single project @@ -192,6 +206,7 @@ Parameters: "path": "diaspora-project-site", "path_with_namespace": "diaspora/diaspora-project-site", "issues_enabled": true, + "open_issues_count": 1, "merge_requests_enabled": true, "builds_enabled": true, "wiki_enabled": true, @@ -245,9 +260,17 @@ Parameters: "target_id": 830, "target_type": "Issue", "author_id": 1, - "author_username": "john", "data": null, - "target_title": "Public project search field" + "target_title": "Public project search field", + "author": { + "name": "Dmitriy Zaporozhets", + "username": "root", + "id": 1, + "state": "active", + "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png", + "web_url": "http://localhost:3000/u/root" + }, + "author_username": "root" }, { "title": null, @@ -256,6 +279,14 @@ Parameters: "target_id": null, "target_type": null, "author_id": 1, + "author": { + "name": "Dmitriy Zaporozhets", + "username": "root", + "id": 1, + "state": "active", + "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png", + "web_url": "http://localhost:3000/u/root" + }, "author_username": "john", "data": { "before": "50d4420237a9de7be1304607147aec22e4a14af7", @@ -292,9 +323,56 @@ Parameters: "target_id": 840, "target_type": "Issue", "author_id": 1, - "author_username": "john", "data": null, - "target_title": "Finish & merge Code search PR" + "target_title": "Finish & merge Code search PR", + "author": { + "name": "Dmitriy Zaporozhets", + "username": "root", + "id": 1, + "state": "active", + "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png", + "web_url": "http://localhost:3000/u/root" + }, + "author_username": "root" + }, + { + "title": null, + "project_id": 15, + "action_name": "commented on", + "target_id": 1312, + "target_type": "Note", + "author_id": 1, + "data": null, + "target_title": null, + "created_at": "2015-12-04T10:33:58.089Z", + "note": { + "id": 1312, + "body": "What an awesome day!", + "attachment": null, + "author": { + "name": "Dmitriy Zaporozhets", + "username": "root", + "id": 1, + "state": "active", + "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png", + "web_url": "http://localhost:3000/u/root" + }, + "created_at": "2015-12-04T10:33:56.698Z", + "system": false, + "upvote": false, + "downvote": false, + "noteable_id": 377, + "noteable_type": "Issue" + }, + "author": { + "name": "Dmitriy Zaporozhets", + "username": "root", + "id": 1, + "state": "active", + "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png", + "web_url": "http://localhost:3000/u/root" + }, + "author_username": "root" } ] ``` @@ -335,7 +413,6 @@ Parameters: - `user_id` (required) - user_id of owner - `name` (required) - new project name - `description` (optional) - short project description -- `default_branch` (optional) - 'master' by default - `issues_enabled` (optional) - `merge_requests_enabled` (optional) - `builds_enabled` (optional) diff --git a/doc/api/settings.md b/doc/api/settings.md index d1b93a09c0..96867c6791 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -57,7 +57,7 @@ Parameters: - `default_project_visibility` - what visibility level new project receives - `default_snippet_visibility` - what visibility level new snippet receives - `restricted_signup_domains` - force people to use only corporate emails for signup -- `user_oauth_applications` - allow users to create oauth applicaitons +- `user_oauth_applications` - allow users to create oauth applications - `after_sign_out_path` - where redirect user after logout All parameters are optional. You can send only one that you want to change. diff --git a/doc/ci/README.md b/doc/ci/README.md index 97325069ce..5d9d7a81db 100644 --- a/doc/ci/README.md +++ b/doc/ci/README.md @@ -9,6 +9,18 @@ + [Using Docker Images](docker/using_docker_images.md) + [Using Docker Build](docker/using_docker_build.md) + [Using Variables](variables/README.md) ++ [Using SSH keys](ssh_keys/README.md) + +### Languages + ++ [Testing PHP](languages/php.md) + +### Services + ++ [Using MySQL](services/mysql.md) ++ [Using PostgreSQL](services/postgres.md) ++ [Using Redis](services/redis.md) ++ [Using Other Services](docker/using_docker_images.md#how-to-use-other-images-as-services) ### Examples diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md index ef8a7ec1e8..31458d6167 100644 --- a/doc/ci/docker/using_docker_images.md +++ b/doc/ci/docker/using_docker_images.md @@ -1,19 +1,29 @@ # Using Docker Images -GitLab CI can use [Docker Engine](https://www.docker.com/) to build projects. -Docker is an open-source project that allows to use predefined images to run applications -in independent "containers" that are run within a single Linux instance. -[Docker Hub](https://registry.hub.docker.com/) have rich database of built images that can be used to build applications. +GitLab CI in conjunction with [GitLab Runner](../runners/README.md) can use +[Docker Engine](https://www.docker.com/) to test and build any application. -Docker when used with GitLab CI runs each build in separate and isolated container using predefined image and always from scratch. -It makes it easier to have simple and reproducible build environment that can also be run on your workstation. -This allows you to test all commands from your shell, rather than having to test them on a CI server. +Docker is an open-source project that allows you to use predefined images to +run applications in independent "containers" that are run within a single Linux +instance. [Docker Hub][hub] has a rich database of pre-built images that can be +used to test and build your applications. -### Register Docker runner -To use GitLab Runner with Docker you need to register new runner to use `docker` executor: +Docker, when used with GitLab CI, runs each build in a separate and isolated +container using the predefined image that is set up in +[`.gitlab-ci.yml`](../yaml/README.md). + +This makes it easier to have a simple and reproducible build environment that +can also run on your workstation. The added benefit is that you can test all +the commands that we will explore later from your shell, rather than having to +test them on a dedicated CI server. + +## Register docker runner + +To use GitLab Runner with docker you need to register a new runner to use the +`docker` executor: ```bash -gitlab-ci-multi-runner register \ +gitlab-runner register \ --url "https://gitlab.com/" \ --registration-token "PROJECT_REGISTRATION_TOKEN" \ --description "docker-ruby-2.1" \ @@ -23,101 +33,79 @@ gitlab-ci-multi-runner register \ --docker-mysql latest ``` -**The registered runner will use `ruby:2.1` image and will run two services (`postgres:latest` and `mysql:latest`) that will be accessible for time of the build.** +The registered runner will use the `ruby:2.1` docker image and will run two +services, `postgres:latest` and `mysql:latest`, both of which will be +accessible during the build process. -### What is image? -The image is the name of any repository that is present in local Docker Engine or any repository that can be found at [Docker Hub](https://registry.hub.docker.com/). -For more information about the image and Docker Hub please read the [Docker Fundamentals](https://docs.docker.com/introduction/understanding-docker/). +## What is image -### What is service? -Service is just another image that is run for time of your build and is linked to your build. This allows you to access the service image during build time. -The service image can run any application, but most common use case is to run some database container, ie.: `mysql`. -It's easier and faster to use existing image, run it as additional container than install `mysql` every time project is built. +The `image` keyword is the name of the docker image that is present in the +local Docker Engine (list all images with `docker images`) or any image that +can be found at [Docker Hub][hub]. For more information about images and Docker +Hub please read the [Docker Fundamentals][] documentation. -#### How is service linked to the build? -There's good document that describes how Docker linking works: [Linking containers together](https://docs.docker.com/userguide/dockerlinks/). -To summarize: if you add `mysql` as service to your application, the image will be used to create container that is linked to build container. -The service container for MySQL will be accessible under hostname `mysql`. -So, **to access your database service you have to connect to host: `mysql` instead of socket or `localhost`**. +In short, with `image` we refer to the docker image, which will be used to +create a container on which your build will run. -### How to use other images as services? -You are not limited to have only database services. -You can hand modify `config.toml` to add any image as service found at [Docker Hub](https://registry.hub.docker.com/). -Look for `[runners.docker]` section: -``` -[runners.docker] - image = "ruby:2.1" - services = ["mysql:latest", "postgres:latest"] -``` +## What is service -For example you need `wordpress` instance to test some API integration with `Wordpress`. -You can for example use this image: [tutum/wordpress](https://registry.hub.docker.com/u/tutum/wordpress/). -This is image that have fully preconfigured `wordpress` and have `MySQL` server built-in: -``` -[runners.docker] - image = "ruby:2.1" - services = ["mysql:latest", "postgres:latest", "tutum/wordpress:latest"] -``` +The `services` keyword defines just another docker image that is run during +your build and is linked to the docker image that the `image` keyword defines. +This allows you to access the service image during build time. -Next time when you run your application the `tutum/wordpress` will be started -and you will have access to it from your build container under hostname: `tutum_wordpress`. +The service image can run any application, but the most common use case is to +run a database container, eg. `mysql`. It's easier and faster to use an +existing image and run it as an additional container than install `mysql` every +time the project is built. -Alias hostname for the service is made from the image name: -1. Everything after `:` is stripped, -2. '/' is replaced to `_`. +You can see some widely used services examples in the relevant documentation of +[CI services examples](../services/README.md). -### Configuring services -Many services accept environment variables, which allow you to easily change database names or set account names depending on the environment. +### How is service linked to the build -GitLab Runner 0.5.0 and up passes all YAML-defined variables to created service containers. +To better understand how the container linking works, read +[Linking containers together](https://docs.docker.com/userguide/dockerlinks/). -1. To configure database name for [postgres](https://registry.hub.docker.com/u/library/postgres/) service, -you need to set POSTGRES_DB. +To summarize, if you add `mysql` as service to your application, the image will +then be used to create a container that is linked to the build container. - ```yaml - services: - - postgres - - variables: - POSTGRES_DB: gitlab - ``` +The service container for MySQL will be accessible under the hostname `mysql`. +So, in order to access your database service you have to connect to the host +named `mysql` instead of a socket or `localhost`. -1. To use [mysql](https://registry.hub.docker.com/u/library/mysql/) service with empty password for time of build, -you need to set MYSQL_ALLOW_EMPTY_PASSWORD. +## Overwrite image and services - ```yaml - services: - - mysql - - variables: - MYSQL_ALLOW_EMPTY_PASSWORD: "yes" - ``` +See [How to use other images as services](#how-to-use-other-images-as-services). -For other possible configuration variables check the -https://registry.hub.docker.com/u/library/mysql/ or https://registry.hub.docker.com/u/library/postgres/ -or README page for any other Docker image. +## How to use other images as services -**Note: All variables will passed to all service containers. It's not designed to distinguish which variable should go where.** +You are not limited to have only database services. You can add as many +services you need to `.gitlab-ci.yml` or manually modify `config.toml`. +Any image found at [Docker Hub][hub] can be used as a service. -### Overwrite image and services -It's possible to overwrite `docker-image` and specify services from `.gitlab-ci.yml`. -If you add to your YAML the `image` and the `services` these parameters -be used instead of the ones that were specified during runner's registration. -``` +## Define image and services from `.gitlab-ci.yml` + +You can simply define an image that will be used for all jobs and a list of +services that you want to use during build time. + +```yaml image: ruby:2.2 + services: - postgres:9.3 -before_install: + +before_script: - bundle install - + test: script: - bundle exec rake spec ``` -It's possible to define image and service per-job: -``` -before_install: +It is also possible to define different images and services per job: + +```yaml +before_script: - bundle install test:2.1: @@ -135,34 +123,91 @@ test:2.2: - bundle exec rake spec ``` -#### How to enable overwriting? -To enable overwriting you have to **enable it first** (it's disabled by default for security reasons). -You can do that by hand modifying runner configuration: `config.toml`. -Please go to section where is `[runners.docker]` definition for your runner. -Add `allowed_images` and `allowed_services` to specify what images are allowed to be picked from `.gitlab-ci.yml`: +## Define image and services in `config.toml` + +Look for the `[runners.docker]` section: + ``` [runners.docker] image = "ruby:2.1" - allowed_images = ["ruby:*", "python:*"] - allowed_services = ["mysql:*", "redis:*"] -``` -This enables you to use in your `.gitlab-ci.yml` any image that matches above wildcards. -You will be able to pick only `ruby` and `python` images. -The same rule can be applied to limit services. - -If you are courageous enough, you can make it fully open and accept everything: -``` -[runners.docker] - image = "ruby:2.1" - allowed_images = ["*", "*/*"] - allowed_services = ["*", "*/*"] + services = ["mysql:latest", "postgres:latest"] ``` -**It the feature is not enabled, or image isn't allowed the error message will be put into the build log.** +The image and services defined this way will be added to all builds run by +that runner. + +## Define an image from a private Docker registry + +Starting with GitLab Runner 0.6.0, you are able to define images located to +private registries that could also require authentication. + +All you have to do is be explicit on the image definition in `.gitlab-ci.yml`. + +```yaml +image: my.registry.tld:5000/namepace/image:tag +``` + +In the example above, GitLab Runner will look at `my.registry.tld:5000` for the +image `namespace/image:tag`. + +If the repository is private you need to authenticate your GitLab Runner in the +registry. Learn how to do that on +[GitLab Runner's documentation][runner-priv-reg]. + +## Accessing the services + +Let's say that you need a Wordpress instance to test some API integration with +your application. + +You can then use for example the [tutum/wordpress][] image in your +`.gitlab-ci.yml`: + +```yaml +services: +- tutum/wordpress:latest +``` + +When the build is run, `tutum/wordpress` will be started and you will have +access to it from your build container under the hostname `tutum__wordpress`. + +The alias hostname for the service is made from the image name following these +rules: + +1. Everything after `:` is stripped +2. Backslash (`/`) is replaced with double underscores (`__`) + +## Configuring services + +Many services accept environment variables which allow you to easily change +database names or set account names depending on the environment. + +GitLab Runner 0.5.0 and up passes all YAML-defined variables to the created +service containers. + +For all possible configuration variables check the documentation of each image +provided in their corresponding Docker hub page. + +*Note: All variables will be passed to all services containers. It's not +designed to distinguish which variable should go where.* + +### PostgreSQL service example + +See the specific documentation for +[using PostgreSQL as a service](../services/postgres.md). + +### MySQL service example + +See the specific documentation for +[using MySQL as a service](../services/mysql.md). + +## How Docker integration works + +Below is a high level overview of the steps performed by docker during build +time. -### How Docker integration works 1. Create any service container: `mysql`, `postgresql`, `mongodb`, `redis`. -1. Create cache container to store all volumes as defined in `config.toml` and `Dockerfile` of build image (`ruby:2.1` as in above example). +1. Create cache container to store all volumes as defined in `config.toml` and + `Dockerfile` of build image (`ruby:2.1` as in above example). 1. Create build container and link any service container to build container. 1. Start build container and send build script to the container. 1. Run build script. @@ -171,33 +216,64 @@ If you are courageous enough, you can make it fully open and accept everything: 1. Check exit status of build script. 1. Remove build container and all created service containers. -### How to debug a build locally -1. Create a file with build script: +## How to debug a build locally + +*Note: The following commands are run without root privileges. You should be +able to run docker with your regular user account.* + +First start with creating a file named `build script`: + ```bash -$ cat < build_script +cat < build_script git clone https://gitlab.com/gitlab-org/gitlab-ci-multi-runner.git /builds/gitlab-org/gitlab-ci-multi-runner cd /builds/gitlab-org/gitlab-ci-multi-runner -make <- or any other build step +make EOF ``` -1. Create service containers: -``` -$ docker run -d -n service-mysql mysql:latest -$ docker run -d -n service-postgres postgres:latest -``` -This will create two service containers (MySQL and PostgreSQL). +Here we use as an example the GitLab Runner repository which contains a +Makefile, so running `make` will execute the commands defined in the Makefile. +Your mileage may vary, so instead of `make` you could run the command which +is specific to your project. -1. Create a build container and execute script in its context: -``` -$ cat build_script | docker run -n build -i -l mysql:service-mysql -l postgres:service-postgres ruby:2.1 /bin/bash -``` -This will create build container that has two service containers linked. -The build_script is piped using STDIN to bash interpreter which executes the build script in container. +Then create some service containers: + +``` +docker run -d -n service-mysql mysql:latest +docker run -d -n service-postgres postgres:latest +``` + +This will create two service containers, named `service-mysql` and +`service-postgres` which use the latest MySQL and PostgreSQL images +respectively. They will both run in the background (`-d`). + +Finally, create a build container by executing the `build_script` file we +created earlier: + +``` +docker run --name build -i --link=service-mysql:mysql --link=service-postgres:postgres ruby:2.1 /bin/bash < build_script +``` + +The above command will create a container named `build` that is spawned from +the `ruby:2.1` image and has two services linked to it. The `build_script` is +piped using STDIN to the bash interpreter which in turn executes the +`build_script` in the `build` container. + +When you finish testing and no longer need the containers, you can remove them +with: -1. At the end remove all containers: ``` docker rm -f -v build service-mysql service-postgres ``` -This will forcefully (the `-f` switch) remove build container and service containers -and all volumes (the `-v` switch) that were created with the container creation. + +This will forcefully (`-f`) remove the `build` container, the two service +containers as well as all volumes (`-v`) that were created with the container +creation. + +[Docker Fundamentals]: https://docs.docker.com/engine/introduction/understanding-docker/ +[hub]: https://hub.docker.com/ +[linking-containers]: https://docs.docker.com/engine/userguide/networking/default_network/dockerlinks/ +[tutum/wordpress]: https://registry.hub.docker.com/u/tutum/wordpress/ +[postgres-hub]: https://registry.hub.docker.com/u/library/postgres/ +[mysql-hub]: https://registry.hub.docker.com/u/library/mysql/ +[runner-priv-reg]: https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/configuration/advanced-configuration.md#using-a-private-docker-registry diff --git a/doc/ci/img/builds_tab.png b/doc/ci/img/builds_tab.png new file mode 100644 index 0000000000000000000000000000000000000000..d088b8b329dc5dca75513e4fbe27d2323203d770 GIT binary patch literal 3845 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. + +Now that we created the script that contains all prerequisites for our build +environment, let's add it in `.gitlab-ci.yml`: + +```yaml +... + +before_script: +- bash ci/docker_install.sh > /dev/null + +... +``` + +Last step, run the actual tests using `phpunit`: + +```yaml +... + +test:app: + script: + - phpunit --configuration phpunit_myapp.xml + +... +``` + +Finally, commit your files and push them to GitLab to see your build succeeding +(or failing). + +The final `.gitlab-ci.yml` should look similar to this: + +```yaml +# Select image from https://hub.docker.com/_/php/ +image: php:5.6 + +before_script: +# Install dependencies +- ci/docker_install.sh > /dev/null + +test:app: + script: + - phpunit --configuration phpunit_myapp.xml +``` + +### Test against different PHP versions in Docker builds + +Testing against multiple versions of PHP is super easy. Just add another job +with a different docker image version and the runner will do the rest: + +```yaml +before_script: +# Install dependencies +- ci/docker_install.sh > /dev/null + +# We test PHP5.6 +test:5.6: + image: php:5.6 + script: + - phpunit --configuration phpunit_myapp.xml + +# We test PHP7.0 (good luck with that) +test:7.0: + image: php:7.0 + script: + - phpunit --configuration phpunit_myapp.xml +``` + +### Custom PHP configuration in Docker builds + +There are times where you will need to customise your PHP environment by +putting your `.ini` file into `/usr/local/etc/php/conf.d/`. For that purpose +add a `before_script` action: + +```yaml +before_script: +- cp my_php.ini /usr/local/etc/php/conf.d/test.ini +``` + +Of course, `my_php.ini` must be present in the root directory of your repository. + +## Test PHP projects using the Shell executor + +The shell executor runs your builds in a terminal session on your server. +Thus, in order to test your projects you first need to make sure that all +dependencies are installed. + +For example, in a VM running Debian 8 we first update the cache, then we +install `phpunit` and `php5-mysql`: + +```bash +sudo apt-get update -y +sudo apt-get install -y phpunit php5-mysql +``` + +Next, add the following snippet to your `.gitlab-ci.yml`: + +```yaml +test:app: + script: + - phpunit --configuration phpunit_myapp.xml +``` + +Finally, push to GitLab and let the tests begin! + +### Test against different PHP versions in Shell builds + +The [phpenv][] project allows you to easily manage different versions of PHP +each with its own config. This is specially usefull when testing PHP projects +with the Shell executor. + +You will have to install it on your build machine under the `gitlab-runner` +user following [the upstream installation guide][phpenv-installation]. + +Using phpenv also allows to easily configure the PHP environment with: + +``` +phpenv config-add my_config.ini +``` + +*__Important note:__ It seems `phpenv/phpenv` + [is abandoned](https://github.com/phpenv/phpenv/issues/57). There is a fork + at [madumlao/phpenv](https://github.com/madumlao/phpenv) that tries to bring + the project back to life. [CHH/phpenv](https://github.com/CHH/phpenv) also + seems like a good alternative. Picking any of the mentioned tools will work + with the basic phpenv commands. Guiding you to choose the right phpenv is out + of the scope of this tutorial.* + +### Install custom extensions + +Since this is a pretty bare installation of the PHP environment, you may need +some extensions that are not currently present on the build machine. + +To install additional extensions simply execute: + +```bash +pecl install +``` + +It's not advised to add this to `.gitlab-ci.yml`. You should execute this +command once, only to setup the build environment. + +## Extend your tests + +### Using atoum + +Instead of PHPUnit, you can use any other tool to run unit tests. For example +you can use [atoum](https://github.com/atoum/atoum): + +```yaml +before_script: +- wget http://downloads.atoum.org/nightly/mageekguy.atoum.phar + +test:atoum: + script: + - php mageekguy.atoum.phar +``` + +### Using Composer + +The majority of the PHP projects use Composer for managing their PHP packages. +In order to execute Composer before running your tests, simply add the +following in your `.gitlab-ci.yml`: + +```yaml +... + +# Composer stores all downloaded packages in the vendor/ directory. +# Do not use the following if the vendor/ directory is commited to +# your git repository. +cache: + paths: + - vendor/ + +before_script: +# Install composer dependencies +- curl -sS https://getcomposer.org/installer | php +- php composer.phar install + +... +``` + +## Access private packages / dependencies + +If your test suite needs to access a private repository, you need to configure +[the SSH keys](../ssh_keys/README.md) in order to be able to clone it. + +## Use databases or other services + +Most of the time you will need a running database in order for your tests to +run. If you are using the Docker executor you can leverage Docker's ability to +link to other containers. In GitLab Runner lingo, this can be achieved by +defining a `service`. + +This functionality is covered in [the CI services](../services/README.md) +documentation. + +## Testing things locally + +With GitLab Runner 1.0 you can also test any changes locally. From your +terminal execute: + +```bash +# Check using docker executor +gitlab-runner exec docker test:app + +# Check using shell executor +gitlab-runner exec shell test:app +``` + +## Example project + +We have set up an [Example PHP Project][php-example-repo] for your convenience +that runs on [GitLab.com](https://gitlab.com) using our publicly available +[shared runners](../runners/README.md). + +Want to hack on it? Simply fork it, commit and push your changes. Within a few +moments the changes will be picked by a public runner and the build will begin. + +[php-hub]: https://hub.docker.com/_/php/ +[phpenv]: https://github.com/phpenv/phpenv +[phpenv-installation]: https://github.com/phpenv/phpenv#installation +[php-example-repo]: https://gitlab.com/gitlab-examples/php diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md index d69064a91f..a9b36139de 100644 --- a/doc/ci/quick_start/README.md +++ b/doc/ci/quick_start/README.md @@ -1,44 +1,62 @@ # Quick Start -To start building projects with GitLab CI a few steps needs to be done. +Starting from version 8.0, GitLab Continuous Integration (CI) is fully +integrated into GitLab itself and is enabled by default on all projects. -## 1. Install GitLab and CI +This guide assumes that you: -First you need to have a working GitLab and GitLab CI instance. +- have a working GitLab instance of version 8.0 or higher or are using + [GitLab.com](https://gitlab.com/users/sign_in) +- have a project in GitLab that you would like to use CI for -You can omit this step if you use [GitLab.com](https://GitLab.com/). +In brief, the steps needed to have a working CI can be summed up to: -## 2. Create repository on GitLab +1. Create a new project +1. Add `.gitlab-ci.yml` to the git repository and push to GitLab +1. Configure a Runner -Once you login on your GitLab add a new repository where you will store your source code. -Push your application to that repository. +From there on, on every push to your git repository the build will be +automagically started by the Runner and will appear under the project's +`/builds` page. -## 3. Add project to CI +Now, let's break it down to pieces and work on solving the GitLab CI puzzle. -The next part is to login to GitLab CI. -Point your browser to the URL you have set GitLab or use [gitlab.com/ci](https://gitlab.com/ci/). +## Creating a `.gitlab-ci.yml` file -On the first screen you will see a list of GitLab's projects that you have access to: +Before you create `.gitlab-ci.yml` let's first explain in brief what this is +all about. -![Projects](projects.png) +### What is `.gitlab-ci.yml` -Click **Add Project to CI**. -This will create project in CI and authorize GitLab CI to fetch sources from GitLab. +The `.gitlab-ci.yml` file is where you configure what CI does with your project. +It lives in the root of your repository. -> GitLab CI creates unique token that is used to configure GitLab CI service in GitLab. -> This token allows to access GitLab's repository and configures GitLab to trigger GitLab CI webhook on **Push events** and **Tag push events**. -> You can see that token by going to Project's Settings > Services > GitLab CI. -> You will see there token, the same token is assigned in GitLab CI settings of project. +On any push to your repository, GitLab will look for the `.gitlab-ci.yml` +file and start builds on _Runners_ according to the contents of the file, +for that commit. -## 4. Create project's configuration - .gitlab-ci.yml +Because `.gitlab-ci.yml` is in the repository, it is version controlled, +old versions still build succesfully, forks can easily make use of CI, +branches can have separate builds and you have a single source of truth for CI. +You can read more about the reasons why we are using `.gitlab-ci.yml` +[in our blog about it][blog-ci]. -The next: You have to define how your project will be built. -GitLab CI uses [YAML](https://en.wikipedia.org/wiki/YAML) file to store build configuration. -You need to create `.gitlab-ci.yml` in root directory of your repository: +**Note:** `.gitlab-ci.yml` is a [YAML](https://en.wikipedia.org/wiki/YAML) file +so you have to pay extra attention to the identation. Always use spaces, not +tabs. + +### Creating a simple `.gitlab-ci.yml` file + +You need to create a file named `.gitlab-ci.yml` in the root directory of your +repository. Below is an example for a Ruby on Rails project. ```yaml before_script: - - bundle install + - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs + - ruby -v + - which ruby + - gem install bundler --no-ri --no-rdoc + - bundle install --jobs $(nproc) "${FLAGS[@]}" rspec: script: @@ -49,71 +67,131 @@ rubocop: - bundle exec rubocop ``` -This is the simplest possible build configuration that will work for most Ruby applications: -1. Define two jobs `rspec` and `rubocop` with two different commands to be executed. -1. Before every job execute commands defined by `before_script`. +This is the simplest possible build configuration that will work for most Ruby +applications: -The `.gitlab-ci.yml` defines set of jobs with constrains how and when they should be run. -The jobs are defined as top-level elements with name and always have to contain the `script`. -Jobs are used to create builds, which are then picked by [runners](../runners/README.md) and executed within environment of the runner. -What is important that each job is run independently from each other. +1. Define two jobs `rspec` and `rubocop` (the names are arbitrary) with + different commands to be executed. +1. Before every job, the commands defined by `before_script` are executed. -For more information and complete `.gitlab-ci.yml` syntax, please check the [Configuring project (.gitlab-ci.yml)](../yaml/README.md). +The `.gitlab-ci.yml` file defines sets of jobs with constraints of how and when +they should be run. The jobs are defined as top-level elements with a name (in +our case `rspec` and `rubocop`) and always have to contain the `script` keyword. +Jobs are used to create builds, which are then picked by +[Runners](../runners/README.md) and executed within the environment of the Runner. -## 5. Add file and push .gitlab-ci.yml to repository +What is important is that each job is run independently from each other. -Once you created `.gitlab-ci.yml` you should add it to git repository and push it to GitLab. +If you want to check whether your `.gitlab-ci.yml` file is valid, there is a +Lint tool under the page `/ci/lint` of your GitLab instance. You can also find +the link under **Settings > CI settings** in your project. + +For more information and a complete `.gitlab-ci.yml` syntax, please check +[the documentation on .gitlab-ci.yml](../yaml/README.md). + +### Push `.gitlab-ci.yml` to GitLab + +Once you've created `.gitlab-ci.yml`, you should add it to your git repository +and push it to GitLab. ```bash git add .gitlab-ci.yml -git commit +git commit -m "Add .gitlab-ci.yml" git push origin master ``` -If you refresh the project's page on GitLab CI you will notice a one new commit: +Now if you go to the **Builds** page you will see that the builds are pending. -![](new_commit.png) +You can also go to the **Commits** page and notice the little clock icon next +to the commit SHA. -However the commit has status **pending** which means that commit was not yet picked by runner. +![New commit pending](img/new_commit.png) -## 6. Configure runner +Clicking on the clock icon you will be directed to the builds page for that +specific commit. -In GitLab CI, Runners run your builds. -A runner is a machine (can be virtual, bare-metal or VPS) that picks up builds through the coordinator API of GitLab CI. +![Single commit builds page](img/single_commit_status_pending.png) -A runner can be specific to a certain project or serve any project in GitLab CI. -A runner that serves all projects is called a shared runner. -More information about different runner types can be found in [Configuring runner](../runners/README.md). +Notice that there are two jobs pending which are named after what we wrote in +`.gitlab-ci.yml`. The red triangle indicates that there is no Runner configured +yet for these builds. -To check if you have runners assigned to your project go to **Runners**. You will find there information how to setup project specific runner: +The next step is to configure a Runner so that it picks the pending jobs. -1. Install GitLab Runner software. Checkout the [GitLab Runner](https://about.gitlab.com/gitlab-ci/#gitlab-runner) section to install it. -1. Specify following URL during runner setup: https://gitlab.com/ci/ -1. Use the following registration token during setup: TOKEN +## Configuring a Runner -If you do it correctly your runner should be shown under **Runners activated for this project**: +In GitLab, Runners run the builds that you define in `.gitlab-ci.yml`. +A Runner can be a virtual machine, a VPS, a bare-metal machine, a docker +container or even a cluster of containers. GitLab and the Runners communicate +through an API, so the only needed requirement is that the machine on which the +Runner is configured to has Internet access. -![](runners_activated.png) +A Runner can be specific to a certain project or serve multiple projects in +GitLab. If it serves all projects it's called a _Shared Runner_. -### Shared runners +Find more information about different Runners in the +[Runners](../runners/README.md) documentation. -If you use [gitlab.com/ci](https://gitlab.com/ci/) you can use **Shared runners** provided by GitLab Inc. -These are special virtual machines that are run on GitLab's infrastructure that can build any project. -To enable **Shared runners** you have to go to **Runners** and click **Enable shared runners** for this project. +You can find whether any Runners are assigned to your project by going to +**Settings > Runners**. Setting up a Runner is easy and straightforward. The +official Runner supported by GitLab is written in Go and can be found at +. -## 7. Check status of commit +In order to have a functional Runner you need to follow two steps: -If everything went OK and you go to commit, the status of the commit should change from **pending** to either **running**, **success** or **failed**. +1. [Install it][runner-install] +2. [Configure it](../runners/README.md#registering-a-specific-runner) -![](commit_status.png) +Follow the links above to set up your own Runner or use a Shared Runner as +described in the next section. -You can click **Build ID** to view build log for specific job. +For other types of unofficial Runners written in other languages, see the +[instructions for the various GitLab Runners](https://about.gitlab.com/gitlab-ci/#gitlab-runner). -## 8. Congratulations! +Once the Runner has been set up, you should see it on the Runners page of your +project, following **Settings > Runners**. -You managed to build your first project using GitLab CI. -You may need to tune your `.gitlab-ci.yml` file to implement build plan for your project. -A few examples how it can be done you can find on [Examples](../examples/README.md) page. +![Activated runners](img/runners_activated.png) -GitLab CI also offers **the Lint** tool to verify validity of your `.gitlab-ci.yml` which can be useful to troubleshoot potential problems. -The Lint is available from project's settings or by adding `/lint` to GitLab CI url. +### Shared Runners + +If you use [GitLab.com](https://gitlab.com/) you can use **Shared Runners** +provided by GitLab Inc. + +These are special virtual machines that run on GitLab's infrastructure and can +build any project. + +To enable **Shared Runners** you have to go to your project's +**Settings > Runners** and click **Enable shared runners**. + +[Read more on Shared Runners](../runners/README.md). + +## Seeing the status of your build + +After configuring the Runner succesfully, you should see the status of your +last commit change from _pending_ to either _running_, _success_ or _failed_. + +You can view all builds, by going to the **Builds** page in your project. + +![Commit status](img/builds_status.png) + +By clicking on a Build ID, you will be able to see the log of that build. +This is important to diagnose why a build failed or acted differently than +you expected. + +![Build log](img/build_log.png) + +You are also able to view the status of any commit in the various pages in +GitLab, such as **Commits** and **Merge Requests**. + +## Next steps + +Awesome! You started using CI in GitLab! + +Next you can look into doing more with the CI. Many people are using GitLab +to package, containerize, test and deploy software. + +Visit our various languages examples at . + +[runner-install]: https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/tree/master#installation +[blog-ci]: https://about.gitlab.com/2015/05/06/why-were-replacing-gitlab-ci-jobs-with-gitlab-ci-dot-yml/ diff --git a/doc/ci/quick_start/build_status.png b/doc/ci/quick_start/build_status.png deleted file mode 100644 index 333259e6acd301b579ebb7b7682b1df1e635a61a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62140 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�n!5^ z$5Qa?>HGsR14Cz}sUwCN7oTVXZpmJ~2%W6REhAFvN~Bjy%3i*Ci;y=I8nOd!myQ^o zuunFAyKfODhNvb%KXAw(ecjm?i*2%pd#8|X!?}S=O(@_f0SJz^Ha=Ef3~Z zhYxGyc944lc33H-=Omr(RV0W5U9?QoHazV~jYDX!Ti`7l-F?7%E8w$$ohjUyOc~NO)yW z+zYZGYN-ca8C?Z*GJO)@{8G#~4q-Pw$8KpSeI+$`5o&7^2~*I0$^$0xf_jAEJkpr8 z+SYh$^L~doT*k`fiqiB>3KodY;C1|8p^(S;lbryHmn|yZ8|#WrxX8K+v+d45SI9?( zn+sNFKwWrD;b&L{v;AGl%)z33UuM7*1U5Rn{-X?)<>Yi3Re;=(pFpV>apQhAP}Zkd zJh%9iBs8P}f9%=dtizKd&riv1CPsbb09)2E^4v1k`fg6ILiB+GhP$4zE0l5_WcVP^ zl?5OhnDYSwG)+3ki`dXNqGqlLRoXegdIA54pe;|55A7c?`9d<8>Lf12ZlGNMEKG#P z`K`7Y($0ybWVVXAmI0FdodV0vxEVZpzy%mh8xtjUsAR|jdWmWxEro1T#lQFxZYfoV z6$FFrI)e~Ma*fqv^V5|s<(3kVJ&3_=5HyQ2R7Q!get1$H-iF}sW3+$~ild>u?0TQ?GK3pZoKUoWQ`3RS+2&M-m_;nJJ-&ftOI z4m4~(@-uVEfFsFaDuX_<1cUi1?WLAj+o|g{yF@-%MCKG)f;&HJgO9{#R^>P0$)klr z+eEZ2VXR+QkoSfw~A{l>Ay-9r*7Hf z&^*an{w6jcw(Yvbd8-zy zoX#puHaP#?r1=fYl;WClKoPC*GNOg1;6kh9!eV8u0dT}Hp3E9Z6{Rmp7D|w3&R&uS z--|BP*r;z%$?ce!RcPi*#WJb9W|AExiXgOGhoeY{(;0^nlqSSCgYHjKnt477d}j{| zYABY^e5A2Tsp~)=36W|s_U1J~Wo08ZUbTIV7`}rR zNGd!|L|~i|kmMqhG+f8LkFV+4hQ3SqQeCP$qCp!RwAFC=V3Nvoi&tmUYa0!XvMB(n z@gU!CGq=tjIGNl38DI2#@UhYa<=0S`D`&2Rm+9SK3y0_%nOHe|WLdVa&mu4SH5M=1 zI?!tgz;E&n;88`I#XMZsxNm+IvP&xj^hZ5wHY;s+{91}v>!~Z3cjcTqya+Zxr=T13 zdgU9qJx_k3*l#gbZv(60lB_^&8j#MWG|>pRop;9YwF8DFHA$FTxf{6!<=_UhZ;+Hk zHuiDT!bnuw)L4#R?<6!})N``IXA-FhTT1`Kt^iyx0I`toZ*%u%Q#H`f6JhJMN)!TD z1Wc>+m@Vp9o@};7o|U{kfT6fTU&E$>kg=`}4qVbnvv6jwxqxjW$IR{T8^^TEGCQ$= zMB1v=P#hBtpRE$JCSO4noo-ZIx2Lz(j}<7$)Ks1<59!0wQfl7@mH0REC%LHHyFo*G zBjn(pTl7$MPJkb@Vz)T9-dBGb=~CfmnH};ajCN9*&%SX{B$RTHMop`U_1;Ygvk`v3 zv6ARO6bpv1SWBoe)%c|32=Woo1*m{}U?k_ma7^|SIwVHmy<$~~FMfUfPYm7~Avg7l zR~gL0QUu;~6)|1&7K3o zZ0+dB6vE$gyPtL`J4q+ ziJs`3xu0;xaTm~j;spU~8ihC-euha|GcHoj8oZyjA}pHBYl{)K#+XdZm?_Anz) zP`z{(U<>Q}R=OEYd(b`^j*MAzeJ#grm9;z(fw!#l$7jVZao~o|a*cbwOMzrW)_T9p za0u3qyR|>f9K8T>df-7`(>;ayW~XX%`L&a^dp|6!qP4%Cf(fFDwqALTqfi8ZX?qS} z#v8GL{=WLMzKjGMRvmJ6R`E~_@XQ}|L~~IOKJ^^6I7iguqB4qJ-bE{{bv}(Kw*+s2 zce({zPTIlsIp0pDWSb-eYagDZG>^P<(ddwx-7kEAy_Y?YM--2~;XOtFDYv{6y7V4N zAL!}t4iVOZ@39C6bmX}KhCK(UB&ihKk#Ca?|BTgv;flOoc_dI)*B1h=-Z@FjjL5J3 zr?}(Z?kvAF(K)0T0h zks=hc+||mcOnHKIK`#DtN7dd`A53=VexRQ>T;~9&NbA(=5Wk(a9esIW>)8*`LBTik zycs}sIjd;OYMwuU0c|mw&|$-%RcGV68GlOm{llj(z6zoNh(s5LYji-e)ej#c+If84 zv7KHd=y4tpH(?YTsY(tO+3+J3ME-1{B);k=4N^b8E|~T@UEeg*QtkYqcTr5GU6c?D z@B?F7M9vN?LM-<_5OZ^Vj_u15n!gRb`(!u_ORr}{Hi5EG*I0K;*)Dc?!#~6sMEMOQ zYFoCe5jYh{3}IFt@Ke)G)gwz;Y(BDOg2QB_-{$neF0ncrU_M0zx1r6C8d8VDYZXWg z+kFPM>(3`8sGJuadeL(0v6AJr3cbu|QT0(08aBMxZX5p_P@tY=JYkTieVPBIC}qNh z?6KC%B3?T|VIx!Vsedg>qMCa2&E_()HGjWcKrKx=f@@dKM|({a+OC0fIrSUVPkb~b zF2e9KX7_QG+7~_%-5j$FwOqwan6NKTMw2-;z0u}^C>0ZSAu#W*i4OAuID27hf6m|v?3AxkW*X+g!8?{S0nWk&*7EQwwF_VtC9d{Zikf=dT;-H03P+B> zkOVRhZ%|HQoFO|kRn(rE!b1dbK?I(HuYgLFQ z{j{RxaqS>}hk5WA@S6QhuJhe~+dd)4VaAX~wa!fc7sU2b z2G4lcTu@T}e_2??VgK|1Dc0E;|3wYoJO812U6pk>TK>x-x>kT^&GHNC!i=T2ZI-cx z%a(gxNIe*!EnR=<(?`2R3Ff-Me&6UTafmzOlG9^l0PPz&-kf;~**RDu-JLEs%cTH) zr;;uxgN?@A=+nRLpWU&c_vB?%q0W7lpgE?!l~S*;cx@5NApim-Sh_T~m2)dcsNd2t zu|`;VQYb)Bd^5+cE%0rqKw!M_0(jExe28}vXvR)%J>9V8=6WL^!T_Rj8H>#ZwqMkm zI+!@Rf~`E&Fxa_zNBRqCq;RJ^>ec=H$_>MdN1s2~k6FjA>bU^V4JTHwixsAewrP$? zmyI1Dd<}FlG*{Lm4s%Tb?$>`2db%V3x;xu+_#YU!esJYyUD7FqWOqAiY>Pde+zJS$ zmZ8e`9-q0d7n(aAFhfqFubI9FC#rqP2d@W9RQHP~h>8XSYdzBwVh&6U8;&dv6%)sG|G z#LA;K67kHb^JqWkXNqXADS}0BOK%7qLZuIL8l0A@mNR<1dC_cr;HbzPd?jEx!k)xC z?m&MaMww0Newl36$}9z}RSpEniRDn1X8jg~imRm2ar;_ruja3_QQsf3giVX$JQ({Fu{yiKOqd+l%(<*pi7%b#jH z`D3_|$H_c|Adk30!lA-5L$ny{5&MBmXQJ6UMgyCz9 z;j52t(%g3B!k!N`@&aG~G((>}Am5N&%n~*|T|pAdab8{cE1Z!o>uS4Bur5HvbZAfl zms4rdzUX16ucg{0m8TfE-fuDzJ^!;2q3`D`!lTn(cd>ai?z7Oh;0RSY_FJGUFPys z50P;Geq3aSunyqg`3WB(fs~ProVbuT6B-RJtnXuO0;{hNFAyN#a1ZpHq6?G1BxEQj zEKEY_A_<(Mf-H~k*DvtlrK=@yrG-Bm63i7HZMI33nug@> zfN?}xO>^;h0n9~>Q|Z5z5K*e;6JO@%4b#kDby3Il9ek!5xV!v7!h;J3 zbe<}AJog@6eD_-JAgTtJ2?EOruB$;A)*r#w(CeE~T(ZJuVuIMHf@~|rNrJ{ZrX3&i z;} zG1UEP2q>^S`*s^3YA2BK7`e=W9;pCb8s~-8SLh3tUCo4UWMrIlp2z{)%aljrK$fZT z94|*mI0~nO^{Ew8?-nwIP3p3&nWwm1!|b2V{8<}tE+Ev2d30~|~mWB%&I|&6=PY5-~#Va_>8QcnE&LNf`1Y3=^nUJxH2N8`n(DbT4 zxa(uJcMYtbYq|^PWwJIs?TE05ADm@_`2aqRYf%)v$}lPD>n;!KFM+=&eoMb-99XM)G@D_IXzh#T&4#bS$>-%mry-rj^Ijj$>4cV>|!Y_&BzXkE9YYel%jSv=(Go1|Io&ZTtqIOiwA4k$DE0V0)5s=tNbVz>a? zk*kVpc-%S7FdnYD_2|3ggljglpCUThR^WcqYJS{XUz;69_uScqU!f`U8c{SwE5*N% z2U-=%!%17>l9SVISC)i&=J~RcmpE993XW_=W10d4?jfz7)uz?5b5U%7Czb?@jY?*Y z_HNu7GT;D7lDc|1@n4Dzic&NIew(df+fgZ6u-e;`=IU`I3}W^lgM7DkXv01;D=iQS}+{gkZ{jyd&-<#K?~LUygNRx z#cqLKsl9<8X@Tn2unKmajpeiQYv?TH4u#$CeA!iVxT~#52OP1m(F@T5Trr?P2S(9K{O&tFlT7HE!D^(OC*d)= zGr6=||7f-|wA)$zfH~7OGcUs5Z)Jj^v6zSS5K?)E=OR>MyniBiPXHNGqT3XL;j_4h zV7DXOToX+yh#f9A=vW(P$;GR$XQtVxFeZCO)-isgyWb4yMa|`r^ltrzk7f> zfIYpv7oaes+>b`&GK(?5BP^H`HFeL!Dd}3%0Kq+z+4}K^nfq~LgFrUFGAdrZL)Ffz zLQubc$#mQMb*zSMyWmj7q@)x?+rL||J`}#T4Z*$XnPJrK(%s0tFGBWF9k}I2>9MP- ztXOu2qL66>vt5JMjhysV=+Si!l86ZkSDW@O<%SRLrf#|Dkhd3qjPlefAkEVY{!a;f zxQ12FbOi^VJHB9B^%8AKCk2@T)!*FIYBm6P$c|Wm1?acBInaBc4;oeMoBfid4J?Hd zTsk6kYBF3_1{EKIHWtBa(?o|xvBE0_KQMsm1^ry0SA1k|>}iW3%-?g_D`xUsn$3jJ z>~hL9nZX&(7_Wy`E!Qvyk;W`|a_M6mxB{MiG z!G^}fgPUC1zalKNtGCL#zRoGy)HZ^w{Cx|I#*^FU=%u-a68gQNPrHs7tyyk&1VVZc z%Nf+*sObF|2I5duwc?HF{!i`@r88%=+ay$Z2k) z&VvCBN+>v(lNym?bG8GIE=Sx!bdDI2ONFC;kO)JaoCpVxj!>$6Mh8}OHx0A_5gjbY zCu$Q{GIkI!HYalrBH(h$a!8M2(Hkw5#0U#Q_>kPYy~oo@Sfe96T7Kf9Q>SqT+D_%0WxnFQ0NspP?G{< zF8Ejx;(jA_*@JXu_n+4Q85L`+teF`0T?*hJH`88Il7v{c!L8-FHrE=QQQ9Sy;tC57aQNbypE*g1X@y&`(2 zO#GT1P}EE%<`76Gn~@vcJ`pn5zg*PG>+5quzwXHAoNf2~#7t+a-q%8Sz@DNw1gKSU zFy1@fE=$_8T$)fnAHYEmRv%hnv}gEp@1*Zxjc zr`dyTN)k|&&OGby4t$!azQyMzCb=R<6S<`k8h4oLqg~sd|J&Cvwt5UQ{=77Ug4X-3 znY3}PUD_T4Vm%x>4kXn;nhtSUWxC!8$6xU_MO*R0$h3CushhlL$yGm3|MGS}LcvgM zta_`uY|@wyhGlZd!G&fbn*L1Xe_TCSrcG%B{1sp!$8P9+hk4u2kaisk1WiX?T=C49rsfju93n&q@ zdDNQsyAbhS`qxc%-6>~mJL~fs=ce05qtTP)=OyXQ&de*1QE}x;9Nh^@M{IjqccP?* z+`&}x-ASp}VB>pwaRK)8I~ph&x8f&e-4_Z@>*LMAZX!g)I!7qu)2A;ZRy3!On|{~p z8O->{1rW`(Rk7X1bAH=G7(0TmCr?gAXNRMSMMUhzokn@-8qoq9TJN$cD2&aOr>7V9 z9%IX&31;Ig?ZV9xl4pmpxpmQI`6#V2may2lcDeM9zU`s3_(%LT=BA+=3Y*pbp!s6z z)pFX^_qSV>U92$&{~C)yA7!6dS8q2nIcZZKF6Bw?} zM-%cA?#~j5p=oO=lpWTLNn$OaU_o1WFVyuTte7d!TGA^XF2zH=*j})oKg0*KQ^J3S zbxAvugjmGCR_UMMlD@R3AhN1aGNd;;pLM;AZlQ4#Vt#2`Y=nMvMdmf%Y&|SGCQ<^m zW%8&)L~g*!KZg5&Gl_P?bb7FHN3;G?1#>A|I8Wr>DWkshS?M$+oafe&n8U>nY`oGW z7T^KKK)hz*s;DEt10uKvLr6JfS);8Bxno1XcbmJ^a+8nMweX~fy#bR-O+)d`L@)_Q zi_FBRa{Io$EwP&^+e96azfL_EzfF(_xRDqydayA>fd}~evHx5;#lS>NPGV9I|NZ@+ zTXJit36SA_!vD{;OzxXGWCEQi!|>EX>$Yuc?M|gdo72B0(NXMieLkND^B_hRf%;-V?DWk!%6qyVR!zPg_&;TiPzAkupvoXL?^cm0jKYSwQG=00kb z?d5o%z!}@!2tP3wUx6*>pNcSav^{-r6 zJ})DfP~Y2pYoFzfU*NYjUoG)vB7MP=BQ(!jN*PNcKTl?WZ$oyw2W0f&;c0y30)9tP zHE_S&xf)0vkxv4Fe-12VbRfx@LjI+&#U+T=1OIAK>!Q=wb=0Yt)iRXQB8okqRGtJ& z;(+@g@=+T}a&HVXknW*I#6O~Av(GwWo$|D*QUca2?!9igQ+p>5pRYkW8W4?rp$X`+ zIj47Bv;lpw!2toDaU@Xst4!a|Mb?s?N`2_$8L0U%X*2Al6yVJO{MBSF?RG^0&Y<+Y z1Y3wDn$~H4vMHi%1cW}vdp{&LO znehl+bNKaGh8<`GNxxgNh|0Cc@_HQvs|1={rSWYaf1tDLO;W`P89eXGIsn3YQMLL` zU6KkVDG1ENBk=UjX?tC@F-7o)jI&b}^1vsS3HrQ_7HjHQ-tD*;)yFS_Fxrj;PHa%j zGtT@tP}_#=R4IVIP0%`;$DA*}%V(S?spD-|MWOqIC(E9_X*`+(?aE!aG!j$Bo2P(^^w#h6nnj~6;#}^{Y8m*LC6i9wU|3;TW z%zSPZ}GO{4UmPv#5$ zdl|4^VSjM1o+|A0KetiTt59eyUPb_PSqE=4q3yCCe7Hk!0K>z6|Lx$+dz}Ck+K}sj zUp2=x9>>gYC<&gzqiDeYxu@;bV0tLsO?>2_&p^@FVcvpri+% zD}8p2qo8j-l)+$c?cwdSuQlFIejKsw)rwCYU`ZpH|A`+zBHi)w8aF25RA$`Lw@A(g zxm&5_);_Fj+R&Iq85{2jd%+@#@j7hm>bJ%4A2$xj&b>8$To6N8$u1+PaG(rky0Cd= z${xwMdttn&?NG?h?H4YwpPV?tv-E}?Pp$Yuf$YNIkgGmq5NX+~DJuO)LrM6LlW2l7 zku{1kS!oMDyT}?rXI~`0P94J3Lyj$Im!q@vQ^r$ckZhaS6my53z|YKx@gg zMNLDfUB?i4*x%k$bahyXwulbQd!ebb+s#u<8C_oc-2`5^G2jzP~w0E@ama%BJ&OGS-&%jndlLWoP2~*=vKLJ-6)?qAs!L%F%__ zO6Z&(XTUqkF*pn>pImTfmqzRi7}-9I+n&;2kJ5EE1Pd||VhI#68lHA&&IX6Eegqk; zNU#oXbt~YYeaAY=DCLOEqqjUcUuAUMAhvNp9{BU^QU%BA8-Be&nl&(P&ZiZOvT)MO zPMkc2MJwy8z~9mve^_;iJrS4L|8^s9Sx{^%!iOBwyj9V`*$AH@wAB*usE0|@j*L!_ky!+M_n?mBgCaD+^EMc+gfZl;OHrgPnFkFW>@^^-sVbcr zfPMMTy<3%iGp^#vC0iLP%&Ki8Zzv1j>@fhhviZJx#GS8FJ?+w2MBRF))^{Wj&}o7r z`=Yg&)S>}Tr^P=Y0Xlw_N0NOyZMpV+0UH^ZehdJHZ^0DUrqCuQ8Q)Dg0@7?9^xiIF zN1c+=N(|---Q5nAdOn;G{d1G;tw%TUXMM`JyI8*&%vZWE0 zI&F<+_CZjXr#X^<)VP4njQU^Y%N4|EJcQrNK-P(ynRXPO1{%-kYfwLF)U=YzuF7I8 z`G*ft_zDJbro{Q1eSkRyQ%TK5T7brH@?;X0wGsid>kRZLFG(wxeRk35?RK`4D>ZoQ zyDu^NM_7Mwi3G036KR06IqCsOmL!HJj&y#*7Vs;f;jLG}c5`$8eKyr?kG>P z!BoP+cQ07He*B=N5f$K7cvTED!CBecPtv#-w!)N+NtNy-L_l}e>raA@vuevq<^rY( zoN*kE#CH?f;Y)&FxKX&2NlfU&TJL0W0Al zWp&$Gi)R(r^@68_K@6GNbrNwDHrhHfVBS)}t8!{balBpM@1EAcQzdowdQMpAH zc5Ep2xuy2UqhJRHN(jY6uj5Tq)Nv0^uQ;f)X%Q!N6#Hz29I6Z21WOWYXK9yY@Y_Fn;t@t) z5UmZN>nUvweZ3Q7t)L=p&gfoilUY8O?rISD#^c7=i}VEjapY4Xdk|4xR7ipf&9U!- z-mPAXn{Lh5aZRW4S@no`?b14T_GgFRRGD{H3DI}n=pwGaLyzg>;!z-h;WAFb%kreE*Nfj+iPZQ&j@Yg$30Fjd|SdB;pp#EUVV z${lJ=P&1WDvwgQfLukJEi~EYUm8kP}_fKMzQKt?f9cVoU}W?hAe+}I=4d|pp+?nkCR}VnmigZ99XluNVVYGNB)e@ zW@Eut$&su-+SU|SNpQc*f?T!5-*}f87=HxgCS5$i(3PQCK5p1qpKF}TY;(zr2Rr9# zBfB<>|03hG)|T(yxT^nUdA9)_!mLh{xR1s0v+8o>;uD3!k$f6sbpS~JKI~m!YV=^W zb3M#J4ee-gtYXkxd_a91^XPpk{2|TDk?cR=Ki=oVyXyor`<7zTF_pA)@3S7e{1Jm~ zPi&Jx)?~V2vYPet?r3*X{S#7uorbNC75bC$A>(dMdFQZ{^@AvU9cd2-4choBP*{!T_VL2hI& z2bsNz>`=uk=%=4m_RltH$Pf@ll+6?RAum_)(iNRvh7M3dS5mY@2}$k6E%fG5D({M; z;RMSB7xkI}yp{Jrz?y-C?+p+AH~tJfuRoYnE%myLVaI(Gv-23Xqiv+4XF3}}JhBXB z2x|@vE5)rp9suvsSfV2l@jW%8e5>RN^r(Fb`>&e8xWEmdsp@n&ty{@Fh@K^4>BiQB zGsn2c5xp3_-01VcZ5{7V@y{c%#!s`&uVmPMH13!S-ExrZ@K`Jz570f3 zj51DIzCY|2Uo)v%LdU<;Kw@17CAH%tz`-|9s!?0!N2spO$*QrFjCC^aXp?()!2JPW z=A1a`%Xj4dpr|brDczErpC{$N??Ek`9XWT5H9&vSw+Iv+Oa1AIz~|y8a2U;D+5{yv z(zo{NUpKxG3>dlfZ`{9Zs3pM@!%_2WWNr-kS>aCXr1Rr>)J&wDb*j|Ej$ z+hAy;306iCJIX!_a^RLoxkfNt84tRo0ss^nj`2B<=HTD=X;bTDgK?GC4`_#SSo<=< zDa}FgY71X2f7T`$EO>eK{9$zq*P*FERwZ&E82{l3(7p1C-o4VTLK=T-&#r44oK7Q9 zgph0r_BAeMM}QG*FrrE!rxE2eZZy6Qki*9QPNP}^Zw|;NhQ+h`Jxfac!wF%)th%of%mc;M@|C=Dr((i?+}blgxQm!X(ZQDY7q+(7i{V}7HF=`oppr{- zv8ES;iF~5)xILzdU3{@<(x3@!V0bV+hPMI5O=)v?o0`W{3mS|ZlZJ>K`}Ig(aGD27 zu&Hp=!aF_uDZFa?& z#cSkk7eRX3>>-7CI?bC2Fe)RALyX(-cITkv`i(>po zAncG?4{pRewBg($9f@SwH4b-eDrGvJGYr$(w6^s|VXYYZi*87h>c;F(>A9-Ha=y~Q z^GQ3`j?Ay+8E?7_r*idD?q|FFzPIwh2PZ&kzg?||qq_oTFt%y0G6KDA>4W$?;w6IL z?ZCbFfOxxyTTF_kU=oi}o3(qMx;g^9Qy~bvn!`Q&DJWn4tUJeGA?-IBS6@;pgZ>&r z(X!9n~+zBu8c3d_36wn z_~T5_vqE02Hp|cco0Xr^k8R8!7h1j{wuM@>>eU(upB7pQ%*O14b(D)78i~ImOYAF% z9W3L@?O)JoyB_LO4bm@7p4mK!ndb0Fs~XXLP79v?8Z-E?lOgf0}%*M#Rmn80he=Ct+Sb`!4wh-0OWC;^TfDaVwd}8-LEIEB+otAi`c58Ysw46 z)h55WCm;E0R=WLM&RhAqDP$ZgaM+$sB*gV2u@bKfv7fN$oo{KguB|%q?(aGQm=P%m zBbC56@Ox2r(OLM>GDC-Ujmudb6^xl;+F=ypyDTO+3R#~jdgN!{-JgyGOFOr)8D&0x z_Lmj@l;*gklE5-R2S1&Pm%HM{ul=0YtZc-gCv7Dnlgjc?0ogT*6*@^WN<)b+_pmU4 z-Fx>=Y#mvq^Cpk;180XKGt}dJC3__Kh)Fj0t40Euw{z1Wm~E!ug&41e?j&&ta>p5h z^4^OF#{CDIltx=KEQ+!#6bthf4thIB;aw%7L>VbjT&J3;HW=f#(zGHo;Lfm5y_(gS z!AyFD68hDSYs`M&wI%>;c7~hl&&S+I zoTaH&uO?AY+!pqg-=L)EPe>*RxRlKj$mZFSjU(Nwn-0Qw z8js#7p^TVFdUCdnOCK5Nm;~f`>r1Av8qe}DV>Q@uHjTZ2OjHs=-(d6!2IZweq4{%u(lgMOO9Sy`1J?!V|jiUv|M9 zi|;P+u|vZogRK7OHW!NiSmsscj7}8A`sr z0KqCw5zo*aK{eZzdL;{NBEtFQhFsoNP~=O@3!;4PMx{3EdaX@g=GM$m0&~A~Z67xd z`>F!pv_neSfpeCX;Ay|j@~K_`lSiVu*=%wFZze+f&}TF`3;H+Kc)kBkbDE;&o85Bb zwfhyAh(YEKUIe9Oh6+M)In3?OpDf?i{-P)&mrLGst|8uJb39%bD_<@0RLqz7C0=6P zJyG~sq{SSiR5F~5lZUP}%{6^9(6$;8f?J%KGo?Klskb75i(_Z*sy%|v98?I~`^5a` z5S#R2rw~%vP@5QC&QkEqGA+TmwzW7--zSfB5xPFS1?~aGGMyEVmPzcvq^K*^i>cqp zryVuvRy>{3fTTY=VX{4Q?bNf+o6WFM1E>Aq8+b>zVE9XH|1cG4{q*2F)>G|^Vx;C= z`0U?&vI#~j=~z45U#}a(xhACx{)mlrJrc_}vzI3dJ;SgWDQ=4wagcwjAK{eRqF*lc zv*?YJVmd{K12V$us%LC}m^F1Jfj?2hD9IUM*J8LL<)mA7ZBJqV4~Rx!M5YX5s?E*H zM}9P~k>4ds-ISiM*u~-IIU(YL4w=VF)L=4qQl1fX-Tp#4TO?sAa4=i^@9(0{X^A0($kNx~pW;@wEnFriTZ(Kftds7DkR)jF} zG(MR@id&=}%k1)b-NR@pSi0}N|7|Jl`!23{n8fB3NKxjOnu{}amPZ@=D1!({Mo)>= z|7#FQBU(Cpg?vsHFYrm-He+$}Ly%P0I8f|LS3L&UXyAF0v0biSqiqyd648Pc7Z&S7 z{%#ROzq$qLv#0Sidq0;)NSW`}K*^Z;AR9SysA=e^zDttJjRC5e+ND_XbnW6DZQtjT zLOY&$7F-u1sCaio86R6cBwEQe{+RXLMEbKpkNxMn*l{bx9$!)nISaJ^B-wyQRijIr z${C%yI5`s8a?i2aZW!@$I`e+Ctgvl% z=}WjWlvz!?8>Bs=1gK11D!U^}F<$ArNY$CAM%-lSzb-vox*E%8kn8ZO;6q{Ep2y^I z4Z?CFXWjPQWyx-VH&bAjYUdR4GSW1ejee-po>S9n7_TMPkeHcv9M6D)>;o z6g3NF%ecdn;xGk!hcUHoyUbsl@A2Hi#!Dk;tbYKsSYwj6h-&KS049{S6bEbLV_ASh znUHwndF+@_pN~`N1*(TrOn51?d&E0O&-Xa#xUrzf&#`x_o`80$xDA1Vr7Ab;B$p)+ ztI*%o*em9(l=xt;*t+1Ve1ZOr;peMM%}S8N4;!D5!yUG$!?TfwAQM~QM$}l-@#~)q zHiLrBdUGpEv$LgNW@+o2V!9UZ2CF-73I-j5H)el8>p3esgouR|(mzfYguF1T>Qe9c z19NEz$FmVe2nI*y|2#3#K`SphWA$0g1tS4OVGD(IUQ5(E$hQ@%&lU-H-hxY$qCDVw z)W0DHjPnT!991YQ*0c35Q?t%#nbJ&}VByvrUQbLvEWU-dKqADGwNaG){U6lDKmohi zI~iXhZ-K6zDhh(yO7=XyReV7A&^WMTeD#{#a8?v;nzgDAXB7tw+fGh|;g0(7)avh^ zb34Uw1X!=x*LMf9lOFI|@oyxrPnM37$tBJ0j71(;Ep@--h`l^eS9jW}=Od#g@93%+ zG?q#&TGEoN!gXRc%ztxvu@$A3w3GbCvubls+nc5k;3a{-W?1yOo3 z{bd*{2gx=PG32T`I-cH z5LTbgtI&jm$LA~E->WIk6+rS=Iq#26wk@M;>lmOGoBN&Tpq!mr&E*c2C)WojWjZcX zdT%^Kfu_}|PZ^TH6~T3eejQOR$(EYsW#?g~#@ivLQ5DwPE4p4bDpOA5vAfBZkAd1+ zAGzJ?M&r3d3z>gZ6eC9WAIH~}hcTq^9I?-|39YDW!!5tje3J~y%OeFc@^+TC6>Ps~B50C%nV-8wI_ z?MiO&5_(h9TNOB^M#(6)#L{_qj97W5k>n9k6OBY*-vy(Z zx6l3kWB^sO1f)XOf5!NLS|qT;aQkOZ%=5lxenVl=&^k;@gr!7l0+Atd_)>9|QZguc zqdG9V=H0sU_0k3z^=ixJjIyxv(IY0yOa`K-Qo+SEnu89eafT#Ds{aSiaTm)2vCl*w$=633K1N{d=d=VJ(&7 zUNniN)36vCJ;@E-AtFFWF?#i z(6L({vVuc`fhmb9lN8XX%`eOPf>*~qF24OptOc)Fgba^&S&AF9PjIPCw3?o6TI$q! z;I_RDQ>mTHGieeKko3B5c)?XL+g}6;gMsdlWL)8dDaJC`UE<)365@Iflm*@wo1*ub zkHjv$)Jdxi(!41Al#N5S=#j=gEfJ-uo$k)G?G5Y}#EjWwB~7XY6ZM958WoQxkvJU< zu53E%619Px_V~#3-@dz)Vl1rK5r!lZvkA=vINC{D-g37w0;`E!V})hkfTytrKc6%^ zMJKKe#ENW^!&WPdaq(%|q&=v5akz}rXqR3ek$;#=9b0HyPVKdM@#aDl#kOf!9UGD~ zh$*--#W1%Wk#yXJE0xAnlopwrP_d@yki@CZIPr@k%sx(CVV4W9i#EGXc8Qk5!8{XvOx{w*K7w2g7al>?Oyq0pl>;A>0aK7)i29BgTGMbi@T5;b=PO+;-XO4DO z{+d!zABU7YvO*rAZS>G1{DsLAV&89iD=AipKE$c>1;0ZEa+jD$n|XKGU}r|&FNKFz zT-;?(aKIH9l**5S&%~wnbL_oGQ-cGm0tSG|QQLt7?Hr}kQvA8-)YW)8z4GIf45Y7l z8i@+7%FYTdy?J_e_M~TV&TY`GkCyHQ;E9p(i~CPaJ8*aFp4>0s6lGh|_G=8NYu1N_ zV6xTD2Zl?1+W?4gZEG}bPmiP;E?jl-QPEri*e-b1hGwE_zmIsby+W0x6^xe^D!I4obBFzkTO?JbiQ5}fu8U;3A>RF!qtC@K|)?VQE{HW9O`#B z6r5}mP5>fnE$4KR#Amb1a%H^{_|HTv3Ic|vs0u`?e)Z;63Jfvg@3zgniOwW%Z}hte zI*nctep|H!G}}@;P`)i&`1=>Mn{A%lW^DUmRDkmQmdL|X!2>b2iU#W?t&n%u{ea8* zSYFC9kZo?jThk*_I-pIjbB`~{$SKXd;b=jM)Lv&{p>~d~7{;blcv1K>)P$pyEUc^5KKB=$F}AIoMfmBb&LS`;;^ zA-|6qI<5^_Rd+yN`R?wT_W2qaU)l5L3*MeeQiAbZK#ab$0n<%Nf=SYr=hmwo-6h3) zbu%Y&^Be?m2oMgzkKmgUNw~BrszMY~w_1GL00YvZM*6DZKk2n}arH03t)ROh8y!$? zJpsCZ`Iz&;=1Z#&aS|CaE#gOev1$zWKPhTgc=BSN2hjMv^|LYjcfArqt2b7}j!SU{ z&yDczGj2D^tWVIe-(knMV>ta^Evvj9tBQp`vK+#Ex>X{1a!T|jI_vvPab|Y#MRdrI z1Z_}9W_uJa_A;APkM+OOLjoF8l*!hpif~jlsoIsOv#TV&t@V$RL>c#n3677CTsFD> z6cA)uYuF;D1uVrw3ZuOS##5y&zRc^q5aVc4A2fdlepi03Dp5!X{9Sukn%u`;n-s5k z`AyH(5p7hZNkzKsFG!#-U%{$k;#Y{|?gbg~_}>Xpm>=O5mBh^j*{|m_a6=F@$kG?Tn{vLjJuRS`N3g(FWSx8EN$Tb7ba5> zNk?>DT=?CG`L%AX^69hw%i^dvGhlvge=N7?KoC&motJc{Hc6BCL+Mf+FLw!4 z!E<6v^|!6iZNe0ux879ppceKm>32AO)>YCw*dc>5q&bjf4_&lEa59PKU`CZBUtg}z|s57-_a@MhmShkEarQFATEbuD_c_vMplsj_LrCvtQ z;4-vA?_ON2Qf$ozfte}~+i{5Ny+A#L&7P+0N)0A$t^ zUc)Pwz#4YkvzH&p(>gB*7|ca6Od$1^5~DF&F1YWL`24riRfU-`>1a0fYs>0@ z=0MaQokpzf*Yxoe0HdJV!q02rvSdA;$H$ZNjIh$%&IqrF^e3p_KH(s`-mSILqU!2? zv+0H-Bry-6DeYVK4IkANog93HT3d5tPjl%|H6FkRdvWEC9((8KY>Rd~S5%JQ?3T5*b;ZDNzPI zmqv@;pw`c^(7C-vF0~dJ{OG~xCu%#rd3WaFWgjGSEQ1Xn0x#f%kKvTEB5gEJZu8g_ z`j^Df{^wK8)GW!~R!R>?pZ7z%2#!L%YZ1SUp?s`J&tA z>32j{JfLLnaWfW=T8W|NS{hwr7*VB;2;Y^{e)PPrKNzOFl6zW2tsP;sCsozPbzci6 z?>QD$8|ZZ5C(b7y*9{kxzD}A_WTHKAnIxgOl0O2+1C{Oa5UP>|`$xk2*Vc4y!@CV9 zOzHNS)z7dKlc`*AA*$@=x(V|CiMie8FnhJE>c`1Z)@D5INkIah%-CHa%He$;^iB@v zMXuL|WUt9BYc15VBZko5-(wno54a2b1S0%4^xO|q{vJ~5ypOI@%QGQ>6j9SUE^0``)hed{zCjiPS9(i$U3T~FgIO_3`|3{P$)XaV!`!&-_UDPb>IuJ@<)2RtN-d~(OucjyuKckY zev1@BtpzmNfb-N~M5PE@+zH>|=s}5|mzGC$9+p*T+%L2vf!s zosa7y_why&d~^qdIE)XSF+We zCi<1uK=;t33@M#?r{~5BmcMNAUKi{;v~9dti@D95(qe?;0f?;A|AVY73gzw}ENzf- zBZxX@Dw&;*hVl9&V;K$t_@z6ig<=Ab@f6rVI8zETJs*XxzcT zEmW9FP~<|?Z9O7FO#2j>R(53on~=&3I`t&BH6g=S^9|jA7wyLE8t5eXIT##Eis=Mjb?i9lAxNU81!h+spyG!N`#ivK3A*XXTY#Tba zSiuN|U@8z!O`}x~!6T%*Yhhtd;Zrn1Oe=)j)a^^a)aQ7e=L=Ovf(98#WUQ3CpJWSj zrgvajQ;DyD-Oj?`hUf_J-`cw~|H6h#?#X zpJ@&-@@tP_T3q|^MH2SCT&C;07+&lbE{E)Z zy+2?X&V`FleK}Bi9*YU(5fwJVOiB@5X{rsMSRznp_A^@X^YbQa#50R#ExHY8^ax3G z@h42C13S&v5U%Eny?%}jn$|99{BOwpq$FQmYezHhhsO#5L}8Ge^8>PvJ1XP!xf(F4 z^3n$v(Oi9|XU5eIbt>0gWEkI&NtsD-__Pb_?Wy#~s=^6?a`6k2PjsCS0j<&`4p^B4 zS#wAJofoet7{tMG=0RXbXDrY8T}R`Y=jK0d6urBI;|b`q$%>}h!|#Uv^+27l&Xz34 z??q4lCrRR<@a4Hlih$D1;((-n7jy7E4sYuo=Ygn`+mvL1r*X3rX7N#{{kTp4cBHT- zT2wsX%6}6?e4{`f%Sy{2FP*gi!85MkVqui^DD6!QnZNvvbET$#6y5CB&Hsmo5#Yhe zkL}9ZpbHM!EYUD;@7TCc>`*5)7L~A%hp!Ncax%Z9vQDbERQotU8n+^>e97^!u-R;% zRj+iijIpK86O2zqXS;PKF94kY@f8Llg z4pk?9v$P+BIUnJeK36-+DW2*Ksu7=*$KOnua+(g2GyD2y1!0_wh&0j9lsZPd!Skfg zg;QDLh);XfU|`}OYKzM0Z{1{Ai5BVC!r-;N}R06>sk z&1aH)UY#ZP-l7ElubK9h)f%=NI(L&vpL-R-?Zy~C^0MHH+{bR#wc|t4g{B=Yn69q; z-Wy1+)5y!aZy=rDy*ix#SbFVDKg4D79jaznkI7s$0Lz-YJO_^Ax|O90t>a5pP#R-n zmW1ij!|t63O~)T;*IC}PV2<>`DM8UA#<*mc+LY<%)M-e+c>@k-(hMER{M z6b~kMA`}UM;aT6);ps66qi6vu9jjh=xPnleXb9C$n^4v`2S=p?9kp@gr| zerYx)x2*EWU3IVj;V0pzw@A|pA5H8LMO_9z=>?{AsDxhGw)JlUj+aZ1+cA^Xv> zFPs0o~rd(1FmX@{M?u|bAX`G!uJ;Zf7(Uhp83Bps?1{JZE5q0h(z(Lxjh zG9VZJ42<+1L0EcuO46!UhCM!j#!xm}$p-M1_M`v%CYp?Bc5=Q8SnrZ#7{ zZj+sK>B{W@w@}Y%HorlA&S>UjbCQP1M|y81I&IXyQ(2}VT__W%Jkdt0Ukx|~(JOCj zDX--&n-Vk>1PX(m`qN8boW6>hBK)h&edg?Nce1|Jr`|q^tm!KJSgmT3!6Df?ki;ev zoP0zt)e{85rA}lC|CUaeAej?ZuDIaapPc$F{E`F%3 zHj@iy_#)0FqI!@Myj)LEhg|p=W&hyCbk5%RQWxjuky{cJ%IlRL$PaBW$T|+npuVni z6H$}>cXNIO0n{a;6UOj2eP+g&=`G3d@>;0p(qJCHP<&9w6rZi8@zb!)GLc2_dEWC0 zV@=Lp+7})zd7UsV3FFyrUdu_#;7)6Y2YsTtEIxL46NT)fXPW@q)Y*et7);qVbT$}Q z0{uWO>Ggz~^L=&qU>^w}kaTSRH#ri2kGtGQ-|4H##=00Iw3vAXZ^>F;UpUq26U9S+Cf-0RIZK;iHTx<0mOp74EKQzE5Ovz#)0`1+ye;6P+qF8gq>;UUON6nd zv4`Et<3rTLR2lSY>#4KfZ9J#zhIIr|8d;P4M3_a7{fZV@Rp!A6p1Q{b+nb_A@~WKc zd1Gqo6{j~Q>Z-Rcdq;BD6dQz_9)?e}httaN7`>167)a8Jp)Pzu@HxH1uxd%6pwZvb z)0+9b-=*-FUF`>!29{g+NkDztg6QQHpvPnCkgK1VWVy|_JDOR>YIaQNC=L*dH5aPtbzKtgtFNFIuy5t&oua{mYl`+e zyLf#X(0~eVke9t+@R}B+oY0u6hTNhR{YRj48Kk~$S=0Z(dM$`~ea~@Vec(cn;L{1$oVMmllp~3SIySKMj2MCm{ z(DBZ6FLb;aA3=bGv{5=@{2p?M;D2)wE^WT?DaP*otvQSq%_|r+C_u6jp6u3s(cE)En99Wpf~QluHd#NuPRi eWusVvlj|qq*=L|QlDIplzvuF5a-}jxf&U*Hcv_GE diff --git a/doc/ci/quick_start/commit_status.png b/doc/ci/quick_start/commit_status.png deleted file mode 100644 index 725b79e6f91d1de8e8240c28f911b2753d92222a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33492 zcmeFZWmKG9(=Lb;T!Xv2yA#|k!8N!vPH=~i1b5d)gS$iH7Tg_zy9KwylRV^o*P6d` zW@gR#`d9b9t9EU>ORlQjUzHW5kl^v)!N9)G^CSZpy@XbXEQGB}~<@y$du9>LTej z>>&B6YC+OkeOpev@4i9ZMk9*=WCJ8JI@iJQjYD z?4H;ZY&=9qSkxgFH92QNsT{fPCT=h6VOuilL_gJR+=5aJU5Mo>(I(UWa zvuY@6rKLL9nYEOpI{HClV7bVc=BPknSbqg`O#VpJA%lL9VbKo|Xekg?E~OV#;f(?r z*i9RhG$;TA<6{l;8L$J79*Vw>Z2r*u?u$X1nGKZD1rIAr#mfEjb2T0$6ig`JYZ+`w=&FGIq4Iceb>%CHbdcqmOnj&VpoQ{|Nf~`7=&aH_QJ>vUU1* zS}zl1{^toZD-#Rz-@ad11^#K}Q?_(7wb2x}1en@7y~q&a1P5*y+@*j!+#i{il zP7XGf|K|L!C;xH^F#j`w|C-RB)%xA~vRp#&0?dDxUI;!V*$)*AOax3uT=cyg_~9~= z=KI-3=2Krh!<>LRWIzx`SGS~P#8?s{FWjc23IA76P*JV*lq3B$1k@3a^sMlCY_iyisdBE-^xK;|rYRpj-0D(BrIWxT7z9 z3HkeBD;sfD)tE;h4mh`{%{R*D?pp7XI(@1Mv~R3j+q|t4v$cj$GiZ(%9Dg=!Z6855 zV@+Bg;(oKeLuJ93HN~hhBH?4)kHqzuyaLzmd)L|0&gEp6ikrqrDk>x-q~=OvrwHAn ztJGd4u6i}~0cf~3s~*B1(`?F@E}O(KSW_t>5ix|2z69d9_P zhlZAlN#L|B0;X7-uT_aJk~76(ewL)uy%!*b0iDhy+bNu$W^q2B%vw~>p=sfG5DRE-v>!b%%A1k%=f#ot0bhOD7^u{P;r?aaKtd#>!ubc9 z{h{-U6-Gmga^0{P4{}*+yfNi!f@yr&u~3Vh!f!>b=*4pTl`S^LZk+o_mW9!lRBLf4%p(B5Yl2jNsbS;N1Eu&E`aa=Ic3g0$^2ME%Q{g)6==?mo@MJx?8`hmzH$SBWp`GE^Fuc! z#txS!j6*%16_V>I1LxviiP{W$Jf`o{r!@DSJ)b!qdydGLp53~%Ei>D_%HG*rJJpQ4 zthk=oVROs1svo+Ie%kBw{672b==n(2!>eBVdbtn4*=oPu*%K{v7_7S#%bZVt=)Fca zFuJk}xQy*^-@iHbD$*G5*|=ga;IAKYSm;sATg)Y-j}v;&q`zB}uJOIR&a|iJ`RbkU zO2tQcwSnRAKl+em59*YdP{zc|Y|@P1`yrD}B+t4{uO3mGP$#{6atv5(`TLM-FhamTq_J5K$p{HBcXb*zS! zuxw-wM{-69K+5MG!*>djq16mBHLD0lWGjp#0DjR(#MFcAAG2}80e@4%%Qlo_&>c_4 z&52g2qVgrCpyY0o)oo`iQoSI;BS}ynciG^kRyqs=J`xITX*S%3`SkemmuwbdU|3y|T@WVHDC|Yau7;E|d~^zpf9}t>oL`Wu z?L?23ZK)X_t0d*-bl(a2ACz9qGZIOI7r4-f% zbAF$l^A49+H=;(IlE(=^w0z8WR9)a0Zn_^EO8u`j)-V83^Gt{jRDWn4w&2#@grh`2 z3^%1=mzLP7X|iR&OTQ>DzY{oRGs9dRRF+?)X`bq&KFAN@6nO^Dm@)CEP8lX}4Cfx)8h%FfH zewR;>`mK7}QVKRPMN;TeomOdxHs9N#WP!wdA_~tA!8ncsXop9Ey#rQCNn^{=@0@m| z&sbZ#`-#Ie4d4P3)u!;iIP0sDSj0@&wi)Cv30~A>xrLmM8+qf4V^*m2z=jC>b~(DV zW_ruVz`PD< z#I9e=I#~P5dotK&C&2v%ptx%iQ1(MVX+w^qYGx3_;;mr67Ul`h-gU8R0)SGxX7qAy zip-t7A89VioP9X4R;^JVs4SH17Vxi%frBbjN%(SK93nxe_ch9rY%%oyizQiH5x1{K zygz;@lsqtTU3e!ios-Lq)Ke!xYR$=#5;|pwj$DMX<-+eK0z}x1@`f94H;BLYQcBF}%puvro z30Vg573xSo%-nbPH#2-9DbK;an>Z63=lrzipF0+YC(b7q1G1c28%VaVNq1PWt|60b zm@z*Ls4RYqZz94{Ko#yk{zg$i;r9#P!N~H_{+Ff2r=SwZ?*^H$i$PcwErl==xJ^o8 z)6_AKxB^C#t^>NS2qc7;IfA&}mZgDNPV$O45tbUQuXVbM@FGRO=;>R(M zDwId+(a4PcoqhMD$jgp>C!aLxhZ)~A_rCZ;W6igr?Bw-BeD?4Ou>}wHMmH@-3&D|( zOGg5Ckwl&2OveXpG;D!f~3p3WHprGCF! zEbh>q4*8 zb8;_djE`t+cs{!lqNnT?-g{8}B#Xz`aafCuY8t?_=8T!6e;2uQv$Tou|x9_`aH zXdY(ou#hre5i{#DvhhAgTPj;IuIX-@6*v&~c=U3LbjUBqc)nWjoI8-miWodJZLl6e zTuesr?H#q^JB?wlLXesdyk1{vWS>6R9$6)E%G6max+TCnZwp8|h#Ml_xULPSc_^-W z#+~{R(X&?W8|>1jr!tz(JuK1l+=hWi38%PTFMN+Ad#~5=_{hx+Vy8!+DlStZ-l%^* zgOM$WTt-QpGAP4$i2SXgs2ct3?0=2xd+9&`bEPsnHfXE$rnw)%dnn7-?k8(+X5TvL z?ufZCGrR*d-rfEn#gs8LiTK)e3>%B;urDa^e9@(Oc~O5hW9%y1)V`qy7k1q40^a5` zglVX$H~=PL62_?c<;^{!8JPgfz(J=25DKpr&T9`zYJB})occ+;WD zk4~9G??*y7f@|YzSN7~4uoYzp;QC&n_onZ9uci4}^W7tj_hY+#s^g;xwId~qDnwe< zeLLdAW&4?Kmx>8}LgTkBk~>Nk?Z#6f0hig!U2huH-dtuFkJG+DYKI$XW_><{rK{k|`}LSR zdKU5g-#XvFm}U)w;Ao)=V-g$74MtKH8h9e2)xjFaMcjwF-7j~`d+6(qu+JA+Je}z% zhMqy=MR2CJWnYM|Lx)0Qx$fNZv@evFpf{rU{C;S10=vBE@ffo{FY1e}>D)1F5&-VOh%QLnoi_19t607wg_B+au zs>|c$z#T*?7n9xIz1az`@z2+U$3ChiwWU zde676)Ff1@$#s>P^?J45L|p6j?KUDs-cTlchxn)IY42U$%gPw?p7RT=E`%D;0~u!( z#d>l^=g;Sb>B%)lIdQk{gs0eDeMI+fPQ95SxY1&p z={HtCR1S}x`5CYy)`WenK#IJA7p1K?j~&UHK6emiBl>=@v2BI9l1n+|S@|cNo4Cju zv~UqHqjW2oT@%m-@9(K>_jH%c++ZKg<4-8yB1STL#!)s`3~mT)1s+}V-jp9N8tPz@(m5Sgt8k=!LytgPSqW?YQAVq@N1<@^!1@OCzj$Mw|o{n5jl$oNN1Bn!ow z*`MwNB^<7NfE z?m7t;##)xRJ0-|yU0D*fm%5~LoUAeekqR7iI;%UZDt?u5mQ zprGH%ZIhpuQ&$|1h0NU#o|tUz5oMJV4yAZ(`Ak-FD(Ig^;;J+#!I5&wZty3xlQFFFDtZ7){{T$}fCp8X_ zRc@nG1opG(xzV2|=oPXY$12UDlx}Ehl+Njwd83ehN^2TuB{oi1Tq!}V$g2$l zT)`o8i>Fb1>9?#L@t1DnKnhd%6C_Mp@(*xMXCj9rD|3sXWMAuTn+M2AQGN#+BwwHe zuuU@W-%xKtyY6d3(&axE@)LZP;uidRVcQDe}O2y=UNA2d-L)JZt*O{T$S9!X(L&2gNKwPvKE8NjZ z>)Uw{vT3Gj`4cG>YxO#*v zc)H7m;@COsE_I+u_GbLl=8F^Dj4VT@b?NvXE}Y^`gFDkcQQUoB(8laZd&qeL(Phh# z8jn?m7b-%mZPyWsNscHpH_vn^B(YbR*nN1+Cf}4dJ4QWo1Cnd08>$O;Gv9#6J1l28 z!w=VU8dC@L1-{Tq0|EHBh0%bLyU2PUD~0nr;F>(w?K6eYO=F&VMT%$e?wUk*JaSotmafMgIZc5m_iiZD75S= zskc;$Y(@)By9jD_(}w`&!40_W`}4E9b_lxd(+VEP$(eD23;$6REbwj-1i?!F=ssa} zNJ%iLPwPhR*-emaUw+mp^mNAU6~>9cAjD%I(|*Z3@&KP5NeO?|GiCd9CIBcU!Et?5RgPoeRs}j*_ zm&b#`BH3jPd+ri;G3lL~8;_7GMA4)y1y;D06Tw$P7u>CbAfeM)_&Et_FUFo+YK4;nGIqzQz)7QH{(I zChT&Z*eNol0V>y7QY`{L9;b!kn*!udKn8{hYu4L`%w!{_^*?0R4} zAyp)e1w6*wpDM=yHjhR|42+UX*zeMz6j69`5)ROn?{mXq9xrL0E-tStj;CkGl}|}N zc8>IaC)aYPP^zX~HLf@J!j&`Np&>U{kgeR$r!(M}m~j{&J4n15;#e|QuG&;wy2z9M zMdXI>&PJ!vaPa24#?sIJpV!5gkQhQyEvt=-T&4w7@XgSXULAg_wWE(_8#2G~teZFl zuU_EOx)Y1=p#UH9;uHLJ0~M^;a_vnS!=U=JRf1pF+ub=;#q_+(ezr}nDqs+;m@LW0 z($e)-uB(xwm9)NJoZH&m3Sukol>YY!@tD^1?waQ) z#+pJSnZl8&31!_A^TxqGsxxnNg0{6I>Cx~OJ;>o0QLmvJosZ-jP$Y+yV)h8!9qOc) zIoLm@`$v~XS)&2N1O^t!YcVMeqs~n#`fBGPN&7DQS(r(NIkchxtBP&(lZgtNwI?`2 zI2i%uOev9UMX~e4rki(>K%a>Fu$==?=2_ned7ac@d8&Wmf$921mx20$$IX=Gj}%5i z>U3|707e$oZ(-UjQb?OW*tX1gKfUo4m?&70!Jxg}p;*Va9C!4>dVKn9O@?uLvN|ks z)X5V!P^foAj$5cMIW6?02|+{d!yM@2y21eTuA-u)JNKXvIDPwG`q!`HuPAzUkXb8$ zO(hi~Lh{S>?OS7ZM@9YYe*$uUC7|D|ojdNMR$~BV3_s&9i3$^G7s^jWi5$ zODFWALV?v5ToDUJscv|PdU>zaeO~}Bwc*vbzTOXV?*46Z=xsCZQ{=bnfo!YP2ikE8 z{0i=@LUx(GRh0af{%l1qr6sY^dwGMiQ7X@6M*)x3=p3{iv25@;2~GmPd-?~RN6#eBS-}SGN1`9$;oT~x`wUdtSk8;y+;`!A;2(qPeJh5z-kRE(Ua!cuoEI3C z{LrKO%4Xs{9x`|C*gR>tX2|%-2j_D<3Kh?2xUW<|=p^jvppQnw^kXQt13~@A`7~N9 z)L-K=$z|1cN6f;ZL|XNZ+LF*-_4ArMb~rBa&AJ^4ErJ~=uAlm~F-$jiar9}JddqBG zmIk<+N0aAozK4mY#RT^VFEW#pRrNQxJ`=e_SMZfk?rj{WFlH)|Kbr$~6S@63h%LqZ z*GmxTh9%R&GM0Q|Hxpf0Wqm?h&Wy@ivgkv@PFma}j=nNnW|*reTMyaYuIaT*<+hOc zB44ktVbm`dg;k|V?lCVKCEV*o)D3aOPq;0H`UK(SruVG_&+}hisU>39)(F+DqB?{E z%6^>Ue>RHY#^*_@e0`ofLOOe}DWkRjR)x^Vvzx1P*QcbBRhAqyMCI4 ziJ5Z)ITE_r4S{@ztvH)#cA?%C45_ow)$4wI0pxzQZxf%gnH#Okph66~A=zYqU1cji z)Exv_In``w?B6ReDkN?2s+!Y}TsR$i#Yz8ayb!_nv8#W4WL}&q*b?ZI7OXz|@;hJ@ zT88j>dP)!P+&8ZfBWh$GwsWvf$D&8@3CpXFQ&Wq+U*dCz0MMVGe=_`5g2X3G@R?F6 zj#R=O93MW`uh(@!;T_3y>O(d$7c;IJ@&lMVf0rrcfIIC8jDY%6E<-^=Ps>3jEtvWG&0%sd@P^i&Luq{)4za?I z?|Z~|RGWI_(Gu4swG-FO-PTYVAYXS^heZ*BF@PzzLf7P5`DZ^@!B(#nDnz&02wmqnz zx9~aXG8PTTWl7$9Lf)430R`^UQ??@RcW!6l3QNf6fu~=@H*`(35C>mTCF2pUlSX$d%^t(q~cPw&fR9rP6cG z#at!u?A9{LAGYm@nWdfXWOB12-bahq`%Sy6$xn^n#_bK?Kad;O$6|^o7Nq_+ayReA zM^D@JchVRd1i3LIb}fW`XCgH#c7g+$eG!;Z1V3jACHs-m+JWrc#gwrEjU_qaVAp!9 zX-$(&?*Mlt7Nb2Y8v}>T;pa-q{a@s}!*I#N_@pb?NVuo^UE0-n9rfIO(=FN8@88)p zXS1oP=*VZe~_%?P}SJsQhy}eic}Rg*V>p< zA?lHudxI5Y&?rQcU9nmx>t{n4g=(Rlt2r;(FWH(`Gi()4;{=6I1864M8jxO*z5>SE z9bm)tnxw?w|50uApxusfsM^Ohgw^iQuEs(w-#)12==$Gw<~Nr61notI{y^PaWp3AC zOd6xaPo+?H*s96*iZ){6C>W}S5rnIY>I46x#Tc|}7c~pwD{0sNrfy&A7-ALtI>t>7 z&}KsZ#f<%n=|F3{-_I|$Uol~Mt`{sbwp2=!_)q2x47%+53(#CVIGU>VZ?Oi;JQNOr zLLHHj_iG78!}pich%!21JH>yoXOIbop*_dEN6_W#EY`lmv+y*1e`w)-9rgdl!5FQ$ z664*xAx+YH;*VnNbvcc&(sc>Dx6MEgI zx>Y*isO2kxAF@u2-Cp2G;$R7>e4a+gS&lWBf6NvpVSauqaJPY%E8kjG-}I1|*+=Yq zi%;;_=_OFJ8=BbemLUDQ25-?$ae3imSyL)BI~8g?m&aKEy&VO;3C?TpXo6Dij9Pbm1+b`lxkKqR^2ZoMw4$}2y( zg3TWQgD;}<tU{6#f1BE0{R#w+|1K~~vqdfpB z@I>+{5vy(I^fn1jJhmc|Tb_j@o~RDdBEAK=tFGvF^n09>$_bTF^`p@VSGB;kL@I%3 zR(v}S!rqbfgUa$#A&WS+ztu!6Mi4>>Rnu;UnsELUl6ZKk!Z7m7g^b?NYLpgVHAXUp z{70IIe}?c2cXob=G@2L4s%wDn+bQXdw6;=y1QxKawx9^R-A2XWQG0k)oJ{k{d!Kq1 zMjt4Zr-eh7tN)DR16-rkdEJNHbcG?tY0$ePWC=E4^e_|0wG8siSk_Fre7wE(VQ}{i zdh4XPHcfn3GklYNAiCV<&12uGZZN=d^~nge-RGGG{=UG_dO_FActNq+HJa<>jzfWJfEiy#10@!FIV1z@HHi)cd3U$rK@1Pv*vLn{E+PWFsHz|4 zXLXkxj`(q)T|TdkgwgP2to(oLu$0%T5MEMZq+WEN`3)rWSBizWbsByA7kL>op7yR; zq^79BKeHSF z(|N*l&VZL!(K)zhZs(qRH!}%cY_gmNNC61~dY|Lw>l$nGls0o{eNiH0lF$CY0%%-A zT)nwV=3a}=99|dnU!uF~mH5LG^@YD8;U>GSVQHBMGiPr~lj}d+7|#=f#?^?8Ej!!S ztoP8t2NPKICb%Dv)aQjS{lz)i&VPZHuSwQD8tV+X$gKF$SiKmxne+lYQD%U?SGoeH zAVyiMmbTfTWLATB)3Y&~n#buBKqcXYki;t@(YzS(I{bDP*vm%RI!K?_WSn6qv{xXI z6gN2enZ|0Sxm5%OY0Yqw-mUVNPSO)FlSEfCt}{k`5rRB#a2@VuHj`=%DCP@V=@Q%( za)$^(A(nEBDMgft!2c-rjCi2$jl`{(`Z=Dv=i_=;^4K6vG`c1& zIOY_ITwBIom;Tp!G9~=8Lwaf!8nqxaBjVyoYaUN^nIc=IyrK<-2r-|(b#wvHUis5; zZ$*ua^dmn9kAec;Dv`kLoP`jX)`)Z6$J*3A8qb{%3&geE@I@dgbp%jWnOSUk$!tVR zE9~Fo>Z`y8cB0whV>;@d-|nk~dANij3Q;yFBErNy8xt&CA~3iQ`<-v>IBfjTOcrVe zXE!a4#=Ggx&uUu(pIX8VY~~1@^V+3ht8e+t-4quuM{YAKX?TpdD792Wdn3$k5J~-U z+CrAi3ua+&HX3Xk~v%2m2=Sgcq32=HrjA|V9g@$;XiR6S?(6T$tE(E6cj~bT|NG>_!6Un-U=g=ZF zMOv8;#{1~pKFGfsjt_5N42P=qMlH#GS_`YmeT1wtol^4fbrP7W6Jy_ozrt-g2qv!lTdyKpAoP7Nh@HyJt8wEwy}mQ7($g4{m6X^l!!L3 z>#qj1ZFa~Cf`jgAq&kxPb~~^@;= zDxI*GX$;?2-bY3J{I0q=J=m0Kq}46>s4nm*XxbW6wQUinFe63Cor>nO()=s>LOjfC z;Cj#n?k3_X35umJ>NcPXia^udiNn@&H7Muvb7#g$e$JsefM)qRLLkp<$Y*<)XS0*^%O41L1#Rs z{*MRi(iUV#9bt}oD`a4^^W~8)b^~^mK4D)h*#TSO@fov!k0p!$5FUYoW~n>*tM^4? z9}M+S&fD~k+qm-8M^iSedP(i4913>dy%x~2WWRV|RB@@?uMXh{#mxd0C>qAC^#@$_0t!nCrOI8aYdkiwH_535 z(GX)>9NhlurUI?Cl+dbM4vZApgIM#I9(@xvlrMtAU5;^2B-|VS^B{x2;@e!_N=-}!e zU}h1u*CP%_hfz@#Y6wT0*5tCoFZlz<_`mu;EI}K|{RA6yTyZc`p5Zq?Z zu@D;E`>#QY*hl@y#d#sJp%=0?IYb_<=h1ImKxQ?x<Xn&J~2-r@K*^z?5>I_J@iZ42(y zPIj>Sd4iW$><*UDbJ|UVM+3a(s>gq2Y(nT;N0eC5Dki!}oJYq+PytWArxwn+wF3`#kGW3#^YdC$MSS;K2#K@(RiRAw`C%rx5}?YT0kM^u^07QEA#Y}z#9sg{57 z1B#DAiITwll$fqQ<%v#6BF-Sp}VxbnDLKNy#NE!c{%`L_&BlyZ&JF<10s%E~-w zJI2LAjkwq~qv|AStY(-(o&Ize+;$N|%D9ls%2r#_`?fPrp{hrT1nkyCEo!giFnA|t|>Js=$NL)m~=xQ`{A@StQ(FL&$wHyX&B?85{~brvaT*ARYjwhVvJo% zX{wqrB{pmvl%2QGcq}cmiFfU2wvPO|XQE7N_sH`ThH@I@Smi}H8k3W<_!YEbJMz|? zTm#MOiM)~1gjTj{G{kHE{5BimpBLwO} zgTffR_Z-Nl_lPT+MoCJcPQKWEw?7hoYPmW1!Vs9-bGH~U&3cvg>cy)ojRU% zJ<01`)&jS8h;}vUuTPKc+AlujR{Pr={=+xsHoE9Q#hL*wAN3#97Iu zbzGn7AFUR_|3@SHkD;IPJ8p`SJd0RoGECIx~xuqhcUu*QdIKIEMS{lw@O~>2rul{KYxSxW{TI9rVJta|WfxqNXwJ!T0LC z5`)4f_($pUK(h$QV)>3_2Qy`DEVQpQfVic}dK)RLzri8N4RkMZM8K*aWA0yAQW3m; z(rTo5=@ol>xtm4xayP4+FKzg5OzHdrK?3hj>0Y<;|2q_@+vTkV%t;RWy24C|nLQE@ zT?XhGuP(PAgy;+AiZV*)KOO=p_~lLJXKP`M2rHD@Y7U(>R10iON0gC1`#2hxNdEM1xB)CY0u^lM*O1l$Pr$EKyvD>x3Bu02KC{^ z=MQL)oPYP)1c7R3j|qkqtNJfe`~NcvBaNJ|fz-l&*{y_n+mj-j1iR1f;J*wa+R*Di zCckWL_!Dcbcir_YcAG4YdjQV%FRft=g6?)SkQC=? z3ZhbJ-MkU*D*qYbmz}McXy4Fo>&g9>X4{z13XfNYpc;@Va)h6gdACz9D$JH#Q2Nz{ ztI66KJF(GcD9OOqleOeb;@XDRzF(~j?>J-C@jx48nbJU(7~CnpOxE!I(;)p@5Ok|@2uyXbM+eiaM=@n@)r|J zE}7>s`SJ!Wykz57wc_a~qka0++&0_r<01dfC#Vo)nxT#m^3?Vg1k1d3kebnDt#Gm? z?J7K?j~y6{TQB+(4bEN>_`G4vvjZb!c-#RxjY{JU5gf(No)I7(^?7u+@pgtByMSm@ z@wE75jV%OnTI2#=_ZBE$ZkokWjrI*ayF&6ku?4laR_j3k!7+vJ1oXA(N`1mGAd2ZWddR+$~dwQN_Bx?`X1m_M~lMo##u9=k&L^7H!PKl8#2!Dog%<+6P@MHsys zrb0|h51;dGBxW9N6vK*I+}|m|bbSqk-q89F5fC7)`%=7tYZrpKL%an&2Ji;0aO0oJ z_gyrwKDp;wdwIv(ixZaP5+$_mCE@MKVw@?RNk361L)>4Sp_N~@m2KKeiN*u=e?)us zawHFWo}yu<;-5_lK7UTUrqS45KijfCy*&U%)BDekJU1gLJxi6QY{^wNYTnz|0N|Ab zyOjPOw-nG8QUp^Pi2Yf`zd1oLQpz^dsvc2l>1Rmv{fK_e!+g*$Uv)(#*rj8EUzOC& z_uVsVnX4Tmt_43k7Hupa^mH77i0p(iAi17ve#q2n-&?SJBVIc;(z}ch74PRRoE8>8 z;r2#^)RauA!xrDJDI-RrTQf?c=&?gzkH{kHguxVZAYbZ1gn(zzpVDR#|1q?N7VC(z z)WBMFjhe$Ek-lekBjp)1Bz>NcYu{?ZT68eRXGcV`pSJH1Jx+Z_{b+^?C+zgQkmuDT zBgxu$h_BZ;xE>z}A0iRSkTUlAMhsfQ64veI@wc=OTQCP&5%_&B{F_j9wbCAAHQFN$ z(gZ@DRsoV72>`cMj-W3GW+Zo+W-{8zs`$r!`GgWTYu8TMXRnKcb6gwv{$<$tpP zsNW%Gb>oIx&!nCf{Ap8?j|(7{ghL`SpD~#U4jhKK35yfo8qFW=zaw+^IHazUzNp+Uk^wJ}gQKF`hu_bEN>u0LcnKa6gGL?Ni%I>zlZ001$(ddXTI98BH` zSWs-erny!dx=8FRnE1~{j|v305Y)u-R&*Qr`;yG8euog&05o6GXz~L}J^U>nVEj%4 zb^BkNfCrK2I;>)mR2lzz%%Cb?GJGV*x?KO>^%L<2LE{iW+x8OtpF-gk0Hifixp8x2 zIgLpQ{MX?Hhllci0RuRktPo4O%%{Nih@WqyP&uL%UNa?r5F6MH+c`EX14;%g8&i!w zx;R3ip@x2&M_tCRCOJR@WM_}rGHg2Zs$#N0yAVPz_$>9#hgTvR)TMt+d9&|4-)j>D z=8GvO!TAp^@xO!OWuhOgHG>yMQ0 zGHHHil#rT2+1SHJlNry_|LsYi-KLfYvTwdp&Us5smVluqp6ip)-$WeA6!e2)v4mTp z1sXOsY^i#&PvJe$>@dwxnRsSjb#)0#-Fx!p+?9+PghworD-1-Uy(+7*Hq_h^B!-1 z^l!K;r+E~@y9J$4Yux-$!%0*fb$1UG`#a<7(P&&lM zn+Qp(xvVCk{!bqw#rsmotx;x7%PUJUCa~6q6F!{cDC4a+Raz3NYs{--Z`t``yx>xe zUUWum93QpxgGb#(LIcjdgm<>$@(}RzY=_OB6KjWt#w%EttJ|Jp&lz6B2vNE<*WqYS z9aumh?{R^NeSc8GAbbtqNH1f+xqUJqRHVdML-DTc`pj1k=&=1R$c{?t>%NAyL8y{p zZaf;0r_^yi?0XEGv)iUJvV7qsd{~V`gg{;Q_BQ(F%%|JUO}N)7y^}Kh5e?ku3{?^Q zE`|Jw+anyAcOsR5pWKV^plQ_xt0p17q0GXm0!T`Hrc$^2V@`Fi4r?$TQJtNSfLt=B zz{oY5J?nt|JsEqszQU4DD^l-L=~$!b7SroYvdLM@>^ZoCOZcq@-WfI79_A*J2iKwu z!$^rb6k5{6f%+X7PKM+3zZ^XZYN{Q{Z#M1DvEv)Xz1`%ye{WbKM2y5)bY=NYD{xb~ zul!ZV2c?0MI#e8eXsevjDzujYFb;){c$Zh%Np~?eBzFp!`^!0)*PDqBs|&twMk=H- zL!pH0<>iOKTLQ@yFt=p{ZQS`QNIfeVl)iPH*C0|*Qf_vQWPMVf5g}&CHtf^7G z3_UI-<@5X505bE7iAnY-?bHwfPgK?RQlwi>Tze)#$NUyYeusgJhgGFwv8tsRr)3p} zb5}c2rEL!ldrCXLd0hiW;w!%1Jfoo*)m+_(`iC~hVY7kPdFYDzvtpa*OuH6e89;h3 zz|TS(M|x`yy1=g}ozW-4jCxgZhdC2>uw^)A$>b{ z%BnA2`=krwp;Ia3^cE3omiG8H&w{EAVf+%DI%rakIoO)rn)4m{4`prS4p{lNllQ^7 zk15RD&k@bJrX!drVNjk-0Y=9b7m$1%!t(07xRtB5$7W}#iOt0Ke)SJBiYpi+@U42N z&EUtsJ1GfjF^?TLC>nwK8yS;)f$l|&;7CEsC{7F>4}bfX3D2EDNHSSXZRUyxm?-(n ztp~UFic2FyZay@3o92WmJwc7+guMnf zJa~^tDO_R?VO*IBJmwlJG4Ke9Q`#vlGW-{NAf@%U94{%`ny=d8yypX+_B&k1qV9@S z7h%@axLcf@n#W0$PR$`g^~j5P`VM8?ww~IXaWiYB3K;+gIgs98Z6NYb#ze336J2Ol zeDK1{LSng71f)PwQi4`P&*g-G(mO&V) zOf%e>*L%MHQJ4*zmbFn+AAzs9!5fbk#6)zp$A;upL-@a3K!q0%wfrB7KmQW+f6sd8 zCam>aRf0^|IzHCIINIgEB33Vzb&6{k&{EzPrQYN z)ykZ-cJZ!J)KB>o>JoT;u(7yty}xfa%$PhsZpZpjQ@tlSR6Q|cog#Dc=B%-VF4Ri> z)*ziVJNE5ojFpMG^_iI*Q%5j}x6GZPT*)hBT4xB@B(fG26i*k>w)?=t!uJqH6X(xnmcq6D9rx&F0V-=t4d`aJdYLw+q zBp|qS;g*S?tni+sa*sM{el@%2zIB9LCGw#KrY2e0X#{XK|9EL+g5~cHaD zskn?Wt4KhH_Q8u1+AA?vLbTXr+2MyzLVFZ_b=BC=gk}l?(s+GI@5q^ z=WI=%ayntL!IS^h+&xBD@~sU5?^qpM9ox2T+qOD((&^Y88z;7{j&0kvoyq^+_jb=( z^J(5SGi%Pred_Fb_Os79RqIzz?K)_Sj5JsBk>e^jtYOU^GtvRoXJ{}2F!Gca#AcNy zektf)vmMh3=4Tupx!E(RhDME|@E#zEt|YCSvvInMyiIFupZ3+5_62`BPL>@jwHCdf^zFF}{5KMnC)=!^HhZDw%i2Tm8aLKR1HE6kJrU(+#mFRn5h?(C6hZ3ag*g z!*T|7-@St>h^_3WpfEh^M%^k-=*)D(cO z{nATn0OlByY!T;9?L-UJG#MOpj!XM=JrN()2vOA8m+JD2`RzP znQrkT4|Dgaz{w+$@*7kO)()>^R^H0Msz-Yd8ba{GZj9$=ovoW!2&;fn#Nk!MK&JOn;PUa?0!ZNVK zFtqH`Z`F7<{XE&3&Q)w$W?o$tL%*!8$QvU`hIkQWK26QTFQ#Ig53aMhNy8OfFDEpN|jb!jInf5noSe4 zFq}$5KKU?cb-~E&5-kt)03EpaP9j&@SAb&p;PND})POo?f-P?oJVSbrP5z;f*DprI z$qQD>{8m(gCwyM=btPUh3zT`;*t$6O%kX<{{))2S^IW9jk5~S}JfWFRm^*Ka!QmKh z4l5R_tSy$YeHYpJO7fNODR5IKyIzKbSh-jsuG=GW}#b@-tOX9`#Ma#2u(GBWqTZ4p0EG@gHk0I93@rdTX=}NuPh; z{7Efn4mAap)$Q=lP9|3YU^Xh{eq|ZqNqAI%H#SRmp$zG%C7hTgx%EhTRXhtyNFCh5oPBQDn1tnCl6QyviH^7ebV?LaQe#a7`rzMAVmtPa` z*f2f-3QJ)thdltWxOanj2fwAVE>8by%Z{sq5uT zyK|=zD_au}10A$s>~3X5wRX~1iZgni1N5%Z*s`-@(p-r3& z+uJTt^GBA^Qd}y2>DBLPK;4TD!3RY^Hdj{0ReN%4A_UK?jbX&2&zL?{3$D_ZX)T=o z#5g^ae~45}9KXjpY3tAU0?K?vUOx1j@d;ObjkXfN`M}p|7~5KpND2U=i5xqmcgogy z!ab-SIx$|QjQ*kmWxI_wb_4kxr}D@AJ1sd6dSfZD?HZJp>wOUu)2S@_Wj>f#%{`!@ zOfkqZEGCUG9Sb(s$oV=p97V&aRpI@*$d*~$KK{5R&PZ;*ZGk4SbAKY+XIIJ_=B<&l-1dVuyf^0K#q)0l}S-`hv1K6#kOXa0GM@P^mbqlLKAO=cq;>+ z_){^nY%eMJ#PTExr4ur!C~IFK3ZT2}S?wpVt<~Ig&n)YKWk82~FDkKH;>VDri7m9Y z0+6>Y#iTZ=5?d+#ggo8D@B?&E{J|PG+mo~HhPCgqrO^R_%@g+ve9G%j8oemgUxKCY zM<>#!gT0kNkisW73Yn_WzwS^c?Hus%tFjsF7~=ODhd98lAwD#B_mgADM&!6zpEB6y zNeSY;m3+8{v-{hW^Tui)T9z}A1gJXa;?GT8DTR++EPls|zW3Xm#oQ5sV_t{fLG#v4 zQV4xP%;ftXg~x7WRSzoaaBc1jxS8?^|9z(x+OC_a7tbJGIW}z;&(x6IG%*=sqoawk zS3pRl8y%q%ShHwPR3l|+^4lfohF4eQ(*6e+&IZVNBg?}>6WqX|nVR4Q4=fVe5FJ{N z&(Vd7?b}-PTlp_l4GG-Af~(hcl>#D7N>=`-)^ctYba4r3sn44lvZwMT*@^8^s>`8n zjCTpj+h)%m>R;dEA@n$PJZPi@R@A246O0ZE{2Nr{hfOcsMRJn37(@-n6l68tA5nd1VEXS_e|kQYTl3KWbb8)d?VcZT6mXJ zBiVd{iCt3nL2B5lH|L%e%hl-zT zSp^;=J^2rBL?y0zp$rPUByeBpkB}VgRi@1UV$@)o4MB0=5zA=%t)Z;~C3(#m)2TC0 zOHu$R$i{TP2GumJ|4xQUvaB6758FCx5&yZ4)#v>_3k!hyVO``Wt3qwGgX6`Wii+l8 zPZg4rcFSy$)V3`{g$kQ39z(GUGm_e~)?tMRoF$*&!9Wz|Q}QG>D{2AVhBGdyv~d);yecxh=JtPTI(Q8O@Ub8MD$}KX|6A6XV{Iq-5nh6xE2d z$Ps`+V+Hi-!P9|E@qM#i-p0E&zif9J#7yuEq>McHTx4CGtY5TWTpajx>?rAo`QG#k z4CyK3$WOc?A2xIktC^qIkC)#X#c5cKsN*;zwl0ZJXh?5!%UM@WX{}_jNfP$a*aMYY ze8^g1wR@AwnLUo3*y+C-cz`6$PlLhyB&r{KHM98f#(f}4`s1AbMh-%tmRMIq&Mra= zZsK(eTl~dF{XqgJ4l<%ibjw8}oQt^Z=boHz?9EukRm$I1{lv5)`a%JWIgZNCQ0 zn(aKF=a{6sCVAYiR~3)SKp*7dKW^iy$v=_Qa zrIaoNvTUwUz1~;EA&Aa?#q#QToqb<3d#=?<+1oFycCWW&Cd`@zT^!M58&6w1vY5&58ZJ88;VJ!j_~ zmn%$J{>`AbRbTAjMjAeQ8&DUH$&t31i{NaW=ED$md0Q z)@Ty+E^>oP@6RQ)8D(9%mQr9(A?*i64@7D&1~qvvA&2~iOOpX(1pGh^geLZ2y>K1K z07Tja`mZh<1vk<3_Bs{wWDz2(M#28bi<*B2YW@5u7+ z{eGsbYZAX}+uZyXx$)OO3I10S?GZlH3I{wk_n(H(i3<1<4#=63Tb2A1T9*K*I?n&O zz`D-)GM(kywa4fQ^~sC*{Tq<&k2=f)(}4Z`-yy$VpYkr6jfUjz%uTjNc8>;w=oegH zQ;khZ!}yy9o4r(z*Z*CkpC2C=bfy&nSUS40sMZF{-)*kF@W?vkAvIuseYs7*LTq zm#WTtY|0C{kKHQdZEHDDFh3^vW0p_{AsWudcosJ?vM^M6@-=>1)SF z^%-zi*+$`JdD9_RWh`Ipo$Oj+3j?>*P%SzfrFz43Sn-e6g+4|HUo^_q@)%n8V)u4`Z;TCIx{<+X5rPp7IM|Y?ixyN-i#0QaW>V9^gTQRAq8VKozv*e$=B=E~A zD{wKkMmdQozniwTGD9xYO(?u@wjhtsZteBKZ{_fNDlB><4FrJzuJ<8 z(6S}9?9-!Fim4+;bnJ_hPs^|HXs#$GD2;70WcA9^e%*ouhE}WgTnYWMp`cFoQ{EH1 zgF_?O8VRd8&^aXEs6iFGmDN3}@0?CMA@JkxWjO zK*hth3|XN@|#3Jqyfvw1%zniQ(#trJ*;bILWPO&ji2XSF5s-@kClXm18w= z%_ppVOTTR*Jfb`8Oeb!9`fn6h(c+Fe7mm(f#zsB@zYgt#Lar1iFmK0HxEMYX2v>{Cl6R^~<9Q zXvZt7Q_9dFeXoJ%G&T7x>S9Vll*|W4IIdKHjpl%Y7{cXMM^?ksYko;)?o=#I83md@ zfamjSQobp5INZQ06!F*PldG)_I>8f1KHcYfw(BTeL59zThwGSUD~f|^@Tzw{Qsw!P z#r>ku4WAV>VZlfSX;{SxTMpB19?_w2oUmf`@&=@nJWlZqW>I^88bh^6x-*jr%LE01 zMwx!IiQCf_uqnkXfN>tozftb!VCHb|{w#TsfjM011EXx=J(DwBZN)czcQap(q;GZa z8PRfi@H`wUb{o`$3e8dCh@53owDeS;r-d}JwlHHsBfJ-G3%kOQJWmKtK$37e~{Xy+eM;VpM9e%bh) z=!~8HTf}-L1N>*@Z4#91hsy#d6rhjCRD!n#Kt9@!PGU(Hsabqk(zmd z26q<=Mxv1r8tKncTmd|JF$?eS3ZRM~sr}Mol4I1?+&8$YVvmvu@e9m^jO?JXQVZL5 zb#Cs{b4S9GS~O0PqCbOpL)6}rgM#4JwUYce9sx}?p9S2C(RHqboeeT2Z}2e8*FU8R z0S&dtGNdQ>T4W{Ux~t}-9BZLJ=4DaRgkM{-OY>+-Nw04RVDdWAy)?frE;y}mH25mw z7N#1{0qiW}Kv6H5hMmrmx#&>1yhr6RurHqvh`p%0WsKpq*#kg%0;5b(yq}1!hw}$m zdSz7NFj~kJ2V;+*kz81Y9gu{4)%gX7>rv|k{S+Q=HactbrqcH>!jqDM7O6!=aX5s# zL$32_;S!?QG?t$#a~W#{HEN(o=B|r%_Uw(5k?ik;%|SKBVEiYmzL0ZSUa1;TA(`Jh0kfQi3BZfY+fGW0gbar$F^AiI(y4%1h3TLdQ#JeR#37cnB@E8 z{oKks*YRLC_YxBF<%Jy|#YZq#vgVT^Koa2ZqmWRtI? zAUT$=7K6?@!IeA83KzFL)eFRGIaTYyaQo-4Uz9sEHTt`Y(a!o;s8M6a9nuPUsSIZx z3WpU57_DFoT)-wr&CAz45QF5GFHo7+Fy4g;AL>B6< zva%ZDXys;Tr3_3yRH}G`!j>*I>6@rB1w$s6CzO6fQACseqmok}Yg=i#oTKUV9WQ<| z(y1jD+h`jN4rxl+W1WOhfJ+CXtL->}_}MT&?+v4@HZBv-5|oFuZ~kL<8-_OZ=&bMK zcv>zA2Bx=Pxfv81b{|8|sB6w2W94G&L_EErGQhnQEn^zjgt4G_GE^(1Hza)Iw>l>4 zur5_iur+GOg#b{ZvGLr%P_+XD-7?Yevdn;{4#a^G;LAthlIR~f*}y4zIo$&gf6=xsS8 zD-WG+91hoIc0h$Uhrd6R>BOvcA3G5^?)O~{VrLXu*a~k#Ul+w$)0I&{oqj*q?-5w! z)lue_Y>Sye9lh>xeAv)oAP5`Z1UP1X9&&5f%dVm3>&$YCxG9yC2nGNO{$cm?I|P0ho{^>? zE)s_Mm{hJqaI<~xPx4N(zjt)(PSnfQ)>ts=j0tR9{XGP~u=1dP0pZZM!{-BxG9|d( zq1P2@6K0k8Rl8YsP)}~Je`NN`k`2?kZ#^BDZar1x_HT2nag@=VcO6}mhO-lzT`*m{ z=#DD8uOMc#&3J{1@IcWn52s13IEUE(F2qc-pqdc3n~r4}DKC|e`l<%ZJe$9HPC?_7 zN^%r}Y$O6rTovvlAIG9xc;Q{KUaj4Mhk6=gW3cZ>H`Fd%QCM71d3U5Bu^K-U1u=+3 z4sk4&I!_od)byo>6qPUJK{2zcjb89XYfMBlZcZKrCwInV$ZAMj>sBo0f+hSl%9twt zj@|b`hTli~oU8o;g>k3Alw_xz2z7U+#BTzm12U2H1df~q8Np96J|S!jj;W+$FusAf z*D;jQ2|9O>jN+~flR1`=Rj0g9Y{}EUE+F0JMM5bG>bGF*MRvN}_v7`nh_QhZ3$Alw z)^ojp9cILkM%r1US>;Yh)AVr<*oli*EEyY9x8k`=Y>9Ak*s4q+G0qgeb5nv(9U(tkQ0S{PPNMASR{gArYbvKK)vUQ`O z1;Xy6^xBuNqBwj`K-j!=LcHzwbU)N4$w4Knt(x{p_#CjcOkjRt=*$QEBl4*bSS)Ci zO}r~`YI!j;4=oh=1&T=_U+0mw8X0CMjCkJ;ci=1>8~c(u*>L;6Sd5Q@G2(NqcP6DKFZau_SwzH%hiOi@EC)Im$rVN`D)F@5E2*7u-DUB#a;ZRfPaDhhyjC{I_OB73u~$vH=F@xBNbmieMi*O;_H^!XXY%&Uj;7 zNvO(#=RpIlSuq1fj?eRbX|TSMJMxKa?iHrIoiFV}Xk3+2Hd=7kNg$9YYN|V9)XQbL zXN8p41W3~w>f)r}Q(9UkHS&YJD!`qknU89S99Ho7pt5(QREQi#Gbh(sKJKVKqC76z zXH+}hm*E&POyj7%(hK-)?Ge{4hVMoMtcj)T*B;yGTaw0TX;nM5g3J-F!KzkEnnbav zoJ)8NdiD58UQrD=)+B`|tV06Wmt7I!cCb>|N zMfhEMa{yd_ChzPL>)z09nB57dlrr(%PU3NxCOn@;pM!fBe=loDBzen2ff*9)V$TV~ zy&9+9-h6`hw~zjUHTT5Ql%MrfJLY9>_dIGdDX~oZ1Siz(C`t$;XwDE30bg973?!|M z-fOb%B&P3KUFuaGm#vyt@3-S?1kEnKyD`mA z!6=eZTR3(PjS>Iqn;LVv2(d!3W52R{(Z|X{Im_)i=efeyV2D^c<*iP{64G}S6?hr2VJJkmq8)o{x)f&qT~jqK zP`EAQ-T?JGjcArQ9*Ks!bdidO(T1JMqg6i%N{Cyx@gemd33W_kHcv`Uty$1)uin)d7jprJa*a!7=pdb6Knp+Yr`Za7cycxv+ap&3oc! z3F)$nHu(y7xfxd2_|6?Njn2Cq5HFyLgEgYB9TmZM1^Liy{mikVfi5tbJ;v|tS=i3G zGX<2|7oFkuhE1{auBIZC^nRhRfVGA*mc2nM4cE;^sJ?`YFe>P{&#^Tl+OIfJ*O|;< zYp(u`wTpGSQXX5ga;j2%Mwq^fy3q-Xh8x_YR(5OZEjxX zX~yokUmhpu>tc>OQEBf3uMj`AAwBa;C}5WO(Bm3|`~#o_Rc;_-+?z$nh@9gBH@=cNro;)z&sG!GNnJlf>4h!4t(=U>{dYi8%A0K!YzHUij zBgvSJOvN0M+7kcal1*~pc{L*(6}*MN&_WMXNZPeMSlk+nJ@7|g*i%0#Neubm`7hx7 z|GSm`gKsGd8ylB%K(oUi^ZA0@lm@C@N!M0z2I1Be+3`;QG4^M8^!^3{evNZMB5XGz zjDJ)Ogyd6+vhyCf|L~8#I)c6fGj&S}-CsDuApe9T5R$%wzZ}=|;}ebyrpCNt|Lnet zALFeg@H?k zO&I+_t{||_D0*_!o(TW&n7=>LXRz{$Uf=#R-@%BJL?7W7Q@d5qO@vy&E+1EAHiQEy zT^aa)^odqxtAJlWn-4gEyA}Q(lPUMmjpf!BK!3CKCAqlmRg#H$Mlc%_P&Gnwd_t#V zY~EszXoX;uN1{T|!so01v&WJJ4^Nk!9`Oo{(s4^xxV1aES-43id6?5;q z2HseQx5^rYyId?g^MTosk(&^Kbe2$0o1Dhp>n^Ymm~05&ceY;6W~`$zu&+cNm~a`4 z*g}aE)@do}SVKS+>9!9=kIXwGXtLCHa=-ux0GfdyMKG7;Fe1s1O?ejC9+=iFrKv*5 zG4}UPlEpd7Hvv2~KV;3e8e=TN{#6Ji4Jf2*VQiY5s+VQy1eL{@1w)ymXCIPDWR=;d z(F&q9#Dq>vY#myn{Dv2G*U_E=oi#BI);37;zSFg|st%2>g1)WGe8#KR3|{ZJq?^ZK zUm^m@U;tcSUG)3b64@E&yrLsOj@YMYDX{|sYv=LL)qc~fWc)4w;nP1$1qGGFwdyZ^ z*zkX70S*NRo0;PExIA<>Br;rh$OtjXSE6a{g%@pH{+nxG0wKt<015Wv zR;-n*jJ1z;b{vC^YO4ZgdLyz?N246}gdo?G%&sgm<(*0urIu#bSwmM3TC~vmxMP(q zM%mY$FAb;%u_9QIkP$sWO=4SS8qL_y9sTD$nCx`*4oIqWl3lOj^{d-y>QZD712Zj; zA<7l%osE0S`uoWvgC&mwlvI|-9=&vM*s4Z5ti7>tm@hL^{FCdR)R51)l~q@Zdf9O9 z=$(0mr_1Be7<;t8c<&0Luax+7L^jg1Mgv{Xri<`g2!-YndBjbM2r;E%{?z7DvO z8o?W0?Ux9XV@XwUm{Ga3*!966qNGr7C^M=vQc^-^sg~p~h+OZLP+-hM5RYyI1$g;$^721c z4FiaC!#g;lePg=>3K5?~JVu?02jGxIbp)uf60=L=#T*4^jm^b3&G)C26CAU4zVyb^G556V9Uz`$!UhwWWD+s2T*vEfX>UTfM zdUOF>t%Z2H9?_Gcb+!Ehed^7cH_^;_tQMLamjM26qjFWJ@d;p1jCjV2xw^8Fe;ObR zEF1rpuP3m9VLXGvG`!pytWdKr;K9zNxf&L~QAm*d^Ori+LO#gF+mQmfWJh;PPfAE? z$G6a0uN*C8|XSr3RpxQ*$&o|yViT% zk!x6L$v8ncwG1|r8b1-#Dt+1eo5yI;Rg=In<|)G$E8h=t;33#v=Fg{pTACW{q+C>S zcB_@-wG|-7{w4^~Zb9<}^o_(-$dV~8Tjp3X6Efclv|SG{Gdo?bw}6iR#_LO9VgDZQ zk=Ks=RBxkr=Bu6^OJ&X=aRcfyuARXLt>-BA|a>Z z_}acXW7yU4&W%wVr6f~xJjE7EA{zD{!KlNvKMvC;i^qi058n390fiTCkIVv2n=bGp zQ&5a4tm75YeUBM~;=dfLZ^{V_sugRGJv4`p8lPZqIZTtFi~RNJVnbuv&)!$Bt&O?Y zl!0-3kN`Lmx2XPltE}1hAiwkOh?3UQ)0z^58#w>K8f<3_5#Njgw_DZz$yCM(fEO5 z7^0j00SJkE5B*t|3elpA>m@Glq5{4VA47uNMh_+0TTJ{dGfoNZm&i#$HJO_Tkx3t8^GqxBR)`U#6Mn7Yt*`52K@l7iS;PgeK5|^a*VLxIMw``r6!V)( z@osXjRrR*VJU3t~k*o6mEF zDK+q(neS74ETyJinu5y|q+F^bh%&#4#Girlmyu7BumBt1^|=PWTf;dX?0ZrSusoy{q$5Txw0;=y&_9|7Y! zr^+0ermolocnJ-QN$;6mPI1UlCtPdT&1YIn2!{&LLsR&AVQ;A#II9HLU?DZwc$j+^ z?(9WIPsX)lF6S~Wy0OESNF0THXEQRzdE!*C4X8kS3f2>{40>kWxQtop&ten9_gZDQ z_F&{6S5^z9;eciLmIyvfykh0mC$g=OA6atj?$3!jN z7qxf&R-_+n4Z{TCC2>wN@8J=Kt=Z+#1n_H^zEwNYE{(})tIL6p>?FfFY;9QUhxL1( zKasNd)WJ9+v>80>lKqM%Uv-0;BH zCTc@A?7@h%)P#t}DCHQrQea;AN5VxJlxd)RQ(*U{q}(!PCjh33p0T7BlHdrXP$7O; zyxp-slX^^-b_%|J$P|C^P4Iw|nge4s}} z>M{E7h#8H_t)~nCSYv6 z_^!V9D?gS^DK7agf~!NMV{qje+mCQ077 zI`D&EbjX*?rjlBvhP)$y`g_l321HGOGsz%(Is~X3o+=kDYXfesJ=1R%jLLyt1IKgK zvKng>|Aw;l2&hkMQ#}>U1aqeoVJAt9Du&IM7FMW;ogDfS6)!xl* zcFTI2+S?w74+YK#Hy)|!wS__w^EvUCmL<_R4Ios5YZ2FOWg!QvANkLa_)R#K%}bi*LXM`R%E^gvWV`9a^9 zb!uW;9;j7mrNpGQv9>op?5vk%U{X*>4bFzyuN7`iJu3=s2+c-?<~2Mh3h)zYj?uom z-cWVv_#`7alM9&{xG6v&1R2v*ked|L-7lPo^+WvQn!!%&na4&C%dpt`kJ zB+To3{H9Qo)nz|X=@o$<$ua9ZvDQ{(jA(5zT>BWbW_{YjBYnt9sxL3`AnnU#oOCzcl#XDOK(xPX}LNjgSSp$Bv zY7C1(ct~~DGndG5zsY;6I%e1N=9C3CS2ebj9b7)F5oGf`)3DywjG;={C6D%cK3rd2Mz9aj1=Es>u8Ik)BiFbx|MdE!mIK-NM!q_|Ou&ZbF}^R+r<$2B zxzwdww(xgm-EzptCt7v-XlqIB+L2C*WM{cIPBgbrF^Pc(biuylXYr!WcXrJ4IMA@Q zCZvz1Y$E8xPyF5*um8(JvY$p1 z8|U(sE&MO#;QRwJ!CVW&e@N-GS2Qu%WrkJizj|cgYaGH@?EQ%J?^R2>+xG^iZ4RPiUKM|D^7} d7g*N^#8YpHlaZh`-j~mpgovzgg`obA{{bEc26zAf diff --git a/doc/ci/quick_start/img/build_log.png b/doc/ci/quick_start/img/build_log.png new file mode 100644 index 0000000000000000000000000000000000000000..89e6cd40cb61d890b7ee1ce0137c738a18526e74 GIT binary patch literal 63272 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 o zbRJ-!MS}(-)U{l_(NHZm;8*JD{p1}mxBFi;tyu8`5I_B-A@x z5V@AM1_2n;ebxMr!h6G#v-EURbP0pi{0VOXfw=9uPoYNsGHPr6F+^N_(-4+8oo&5F zPJ)9Jl1Eow`__c7P8X~YMnbdR8YO_n0v zxH#5cc3YWtnsR!r`hjcv0AE`%#uIrY+SA0O{HN6p|N32d52Ahn*@(UX4j|&H&=s9 zSIOI(HI*@43N4W~qav6%FSs9Hs@u-bC(|1}LfhXknzGmo#$5tpa*of?+#82Ez(m=t)Yyty-^7y4#7lq-FG9SE-QwvPE5_H0HiTt zNx)?2^@WKTJdIU`4}moYp9dGS?Kon(@qdCi$BhU%HsX!aek z|FUmed%l{=N@ck}k9l7h6IQ!-6kGgy&1IBRP#nSNcp>)6Vx1$@cJ3IYL{m3 zn*K_i?6Tss+>C8h*Cg;7O#7E>aGHP&Gs1AG_~sTs(#`aCfU_;C>v&dP^f|EEmUfSZ zT=-(!ZMc&@>ucBO4ESK6wXn_lI?V?L6i@P}wfeKKKk>S!o9qaQ{N(}+9)h?GRdd%2 zv*R>DAe#zf^r(~8)>K_?xN6bsufjY-3bJbGR(ZI+=)`-Yb$Yg0>Aht9FyE&|%9tiO%blqM`hf>}@ zpPX>^div6GQU}fWDaW%<881;}TT(oc-#VX@gGF_^5F`4_vzD6HxBa z5tiKLdXxUiRuMU;!y?Dh?~>?;O?sZP^o5qkBxRyeEQl8STro?r00==J3$uIo~SiJCzhW^UHwa}EmBl*s#z+}qY7j`_8I@^Y!GkmpPF3Pn>csP(5-%Y z9HK2``CNtD{HOF?`A_+SrwD`c6MpLt%PYaL6|9^1I3X3+{J$73*(KCXri>u$2NR2} z&l|ZddEUVnsVsCiVhOS*UOVP$?`u9iG0zj&3sScqC~{gIBX@8mx{*URgttmw!Yi=E zUSk=;GwpKsF1rJgMo#M^IpM+d71BxWh)1-7>*x*u z8#|Q=OI^zFbw%;eWi17MR6KGC-~{Ij32HTQ)G@qKlDvOmmRasu)fHuB?V#gh1KFf2 zmou%t9&s+$8@PuLj}R-1(<`nT8@n1Ls+IkG>iOH!o^5&%OJKctlJw7{fw+i1^=*|2 zOwvf=reqMY(*BzKt9gkXuPN`|+Xg5iUP&@BN}8OAyHtS^<<@XaH_XO= z=Ie-huIFiKvuXPRJ|DU+hnOz9D7 zF|!Ur1L<%q;nUWoDkej)G>cs{sxjtA`i8SS1=TqTX@9Oyo< z;JyEP9G<3Gu`U7zG+wHN1YJ$x_2Ez)$n-1lU-^6lzKi9EISNehdM)s+mS%=RryCjGg^q{$CyH>TNL z_o)?9AX^S}rFd}oy*GzlQUj##quHXDc~+K@9pJxT&aEYtfG&t=cd0ka{IkObrP$GDVanI9|JNgKX%x@F!$6uaD=XcrTK9#@z2YEx1Lu?(;;WR>9GQC?Mo(R12 zP%7h?7kBm3WLyPQmk+u*9`t^y^|btp7@ATu>Q3hXmQChIaT%)YLu zX&0@Tbd>OMIF84YQ3A-F6tXa6`OSdKGEwgw>qBXnBUy(Oh&5{*RUfnb~5xt*mx zk#4!TN6Ar7W(X{wK%BQandgC>a>yd-Q?Zz#yuQj#Gc9lHz~y-@FH(Ay1QxDUci6)YuYoSwPe3C z`iCnrE@3tyt=sMI8^4E610zM%KaKBXrFzeerVg3C|Wx(;9_K}Skt5RlCf#l(6g>`gG ziGR|CDIy#e08nfSON7_rMyg zfCWD(1q$G7%ERyfEF}lRu|PQ4)dT>4a`V{++&)7R5oCe6onj)O2jsPouA!hfrEAmD zgyKyUkR+Ma*#z}K2_9-yCW$a`<0UXcA7iK|pmKl+HsSKzz3uECAza|B zT@uv-P79nUeTy1(VIG`7I8lMvy@){qFLBS!nbt^HinEEBm{%AFVBYua?&Qf+dbdD# zc0q2y$Bd9Z+E@L3Y#&<#VK_asrSdE00c@DCP145A1wcPlOrXP#7OVGcEG@^Yl|iBE zKDve}U~bZ)^SOkAnkE7$j}r4)O!UD2drTSiQ0VwdDE6x|j$voSk6QCu<6u6GbOe)N zqNkvL`}0sEFbYVLpz;|{LWs#fefrY+glD=jQ4blwd(RytHtbwx_9L7#?Jai&?GAMy zyzR2+GG6G-^Vyp$ucXe-j;-Bm^ep*uGNkDcj0%a@7u zL*TX3@>;}nUB}&A0{rmu0d~xcw=kvwSG>ZO9_?i}-^F50;V0KPOE4r>xLvRbm~rXE z?|+wD#?n~f77^3GN8b`KtVn1SlJwCgcj{tO$_!f;3{XiHX~BLoKR;~dU4Y`4hHM}l zl}gHf#S#<9_Wd&*w4=L`s0BKQC8h$c0glzI6r`~j9O=uWU%`Yd1pL)c2l25yK;olgiI>H=JpsfFnEL zzbNtPLFlF*Br|<&X&_4=)(BU6U`$jl*`#o8LplXMsn|J~p}Lsh){?{pz^MhDloD-) z=4gK61%hXD@ln0qKkVZs@@!l#y_`U$5kfK-FE(+rzcm=<(^5DB;mVBo>D%^B!5(b_ ze=u^`D<<&^5Hy~+uTR$3L#PG%_dLLvrId)JHRV$>lj6N@dYoixV|&J7EG)wC@}ZE! z$=k0s3lQQ#C%zSI{Y4i0cLRL{8%Qu5MZbFaslfF=wu`;+c_!~z4hdC`?ki-TKA|E< zGWFtA#up6FFeo{$K)}5b3r^@=3?)~no+j6a%f3ea_*}z!)k<@th1&++oQTw`uQeOb z+SILm0^ur_6=afAH*u{AzbSAzt*W^nf`LFv&)pJmkOT4##eiK6l4#3ZkAP~HGk_8* z(<_qO%?>+2C~eC|EPJD#_t&8zK5itc8mXNbGM=+tK zj_z6$yuRceqi3v{YV+Z`_;A3VGA~L6GBUCz6(^7r5!oKB9Ij}GyK_^DEWr3f{#EQI zKwiv9Gb%yhejSg?ufg?F0xouwUKKnxazNk_zeMcbPsfwy9I~mvhtm?NOUNjsjow~M z3Y`M7tfId^gaZ3;7kw32a?f1qQPWXQ@!DU(X>$ z%RLHJ0Bo51`GoeGrZd*r<&KD(8kTmNI8Q2akffBO@*>Y1$UWA!=wk9fY{A~@Zw4$1 zl9AxjHRypQoaSm(y$TNx?>_@ln(DmM)&A{vT2BXu|E=&K!ny>3C3w$|FvOBj)<$@K z7a90l{4RcsrN2!2x$Z81iPEk`A%cx%%*?U@ZA$(ti>S?%mr|yJxb8jx+q*%F&4fU_ zyv=Pw7tO9)?%2mi@`@I?mpDRZH$QWmrjV9T|J2KnEjhKR1th>6k>S5J#Qy(M%22NoL|MRox40|T>s!bea{$h)^YCyIL3 z&3jagJH-mHYfNJGB)e4u9!@J&;Ij4_QU|BOz+vkVz}^H{$=wHmzAHcocH!*6`|pLr z)3dSu(|PG-vo563s~A8q%l3e{A9>*20~Ptx4 z1(Y^cIp6e-^|isUdBB+H5tO0yl-Fu3vjQ$6qQl;tyY~7t&_IIjrvzKw!OT@hA#6xR zod8WsXpU+@7nOBwGTw)0k*tRwy^jvw!$EXp_^U6^vU-@FeGCJ~@W|PRxA(RORCV#S zMcoc;z&8hih=Qi9(hV%F-Rx?u`nNq_)c{-3o%Srnj5L#z z$nALs`6A)8q9G{r)YT% z2A#A-oeE5`UoA}G@6)`EFl_RBy46Ot(E%QI-3lLt0#cgX zC{srmhn|;))tE>a&`py9t{%1#5xSsvYPtvC;V1;KE!`roTnkhoUyFZ!t=M_{^}KCF zcsP)bb-pG>71kF=SezJw z(Z0~UN8~U?NuA$rM@?oW9^>BJ#_2FD(`R{`&y)p(9hPgS_pLR*Y`3|-UTuswrlAx7 zpJkT)NJi_Ci}&Hp`DFdC$Iz$jfD8H~K{&^HAK=TQw`O{ z-M<&9oc`ORu?33aYVeh!LY)IzW_~Nw6C|>PZUDTu^gcogSDywbR`!Vbi|FGL;Aahz zL^NE0f#$#D^r)vzz`#|DP>yUAO^=2Z5XYIHn|F3`;T`+^V!t?!ojUFzJ3wlC8hDO& ze^#9n=buD`=1A?43(bC(A%*t&qD8sEOJUwowVjnd`uG*3%4Rb>!-K-TJQ)^VWov$& zLK5V8Ci#Wo5|U(ZfXr+e3h|bE=sThwTJu>A3u4wa@d0qyM_PV6DN;!2$)lv};}qp+Y=!*kC_z*(K4!p@$_|8a(?m16Nb%# zGE;){ug5#l;a|F!Mjh6FF(io<0tCWzD7oZgf!d2Qrn+;wM30ueQvyhM;^;ZOZd4v4 zkNH3Z{?+K1!R`K~5>8YH(P6cdu=0?uP`e12ihmLF7I?EZ*lqkf3EsSGH2kKkl+s0e z`D8&*{66e;Vu+TvkF_9G>QM*Dter|M-D{%1-R_3L?B0l@q$XcbVA7YP>&M`wqgkf9IC(cf;0F6qM zA`RZP(4~aS+w_#X#~UKZj^5;EpoW4c*!B}Yo~+wUSQve5cOX-|b$7DJKKix{yLLI) zz9P3B_`5V}4YP8!A~U6e<7=F9YMDIqbW&+^Kx8|o#|d7U$97cSuVSO;k?k$n536Bh zEvfi$PNTZ)OsQ)D1d%x&Yvinbbp{lN(;2UejW;}$*Qb(+MX+0ptM2&h$&#pEVVscT zVBer4t8w5UtvA6rR3leN@+=0Sc@|e8v%AsuT{BV!H@UsieXV*jn>Xb<*X!?*uZ+4} zkKC+#U7VK3v~P2p<>KWSv@05d;k(`582)o_#Db{g(a&L!M_9#I^7XdhFl zmpJ)mkp7Svb&Bt=3fSON2uXazvQ5FJg465m>(7GrGx>Kh%)}4~@5|`HK-Tx40&>Ry zr(b6Cb3mV`0@@0Ju+VG1YL>bvrk%A>)oaDm$q3^gT8X=jQG_`90udRq%84JiZ|Klv zMwHiq8mZW6+@-r(t&9TB`9QOxuYP}VK$SGoyWz4vuCI&bR|IpwfJ@1&glvP8X2nK- z^nf)cl})``;+*CkY^JAYO@PI_&BB#YoO*Y%=<>e5Ov-YV<&%b8mG<@{5cs*gkY=_! zQVrA~btSLQvj(a5{U4EaDBe}EG5?P*lNty=fP}sSpi4I9rW@Zo_zIuJ4zcRbMKGZ* z^O!ut<)nv;JKF@^;eYmZiBFRRZt!DFRQZ>OUsZ!Io<6(A*Qs4^4r&ydj+-EX;q#Q9 zG6ffu-T?CQGMJ8Lx9}|2AS~MMIjQAU2=Mv^i)_}ju#-Rzx|K6iT*dKjpNw9Yq|-3P zkq1%IAC2)PjJ~y8MHx0w85{-ii=28DgR4o&$OK24uBcfy$t(KG>*dCUNdl5cZ(lV2 z_?wB7#|Z*MyT9utzL*s|9I|S*cLiZvs*6h!bVK3STcL9#;%6Z(^|kufq!ET2b&Qc8 zC%T$(SKx+pK}^GTkW#qT)OOnoO{IGTc;u>#YB;U!xjbGSe@Jxcdv zBqNdRN}csV#1$U#x`;Gf|1akIx{gK7W?wz4Cf(0{$+$~5pbw)8WOtt0nBC=`;@WZ- zWBavb!)^Ujg-kj`C2`uw*C17vND>U}RcCzaVLrSJtN01DM9EoNW$6h}9%$aEQy48( zg@OcWh_J`Zjo%gLdJO_c6)&|FiR+)omQ&A<9tF#e8Z)6`qqpz>_cQc70VX6A2O+=p z!>%%du7F9jmCki12GNy+*G&jHcoB%(7?qm)spNG|?(SliKIZ)`9#@D<-DsKfZ1&Xf) zPfpgkA|M23m}N1E0WqZbR?!X9U%8Q=oxezC0;Q)Me^%L3Byzw|d18;my%W(RFJT5!48X2uKG(kt#)zuAuZHQk0GegdPFu(vcz-nj!>)iqZ*6=p+>B zH3Ct3lct0sB}9oN_eAvd{nq+^+v>&+O;f&#u3{Pip_ZB(EGUdqyhW z@tEtFcY86nC&opN3=dIyXr;Q4Y^g+9S4~qbz^9vc2oIV!#vUrb3oe9b9xc|bm>V`x z-uJP^o!e_7%WPrC$)@%t?if*4tVvm--#7kp)(Nkmtj8=baWbT_rR2HGPvZukGcl_G z8||%FR(vwp{zoU#eRs%eMTdKh$Y~pNT<#ggCwoaU%DuKLl-Z|M)?VIS zZ!AL-<$vzk!wT2Fe8~hy30$1jt_;daV^22P?$&Z*1!;|RpsBKQQF;)p!}8AD87*_k z_I|iDfs*`8@NRnc?wBb9Q-Hpm&M*Uatwl_cgP>DSdhUBy1#*8+8%@kmTX9P&dotzR zYSdD3i06|ce5uaURIy}I+t}g(tEu>X+m@=!yc7FJssk6q;nzPiv}lhtUZ^e~D0ZDx zdV*#|{+Pg?HXn3&VtEagR0K!q)KzX&E7;UAuIGFB3=%&9x%G*e;{gTXE~GswPy~=9i_or$=51k(WgZv%<}4^{WjV&+A^U@mJu3ZZhjNkVs1N}6IPFTg zX$jQDu-=_erufkZ;pb#Zs4z~m+sVJVHLsk>BPJgkR8qL_N(tqN(o#P0oZ)cO*pufx zgT8O;DvX`psvP#4P{**%hN;vq)-Rz@x+^u+Liix;`RmF%q#JuJcjn6w8SIgc&cRPp z%muHbtfU5@PQ)K}ZCz4*sPV~4twsS_SlNINn(L&`GoG$RoAAlPA~%%COL_b$L));V zK~v=ji_o2{dT88mwNUhB)!#X)cS12%VOp(r(vylm1V`VyFYbNYFoU4$rmQK2W8j9o z&7b*MVf(~k6aG6*q>BqDn&*PMNK>)W>rcB1dBoQE5FSZTJEHU64yjYI&C3bKZHEW} zIreedq(e&P7nR4HEEDyWZ?tm9)vkRDY*WSYaWbNQ*mg^r_c|qUr65)J!*K&;A^c>f zSDBW`fJJ##xGT-#n~wwT&rPeVM`o`@F?|e6gBg)V&DmH|RJtI8=?e9iCZgT!4Xv(a z&gMVUEEVtdQ&(!R{5F87V}GI^f=#-Ok?^;~wJdSq7JX8h6Yo-L$Z}gzL>L4%yQVzZ z_VRGZS8r?hW;w_w5X`SK(#sJeDQk#Z0oFIC9yWS4(z)BjGT_taSFt`=W3~4bsd^O| z^{n*qg`P)gxurx7tZ|Dda{k8%Nf~y=N2+njCcNfVi4mK7?t2S~fRS&v8x!&Q+eb*j z+eU#KCt8?L!H>Iw_wmop{}Oazsbo#D*Xj+Oh&2t^lSkLEI6>F2uLTWT%dC=F2%D+V z^`l#bw~amY#z&c;%dgMb5@p+o2;$2NlbS!&R1n+%4Ir)Ks>szbl@bAG8P89>x70!x z57f~W=9-e!_WGVfq-565;qWdMy#-_Fxs8HYSb)p-S~$EImGBNL-Q=5d^z7*-!d|9{ z%)*+xa8k^T+qKY(-mRnxHbSFa>kY(s&3D_V#zlMR^IJ+$B9K?5SS+&c79WSdph3BK z0n#mnYOKOLU*~NSYY{|+c-==Sce94-H7^wBZV__>g};P_RS_N6Rb*&t7%n?q0y;Y z;+WjSCd_m9Mb2{J&Ono{3dTkw8xKn=QEk7Om_Z_q0ah|)YRlahZ8vmOeP21FL`Q+m z;CSlvk(ZS-eydSoV|^D0PArtEh!@;4H^;6kKT(IX<-*0Eg)w0cc-o;2{1>hqoAJ;;qDaxg!+GGvL zyDB1++N)m*Zn;(E&sfwwm* z#Hv2}$np!-6E-(zU7deIh>vNZm`Wb`cdB#WJD;MZXMb@brGE%U*DQ zMYN0A!WY8N`N8CtbL>SDexKwq2TVD$Fw^l-6pwob>I=Y1bjn2Z_5TqHvJ)L;b@ z-&nki4If^#j~m9sGBNM`flWaF_%z~A7`P|Nw$(|gNV}V`{;DOP(n61S4?jMvol>U7 zAgkNwrcRu7wDxG93y;q1FgH;-q%=0qm1?Yv&L1LNeN24o&nq}@0&8Rlo{T&mPy+&o zi9mfl%m_(gGPx?bGmVNQPRl^=8gv-TJ-(0E2tCBrRfI5GK1>^@pv9GE-!ZxNP)N=a zYIcez16ACcv-n1c$24%SN-wmgw@44A(#0}3tcvmaVZpP%d9v^>9pX~j@E-aF`sJ7# zvFJV3BlFi5^mJo5iX@zNT+G-|zMj0Dx2<3B&TKVTONc5X-B5MsMF;f5V!S0A>`Xqk zpcocdJG|D$MJ~DL5pWbTlg0WLAyYZc(ux%@9Lz3*6{Je zhsct!UM3vvC_f!Nx@gK{E(g&{ssX|mHUF|NfM>VAoMq9*+!2CQX2RX_eER!tZL3T3 zn4vte1w60I-qIXFI~sddAn3~7!-nC$G>qZTBK8Cx@LXQzzUqc-1Q^UJ4P>R%v#a1h ziRa_kONymiC(WOG>8KTMGsio}=jFJa&M;Wu_H5T3$Q9T&{ z^#m&s8*Ul&)H2e`&bdN@J>Z3zFZzqTX6+1)^ExEp0}smA$uWaq?o`!VW<^V;n2^Mj z)V*M#*S7SI%FZnNBz%34N7a+W=UtW zIw{#sDduofq0k`ln?PNj=`#xz?XG?nqy@X0tK ziv0EOu+NpjP?m5vWal;|kt8=@pgp*Cg+6;|#=%;!V`Px*`$)7!c<3Z$on(I-qm_G z=>DDO^!(FNzuj+6^Dq1t&~-L{6$<`8;jo1CVF!ycckVT~((VVPp!naJ)AOfE*dA;W zUzi8#%-2)-?0t_>%fzVw!nN00NpTdu-8nFe{(jHp0eb0}WOT&0vgTlxqQAi;8Nj$8 zEyhP76YEcsXDLB{5r6F;{k=yp97r-DjB#Fb^AV+d(SoraJFY?dV8Am}xR z3I5uLzT?3kUy{lW1i=nuIRgA?>tKAo4JPQr4(LrTo)tz8Yz`Cty}A3}&6(SQtY7hD z^eTG8;EZWODz3!V7Ki{AG&5%du*(S02zKHqH+C;2IsFeh5GdsU0Gvy(PEgko4HEqg zm6@*vs{s~qk{osE_jUYIF$4(Td<&Iia|XaGv)*}I|YJE5t2&){WH175y6htv; zOUrmqyBUCwXLg_+FptSLN9Kx_3Ara3;p8 z)=&Rhw%u(_`ge3>n>By@C;MxV2swJERBZzTvq{Yd>^B3W$e{e?Zf7vy{|Jz?|ICjs z8T1385eGExXSi3r-36pinKjuYh}lcLW{iML++YrEts#=Q6m5)R~w&09AYq-vl`5 zru65T831+unM}An{X>n~VX(BKY9)G%rve~T(qb#Yy?jIWq1ZnX7e{_xa$S(j& zO`3*9-C1^|rvgON#0vyK*E)~kp9Iu;Zy*yU?=%14&LU1*#I#`6*ajeQ|MfidOF*0l zg+6oo)TskvhXoEMmuPHjM*X_7#BR`5o8zG$N<61IF*TKCM^Q<|CSaO&0PYRS>u8>q z1O5~Bc{Yd1{x&GcRmjUeXSq>(9f%7qF9}-;o^A)gCD}J~egd?ePJFdF{#ZX?K*dpR z|Gs&B0CSeHnAAV^=KC{|b=()7=xA;$%Qg7vmZ$8If_b1*eJ*yL3h>Q#q|AYO&ty>7 zuC@ZKG>dZsu)g%VLV#qG0D0#39n=7?O^rb}NX<6Kv;3H{JL!kKo39+Kt`JX;R#-z02F6! z*ee4_giEB>!;JDbL4=Yff#`;P@qoFK5JA@tlrdhZ+1_W9YD(q2zmj1czGg7*GCuY$^1hlkO!vx05A()%NdErypH|T^HY#ox+DYW1iSU7zaH>q zu0O{+0=O=_E}{AVuvvz&)GY1|%B53Sv7{KgO|y_ZM=>bKmyGfqJ=>a_nKj68y$i~# z2eBaM>n=F-HrCHBtJdkFdWMuY)C;my8yCH%S4~b-+{(e0>RvC=!s^d#uF5bLL56bO z9<5%*Cm7}-D^vr>RaRR|wad8B{Cc#1hQi(Rx#?nt6JiS`uM0dhR}rUSdL%R3$)6>c zN;kSMnYKo3w7s6GNpcwp+FlP#$A2vh>-pK3>#pc~7H_DCKNG_a0HfVV(Fa7^GWyhj zu=Ii6w|;J#&+hZLG*``SH0OTR&;W{#>I z@Py|iXfvrGt#&Leig^Si4Upo#PyNzjM7MKX@b%CgK}7@J#PZXA3P_rk#IyfUKVAVA zifs0qSimTYn@u=9cdw&-AHc#kn{;39j2w04KJdMiEvvq=3+p@ zmU@LDaoA72({nh;wVu4w<1$$gGE=FiW4xl9f^P?x=+NyM?6F+u^+4qCtN0X!tB`|K zecg@8jD2`wG{G%tSI2qU5JX#Q!GHDy}VCXi{dsgi})^764iEFN&x&-bC$XEWD zXCIr2*{=m_%awNvzYU+P&^PX~O<(5?8D5czO%;xs2|1gcREKW;-0M0D`>CWISzeBv zkMG2*Z-~6J1bxkJf_G~-W?ViE9H)j4T*hI9T*fbkku$uiM(-VJ*YGf+&Ir<|(ta}n z+g=-Sl|7C(qBEARNfX7P$gJMI2yHIn0cb9eL~l;yHQO@o>cmopp`#L<uXOyZksU7pHB^z??6kQhI55(68rqe)(&+ z2Io*OJHW^z6Md@MV_$^OWHp8yDEwE|zQN);XfI;GvCy(-C3 zt|WK)a>I%&107?P99)Z@G*r^|s*S)ji+a&w-_3EYu}4ZqLT&p-N}ZWwLzxo)5FNo8?HbN3mq@pN zT9JN1s^Yls#bNpgFN^=Q8D3cZ2C``Ktx$gxtp!W^XeR$zkAmxf*)6Nh^`fE=&;`rS z23hTi?r)e1xhcjwFi!Tp3pcU&Fj2}N1oR&@GsYcW#%-Yw3`5BvL-{-8EsE5QLO6>m56(eq1Dn~44n4$;jl5weddjH%lYP^KVbAiHwq3dJ)O zC7ml*uCrdba@C!L2>;EP{&vlkD=b%@DJkfAC2lqn``k86uDXDHx$qo61bf8QNC#j zglpPX*GgiZT=NR_L>_m5k-#qZE0eH7sezXt+!E-iO5|xuW_K)nxz{*8f=T-RpG!cJ zn6R-T(=gHxf8PouN!z94xc=AAEk@AY3t>S+t~&*}Tm?@6!zIj6r$bM4Qm@HLL>e@-p0tC9RU?I4M# z{&V`}rr_u!7Jpk|0uvaFBwr%#`Heg;$Z1`<;h>{T}n3l|bh zJWD@SHCU9eBfV_OmyK6Iw$AiXWKW1)x5bC<{v}93ivRh7RvR7(q^@IZ zr<=rozeG#2!=C2#MzTc~@(b+kKC>j^b8_jBBhsg#^;(b`jJi&)a)g6X%MR{HmUV~M zgl-ma2-hCKqOvyO`e~lZHHrr-qRwlnXU8E%Txrvv^ERvtKswvDE`k^^m0vPnh#3O88zUs%lOdOv z@(srx(TkeD4V_~j!awDCVl_vnsxnLF+pP(~IZ!<596C3(|ABJ27^4L3I4j-7$)4(P zp1QItdU79%OqB7Stgu6N`tH7@z>Xr^d!V7ZJ;T|*cifSloAw82=~qoILqneaz%1a; zwqA?we0W>w{@z4yR+*K{$QwxjJOhj{zV4i4 zVvki8V^vYT?CAS0Wepg$W{Ru?aYT}cY;eCg@-QjHA215l+Su$0_vu;S{GG*>B_x8~ ztm-UUph#`4dik{(*=O~(xTHhIe`hEext-hH>yWauLS`R$ErUS0@Ar`9$2FNZUtx`I z^|hWDNUM7whkDQL+<0n$zs~e$W@%OrijT{XO{oNN2d6rZjivhVfZyw4_V7;KEci-) z3cNe6INom924>jYLzm_*Uw9CcqztrMs+OmxMEM${?#aCy*;+W-iOPD~>(YBpK#bmX z-@x|D%b!mbfXZiNyiZ0FWj$vq><|+OC`os7!|7QTZh$>&WA?Z8dcZZ;jRRBM*(VB| zS~aWcW*NJ~!8k_TQPy#CKgkT(_>{MM{qznuE=0?0BUcm2JpkeUkQaNuKw)a60tyQ# z%uKxvn9|tZ11)b=WZG;Mqye%JM?XqCbHBMgf@h!|}rVc&G?&NDe&8wQIEnmF;Y1pPmoPdb3k|X#=sP^~v zxEIN`8X>8t^}hRAuzKI%TDPU3T91WTdO54Ym(@#OB)#@b3U0WFAzY@!SNKgt8kPAa zaFi*0m5pN)r5H~zDYS8O8T0AR*cFRoO&yn zI%>JFa`)CKbel*D7nxjnRp;ecXjyol%VGuX@=Ty|6(>|g^e2XbkqRKEcK7bX9}ME& zPN&#|M$X=N7~`#?Vn2P++&$>F23xJiG!f%Ar;)PkZP6Z}tNh|pp-_LaY-B^TY8*c< zflUWTY1%uQkJv;Zt1-N#kxCp&TIaueGwKg})?R4Iy)sFj@Xv62FXP%N9@UIi>0}lx zZ2-voSjJpfYO2S)D(PWi}ptJ>u8OFs{6^p_XVd-|>mTJvrpf?`WEu~FxB zBfYA)btS3x(Q4?Lg!KpdN06_6y{i>Z7<&rqKQT^s{QpPta?(^ainJ?&$NH4&Ru%wod5ha@SdFS$kE${Wxje}M3F3elcpsQ zO4$1?h|2cSk6m}%bG~{S@;qGlOFMp(I?z1s>+l%-0Vh9nt3G}39`($Os!s7u*WR$W z;!P>-|JXjiCJM7cdx)e{0`loT7`@EqePQ;xu_4^2tPMI)>p1oH(H{7T)&?flv|TlU zIy+E3#L>35H=1;Adv{4yw_bxl#NnVp1?RKB9>bI%aJ_z9C_?Mw(Xp zP$Rk4(WkP2=aJrPSP-dg5y7D+oq$>OPqNkn|5+l>`(V_bTk@i^uRru{DP}LA>?nf(PkV$6U1ll^3+t(p%4Dg^enVd{7%M*w z9lmu>Y2eY3VtXH)HEQgaybIE`^>Y#|<fe%ST6ub( z3EH2W9NF}~P5m*^@0%dp%;M%xn}m|4O00;gSf@<_JykPh#uR4EsW2q(VFhT)!Sd32 zOMgtiU@?)D_4ddip#Dc+G0W{Ko(_zNeKNhEbJ|1&HpI`$x+A_0IoLv`>>-6j zC0d3meR{*;)xD!H&h0<}gx>W%XShSB9|a)(6J-5#x_!j$*!k4+eqO+s^S$be5r_U?%zP3qkR&XYjB-urE)4l0RF zZwh~%fEg9d&COe9Rif7S=_^~^7-|NZ(uV~GzEx16$%R$5&ZisP+m~S=KyK}gEP+XT zGoIS2*)K_m$Hk`ZAix^4aO!(7dRg&mjHWXfrL)ri%;FVM z9os6gR=WRW$49ud+&ZTDQahA8xY>kVEN z=JwZjqgVVphS#U)O|H&?_Ro4zyroHZsy}#J_yT5=EbAZoPt?vDT`^XO(rUGN(?Ike z5qqY7JoUe6Kv#$$>wn#U(;Ue1PY}=bpcVS~pZm0)LjNNh_)J1`?VmgXNPqMHIW_pd z?L~QSXkPDqmMI5go8C1KaB8N&C%VPqmmwm%gC`Nc>Oo?9k-T{yL%BC%u)?Ij()dul znpLE?k@$(7e8eHR^?=TeKX+02$-_-45q*Q7q8?*;1&^ryjM#GndLh>3A}*D?wofTG zKczGZYKEm``=< zknJslRXpQ>HlKLwT2?=>|HaNAQ}QTP%eeJG#F!Zd|3v~u9^9v99PKiEw4BuX zL&m*Nwf$X@>*`{rhZ*vKS%RRA@3WH#3h#Yu^iJ5gHO-G{#8S?>4%G}n_a1o^{o1uG z_8DrZ9D5w1NB0` zA=-z^FA{^GxzFXFzFckw8ZV=fR^}8anyP{Cy8Ebyq`rGFY~Ir&<9d9;gq@wEaY(e) z8Q?m+{U_niG=6CXu$hgbX0dR|?Ylkuhs@HEo&WO_T1cao2H2MlC61+;8X` z|0b{fSlMJ6(Wi|>g)5ZI(>QG&aOC)LUG>+{)c4pE0at#mFK)5y(wtBZ{i%|(FK6|< z97^MV_om*5PpMNEcZwE{sWyd4k(y3C;0t2e;Db_rOSmSY{$&5*@(1_ z51gr)1DPQ*H?Y!>@n6xo%m2}!C|ffHyZ3)gX(_irg!NwTzTwqxbqO2Tu2WeLlSY(W z;wx<$wz_IVo*J6>)9+b5hvo{~`eFfk8lXZ>z>5`W!W?|) z^H~7VK#UJ9E&G1^oONb+N6YYqk6tfzzv5eNJ6xobu(X_zq&>}QyrMTQ;Uo135*SGu&7rMZ&C> zB1vM!kWxs3vVuav0h1+=%M{@xYkNT{9hbVH$f$nI4Npmk~J?T4Q9(tPQF4lr_AD%tuGwrqJ{y-gjNSk;=9d2MpR zhMzcr8jOUFxf`tn_OY*?L_NcDc^loKX~l1wJSmOdtTYNw- zw~=iGX>l>=N(*uN<9DMA@ZOnQIdd2~UWSWjk`i*C3p#R8y!p3fa>f1s!YTj13^TNI zNC!*a4%cM$#ar~5*8Pi3;-ehveq+7MC?}|fbgwH?=!RLn$F#3eVbDWf-}unsz1t)^sFRU-xY%5RV`ykg}m3@hD%*NU2z9Y zIEw~X1ha_k_O{oLgp}say$$(Cxqew?6d6>W0|HTNd$97-E(4nK*GqZPhcIWF*5lLF z!3X8wUMWW2V$*8YC2XL?RL$FAU#yd#i2I}(cD988dwT2|6<6KH`?9VfU6YUX__%hz zfy>=LNzQ^n!p_{fKM7!mgOx8YkL(+;S*bg`SITjG$P%M~A)-m&)z)^8I6a*@aSGgQ zHTLYgKJgm3xZ;Y5ro($mQHQ~{0;8m(yQ*=8Ds?Owm#u6jMudE|=*bye(3!Cr4}8|* z!p#Bw`H42)@ncC%&7&pP>lP;mjFu;ROj?84UvJmq(|!)XpJ5cU z+ZEN#_b|oIDwv=8sD*SX<45ovx|*Ua?2|BSY;lKbcT>Q8fMAVhS7d=OYtRiQJ03TL zZ=FLVlfKPd`e6_q=#h7~-9fp1%;J-BiVEvu6c> ztwD=6ID=So<#E=JJYKvjoy(cpoNh1qtoM)~Vx8xwJ$z5b?U7q!XjFDW-F|cR((9v; z!R5K1)yG*4V`p57iiZn_>c*2ZqQX2IV=j)EWF?N30yzF3*r3hrnb8y}&%M{nQ z(~k$B%KM+lK8WdCKT9q8Xy4*#Ry;&{i-x`MyG-}Ud@eI2A^5w(_bm2g5%X@ErOa~l zn3J>`M(zwwr?d)^(t|Mu)%7uee17>%bii2*0>1MDz)iG zAAzO)X{%0*_t)N8x#TY83jv<-|~ z37>jYQdw+U#Fe~m&H?S(B+54@wdliOL0OOD;YYIK8|QXxTpe*EQ&#m)`+)6 z*eT@AQc1mWXZLGhj^iVdJ*j9sT|oY=Yp^A-MUj+6D6avUnZ_+{)Q-!Feu|QaG;C|| zE(XXp_O^s~edMLNhB>4qkd3cj?0c z8c(<{`<~@`OQ3_-nFdJfSb0BhvjQ`a2_?O0fO@ukOlOds>Kmf7qH-X4UniHm{xGTw zQ+jwz7!zmd17yQW$8jw`-#-+bs9}lmAs$l1XI5ZppRdvl?i(Js!{}U*O+gA`T0z=J z?w#6cx^p@T9(2qYaUin5I0bM~AoO&LxFPV`Ls}U$K<6i>C9}u?e7D1!&iwf1-uwEK z?!YI-0d8FRq-l4EWN(a~k?SZ^xrM7A%3j;(Wpk#!bf4jVeG8cb8g4^!R@D_4uX zxi~ao&IDHBR1A{fM0&w5&%t?K!4^3_(cA_MHmldaD;%>nP~CTu_dEyUst?lkNBy1` zeq%7pN|VWLO4nV|l&^!6S7pfy<=uT(J!(|Ywf{3Xa+3|nxGOPn>bBx{nB3^pWOuEg zMKK6og_eqmcNB=?fTFPX;XAQ5**oVhW!$yO5zJwlr}+6!Qn5=~yd0<2 zEqRu|Myi-JZRLBLh=XI91yCs$!-hL0=hoDcQ_6K^!`*vU$-gon2;Ylo0qwE`Y~*0>B*BPS*nQSgAeH2Lr=nDjlKh;;&Sw# zn|e=uYwa%w;pE=lW5n5s_3{DHL2&EzZ`t8LW0QYZ4KCN+WVMRs9qccdNadgDB8GV- z_&$3DRN{PY#EIio9fOi|sj7uc{dNG7^o|!bcv7{KiC{?P*9N9ktn$j3(9 zvxCFCH0kSFAUv_sqaTa;J9=S$AO#CkV^e*wXcp5*Ed zQOBtYC_YqI)cl9LR}r|;{-?SBP0k(!*TU7DwX7B>uYYRb6y_9x8O_J^RzZG8q0Eq`ao77WbK%IyaU1CWhDU#bEZI7g4K>#ZxCN zT+s>MBlznV?;VM0(!V`E`TP3gsz6fhXDojn#)8bP;P};F>aQQ#siX3r$-zQ zE06a6RyFJiqZ8<9zBn{1&`6QQ)T=kQeBa!4ZX~uoa!f1mMV4g3QC#ikmW+t;?t(SF7aGxnS-l`ksORw|2p{u{r0nwX1 zY9HU)8hqdiuS)9anQ$G3BT>{cVa`w9 zQn+3yq%~d)`8DK`&?ZXs!0Lb8dvvt?5@&(>u=D9uQ~u1-12bWhAnIWCG%`u+H9T80 zB>^8v!33J~obYLc-2qyj+Dsgu$}m#bxNjbj)^DC3lV@41YOB<`_*n&y zQ!vPh-{Eo*iA<3Z;+u3Y$0bO)LVS@Nh0;h2!B?}k=N^<>;rPqFHzGRPi*0XL_?t9FNJ4hic;9o0 zTUa1+l6imkCr^kLB5T5BJ(rdyDG0|>>)xz=nilVY4(#&F;*7s5Tlb}0>|{#1ZUsC9 zpZ-b^3yUo*>yA#w_#b^do1v;Ey;o6>8BCVVBT)jnAL0;t;Mw~hGd~y5c_l2O}_{dy6JOPy;?YY%SWKP0EHK2$v39+{;GB5u}2w?4^=v zzuJHFGvTs-Io}{eNfz>CcXtUn=3*KJj=2}1-_XECqFsFvP$-SIS?c~Q8LA%AZ$Bnc zf3O+pf1ZZX5^m@XFXbcV@z``#=avK#Chh>qd6NeDoS0@(n?!6{G|iXa(7Dj2{zWr z>2VC2*R(3#M2%!R4xeL*dgqTV7LaPwcU!$2#M&KyYIukAAK6_!J5yQqOl>H>`aDXP z<5%Fyld5dR>E5%RD8v4F6po&nuPRco7=-hjhI#U%PQ9&EvH2fSFfid+??+_>`q2O7 zL>F)Uk@ySVnztRN9?yOrt;`$t_s;&rZi1UZdi@m>l9MvNJ8W(f!{cRg#MbeiuW?|P zC$1uU9lqG%{$hfD_Q6A|XU(5}H~@2a8s#pQQp6m$bFT~t-FChhD$8UhJ1Kaq;-yY3 zPXm-CyS*9Flk!P3xQti-OikYv2j~WS#TG)1k z;7QwWl>G5z0jh?*X?k!WTMcvm)3KP$9b0^^{y>_|0v*(Q;3A=@tR8ac@fAD0(B9%f z@>z|!Jx7QB#-zAoGi~SGcTTmigX!Lj(_^zS6#V%ID9?LA}!BAWjW$ z%s`>0uWa^VXU>jpum9;5TB@tOWPwW{C_KToyFRF(0yEi8xv)Cwl7rc?oaLg@<8af^ z5QuktT4*Nge>CW^=H|&R@4Kk(k}*GTV?Do^o8^3lQAbNrIBuN%40hqkonhJCTNBB0 zxlqWmF2uavKuFMVs`HJWLC|#+)&sM1cv;e979JU}#x$LM?Qf5~lr-VZ_Y(Y=Koe2X zJL8e7d-5~?zy&+bs3sb)dS1t<%lHT->p-nZqlfI=;rhER1g+V-g+isgm>TOsDfTg# zw11kq^dO%>njTMl93B^mA9Iq5K5{LZqxAAXV@CA@1|>GyJj zgZ3F-v6isWB1CWRwCNP+Lr*OxzW3Sj@st<1{}gpx**oX6(i1gar7GYoW|%Tn+TE%a zGA8{LCNSnHk_`X}eH37Z*V;(L(-oUNc_BU|ijtd}ddOdqSDsr8qcKiiH3{e|DfsM@)%aS`%a)>EaLkK|ho_bB6(RbA$$XHCOt_5Q>3g_UVW6*frnE zDcQsKK@6+X`=EiT>*_}C;&J?O%!oA`;A$dmyr0hZqQYpd4)-FPm94X#es_jSVJE4x zSAp#U_F|&a9vIb=qltiBGrPGW>Vr+`U!cGssYDq+@$<%O^O1Re7R83g6^=_rNS?*h z-`yU^TaCm$7w1bfK4>Gupx7IqHzZspQVp=aIR&}IfkEn`F34VIM4lp*Za%2|g`it6 zWhlKkSZ4}K^0zI`FXb0@vd}zsb?$gI=*vj?96&EaOa&-k;de9h_Tlgf{^8{Vgfc0+ zMt9te3O&HPRUd%;Q4DIwd8)xlopRbo+#frZ;DB(+k}&W3fX5=@pG9R)d@2d}< zf-ws|CkP(D6Kh=U3@4@{>;0jisE!AS(AZ~QfzW+M@kz2!?tYv8_Uwn4p1YZ< zysxMeTw;p zEA0`LhwlTf3q1EMbUnofW(}ICt5q_Z@sEBJVYw09oSqi@Og3khyL`N_bW+hy-Wt(O z3Wp8wxzZo~^inY$_=z&qIwz7vrpv$shq!Z0o;DtsaCTwz7dZHOS`>qwq!wMK9PyB+ z$V?#L|7<$86L?kRS+@dxaSPsVD*w}N$o8hKe@Za=a9TYMQ5Hy!_q-z^sH?FwA;~s% z9Y(zZFs;VPzkC4(Mx|P^xqB9Y3@O3f)GPl8uU;RzPE3B}+@2 z$T{hm(1$cmj8(jFEyL@QS;s*LTu)1NF5B9v#4k%QWdC?ao$9_m(dhS$TGfHWR_(Vo>W(t3YUAdytT+v z1M6jSD%BMArq=Sinz<7cx)Yrj=>$w81h5ejw1Z6mc1b{+#{Gi|&yevOiW zX(-wsd7i)amE}}1z)(ovTYx{^i9O9nILFK4s3u%txbAJTPP;-+6-%Jk@lTXoSoQ~t zJX@8}K&hJ}nqwC_3he&Q{=3IeR+`=l8%%Z_C9^o#Y&O$DMocNF+4q^6f)x zFO`p!q?wWRoKMGjq>`MXOkPjf=%An-$t8sx0uzi;gQ; z>6v5lxB}P%#bxdz<^;(Hyzx(cYn!`X-UYmfV8tN&P{m>g-1F%5c|+(A`d-1};R#tCulSm0Ni+ zx`oitCbKfjT8!3>%I!M*hG!+%@#4*Q3CA4wp~%uw7DLn0vw_;2ZjY)ty2Sk7&)2@k z%FOivmcq@9?5&Sdt?bwKo5JtEq`41!cXvsODLv76TsD5SuKeSr82Ry}U%365JFJLn{`$5jH;5ZOnN)n#FM502o7yHf1IAB$cLhA&1G4ad0#M4S&KQFE=<#; zUFngWu|h1`QYO6EE&QrewoCgPs`WU_ePmK#M5myZI?-DMYIIr|G4t(f&koNm*dt+0 zdkBK<++I7)Vb|bJ^a|P2j}k0n5KEIaX~Kr}1B~_HkPMDYOMqKqT_Jt#9>x2rNa+hC1A@{6E`NZ&7W!{jmN)@X9CqiN)~d6Rli(a_LL!>z7XarD>V$I z3#T_Ae7wM~zvJ#1?8ePwFXpOs_`Fi@gpl;PE?TirC~q-OIRBH1Fg^o1K1y@$nmo_z z7vWv?Qa~)G#?tCT8wyotFtjS2pQ-J`ci|F0j6?Md-6|(*%q()c#?zmus_GX&>#C{f zjZO}AK19?_ayOP!G|!rt+DsoW^#LfXv<36`_HR{et_!pb_rj~^Q8A-Xm8^S2Fly~S zzHR0kHCv7fR$6>1>pJKXXTK&qj~lGB5nD}~wl`eLBziE-B&ZIPdLW1SG%fe~gadrX zi!_0z)x}JqoeEsVj&t;I`Cjo!hd&DM#~#F>cx2(UtLyb#-d`NO)s*5%Z|+G`>roE9 zrBG;OrHM)6vNIdI+)Z3LpxX>LJMU8aU=l^oDErD>d2NL|`F%JNVv(qdAL7&EBce0H z;~LZ+!EVs*%^)?O142vsAYs2$+p9=%pjgnmxdOFWlq$Yw9SzpFLN8~Ehs)!RLsuBV@X@{bv; z)1Ltw3#Yms;I9?aB>A^gnR*B-uAIr_73%UK>^U(Xkhz=i zqrCseP4VKVpOYN1n%1AyDE3>uEWoFZ-O!Y(B(@d%rW-(s~RzDqu{m#{StXF?k`CMJ3_H?$A?3K9fGly-}; zsb*y?%XNC}EkI^x)1b#iq_rcH+5BVc_Jw0!?v)-!19gY1OaMr#b9~-iTYs{$eTXaJ z-OhMw^Oc25tbEgiEKkW{Y7fs%&s%7najPgG-0--ShHD|H6S|6&k`G~59T=Eth)m>q2XsMMAet976JNIt)qO*=ci=Ah^xA=yejH=PL zak<$aciqRg2d#uzzda0A;82QoC2u4q7-BQlf{n=LYz)h$!*F8$AL4e!S>0S50%T{m;jo$T_7oa<;FF8{z}C-eU0)Jyl7YvNOMbN}#pKMzHy zcAZ_#dkzIR4q}S#K)tT-fEiSzC4@MAO2n#`2y^~D`rmbrCq%rCPhu$gd^X{?{D+lp zlcmUu%O0wWHJhC@CV46>xAbPa7)6eLpNpzY>M5oht#lQ4Z1k>y;??^MkPs)_*6#9h z^Bsf)+9N`!It&2ikIEgqnB~P)kvFm~)Z?LuLEH*Wvg&|j7SEaRM^6nB!YHyAiJ=ca z2EeK03$2VVtVp=tlZxOq@7)Djp3eG{BV_pq4*P=IYvZLf*?9dDQ~jZs>`BAgWG0Kj z!Z6dpmb@i{xPwcuiY+Ke-cN73iL`~DKfRNiwrAa_!bG7|jlk2PdD&%~aVyP_iwgk< zxNRi>6lGaPS}{)*%8L{bww%eIGsA|-A9U^TB#dr|Pj1B2raHJ4nb9b6=K$obV#VB} zSHMeIW1d=%3nWCj0RD&P?H&OdhrR@4ZdSJ*nnuepWTm|_Ao_ZPdQ(c;-b^OhjLtOPyt@h+_y!RoEfm;5#!R8%w&4*VPO?~ir5+)SrD3D;TdpIGI!U! z{j2t%&yP2705^`Q?(8lmWkUGKdY-=RuFXs?z#Oz|Ryyi&tfm@Dnm zS8gH~>mrv|Jb6?m#p9zgL}Xu*?vPe4I$V2L*>wXC#Ti6=6Jl-cYp2q;y?uTCp4cx1 zS)xR5>r=ImR0nQu?lMJysByKCC++nda@%yw$B4pbHPCBBvh_@&5u?b_$!AoRQympr zCt}V+Lk9ROUtgB5Ox%&+8@_IumqCg)rZvwj?NgLxOK*rtz5hmYJZB8#zM(H+P47uL zv-_Paw~osJDBGLBAJuASPGyuuKM}(z{7zKE$kje4`&k}`lJL@i%j@TzYfHC0oXy+G z>hQZgt$)&Yj?9sJR0%mk&mTwQIoL*Gqbhrw?&xLx0of(WcsBsgi{W>ig3m95NZ&f1K?T)qNHwRmE^Cr4_9gibe>W|V*<-S zfu0xI-5M_@<0_qXzT)w;tL&_Ja-)m5GF{YVqDqPUGj~niZQJ=@c@Q}*u}(|Lj2?n3 z(QJs6Fg&(-eTeExs_z?6VK!nZ*C)FUYQLFnB;qp7Et`>=mqewfF8q@6A@<4@_Rjs4 z`y5K_AMlh4mwYU*sdIZq9zONccHj?CDy}d1v_haCr53B$C3EHRvv7yH>$>Y$FJ6^ES%q$+8Ht{Nax1 zI=KHO+_(k)J4LBlTX?`R_{l%QdTOBclNs*eGX0HPMipKUWm*3)P%Mpt_x|RVu3Y)= z)xzS%6K}C=e#7?dD%iexqGi;we;_c!&A!wRTC3+)Zi4;0!r%%E(`7FS=BJl>dq#Bg zdy?i`-$`p&0oO#2Et8KIcC(fZb^<@iG5y`3_mA<#OIlPR&o~WZk>@-j&#T8u|Bzo- zI;`>6j(X=$mbXN}k231=1)>CtDEu1V-`FuhaW=~Cj3(P>nLMV3weHR?GF(* zLHTFeFR#6K%pOXhmTy1TXXh>_y)4{1J_?gs)&%HF;FBpK0Z@bB#W~8qRLXC;0V94! z6j|0?zt0>$SN?H#5gEkSyEj3uJ9+TCJ1$E-8?;=FIs3WCEGW}!6N~hHSzk&oa_Sce~EYOs?Jl> z=PQqyJ1i77Q7qD4QwvFt(^T(01ud6Xn)XcF=&!JTDdhOo+;qzCeD`$S|J;7&BByR` z0Ilqb9Yc5E-l&Bf4m$!jr~Nw$x&=!7UB)X$A$O`VQzE856oLSVQTOR`Bmm~`3qq=5t*K+_wGG>?BTV$nA>Sw-r}5ZHQ5X=K{GuKPhl{VvubNNIy?m2PUw@x z!94NUe}YJ$^5^Og7FDIMN5OESi~V3KH8c@lZ!MM%eRvG7PUvsSvw>joRm+!z8h!(h zojjQPsl0qf)htK>uZ;Ak`;8YRt1Y#g$rqUqYgpOOmXv1hzCwNYX;**X_+;s5G~bZD z37bGYQ}O(8C-1)An;Aiyt!u8cvv3=9q#tn`&xZWjUerXRO^V%6K@7dD2QbtrSqjBp}yIzA!!i_-&%Y~gt7tqnI-Z@|(NH-W-ZC2z+6h5)0va9$~r&GPQ9sydax z>+l?>>l#fWOlS1kgc(2LNfvURNJ2tm_2K10ba|6sd(radgzMMX+PO=@g_{OQq_n?3 zjc&>ikl0iC30oqXa0V_G_EzJ?1Dzu16?-!Y74MWaVbDQ-7C0r8w2&_?;?(@ro=fz?Aw&>uf1c+Q-4AfN*W z7d!RM35v=Q@M#?7SUh;j%NNO+Z&0UPn6YJ37%nMClC z!HrqaC(M~`Fvn}xmb*st4=@Kzb-xJE0er}L1sDQ)SMIgjRLMAA_miuQHFjO;n?5>U z?laa}elJ&KRr&wM<=y6Fhe#-^9sFKi^rSJ58 zlkmmoOQATa?^^T(bxKQO$c}!L<;gz4gdfK&<(Sc!!bAh)us}G=$J20XPV6@O;WV%l zD`v3#($ju1ZVOmA(EFlkX@!$NQW$PEl^k|vW^&rolhi!mYgqi%`~1{HL*ce>kt;KDfa75H0eFbgtqZzLJE@R#`LN`r>>6 zl|S)noT`${!OXta^Qh>p18zE3LI{w>Y5OX#1s$%S5#} zA9R1zL4r&sPVM`i&J~8BBIW6G@~W-R{?*}`}6&sia?EbE{Y5> z5bKtJ-v^j;0wQ=r!_eVrawE<$EDv5Z?E@2YKx8jT4TYM$k$b&(SHyk~DW&Eelfo$B zY+XqDwbQlxc4(JFRjJ#=r*}fEZe|`^lf#RJM!M;EDcmTj{YZh+!Pa!j!9tuwOli+k zh5qa%p4~2|3-hJHY2@zy2BJ#2H+R?u7+3oc@WW7@-6u48?DE_rm0K zy_VkBE7=r-2wR7VODn^J1(KosJ`BcVD?e^vH5|<_g|^N?%rFQZ-jO_P6wxPf&x?;`)Ytr7};$r#swFYbmfvpZwM=)vzVA^BlX`Gnbcf5drRGq|W z0Ud-vAb*&THT?E~Np}?QpbrnEO*N_U;8_Vel3Cu$N6Pk*!UgMh)g+|yXj3Ts?z;JI z$_4I&tU*=k>A*3e`;y@~Pd_mQz~=n;cXjEj1@%|EIjg0|I8HM-mQJ932=eS9O}ZJc z?1=OeMXQRLlW=2TWUe{ib4|{a$a~Uw5w;zpKpZH!Er4x5>o`UJqB~Z9{{~laQLfe8 z_8?8x6WrE;j8(>3;`Gm;XpqC0OPQ>V<({bHOv{1P+o3eYYPp^LL}m_%9j!;=yiI>k zi8hTBy&fhBUm8E|`!_eXEC4b;KPXN(fQ(9d`?Od-u%BB${ux=NnqAMcKli`|Jed3Dj~t>D&3^#zM=`Iu+v{stWXPXw{+kY;?9H(p@<#+cP*ASZXC-o<|ryQ5er zKWx({PQfTqj-OUmiHFp9?=FVQQqh0n!5YK~vpObi&-|qp_h|&5dp&bYOm!s( zZ$0sLCeE~Y0So`eU;8*3#gqA67Zjr*?XmSqfJ${mugl`TrPS&@w`R6-H3W;RakD~K z|B!dmiP$6D;d$HBhXC_GzzH6PT?W5V3o>H#LC%7Rl)@=wA23o&B+rOkctV_9k7gvX zY*px?Fyr1)PS4FUL7Mda2<_#t{pp^yU_-UJuy*UM35w<48-_Py!$o_msU$o>OO z1iWX3TR3M>ldn}Ao+k5MTBq2t0vHxsH0x49QD$C2^>49NVv=r{37H;a2mGHtz-FKiiH$0^ zUU8@=Tl3VD-D*CrYN`eJKqU77kA78Epz7R_GG1D?M3fBn?J4WWYz+#nClriMAC+h= z!?pD@l^4>PDw?=CFO|~X67DBz#t%P%jh}$IF+?nBodq$prj6IhizRFa9T% zOdqEE#Mh!=H*^1%pMc)mp>g-Ocm=94{qDRNtH=MulHH>M;v5F^Ol3$0OvvW@lBBC% zSNpZ|`^egV7=3fYouFU5!Ihos3}3ro_L|A%c<>&*y}th?OBP`KUo2Va|H_gf{$^ZDD1J^3d2iBsWca*`XIQ7-0JqXO()x?R)vDC$=xf8-~Lx1c|Ab zst^gyZ_9HJp7eTARh77DWXf;=IZ_T*Y#tNw4U4TxyuSDlc|#*AX20kDbhg!6$sLM?}R4Od+!MldI?wFUc!Bwh9Y1kJKGLEpuKPA3yt?kR{i|uy_G+S7jy{!fij$7Uu2{s8oD)9Db}h(tUn7sU>_|!mLXF-?Fg|k z_pHPFp8I8OLcf^uzTAFia;4pSIk0+2C~gnv=08L&G+gqMPin3Jr0!=15_7|qdx>}rox80gZ%m+>L_zhW{o!MJtfu! znKDTuwHx^khO%{e&UU5>p#32nD&FZVC3L~?Xi|^_hUlrfmqYz1cM(+XWwJiY?x{kL zlU}LQ%g=5q$+$UkvBK`usT_KWrvi6$*Y$%B`&u(50MG$y1 z)r6wSG7D@sgX$QpHvF|(&-ZL94b69bR@R!EF{wz~{#w%*P6SvZH77szMCwP1q!U)j|zwo-{Sy<`D!YDcO5zRa^1!Uvi!P$}PK+vjA}`7WBgeDB`=pQEu>zvAg*JN5$I+oXQY zX1y*8Ig~a_?koI^_evkBx!$lb%s<)KT=5MX)BA^w(b2YLNc2%RSNy`TlkETXX~&OR zw(Ld|%+OWm$7sVnOrP)w0c;S9^%C&u@`bD7@cS9m97TXz zTGTB_AxduobSm=@%{AI{ieKncd%5M1ft*5bpB57-)AmW*3~Afeqmc#v%Vh+FdJ^{C84Ph82U#O0@@KV25HqmKLFebHiPM zMeb7+-Feq#@Xcihc6aNw<}aT0Y}iMeuSa+!iTTr^x@&LZ-n@T97H0+wxSLt!hyRAg z8u1$z*kj|V7=N+1I?kg3-hq-$o63>%XN5dfRwL>QNNs7+5PS}l&sT-Qe?!LlAwMS+ zhs(Yey}%5p7W&GBRDk8V^5?z zG*eDzo%JDP^fw=i`9HT^HV}@g zLc)i}h$@s=r4lC34ZVD4M3GzXr`(Y>wE1y2rBK|oTgfjQ#DELPYV#fI_t6xmoP#r6 zc}T}=ye*(e);t@RG2QEa`aFh8X|wN`ut>;4Dl=0YZqCaiKE}-9&wjA;dweo^&i&Er zXW^p)rEeH^jzouV=-4kkNe;Mh6+Qunmhn39Xn$ehv&7E`o3D4&i{;O1Ee5jA&TR}a zl@AMsrrN@OB<#(S-zU%EzRvnpXuEMojm~;m?Ra_kn8I$xoQ-$3w%(1xP=a)Mr*6P* zA|O?or)(bOQ+Z~V7#{s-Hn7rrr~)=Qs)GNR^hH-RYu)U1|BfgbpKVWIxjsa4psJUY zzesZJEkMLP3WxJKM0Oj=ETlHey$QbB=9*UgCSuBou zWRRap-lv7>W6u4*0WoTv#}LE58SrppG4A2f4)F7GWX zZQ%lSI@&}+)3?o3-r^u15)2Lm$y(;4etys?{TE-Em&mel<;U^qe2g9a6A(M6dDDf& zvozLRwX@3~TeXhg&QU+%dkuIzgbw0oO*OfI**43_&wFZ|AZmCL9SJ;+Q)drgcR15Yn%jkKDto@rSz+fx+5ip;6X#Bcm z+2MzlQ(ia*8AczG8XBpE)WgDLog8ERj{=o#Hqa*BHnPvr8PCLq!NWvY1GEgkBA)*y zW9UZ87lq^pH(bnZkDozYUnW87@$<1tt6F^GMls3OZ^7#n`#V1&elk<@Q48rr-Kv>C z3|7XF(xhBAlY&qMVWS~TU}aJvr!5bRm{Ul45YrXC%u_fHla z`k3#|ZTIN=%h}}Gmbcj@NSQW20jZaES}p_Q#m>dwHoyM~!SgZN4beV~+xl zpVAzHJRFJsz%0Ll>}ig%>G-Z!Ri|=4pJei5Ybm6rthRL#LM@_PgK)Itk#_O zSd>mzMsW3Iq13mheV_PL%k$a8Mn9XI^z$*-AIiu@ulEnrU~XH-f5VMa5;{stQFrmK z{ky8~_jp$$3`{DXoUbMxjJPHr0$OQu!@+FPln@WVI+%(VO~`TKDfqu|eNF{tr0X zrFNNHEp5WLk}B^vnOz=i-gD+}MCl7ZnU&F~uirvbi0>cj{M)(oM5L>5^**2r?CF#K z$z9NYuy6vtzYY!ubO(d3Qe)sd(;6lWn|poU?r^@YZj*R{I<-`et?*shLB48Q6D}|-0!qYTGBQeC@eF!rzc`1f7ZO7xQuk3jzBD-|t;- z-%v_dn&;cG{(t^Y?4GgIYmyfdfBvh-gNyMoE-eDP@ueip}b*unqJp0UWg)|it2 z#xC~gXv#+Fa;G1@9MTH8+JLO1V!ox_o%81tbexNBAnXQ%BnDVJ=24;0y35eUo=c$oCJp9BCdt*zPeEU#1eSdkDfr~^d(%z_j>G%6~qJ`bo4?@opQ zrLFmU0jMQ(je1E%SJ@$MUb#Nq^l*^9zYrQ~N7@V>|gbGbYb~i^L}mUVyn##lS3*P#Z+cWHbPMW`R}7SP&JL6$#H{pl{R@~29kyl$0;KL$n%R0mpG z+o8!uV*Rwm8TKE5qZ|vK>dv^RlQEAnwDNy-6Fjct<@!?(A(l5YROHOAmIyPA69S_z^4+%V(@;FV=_fiTE6ANQyQKsa~0J#UzpG3Z~J zn4%pgv+OO%!~+nK&txCX+2SaqIEUL}*{$ApK6foHDRj?>4}fNu-S8`$yR zWYrWN_TI!NMu{hN0up8y4X3Re7DHFk0#Otkdgg%r%;vfTFpHt|&Ko?W1Nk99Q0H6a zkeKfi+`vOR9FwKf!p?4i$M{2*7_V$h)+EYW0&qT5TAyEq8co9U_U+q~@)d`!JoKn! z0eS z=6a$Jk2PIFV<>3_pLoD#?QMQtj?dP*3N|&@BFGbkqhV`~&9+wKkRid&&Q6QtPwx3D zb0H^4JL%T*nuCPh1y0lEgo2@TexT@{n_aWy10(?;3!=_OmiHc;qU9Zackw#fbha(| z>YMq@>#=V;e!}ng6MJL=Va&@kUxl6Ya0vu-iE)l+{{e`hv4;jGyP;H4dCp&Yd}{O@Me0OoUURk30HE8{xzPnxveDN~5#v!@!mkDn1pPkdv%g{kK`Jp^Ri*uT=!{aVnsq;2ki z7zY$VF!h(2%T9Ktj2%njL;_m^He;-!YbI z$nhDPAHPQgcx|3m>gNa5$A5pmhuAhs11`kQ=AE(nES*y0AE^54cde|PkfU<5p?SZ2 zod^Mzrk&}=WSw#kKiv}Mj5Ev)X1QqYJh|rL_C&4oTIUsu@lQmlqSZ3`}F z1<`U^i9O$o4>=g>gk+|*hHgw915@Hm>vGo$ue0Tsn`H$*%>C{{x!@fq$MYZ7EjHuM z*9)?Yurn2N;r;RcWPuZ4wQ5hlt9}XFNi@Vf3fozF>4cL*4=8gVx&sDJxB-*TtLu}& zcCio4I}_K#jYBBdoFmFBc+XuIvQk1S(6yQ_xth+46X(jsdOtx~g*7Z)1}h;L<2HuW z>TAz=W}8jxW4ED)_{Ae$UfYtRbE5_Z26Gx4S{vzId1%tu6#i0zIPPI=Qv0-?Desc2 z1I-76I?D#FSLua3)J2JLm??!_e4(DW#fylr5eQan%~^Tm)N%H)Br=rq+gO}Abb7@k zC@j!YHpS{!ndwoT$dc|WPYJ<*3oKNiz{Sw%aR;K6AP8du3BWUpy^savW8oi6O5-(; zUa2OhGj}V`3^oqT(EG6jk!JD??%$vGX&HXC{HFDJxZhN4B$7BdeDC}zikvg>&_jcR zLvrK&aFqqh;viiTYCWAF0ZN*@n*TD zpcr=F@t(wkegr5?I?MNsMhU%p+bGK}SKes#0)sP)M_v2|jX2Xz>Rg(zU%vHZ&HJx< z&Ee4bg<6Eo;+g=Hsw~z*aA-6azpY@H-NK|&hCn$OiJEq&hK4~$07F_`{>yUB8$%lI zL^qxVt>r+b?I!_8j)i_2q3L^MWU?`Y*L%Qx3m8acnv;AaQ%N=4p=1Dacdl%d@ToDR0l8||ndD7s($u4caU+7crehZYS zRwS}?iEofz%==0CYK7p2vGZwGXq->9xb*eX1vHaa;zIvWFBI*jJpO=n>Hd@xx$T3R z7>!I6*9$PtH@)E>mxChsvmYWo3n7ggm)Uc*F@SrH@$^-MCe<=yxy|u(Pc47)AC|PY zRjTWC2l$f>=VKjsj4GAe_wddEQy%|<|EXz(U#-L9MAJbg=0WVjR8LiULK+BpDAKf0 z&Jkx>Zls5K+;2A2$V2)-3ZwGl0-O%@)b^+*1$6-R;KZ9IOgui-eM#_90n9KFOh#qn zc%Pw5>^8vC{7A_eT;L0Q*T;$m39g99T8eYnPs9v#&F8%A=?kz`vuXOdzaOXT_8^NZ z(m5{mx*H2|c0P(R9>s58CZBeRUH#?Pg6JePq9{g-qFFfU3(62%g*d2nY?0V>pulM2 z!#dVOLSm_V$8`g_j07M(BEzK(+(5;W(H1}|zm;yhS{8j#HlND&E*<>|vz_tcJ~ubh zE%&zli#j=JDmP<>nG4u#qlA;+@KvC9m#wmzS-Ly#^L#r{9v4gKZE&$_Hw@MJJ=kAXQa?Po zop}r+gJL5n%#~}SumaD?s8)gtfCTU zQe4g~_Dq<0q1|kfK#9W743DxHu5z8o-1M%pBuY+jl_{Bn>Xe&1rCa$m7{|{2&=7Q8 zT9$P^b%+B$6!r4Tct#g87#=n<#4E6wjuYCV)*5EKSo`ShaH&DVS_?zmq z@r08Wyg~zkI+j%6dQP3IKUK&oF{sX&MW>W;u=1=D^4P5@qJIWTIof!nVJVZDcKX?9 zRMkPoKVkQzS6@(q_%;{aTqe=M^aMOJ2D^>X-6=xGA9+~c~Zjx0)&RLxV$I6lmBsPs@v%ClqW7Uo&BZG-=osmRmnpzm0KE zyvg#at|mOy+2zY>tkW`^R60k)W2A(0z1ds#W_J+R<<`UncX!{Q$lGmux_i}6{oNzw zCuMOgO~x}*)$uMe!?zNvwV@ zrNC-W@ri2l!Pbca57@`JY`dTLrB24`oHY7G$Vy9LY6o<3qjx?3(BXc;+d+qL* z+feeDv~MxCRI*qC&$(2|h;j+8QH8J%<$hF!yoD!vmIirLyLz+SGlpGuUdPfBs$to6 znDfEn8?@vp?~70TlyS>V#>vph+s_MhSP(+BGqkPmXzr*GvFt(}cqRzq$rvwhM%C%< zoI3w@3yYnqcsiwnleL)*zfAitUIHRBj|+`hePADHC5V~gHX^7Y3yqbW((C&k*+Xnh z_|Hx?=>8g1nV1|^QIW*7@x%;IEbl;42J2ZrRVN7u&UvUNaS`s5GFGjvhk3RkC|Ddr zvfT~cQE%NX7wS6n=weDEh@iTr+J_!^^H{BAKr@k#5ja20I&IFW^X7p8X*}75*Invp zg=UMh(#W_(>HaC)X5pK3OwB^IyGL+$5P}9Zj=i@Kl0eiZ>1PkaA+ZY4>13I`b$~mB zh3~V0k5j(HPhD|zNr$zYy=0o3m1^QR+|YPLDzQ(*D1*l3@ltfU$X@Hf#h5iy{5Hre zcK;{J0Gzoeaso2MK0SfpH6w0U*PwkNX1t7+ralldTtEoVPq|XaJe0c3DaLy&+3*nk z5a@dm@uR=xx?A@+uRIoCKZU@xE?BCZ+&)(bXBOSy;I__5+SW`!Yz_F(PhWupwrBq= zn0E7G%o6DS!CgM!+da-b@9sj+8Ry!j-Bn}h;dwNP%Yz_uJdbDT7n9~rS#n>dTV>*6 zc=BwCfErrk#m)V8b@{^{rhBWoh#iP(13EY&4srvsbDiuPrsF#T{C85e+?xSw7%@|- ze@c&+F3DHDVKGX0Lwnnl>qcj+MF1O>-&qBtRv%&|kgBG;%?)uFa(G~}XubqNgJH6XT70Txu19l#9|04E3Feqj% zgPz}kPJ|R6R)3*kJGY_(dfE)fo zcC%CQ!G}fOHVUlL(XcMkcHHA7vh09#F~@n(#wbaSunEIvLyIDKaexzc1!I%KpvC4S zyP%^ZHU!ZQN!2r{bs)5HNjva)CtD2?10kcwqjz;vamyAz^(%czj(eU~Mrg4{Rm1(< zlqf9{XGx2m(@A3;nJkuR;@^!BVZ$qbfqyY;hy`1tR1YJ5rxm0%k9NvHq2*>#m=57K zTdW0;*U$z&Y>&BI;mYvsCGd%TLJ2rmXar3*j$I7trF4Ls?@SqKvwO19eGD(JiQN9a z$5IbQ2~jd(GTZAugcs?a+S!CWwlH7*wYp3&%LHB%Ml_KZLc!m{VCJ(oeOT<(Xc;eUh>E< zB-LyfSa><;t1=9%G(8k80u3aj!RZss7vV(42)_Lf^5Y5A?}qxdiW6%5(wLbtaa!?( za1Y*n_8auQ1GeHD+Oz>!4GR`8*4JZEr>2b7WfrMei6Gy*(Ea7Q!SiWf!tkQgnd_*u zYBQ`JF!}TvRW26W)9^lI)en3 z7eSBolXsi&q&$?YLrv0KiqSg!dqJWq`0o zd&OqJPPAm)L$lB`>({1;$uJhDzGeV(;S zw|ZG44+_RR$D4g!fz#TkOro19L3viur~zKAAJD7%xB=$BT&aXCh&e8OQVyG)&<7ry zx0?OV4UC#C^@hu*AjLr!=1d!zD!{K)(*9!)oNjSTZUJgF(TjK%zFY9;G%Aq^L)7c) zbtFO@X(6+~7l%_#PnOz*wD{ziR2AER7l!S18e!nJZ*}HvFNo;M4T&!|(KA$u#E~os z@sEQyH8(_gxjLJUT5n*uq9i33g=M00us3>Uo`R(1f)_$ln5zf7iX)6@`@f^q-;1zy zAhR?{gFA&xW1OXfq#|Eq+`>;`Ab#7vZqKA?9LZ~CN}lx0&tfvQHS?K!5(GyQ2VDpk zEjZ!KtshWQl}5)iSY(29_5=K18O)avaVEBLkQg(N-j|%i5ou`;obpf{zQ{(k1D>!> zemXcI$zy?VN|?Zc3}uTpy@+)Pc;3mN88Y`eQVWmJyM)udz>iI)go26eZQCl9tIYnA z4-Uuo39=2p#enHsuYx?v{c=6>#+mLe>9q6b5iYtf`69b2vetWr8<=ZO!tSXs-(R6x z3WxuM;Iy_r$HI5q{-7;4Pb@=HK+(PPV6&k?CTzy@j%;?0U-1F`y=Y=L8t|QqNA~hC zLQzAa;D+dKODR`SKi1v=f&oJE;E?GRLoH?zH5a;v#alW#WUn6;2AO4vBU3OZ)?4yJ zN?;i^MPYIHGO2Udcf9b&+XrmSQW#_1cvy~M#$8j@Y zo+w9h*(-_d$G%uC#(0n;%o+-!|$8ZIin_X-3?|yF7U%AFoaV7Y}HaQkDLiD~r>B&2_k` zvHE5))8zxvY`|)i; z{_CgDW%NJ(8h(h!v|nhMKS99 zFU=)>i9;T4^{+2fD?A+7C)P1n;rb5jDQP7W*8If5&O!7SDE(*b^kTCxJ#`k1j8odVp^Xfeo zmO`AIhaYl(|0pP^5lj7Zgv7*bCh%Xc0UJHaX_E~L67j6G8p)N7Am`An`0Fn>X<6D_#fg){`1Gf`G^zed7WfkZCZ4` zv&_1FeW@<5_&g_L+9HOV0=E8U)BV4E`a=djCXCx1$bP-FR5qreYSJo*3L;$CO+a2V0*Gc|>nn=$wMTa$Ra2EQP!K>fX0Vrd?e%%|+Vg1@%N z1!q){F&fGMMzNnd;D=8dY@05dn$9;U#s+|d2k1(7%s|%F73U*Bu06gSjDdt4&{Pe>9(a*b}<0n2c>5nUFCyUF1l<<~l>n(5DeL7dq4( z-8VZdF;E53Yl6>8(`CaNk%X!4)YUyeM51HDkdxST{?=4L%K2s5^g1Wp&*TbaV8FXq z;I)2^h;JJQ%tm?csRxLl%|ieUq;wSvr#1)d(<9ES-JwB7$(_D%%~t!-MmQ1Ts$fh; zzn6x0O4R@GLC$gSFV3QSbM=;hUhjBy;qQ#9wt#;q@d1*KryATt^$|_M@?F00pKIUq zz2vkI;}Xq@a8#9d@Dro@rPED!rzHBF>PUaj&Tq$u8G;Ka=r8+tlfiT`dTrI_y4Nh5 zdKK^0ySX{_JCk}qTF~LUafL!!fYu)(+GE_6 z5lK`Q3s>kP?tqaXUb3W|255#co+0Kl=(abn*VKIt*uP$k=&;ILjHg)5eV-^~w%^|Y zG7vi>w1$q{h#1p1ww~xCWww*XhMzx%f))@{F>dyRUwmJ%6W_iCWFF3!arO~XUnEKoJjOPmVAL#`dnkAGd8>TQ zwNh7Ep>gPtgpuozd;ON_aX~HKnxnt3d}OATz*Un$81r*?(t#az-}ecHAEj;ZVBK6km#f~1awc~?4koK3fxYcvn8 zHkxnB>59+{#CaaZU+dM`cF(V~>g&utWP(q+$p=2~N9-+raZ0#;ll-E+*=5lonHTcttcC#u)PR;D zARS@>ctMFsd``A4qqCkp@)H&DDL6l=ryp4B;V)4-wISM?v}}c+@536$ zv>F(8SMy!A+Z6xTbQ=o)$H6$a&IKLhqU!2pfiR6B8JV!9JXS1VeNwSfaQPsh`P7=f z+@qa*Xiu|biUE0X(k;i`Uw=aPq@TKKlZaXBvTjxIT-0n8bbbkBU?C)~&y+-kG9?0@ z20K`+ESzudY&L0YH9GK~i&**P9^-)xh;*6LY*5EnqJOh0nS>Ss>lwq&k_XNPil?J%C zlKZ_9*$lhRQ+|*_YYre?Tx4SbF0KeEcB#*04qusWe!T#5dZ@?oh? z><{$=gv#HC-p(Q>Y2gqC)-E6#;|HjZ=^)?rz`YVLb5|N|X)SOG>o<-69ml*mjSl1>%56@^g!88%c$Dp})yuYkR20 zubQvwj-qlzm^j6)=z&gm*hmWoc>rHXw9dNu*(eOiz=-!-*;8v&DYtqN^8V@o#>Rp=K{1er%MlJ9eM%Ao}Lr}sbx8-|DF56XuBZ}{zHv2nKS--l)o%V?UVbYVsVIn(fK#~9Mu<%th_yu zmvH+3k`D18@2>V-0P^|%(-yR9M#8`NP#XOX_aqneERD*W4JbnR=>9ADSjDv3A)%@a zKiK;ZNQB|uW`zVGkt@54|DZ3Xh$qE0=*L2}_@#Q}8XYR66QuH>?B-&~)`+>4FV{%U z)G%AC@o)l5@;w*Hq0TeOnjGZ}5Y<)vDIM4K*~G*$RZvdEfzS0-aEkpt{!$IOl5hwDaciUEdeKBEYn;~m!@CwgO;Gg zgnqqCTfgd?V&B=BRvKNpH2Cp3av+1A+HeCVvD#y-*_fUE{7x6g9!W*?ngP>9ELC4y zn-l`E>lMf(1E}5sArzBnu$jUsUEaiNI z$9TY1HY~P#TJL$)CQD4P?~m@!X|?lzl?Ij3{6`w3nKfmBpYt~jimNQI185KqrZH-) z!S*fKB(nAgGCQ`p<$f{Pz7!uF9}Az_pe-WkK^Taa3s0#B?HqR!%aoW43%9lud41M@ zpZg$2atF0dfn|qW?p?wnZrdB`a!Bk4khag0oQE5a=5x5-{&7)~#0o(h1*N$si3OqPtULFOsEv zkc57^&?4FC1>)k{w{lwHkgABD3Yl7T;FQI|rvQ^;12~Qev!hdr(6{PXP{-K3TAK+1tv?s1e5lQpWtjbZSAG_VX@`?Fe>>@;(xn zT0v^fY324XGwjqpV{UQ8cxWUfm?*dPz|H|zf7@#ktC;Yc5#?l)X$;rtb(nL(2ZJKejvWZhqx*&9ug|hjfiSESW$s?XYBSle>>K5OU%F)D7ggrY z^4xdBZrnQhWwBEQ#H>e^DU)9n-yVqtApFZrGjDnl!b4OzT`>nz&dWiWAmWOwvMWRO zuQ}@BL`14#FJ8ZMl6ok=vzPZk|27d8dFC9A!8LL$_!V&w7hbgMIJ02zLfxq6)3odA z(k2@A)H)0fPYo&=97XsoW-}_@QmBI-dRJW}b~usfVtUrg*F6iAdjD{sRvBo$2z?+a zzMxM-MD(f^Ij1TP8>L6lb&iAUxt-Xf5aBlVrtf1iNyPcUJaOux@h*;iw)o&`0=cNb z{-M(yamvmHi(lcu$k=xe(P_#3!meB#08#p$8t67P%)T+6Rzu~qazz;c98>I$}i@8;gVT^*4TSA@qwJt3UECcMfLZ% zF5YA0LbIPIJNFOTqlW9W)YiX$2Q;RSFoChg`HXqdG}oProyPk)h%`%!u>Q0Rp8is{ z1i-IKd8TF`5ce;~Nu>^IFb_nllC|vj5cnBRv`EebfZ>z%EH3H0gK;!?4-$5NSbpp6 zd8$%3YU7h+-NdgEZ^%UVT5p1vl})C+nE3%`XKj6L{He+KSN;)w0{Mrrc2}VC#CWnYDS)V-6c-!)}RCfsDkgMi^gt2Gnc@vIB zytCJauf2E}wV-3K60f6oi}pIGL7b%8OB}mcwaOn7k+fH*n2FtB)KmFxBVvI2xs?o{ zw09C2Hd}vRZ7$8^BClSG0kyh!*O;R@EiIc9TlVytNLpocoH4rc00pgI@p34C1^UvS zeEjNv9I2ID8Vlfo8ch3yMpsD1+Iq2wnI5|ogVPPb*-$CG_tqrT0cA$p-7*?>@}mts z7sD^jti0h?h*mF2{?Z%Zo)ZWKx=M%=;4%c#IQlc(O~KHDI*^3gS-$r^r6MAbXi-j< zBto|LtfO`)DSN|+B##eruUi=76$1kqe~hqe7JcY?=<`0}EMs)Uw0q!)s(cj*6^Nph z=*6ebB=Zzvcs^+s(P1ru{hb^l`P4CdbJQ~%U%+#BmZeo88Dvg;bC2?8l3{YkYryuKet>^=tR+as zA?4(l08ZKA-(;&Y(fn}n6eBZeuuPBC~1=xDtg6p z50&X7Ib`4LfxlfIUZH5-t_sGniID-6a869SzMSi$U4XUu`Xijjnp}gY#s=;&7o_eF*++g|k3ETQqL2~}Ybb^^fm$x!FF8oIk zzNe@)duSS_>e%_;%n&<=EV*VBBmIW1+7&2!$*XY!_n&WKxHIFU5#m@JWYCB>>snlM6TM8F{QRcC zswph{xOW`x9yp>ndtV@DfvBua?0L_7u`GbvtPLQT3u^#lP0EEs*BAuU5pj32#M;ZcD;2V2=uLTKyu4TD)za zb=w*>`^*Oox7fPZ228Q_3RTE4bn(>JgT##x z8wI;{n|Dak#kzyp>aWpB#+a!6hu-}d%VKld%q`OS)SRdvEvzH_O{2KN*n^KKHDp8X zYXTymn{3eh$vr|p&DV5)i{y_(fC{viZ@CSVyCdnIHg;%Cl*|n4*K6_sA$w#0fSx0) zm^TgcJsI3x%vvvUH_LMmv;R`n)t!M(nEG!&J9Dg6nsj({|65#B1O5MT&HoFy=HLlD zzjjQZfAvaL%=I_`rN(k+!~45?zLz&+wbYE}Ke)zFFo&3th~e;R1bR=|$RyK%v#@jp zOfXn!HSLmcs-l6|oi6?tTJx1lidky$)+;`Do%eeZyG}4nDji7u{eM`Kx(Qeg+~b#* z>6H{v-*!Upu^-msSAMlq67n~j$$d=;9JMD#ZEQr~A1wBhii}YTTow5DX7PiCIK)g9 z1pgo$xBR{^B2GGqNB*ddfC=tuq!Qk&`1MRlzSHXE<_0ytPg*Wj^T+K;)ggnA2p|7; ziH-Lki01E+&+{Ak8!cQSBDU8r-z%;ktaPud23#j6Y7`84`&+(Pf2Olw+p>ReLi6hj zItj10!frc`S0}B_1Mf`o`t9{(zgqo?dpPGD!*XB0zOHpy`*xnMOK{U!_Ix(SRFKyP zcKOcn3zp|x;u(0W?hR&zBWp-i!m|7q62?r5IYB|{yF8e*T`3f*nR3a^ptH$Y8=>e%MAie@6RHTn&cUg$YYG@` zM(UtvUXpI-y`z>&E1DV51&Onm^UE1wi&n@FNB`P4PBU(Bk&cFIYkp!ao^B=bys5** zCFxO1wR|sR9t2vSFr<5<(i2@ z_C;1U?5Bxr*hgEz4{>7F7k20R#hMA~@bU&392v9@tg|2fiipwK_lJTKP0Vttk(4zv z$|H?F`St~dWsubJfbes1sXKBNdfi3YocpBtgYn0BKid^4x4dSw?w0M> zOhpfkPFZ17P2>DNAqX@+i^hLJml7U#A{izLGN}(45b5#I->9Un3In;r+E}J;JUvQs z8{&taJTtfb0&R01+(ZJtomPKI2b>`)5r^DbxAU^gxmv}T!kk9)os+^=KqQW);}w6b zy*pbw^Q%y2Xmw*D4CZ(h^qwW!6#!Nm5J`=4f0W!!Bjs|S&9Vm2-dTrEfNPLV`RU29 zFUfg^sQU%sXpOaE`EvD}5qotOsn-t%5lUb;K4akAq)gU0ms9cl@)4z#Y49Pr{BLK+ zS{8?xMi)PZm;qRUiUeD}d?si8C;`WrQB^jql6uYcDk|+&9?D^)QGJh>n7D1w8yQY? z{K+EaK*K*C=pYBoynYyR-#9b8{g*Wm6OVK+&A<2xc>~2#)xzTeTI(C2V zW76P#(6Q7jlcshJ*iRJf(%x3_nP1r=5y*%^;w}&U-~r@b-`hts#tUVAH&^XY5os@ z5pN^%C>$8^IBnbxm&3erZcgMFxDcnv`n&*ct!vMyO^+DYE3O#A41sFhyMncju3?gt6Tjk@(|Yz|p8;Ol9F zYuwJi`Cd%~*o2LM5J2A!wVEq+f^NKbLzHogE%;9)6izX?i2t<| zs#B^xt`mnAO(XIs^A4C2pH@hGy&i11@71xXh5kZ{MBC#6Ds+A+TPb{)T1p@)L-c4r z9Zi%=d!ot}zIkdZXv5LJAL%6Z47Z=b$4T^b};6s zHRcKxoZf$=1JQR29!&7_JA9*DO9!wZVo3azbeYV(a{H+-6VInk{5xV-k-HH{sv**y zCdJ0_qJ<}P5;)RY%;<4_cX@^VkOU-xZwu0#2bY-3u3CdbEr3=!`6esmKm#jQo)yoH z!S8{|Ghw3c+Z9xzZs4yv^^#`DE{pAoRF+vdFq<=$Gm91g8o~ds=FT&$>22-PAT3Bs zkSe_kg7n@4A{Lr%K{nExigc9#0#c-RR6uEh0&c2+)X=+9MWiGUdZdPq^jV;8b)Wal zoHJi$zHwb7q%E@k>-jzR{YV}`qn=xfI^{|x3Lfii9nTd9BVDMu!c+?hrPIsNR@?TRc=cumh4T(C6&|3Vw#Oj0ta_>! zxJQed3n;z2%hXf4y%%XeNl*4mk3iR#n%f~I%&H(3MU@Jx9~-Y6>D>UubXARK75xHz3RNcT(>5dCGo$E< zO>^1%4?Q>r6ok)6JWh1I9uUmnL!M6@#bBqjU#TxaSF4~7vH1vt+-)OBAq+71>JA@^ zwTrk$E`HEbjUjCjozE7Y_c5yGsLVeKc)-!ix3RS;82X7cV{!g8MQ2{ywydkn0@`>l zqs1GuvwXRIt0x0f$k0tnu3A?3NVQE2E}T>{dxKdZw%X3|O@ZEdm4x;xHXp8++*6;w zw$|22Deh3x`qoi+5#YDTCd|qsUM10wGxKTh!;F`vNn^g0Du1$fsL30;v3k$!7J#Rv zD;-u=`z<6+QNz7YmU3X!2kQs3ytddB1np6kYC14zdG|>iU5Ms+(-PSmdtKtvxJrmL z`V^Y&gML03m`E2!Qt}#gD&2DHV8XazUqf~3ZG}!Yy&oiR zd#&It8uRRBkP!%j1~ zLt-M@B}yhDbxVV9UQ_@_Sq0N9+Y$Ve7#28b{v|1x;iQ74e-|nJ9dcT7F5;9IoWvBU zW+O^+>JZ}~pb&1a>yGe@uCm)o3D)c7wRzE>GjK7I#LUMYbw8BSqy07B_V%^~)CxDq zgY~y19A_x^3!-q#CmeQM+8bO}c01(APhrIR`JLcr@GiOBBlpZLnx{Fq7yTY41m_+6=6<8I~fcI(vb$D1u8>_`!2VL#pVyy7{ zogDXpCP*WLtL2tz{a_ifggKL7BObvha%?l5or7zXvg5=SQxea`Q$yb(o%X_AKHv0+ z>n2~tlDISiZjBf|i?OYT%lAAJq%ulc15?mATX1}t-E~*omo3LWXAd-lGc)Z@p8u!` z*VE4%p(#$950)l^*Bc$~iOs2k&TQ^VA!1n#(fvrJM#(7pa}67;l1k2H;{!x32e}os z8p>eGhxV$SjOvpy55%~F4yXV`^^mz`KLOQzHNP4x+5t4qP(Qbtm$d(kEK0r^%+Ak8 zz;A1zW;3+4Bt%E+ENrt++qytc@CN6TZNJGTb0*avJu4ddOVH!R2HK+UvUDda<0?`n zh5kh5Hf^qSk*Wn7YN1P$yHi1)Xj>10o(elCQ3BEZUxFSA`f$g8nF?6ayX*cll+`0NZS!1U@1Axt9DPC9+o7#mrOdXRLI!ezaDUAGobFq z)FK^H$j=%q7y){iMSE!fs$|Bw*6v7WkHa?KXER=#q4{A|zk<5!%jsPE0p*pTdN;D5Z)@LFO`BS@1 zu}IQ0evjo|%8wvNm`>r|NfSzDG$#;ddn)WIZ(l^tJ*5<3PgSt4B+q61dUzwp`yO4a zFPXTxwwvy)&*@qcB)*=}XGeKIc#C`OQc=h2)em^fQAzjbVi)6ws1wwg!HU8eZ@}4e@hy#8{M8|>PF>w# zP;7jyXz79)PunSr(T3N0{vio&wg*Jg3=W$JdKS{Bf+i_YZIOi=Ix=`SbV6TpnO1Q6 z803Tqa$R{m1V=(3SiCM$nEx_`d>B5`-VZl8gcb3vtIMri>wgjUEdNQFA>Ij{ELH;b zCr-SmshcDIkR1YIQJKe&t;+7JAs_`|@7fhfh0}yN!p(!TUO-|x++9pL_Fbb zP{+#!{|eg6Z$8;Ru#U1#z^v?bwKoV-`zw{j`+CX-(pV6VJso>0U8mUAOqj3hmH-X3WT zdkNq_&N=oc?$!FTG5dcL(@rNTV+kgDE!QSS8waPgkha&8Ih)oRJc|}H?1QFusic=^ z9U;n~`JbcMcbWkJLy%ZR_0w4X*qWL9#-4@4}{8-G)I)w^!4J+jqKSo@NWzbmYqqH zz4ZlKFcoh-t+-DUAIk9Ms28z%Bb5`z8rpQgkg#@epFG?OfK@w)UY{{&NUe>TX2;Rk zrS!KSOvX9AvG>*ooyEOc1hI82W!OH2|PTu zyBF0}|1jd*S!X%p-wBSF?YW;j+gxd)s4P5(sGQM5L-N+g!3~V%TW|xZ>d@Z&KLs~d zzY{qb8d1V=keDmV>i`XWV>G7trH|Kq@_rZ;jpBYez3uO;gOWcFsX+m0hP(ES4CNSr zFYs}URxdQ+7$*!!YOzK=YeNM`o0F;6(YF%QC+(2ECHzs*_0I4I$qG?%fAeHKaD`f9 zZa)Iz1F{Q6;sJ!}qyZ;JuZ%wiqXd^;@$ljtBd(01w3^7$(>@?fVH2ZClDu0w@22m+ z*i2Z6D>GdVB#+ecyNr0iW7-srmYz$TPc4z8`n(`faagARl#b)B`(fXmOaN2$Ha&Ty zr|zN{4kyHKknmH7kh?aW40k8CpF)7`WXKIp&#Rq0eHIQqp;~jIj?7mEaYWp3lMsxO zbZk;vVu}w7ZlV>{E^d4(2zuZ+oVhsx!kOVgZi_3Zhp@V+v*RbGD$-aD zCo`WQWQNOJ1``hpRlO<#li2KKI9#-#>G}mI?hOr*LRq0RNPNOx5@(|Npo2%cjhl2? zh0z_Q4DFVDozc4NrTaAxu8B4X^?5(%TkOcuonkOJ&v7~vYgAW>CvIlT8`xw}r;@Cy>pZi=EB4ib-G*Z` zvA#Un%X~A+%CMu$HsbVI4VPcT8RsyY2Oob8XKb`UIP+2z&&e&Kj9Esi9ffD z!MN1+AqKXl^-KXBNck`n9t zK+aAIf$a+}9W;(H#k2_SZZXhY1wHK3XDaRKFS+9E0yT44>Uf+p*@15;sqW2eZFf{lN zRY%XzAf>YcR08k-h&{o1y(i1g6I1*bWm=Benf`dh9B>1GX}p&LY5sV(bLM*7ADe26 zYoW2DV~Sx}WCnG6cApa=%sB$x`Sh9&q(2djiw2!E z%r8*P#|S`R=yYSBBi){dibfi!T=#XIPLg#q*?RLgZEya?uUW^BbB{^IxGds^=j;pS9jq_~S4rk=xRpe}Xe53AASo62l)X zTD}Krxc*Z=A0JqG&o_$xoj3q==f6W`{z39U1z;0~qgt*x_Rre)Q$1$p4tHK&qUqYu zpTDxU4tIE53Sg2S(FxK4yvgh;Q~Mc-{LgC|KqW!fyp@zG$*#9#nirRxIWzRmsGv&j z$IZ`#9w#kz1nIZticX?@2FKB4Vnrsuf-$cfAQ6z5T@A%G!NUhfY0VfcX4htaz?kCa zn{=G#M6%lnHZ!!ISi!-xVp29dx6uhtQ?Q|dJTRLnd z(v^E1lo@M{w{7=!OW)a)Ixp^hw*PHvN|gY1YcJ5Ji;R{7$^V~IHnEq!P~F77C==L> zkUOf(8oK)A^;jacy|Yp1@I)EKo$Zx4zD%{UgBeG*Jrp^E)Q;q5L9Z{P8BvC%$a}RM zp;z_xvG1Se%)GcG*|CUnn{o|`9O+o7SR<%;dK!KI+Qg~Md41ZRnnZ?S?NBygfI*nt z!=UfVw9(vSuryI{KW%(4F>dLaGYxUgX?EI1g^_$HOSHpDN_RWbKF7L+o``zQslL73 zPeqaLSD%VG7<~Bk{QbVy1MG2biyjTTg`7=6(}LedHlfPTAB=+B{$b$!wzL+Ay|qnzVxHRi=8u|&Pod^)M35k~jLd=AHyXVx6&6NqYC zYPP5U3GNt@D}V40qS8uLO`KVbsu9C^ujVl--AQ)`%#QOZ+*fn6NgS#J#7JU3?pv;F zM_|ZCr50&k6)3dcPU-DOZgdO3UOcKYEs3Hz)sF%QP@kD8z|otQBD^eoQrR^3{5x*Iq@tA_HNX^-oCvA-+sY{fo1S%kWVjKd@5c1ba_+K zbyHXrb3wCy@O~H`QB07~M1w8n6Sb;k!zaTc@A~xVUL5F^7}?u0VtWBpxrtz0)B7EM zaH;tzVuQpr^0}5#k+mZHJZCEvL5Wf03`>Wv+Jz~Pyph85>e;UJ=eF|+$PZY(f}VSB zErlhl_15}`0O8x3LZnf^n5VtmW^6a)a3R6LOEqh7+ASf zKu@R}ad)g!IGBqBn}DZ;LhYpAWA~V(Gc?vl(mh`f+j4RerVywCY0dOke&u!y&g)OD zaC6}VS{u_2wEXO_XQ80uV7gj3WO+UoGqn~SGdaE17!=iUxHl=jGKDzUt01q$Jlqmr z`#rkRsQ4D$G)ty<5wR$TJ9T~X`B0kdI}eJXgA2pO%9S;kF+nh|iMo5=1o@Ch0M71! zT9}T=y;#oP5upd$yqH-Tdt7bp&01Ciq`l@hvFrqX| z>=Mss%U3ca6%3M?>jl>5E-c-@{15ua?$UxS5YLH`&A+n69oTdZZ%n(ePKU%hE7>d% ziaYGR`hpFeQ?96Re@V-6)v)Z3$tA40H-qD~@)^-FHPXU0!`r zR=f7s?fG~_1)f4wWm+QGJU~-!mmm8$ZKSi?x-i(I@?j%O&RuLXD=+(I^goRAZguYP z;&2fi$@t=&B#7yqFLW&ER8zFi8O-=@fcw~ObCb&a>N6f@4qFLUE{8VA$F~&&p zZCNt94{~RzzX3ik9pcEv?@fJ8z)^eDV__Ml6ztA8+r(tU!}LE{wmZV*SviAg5ZZXG z47qlw3b*y$cTDe|StB$ES(L9hMO5UMH2c&P(2Jg7CCr~h1EV(&2Y>mBK|!D3>C^Rs zyygN3nTM;_JF^GXl^crvbdPbM&{9hP@T^L6oD0@Qe2`JQyB8S-@y!k}Am@-v^)~*H ziz#^rN1cQDb%l5o7}gppI6^(ZEMU$P@ryWP4~lRHTSZ04%1g%~drCG%7=n5DE`W|c z2Ca0>qFvJhoY&c6r`?eNAc~%E-M^HaOMfN7TqDb|R&`<+caNt__M!S`WyEsNm1Lzp ziM!~APk9)18ypVpF1hT&6qBW$EcI_iaALuZU~b;g=%t1YP~y!1OyojE=Iyo5tJNJb z8CrUJdg};ODNcldnDXhQacv44LYrY75PH;Qc5@cC^3~5wk@trBzRTY<-W|)|Iu54| zZp(k^ud4kI5g)YcI^z!2fbC||w%(R|?R|*KB;OS}N9z2T`%z^Ye!DW$Lsb6Y)LKcz z@&PDkG@?Z>{NE5h^hbmbd*bHPm61*(n;D(r*GmeQ*+=*1c>iA}JU6QJhz-CLMOp#} zj4!jHDJv)8C=rBEY6>4nEY9vJaERC>6Vv&K$1P2@$7OwUym6%+^E-`h$NUc7cgfok zzjM@Rk%#LVX;!|ou$4zu`{W_jvEnVMPGwR&g_4e3@|j`d0NCWyfz9n|8I{s*SCY)e z1^D~}oTAymNP~9lI0(}unjZwElt8${oCrR`RptH2eBLBcd?t}zlh!bh2X({ zCwSicAb4(8B^KL!sFUg4LDb__S!OxRG&G0JERArI>LFHF<(w75AOAN5kHB|=r+o!) zp}@XMyH{1Xf`(mL*_7PxnBZ9sXJ_{RmEbw}PViJ56Fe;c8NtI85)576wQP+HtCw(E z7Mbn7mf01oAdS0No0*CZ4tM*_;?`awjBRsmUllRb?n=Aw z;!QE@IgXXEPmcae=CzpWHTrX*w;pXVEqm5W${@~UH97lvD}VT=SmJ{t5$omZkiY=* z5@rVzg@^(K$z#iC%M)+wfHzA)(X)B#z(8wlZz*T+;{}v!M}*wIIwDO;N4rK$TY^tL zw+z4dpyP=}&yyfXOtoFXUZ-GQax%qxQs0%f;jsj$1n00}dU(z~D;IHG(J&pvmxA%2`$lv91at0-K7B!pR6&`ELm zYNDKLK7wDyRUVP22JzUMbUZS1PVh9y4zIxx(RK%|IZ$R>ZHPK#Udtj;m{UE_cBDKr zm|@KA=JI<|Rk2on(m;<_C$X~l8!1wDCLL18Ixb5b&u}N%*2+mPf3>+Am2W zT128*{zi#YE-K{A328tjT7p@jA3vYGXo(d^B+k;BzkyJ#L}bSl_l6GP%Ld; z4X9&KlQ9?ZST>6!*N}EV3(hZdtK2ZRi5rrz=@+qR2<%gPWOuoXe1|~XpU&3D?AcQ& zt?jOuuC4B3Sy!co_+VMNWodQz(CS=}cM23}0zs#9mwY%#3T1$%EloAU23WZ+4JM9& z;QOf1kE&saM&p9X6{w)ZbvW;LO`d^YH$79aMz>SCyEaeGz3}cv-fJwt@UA{|p4_M^ z+q70N`R4}u2!QyDR3=L_#{?wz0JgbNzJ{qvyZOBuL;W2jzf z5IvFrjC7rDM>uNAXe8TAY!3WXwD~JuV4{Qv6So#uusCgC&8yt!BeR#y-}D#CFcVOP zeq>fAHw&gbt<>Via#5x>mv!DFA`6mEv3*+RLe_59wE(kHj1X_kT4Sgr1CpD~{&Q&# zLRN%HM;X6%(k~v;3xercrh-$ot|tmS;*WHGT_C=haz*<34XkvfRGC$7Fmg6fE#A~6 zojA`Jt&<{VOx#Vr=aYL~S&po|?s1|>mi!qByI$Vs{-7*RD;#ZIn^?0?5_0(rruFrw ziP6zO@j=ymQ!lBzXl8L#hudA2Nn^gP6>3?&aO?2hBcWrjC0|>I0do5CGr=wLX0yP7 z5YOnadcT(w0n&FxCTE(Pf@8v%O6fllxh)osTPKOjU)UY%#qXMLe7ADvve>|Gp5?QF zeW_3Y+*s|Hb7F5_eC43JWrkd%V6=$ z60wytAkLkQY4xmmIWc>UP$#nN6;`gI40m%@*^Un{8|nddjcY zEUiK>!=R%GWn4X}XsI6DM&W0sqDhpFKcS-9`j#{ds-tZxW^kyZMM~l9A5XY}@K_nn zu@-=PdPT=op4#CZR(w}KgOvj2T$)_PjhOtTur=7gUwB|faJHT?z z2gq(+bz(0FZsv!Nz43Dkxu)50Yi8rGb;f+@0^F9%lkaTf=^oN_|ZuKH7&qw9b-8u9s75j zmDKj;KEvt5V-I{Pf>DbTQY&}Z-z!BT6$ z{N`0$bP4hEyMc9s+nmFGtc;Sw*Dg%8BkJ&RSp4}k4jj>b(EKIOkAYKkg?>-H&fBK? zCQ?^6*sj{LqsP495Ioe8iLJE`72th~;&$!i2@N?vLJm*^hTK91KAj3H2upJ<+ISFl zVj3LgjvGqf?w zAlh8nDUJBNLcqlc;{;48m@ldB!Y?Ai zZR61#dcAkhy1)rm>ni85P@bq{`RrlpQ0Ci7zC`oJ;)!!4gpe0^W4_vB&H5)K+opwJ zUOSXe>Sut3!b(5vl^fzA6!pP7cyi|cBXaI27G;j~MsOk09EWF4&y{_lyXN9MgTI`D zEXTU8_;6?peI6L{!6SgtTX`-8MKMS4Hinf&dcDI9UjICPyZ(N&ieT7(mG(4O`PIB% zDJOwRix5&xGjCR#CVy4@wsOflz{QV&?(xMB`1<;`ZtMCYY7%?%e7kAspW^bGd;9oNYf+$8D8q@ZuJECy4ZVtdRu}XUDG7al2W=tCd=w zS2o*G!U#3uR^ECZg{oL#3(X~_jgAeS;pZfF51ykBjdCu9K}*fb%?k%X?BlEkR~?mm z#Qq2$h^5UExb)3Bjzwz**QxCy-?kaSK)Vi{UE~J7<#*3oQ*`t0BLk%a(1V_7duZP4 z1e11v;f?$DoSf4*AX8vZxb5b$&~!WTb*rbpRj?MPMnxw*{$BZNCh_V`T`CvaCQq3_ zy#N*Dcz*&!`lbP4Jea>u1PVij>g@SE0}0V2;n&Nbzu*JrcHe-oc_{}Nj^r#{#EktS z=dShPx)2#Ftc0gPetKupeO%(zeq>loml4+&Bjzga;s?&I?5|?eTmd!XfZ>;*cwQDS zRn+36E2Gil3>EkiRKmm|3XZk0y1WIGD~UCoMpC!z@@-9cG$+odtGJNepf@94=x9=S zICOy_TO1jC_Cxu8NwN|C-Zj24ta{yS!<{z+5ce|`BeK3>IyrxFW zBbq^J(S{Py4YQVh8=&dw3W(@f7bDO-0S}M|&IysPE!HVk9#+Av%Ur5PJ#wQS4U(#D z9HzvgJBa5`K;vsBn+H$ks~f`cKTf26rpj(tf$1`ZfWdv8-$lSlNA^5q$x>bZvys1C z%;tH-*hU39>tQ_ilOwg7TT8KGS-rdRdtvD zTmKcXX)PU>(gUb$`cOxp4uOr+{|xH9`32O0z=nxI@qc`>sr?$Li49DP_66k#uY3Z2 z4~c>Nr{w(EcQ*9?;(fCaG>oO?sjf%S7f8F@31^&7#t6gK4fWi0f0Xb8;&?8{Uk;bZ ze~pw1ADlrHRON>La#ydRy!Z;!2Kp{4`J^gw=ggm>#w#X3dZeUuOSK3ThpSSKt#8F-Vwx_o|iLx_FV_0LGbN?D;Q$iLSfo*2>k5fS!N2 z*h>C*2-67$0)>vE>9ZZrgpB@vfWLnbc$FmY*0tx8!16xF9#4z-Xe!Ue^V;h9a5KOE E1r+N0pa1{> literal 0 HcmV?d00001 diff --git a/doc/ci/quick_start/img/new_commit.png b/doc/ci/quick_start/img/new_commit.png new file mode 100644 index 0000000000000000000000000000000000000000..3d3c9d5c0bd078333a7bc1e670b9a7dc736a2fcc GIT binary patch literal 9033 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 A-T(jq literal 0 HcmV?d00001 diff --git a/doc/ci/quick_start/img/runners_activated.png b/doc/ci/quick_start/img/runners_activated.png new file mode 100644 index 0000000000000000000000000000000000000000..eafcfd6ecd5daa3ebdea96496b2126f756ace99e GIT binary patch literal 27597 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 Ot1Ig$RVrA#`hNgeb)0Ab literal 0 HcmV?d00001 diff --git a/doc/ci/quick_start/img/status_pending.png b/doc/ci/quick_start/img/status_pending.png new file mode 100644 index 0000000000000000000000000000000000000000..a049ec2a5ba560c222078da1c45b3e358ce15dd3 GIT binary patch literal 19782 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

&I#>0_{^-L0SDa6;E-#{Wt}}|6@wPdcqQ{^ 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 Z1Sz8|r}y)&xA_A6i3v#yR`Bco`G1c#sD1zd diff --git a/doc/ci/quick_start/runners_activated.png b/doc/ci/quick_start/runners_activated.png deleted file mode 100644 index c934bd12f41dc17d10eb131b233f630b18fc1761..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60769 zcmeFZWl&t(7C#t*ySux)I|Oaq-Q6L$ySuy7xNC6tpp6qC!5xBIfZ^Wz?)$&0`8rcI zAEv9is?XZX&*|Okx7MzXQc{pYgu{dT^yw2KKw4bo(%Vqm}2JB;3=7#KVA!Et-fzqT=iMb8kBtPcR^qtGB#h?z`@C( z6Z3Laa&zI$4nM8&O+ZReirgcR=zi-4ei{}6GmF6hBZM*g3D&qkdWKBmj+Qw+{84om4@fD7?=70ukg3R z7K&DBsR4FoZAGbp@&36_KqL%HloDa+AbCp+{sffohU5K4l~euw8zCsN*`xgpe#qb< z!?dB9lLAms{lH=*g+WI@UXHpY`wg{H{*eWzfeGh_o2VP zzxN!yzxTxi-GlF*i6DKV@UZ?BYm0{baUb%m)wEo-CKJL?} zPXeBNA0O?_U5!aR?d=>~_&f#4{^sEO`1}`{nT+Ib7FSzAGA(%}5-~?-a}rJ_4ki{d zAvh8e5&>s33qBQb$^VFdTnUm{xw<;>F*AF3crbaeGdVh2GPCmX@-nlqF|)BTesD0l zcsaNldont>kpH9PUp?aHE~d`bPOjFD4kUl+H8yc{a}^{b`^(UOU;p@N?rHshEIGLR zC#;VEng3d0W@Tbw{;%#2QGvgxd`i}y=5|`**7oKOE+008ICyvk{^tL`t^6O0|0AjW zKay-5|10@FEB}!cVE!wB{|V@yZ2e9BNS6?t0P}xSF9c`SB0llylgKB4xTu;Z*jW#< zQtC?2`+Kk30K-?0?9Dxs(9t{m$S~deGCN%kmY-kh0!*j|3`uWP$z8zn;Bk9UtKAoE zya#mUDbR1BY8CbriU?z`35zhy3cTMV z!!y9ZJ@T@5&Gxwn9p^}h_NpKE~S)&ovW|56%~5BUDWDrc09W<)6{4Z`^KL=&MjCVE`0(H!PD4*!9 z>%c#J{(HTQ_QTDE79$?*e<@l37s9_|`dDX?hiypCFM}MKF!?LWza(U`PyZ7$OOUlp zVA?GQBaQ;rKUrV_+f*aPIXe|2esv%vfNBN{?{F!nqf7t(pP-C1&@#;^HzSa%;)@=a z(A&`>zuOJT>KYDqrom@EXjSx?r#U2t{#S>+@;lyzp-BFWwNik4l4Gz-$_6d>@$=^)|_ZoSQfu=fQK9wA)RSIhs?;Zo6E+R!*{OJNy{y1K`%^u_HJ zpXc;;Ng?)5mYZUtb^sXe1L;=9m`Y#ODb@MIkG_qQAzSb8=AzW)wQUBrB``8_#_Yl@!<>&YAUk2(%d?vAUd1jAe;)QDZBS`L>Dq_Oc)vQu=)e1j*%p}(#?>TQG1vy z67-wXM4S+xHH+?V#2myJ>_>V(QdJi}&21-+-DC=Cf`bU`q5ENO>E-dBz~1VNUsiA6 z8!MrrI-!juq@-Z!fu2x+`&Ne}J|m(hRH(D+&CSQ(p*4jgUhKF-^_`B}%iR&iUQSHU zb)BTpuwz5%kV6bmMWc*n&>ntHU0wUKGP#;Lr^=U3yLd#SooIz{)E|2dhU-dS74@bc&j($eTUZr1fz^vR zhAFrDJXrqZV8B^vDQ8Lk5fXa*ma?O(VsRBqpvm`>IZLO zgE58ahUl|kd&{lfUDVEX5;SM4EARRUaAr%tu{FN+V@@o{nvrT@`$J8fB0oZ_#7{A& zZR_2edfJ+^AxZB{o3Zj7nzG^;Zitc>rG#W`fj|wvOIMOs{9w8i$E_j8Wv={5;R@6; zv%eKzY}~wU_-0kFOyDI0mQeuFPq-M}b8&*uLImldVW$RTx<3{xqec6=9T>GDzr+s1G@Fq~7 zW$w??pEaI^*@v54xKa(%vV%b*EcknWkW>Afa+7--g0ftL?A2=3HxCJ|Jgw&D-B-i-o3ZNPkJ zI6V-fp3zNhg`p>5eWN-DX1wSLm8Rr!I7!a&6^Dr`_Yex<3M0UTUGZ9^Bp}8cw8Jhe z_|~pYJJcp*-R`VK!>29^U%-8QIJC&NLXB7j{I$}W>)uyOYo&}NB>i=N82Rg}DE%7d z;k50y4_|;yH^`yb$S-ueqPaiP4$2FsF-Gx$`1J<@VO6qzHXK57gpWlD!B|8NTb+%O0zse|N6wi&DSC9q&GFZ-c~mB zuIQi1Q;k~|E3;h>{oP1or+CVD2RRkbkEXfnhvX0E#5)`65`OobrVAI}(wrsCagc$1(ztl<&ED~m)BfXa;}=eKX?>!EDzjy`d!5h==E`7%zDfO zx%pPh^Y^4luI}h9-NdxI1o5Y!dKAk2+{M&29IMR6%jJ73dyibIR`l!fd64R4lI(L! zrKXE;Azm^5$!>u8JW=Z4=-Jm3wo09;p}eNdOYrj{*1h!woLk;*yso|ju4|Sanq!dB z=NsxF%~VGMzOu$I#G8|6Q=B3ktN3l)ZUc8XPR{b*2hq^mZzAUvksKV8`#Nq&ah#M} z&OOebh%4@-WN|P5`Tb!I0;qucgQ?rL^;KMDd+a;7S8fGBPw3EA5Vr)N-aE3Hj-`Y3 zQ;98I>1Y@HEQ+2I_3xARo-TPFa(-ujsFO7xptmd=SJDW^nzOAjJXyB22?F%hFE$^a z>NhbgP>53t5=)BSGbRnj(1mWQk(msl^iR8^JUkw({X@>D^60~tqE#j5PPTua?~M}D zyl1UgZ?E4}auoD_N*`${7MdG^h<_j?yJ?{s4_rJGkdNL)HVCWE1Lj%Y6AsEak}#BY znB<&n!^yizk0>z2S1v$Wq!KWT2XkDK3d~3hHivoYpQ7Z7^vqi6U{Wp%E+%49at;JT z!ZV~gqGNV?-@(;&)LRn%^evanQ!9kX3<)>MtjANTz! z>Z1~`pR#=#5hffJooV}Dphh{#<2S+Y3k(yNow95mZ^ z0_Nf7q0d=YnYd1o!6l#++2M>4)1xjB!Wia&;@8FPt8@aT{r2d?%H8eL<+Sc!d1OgU zQzJuLkxrRJ&;oL8sim_uA}65IhWTKTA3Ob%2lPn~S%1|T3n~3TI&03DaA@p)$>^c< zPP89z$CM;3$%we4SGFK94 zVL6LCWy0y0pT&)7SfLvDDHkw12k~6{1j7Lp&FZ?CHXIi14HSGc1ZK zu~o`mt8OwQ-Nw|2o>N~`Fn)vfMTxN+bB`e(Q zpU~s;-#``zvM%GeB{Ps1H`f@j;`&ZG{&q2WgE2G2kS!T>(o=3%0wkaw&^! zHXJghk?jQ~OOf07wc5GltfDVeR0ZVXSLl0zRogLg7~6@@L`wz`^+hT`ZT8jg=8-@E z2J_=(Xk)$56H0_TZVU`546Fg-e>WPuhygBA#n2uZ*D>}`KKHjY6!h%7u@KU*;1)l}!XiAgZ7IL7FGO~OB(0&Nh` z{dawvDFi_!3Q)~aoCQ{uP(m}(c`u{sePw9SqB(3z#)>AJ(=R$S5dLX_&&5X2eINC} zdj>rO*q$jp%$AU4Oyx_w0&&$KpzV{yt%s(_uV`L1xQYj8&I}1=9^Y7{`VRP6VCVDu z!X8}YjPv`$WyOS8BdL$`w7DEV87{q;jn(ccW7a!xf?pqo49P8oY&x7@Q7*j`{y>Wv zqhX7{*jDLovDXbe)=`MkbFVTNW0HD`PG^5odL|w|)I5GYZXtGPFfyldgJW;Lg40&4 z>wFJHufG_CT|0d$bhNKal2Nw7fuHeyMgcz#OcC9l0siO=>Aa)_P``a z!gp1I-t**BI5fn8*x!%YE#=2!mR&PJf8AZ}X&rk%bZcgZmZ0bNON70rANaPRyV`P1 zOOP0$h!%I4#w`w6%qvPYvBQ4r%gOlXIae;jF^SeMf$b6N@_tgGRaz8_VLH63tV?lk zcVx%K$?!E-C;{L|%&!@L_q2s1nvZ5-y_L{%B(!lu09P%fv|}xK6>~iIh2hV9Lzt>g zKkUWETKn|lsHx4D`d=f&>AN8HtK+%q+q9-H-n=nTYIm+u-(;KNTOM1k%iO?s?2Qkj zxk=y89rmBurS%0gZ}@j+^w@H2v1d(HjWM$~HEH__hWw(0&YUy(45PbD(|tL=Y_a`? zf*eBnftg*#h2KQdUSX_x>umr}i9{X6Ql%lCn2@4!69%W83TIwP{zD;5jGhZ!&pvgK z_1ztq*36R$H#`bwqb{O5=wEB~NVsoza1Xh^<(DfePWFU-JH|cv)&tNWi!azedCT21e}bSz?g~uyYf_pk(-p(F7ouyrag^kN!g_x6SrIORY zrYXydUasdx5XcX-P5yHwW1wyNU4rFA!W#fstK{w>pM|`^0B4!LsrDyQ^N?J9)_bTs zx(BGv8NIDYnH%d${oHl{wjyrPMl|lQ&h7eKrpNux6)Lqn?)<#S(Yy0roKbkZm+}`- z2|5-ta^Bh`%q$RnBFFGEYwDGt>lbkWS~O<~>Eeo)%<-3S&-0fEW3Y`+ZD^$dN;*Zo zm$NOx9YK$@zC=U@zkmIHIt}E3o@iN(l8@E`7RG4FG1?po*9-EgXdx0lP6d#{Lp zbJ(LmA|T*92;)g1XzWUm_%C_!ue7xKYV-Z4$q@vL{z3TvIsPBc$DBOR9wFT7PiHj# zcrFz?sy(dpAkIPIo%9q)p7m95F%>3*iKb`6ZZWAIeZr#)=-ByrmWa(FX|d?hkh*v# zPn7WSBk5;L?mSpeJ?h5R(34J5Sc!Tw(!#2r?x1oA{lmAFqCG1_ zKIm|1X$Y0+vBJ!C$%s( zDwMkB1#TZp$y;;MT7A`Vn1p)gOG6Noqwz8QoFZ)mMRN?8I!}#c`%+Im;3pE=!cLha zCubE(L}m?M$k7y>k2A!NLpPWm0uJ32*w8@R;4Qc7jYno`J0mpisg|Qet#jN9zI1)} zVlaeO8t~_FS9OGCIJAkIiX{rdB0X8-Ql9vesKUHDa;{sN=V35C@H%OS9YqYKgQg#u(ukz3~0Ak%9yNh|1DP%V2+NG75yj9`i)9D zAyGA6qx9yYhGEpd2R7@+H3~gt4ZNE<_1B`MI3c#NV^?qSF-lT$dUO@GJ*$X!A3h~b z?GSi{41)O703apmvF$RM0iYUY@w`S%VoAH*2Z}}9E4FDhF+U~D)22pX5JAfytS9-F zNbTY$atSLeK37>`#>NnxLB$!}l&_n;XKh7PWcC13p=Nxngt_7_JVT><{JSt#ry~i0G+} zu%lJ;X9bMU=%0?+FaGgRdXqi>oyjo1){T{<0zp_oQzs(jh?Cqzdl|Eb(2^?@JXyvh zUTUG-G4@<4P2jqiR@9PTr@AJA#8K2c!B`4#jFd#%r*;9fV2qNFXd|oIaDmA4hWm&F z!6nVJEo%4x=F9VeZe>+9X!pxVFyHI*Pvq1#oNK0KO1cx& z6*+0IXEN^`yWPZkk!SceQ@QBm#W3u?vnOHpckY^C(#@{VlP*~bA|xqmz1`{nwbMYh z72+ddNIN-E1hNr|ulK*sl3uNV&#%nK#x%%-P7G^c5J!pE?R^CLW&5j{*5VQXNF7>z z06rJErQ*Q8@+CSX?xy32+LjGJYS~g41Mq~9roK&8zpz{NB{4NWu9epLg>0!7UQl{k z8@#6kZYj=wv9j!%eS}1iU(>pNkLM^{N?QUm*P)X-+?7RX(;z=h?4eOKaC0sMbmvu?M<5=37as16)zz9ThslBJjRFN7>5=dXivs zZy~nfLc!I&t!RF&DAZ2MR24t(RP+Xt-zr+$dFI*M_5QYS1?RZFu(TTdi0r*s8N;Da zYWytJtd^owv)h`v3Q#tuTt8aQu**rAg1q8%uyIqOqV3z{HqEQC8PvI* z{qX$YXP&fBx5b{IFKl}tNJn<`W5w#lthA&B&8@*ckTLU^#`Li zi^;)A>=FY&;z5xD{JXIjC0`w?ZB#jcg6gy~22pJqp80_8pV7LMy%^9E)nsL@D*d;{ zYueIpeULBTu!?%MX+*1RsmL)ciPy8M8a-Z66W574@{ztf!Q46Oxs?z)+9h3rCvk;{ zCKUB5tX9i5oUTeR-ltc+((oBDyYT>C`Y{efi8l+DN`1Zp6`1;oG~v_qsn;t)jt%=N z{b}xeXkdnv%xqzmJ;aHQw=V4JzK9xE0t-hdXR*2GzPL$uDPp|mgDKaK3+tm#2Weo_ z6hOyw7i(HVnCE2&5^-n{iG-;h3wfw)7JIAdtAy?X3oCz{ooXuLw`%&dzUb5ZVoZ&v zs$7sE#HkAK+bi!h1c6sD3r9b*vUnIWh}G(DPYHC0AsB0cm82PL9K06?>1!b@yU9A@vHk_?c{}RSkC(LV*?Ui7K}C@ zgJPU!z4tfct5vUxNDL6tDjjBym{Asab-R7*!R;0 zGu>>>^v;!^qLZowM~!8_If0oY{?PH~bdoNH%(=k!8dfHP$};?HP+E2ube6_^N}2Le z(r2}l*ZQVg4i)#hks|P`)z;QjhASw%>7HVS&Qt90u798(KXy(mdB?rSb)V zg!TJDGElEGaA$?etj`rGl6e^T1f+WboareuwHFXNgy&j>Juv4;19I+uwF)PZBjm*~ zX3=Dl2r9dn)xkSbn@8h+YC88ezSOkJQ2eS{O;F*dU0RoE5$Hk3N~3o(Gm`Fy!W$S% z9z1g+5VMAH0|CR!$AOz~bJxceDEp!_iIEwG6G^pDi-3*3R){>Y+6w0y+{XN>Cs13_ zVjqvAK5n%G&v%)5Nnf{gwX?N!06MdpDqtG}L%pQ_iN|f#PRqV5$)YC}oT4rOmsfTV zZkJCUe#B-1sIMP#(GsWhU9=%864{{dMVGFnMjF9~Ih;b5Ntv-CRkULJE*(_j7XB$1Qd@&_8#RdH!#T%d!!sNfGTKC$2+t`~VpwvSZXMW_f6 zTGCWNd7q{E%x*;?f3T6sGd%M2UVLjao!a5i+EGfVuNPicI1)w4yVfABxjr`sN|2xh zTu+Oa@UtSFSlN^YuvJS&CFvq(rCKfQlc|d5@D9bm85iBxRHt!y<#2l?kY0*a#yxSGRJyCA--V;c-18X_6*=_{MvDPgzcl zRc6rArRUV@F_290v-_yUR?w*x76(gloZ5AqguQt=64!owGBWAQ1IJoxQf&c`3tZ_P z%5?pOSaA_Pq1jctmS)&9mx{rjx6gj9VP;^+a18@MG-d(yYt*9Lq{1Hc;vZdA>72w< zJDcP-1-#M}s*nj0%4IP^R=yJ(>tsA(!K@}JT9a#94Eeuu(3l3oA;%PoL#SlE}Y~O4k);5@R`|gRvqStGUSv zKm}c-`W@86+5y}euf2q8HgW)b_c;tiZ4g!Q`7K~P8KWi9B9u{~Zo*)nVa!BYkDlJ@ zD-LQ1&pZMwwYp~$&SYSs^!CW>p0jebc_YZ%eS5C z{P`e`48_3rw0^qQL*oIM`43~&^JGUF2iy&C@HQPI-hbg*LH&U*M<2r3> zXGkYYYtKhG)&-*fyfN?a=M3_i`Hv&eAy@`{{vJK-#uN&ae{ zH6{53v6P=gH#d^vXmw-zRwO2PtxnPVBBC4l#7#{#pafWe5>zAVS=>gGAZX6z=+o=Upm67aB7-P!VR_U=+3rEio z%&pe+hVcP2Ke?)(B!xlAQ>hwCo)yYwqJzULGlbFDy{--r?YWu26&GP##!WO+u_7>vgW@p2xe!%YxGuvHVQnb_nt62Ur6616M95(U>DPj9&;Vk%Zzb}=ZB-rXg zDsW`2o}k@^D@-+hE(F1=V_Shl5QKIrx627tKq?(EDQ2bsqJc%mx+(|h&qYL0j9*d0 zXh>iv=)TOuE^c_90I{UkVQC92^2{t8iB3e}ry;fcuIINaLN=GcWhd!Yi~Y>2VebSF zH;Jp?deTdu2}>Nr#RtATfK5Bied!^TE(h1yky>YGkA|>M zG=pejDTeMQ*kO0fj^Z`(7yMPGd{5!!GriE>P3!%ok+;MwAulhQU&xHRW|vkwXm;^=MmUY5;5k`d0UR|P!MVK zz=st#E{BsOu}Xa&(8kbeW2yOV(mftvHwsgj- zmno#$(TW78VX$S{5XTHkQi)>^0`Ei?JF1l?9lONt6rrD~IPv;!)I^ncwF zN+{@7It5O)tT3xPY*P9~ld zXe4vEaY$}T>!vW3+84H>>B12-%>VI>Xa;zJ!3tVX)Y9q6?`tdGdBLbW3p<+Lb=-NXqD(2k9Tl#g-G*iCxV3_-)?j z>#?h|#x#U42Vp1+I@E2%=*L5NPdURVbe4tOA8C=OxdoEZ!Fz1iNP zZnlc4Ab>?mv)19#DsUkCqYWAtmh4>2%C?POMq`haIA_GhZ6Yfvy$)D_;ig!=aWrB% zFQaY_{JFMH5f%qf!?v_0!Ni54C`OR97(We|&gfUOp@GsXs?m1bU2E_!RXmqNI5h*64hKfuE zUIn;xguW+HEx5|ss=vz=lwvoS^ zwxo7r`N*;q+0voFodgt}W-DIkeDj0Kmqqj)kt^VHDLd&z`X0o~O&VjJl+pRYU7{m# zqs6cS+TIpRdRrKjfd{@VPlqAASb(wFRtrJp0TqNlgYCkda~WS7Q2Cf%c0! ziW*4hMFe{`uVWBgq1e>p1YR&RnHUKKq3yZiQDzntXTejh38#@^k<#1VE*z}ofZW-} z2%)=0VdcpVFl0&a)RMMp1qe41)Ko1W`w9AX-g|05^ot64w zv8i&kGLzn9gKT3WjS6SB;3Y`M&pkfm%YCrRh`jbKkvaLs#HcyRimaTd&Vn~oUbj7f z^iBCw+2JoJ#-qfRj5vaMB?fneITu5uO`LM;f*dx!zF*m3LL(v+wWiK4T;_Kvl5V?H znKFYv@P85-#wp+E=@&R`EKwJb|FqYfRd6X|FkVKZSTc|GfB_DtWRmD%VTdG+0u(?O zq7jC61~m*y4+c#tFkymUO@lUkQ=tcs)Xq@~o&fP8X#vkfNQ`#D$ctdV| z2&-lWLiR`KOxQS!+S-9}^{W`77ysK}MG3JN|7V^v1ag+Hv|9xFSnD*sCb)5^;|bqf zTb+HDy#IVZ8G8yPGN9ag!a@FDWDUoUYfV zN$6ejLf?brgV*ATZa-#zMMvz;BmGKmbU_)eN{dg-OYYu!G7Qn&Ab2{vm@R9?i)_Im|ErJ+o;1`CAFla_-~;_GUZqpFu=FgayUNXo9_Im1q7RiW4)6 z5v3nH!xI~2NS z3B$dA!U+%B^5m9a_RbkZm{OYuZ+}`dbc*RM#&Y;Wcd%LS+iF{8VTlENA<_W7R;;$- zkFQ76^e3Feml%CO*oNH-!igsdEqs1hc|ZVku043eoCi?snJS_@tXIPgBYnefyz#`z zc?F4MYpj~^t23X2@WH4fK2AQOx4_m$<@zhe#%Z{H!d|!j=dE6*T zo=%U}=Q)WbejA}u-^0<((ua4BIilAsDqiUA=g?~>r315daWUeY{W$R>5JH}R{AJ|r zwZTK>d$jl&e=2yw_b4Vmgq@{9Jk~SUuDPHpZW-lzUtxWDeGI>3R&Hkbr!xy-1(i)Z z&`H^e?R6U?b)^Hhe78eHYO>PBortj7yT|;>v58B}kw5ZX87w8IVexs-LqpFK^Kbu! z#KGw(k@6I33b&=KolvpM-6DmuD|vFT-u$`dZUkDC2cwxO)V`Ecv{&Iwb~ z)B7oVnJ|*^RfIxGeTeA!H{;nb(vySBE@>>y4o%1630D*If^ddDWmm~6>8;d_RFxxR zo!B=6Fn*B1&_im^LuUa%Xc zZ93E2IvKVs%$wi<~*79jMMpy+F=WE;^p+aD;^NIWGasE#q^P|nOc)z$O) zZHO`B{h1v%h1`&+sZ>d9uNawqi>{ug_-=|DLszuN(lHN+nNYfFtkG4QR(8i@#XlP2 zWAUCix@iJ()&hYX^d_aZ^J5|vnYU^d>=Ug8bt3eb4tk?Vc5*Qq$wX00URRM!Kf+hfdNZ^1zmH7|BQ!<Po)J@9C3cR74b(Kg6B93H?Ifo3B~3MuxiaI?O)8l>rbzX35a(v*OIRFu zwpVTSCxvs-MuQl2QSwq_>}_|qkDZH)cPO$q{6L&}LU6RU&WYCeKRwKS2(d|kW3?0a zbXI`k#~5*M@6Q{S&@3c=i?FYWTh z1*>qUTWUFNdoofG^P#J_Tqn_DQ;n>|bT+A|aVvN4iECThPlYii?*JmlT+rwz2Xxn&7l5SqbbA4|Z>^f2%OK)}rv}2p72%R77!#7rrC6?ZL zoW?9nbq{dd9EN@42ER;9j^{At)?NbhA@}uF=L~+f-O6#aGb>5WTYB=(MK73hR@fIi z?fHIJAb99JQPR;sd}^B~W#WYI$l|J9cAalg)Rti6qdZgNp5RMK`Lb4X2 zih0DL(`av*zE|E=inOoh;Lzc$`e))}d<0+F8K?YSGXpAo=)}ugg|bIx8_|bAh~!gM z4WY7*7TaTl#%Hh9anjVsovb?UMYj~sn_lNJ@tJqN;`4fjLlQbwpUWY~jOz6p_!f3@V`HlPIwzmH%tgP56xP_${h z0gh>H!zi378j8LAmt@Z5`*r2+Zy56WN#j}taT|BI97q@9eoy#L&n=oNg{*HI3fNDD zsG7y=&o9uC3g3rp>y=9wX;G2+D&0gQZm0c7pYYAr+J!yC^J_YQOmNwWV zu1Q-5Cbndn{n|U4I;UrGfxyudNt_8qhYN3tv2lU>0xWC7kxC2CrI>Pf^(A*c&=4Lu z8;eMsBe9-e(@sjyJg>?{&*Y-Gp$G9s+){;`Zi6I{nHNg1wv~pLcI^D>w#cy%aS2#h zqPjw&DF=V#qolZi%82&juZDR>1-ThCY;N1&FHcA2qpRHO!JG?n9YN`QSywU;q0-|< zNlAn#>Ut%h?S7?9Tl9)f!nk}!I1%s6adLIUtqgGf7!YF+Q9=ra0uiFg$SVB5t=)ag z9ll7mam7Jzw0QMqkc}0$_2Y$0?OZvn={Lx}KVGCZl6PlXW^OL7?!fZ#lRME->0&Zj zxln0A6es03)R-gl-Bv#NgdkzMmVGxa9aqx15DBiE5Evb{adbDU>(KkqiB;0Vo=mJ9 zrej;Z%~m$&mnQ!Zn}4klox)V9QXICPiKa3)I&7|`crIaL#@veSqr9DJlNvw)r1}v` zmTM~cM+__jIK=xn7agNdVcK_!b`y=InM9$S8-;OTUCyn(`=qOGX zvfb}7@5sVsUT0^Hqs6Wg3~d4&(CUlgXK6Nq)^d7|h!9_0LQn0r}wy~-sgIE_y z*D#;q3-P`Xrc7TEld_}k*RDWZgsP4mTZNm0hMSS57+1ugi>4UO%PtEY(Svza-PEu? zJ5?hCx8eQkqF7Rx2|TA6v=_6C(@w}gNB50VC$M7C7q2G@2CO*cd3D&D zUpsnQ+c6EJjVi`n;;gu@^97L?YBt(frl-}O#-mJpH^~HEL|s{J19D{Yb?5Ni$H5;m z54)OC1v|PTHqs{|55yCnz{OhVq)G}`Ks4qHciJzrIQV6`4$o)b-QUq^52@Z(06DR2 zd6tF&EW$7lpE7x1T{c}6zPDNTpKOgcSrrrOMv}NK`jf;q)mnB1JVshKDu33_Gj|=W zRybQt*;bf|uY3fKZ6!H-IhEw|RN7n>jUMeVorwAh(3{9qKv;ND7&ir{yXlNEH)mHY z1N_$9%l-f~nq-U&E7)$dTP>MhX3f5)n_qSkW zKPqx{gMsZSEs-s#nB_kjZ>)KB252+kz3ZVp5l+SyXgBY}L+!egEmOX%)_C)96PC7x z*&xLIqQ~b)P3y$uPm}2|1K`QMa2MV0@oSmthW5ZPh)!HVfzqYgO+XgcLDM{6#cB8l$RL)+j&87E1b~RsV05my=DeW4@Uk) z-y>`BGj@XC($k8WuDep&wLs%Dnzcq)z8=`dWpSWTo-AU6FaLw=q&bXO@s8z6v_K41kqB7LXK`BQLGLZOWXz|MYYHdd|dJ;&Qz0k&! zMjnGIGfNv4vjJ92W{ZfztwTvu!X@qkseL0a8R0$kv~mdT6rBs9I$r@eZ$s}L38w8D z!l(L$O@;jK+A78O){Sevq5-;gP)9_Dnt~crJ-Nw5D^y8#lDj2{PsQRqR8Oes+KpGI z^d|oLGY=;*kxJEGMag~iEhy82wr#;p?uhx^^MxYP&Ck-=9B3V(Rhar=Rip4-n)U*`mXAj z3r6&*;_G+~cVI=X-=37Cl&EM5RsRBc8bT-Erd8=_IFQnRA1y06LX5WQ0ju$|X(6gl z%-(J$kV67@p-~E{UQzBUzhnXRN|9W71;#QV($|jr%m5jUB9nNMZ%1XPyEn~8HTS5z z3A1C7f86F*ZE9lk79?4u)i!JYX8Sy2PIKvvai(QAa)R`8@*9*j-tH*l1_mlL2mCb| zGh0|pm?_xG=i)?UH)T(uOWs?(H^MF9h1dk4m(PdZX>c_VC~U-$ZI5m+gT(UveLH+x zC$F|jjm=MHG+LG}Z{<{uZ*DWpNX?A!5q8zT?3@O-?SdB!VlJWdw* zlp1tnTihaxo^FBVE=IR=dRndRo1=$=x5aKHN#6XG$maQ6e2nlpX+cbU3Z^Mm6x0*E z^l(Zx<*7L)*T#MV9()`VIHZ$rWQ;I?H6@m!qLB*{PlF-ZAx}gl_{Aj?M?Q)rq;E0m4 z7AsN#SG0}hVCD?G<(G8jw;pW#y;SJsUDj*#oHq^x4i9xhoglTP;p(s=-jQhUb1Pt8 z14*?^2vtb_p#T6*r{L&iifcM7nrm3m8nLjh2wr0;T`?o)gz(leRH(v;*L*@FetDM)`s-;Bt?H`On<+pkygQqHb|fk+ zq8g@-fPXIb1l1+{QU$53+!uEQ(s*E&6JK3TQEIkTP~p)qSkVfvWACU%Q7PS{f|h^= z<y8KQ2^QA0+4N7>R(Sp@mo%YF4BVjPC_`$977v9}+sjv*(v!SLy z*x}CpbNJTJ3DU!HGMs8__hvo+64H`WxQOp{T> zZTPBgY4i|dA~L3?yXyflFVb!a;)RUUnoc}JZy|W?S)z<*J~1vA%ZG}3=QkglLFN*+ z&_rqMT>R7}q*xqQlo)0%w}7bF>MEE5ogbapP(w0eLA4E1H7wqQzqvxe~bvY|pE6Z{axte5&-% zYLKj{hbeu7+&HzV@&BRpCz49c%{4)ou%x8sa%nviOJ&Z7{@lqYxG#>$_v(Fg;E3hV zPkN?5H?ya6&K-m+{2$vx-z#EIdni$liaGQTnVazdv7vh5(Q-m=4&s2fGgaT)9|^ye zLmpOspCVsXn$$Xw#LVB>t~mAVi`l(r$?EL;^@!E5Y3dU%zt$iXsFc6(WsM>ixTX}; zle}~#R1#fe)hcpd=1(*yE9cc!w{A+IH@wdIFc3~@6@~E zin`aqi#0sq?3+E}i8*0;@JO1)_f*Rnr1tfqBTO<72}jJ<28)`uqE6@6lAx|rZ086^jw|p!+nJ{lmHMZr8_rHtlI$GZ=I6`yAr%3)vASRM|yuef$A`UI0D?flZ=u`PkFjfyq( zmb|+Bw0qguDC#bLIo=M#`2R^tzRN9&b3Ej{Z2FJA|MPU%uKK5tqF&=v@NcPQ=-VX1 z(^~92@LvIiE@6+- zp44L2!v8CIaSQrxXb;FF{*Ny9ADKSecR|OP*$DsNVK1S+8{ELS#mD}2o3Q@Yw+#Op z;QK#u4JvR~_Eal1WXehGW}8Y#;yvw>fvxF1@csusr9yWn-o!Mo8$hq%>x4Y>{vl(S z;mh~t_ET>G#}mDn2J(5Z{$8|*(sASdVw>)DPTkx2I$Avv*M^^}>FW2q)Yfp(mG4&9 zS;)Ageo1&OQ3J_rG2V$&o^0*yQ>(VzW#4R(J4$B~>-!$^J?)jQwlrdQE`;V>a@`R2 z^2HH=^q)uK1pSttaN@*bf3c$Y+*v(CeuQ^Duv(|$2Rq%rG*0Z{%PGOsi%jHT^M5OM zm6N?1VJ7q8iw9?pZi}WK@{0;k#J4OuD=F?5{xU^9u8!VFT>Y;A;mH|^>K)ouSIFtG z{f29J5wMa=Z#pY~<}Xh`$M4|%k3LnGIA>$njTWq)Xt$c+V6@PEAo?(w;iChJzsmvF z<~s|uOYc5L%KOB}Bjj~wLCsB^_5S%4L7tdjx;nCjwIqIQC+rQ%u;X)TX~dA2#zupIGKG0bYf=_4!U55L~|n6?^_+eJa;Ql?Z=Ks%J)c9n=oG& zUu6#Z1Kwh6ZVbk+K8bYw2>O06cQpeu!c!8@Zpz!ACi@M@+l};B*iC0gXHI|EjqdxN zeRD=Scc@p|`$BJ({e%{i$ueGgnI_^%JihooY;fW9-(k87uUep*9e0+m=jx>y~4; z8YuUHGk6P~ioc7FajeH9gN9wOzzS_?rfatQZnW;hFkHwA4)=-YEt7WLSTjUKWr;mS z)>SxZ!cIn}Bm*~9gZkorhR#pjUaZ(k3GPhEFloExR#gDA%G$o#HbCTw>x^OT|5_V* zin5G`wo}N;cY>~kG7}G#7U}s`F8ZIy{hr*2R~7Pw!fJU)jhAUF5IFQkjSf}3pV7ZL zqVE=nu7Kay8036MWiNDUo_Q<;7mfM~ipEQco>SEy288q}EY3x`(MwnI%zUZ8Z((Q0 z27ChZ%YAbBzE*}@OZeeC%Cqh!#c(`BetwvBlY{YwR1NPM^r_FfesD2KpV=$x;J1nH zRPSa}OA4M{5+i?XS%s_Wpj|Ed5>Qv0;9WP9DjJvhF=Ve;&lxq*?rREyf1lA6!X}=pin63%@S4;{y!i7fMv9y}vIvn#YJuf|$E!qqq+MtN8JY!aYvf5q)-IRaku@ z^WjDcjaQ#=b%ir~P$wwb;C#-z%^nly)&;ab-*v0SitwrKze?hoxeSyF1&l&0QC{Qf!sC%EszH9iq7>CXUTq^%fMO0Aw<~8fJS(P>VLLpv7!e$ihv>RZ z!0q5e=$JG@Y*t>2oGz7tfgqKZP+%WsQC>rm6<f)eJq;Hs&AaC%cg!!x=?SMia4Bave+|T6-gD)u z94UzBpwq^kJV`U9f6W~+S-?1UUmf?x-yO`aewie?1-ysw-#c0O;I2e2R z#q%)f*K-#kX*?(Kp_^NAqBF zSR~8V=j88AOw~+w8aOhZI!c4HsV&Ye+9zUn=WUP?;*YLh9s}fX(F>A_sGU@k?H9?D z--Z0h9f$nH^ZC~S6j8x(KH}YMvAin8DZEkl3s}D0EPva6Rnx%KPs@-lwR@-6rK=bV}Q7gXx3#!a)kwAgEzur=Hn<}PcBt5W>ROi)i1LF$d= zdF_g|3pgYwo6i$L!071hb&&C0>@9-AVm<}3 z>dPxa_e&~l zlp+%^tSO?qJ$i+-Hyopc_mF8tbvLiU-*`CTsq*6_Rrfn>TjB0w{RiE#sk}PzC)iZ` z9}J|o4A4fSbGB~nBiA-}d}iyWA(=m$iX=50Hf9z4$C4=aj|vTASw*Gt&YT&gEYr6y z$w@0I9vQGqp_jKD)s$w!T17`{smM|{Bj#9T=8W|%b?Ov8zwN#Z$Pl)JjFr`-oD7(h zq-B2T)|ylE2vHPv?_8(CJAACMdcXeFQqnO_VLkxTAEET#*H&bq-;ACxZZvmt%PZbP zUU-ibyUX?wB(~7RgfQ&=W!ot6+MRRM{uTMr{SL9rUA6OSO3v3tgGM)*ySO1%K*Kmw z(2o7rkMd~mwJ`enD)B3b3d?$W{)1NuNuu}OFF1MdVfqt0o69fI5B()FrJ5!uUc4H1 z60Sk#bRkdG%_xaS$m5!z`QFBR!7+9B3wJZmW0&f-X0JV3UO{r409*&w+`b`3aU=BL z#6dux*cDy9=fqMxB2dlhs)vc_;*;o4TpSIp_DW1H$-G^nJn>cqy^+j{wJI;Qz_p#+-B{k3es=9sLmn%a| zO-_;3Q{pW<0`CXjt>FMoKYx0S=P572Oet*26`rfox%~8K%CPMcojHlui>C5+Vdc|RrFbsS$%I<|O>Kr{{)LqM* zZ6e4p>sI4$jr1HOF;cv-LA8yTDQD*a^(E_y5}Q%r5r$Ox1qE&Gc<()0#q@MY1Aw|E z=Xd=lfvPAqk7)6Maa21-Vng2Bj}H>@Xmi@X0?~e9mWXH(`xqdW=~jxHYk@xC^)+O( zqMud{26mPEyks7jM464|m9&F{2X7{rYy5+>`;pu4N@zRy>gT;Ur$sf!|M{mrw|^13 zwL^9~^tWfde7;Fy*I=ji7|>TP6}_y6f-_iWx$GC}aOQmT*e8V`mI05&TE2#9F!3il(?~WDrf1#ZN zVhb+mq|@A<&}7!X_-~!_8<}0M=X;UNFNH}kFBr_(u4 z{de3<;%{g=RePB7FGh@v`2JOg9jpx}KRfoeV`#CB5C1JnJl^#Ly+V2d*f;Cj7NP<- z`K_$q4ueDgd!Qcao-1R{&G~wdYHSx%RE{(2{+<{(MMk!QBNIa3fUR7Fg0-_T`-V2i z`_!M4Co&Er8%;M&`<8t|YbWA^kGS?)PB&Ufs!%&6E76W#BESDo+1oB7PKj+W9Tno)ymDC-tVFm~niR}L>>_Nc{&qLj^LF3;E ze&?dSZ5@4k8b8|)!zCNdKN$Xst4V};!H^lK`exIW)^5TB9$mQ*C>j9_$gVlvu?`7cS|4I3FNWlsfeLu;Qp{)9oSR}sRWc$Pp*CtFZO)L=(&r5 zpCGA`6Ljo}mDqJdj=LM>IuVi=WD^JNH((V@`pKxO0Kk&UW+7TgkI9IQYLxEaDf|tL8J;qRa}bovFMMf1Z$f^ z?tDOUb7j(A0zfZicMIa-;)h&E;pT8ZbKa&FA}>^7meC3{c?wIXxo9@ z#Ne+=y$Giu^ZI?EL*<|VEZinj(fqs?9Gff=l*4odmAT;a(oJMMjxs4l%`K{BUS;6#in#rbHGAEoO|bsfA4eF)5GXo>#i@y}?9L~k z@YAs+aeg9L3!E7N95NxYNo)zaiJ4M-4S3{A7!?LUDRyO?ioc&D{shXQC77}z^{3>o z9=EVr6^6nh=Y+IaH({g_C>7D-36i(~N&n!oo=O&E32Vm_lHZ06iWU~YviCl38J|vV zCq;rYIp>)Y*-np}R@EPsK96fw7cNtR;xC3Q8e*~fTA@Sgfc_Q-_Bx~tptznJS-blplM^paTi34{SXAwqphhj8LDky2{1o%jI#YV;p?*3g_&cTJK<6%ABiNzbWVoP z3D*WQ0z%A=jdD3tBUastE^2<-6Yyz{FzL}(Hm$9*&dG9d zmI#mNjVZ(=BllCAFV-Q6%!~hvICa^-K!Ao9yFWOuKAY2T7-&<1+^8~hliEr#p&uo3 zyQJWYZ~@h%cDa0&AAl#YcIqPK>uiQ=na*W+Rxg_lja60o6CDb`w_rd1qoFu5j1QxI z4DCznG zy_mKIhz$jPW2V;}8al~JyOH3cQ%j9qX2ljpd}$=g>|jTg(m-U|;Rr=RFxse^?giputh*u#-j#SIV zuivRo+o3KUEsU8(^i@b~egP12z2q7rK?T7ba8oC}bCHmc7O!jZaJQb&5PH=KUVB}k zk4Rp}X~KhXDTj9DFrCrTj+iQOuE?)Yr;I^lI?TzROCdVXYADhPgw@4yK$)vX7X*x=uMV8d2Dp0TpRpnuf#lXBkGEqoQn)SmR zJ&EzHDBz={;8;gQe;cFl3_!ZTj5%*#4{vcE9BEule0f>BU#DGfg z&^3IHd2Ah{+IH65>dlDomS=fjmLkN1?-8Yddhz@McdWV?2BCD6z3AAGiYp+O5LjIL zO{6?3qTl=6eu*6`9*EEjxTG)_!Q~Ti*`}je>XF04EaQ)a{}^>@I9K>Uo4Tv9Lqba& zfa3B3fB#g;em73lKr4^-d9&Ps zqWY*W*vyA@Q77q6&(}EQPERkga0m`smH19jYd)(QP< ztn@DJC`H^M)jepF1dMo$ORpIn9Q)M1>`bykieb0$<4y9HH)!YaX#8J1|61e2rmHy- zu9=W0czglfkSKQ1pG{X9)pEa)OHYesygkvfj`(-hF3*~BIvWv-Tk&<wgYXEm|NdSOyhF9r#B*Hmx-nTm8pknbw|FtPL1*w=qiZ7DaM=gt$kXK(waXj>dl9MspxZr&s_x8kFmoyV#YKBc; zxNN0whi_0cyo}fc&kblH6D_6_B&%c^T-$ZQ<|Un6Upr<<1$YW%H2M*qcq0&=#1mHWI9y4(dXOU%NgPx4enp-OApjK(= zbrX@Zk`G6?RRjCVkA!7GBSw`hZ1YwIK+~KVJjDi%sdl0}y;Ga_D*pi*GQYfEz!g!% z4P=Csyr-GTA0K1Pk5seQ22rJ>m5X&YwyjZ^<|Y3nSyjImABW0b&w-pw^q_LBxbKiK zCQZVRlzuEy<9vX$fM+cf(fA{HXr3f#%zS@Th7ju83{=R6HBr6Fljs?FbVud+6!Xh- z2hqQ9{CKR=Mo?X!!lqe4tMdfIyi7n=n!K%|vLa^e!^6!c8zc|)2ZVMvR>Zcl;re_i zN3AZw+I_MLq4`5gjOy4NPIgbNYA7|ekjMGee&o*fBcjECuDyj_3>-Kqq=8 z=9oOp(iPtyR9&)^wAK_>Myc+$z^~l|cZfoX5DX~2NxqHFegopo(nwc+*nDak@K$a|b28-(s$ z(wMa)on~SqHjc2o|Ekco6qmvnzHjO=GOqkpd1M#4(mXdvG!`>r3P!6HFDm@QoJZjg zExpQXBW)+tt%$~D={v8kZV<9_=CCP!dQGCS1Y^x10+;!srSjbgTGnYUzPOdh3=(3; zQ|LC2?5S;q`g%y-7ttVgvg6#Ip4lQe1}rO4EKB@65~C$o(Aqqj$S<0~fbEm3pLvA}Yx}}u4l-kZh^S$?kHWE?gcI3B5wY<&<(~0ce>n^P_Q(iT` z)PT?gQ;A=rYjd5>#V$9Krn=_);}T^j-&*?v&W%Os66Du(3{ovSq3lNZ>?IsA7xL_B z-L^lrEnx*1Jd(aPxU$DMQ3LVg8R=WdC0K^uNTV5|Y2(rgqmS)vYd4>@MhmV0B2UT7 zm18~HNr*0n;KaA|aYZ#vcqesqKGTHPE-fbfR#0lp#qxp_mbMN|=#5qRXtTDtVvNsV zz$1e}aP+vTW$gkR!>2=n;$TziUwGE+w3eA25*?*nDsV>TS7|QdEEL?!(*6ijRR)(E zS;v9(0f>j)aJ8k-ex@j|4SYxkS|+YwzYq+O14_n)jYv;Ah10XnuSV?+tqIMPaDyNW z{mB)tXP=Z4sSBpX{1mV3tO8@~1#y%lRG*nb5l+KbNj;ShI=VR)Oc9#tT_?2a*qLk5T4rR4L zK;A|;5QMDMPjdSD?57@f5j)ko7GY`mnT;#jtD$sL#21mLTjJ1oxfU8^SzQP~R-&R5 zR8?s+dF##kx9^W4Jx_dHyk3lgRUtp!n;9CHlA;|nBdkHf z;QWo;qd3AIE^B2!lZ+i1p&fV~G%}t1(4{(8;2VlPH}8%8s9JPnsbl{J4kH6b^VC5c z9m&xKiB}<3r&3dN&fT?Ei+~FZDsG8nh8H)q&^=jL85`VE^QFgqXi`}i)^E7 zqF0$p#&a*B(N8@Q2hUXJNBLYZcw8%r#VVnZdw=BNAAS_uF!n3(nrD*e2o2uD#>If8U2At(smKa{FQ z`Q501371og)>@^L=~^WxGP#$1c>cnjtCiov)bJ@qmq1)h9C$_@h;`M)$IiKO04)iLSIL$6(3jQn7|8IdaCgF^I$b~lgWJS`VTtW1uK^4=(XTs>w41JQ>V z)88)B0hRTCx;X|U4~ysW*<1?EDcSr;!W|B8$`71I?^ZOxsb;%7ueoI;ziEl%qrzfT zj0fX|c!4zKX6P9{8;Wnu+!J&El}E-)5x}^eqdJ_3`t4Kh!2wJ=tS2BEg7~&c0nsvZ zBcFN|Xr>QwxIbL&7vNhhXOY20N%ce(-Famu@8nAN?m_;uBbk>pQ@rB|{C(ps(%Ub# zI!$)71s}{COE`Dj=jtT+00Xcer2Sh!Lt_QDndujhPk(}msK~%TB)4WOaIv$>_MYrr zTj-Cm)gVTY1+r@L3Uj;WoW`_qcfPs$-Jhrp280xTbbKEln+R8*5VE^z`Phq#cEGdy84-n+Zdu^|1y|mIM1lgMVU%qRZ{O z5X|PB$)Un&-2M_0e3O8XQmx_?d2a1`fPD{ z^g@W=v@&IaZU@QI?N-tmggsp&RzigYB?*J!@Wd}-eJ(38Y8UHLvj|g*K!9w;VrZm1EY?3EB;1}Z==;N-1bD`n|KgwIv~S4Cmjkq6_x=_lhq$;VcCc2Rt_GE!Ut|J) zJG*V2AZ1m3PP&58+84C@tTkH~OY=2@Woqx0bh4EOo?|L%sx}50zt)OAl%q z_r{;(w#VW5x4TEj?_6=g{r72%X~~!@O)$fH?*AE?#h7c(3r*b(H;6X0ug(6j`{w2B ztH@1)+ByGcYtz zrMRYP`vW_HXYOcW?Y|o+blcvunt!Z)FrVILYJ4ByGx!JCra;_y>mZ)?s|V<>R7*MN zn)Y-CH4O;SSz@6bmixBkZsS7&k3FxdTi$KCFJC92*6SbjV6xI9z_UD8Btt&9r<(d* zTBxo0?o+$_JG^uwV2qwOwJ{o;sT9YFhXK10;4Uq;nIT>gOWWvazM!|bzxfcPKOl8J zMnp9A$>1Xp60<}8fZ8SanwJKa=KbVHI%*aD3IkV0ch5=hiOuA2QSAtdt+x(z%t+4; z90=iI@to?2h!C1m^JOsU_aiXm9FM8O5Z8tMm9zW@QJUzGKRvQn*sk|x8|uBzoYaWL zM`ZIjm7I^sVcFQBIY_K(HUHh{z(PyH62aKALM<&8a=QKbR)$TJfcHbS7p5btmx z^p4@rdi(FACnJE7N0_wWZK;}H$uoxV-^aaEb$A2cQ79d+yXqRAC;z`Lw!BU#=;3lk zQ^=euIMfWouZ(nl&r$I}N7L6}FiAde4%>v*;yWOiyb`huxPYzEj)GN-(4o9ayZ;ovO6D;s-T^XN_I}9J+ z6Q=DBe^2Q%9b(4_=1OhHYh2^Wmw^*}S5Ytddug<#1D=cPl6)5HPzU%SU+x@GGJITk zyk9SZX+=RJIM_jbUYwxZ|M3gvi$H`_*+;~}3pk(_4GM_%fP%l!%h!^M3)WwBZePQ~9e=92xjrIgfItdka6okUjd`!dMF{JJX|Rh@sq{@H(<$RjuOm5_>%6kj|xR=m(s z?419Vo#e(Nil_UB{!5YHHPoQ0@R8^ z$fj`jVD;(|{dgI}!Vv17uqAGxkpidHOWg238&Ksxi(h)cBaeuJW*H^0;ZK8OoJH$%^jS`5)GaX zDOV1?`wU0$;GB*U{yT8+&;9{aT40BGY@FZHNq${x9hvR-L9MDt`M~k=MhA>mFxT07 z5iOD5=sk^v>&xT3)R|n`L<(H~8R^&M3%vE_@y)giZZ?M{-`k{#eyBc}oqdC>nwxvm zoFy)k){W*;* zudl6*qra>%__#Tp=zxHCQn%?N9nA|*c2vu{kNQuDqV^qw+*gWd&#O6epkc%# z{Rye>rd#CY2D((m{Jbk1&1%=I`zsrqv1i1U%V4KQZwOTndw~YSx1o$sX_+Nl!h-Z2 zXaeZlkQ%x2dp>)rTKAn+MtyK0-W}3YWeAwv7y%D_w0q*V`+Ce+{gM> zcKuGX-sRbEACron_sUV2`?V1IDGijapD(+~fN#0zpqhJLK<`Ms9~nIHelEJMDfwv6 zUZ@^N5`4EdP~-$WnVDb0KI=a(c!`kUslX0u$+yA)-^#|ePwL%z@~GwYoJ|81e!4T# z{HIc@QjPZ|X#bS?j#^B1tpqo5Sh@Y83toJr7Zu(Uq#6_s$1h%G)=#Ht z^l5`_yWgLk!`|j?STOy8rr_5HS^PU=^XW5(9XOA#XH)rt-tpa#!f5IqYa7m^(1|#D ziU57?Yzx<`t5*Z?vR3f%$L)wb-If8*d`uJp@LFbbY3 zoN7rKHUs^tHbn7mGwrPNGx)v5Aa9kuVRU|%gze2n|K%yk&|N&J{$4(=;|Y7B*F&e* zWoUKVoJVC1F4x1_*VYqlj{K&h~-<;R91F}_00jzBi{*LQYkK#ul^DE zx9_FnN#_E%PgBAjB3RO|?cjVckOMKgVe}u!B7@~$Q`2)N%wRMZ2Nyg8Gud4wLNZS) z2X?_9WJrfPyq_$C7-~$QLh+;tQs|Y%`}^fD8mQ__p05Z;Vmdb;QW+6xLc7 zr`Wnn*0f|Y!-$Ri>>u|ub8KWvc6x%(tTjX$=0Y$i#z;Ky{#IXfi>${Fe6ZyDrYw!| z2#z1A|150U5#KOMdEkx9tV;WXw1TrcHAI0=&&g>{XTZHP)!LeRc8}t^w$N@Wv1SAu z!SQnX*iXwvIpoR%6P}KJJ!9xnqOAAeeDR{aApEgUIO{vOKm?xK;1$iOzT<8u%)d>a zQ~sle~D9B`Z}rm&P_w( zc{rvM6Yz*`V zYlDRBCGo%D(O)z0yHmZ`LS6pp|7v*8`FEAV zb^(XFA6it@eJ4nlf?Egdt|uy@yR!~M^j#`;^a(qJ#KNxHL=Tbb!*tU<{xa>+mRaUI zq3l%1`_<6`E&G}SpXjCElSKQsw(yvP3|Q4`kq)I(qtsh(c2f@(AzQM3SG(7+kIvt& z9sk;Ae5%BWn@XRiFCwuB(&2#m2vYS{dBl<}xASkHs#l@7oNu`Nc;V=st@t9Hk(0O4 ziVSr8XQ;h3s+09aT2AD9tisjTNf-V{qx0Uf_wYcJavZB28gRXgBz#VtJ3iKPc~W>xSKdKT$eM34|}A&{oCBmlXO4(dQQ91QE4CrzvGy=!|PjFZTnaO{P{)k>^gIJ z!(z}%hX-aJnUG-uPm3Yqy9~WN9-7doJjGZ0M;sp)%4{z3-g%x>@Nprssb zCHB?=yQj&ul+-cY)~raHm}LQIG{^Z1)snEV zVWf8~mh6J-A%5ue-J3=(WhA+^!nzxne5K2X z;UvG-#D(t`jl3q44rkK^LHNX)Jmi7_Hl<8KYT0b4D7iIM>7;o%A-B(3U{sBGOrJ`e z=Pj!r^-oU$vn?hPxLkhKWRM{no1GSz`W3DZEd{?$6kIV(T)jGR+a1g6Je$J~T6II| zhw(3Mav^mip8!bH16Tn|KE1y&03avcvFK$XR8@*N=H+|_@(tdAS1n8XmO7vhDRRod zbs6Vu%ipmd2$Ku=6k=B1KyQ*m;1eZWdSOLVzJ(_<5+G_-)8cC3o7EXk&iFacA{0$k z(c-3>U|hHs?gvr8FsY}Cnl1r6lu<(X$&u^8V{B`YOuHtC{Z)lH^eMZF8g;0zhaent zIMH#qoTtSsfg_9WpFlWQk%RFTASG2c${vO1&}?=AUhb6YgZN*@Ec8K4Fmr(PKX(Q_ zDuH!-Q8UFyM#Haz9b5?RFx(Ry*K-a7Ro+M-#bvp0AcWb#*1Kl1AcdFmRtkC-vCDDi zB&ObNWD<98rX04C{g+4e>r80w32xyIEl^xelNhN9)_|d|z|0Xp8)_wID!ksIqvyR} z=e(Z%PT~0*S1B`@c-`5Ea^CrBG=cd$plb_2aKdYrC}<|7S#19wUXZHtn~W8K|76}- z{n!R>Y#m+*+=aj5!~+26K9zrPC;S&xorwt*x?SGBhw?eEMwA>06_m}!DNLl6mP5fp z>ooPPK3BlfC56dRm9VWV)lV)gg|_m!;Y?ch1wukv+)?N6+PU!%5{9uV*iV?;+$K0h zX(z>$Zmh6ZUzP-Xk@nrD`uw72QmSLy0@EWSTvYLM0dOiQ>5t1&aZ*e}neboO8T)h0 zF^2n&y;GfSNVgW4qC=K*8kvwje&Cy%Ur49zV0L?jK$q-E6wrU3Bdsg6o3Tpwt4}UI zIC50v1RNJAXriKOxJDb;n~cmCg3*qQ{F!;Muxac?un~4Jgy7NjK!nSb>NIU?SQZ^` zj09{A3DxK&Mf}8Z;nY%9EkS50=qd$<1z75qQHj2(Ga9Fsvm&xqwIxt<$zH?1QImol z6O;r)hDfO}LVX^S;g<5asbE{rmI%3N(Qsi=DO@l0;TmwnEkr?n8qL?p?GR(ZE;b%F zJoM+$z~LMlrf+}rcS}bkl>31AR_lqJ&SC zi0?P9;)k{F2aAk#eF+cZ{AcjSnkukd|4Wb3GjnQlH=!B*jX@`zga`A$nGZuopbq}h zteIAlR?`Gb(py?38#(!W_!~r_TIMW zuqRK}mg@`H;G;P6i-Th03yj8w=O3F@IZXIrOr*g-_)c_fQ+ePH*wt{_G)r32>S%cK zalyInYFG(2I8#I)Cm}Rnb72%d1}b%PY8JM&>4*n?u_)3paGoiUL4g~GWU-eUUBCV5h_p}_!P$F7%N1IN{0rj_R6h&FYC_1r z3%nAS%%o~s7^;3k6?|46{OvSZKhSCTM?^ANt~+$)-I%Az#mFtfHK${Wd~Vp2jU!z% zc9PN#Gp$~Rf7$MZd0C~H`jQ$3v$EowD>zq4Ve*iMAyc_>VP$?$1S)aftBkpEC#iF{ z@N(|V^=rPo@MsqBq9Yqwezgm98Y(=L2fqt2o2Sy!#iswDVjdbgp^5Q$EE%0JFbQt# z0TCf>c1jVn3~tHlq6oV<+vZBGRAqxZW8|z?ZFkkri`LQO5{tr!V6|lcvF9-0UoQaQ z#X1J86WG-VVp-lSF^Qxv<|rY?M`xx$!b> zM(%bNc}TIZF%`hnv`FcLu&_S)pgbDh+LUm=y6a2Ag6RI5-jq72_k9$a9%pq>W zuM`*+iwCJZi?~ZO6vv)y6nozr##SY)e8Y5rN?fL_H}ovkL4tOzCwXL+(Q+K7Z zjGML3k3VbWM_N+{HzWuU9PF|ILpB;Lz+lxE;&ileOKXlQ?CJ(~&MdAKj+RxD_vS?Y zq+>DB4E99eX=iYGB>+L;U=l6%)RC>2!LU_;r!v3xB6CgU%6yx!4v1%4sZab69dW{M zmZ@~3)BAO}SPAunFeOyi;v0h7N!rtbStUgn(@V8*4h~Lcmxg$`xL`osNfkd;KmhT% zIih!Pkzl=X&rsBeZ*24^4?I9S0IDNl^f_a@(y8o8BCIev8I+9+^151@ps$3pL&MX}Q5=Ig8dL zh1fqT<6QN?r7`FCX4Z5HumAsdJb~H77SN@l` zRYJhf>cPU7(+#05>!>3{I0lqv*=1F#pnCM4TM^(`V%_ifVqK4c2pF}MIUlL5gPHL9 z=BKxfIRsD49L4I2W7Z_74d{BxoRH3TvO$NDl~y)( zBF6eGYNoSs+XUe`<7OxS4}1R~ zzu9a2V~>5j5B6H;8Icj05s{Hs+|T{IPS&P27qtBm>?W%z+>756*t$aZCg8WL5?ctP z20e4d>kp?zlAfe7V@Z=&+vxMPAN4h9AeTKT5mR)i|JhUx>LM&swu1EbJB|MsMTN;- zP2p#`{2&=gMYY^vxKtdomT19pj0AB|VzF0g&m;589!{_YmC_Df#1EZa()NVO%Hg3% zdkRf?FeNcI&~%#dZaaRP4@!br&JEjy40{n0(#OO;_iQYY3-?l9+%dxil3G*~r#NlH zD8kbasql(TCEa}{ii3Hft)7!JSA1^~G)$RE`ns)2=Y?@T1k+ld^Pe>hoFg^GasH?! z2P5c#jnG8d)au^>wuh%4URqdR+80?Rk*dt&3-+%&Whn3DW?aIK5|@zob{V-YR}6)n zbplb7@|3dr&~nVe>nnI611&~*KDGo`+2+8x#%{j{J1Xy}XPz6^NO^2}O@^w{lsexi zgmdp;Dib7EYFbP7^4VVh2-t)EIX15};8#Fatastk8ULk$^~C&A(8EAepvFx8do?cK(O(%y$ zz8E$BgA6{Qx``WPdeb~V6KgKsY@ChAT_bxRBLwDT&%r>F+e;e4SdRbjO5Zh6LPy~xc%;BO-tvlP*W3=j!rUO?&Q`DZSt*ELhP;&W?A0}F``3Fi7 zDero56$8`Kj5=blx)8;2!Px-eyA-3b*A&K3?2f5ua#D6fz##g3O|8XrdYR3o$2 zSk``L*l)Wrw#Rl%(y#*@KL_vA%3DX!2bJD|^tuIHYwfON@kI)$g&4)Eifs7CTglcI zOoN(gB4$fG6=ugXQa#x)7z__i_)X=oV8fd`+Gj`5;+PjJkX)6O$rX=zArBhm0iqV$ zBProW3e;}i)vx=?b@_synHE+C@QQXnQFJvbo1N%3&UBn6=R7LbrCfc%u#uRTqU5Ua zb3P)=X^CK%+R?pSt(JH}2kmoGlVf~kRW=DDvSI$-~XA% z=P!rO+}s$mlAIc@jne=9^ZAx{)vfMot z9AL{<;H6iQpuwXzUpIz!=zw9SpO0Kd;paFBFiM+06An;b= zoI}6Z)Lsfc4VOJm&?CymAh=^LJ2HupX$jxuvM;7f;1Haf{W z8o?U~beTxaeIMRqOuhvOlLW*4<-lH;{lw$!mB)ELLLH(b0#(l97B!0pYa1crLNH^q zvZTG5>Y<%I1CR;Fa~Rg$>dDz?yne;pj6@ZevuECBBC`CHE|km7$sYk7)@Ii%=h)(K z-+kUXhV0z?WhdTt&H}*>HJ&p@2=9<(UZ3RkTMqzQz0EJz+b;Lgy!7$Vx8--={PKa! zda(>Pr$*Y**$J9k^7D-lLK_Ec)IjZ(1HYPWA#Hg->|@n#_T%lAwvMZqQFu!VymM$l zc%1K>3fiPXie%5U%eKw>ptLCUsn!hPL=NzZ%zmZ=P=1rlEu(TdFU-b%c7xga7o z;Ch*YTMy8il{io@Jtr?Lo{Fe8V`zb5hZ^44sFB8#7=~?p0wdW+H)!p)SU!y7W;T?ryST)(vfV}1s&&Ah= z1F_Lw(IWwJ_B|y^JC2;IPrv8c(Qww;s(F0gXktj3$)uTlH4{VfX#vcbZ!`z$(gFnUkG%O{i zVQ(H#KTck8`@D2i|XOYXIg%A>pyy*l=BhkL^mM2I^Z6NGL)p^$MJy^3RQ18WG@+ z&am%IGtu}*-=jgQwW0$!D&Yqp+15#fSV;i-%{A8h571s}{{v_pO{hFc{}cSQZ~!>( z)*(>hxzvB0H!H#q8ao4YMfd9l6aQ1EBRDoT);yP7;vdNY6NvxWZgw`(uUHPppO8}V zF&csYkZ`5A%&zH;TlU)hA|_3gs?hXlPx$}jb&XYe&Y6T>|Y$Btx=!~yV`atAL9 z(xcqT*c;GB{hvhmohFPDz%~qkM#v#t$5QmXc!fico&sPoz~pB;y>rDDW~Ls620+8B zM2s+FE}EgxYdPr29B@&EU%!sUeQoJPpFg#{C%7k|a-N}wh{zxT|xN5U9B2oR$CmoLh~NqM5<3Y4c&-p zrd5yYsw-dsLY^CL$L|ck@eY=11IQk_jD5xxWYH?sQW5;yppH6DIwV)EQy2#AU1+33 zUY@3&c0W3poYBMF(R)11{41VezF;4l_q?>|0%_b`+r^@dMhF?MF~9;k(X93r(A?<^ z34i?F!UO%>XHK)fTr=paQ62u!F}1sS2a2vJWLSP(Ou8ZM4jsMI@&~+?Khd}NoO)kK zpqo5b#qS$Pay$NNOJ<~JP|v$0+uiF-?MFG@+-jN`L*T-{!c^GEsYSs}+v zV*1x<_#eoFu2pBCGYI$*1n3i9^3GjAJw#L+<;RP<8cSujv(!m*eBihzx&`_*=v`?XN$Mbsf2ua zr(1JEJ@tozz;N01)Gy<2h(R%&hse8u9K>>d=P)~kb;;^glT(Z9DY=%P1SFni`d5MF z9a$?)Y2K51{aa)J?fPPjQrkTVXV81FW&)}w8}2KzTPMd%Q*xLG?-K#yDO@Vx*+Gb) zr}|**lQ#I}%Iy{`{4;##NEfuYv=FR=SO06%@C&yWyKdKQhC(cQsD>R?2fZSbI~s6) z%wIwA_9(8wd{qy6j z82nwLe^u1>x@=zV)j;RdXXqR1DgE+VSl%_ns_jl#>(~BSxHGw-%oU{Lw%`h@>|z8w zM_<_4WrzcN8Wy~D>IlVj^ret*|AOh$E*E9ko5Ws6f^YFJpKni@UKkKiNBKtsLdvLb z*UlaspELsG^bzH`fAGYtG;lBT?2WC@1~(>da-3Qt65g76MH9a)j)%52WXrF*0`$m$ z$#>Gg;22eA#I-t;8eEd?`)W9>4pAdw0hEj>n%{B7^Our&O<7I`> zNlSA5p^gzDHHoXnq|^IfVLEe&Q6aIx_64}%wyTca{2{OPlxG~9ZNzq0Ll8uNzgJ8c zYOgv2)s3je*TcHjxT7MFP=w}@{hVJ6yIM@9eBm?gJ|5Bm1?7}+(ysH$b!s~RetSe# zZ2N}6CF%UU;#sqY8=ZlNvIV@QbV=-#_Zgd?OSH-1=esAk^Ty;WV5`6|RiwJz7i35e z+}A5XcK?uqF!Bl;)NRwhr@e-EmexZFsj2;EoR~OrefaqOUP?;~R|?pN6R=cf|2(%o z>Lw7uIV>($J?RV-%Vm2<5kd=MiW&RazYz00x&5R&RD-Bog%WpNn_lu_*|Qv79o|Ck z@W^=SacwX$IW0g)Mrnaet==lHRFAe%$Ywgdr_0&Dsv44Az=F;*GL3U|MBsB_+c&*T zWiD`9aLvwtwAB2CR^bKJV0}#aq0RDh#eKTPm9^pV~@bAp)9HOd2~%KI&eLQ z3ss^cFpP7>12s2yy>Le(Iy(7WPYbd1SwHZ9bNjB>ExTFvE$9}L!v$QAyL8~;TI9KB zk=B9g`wZemW!bN);;i7~AFW)bBtB_LzuKC052(~$VPvKIVM4cF(7Sz_VbMa=$QLad z(Sm!Em~eWDrtwt=O8U15N}zGwfuF42;NBGz=-NLoxP1FZk$Qw$FRsv0YhMcSG*9)* zO9^zL7+Q|`ZgL&9Lk;7^^hDqDk)gBJ!#3j)YSLjXYv!J2?uA8m2pJ*nT&4zsj8afk zNQV6h&RViLcM6r9@I2sj9=&!V+LqeBaX;z8fW~+SbYzbTyf<6b*b|~gZTYANNsUbH zYC>-uoJ*Z6^$Y<~Zb0Q^@#_iE`EZL#Ex$r^b51c>IrH~CK0PPp8;jf_%#cyfM3TWt zscD5$bV2nf57S&nh&k#Hji7T6cN8JS+VK=?V*PH7`#a*-?C%j!E$lp==Ugp+X zuo@+SGCuB~=ZKc*17Sk4?rczYN=@|m7--3KUJjvmz8*H6vlc-&t)7WgqX^R9^?dMu z2-PT`T9&f6l^Izd90^q(weeV5nR;rrB5ZHXC5meXc}S@2yUxj}<=%sk3SALB>s|7W zH(&h3?#xxfk%Mzgczd^CwOdOmqpzmDq=WjrO-qtE+%6quyW#d$P4Rl~*Hyi`@1~#I zE#=Fq-s`-BYmOoD1Rzm<8=?ES;F(Q$6zO|I7bW3Yq}D9v6|o=ben!}@m~~30ydO0R zgN;+q@I682XKRM$S-)M=$(|D8^2_9hSj@$N+GTsLZH~*2k@Wn)n>C#F9qjs6`?Ofb zSW8N1G0g*O;UKK5lXt2I;Q4(bTVUQ+QgT`&;! zNBcb;#@> zD2Hqf|7aH!z3C1&os{x@U5^{x$c^t#&eg{c)hAq_r}wfMky|&2<2Lalcd43HGFraj z0si@}h=}~1`mbN+WM5sMwB63p5^-d6!owb>5IVP(y1@kAd75KqbZFz+e%dRGzdbK7 zjw|sBd|za}04ukefjc2W>jAj9lt((j5{lh2Llfx`_}~_aodfALjB8Vzqe+;&bb4xG$2B~7fSg0Qm)D_ud{<)B@P(SH{Sy+ zy4a}o-`+N?L9X_Ih+FD`eM(t}~;BiUGG!V>RwUu@&vsvIiqY--uM@T(B?xtu_&HH_6tOu0J}4--m(( z#Et2K^?1T<$!qYY&iSzej_*&N;yy)0NW~A&_o_7j=>)?7->g}-OJscm$nK}d311>if{5hsSaA(uP&|i)uv?*3X=oA-tEYutg)*C*f5KEhY zwt^k=X?FHs=J62N-lG`ff^c;5+BvdNgoRI2oo*bp4+_zAckI7&c}yznN_V*AIj6Wr z;njE`&ud>wZTUKYh+1uJE3Wux7agn>NLObjwt><7YU+Qo8u4mRvt|j=_kHY{c`!(0 z0%QQOg5EY~&!@aRh}nrCLr*Lq&mB3Q;+6wRxmYRqsa#`G#PyP9h8LnDb-o%JVw=>D z4{CYLsM9b+H6ux`ClVG&X7K5FXJ@{4_v|&fmumC@O@!BmoW@3KDEFcWVb0KdigsBU zvHlaD%r=iE3yRd*!A8sLYsUv#s}0`1-FhhhTVm={_64^vZ)qvnp@O-IqB%}R?yvlV zca$yyw|)C|y_JwVQuT=P>&crC1dZC!jVW)rj~-~*0-%DC;a4k^*YGoXU)N?%m&)~o zDUJPRfEu2(A_DD5@L-NlgbYupQc56#mi|T5R1Ztl$~{V?GWmzjIh?Q4pnJc_?5eMw zf;}=CUp;;_RN7lgP2Z5((_Y8D?z`pL4|Iw*V`>;zYhN(OxcA}^UPy=QX(!P9Srco% z;UT5kI^K0CD71V7ZT(HTTi7EU=ahPRm!^^KA@1VVrz9$X_RuDmZP+8NL{XwcKE8(! z=im4LxY)o_C>~LQua$+36mEAZB>JlA1^Skc!b}*{Z@|n_1*aA+;R}q`c626Bjm|4O z5Gk)|+Beri3q`+RUewSJPDUDcFXp3uLQ@D_C5T#@-Pv7X!7TJexOWqbr(^cl1p z6g(xvrW_i%du3eJCvTx_PuQFD8Z4pY%z=^FK(GN#(KU|Y=*^|CNL}q=@rY90AC5Qp zhOSlqkWp;Dls25w`^8v|UcV5i&;(6<<%!aepuyMfIMDo9p3$BT_WDIUu_gA8(DLho zs2FN?fx4$^`hs+n=cc@hV&7ugkL|NQ%?b#^8TxG%)bb?WPf=+F-6j-h-<6A^M@61x z25_CS-nq~a)&qQxoF_OMkWwnkGkg&XvqaE#O|`uqdOZD!LT&Ewjl5?F4Zo*imS0bU zUfOE0SEmK*(hQ@$h&(?O$da7nj!3fl>?a4eA1h8D=!Nylh4l&_M&!iztW{sc($`OP zDbdtALU%sKan=c6Yv|P#CKNBbY7TT$jd<#`*&9ldhjyEQG8o{ER;Z6VJrZ+YX$XBN~4CQfi`YHK~~bs*k| zh{8Hy)8iA~Wg$umbk}sC*JoD3IdDMHy1zU%-V{Fb4>HHgKb~MGZR{8V!U%X^9ixty z9l?VWD%VJt2k#WxcH)dzBS)-#Gnm3>234-$F zUD3%|=kRkE|Mdj*{q~_}n`=n%NSCsz$I<$yy17JHXEe`S;@F!FC6>X#w0kU{i7f-V zG`U*0^!@pdyZlry&<=t=yy_QM4h6SH&+E4UJO)VD0itnXwwUbi{sK!FdGeq) z4>x?C6krI2tZ}@QQ6SHEcN5%)UXfosKA<1xDd2u@uRNfr6yC^jV_x?c6}tCppf@@^ zcpobdFi$a#ov6&UO#_c?w_OV-4|XjqXirwT(3{jlXgM16qrKHs(4udzT|L{Gh|eg) zA1i#@Y#{F~7koEozX&gT>g)Xxp4U`&(J=owZO=fEq?YHb;eXgF3Rpi^X<{q7g?Ee6g8SKHdQ7jo&!O zg)-!Ft*>+=vOl&IJlD%m!_z5U64Ls4UdcW^c7mOVnobo}`3k_QWXM_5h}N(}Q}s&WT+R(i&<#AWWEk|H`OeAf6hu z7!BM^xCqbxjMm~A&^Bv*!w(-NMtFumn8EboBfxT%{nMk~4Wi~L#n7u?OP93)`SMg^ zrzabJXT^(K>5hSuR&+dxoIshdgFwA~*GYS1wtjoj*!Z*;9}M~|T{-fd_gA;8`qDKr z4S!PLku5r|*Tc7N=r<%9_ZgN<71s6pFd`~dIWrD zS(`qIL@5LAWF=4Ku6aFB@Ej52YJr~coVPnnw*n6)*%rJgYlGyY4VFJFfd@!Ng%ZWsn z=MI`ZA78cJ(|)y~E8JpWA9JGh1i$H^B8bW}+@K9o!dah4OSnJvaA0F5~(&mrs zd@b%z8OLhzFV#oN+LQL<{Zw~lD#mup{MZ!-pGXRQApkv2Dm^mr+6jNfZlTiql>CPa zJo}^Fgr$@fNu{j+0Y02USzM-;oZ2Sc!lkO&DDXZ>x+%_~`Yx*=W=VJo5CeLzF3f7Y}A^CZ?EUpc-J9*4UTwOn$W6MLz* z$xL`yAItCv%3=TEu!@*nhEBh|Q1q}mR9RPdzqsK#eB(*9AYgQ;?<-2zrr1DG>yz!( zLB-AQ_*M5e!)eWxJw{ER&rf~NMjLnwbxYOo0l7vdn7Xh`%_i;#vSRqu(jDZP+O_~{ zjjd}W1tvdd1T{|e53Ie2^s6-$yzIUidvv+%*!Q*omll!u&2v&_5OXFuxPTn?Kc+h& zwoU8aFzrRK;f^gy!lRNlb>ji#RzCkf99&FDFD9G9q{8gVsK;n$6+Q>E6IEe#`ZcQ4 zX6Y0XG`jGJOpvrd0>lLQeMoEgja!&@)HG51ClnK4PaIGflpm~ZBKIRcKJXv>jGwZ> zBuCm1Ms(7XCNr1p{a28@2Ki463YERYPm=#aSy}%PBwNKdpI7_~&11pWRROHdTPsY8 zk?KE4-T(n8WSY=uqW52+?PfthMADk1cD%-atUXl*d{nHqSYh??JC&7C!8@uGbC2rD zmG$zUrO&sr_MV9Fn3A2x zQvV12LBJ;rU0ZNi-o|I;VnalSQqpXxHTZafKa^*pTbV1@T0!V~I&seGmHat4ClYX!KQguSJR9nwRq5f>%ziE!*xXkN(Agh=^%l?f7$G0FIRURBFaMDn#+PuU?Q_$L4gFi&to zdZ`-=tJrllBWC6W_i3WD>etv;`Gdl7u~+J$M#@hO7+sC{$)+A=hrf1f4T4W&f5?Z-E}PuoxD;>#aP)Z+Q9@HQ4Ax zEEXZ+4?7%5LO=YvCiYa7;;#-cL<_c}Uu*0*>}2H({0`b4X8eztUAaiskl%X0V5M%n zc#QWya?d2MkSaV@DI^ppI7Y|2xE>FPd#96>lm&J)j&)vgpD@UFEc2B%^^}aTWq(-Z z#N__M*5{8Kk%NgtA*6(oM!6b#@~?l+ixB;};QcjBC0f*y@|>9w*4WU^H`0o&`i4w- zVlEUON;z)6ua@qwrq3%NVrGRVak!7>3r4g2%;Vn*Sd4b5Bp($DC!e$Kmp5Zpwe`l; z5Hw{X5mT=%>J0F@2^=Q-3X#bPj^_ahXQ3Kj|MG_7l%`P6X_2&Sji7eLREqgPme9sy zGhbu;pMbDUuadM+nRv0Q9xI|?FzK%tZ$pkXN4^=3v8B^L6S!%3w@CE-Ki#9_`x9BT zx9u#*fiwyE*Z*P^G=h6873ZR>F|p0-4IUnOLeYLL1_^%0ce3E>ygAWu%l-4}C6s=BBKk)c-Ady8n`mQU9|MH|feXcg;{VMn=79-O+_q zfdt?URh2tr5~8k3FSHM$X#IH_*1ks?zwl?=)w6mbnc12gL|+-XQBq)BRsC|NBJ8-~SXy?ZT8(M{^h5!LEca4|gE1HH zcleW-t{@_Z)=JHyk{en|n$zIeRd?=sh-!GfivF1Av7;jU{lBlq_u=yiQux75yKIHE zJ(os#2{MyILNbw3o^I`cJ~^2W1@iS4EKy&3jnz{pSURn&(B@UrPUZEO^-L4`8SgXn zsgS4s#aSb0lONt*$ON;IK*m@&LaIR(`yv_?Gb6RM!; z?kxMf3Zs$#y4M)bAzXDa+NIoaZX0Q7%jPzfBc9Aw!1K&Rj}tZNiWGYw#??cQnTcAT z=;qR+Q7F$J{#husxfDpZ=NWs7vHsX6-6R2R~``LqcQ`Vr>copmPk>3v2jt#N?G-CmD=ccVk1F;kA!8f`uTU1@DVaK z$h+6NyuVbs@v2Dxx)1`$K~dH^+}|m>1RR(Xlhr0dfU}x^78;E}{!!=Rvd5>nA}Je0 z$D=7{yy@m29Z6T0#SfJ+^F)+{r5M${d$nsX!%X;;;~Ja1y(9hk>R&%|kNmv-pb#~0 z*zOi~VIKwVCGb!VDwb?TONeFu9iH?B2;fjq9R{C(qjQ5}W0C*9__5%?V)~Sl9;n?D z#O%5Cf&c9u#DRYT0U*sZFoiho|K{I6BODB{f%xzvr29K3h4o4C0oxAg*kAhs|DDYf z1Ni{rsaE00Z{z>ps{a4vS-pQdSzE3kf;9IpW6|^>yvpCWr8&O|L1P*hXiz9n8m+C{Wpo$|F=r$Cj`eNcufH* zF92Dfz5$HVm(sq)6xQ59=s*0mUe`v@C%XuTKKj3X)u(`$CG?JvdQblvy0;Pn+Jb^H z1<0V__s`AkvLI>`x~Ite7XFs86Yz%er^w{a%^N!p;W|0< z0#fJsugrHfK-)VA2VVYmu9^u@>Cy{ut;gRo)!?-WE+WBqe>E~ zsD&j~<`^>|egu+m!IH9WbiZ=O?{1OU?a>a9&eud@)s;iGf!ID85Qz(Fgvq)(b_Q(&>;Q@0VTx1 z8Yb@a&$CggAN4M*%KAzZr05bS5eKBg)tQ`br#%btAKN7*pz%kycXz5<}k-ais$SRXI5QC?(J4jhPxS)qckV16i{wzp5wrNS->T#2Ds;r*FUa%UIc z=9%t_32xQ!lD}AZ5g@>T~9a=twzvC;Q=wIe2> zU|Z#HQtzsR&p<+oQ?i+(oFfZjcT|i`ZN)es-PuWsHQhbrP9>kvN{lNF<|B$rRRCVg z?ZkD@K#GfZ3>CByH69eBGI$y_Ge*Yn4BRUJeHV+4L-AW!beO2%8eX$Xb=hfAiM)~6 zs9`=$-Hg!jR6#e@->u5ViJ3J4hg8d?0y!i~6)C(_=kY-?bDk;Tf`ejySRA3dnBv#- zN(j)eiVmsu(&%$*|M|}IO!<_1{70VJB17*(^3l3(&QZNh(G>&vl zB1r42e6{~Pwu!NpD|yIj+Al+~j1@b~iM4E>wQDbHX3Wj#qPi$pMk2z(Y;ZA5U zo_e!f46(4d2TcMUkztRDM2|h(-E0e2m<$CS*(DYoUq)%UCB5CBWZIR8gTWrUiVpHN z)B=Fi!=j2CiJ6EUmYI^c`Dd)UnLVnhl8nfpVIrpw8=(#s0S}mtsy!iH;RId2c!`V; z{msH!9lK>Z2MgmUq}6SSgUsZnl|UF7Y(yjlog+`Oaf4TYncpg;pBfa;1+qb7#EN35 zD~*W)CnRtHdyGTbOi1VPy?Nn#aG|!bh@6PCF1M;R6QQvXEo2puB@<-95kb_r^(f82 zc-iKnw}|$){{H*YQg|Z=$zb9{6OnZT-`5NO^%f#VA zH=^SM^{uke0u;ec1Z_E^s~e3(FQRi=MC-+A*+a>@3=`Wp;qFwe3s&pMtJgz|`-Lkd zl`0|W1N}9HI+48*v|RVnu4U0)kJnj~l++y)FvDT}4V-Z1%f&}2hb;n*!&wN492k`6 z=>tW+u@uS6LEx~(UTDasrYR({!%~|ury@nU9RTG$2FC#s7Af&N-}@{+skwfbuqf(?Z>2F40Uh^S)$688u&0{xW9nde8UvKAM1l~`LE~fmaaGh9 zE2l46jz@3bPT{RYCr}T@6P6^6U?`P8>egI|2$sb=6{}?8v4V}UC&GU@JaFLd@&H!< zb$tBHMlvNaYyTmA`WdSJ_{40Rv0}CM=Ly*sV&PCP4;s0ac^7g`ODIHRUF}N-E+$Uu zj=jYCwh>M8t!7*GY-^6HY7ucuj^v7E zggC3XU6Zjt$>#^*Q-y|keX?X@6SNggjZRMLoSeLMgAzEuX_5p}rIp!e1)JM?N#(i7 z`KDEhD>xfyjw;18D>)-bVo{~4ErhhICqJWC4U1?`RGeJYAuGL(dqsKMmctg0rW8xHaQ)ECi?w5$RZWnR42GH7P&7O#pqPpN25dpl^*9Zf5A zI@groS~NXq7T@WW={VCQZ$OMY*K8qKHrq?I=-?-hTODx9k=NGMQv%>Uz+=v! zrBn9cCRvVJ;*>*iDs3qL1nG#CpkuJ`kx83{SoKDeqE=>M_K4HaPm7S-kI;sD7u_O)_hCRDOBM)d!`2RnqL-J^LbdMa zi3zbFPE3|cZ6Ig;BT=^gy3t@$!vizH{nLBqIb}FYriStA?+|s8>N@9VFw7oE6!KsS z)theom%+k;e~vqFNfW|U3+7U7niQ*@)Ig$YtSG3hTlY zb|Ruza3XYd0VgGqI2fB$n6E)*Ci9O_+1t5NzYj_pDzU&OA?J%@H0F=3O9XHt!H#~= zTZJ~S)cg@MbQPd=aD;-V#N?Ow$fYSiBE-nw+mCDaN=J;kFy zksd8EL|w2x%Lv>bqQnZ?nM>;Ba8IK~O=dpc;9{&>axa~r++!#APgnW-(kEoU`$BT{ zkyW2Rak02m70Ua|A$JrJqGcx)0|?>?J)Bt>q%6CLZ_=3?PgL+!2`!YAPsnqP;&K<4 zUI2YrMUol9Nn|ntqDV9^BLqmBlQrs~run^KeTl=A0g!aA8W52O4`*%w!E!ejSnxLo zqPdt<1tnRk4yC8w)MiK#P%ZFgTZ=&Yi=S8f(FKr>oeJVVg!hvWC+TqM#}%DlGHRLi zs`S4ETp62!Ct%osS8x`H++9(D6xoP!1ovN%%a??Kg{}BqZY9;d<8)~1#w*B)V9H)l zVA~$Kekw&l%LQOvs|Pp zLuzrNos7<^4qH%-ts^(gyY$*rG~IDWqf%BDP~4x!IthS7`Lj5k+f}CEI0lT9<3kdt z$`vbvr&6x-f_P$ad2;x6fx9}33twC$d<+@n(6u;+N^eCqH!2ri5Ny7z9T%ZOhW0+5 z8+S}e#*8N-gyX+XEtmM=KfDrgoll1l7`8uTd~^Ka3@Tg&9~k2D1BqM302?8k91~>MfwTC_wiC)<9y#jZ{#sVtQ;P!N;JutqCP-voU=|wnrn&~5M=H!wb7efrk!I@`Gs=zNL37ZKHs=g@qo0HvX19UC>c%8Pgv|JUsy}~-+%R8B zatqIaoSmRb895nIU`{BwM6X7c-#Tb=7Y^KCU)yATds}NpHhMyhJT9c)|C8y6yU`ag zpLV`H(x154h*?LZgQg9{@3|=5D!gGXLrHJCKs%5^OsgfBe|BH-$9A)Z$ zMUsc9#}7X>f7JdbrhRTP1XW3b6-}JdY(BVVGFMJJeiybsRt9D0tOWvgU9su~Mx)JC z<=abxs-5eA{lP|)ZgBx)U7L3iHw;!~mdv^CMVLd8ls=52k0#*Kw}9c`XfY&y2n z{qim#k720|MM?xy%Q+DIOxo=5c24CqO@mrfnFt!o`CmLWsBArO&VmhbxOtVoI5ce= zatN^w4id$zVc}ZNnAKtSU;tkwP(gk8fsLt&e0o#iRPLFwP5neHa_^6*g=WYo(HVT> z8AbRYW0CUFf?9HpqTXJ9NDRf%W^R~>6O8FWwMH#XIi$gU_Ja{k)&c>s0&vJSF~BFk z(zr-x15778P}O07T%Lu102b7n9`I6V=cllnvN&-zct3vSYKl??omGub7CTg~G=gX~ z?`zr4txmQpZO&GScv>AFjf`J==^T1gl9^JVwwUioG6m6R2uJzBgc6xzN<#-ub7{7U z?JF{`yGUK-O!gSV*Kyvs-AO%i*% z7M&tjjtfP5QeIK19HF{-ap1FR>pK)am%MK-YwH=FYTgXjc|(`^F<8OZsW|rySV_#u zW?%ArRI+(-L0yvxoAva1BH{q~YF3d5Qi<_Ec67ZAHcPB3@b)Amw{0Aro2fxLIyK2l z6FIreX%N17y?W2I;$rHlPY!Dmi%CJ(wqZ(mwoXRtcy-;N9#VOAsnm(JvaJ)4@0#Bi z9C}xLb-}9a6~#v0Cit}t;agCoLVHkuomia%CXWz}Xpv2G@e@|IBSGJeJu>KKzEer2A+}Lgjby#JiPdthg>@1VL1$98WW4Or(|Yz>$9cV25>FD!=!-kmB%gH?>n#^=1$ahNl@M3o{o~#Of9={ctvDF2ME@dH8k}2!Q z`p%pUl|tlMFk>Di zBIob&sj$YYoZ`dS;ckHh;fMI1r)y?SEKEKOlxEQ!gryMfPM5;2#P}|NEi2igRA};Z zMB0+yGR&O_9lr^U%;}yM{cb&CEM87ncq243-?ZXzjd->@Cen3K<^HU$(c zOo5Q-yvZ<8J0Y~a#0j{oN^6T(7H*xB|BRCCvf!U@C=f9UCHdcj8cBtU%L;G=7pH{7 z%v0T2q-qHSW5UtOvTlFlA8wcBbrrVRPvaBwWfL-(tHbL=s{{Sf6j+LHPxLt(wxjW4 zP5AbW;*W%|fO1I|T1z)vAOCB-^>SkggjOk$r@jQR4j0R)n&%&g43!n;eAoi1jb&j= zR>OSrAb0FJHc`%nH7TWMcmOD%{P*XtfDZDAv+taTQ~WS|NSbtY?xY|tOE@}R5l3dT zXjVoSufrepbcQV}zJ6ZHru?nhdQCy5#ARa0C)b4=9SaT>Ux1wxGUI1)5ru5PA@m<8 zNO)N`;y2=td=?^fi6ISjK^2n?YxDAe;vsb{#~W$mmT?OnAwkp=Bx^*dQ^ukISdDl; zm{XvZcAhlk?xHxgXHn$X0Thy`qWL&{Fq+F*1gz!){U(7VQKpogu+x63SCp1;Ob&-z z)ryQ~pO65jCWsWu_JgFq~h3g)rskoW`mwqwQ1o9Lti{h)1&Q z$F+e@$X1yZr_iF38r2@WL)f3JW1NHn)We7(?KxCU>5mMWUE$}L2d3_bL-3umJc zVIpDua3Fysxw+Iss}Qro%PI@?9$v3O!4;38C&7>=1UahX9vh_?n;TYh>A94Uaw}2$ zB>nBA=VR-^*2X#eh#e?H)7rlc!a(dK=wnm1l8ZUael#D>y~3(gSp>Dd;~-^Cb8FJo z3G*_k`@c)u^Mat;>!c7UZgu@q-RQa!a+CZ%heTM4s59VcCQ#}$L$F+%g{rC=?%Q%VX00%Y>H zNJr~GS^WtIUA!Or6VN5r1|Q}ktfy*F$c7zI0Rxs60@|W=tw_}rY;<;o4#+{(nEo~} z0Hx-WcxQR2f^IC0m(QV}C&4atci}G7J6gNcBxkn9S|!C>2kmH}jhF1d;N#yf1GKQ*B}2btiob%pk+9 zEioV4&ZkPd01@vekaVwqZ`58P&crSb>9r2gOqj>YzUYx96t{l>YSU0NmYjA36{ zcI-GKfHtBF1F^}rdctFk<)`&V$??BOjF7%O>(K|rf{``lpTd8ixH}bz%VQl#$nt z{0l1O0VtDaeozDNFJoi_&`%d6WHdmU&VO+z{X76V!m-#dj{MigUKs#V+yEXL`d^d% zAfQQ$8B(ZR1}5>kXnsX-kBlQa4=oJ zb;g%o4-C4WNo+OweT;VRso|IYp{JuQ?c{4pX&zCv%=cZxEdp4J~TgyFrvk`ke zG!uih(=_6SV>&Na;L=mZwdkA5#7p+~wdAdZu2AQ#_XE#RiqZjhOW4{0daQ;*K-&A<|9YQY*qgp-41iX^7?LT~n9Ft7#T7P$+iWiD< z`{7N3H=DR%4+US~?bXtZv^Smfh16QL_c-^^VO8ZM5tSVyN1G)%8E;wC+s3{@==pxI zOl9*#M4-{-SNzVqNhkUEyuZ5>l9z`cBqJlWD}XoSy65d2eldCmufZB3Zr&xv!snh7_2WQO=ye#@zQGl$s9f6P2l3QxcH_nATNF77HLJlLZ+y}T-@t>hJEe`yi zSI^LLJ^F*Zt4~ij0c50GfyKo?t!&MNkjCV9L62^p2KIByCZxX@+{l;F4vR$#*|bF+ zPJEnB^RH)gSZ!A*OkxJ}8Jg+bGuohhc$>Xty0mi0HU|tHW(cdYP=DnfdJyMW^^I3< zkT2IF3*d6SMK6MbSu>{DytcXrl|2 zZf*U-$yOl6pI@=2sS&YZ&GgUzS95Ru6vy^PdnbfIfP~fQTUz1L?w+vCxRyl=s$9Fd2@z&b3HHh`fV?GZOXi;4P3zKXi_| z{b%M{CxctnQhL?63Ek3dA`}267I7UGdn=y%2J`QGF6h7B{q5LdgWw%}+}!aE%jfU& zP_!hMh4<6zXGT_*P5wamO1se|kt$2rHOC=46@|9|+{&?0!fSinC4H)B z&`w9j4VLCl3pc)9{hEKfBh9I1GIlu>Ppj5wO~lR3%{VvM_B30nT5Y+=eE0YWS$~19 zpPhAoh7=cObXDnhyA}b6-fSLo{ZmQWN8u5U^Tu_#BUN9|%`zJ%6hfY5=f|B7-@kqx%%_tVXny$F`TO#Q>}_axDL`g(>#ugv_##6+e8Dfn<0A6AtwE^A9QP)u z*@1!UxbCE=X`S4ec;akUQ!5sL3s zYwJKCe54(e_#O~cNh!`@_RaIskJ=IGmRB{Xd^dVP>sHZ^(+s?I%s~FUk0)|Gh|glm*oNJRw_8ZFr2NSBU;>wSSFo=J>VQzW&s zUzhu6w6xa~r)#q+Tu*6BShQ8(tWmL>n4uUpOcs=MJtxrGdT^l>7o3a?Ay=BZ(aRL z(NEiDXp6@iHeTCZ;P0zh{17XbW7LGe7?to1|N%_a}7a*S2q$|pEJ!wXg`3-kQE=t= zxRX})GxTRJMbq>`|fK|9@*TB5?=MLKt`QW2U#(T7%-KcQ}%&qfGbd=GOE zGJV^sYhB_k9-ZwG%mrw)3PveO4`h97yaLvs^p_8xWS~>W z{;KImrY#*Yx23_1X`@JHpGwiaCiNz>r?2kVv2PrMyn|U=NN8ty{!FwjPdLb}sP~bd zHEZ3i(1acL)o+==Iq5b`{*Z8i5_eRvZ(456f&_q3^b_ghm&<5dGLef~DO%7MOC#un&+@r3uEY1ZP)I`FP z814xw!7H5?aD+7*0r+6}VbY5vTc%fh`^oZ~vZbQsC4MN{q=Xr{3H^KB-aemawTHcT zLD}M}!j?useLQ#6Zw zSy*Tnf8)MO-xHJy)PtAi5a>|hHkBN8<4jc#k_5OjnGZthT8yZuD5HGawL(!A86aJV zg^UIl?{F*Mr@Gtt&d-xocI^mDL*7;8ljC_kKP!kGEY?oc(}kmls1Pc2K}=8j^5IV%Kz9 zKbb2=q##AFF|@Au9jW~c&oSZH3maMpwww0Znfa!+{7rDHO90fS8&qr49!NV=aDK$j zy#RFbTib-BH#W9PuXSL^c)@Y=uSQxf*hCnpeD(AMViX9yAg;CyXyCwD?-CVbJK=Rdtb2CePcqE)t9s+u zAE0B~Qe_z>rB^Mr!Hx07L}+PeN}Op6``v-v5Ti?y?E>@^vOPE5#N|#{v0>prc>f`B z?IoO0{b7wKurGfoNHw{Qn^LT|i$TY^l?a6OM3~#PmnBUkG3}dw*5L(LF?Z6x$nOr% z@I2h?kmFqm7n-451t2 z!x5X~D!6HMGPv^TJ;ReAKL&s%KX{O0XZaVuK1c?ACtWHeW!3k=2$)~02*H)H>UdH? zkjdneB;Unnn|~2v{Jo|_Nt3n6iWrNWQ{-DsQm_qG_yK7?|Deqh?r8+yRB}jE|1D+$ zlyl#kZraR)x@&2(a(_g9$Jd6>$I^#cYmjy)yCrgfF`F#zNI%0@tNpnBSHOANy8jsm z{G;Oy#Jz9xDB`5B2oycs-cfc7=b(flP5U0qsKH4!)Ry4YQn0~?V`_n+kN>;Huy;a{ zqDI91YMR6`wTj#?1MIJA*gE^XY@8bsQ%JM^^il+M9A`fiXkspmc(X-jPEO*XDDuOD3nyH z5`2TNprBA?v(9(F)L=#62f-hCAIRE&}e>(d9Yc6Bt$>)U}5o)7*!*-Y;f{s5IQ~dh0SACMjqZm$Y{40aA2Zb zI5FV3Yq0W@!9nN8@-myory~;^X#CC6A_ccVIvcBUR=%ukw2sEccf;&ioL(85Fpm(? z3k|M^;~ey1TjukSgCMr~Cnp4%w({ef*M7e8t%_#SV-h)hw%=G7r_#rHXnt`%QLo;4J{798hf*=W*w6trNJz{d<)F2CM`F+(fa6s7w!jS+C!GrW&9DF=b^757A-C@B2{Y+wR2&+7o| zjaFRGGHYvmqe)??Ay_kV%N?%Zq^=zZlj~yc?>rmbk<}Y>$2O{!5-Wu~ADpVmwH^EV zIi65lc}2u6!h`b1NTnI8pS{gf2CO7JHyhR;ohj%?B(3BuT&y(iX5^`Mqcmqsxj>qH#USE)nFdpVmE}Cuj91hUpN~P1q8BwO7vp#!H57 z7{`5GE z1&i?;)Fcv@D<}Y-w-$sgU9R39(8(UJ2F?P(Ra;J8EA#=I^mQ@XV<_@b=1Wq6P9qvl zfM4xrUvG$>-&jcl&ly;#a$<32z>ZCC-=dIoVb=PC3K*ZCzHE#l9J3@C?gq7@2^wSW zkTH?)aLW>@D>gq8x4e6)^a{QL-E2)mNS&RBoMXg7clk>D3FuX;A?qaaUhK+j;7pR* zU!y*_T%miJy`K|;uKM|3(6{anU}oID12-Y3?VB7zAk~=_1*7E?>)o0VZ8b2gyU0Zz z7xR#|dwfqyj!YwG@|Ld0kL|PG3YKotOBITC9koTBS{w0eq5CSc)pYFIj!Uk|luRrSASl8eCRv}3%g=(0dBWvWO9J<|3+A&C!#_AS&` zYF82aZKDHu!{Er&<<+O!)(Go&v-Vc`D(4FZ2V6zO5VI0!t4Rb(xg zpG=l#NvP#fCL!{tX@J!nnX-NKhysBMQ>MX&h_+et3*TLVr-NRJ zEVCC5(_Ue4m%8YUuOAzTUzCOes?LKSeaasj!b_cVvwIt88``+fC_IABz>Tlcor6xU zbIF8Y?Kk@6-b-!NN^uSOlPuBqFnCDijLC_eb%PNc$BKc6DISsHpopV?+tp#fwg@9d zCdC3)pnJpUJb?H7mwjU#k(=S;M`x(uy1F1w^5yI@r!11pT9a{65fT57#;KzY7%lmm z-GStEbW(htvrx2CW^WrF@6v76w$q5Na*&1eL0o7u{!Ft17dKWQ-^dU9Pov3eubhGh zlnQ|It@bFf(z4S`U-{t}bednjOJ(BcwRwA`5aQ7GTI1N;6qDQDYH9;Y z9aBgJ>yjl$QcO$EK!qPumk(rY=9!qmVYSB7rrs+CTVnc7KYi|#2{k?@UedJb-gEhP ztt$v^0w&V#E!6wkJ$&n1mUCa<4+|E(I&8~2zxeLiZPRMr^_loZK7mhwdwjuWm<5A< z&5u-FomLlOB0VL08P8uqJ59O~yYUBs0^G~-$}_n@spIFy+V5k-5k6^!89&%d(Cu!o z7vq&)6;(`H_W^EyGabG|r52Q#rcdoMZ3-Al?)0&M9b1&4ON;xmmt#4K8#Kw|Q9KWQ zH#FnQ#%#KN6`y9BaYraT2l7fvkXe2?Xtr}F{Zwbi-1qM++`MFDKHJs#d38NugzqT( zXD1DpYx(f-*GM+{m3p0*RED~2XnUVWxn-${=&I0ol0&IsX}P5Y9{HfUhiR)UhyjM( z?6)iusPgfwlq#OeSMuX2032Bd_)Lg`G&9^nGolwGQ-BTK={LxjY4t8}gLoVlyfaU3 z0p|JkyA?2w#`U>r#TgZp_#K*kr6K!$UmjSFgq>-XUWeS=jG7A;gRr|&HQCTMLn+U1 zIKqE8IW< z_E5LwcLy$ZUamS?Wh*afqRYPV2#0yR7$;71oSSKHlZQxZi%LYtx1w=0t~_dbKEBqHCD8)a~5QKQI`5Fh^Yycl}^# zg3ZDB_WYEl*Q>k5;UK2p%TV(PRJNg)qOtJ`^mwQHcAaz0pt07O~ z{S5}%YyQw|N6FJoLyG2&HqbWS^JCC!;T7narmFt+aAz2o-CXap#iu(ivsA9O-v3!K zcPALQytkeX+Lrmc)flpgwhtAUXhaPal2Bax*UyN4KHaPDy87e)A;FQoE9P+0elGu{ zE$8>y$+>{UjqJ8c>sj^~z*F+QWq^h0Ri7n~^B()dE&lV8a2?bRcb|M-9<=k2?<~c+mf>L<}1?ZJ-{I$SP6pmHd zH!&AwNYtT`@xT7m8I*!iTxKck;#yN~DeFn-^d*OdLs@S)0r_ElXgzI4sTwKuCqX+G zLT&!P7ua@V;MRF59{_$>-4N@wI)?o54#CU9_9#6e^7-?}Ca%}Rf+P`U2EyL9FOm}Y z97ATr6AR>#7CtmcTWzqb=8$&x{e|}R&606zpPuJ2{t8Dnj+eVNhX&!&VQAnSrQSmj zrZc4DLcUa~bNjwp&2F7yV+iSZ3D!5w{3XsmQtzI(kz0KKC?ZgFs+=>f77sR`CRE0C zDJZcmCL2_U$&0pKJG+abA417CulodrOC3$bY($%jXDgV?$PY?#utp-J1mbxt1FEUJ zX;`@PKm3eZ42y{q#!^n*XNeiw`zwzh%$^#Bju%cQ9k~!0Asiu(qS%iF2+Kb_I4JyfWB8zme=2yMReoG%eS=i zWS{s_RYNxLT!m(!aqaWlN>GB9u_SHd(XJ$-i(9 z@wfAnC=+EBju=x0Hdzt+d!1_Xb2 z(j-(c#MqCP&$_7LX9hGMG*i>kiq4tC;Cnd2sVCz|&{G?e zIW&T%7r!*>m!%NnK}CY=MRb(%4_9O~Kvd*i?~y$H6Uc&q=EhQBBn5E3Fb55qK#~0F za~iPA#C?)rX8pCaX$SM$TEHmcy=0X2JItIk;F`9Myqp~{C#$-*EGiJ1 zRN+p2UYdngDd7M#BkCRGR<&pnEx(FK=8o?q$ZE_O5Y;EZ$0Tbxr7#z11@=xUXwnT6 z=BE4XP_SetMNk*#?$qTsG|WA41BX-#6z?5E(bP4g^n%63YlNe|k)CU*$Mm9!T@zgu zbrlISAIQ+~N#9^cee}(5QkfR6`8_zdttHuFsw!L&$6&6(l~zz=lzUf7PsOWLkPAto zlo=|UjXMMWYi2vgby7;M0^R63o}rm^neOM_JO1ln)8e9vTCLv`c8dzGRcIR6#(^VW5W85r_m_%w67Dk`Ynz2caa+3 zaY+HK3+@f&7JY(;{}*v0qao(EtTFlF0R_Wnx#;#klAZ;KK1N5^BsEJ6toYWsV~9?f zA8Imrlu%nFke>0TCJdps($TGdG*whh_V<&`Z;y_V5-C=zA2p><(6U97pH7HUE~R!L z4xDR4rZB?FVxtOB$+Pi`=({flv(i?i7nG8%U@ZoTH3VsC*E;*JEh82zer-{6YZX~mNHww zDLb0zIAzD(&|{P5*uJO{M`$Y{O64%K&$xtOAg|JlPKAD=Q;!$m`#o#^UZAOV;h5PH ztJ)@6Lta}sQg4YZ*rT?nG_RPpR<2oLd7AG!2!-5BLnCCah0${6XcC{m2Ov4@9fDTo zNtJ}GLLRk7kTUT1u)Hs~Aj0V#D_BEICtmV$Oil1XK`^i0t%w$0=MIzC4ApVr}m9!LoNaX?=4k|uZiAupSV<9M%|~KR#d&I zsmzHq5Vdvw{5@nmr#;wx@=aPD;%=TVIuXkDbX$#l1p;R1fTjHu_p|%&TIrzmxWES$ zmXUI*ZL5&N0^k=degyqs$%(jT1j^a2#bkY&@t%Yy_q+SzF`6&pV^*@dVBc+}FI44e zL+{Cd?&mdcm^TLvhm~}}V&1#hqpOo;f9qpV?N$48Sm{4u>r3WM&x;9X8)(wde6&lV zA}qG1*)m#YS6tQ@JPmEI66AwJ15`B9$n^~jeM?7$-xr&1B~kfR7~8$>Q}_F#=kGKY zDjubrRD~F+2;7{}+(1YUOK0%Ej0r;EpK+qlDu*T972;+bq*tEzI*kln9nrqT;g|zJ zMBbh3dgnO8x+LL-QF71*WPFK9zkyk|T+QkI&f<1fA&;MQWQ=bBb!FJpI5B@njE62w zZ%XMljZJ#w{2zSQvuM_04$GDByaKkMdBNs@56Ey9U(pDLYre*{AxHu&6`6$$qO}`R zR&bkZ&M1s1qcC;raW%Im-&hVT(Tk;GNi<6S6{lVZc}kKV2&TzhlVm#3@>dSMoMlGH z15iXis>JBnUpQg3*gVJ&EPv5D!JuTVKw%Sa6(UKM@t~u`6PNvM!BcPLoq{QdvW(QOOY&R2)VkN6GggotJ*nZN&y!`E{a%2q}14sADw2e=iid* zE11>17>3?Ldv^h0`H&${h;{8(ba!EHvDFd+Z`7drF9)N3Lr85B}qQB$Jh! z`;J`nZo*=tzxUvv@?rbKVPNa6e^P5<9{j2HeAjjU3K_Oj$RutP#bMz}&y&*%RD DV4kVw diff --git a/doc/ci/services/README.md b/doc/ci/services/README.md new file mode 100644 index 0000000000..1ebb0a4a25 --- /dev/null +++ b/doc/ci/services/README.md @@ -0,0 +1,9 @@ +## GitLab CI Services + +GitLab CI uses the `services` keyword to define what docker containers should be +linked with your base image. Below is a list of examples you may use. + ++ [Using MySQL](mysql.md) ++ [Using PostgreSQL](postgres.md) ++ [Using Redis](redis.md) ++ [Using Other Services](../docker/using_docker_images.md#how-to-use-other-images-as-services) diff --git a/doc/ci/services/docker-services.md b/doc/ci/services/docker-services.md new file mode 100644 index 0000000000..df36ebaf7d --- /dev/null +++ b/doc/ci/services/docker-services.md @@ -0,0 +1,5 @@ +## GitLab CI Services + ++ [Using MySQL](mysql.md) ++ [Using PostgreSQL](postgres.md) ++ [Using Redis](redis.md) diff --git a/doc/ci/services/mysql.md b/doc/ci/services/mysql.md new file mode 100644 index 0000000000..c66d77122b --- /dev/null +++ b/doc/ci/services/mysql.md @@ -0,0 +1,118 @@ +# Using MySQL + +As many applications depend on MySQL as their database, you will eventually +need it in order for your tests to run. Below you are guided how to do this +with the Docker and Shell executors of GitLab Runner. + +## Use MySQL with the Docker executor + +If you are using [GitLab Runner](../runners/README.md) with the Docker executor +you basically have everything set up already. + +First, in your `.gitlab-ci.yml` add: + +```yaml +services: + - mysql:latest + +variables: + # Configure mysql environment variables (https://hub.docker.com/_/mysql/) + MYSQL_DATABASE: el_duderino + MYSQL_ROOT_PASSWORD: mysql_strong_password +``` + +And then configure your application to use the database, for example: + +```yaml +Host: mysql +User: root +Password: mysql_strong_password +Database: el_duderino +``` + +If you are wondering why we used `mysql` for the `Host`, read more at +[How is service linked to the build](../docker/using_docker_images.md#how-is-service-linked-to-the-build). + +You can also use any other docker image available on [Docker Hub][hub-mysql]. +For example, to use MySQL 5.5 the service becomes `mysql:5.5`. + +The `mysql` image can accept some environment variables. For more details +check the documentation on [Docker Hub][hub-mysql]. + +## Use MySQL with the Shell executor + +You can also use MySQL on manually configured servers that are using +GitLab Runner with the Shell executor. + +First install the MySQL server: + +```bash +sudo apt-get install -y mysql-server mysql-client libmysqlclient-dev +``` + +Pick a MySQL root password (can be anything), and type it twice when asked. + +*Note: As a security measure you can run `mysql_secure_installation` to +remove anonymous users, drop the test database and disable remote logins with +the root user.* + +The next step is to create a user, so login to MySQL as root: + +```bash +mysql -u root -p +``` + +Then create a user (in our case `runner`) which will be used by your +application. Change `$password` in the command below to a real strong password. + +*Note: Do not type `mysql>`, this is part of the MySQL prompt.* + +```bash +mysql> CREATE USER 'runner'@'localhost' IDENTIFIED BY '$password'; +``` + +Create the database: + +```bash +mysql> CREATE DATABASE IF NOT EXISTS `el_duderino` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`; +``` + +Grant the necessary permissions on the database: + +```bash +mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, CREATE TEMPORARY TABLES, DROP, INDEX, ALTER, LOCK TABLES ON `el_duderino`.* TO 'runner'@'localhost'; +``` + +If all went well you can now quit the database session: + +```bash +mysql> \q +``` + +Now, try to connect to the newly created database to check that everything is +in place: + +```bash +mysql -u runner -p -D el_duderino +``` + +As a final step, configure your application to use the database, for example: + +```bash +Host: localhost +User: runner +Password: $password +Database: el_duderino +``` + +## Example project + +We have set up an [Example MySQL Project][mysql-example-repo] for your +convenience that runs on [GitLab.com](https://gitlab.com) using our publicly +available [shared runners](../runners/README.md). + +Want to hack on it? Simply fork it, commit and push your changes. Within a few +moments the changes will be picked by a public runner and the build will begin. + +[hub-mysql]: https://hub.docker.com/_/mysql/ +[mysql-example-repo]: https://gitlab.com/gitlab-examples/mysql diff --git a/doc/ci/services/postgres.md b/doc/ci/services/postgres.md new file mode 100644 index 0000000000..17d21dbda1 --- /dev/null +++ b/doc/ci/services/postgres.md @@ -0,0 +1,114 @@ +# Using PostgreSQL + +As many applications depend on PostgreSQL as their database, you will +eventually need it in order for your tests to run. Below you are guided how to +do this with the Docker and Shell executors of GitLab Runner. + +## Use PostgreSQL with the Docker executor + +If you are using [GitLab Runner](../runners/README.md) with the Docker executor +you basically have everything set up already. + +First, in your `.gitlab-ci.yml` add: + +```yaml +services: + - postgres:latest + +variables: + POSTGRES_DB: nice_marmot + POSTGRES_USER: runner + POSTGRES_PASSWORD: "" +``` + +And then configure your application to use the database, for example: + +```yaml +Host: postgres +User: runner +Password: +Database: nice_marmot +``` + +If you are wondering why we used `postgres` for the `Host`, read more at +[How is service linked to the build](../docker/using_docker_images.md#how-is-service-linked-to-the-build). + +You can also use any other docker image available on [Docker Hub][hub-pg]. +For example, to use PostgreSQL 9.3 the service becomes `postgres:9.3`. + +The `postgres` image can accept some environment variables. For more details +check the documentation on [Docker Hub][hub-pg]. + +## Use PostgreSQL with the Shell executor + +You can also use PostgreSQL on manually configured servers that are using +GitLab Runner with the Shell executor. + +First install the PostgreSQL server: + +```bash +sudo apt-get install -y postgresql postgresql-client libpq-dev +``` + +The next step is to create a user, so login to PostgreSQL: + +```bash +sudo -u postgres psql -d template1 +``` + +Then create a user (in our case `runner`) which will be used by your +application. Change `$password` in the command below to a real strong password. + +*__Note:__ Do not type `template1=#`, this is part of the PostgreSQL prompt.* + +```bash +template1=# CREATE USER runner WITH PASSWORD '$password' CREATEDB; +``` + +*__Note:__ Notice that we created the user with the privilege to be able to +create databases (`CREATEDB`). In the following steps we will create a database +explicitly for that user but having that privilege can be useful if in your +testing framework you have tools that drop and create databases.* + +Create the database and grant all privileges on it for the user `runner`: + +```bash +template1=# CREATE DATABASE nice_marmot OWNER runner; +``` + +If all went well you can now quit the database session: + +```bash +template1=# \q +``` + +Now, try to connect to the newly created database with the user `runner` to +check that everything is in place. + +```bash +psql -U runner -h localhost -d nice_marmot -W +``` + +*__Note:__ We are explicitly telling `psql` to connect to localhost in order +to use the md5 authentication. If you omit this step you will be denied access.* + +Finally, configure your application to use the database, for example: + +```yaml +Host: localhost +User: runner +Password: $password +Database: nice_marmot +``` + +## Example project + +We have set up an [Example PostgreSQL Project][postgres-example-repo] for your +convenience that runs on [GitLab.com](https://gitlab.com) using our publicly +available [shared runners](../runners/README.md). + +Want to hack on it? Simply fork it, commit and push your changes. Within a few +moments the changes will be picked by a public runner and the build will begin. + +[hub-pg]: https://hub.docker.com/_/postgres/ +[postgres-example-repo]: https://gitlab.com/gitlab-examples/postgres diff --git a/doc/ci/services/redis.md b/doc/ci/services/redis.md new file mode 100644 index 0000000000..b281e8f9f6 --- /dev/null +++ b/doc/ci/services/redis.md @@ -0,0 +1,69 @@ +# Using Redis + +As many applications depend on Redis as their key-value store, you will +eventually need it in order for your tests to run. Below you are guided how to +do this with the Docker and Shell executors of GitLab Runner. + +## Use Redis with the Docker executor + +If you are using [GitLab Runner](../runners/README.md) with the Docker executor +you basically have everything set up already. + +First, in your `.gitlab-ci.yml` add: + +```yaml +services: + - redis:latest +``` + +Then you need to configure your application to use the Redis database, for +example: + +```yaml +Host: redis +``` + +And that's it. Redis will now be available to be used within your testing +framework. + +You can also use any other docker image available on [Docker Hub][hub-redis]. +For example, to use Redis 2.8 the service becomes `redis:2.8`. + +## Use Redis with the Shell executor + +Redis can also be used on manually configured servers that are using GitLab +Runner with the Shell executor. + +In your build machine install the Redis server: + +```bash +sudo apt-get install redis-server +``` + +Verify that you can connect to the server with the `gitlab-runner` user: + +```bash +# Try connecting the the Redis server +sudo -u gitlab-runner -H redis-cli + +# Quit the session +127.0.0.1:6379> quit +``` + +Finally, configure your application to use the database, for example: + +```yaml +Host: localhost +``` + +## Example project + +We have set up an [Example Redis Project][redis-example-repo] for your convenience +that runs on [GitLab.com](https://gitlab.com) using our publicly available +[shared runners](../runners/README.md). + +Want to hack on it? Simply fork it, commit and push your changes. Within a few +moments the changes will be picked by a public runner and the build will begin. + +[hub-redis]: https://hub.docker.com/_/redis/ +[redis-example-repo]: https://gitlab.com/gitlab-examples/redis diff --git a/doc/ci/ssh_keys/README.md b/doc/ci/ssh_keys/README.md new file mode 100644 index 0000000000..210f9c3e84 --- /dev/null +++ b/doc/ci/ssh_keys/README.md @@ -0,0 +1,109 @@ +# Using SSH keys + +GitLab currently doesn't have built-in support for managing SSH keys in a build +environment. + +The SSH keys can be useful when: + +1. You want to checkout internal submodules +2. You want to download private packages using your package manager (eg. bundler) +3. You want to deploy your application to eg. Heroku or your own server +4. You want to execute SSH commands from the build server to the remote server +5. You want to rsync files from your build server to the remote server + +If anything of the above rings a bell, then you most likely need an SSH key. + +## Inject keys in your build server + +The most widely supported method is to inject an SSH key into your build +environment by extending your `.gitlab-ci.yml`. + +This is the universal solution which works with any type of executor +(docker, shell, etc.). + +### How it works + +1. Create a new SSH key pair with [ssh-keygen][] +2. Add the private key as a **Secret Variable** to the project +3. Run the [ssh-agent][] during build to load the private key. + +## SSH keys when using the Docker executor + +You will first need to create an SSH key pair. For more information, follow the +instructions to [generate an SSH key](../ssh/README.md). + +Then, create a new **Secret Variable** in your project settings on GitLab +following **Settings > Variables**. As **Key** add the name `SSH_PRIVATE_KEY` +and in the **Value** field paste the content of your _private_ key that you +created earlier. + +Next you need to modify your `.gitlab-ci.yml` with a `before_script` action. +Add it to the top: + +``` +before_script: + # Install ssh-agent if not already installed, it is required by Docker. + # (change apt-get to yum if you use a CentOS-based image) + - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )' + + # Run ssh-agent (inside the build environment) + - eval $(ssh-agent -s) + + # Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store + - ssh-add <(echo "$SSH_PRIVATE_KEY") + + # For Docker builds disable host key checking. Be aware that by adding that + # you are suspectible to man-in-the-middle attacks. + # WARNING: Use this only with the Docker executor, if you use it with shell + # you will overwrite your user's SSH config. + - mkdir -p ~/.ssh + - '[[ -f /.dockerinit ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config` +``` + +As a final step, add the _public_ key from the one you created earlier to the +services that you want to have an access to from within the build environment. +If you are accessing a private GitLab repository you need to add it as a +[deploy key](../ssh/README.md#deploy-keys). + +That's it! You can now have access to private servers or repositories in your +build environment. + +## SSH keys when using the Shell executor + +If you are using the Shell executor and not Docker, it is easier to set up an +SSH key. + +You can generate the SSH key from the machine that GitLab Runner is installed +on, and use that key for all projects that are run on this machine. + +First, you need to login to the server that runs your builds. + +Then from the terminal login as the `gitlab-runner` user and generate the SSH +key pair as described in the [SSH keys documentation](../ssh/README.md). + +As a final step, add the _public_ key from the one you created earlier to the +services that you want to have an access to from within the build environment. +If you are accessing a private GitLab repository you need to add it as a +[deploy key](../ssh/README.md#deploy-keys). + +Once done, try to login to the remote server in order to accept the fingerprint: + +```bash +ssh +``` + +For accessing repositories on GitLab.com, the `` would be +`git@gitlab.com`. + +## Example project + +We have set up an [Example SSH Project][ssh-example-repo] for your convenience +that runs on [GitLab.com](https://gitlab.com) using our publicly available +[shared runners](../runners/README.md). + +Want to hack on it? Simply fork it, commit and push your changes. Within a few +moments the changes will be picked by a public runner and the build will begin. + +[ssh-keygen]: http://linux.die.net/man/1/ssh-keygen +[ssh-agent]: http://linux.die.net/man/1/ssh-agent +[ssh-example-repo]: https://gitlab.com/gitlab-examples/ssh-private-key/ diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md index 022afb7004..b99ea25a3f 100644 --- a/doc/ci/variables/README.md +++ b/doc/ci/variables/README.md @@ -27,7 +27,6 @@ The API_TOKEN will take the Secure Variable value: `SECURE`. | **CI_BUILD_TAG** | 0.5 | The commit tag name. Present only when building tags. | | **CI_BUILD_NAME** | 0.5 | The name of the build as defined in `.gitlab-ci.yml` | | **CI_BUILD_STAGE** | 0.5 | The name of the stage as defined in `.gitlab-ci.yml` | -| **CI_BUILD_BEFORE_SHA** | all | The first commit that were included in push request | | **CI_BUILD_REF_NAME** | all | The branch or tag name for which project is built | | **CI_BUILD_ID** | all | The unique id of the current build that GitLab CI uses internally | | **CI_BUILD_REPO** | all | The URL to clone the Git repository | @@ -40,7 +39,6 @@ The API_TOKEN will take the Secure Variable value: `SECURE`. Example values: ```bash -export CI_BUILD_BEFORE_SHA="9df57456fa9de2a6d335ca5edf9750ed812b9df0" export CI_BUILD_ID="50" export CI_BUILD_REF="1ecfd275763eff1d6b4844ea3168962458c9f27a" export CI_BUILD_REF_NAME="master" diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md index 3e6071a2ee..fd0d49de4e 100644 --- a/doc/ci/yaml/README.md +++ b/doc/ci/yaml/README.md @@ -1,9 +1,12 @@ # Configuration of your builds with .gitlab-ci.yml -From version 7.12, GitLab CI uses a [YAML](https://en.wikipedia.org/wiki/YAML) file (**.gitlab-ci.yml**) for the project configuration. -It is placed in the root of your repository and contains definitions of how your project should be built. -The YAML file defines a set of jobs with constraints stating when they should be run. -The jobs are defined as top-level elements with a name and always have to contain the `script` clause: +From version 7.12, GitLab CI uses a [YAML](https://en.wikipedia.org/wiki/YAML) +file (`.gitlab-ci.yml`) for the project configuration. It is placed in the root +of your repository and contains definitions of how your project should be built. + +The YAML file defines a set of jobs with constraints stating when they should +be run. The jobs are defined as top-level elements with a name and always have +to contain the `script` clause: ```yaml job1: @@ -13,15 +16,21 @@ job2: script: "execute-script-for-job2" ``` -The above example is the simplest possible CI configuration with two separate jobs, -where each of the jobs executes a different command. -Of course a command can execute code directly (`./configure;make;make install`) or run a script (`test.sh`) in the repository. +The above example is the simplest possible CI configuration with two separate +jobs, where each of the jobs executes a different command. -Jobs are used to create builds, which are then picked up by [runners](../runners/README.md) and executed within the environment of the runner. -What is important, is that each job is run independently from each other. +Of course a command can execute code directly (`./configure;make;make install`) +or run a script (`test.sh`) in the repository. + +Jobs are used to create builds, which are then picked up by +[runners](../runners/README.md) and executed within the environment of the +runner. What is important, is that each job is run independently from each +other. ## .gitlab-ci.yml -The YAML syntax allows for using more complex job specifications than in the above example: + +The YAML syntax allows for using more complex job specifications than in the +above example: ```yaml image: ruby:2.1 @@ -46,26 +55,31 @@ job1: - docker ``` -There are a few `keywords` that can't be used as job names: +There are a few reserved `keywords` that **cannot** be used as job names: -| keyword | required | description | +| Keyword | Required | Description | |---------------|----------|-------------| -| image | optional | Use docker image, covered in [Use Docker](../docker/README.md) | -| services | optional | Use docker services, covered in [Use Docker](../docker/README.md) | -| stages | optional | Define build stages | -| types | optional | Alias for `stages` | -| before_script | optional | Define commands prepended for each job's script | -| variables | optional | Define build variables | -| cache | optional | Define list of files that should be cached between subsequent runs | +| image | no | Use docker image, covered in [Use Docker](../docker/README.md) | +| services | no | Use docker services, covered in [Use Docker](../docker/README.md) | +| stages | no | Define build stages | +| types | no | Alias for `stages` | +| before_script | no | Define commands that run before each job's script | +| variables | no | Define build variables | +| cache | no | Define list of files that should be cached between subsequent runs | ### image and services -This allows to specify a custom Docker image and a list of services that can be used for time of the build. -The configuration of this feature is covered in separate document: [Use Docker](../docker/README.md). + +This allows to specify a custom Docker image and a list of services that can be +used for time of the build. The configuration of this feature is covered in +separate document: [Use Docker](../docker/README.md). ### before_script -`before_script` is used to define the command that should be run before all builds, including deploy builds. This can be an array or a multiline string. + +`before_script` is used to define the command that should be run before all +builds, including deploy builds. This can be an array or a multi-line string. ### stages + `stages` is used to define build stages that can be used by jobs. The specification of `stages` allows for having flexible multi stage pipelines. @@ -75,7 +89,8 @@ The ordering of elements in `stages` defines the ordering of builds' execution: 1. Builds of next stage are run after success. Let's consider the following example, which defines 3 stages: -``` + +```yaml stages: - build - test @@ -86,21 +101,26 @@ stages: 1. If all jobs of `build` succeeds, the `test` jobs are executed in parallel. 1. If all jobs of `test` succeeds, the `deploy` jobs are executed in parallel. 1. If all jobs of `deploy` succeeds, the commit is marked as `success`. -1. If any of the previous jobs fails, the commit is marked as `failed` and no jobs of further stage are executed. +1. If any of the previous jobs fails, the commit is marked as `failed` and no + jobs of further stage are executed. There are also two edge cases worth mentioning: -1. If no `stages` is defined in `.gitlab-ci.yml`, then by default the `build`, `test` and `deploy` are allowed to be used as job's stage by default. +1. If no `stages` is defined in `.gitlab-ci.yml`, then by default the `build`, + `test` and `deploy` are allowed to be used as job's stage by default. 2. If a job doesn't specify `stage`, the job is assigned the `test` stage. ### types + Alias for [stages](#stages). ### variables -**This feature requires `gitlab-runner` with version equal or greater than 0.5.0.** -GitLab CI allows you to add to `.gitlab-ci.yml` variables that are set in build environment. -The variables are stored in repository and are meant to store non-sensitive project configuration, ie. RAILS_ENV or DATABASE_URL. +_**Note:** Introduced in GitLab Runner v0.5.0._ + +GitLab CI allows you to add to `.gitlab-ci.yml` variables that are set in build +environment. The variables are stored in the git repository and are meant to +store non-sensitive project configuration, for example: ```yaml variables: @@ -109,15 +129,23 @@ variables: These variables can be later used in all executed commands and scripts. -The YAML-defined variables are also set to all created service containers, thus allowing to fine tune them. +The YAML-defined variables are also set to all created service containers, +thus allowing to fine tune them. ### cache -`cache` is used to specify list of files and directories which should be cached between builds. -**The global setting allows to specify default cached files for all jobs.** +`cache` is used to specify a list of files and directories which should be +cached between builds. Caches are stored according to the branch/ref and the +job name. They are not currently shared between different job names or between +branches/refs, which means that caching will benefit you if you push subsequent +commits to an existing feature branch. + +If `cache` is defined outside the scope of the jobs, it means it is set +globally and all jobs will use its definition. To cache all git untracked files and files in `binaries`: -``` + +```yaml cache: untracked: true paths: @@ -125,9 +153,10 @@ cache: ``` ## Jobs -`.gitlab-ci.yml` allows you to specify an unlimited number of jobs. -Each job has to have a unique `job_name`, which is not one of the keywords mentioned above. -A job is defined by a list of parameters that define the build behaviour. + +`.gitlab-ci.yml` allows you to specify an unlimited number of jobs. Each job +must have a unique name, which is not one of the Keywords mentioned above. +A job is defined by a list of parameters that define the build behavior. ```yaml job_name: @@ -145,21 +174,22 @@ job_name: allow_failure: true ``` -| keyword | required | description | +| Keyword | Required | Description | |---------------|----------|-------------| -| script | required | Defines a shell script which is executed by runner | -| stage | optional (default: test) | Defines a build stage | -| type | optional | Alias for `stage` | -| only | optional | Defines a list of git refs for which build is created | -| except | optional | Defines a list of git refs for which build is not created | -| tags | optional | Defines a list of tags which are used to select runner | -| allow_failure | optional | Allow build to fail. Failed build doesn't contribute to commit status | -| when | optional | Define when to run build. Can be `on_success`, `on_failure` or `always` | -| artifacts | optional | Define list build artifacts | -| cache | optional | Define list of files that should be cached between subsequent runs | +| script | yes | Defines a shell script which is executed by runner | +| stage | no (default: `test`) | Defines a build stage | +| type | no | Alias for `stage` | +| only | no | Defines a list of git refs for which build is created | +| except | no | Defines a list of git refs for which build is not created | +| tags | no | Defines a list of tags which are used to select runner | +| allow_failure | no | Allow build to fail. Failed build doesn't contribute to commit status | +| when | no | Define when to run build. Can be `on_success`, `on_failure` or `always` | +| artifacts | no | Define list build artifacts | +| cache | no | Define list of files that should be cached between subsequent runs | ### script -`script` is a shell script which is executed by runner. The shell script is prepended with `before_script`. + +`script` is a shell script which is executed by the runner. For example: ```yaml job: @@ -167,6 +197,7 @@ job: ``` This parameter can also contain several commands using an array: + ```yaml job: script: @@ -175,31 +206,45 @@ job: ``` ### stage -`stage` allows to group build into different stages. Builds of the same `stage` are executed in `parallel`. -For more info about the use of `stage` please check the [stages](#stages). + +`stage` allows to group build into different stages. Builds of the same `stage` +are executed in `parallel`. For more info about the use of `stage` please check +[stages](#stages). ### only and except -This are two parameters that allow for setting a refs policy to limit when jobs are built: -1. `only` defines the names of branches and tags for which job will be built. -2. `except` defines the names of branches and tags for which the job wil **not** be built. -There are a few rules that apply to usage of refs policy: +`only` and `except` are two parameters that set a refs policy to limit when +jobs are built: -1. `only` and `except` are inclusive. If both `only` and `except` are defined in job specification the ref is filtered by `only` and `except`. -1. `only` and `except` allow for using the regexp expressions. -1. `only` and `except` allow for using special keywords: `branches` and `tags`. -These names can be used for example to exclude all tags and all branches. +1. `only` defines the names of branches and tags for which the job will be + built. +2. `except` defines the names of branches and tags for which the job will + **not** be built. + +There are a few rules that apply to the usage of refs policy: + +* `only` and `except` are inclusive. If both `only` and `except` are defined + in a job specification, the ref is filtered by `only` and `except`. +* `only` and `except` allow the use of regular expressions. +* `only` and `except` allow the use of special keywords: `branches` and `tags`. +* `only` and `except` allow to specify a repository path to filter jobs for + forks. + +In the example below, `job` will run only for refs that start with `issue-`, +whereas all branches will be skipped. ```yaml job: + # use regexp only: - - /^issue-.*$/ # use regexp + - /^issue-.*$/ + # use special keyword except: - - branches # use special keyword + - branches ``` -1. `only` and `except` allow for specify repository path to filter jobs for forks. -The repository path can be used to have jobs executed only for parent repository. +The repository path can be used to have jobs executed only for the parent +repository and not forks: ```yaml job: @@ -208,33 +253,47 @@ job: except: - master@gitlab-org/gitlab-ce ``` -The above will run `job` for all branches on `gitlab-org/gitlab-ce`, except master . + +The above example will run `job` for all branches on `gitlab-org/gitlab-ce`, +except master. ### tags -`tags` is used to select specific runners from the list of all runners that are allowed to run this project. -During registration of a runner, you can specify the runner's tags, ie.: `ruby`, `postgres`, `development`. -`tags` allow you to run builds with runners that have the specified tags assigned: +`tags` is used to select specific runners from the list of all runners that are +allowed to run this project. -``` +During the registration of a runner, you can specify the runner's tags, for +example `ruby`, `postgres`, `development`. + +`tags` allow you to run builds with runners that have the specified tags +assigned to them: + +```yaml job: tags: - ruby - postgres ``` -The above specification will make sure that `job` is built by a runner that have `ruby` AND `postgres` tags defined. +The specification above, will make sure that `job` is built by a runner that +has both `ruby` AND `postgres` tags defined. ### when -`when` is used to implement jobs that are run in case of failure or despite the failure. + +`when` is used to implement jobs that are run in case of failure or despite the +failure. `when` can be set to one of the following values: -1. `on_success` - execute build only when all builds from prior stages succeeded. This is the default. -1. `on_failure` - execute build only when at least one build from prior stages failed. +1. `on_success` - execute build only when all builds from prior stages + succeeded. This is the default. +1. `on_failure` - execute build only when at least one build from prior stages + failed. 1. `always` - execute build despite the status of builds from prior stages. -``` +For example: + +```yaml stages: - build - cleanup_build @@ -242,28 +301,28 @@ stages: - deploy - cleanup -build: +build_job: stage: build script: - make build -cleanup_build: +cleanup_build_job: stage: cleanup_build script: - cleanup build when failed when: on_failure -test: +test_job: stage: test script: - make test -deploy: +deploy_job: stage: deploy script: - make deploy -cleanup: +cleanup_job: stage: cleanup script: - cleanup after builds @@ -271,43 +330,56 @@ cleanup: ``` The above script will: -1. Execute `cleanup_build` only when the `build` failed, -2. Always execute `cleanup` as the last step in pipeline. + +1. Execute `cleanup_build_job` only when `build_job` fails +2. Always execute `cleanup_job` as the last step in pipeline. ### artifacts -`artifacts` is used to specify list of files and directories which should be attached to build after success. -1. Send all files in `binaries` and `.config`: -``` +_**Note:** Introduced in GitLab Runner v0.7.0. Also, the Windows shell executor + does not currently support artifact uploads._ + +`artifacts` is used to specify list of files and directories which should be +attached to build after success. Below are some examples. + +Send all files in `binaries` and `.config`: + +```yaml artifacts: paths: - binaries/ - .config ``` -2. Send all git untracked files: -``` +Send all git untracked files: + +```yaml artifacts: untracked: true ``` -3. Send all git untracked files and files in `binaries`: -``` +Send all git untracked files and files in `binaries`: + +```yaml artifacts: untracked: true paths: - binaries/ ``` -The artifacts will be send after the build success to GitLab and will be accessible in GitLab interface to download. - -This feature requires GitLab Runner v0.7.0 or higher. +The artifacts will be send after a successful build success to GitLab, and will +be accessible in the GitLab UI to download. ### cache -`cache` is used to specify list of files and directories which should be cached between builds. -1. Cache all files in `binaries` and `.config`: -``` +_**Note:** Introduced in GitLab Runner v0.7.0._ + +`cache` is used to specify list of files and directories which should be cached +between builds. Below are some examples: + +Cache all files in `binaries` and `.config`: + +```yaml rspec: script: test cache: @@ -316,16 +388,18 @@ rspec: - .config ``` -2. Cache all git untracked files: -``` +Cache all git untracked files: + +```yaml rspec: script: test cache: untracked: true ``` -3. Cache all git untracked files and files in `binaries`: -``` +Cache all git untracked files and files in `binaries`: + +```yaml rspec: script: test cache: @@ -334,9 +408,10 @@ rspec: - binaries/ ``` -4. Locally defined cache overwrites globally defined options. This will cache only `binaries/`: +Locally defined cache overwrites globally defined options. This will cache only +`binaries/`: -``` +```yaml cache: paths: - my/files @@ -348,15 +423,15 @@ rspec: - binaries/ ``` -The cache is provided on best effort basis, so don't expect that cache will be present. -For implementation details please check GitLab Runner. - -This feature requires GitLab Runner v0.7.0 or higher. - +The cache is provided on best effort basis, so don't expect that cache will be +always present. For implementation details please check GitLab Runner. ## Validate the .gitlab-ci.yml + Each instance of GitLab CI has an embedded debug tool called Lint. -You can find the link to the Lint in the project's settings page or use short url `/lint`. +You can find the link under `/ci/lint` of your gitlab instance. ## Skipping builds -There is one more way to skip all builds, if your commit message contains tag [ci skip]. In this case, commit will be created but builds will be skipped + +If your commit message contains `[ci skip]`, the commit will be created but the +builds will be skipped. diff --git a/doc/customization/issue_closing.md b/doc/customization/issue_closing.md index 64f128f5a6..00edfc97ed 100644 --- a/doc/customization/issue_closing.md +++ b/doc/customization/issue_closing.md @@ -1,38 +1,39 @@ # Issue closing pattern -Here's how to close multiple issues in one commit message: +When a commit or merge request resolves one or more issues, it is possible to automatically have these issues closed when the commit or merge request lands in the project's default branch. -If a commit message matches the regular expression below, all issues referenced from -the matched text will be closed. This happens when the commit is pushed or merged -into the default branch of a project. +If a commit message or merge request description contains a sentence matching the regular expression below, all issues referenced from +the matched text will be closed. This happens when the commit is pushed to a project's default branch, or when a commit or merge request is merged into there. -When not specified, the default issue_closing_pattern as shown below will be used: +When not specified, the default `issue_closing_pattern` as shown below will be used: ```bash -((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?) +(?:(?:issues? +)?#\d+(?:(?:, *| +and +)?))+) +((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?) +(?:(?:issues? +)?%{issue_ref}(?:(?:, *| +and +)?))+) ``` +Here, `%{issue_ref}` is a complex regular expression defined inside GitLab, that matches a reference to a local issue (`#123`), cross-project issue (`group/project#123`) or a link to an issue (`https://gitlab.example.com/group/project/issues/123`). + For example: ``` -git commit -m "Awesome commit message (Fix #20, Fixes #21 and Closes #22). This commit is also related to #17 and fixes #18, #19 and #23." +git commit -m "Awesome commit message (Fix #20, Fixes #21 and Closes group/otherproject#2). This commit is also related to #17 and fixes #18, #19 and https://gitlab.example.com/group/otherproject/issues/23." ``` -will close `#20`, `#21`, `#22`, `#18`, `#19` and `#23`, but `#17` won't be closed -as it does not match the pattern. It also works with multiline commit messages. +will close `#18`, `#19`, `#20`, and `#21` in the project this commit is pushed to, as well as `#22` and `#23` in group/otherproject. `#17` won't be closed as it does not match the pattern. It also works with multiline commit messages. Tip: you can test this closing pattern at [http://rubular.com][1]. Use this site to test your own patterns. +Because Rubular doesn't understand `%{issue_ref}`, you can replace this by `#\d+` in testing, which matches only local issue references like `#123`. ## Change the pattern For Omnibus installs you can change the default pattern in `/etc/gitlab/gitlab.rb`: ``` -issue_closing_pattern: '((?:[Cc]los(?:e[sd]|ing)|[Ff]ix(?:e[sd]|ing)?) +(?:(?:issues? +)?#\d+(?:(?:, *| +and +)?))+)' +issue_closing_pattern: '((?:[Cc]los(?:e[sd]|ing)|[Ff]ix(?:e[sd]|ing)?) +(?:(?:issues? +)?%{issue_ref}(?:(?:, *| +and +)?))+)' ``` -For manual installs you can customize the pattern in [gitlab.yml][0]. +For manual installs you can customize the pattern in [gitlab.yml][0] using the `issue_closing_pattern` key. -[0]: https://gitlab.com/gitlab-org/gitlab-ce/blob/40c3675372320febf5264061c9bcd63db2dfd13c/config/gitlab.yml.example#L65 -[1]: http://rubular.com/r/Xmbexed1OJ \ No newline at end of file +[0]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/gitlab.yml.example +[1]: http://rubular.com/r/Xmbexed1OJ diff --git a/doc/development/db_dump.md b/doc/development/db_dump.md index 21f1b3edec..e4ff72aa34 100644 --- a/doc/development/db_dump.md +++ b/doc/development/db_dump.md @@ -1,4 +1,4 @@ -# Importing a database dump into a staging enviroment +# Importing a database dump into a staging environment Sometimes it is useful to import the database from a production environment into a staging environment for testing. The procedure below assumes you have diff --git a/doc/install/installation.md b/doc/install/installation.md index a88ba8eeb5..81edd8da2b 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -38,6 +38,7 @@ The GitLab installation consists of setting up the following components: 1. Packages / Dependencies 1. Ruby +1. Go 1. System Users 1. Database 1. Redis @@ -62,7 +63,7 @@ up-to-date and install it. Install the required packages (needed to compile Ruby and native extensions to Ruby gems): - sudo apt-get install -y build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libreadline-dev libncurses5-dev libffi-dev curl openssh-server redis-server checkinstall libxml2-dev libxslt-dev libcurl4-openssl-dev libicu-dev logrotate python-docutils pkg-config cmake nodejs + sudo apt-get install -y build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libreadline-dev libncurses5-dev libffi-dev curl openssh-server checkinstall libxml2-dev libxslt-dev libcurl4-openssl-dev libicu-dev logrotate python-docutils pkg-config cmake nodejs If you want to use Kerberos for user authentication, then install libkrb5-dev: @@ -174,33 +175,53 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da ## 6. Redis - sudo apt-get install redis-server +As of this writing, most Debian/Ubuntu distributions ship with Redis 2.2 or +2.4. GitLab requires at least Redis 2.8. - # Configure redis to use sockets - sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.orig +Ubuntu users [can use a PPA](https://launchpad.net/~chris-lea/+archive/ubuntu/redis-server) +to install a recent version of Redis. - # Disable Redis listening on TCP by setting 'port' to 0 - sed 's/^port .*/port 0/' /etc/redis/redis.conf.orig | sudo tee /etc/redis/redis.conf +The following instructions cover building and installing Redis from scratch: - # Enable Redis socket for default Debian / Ubuntu path - echo 'unixsocket /var/run/redis/redis.sock' | sudo tee -a /etc/redis/redis.conf - # Grant permission to the socket to all members of the redis group - echo 'unixsocketperm 770' | sudo tee -a /etc/redis/redis.conf +```sh +# Build Redis +wget http://download.redis.io/releases/redis-2.8.23.tar.gz +tar xzf redis-2.8.23.tar.gz +cd redis-2.8.23 +make - # Create the directory which contains the socket - mkdir /var/run/redis - chown redis:redis /var/run/redis - chmod 755 /var/run/redis - # Persist the directory which contains the socket, if applicable - if [ -d /etc/tmpfiles.d ]; then - echo 'd /var/run/redis 0755 redis redis 10d -' | sudo tee -a /etc/tmpfiles.d/redis.conf - fi +# Install Redis +cd utils +sudo ./install_server.sh - # Activate the changes to redis.conf - sudo service redis-server restart +# Configure redis to use sockets +sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.orig - # Add git to the redis group - sudo usermod -aG redis git +# Disable Redis listening on TCP by setting 'port' to 0 +sed 's/^port .*/port 0/' /etc/redis/redis.conf.orig | sudo tee /etc/redis/redis.conf + +# Enable Redis socket for default Debian / Ubuntu path +echo 'unixsocket /var/run/redis/redis.sock' | sudo tee -a /etc/redis/redis.conf + +# Grant permission to the socket to all members of the redis group +echo 'unixsocketperm 770' | sudo tee -a /etc/redis/redis.conf + +# Create the directory which contains the socket +mkdir /var/run/redis +chown redis:redis /var/run/redis +chmod 755 /var/run/redis + +# Persist the directory which contains the socket, if applicable +if [ -d /etc/tmpfiles.d ]; then + echo 'd /var/run/redis 0755 redis redis 10d -' | sudo tee -a /etc/tmpfiles.d/redis.conf +fi + +# Activate the changes to redis.conf +sudo service redis_6379 start + +# Add git to the redis group +sudo usermod -aG redis git +``` ## 7. GitLab @@ -210,9 +231,9 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da ### Clone the Source # Clone GitLab repository - sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 8-2-stable gitlab + sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 8-3-stable gitlab -**Note:** You can change `8-2-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! +**Note:** You can change `8-3-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! ### Configure It @@ -312,7 +333,7 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da GitLab Shell is an SSH access and repository management software developed specially for GitLab. # Run the installation task for gitlab-shell (replace `REDIS_URL` if needed): - sudo -u git -H bundle exec rake gitlab:shell:install[v2.6.7] REDIS_URL=unix:/var/run/redis/redis.sock RAILS_ENV=production + sudo -u git -H bundle exec rake gitlab:shell:install REDIS_URL=unix:/var/run/redis/redis.sock RAILS_ENV=production # By default, the gitlab-shell config is generated from your main GitLab config. # You can review (and modify) the gitlab-shell config as follows: @@ -320,14 +341,14 @@ GitLab Shell is an SSH access and repository management software developed speci **Note:** If you want to use HTTPS, see [Using HTTPS](#using-https) for the additional steps. -**Note:** Make sure your hostname can be resolved on the machine itself by either a proper DNS record or an additional line in /etc/hosts ("127.0.0.1 hostname"). This might be necessary for example if you set up gitlab behind a reverse proxy. If the hostname cannot be resolved, the final installation check will fail with "Check GitLab API access: FAILED. code: 401" and pushing commits will be rejected with "[remote rejected] master -> master (hook declined)". +**Note:** Make sure your hostname can be resolved on the machine itself by either a proper DNS record or an additional line in /etc/hosts ("127.0.0.1 hostname"). This might be necessary for example if you set up GitLab behind a reverse proxy. If the hostname cannot be resolved, the final installation check will fail with "Check GitLab API access: FAILED. code: 401" and pushing commits will be rejected with "[remote rejected] master -> master (hook declined)". ### Install gitlab-workhorse cd /home/git sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git cd gitlab-workhorse - sudo -u git -H git checkout 0.4.2 + sudo -u git -H git checkout 0.5.1 sudo -u git -H make ### Initialize Database and Activate Advanced Features diff --git a/doc/integration/README.md b/doc/integration/README.md index eff39a626a..8ea4111bc8 100644 --- a/doc/integration/README.md +++ b/doc/integration/README.md @@ -4,6 +4,7 @@ GitLab integrates with multiple third-party services to allow external issue tra See the documentation below for details on how to configure these services. +- [Jira](jira.md) Integrate with the JIRA issue tracker - [External issue tracker](external-issue-tracker.md) Redmine, JIRA, etc. - [LDAP](ldap.md) Set up sign in via LDAP - [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, GitLab, and Google via OAuth. diff --git a/doc/integration/bitbucket.md b/doc/integration/bitbucket.md index 6a0fa4ce01..63432b0443 100644 --- a/doc/integration/bitbucket.md +++ b/doc/integration/bitbucket.md @@ -30,7 +30,7 @@ Bitbucket will generate an application ID and secret key for you to use. sudo editor /etc/gitlab/gitlab.rb ``` - For instalations from source: + For installations from source: ```sh cd /home/git/gitlab diff --git a/doc/integration/crowd.md b/doc/integration/crowd.md index 2ecc8795ac..40d93aef2a 100644 --- a/doc/integration/crowd.md +++ b/doc/integration/crowd.md @@ -10,7 +10,7 @@ To enable the Crowd OmniAuth provider you must register your application with Cr sudo editor /etc/gitlab/gitlab.rb ``` - For instalations from source: + For installations from source: ```sh cd /home/git/gitlab diff --git a/doc/integration/github.md b/doc/integration/github.md index b64501c2aa..a789d2c814 100644 --- a/doc/integration/github.md +++ b/doc/integration/github.md @@ -32,7 +32,7 @@ GitHub will generate an application ID and secret key for you to use. sudo editor /etc/gitlab/gitlab.rb ``` - For instalations from source: + For installations from source: ```sh cd /home/git/gitlab diff --git a/doc/integration/gitlab.md b/doc/integration/gitlab.md index 216f1f11a9..80e3c0142a 100644 --- a/doc/integration/gitlab.md +++ b/doc/integration/gitlab.md @@ -38,7 +38,7 @@ GitLab.com will generate an application ID and secret key for you to use. sudo editor /etc/gitlab/gitlab.rb ``` - For instalations from source: + For installations from source: ```sh cd /home/git/gitlab diff --git a/doc/integration/google.md b/doc/integration/google.md index e1c14c7c94..91e9b2495c 100644 --- a/doc/integration/google.md +++ b/doc/integration/google.md @@ -35,7 +35,7 @@ To enable the Google OAuth2 OmniAuth provider you must register your application sudo editor /etc/gitlab/gitlab.rb ``` - For instalations from source: + For installations from source: ```sh cd /home/git/gitlab diff --git a/doc/integration/jira.md b/doc/integration/jira.md new file mode 100644 index 0000000000..624601d0fa --- /dev/null +++ b/doc/integration/jira.md @@ -0,0 +1,113 @@ +# GitLab Jira integration + +GitLab can be configured to interact with Jira. +Configuration happens via username and password. +Connecting to a Jira server via CAS is not possible. + +Each project can be configured to connect to a different Jira instance, configuration is explained [here](#configuration). +If you have one Jira instance you can pre-fill the settings page with a default template. To configure the template [see external issue tracker document](external-issue-tracker.md#service-template)). + +Once the project is connected to Jira, you can reference and close the issues in Jira directly from GitLab. + + +## Table of Contents + +* [Referencing Jira Issues from GitLab](#referencing-jira-issues) +* [Closing Jira Issues from GitLab](#closing-jira-issues) +* [Configuration](#configuration) + +### Referencing Jira Issues + +When GitLab project has Jira issue tracker configured and enabled, mentioning Jira issue in GitLab will automatically add a comment in Jira issue with the link back to GitLab. This means that in comments in merge requests and commits referencing an issue, eg. `PROJECT-7`, will add a comment in Jira issue in the format: + + +``` + USER mentioned this issue in LINK_TO_THE_MENTION +``` + +* `USER` A user that mentioned the issue. This is the link to the user profile in GitLab. +* `LINK_TO_THE_MENTION` Link to the origin of mention with a name of the entity where Jira issue was mentioned. +Can be commit or merge request. + + +![example of mentioning or closing the Jira issue](jira_issue_reference.png) + + +### Closing Jira Issues + +Jira issues can be closed directly from GitLab by using trigger words, eg. `Resolves PROJECT-1`, `Closes PROJECT-1` or `Fixes PROJECT-1`, in commits and merge requests. +When a commit which contains the trigger word in the commit message is pushed, GitLab will add a comment in the mentioned Jira issue. + +For example, for project named PROJECT in Jira, we implemented a new feature and created a merge request in GitLab. + +This feature was requested in Jira issue PROJECT-7. Merge request in GitLab contains the improvement and in merge request description we say that this merge request `Closes PROJECT-7` issue. + +Once this merge request is merged, Jira issue will be automatically closed with a link to the commit that resolved the issue. + +![A Git commit that causes the Jira issue to be closed](merge_request_close_jira.png) + + +![The GitLab integration user leaves a comment on Jira](jira_service_close_issue.png) + + +## Configuration + +### Configuring JIRA + +We need to create a user in JIRA which will have access to all projects that need to integrate with GitLab. +Login to your JIRA instance as admin and under Administration go to User Management and create a new user. +As an example, we'll create a user named `gitlab` and add it to `jira-developers` group. + +**It is important that the user `gitlab` has write-access to projects in JIRA** + +### Configuring GitLab + +### GitLab 7.8 EE and up with JIRA v6.x + +To enable JIRA integration in a project, navigate to the project Settings page and go to Services. Here you will find JIRA. + +Fill in the required details on the page: + +![Jira service page](jira_service_page.png) + +* `description` A name for the issue tracker (to differentiate between instances, for instance). +* `project url` The URL to the JIRA project which is being linked to this GitLab project. +* `issues url` The URL to the JIRA project issues overview for the project that is linked to this GitLab project. +* `new issue url` This is the URL to create a new issue in JIRA for the project linked to this GitLab project. +* `api url` The base URL of the JIRA API. It may be omitted, in which case GitLab will automatically use API version `2` based on the `project url`, i.e. `https://jira.example.com/rest/api/2`. +* `username` The username of the user created in [configuring JIRA step](#configuring-jira). +* `password` The password of the user created in [configuring JIRA step](#configuring-jira). +* `Jira issue transition` This is the id of a transition that moves issues to a closed state. You can find this number under [JIRA workflow administration, see screenshot](jira_workflow_screenshot.png). By default, this id is `2`. (In the example image, this is `2` as well) + +After saving the configuration, your GitLab project will be able to interact with the linked JIRA project. + + +### GitLab 6.x-7.7 with JIRA v6.x + +**Note: GitLab 7.8 and up contain various integration improvements. We strongly recommend upgrading.** + + +In `gitlab.yml` enable [JIRA issue tracker section by uncommenting the lines](https://gitlab.com/subscribers/gitlab-ee/blob/6-8-stable-ee/config/gitlab.yml.example#L111-115). +This will make sure that all issues within GitLab are pointing to the JIRA issue tracker. + +We can also enable JIRA service that will allow us to interact with JIRA issues. + +For example, we can close issues in JIRA by a commit in GitLab. + +Go to project settings page and fill in the project name for the JIRA project: + +![Set the JIRA project name in GitLab to 'NEW'](jira_project_name.png) + +Next, go to the services page and find JIRA. + +![Jira services page](jira_service.png) + +1. Tick the active check box to enable the service. +1. Supply the url to JIRA server, for example http://jira.sample +1. Supply the username of a user we created under `Configuring JIRA` section, for example `gitlab` +1. Supply the password of the user +1. Optional: supply the JIRA api version, default is version +1. Optional: supply the JIRA issue transition ID (issue transition to closed). This is dependant on JIRA settings, default is 2 +1. Save + +Now we should be able to interact with JIRA issues. diff --git a/doc/integration/jira_issue_reference.png b/doc/integration/jira_issue_reference.png new file mode 100644 index 0000000000000000000000000000000000000000..15739a22dc7151af663316c1d44e8fcda704ce29 GIT binary patch literal 39942 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 z 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�Z@S2~7AEhk$oKul=mo5b%= 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 literal 0 HcmV?d00001 diff --git a/doc/integration/jira_service_close_issue.png b/doc/integration/jira_service_close_issue.png new file mode 100644 index 0000000000000000000000000000000000000000..67dfc6144c44f0643e1373bef9961bf0c3a458fb GIT binary patch literal 88433 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

>spIVA13()-a^l@ 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≦GARRR}=mI6zz>11NC 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

eNQ*`uDkjKem2WyPQ- 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�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%0DDJD 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 literal 0 HcmV?d00001 diff --git a/doc/integration/ldap.md b/doc/integration/ldap.md index 7e2920b886..845f588f91 100644 --- a/doc/integration/ldap.md +++ b/doc/integration/ldap.md @@ -13,6 +13,12 @@ An LDAP user who is allowed to change their email on the LDAP server can [take o We recommend against using GitLab LDAP integration if your LDAP users are allowed to change their 'mail', 'email' or 'userPrincipalName' attribute on the LDAP server. +If a user is deleted from the LDAP server, they will be blocked in GitLab as well. +Users will be immediately blocked from logging in. However, there is an LDAP check +cache time of one hour. The means users that are already logged in or are using Git +over SSH will still be able to access GitLab for up to one hour. Manually block +the user in the GitLab Admin area to immediately block all access. + ## Configuring GitLab for LDAP integration To enable GitLab LDAP integration you need to add your LDAP server settings in `/etc/gitlab/gitlab.rb` or `/home/git/gitlab/config/gitlab.yml`. @@ -192,4 +198,4 @@ Not supported by GitLab's configuration options. When setting `method: ssl`, the underlying authentication method used by `omniauth-ldap` is `simple_tls`. This method establishes TLS encryption with the LDAP server before any LDAP-protocol data is exchanged but no validation of -the LDAP server's SSL certificate is performed. \ No newline at end of file +the LDAP server's SSL certificate is performed. diff --git a/doc/integration/saml.md b/doc/integration/saml.md index 4aa6dbe758..1632e42f70 100644 --- a/doc/integration/saml.md +++ b/doc/integration/saml.md @@ -14,7 +14,7 @@ First configure SAML 2.0 support in GitLab, then register the GitLab application sudo editor /etc/gitlab/gitlab.rb ``` - For instalations from source: + For installations from source: ```sh cd /home/git/gitlab @@ -38,7 +38,8 @@ First configure SAML 2.0 support in GitLab, then register the GitLab application idp_sso_target_url: 'https://login.example.com/idp', issuer: 'https://gitlab.example.com', name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient' - } + }, + "label" => "Company Login" # optional label for SAML login button, defaults to "Saml" } ] ``` @@ -79,4 +80,4 @@ On the sign in page there should now be a SAML button below the regular sign in If you see a "500 error" in GitLab when you are redirected back from the SAML sign in page, this likely indicates that GitLab could not get the email address for the SAML user. -Make sure the IdP provides a claim containing the user's email address, using claim name 'email' or 'mail'. The email will be used to automatically generate the GitLab username. +Make sure the IdP provides a claim containing the user's email address, using claim name 'email' or 'mail'. The email will be used to automatically generate the GitLab username. \ No newline at end of file diff --git a/doc/integration/twitter.md b/doc/integration/twitter.md index 1350c8f693..52ed4a2233 100644 --- a/doc/integration/twitter.md +++ b/doc/integration/twitter.md @@ -37,7 +37,7 @@ To enable the Twitter OmniAuth provider you must register your application with sudo editor /etc/gitlab/gitlab.rb ``` - For instalations from source: + For installations from source: ```sh cd /home/git/gitlab diff --git a/doc/operations/moving_repositories.md b/doc/operations/moving_repositories.md new file mode 100644 index 0000000000..39086b7a25 --- /dev/null +++ b/doc/operations/moving_repositories.md @@ -0,0 +1,180 @@ +# Moving repositories managed by GitLab + +Sometimes you need to move all repositories managed by GitLab to +another filesystem or another server. In this document we will look +at some of the ways you can copy all your repositories from +`/var/opt/gitlab/git-data/repositories` to `/mnt/gitlab/repositories`. + +We will look at three scenarios: the target directory is empty, the +target directory contains an outdated copy of the repositories, and +how to deal with thousands of repositories. + +**Each of the approaches we list can/will overwrite data in the +target directory `/mnt/gitlab/repositories`. Do not mix up the +source and the target.** + +## Target directory is empty: use a tar pipe + +If the target directory `/mnt/gitlab/repositories` is empty the +simplest thing to do is to use a tar pipe. This method has low +overhead and tar is almost always already installed on your system. +However, it is not possible to resume an interrupted tar pipe: if +that happens then all data must be copied again. + +``` +# As the git user +tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\ + tar -C /mnt/gitlab/repositories -xf - +``` + +If you want to see progress, replace `-xf` with `-xvf`. + +### Tar pipe to another server + +You can also use a tar pipe to copy data to another server. If your +'git' user has SSH access to the newserver as 'git@newserver', you +can pipe the data through SSH. + +``` +# As the git user +tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\ + ssh git@newserver tar -C /mnt/gitlab/repositories -xf - +``` + +If you want to compress the data before it goes over the network +(which will cost you CPU cycles) you can replace `ssh` with `ssh -C`. + +## The target directory contains an outdated copy of the repositories: use rsync + +If the target directory already contains a partial / outdated copy +of the repositories it may be wasteful to copy all the data again +with tar. In this scenario it is better to use rsync. This utility +is either already installed on your system or easily installable +via apt, yum etc. + +``` +# As the 'git' user +rsync -a --delete /var/opt/gitlab/git-data/repositories/. \ + /mnt/gitlab/repositories +``` + +The `/.` in the command above is very important, without it you can +easily get the wrong directory structure in the target directory. +If you want to see progress, replace `-a` with `-av`. + +### Single rsync to another server + +If the 'git' user on your source system has SSH access to the target +server you can send the repositories over the network with rsync. + +``` +# As the 'git' user +rsync -a --delete /var/opt/gitlab/git-data/repositories/. \ + git@newserver:/mnt/gitlab/repositories +``` + +## Thousands of Git repositories: use one rsync per repository + +Every time you start an rsync job it has to inspect all files in +the source directory, all files in the target directory, and then +decide what files to copy or not. If the source or target directory +has many contents this startup phase of rsync can become a burden +for your GitLab server. In cases like this you can make rsync's +life easier by dividing its work in smaller pieces, and sync one +repository at a time. + +In addition to rsync we will use [GNU +Parallel](http://www.gnu.org/software/parallel/). This utility is +not included in GitLab so you need to install it yourself with apt +or yum. Also note that the GitLab scripts we used below were added +in GitLab 8.1. + +** This process does not clean up repositories at the target location that no +longer exist at the source. ** If you start using your GitLab instance with +`/mnt/gitlab/repositories`, you need to run `gitlab-rake gitlab:cleanup:repos` +after switching to the new repository storage directory. + +### Parallel rsync for all repositories known to GitLab + +This will sync repositories with 10 rsync processes at a time. We keep +track of progress so that the transfer can be restarted if necessary. + +First we create a new directory, owned by 'git', to hold transfer +logs. We assume the directory is empty before we start the transfer +procedure, and that we are the only ones writing files in it. + +``` +# Omnibus +sudo mkdir /var/opt/gitlab/transfer-logs +sudo chown git:git /var/opt/gitlab/transfer-logs + +# Source +sudo -u git -H mkdir /home/git/transfer-logs +``` + +We seed the process with a list of the directories we want to copy. + +``` +# Omnibus +sudo -u git sh -c 'gitlab-rake gitlab:list_repos > /var/opt/gitlab/transfer-logs/all-repos-$(date +%s).txt' + +# Source +cd /home/git/gitlab +sudo -u git -H sh -c 'bundle exec rake gitlab:list_repos > /home/git/transfer-logs/all-repos-$(date +%s).txt' +``` + +Now we can start the transfer. The command below is idempotent, and +the number of jobs done by GNU Parallel should converge to zero. If it +does not some repositories listed in all-repos-1234.txt may have been +deleted/renamed before they could be copied. + +``` +# Omnibus +sudo -u git sh -c ' +cat /var/opt/gitlab/transfer-logs/* | sort | uniq -u |\ + /usr/bin/env JOBS=10 \ + /opt/gitlab/embedded/service/gitlab-rails/bin/parallel-rsync-repos \ + /var/opt/gitlab/transfer-logs/succes-$(date +%s).log \ + /var/opt/gitlab/git-data/repositories \ + /mnt/gitlab/repositories +' + +# Source +cd /home/git/gitlab +sudo -u git -H sh -c ' +cat /home/git/transfer-logs/* | sort | uniq -u |\ + /usr/bin/env JOBS=10 \ + bin/parallel-rsync-repos \ + /home/git/transfer-logs/succes-$(date +%s).log \ + /home/git/repositories \ + /mnt/gitlab/repositories +` +``` + +### Parallel rsync only for repositories with recent activity + +Suppose you have already done one sync that started after 2015-10-1 12:00 UTC. +Then you might only want to sync repositories that were changed via GitLab +_after_ that time. You can use the 'SINCE' variable to tell 'rake +gitlab:list_repos' to only print repositories with recent activity. + +``` +# Omnibus +sudo gitlab-rake gitlab:list_repos SINCE='2015-10-1 12:00 UTC' |\ + sudo -u git \ + /usr/bin/env JOBS=10 \ + /opt/gitlab/embedded/service/gitlab-rails/bin/parallel-rsync-repos \ + succes-$(date +%s).log \ + /var/opt/gitlab/git-data/repositories \ + /mnt/gitlab/repositories + +# Source +cd /home/git/gitlab +sudo -u git -H bundle exec rake gitlab:list_repos SINCE='2015-10-1 12:00 UTC' |\ + sudo -u git -H \ + /usr/bin/env JOBS=10 \ + bin/parallel-rsync-repos \ + succes-$(date +%s).log \ + /home/git/repositories \ + /mnt/gitlab/repositories +``` diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md index 8d4c2ceab7..bcd00cfc6b 100644 --- a/doc/permissions/permissions.md +++ b/doc/permissions/permissions.md @@ -6,6 +6,9 @@ If a user is both in a project group and in the project itself, the highest perm If a user is a GitLab administrator they receive all permissions. +On public projects the Guest role is not enforced. +All users will be able to create issues, leave comments, and pull or download the project code. + To add or import a user, you can follow the [project users and members documentation](doc/workflow/add-user/add-user.md). @@ -15,8 +18,8 @@ documentation](doc/workflow/add-user/add-user.md). |---------------------------------------|---------|------------|-------------|----------|--------| | Create new issue | ✓ | ✓ | ✓ | ✓ | ✓ | | Leave comments | ✓ | ✓ | ✓ | ✓ | ✓ | -| Pull project code | ✓ | ✓ | ✓ | ✓ | ✓ | -| Download project | ✓ | ✓ | ✓ | ✓ | ✓ | +| Pull project code | | ✓ | ✓ | ✓ | ✓ | +| Download project | | ✓ | ✓ | ✓ | ✓ | | Create code snippets | | ✓ | ✓ | ✓ | ✓ | | Manage issue tracker | | ✓ | ✓ | ✓ | ✓ | | Manage labels | | ✓ | ✓ | ✓ | ✓ | diff --git a/doc/public_access/public_access.md b/doc/public_access/public_access.md index bd439f7c6f..6e22ea7b72 100644 --- a/doc/public_access/public_access.md +++ b/doc/public_access/public_access.md @@ -1,44 +1,59 @@ # Public access -GitLab allows you to open selected projects to be accessed **publicly** or **internally**. +GitLab allows you to change your projects' visibility in order be accessed +**publicly** or **internally**. -Projects with either of these visibility levels will be listed in the [public access directory](/public). +Projects with either of these visibility levels will be listed in the +public access directory (`/public` under your GitLab instance). +Here is the [GitLab.com example](https://gitlab.com/public). Internal projects will only be available to authenticated users. -## Public projects +## Visibility of projects + +### Public projects Public projects can be cloned **without any** authentication. -It will also be listed on the [public access directory](/public). +They will also be listed on the public access directory (`/public`). -**Any logged in user** will have [Guest](../permissions/permissions) permissions on the repository. +**Any logged in user** will have [Guest](../permissions/permissions) +permissions on the repository. -## Internal projects +### Internal projects Internal projects can be cloned by any logged in user. -It will also be listed on the [public access directory](/public) for logged in users. +They will also be listed on the public access directory (`/public`) for logged +in users. -Any logged in user will have [Guest](../permissions/permissions) permissions on the repository. +Any logged in user will have [Guest](../permissions/permissions) permissions on +the repository. -## How to change project visibility +### How to change project visibility -1. Go to your project dashboard -1. Click on the "Edit" tab -1. Change "Visibility Level" +1. Go to your project's **Settings** +1. Change "Visibility Level" to either Public, Internal or Private ## Visibility of users -The public page of users, located at `/u/username` is visible if either: +The public page of a user, located at `/u/username`, is always visible whether +you are logged in or not. -- You are logged in. -- You are logged out, and the target user is authorized to (is Guest, Reporter, etc.) at least one public project. +When visiting the public page of a user, you can only see the projects which +you are privileged to. -Otherwise, you will be redirected to the sign in page. +## Visibility of groups -When visiting the public page of an user, you will only see listed projects which you can view yourself. +The public page of a group, located at `/groups/groupname`, is always visible +to everyone. + +Logged out users will be able to see the description and the avatar of the +group as well as all public projects belonging to that group. ## Restricting the use of public or internal projects -In the Admin area under Settings you can disable public projects or public and internal projects for the entire GitLab installation to prevent people making code public by accident. The restricted visibility settings do not apply to admin users. +In the Admin area under **Settings** (`/admin/application_settings`), you can +restrict the use of visibility levels for users when they create a project or a +snippet. This is useful to prevent people exposing their repositories to public +by accident. The restricted visibility settings do not apply to admin users. diff --git a/doc/raketasks/README.md b/doc/raketasks/README.md index a8dc5c24df..cc8a22cd00 100644 --- a/doc/raketasks/README.md +++ b/doc/raketasks/README.md @@ -1,10 +1,11 @@ # Rake tasks - [Backup restore](backup_restore.md) +- [Check](check.md) - [Cleanup](cleanup.md) - [Features](features.md) - [Maintenance](maintenance.md) and self-checks - [User management](user_management.md) - [Web hooks](web_hooks.md) - [Import](import.md) of git repositories in bulk -- [Rebuild authorized_keys file](http://doc.gitlab.com/ce/raketasks/maintenance.html#rebuild-authorized_keys-file) task for administrators \ No newline at end of file +- [Rebuild authorized_keys file](http://doc.gitlab.com/ce/raketasks/maintenance.html#rebuild-authorized_keys-file) task for administrators diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md index 4e645b21a8..093450a6de 100644 --- a/doc/raketasks/backup_restore.md +++ b/doc/raketasks/backup_restore.md @@ -274,9 +274,6 @@ sudo gitlab-rake gitlab:backup:restore BACKUP=1393513186 # Start GitLab sudo gitlab-ctl start -# Create satellites -sudo gitlab-rake gitlab:satellites:create - # Check GitLab sudo gitlab-rake gitlab:check SANITIZE=true ``` @@ -360,8 +357,8 @@ If you are using backup restore procedures you might encounter the following war ``` psql:/var/opt/gitlab/backups/db/database.sql:22: ERROR: must be owner of extension plpgsql -psql:/var/opt/gitlab/backups/db/database.sql:2931: WARNING: no privileges could be revoked for "public" (two occurences) -psql:/var/opt/gitlab/backups/db/database.sql:2933: WARNING: no privileges were granted for "public" (two occurences) +psql:/var/opt/gitlab/backups/db/database.sql:2931: WARNING: no privileges could be revoked for "public" (two occurrences) +psql:/var/opt/gitlab/backups/db/database.sql:2933: WARNING: no privileges were granted for "public" (two occurrences) ``` diff --git a/doc/raketasks/check.md b/doc/raketasks/check.md new file mode 100644 index 0000000000..3ff3fee6a4 --- /dev/null +++ b/doc/raketasks/check.md @@ -0,0 +1,63 @@ +# Check Rake Tasks + +## Repository Integrity + +Even though Git is very resilient and tries to prevent data integrity issues, +there are times when things go wrong. The following Rake tasks intend to +help GitLab administrators diagnose problem repositories so they can be fixed. + +There are 3 things that are checked to determine integrity. + +1. Git repository file system check ([git fsck](https://git-scm.com/docs/git-fsck)). + This step verifies the connectivity and validity of objects in the repository. +1. Check for `config.lock` in the repository directory. +1. Check for any branch/references lock files in `refs/heads`. + +It's important to note that the existence of `config.lock` or reference locks +alone do not necessarily indicate a problem. Lock files are routinely created +and removed as Git and GitLab perform operations on the repository. They serve +to prevent data integrity issues. However, if a Git operation is interrupted these +locks may not be cleaned up properly. + +The following symptoms may indicate a problem with repository integrity. If users +experience these symptoms you may use the rake tasks described below to determine +exactly which repositories are causing the trouble. + +- Receiving an error when trying to push code - `remote: error: cannot lock ref` +- A 500 error when viewing the GitLab dashboard or when accessing a specific project. + +### Check all GitLab repositories + +This task loops through all repositories on the GitLab server and runs the +3 integrity checks described previously. + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:repo:check + +# installation from source +bundle exec rake gitlab:repo:check RAILS_ENV=production +``` + +### Check repositories for a specific user + +This task checks all repositories that a specific user has access to. This is important +because sometimes you know which user is experiencing trouble but you don't know +which project might be the cause. + +If the rake task is executed without brackets at the end, you will be prompted +to enter a username. + +```bash +# omnibus-gitlab +sudo gitlab-rake gitlab:user:check_repos +sudo gitlab-rake gitlab:user:check_repos[] + +# installation from source +bundle exec rake gitlab:user:check_repos RAILS_ENV=production +bundle exec rake gitlab:user:check_repos[] RAILS_ENV=production +``` + +Example output: + +![gitlab:user:check_repos output](check_repos_output.png) diff --git a/doc/raketasks/check_repos_output.png b/doc/raketasks/check_repos_output.png new file mode 100644 index 0000000000000000000000000000000000000000..916b16851018bd6de0258f465e6e125ea56d1e0c GIT binary patch literal 73786 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 DWM-fi literal 0 HcmV?d00001 diff --git a/doc/raketasks/list_repos.md b/doc/raketasks/list_repos.md new file mode 100644 index 0000000000..476428eb4f --- /dev/null +++ b/doc/raketasks/list_repos.md @@ -0,0 +1,30 @@ +# Listing repository directories + +You can print a list of all Git repositories on disk managed by +GitLab with the following command: + +``` +# Omnibus +sudo gitlab-rake gitlab:list_repos + +# Source +cd /home/git/gitlab +sudo -u git -H bundle exec rake gitlab:list_repos RAILS_ENV=production +``` + +If you only want to list projects with recent activity you can pass +a date with the 'SINCE' environment variable. The time you specify +is parsed by the Rails [TimeZone#parse +function](http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html#method-i-parse). + +``` +# Omnibus +sudo gitlab-rake gitlab:list_repos SINCE='Sep 1 2015' + +# Source +cd /home/git/gitlab +sudo -u git -H bundle exec rake gitlab:list_repos RAILS_ENV=production SINCE='Sep 1 2015' +``` + +Note that the projects listed are NOT sorted by activity; they use +the default ordering of the GitLab Rails application. diff --git a/doc/release/README.md b/doc/release/README.md index 1342b90f3b..52eca7c02a 100644 --- a/doc/release/README.md +++ b/doc/release/README.md @@ -1,4 +1,8 @@ -GitLab has the following updates: +## Release cycle + +Since 2011 a minor or major version of GitLab is released on the 22nd of every month. Patch and security releases are published when needed. New features are detailed on the [blog](https://about.gitlab.com/blog/) and in the [changelog](CHANGELOG). Features that will likely be in the next releases can be found on the [direction page](https://about.gitlab.com/direction/). + +## Release process documentation - [Monthly release](monthly.md), every month on the 22nd. - [Patch release](patch.md), if there are serious regressions. diff --git a/doc/release/monthly.md b/doc/release/monthly.md index c9ab87671d..907c19e65a 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -159,7 +159,7 @@ Please do not raise issues directly in this issue but link to issues that might The decision to create a patch release or not is with the release manager who is assigned to this issue. The release manager will comment here about the plans for patch releases. -Assign the issue to the release manager and at mention all members of gitlab core team. If there are any known bugs in the release add them immediately. +Assign the issue to the release manager and at mention all members of GitLab core team. If there are any known bugs in the release add them immediately. ## Tweet about RC1 @@ -176,7 +176,7 @@ Tweet about the RC release: 1. Also check the CI changelog 1. Add a proposed tweet text to the blog post WIP MR description. 1. Create a WIP MR for the blog post -1. Make sure merge request title starts with `WIP` so it can not be accidently merged until ready. +1. Make sure merge request title starts with `WIP` so it can not be accidentally merged until ready. 1. Ask Dmitriy (or a team member with OS X) to add screenshots to the WIP MR. 1. Decide with core team who will be the MVP user. 1. Create WIP MR for adding MVP to MVP page on website diff --git a/doc/release/patch.md b/doc/release/patch.md index 6aa11b283d..3022e375ac 100644 --- a/doc/release/patch.md +++ b/doc/release/patch.md @@ -1,21 +1,46 @@ # Things to do when doing a patch release -NOTE: This is a guide for GitLab developers. If you are trying to install GitLab see the latest stable [installation guide](install/installation.md) and if you are trying to upgrade, see the [upgrade guides](update). +NOTE: This is a guide for GitLab developers. If you are trying to install GitLab +see the latest stable [installation guide](install/installation.md) and if you +are trying to upgrade, see the [upgrade guides](update). ## When to do a patch release -Do a patch release when there is a critical regression that needs to be addresses before the next monthly release. - -Otherwise include it in the monthly release and note there was a regression fix in the release announcement. +Patch releases are done as-needed in order to fix regressions in the current +major release that cannot or should not wait until the next major release. +What's included and when to release is at the discretion of the release manager. ## Release Procedure +### Create a patch issue + +Create an issue in the GitLab CE project. Name it "Release x.y.z", tag it with +the `release` label, and assign it to the milestone of the corresponding major +release. + +Use the following template: + +``` +- Picked into respective `stable` branches: +- [ ] Merge `x-y-stable` into `x-y-stable-ee` +- [ ] release-tools: `x.y.z` +- gitlab-omnibus + - [ ] `x.y.z+ee.0` + - [ ] `x.y.z+ce.0` +- [ ] Deploy +- [ ] Add patch notice to [x.y regressions]() +- [ ] [Blog post]() +- [ ] [Tweet]() +- [ ] Add entry to version.gitlab.com +``` + +Update the issue with links to merge requests that need to be/have been picked +into the `stable` branches. + ### Preparation 1. Verify that the issue can be reproduced 1. Note in the 'GitLab X.X regressions' that you will create a patch -1. Create an issue on private GitLab development server -1. Name the issue "Release X.X.X CE and X.X.X EE", this will make searching easier 1. Fix the issue on a feature branch, do this on the private GitLab development server 1. If it is a security issue, then assign it to the release manager and apply a 'security' label 1. Consider creating and testing workarounds @@ -25,7 +50,6 @@ Otherwise include it in the monthly release and note there was a regression fix 1. For EE, update the CHANGELOG-EE if it is EE specific fix. Otherwise, merge the stable CE branch and add to CHANGELOG-EE "Merge community edition changes for version X.X.X" 1. Merge CE stable branch into EE stable branch - ### Bump version Get release tools @@ -54,4 +78,4 @@ bundle exec rake release["x.x.x"] 1. Note in the 'GitLab X.X regressions' issue that the patch was published (CE only) 1. Create the 'x.y.0' version on version.gitlab.com 1. [Create new AMIs](https://dev.gitlab.org/gitlab/AMI/blob/master/README.md) -1. Create a new patch release issue for the next potential release \ No newline at end of file +1. Create a new patch release issue for the next potential release diff --git a/doc/security/README.md b/doc/security/README.md index 473f3632dc..fba6013d9c 100644 --- a/doc/security/README.md +++ b/doc/security/README.md @@ -4,4 +4,5 @@ - [Rack attack](rack_attack.md) - [Web Hooks and insecure internal web services](webhooks.md) - [Information exclusivity](information_exclusivity.md) -- [Reset your root password](reset_root_password.md) \ No newline at end of file +- [Reset your root password](reset_root_password.md) +- [User File Uploads](user_file_uploads.md) diff --git a/doc/security/user_file_uploads.md b/doc/security/user_file_uploads.md new file mode 100644 index 0000000000..98493d33b0 --- /dev/null +++ b/doc/security/user_file_uploads.md @@ -0,0 +1,11 @@ +# User File Uploads + +Images attached to issues, merge requests or comments do not require authentication +to be viewed if someone knows the direct URL. This direct URL contains a random +32-character ID that prevents unauthorized people from guessing the URL to an +image containing sensitive information. We don't enable authentication because +these images need to be visible in the body of notification emails, which are +often read from email clients that are not authenticated with GitLab, like +Outlook, Apple Mail, or the Mail app on your mobile device. + +Note that non-image attachments do require authentication to be viewed. diff --git a/doc/ssh/README.md b/doc/ssh/README.md index 9753504ac8..fe5b45dd43 100644 --- a/doc/ssh/README.md +++ b/doc/ssh/README.md @@ -15,7 +15,8 @@ Note: It is a best practice to use a password for an SSH key, but it is not required and you can skip creating a password by pressing enter. Note that the password you choose here can't be altered or retrieved. -To generate a new SSH key, use the following commandGitLab```bash +To generate a new SSH key, use the following command: +```bash ssh-keygen -t rsa -C "$your_email" ``` This command will prompt you for a location and filename to store the key @@ -108,4 +109,4 @@ Note in the gitlab.com example above a username was specified to override the de Due to the wide variety of SSH clients and their very large number of configuration options, further explanation of these topics is beyond the scope of this document. Public SSH keys need to be unique, as they will bind to your account. Your SSH key is the only identifier you'll -have when pushing code via SSH. That's why it needs to uniquely map to a single user. +have when pushing code via SSH. That's why it needs to uniquely map to a single user. \ No newline at end of file diff --git a/doc/update/8.1-to-8.2.md b/doc/update/8.1-to-8.2.md index b57e999cfb..46dfa2232b 100644 --- a/doc/update/8.1-to-8.2.md +++ b/doc/update/8.1-to-8.2.md @@ -68,7 +68,7 @@ sudo -u git -H git checkout 8-2-stable-ee ```bash cd /home/git/gitlab-shell sudo -u git -H git fetch -sudo -u git -H git checkout v2.6.7 +sudo -u git -H git checkout v2.6.8 ``` ### 5. Replace gitlab-git-http-server with gitlab-workhorse @@ -85,11 +85,10 @@ sudo -u git -H git checkout 0.4.2 sudo -u git -H make ``` -Update the GitLab init script and 'default' file. +Update the GitLab 'default' file. ``` cd /home/git/gitlab -sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab test -e /etc/default/gitlab && \ sudo sed -i.pre-8.2 's/^\([^=]*\)gitlab_git_http_server/\1gitlab_workhorse/' /etc/default/gitlab ``` @@ -143,7 +142,7 @@ git diff origin/8-1-stable:lib/support/nginx/gitlab origin/8-2-stable:lib/suppor If you are using Apache instead of NGINX please see the updated [Apache templates]. Also note that because Apache does not support upstreams behind Unix sockets you -will need to let gitlab-git-http-server listen on a TCP port. You can do this +will need to let gitlab-workhorse listen on a TCP port. You can do this via [/etc/default/gitlab]. [Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache diff --git a/doc/update/8.2-to-8.3.md b/doc/update/8.2-to-8.3.md new file mode 100644 index 0000000000..c4661dc16a --- /dev/null +++ b/doc/update/8.2-to-8.3.md @@ -0,0 +1,202 @@ +# From 8.2 to 8.3 + +**NOTE:** GitLab 8.0 introduced several significant changes related to +installation and configuration which *are not duplicated here*. Be sure you're +already running a working version of at least 8.0 before proceeding with this +guide. + +### 0. Double-check your Git version + +**This notice applies only to /usr/local/bin/git** + +If you compiled Git from source on your GitLab server then please double-check +that you are using a version that protects against CVE-2014-9390. For six +months after this vulnerability became known the GitLab installation guide +still contained instructions that would install the outdated, 'vulnerable' Git +version 2.1.2. + +Run the following command to get your current Git version: + +```sh +/usr/local/bin/git --version +``` + +If you see 'No such file or directory' then you did not install Git according +to the outdated instructions from the GitLab installation guide and you can go +to the next step 'Stop server' below. + +If you see a version string then it should be v1.8.5.6, v1.9.5, v2.0.5, v2.1.4, +v2.2.1 or newer. You can use the [instructions in the GitLab source installation +guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies) +to install a newer version of Git. + +### 1. Stop server + + sudo service gitlab stop + +### 2. Backup + +```bash +cd /home/git/gitlab +sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production +``` + +### 3. Get latest code + +```bash +sudo -u git -H git fetch --all +sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically +``` + +For GitLab Community Edition: + +```bash +sudo -u git -H git checkout 8-3-stable +``` + +OR + +For GitLab Enterprise Edition: + +```bash +sudo -u git -H git checkout 8-3-stable-ee +``` + +### 4. Update gitlab-shell + +```bash +cd /home/git/gitlab-shell +sudo -u git -H git fetch --all +sudo -u git -H git checkout v2.6.9 +``` + +### 5. Update gitlab-workhorse + +Install and compile gitlab-workhorse. This requires [Go 1.5](https://golang.org/dl) +which should already be on your system from GitLab 8.1. + +```bash +cd /home/git/gitlab-workhorse +sudo -u git -H git fetch --all +sudo -u git -H git checkout 0.5.1 +sudo -u git -H make +``` + +### 6. Install libs, migrations, etc. + +```bash +cd /home/git/gitlab + +# MySQL installations (note: the line below states '--without postgres') +sudo -u git -H bundle install --without postgres development test --deployment + +# PostgreSQL installations (note: the line below states '--without mysql') +sudo -u git -H bundle install --without mysql development test --deployment + +# Run database migrations +sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production + +# Clean up assets and cache +sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production + +# Update init.d script +sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab +``` + +### 7. Update configuration files + +#### New configuration options for `gitlab.yml` + +There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`: + +```sh +git diff origin/8-2-stable:config/gitlab.yml.example origin/8-3-stable:config/gitlab.yml.example +``` + +#### Nginx configuration + +GitLab 8.3 introduces major changes in the NGINX configuration. +Because all HTTP requests pass through gitlab-workhorse now a lot of +directives need to be removed from NGINX. During future upgrades there +should be much less changes in the NGINX configuration because of +this. + +View changes between the previous recommended Nginx configuration and the +current one: + +```sh +# For HTTPS configurations +git diff origin/8-2-stable:lib/support/nginx/gitlab-ssl origin/8-3-stable:lib/support/nginx/gitlab-ssl + +# For HTTP configurations +git diff origin/8-2-stable:lib/support/nginx/gitlab origin/8-3-stable:lib/support/nginx/gitlab +``` + +If you are using Apache instead of NGINX please see the updated [Apache templates]. +Also note that because Apache does not support upstreams behind Unix sockets you +will need to let gitlab-workhorse listen on a TCP port. You can do this +via [/etc/default/gitlab]. + +[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache +[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-3-stable/lib/support/init.d/gitlab.default.example#L34 + +#### Init script + +We updated the init script for GitLab in order to pass new +configuration options to gitlab-workhorse. We let gitlab-workhorse +connect to the Rails application via a Unix domain socket and we tell +it where the 'public' directory of GitLab is. + +``` +cd /home/git/gitlab +sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab +``` + +### 8. Use Redis v2.8.0+ + +Previous versions of GitLab allowed Redis versions >= 2.0 to be used, but +GitLab 8.3 uses Sidekiq 4.0, which requires Redis 2.8. You can check your Redis version +with the following command: + + redis-cli info | grep redis_version + +If you need to upgrade, see the [installation guide for Redis](https://gitlab.com/gitlab-org/gitlab-ce/blob/8-3-stable/doc/install/installation.md#6-redis). + +### 9. Start application + + sudo service gitlab start + sudo service nginx restart + +### 10. Check application status + +Check if GitLab and its environment are configured correctly: + + sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production + +To make sure you didn't miss anything run a more thorough check: + + sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production + +If all items are green, then congratulations, the upgrade is complete! + +## Things went south? Revert to previous version (8.2) + +### 1. Revert the code to the previous version + +Follow the [upgrade guide from 8.1 to 8.2](8.1-to-8.2.md), except for the +database migration (the backup is already migrated to the previous version). + +### 2. Restore from the backup + +```bash +cd /home/git/gitlab +sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production +``` + +If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above. + +## Troubleshooting + +### "You appear to have cloned an empty repository." + +See the [7.14 to 8.0 update guide](7.14-to-8.0.md#troubleshooting). diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md index 593722eb01..c19ee49f9e 100644 --- a/doc/update/patch_versions.md +++ b/doc/update/patch_versions.md @@ -6,7 +6,8 @@ For example from 7.14.0 to 7.14.3, also see the [semantic versioning specificati ### 0. Backup It's useful to make a backup just in case things go south: -(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version) +(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab +user on the database version) ```bash cd /home/git/gitlab @@ -15,19 +16,23 @@ sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production ### 1. Stop server - sudo service gitlab stop +```bash +sudo service gitlab stop +``` ### 2. Get latest code for the stable branch +In the commands below, replace `LATEST_TAG` with the latest GitLab tag you want +to update to, for example `v8.0.3`. Use `git tag -l 'v*.[0-9]' --sort='v:refname'` +to see a list of all tags. Make sure to update patch versions only (check your +current version with `cat VERSION`). + ```bash cd /home/git/gitlab sudo -u git -H git fetch --all sudo -u git -H git checkout -- Gemfile.lock db/schema.rb sudo -u git -H git checkout LATEST_TAG -b LATEST_TAG ``` -Replace `LATEST_TAG` with the latest GitLab tag you want to update to, for example `v8.0.3`. -Use `git tag -l 'v*.[0-9]' --sort='v:refname'` to see a list of all tags. -Make sure to update patch versions only (check your current version with `cat VERSION`) ### 3. Update gitlab-shell to the corresponding version @@ -37,12 +42,20 @@ sudo -u git -H git fetch sudo -u git -H git checkout v`cat /home/git/gitlab/GITLAB_SHELL_VERSION` -b v`cat /home/git/gitlab/GITLAB_SHELL_VERSION` ``` -### 4. Install libs, migrations, etc. +### 4. Update gitlab-workhorse to the corresponding version + +```bash +cd /home/git/gitlab-workhorse +sudo -u git -H git fetch +sudo -u git -H git checkout `cat /home/git/gitlab/GITLAB_WORKHORSE_VERSION` -b `cat /home/git/gitlab/GITLAB_WORKHORSE_VERSION` +``` + +### 5. Install libs, migrations, etc. ```bash cd /home/git/gitlab -#PostgreSQL +# PostgreSQL sudo -u git -H bundle install --without development test mysql --deployment # MySQL @@ -52,19 +65,25 @@ sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production ``` -### 5. Start application +### 6. Start application - sudo service gitlab start - sudo service nginx restart +```bash +sudo service gitlab start +sudo service nginx restart +``` -### 6. Check application status +### 7. Check application status Check if GitLab and its environment are configured correctly: - sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production +```bash +sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production +``` To make sure you didn't miss anything run a more thorough check with: - sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production +```bash +sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production +``` If all items are green, then congratulations upgrade complete! diff --git a/doc/web_hooks/web_hooks.md b/doc/web_hooks/web_hooks.md index 7d838187a2..6420d65cf1 100644 --- a/doc/web_hooks/web_hooks.md +++ b/doc/web_hooks/web_hooks.md @@ -57,6 +57,9 @@ X-Gitlab-Event: Push Hook "name": "Jordi Mallach", "email": "jordi@softcatala.org" } + "added": ["CHANGELOG"], + "modified": ["app/controller/application.rb"], + "removed": [] }, { "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", @@ -66,13 +69,14 @@ X-Gitlab-Event: Push Hook "author": { "name": "GitLab dev user", "email": "gitlabdev@dv6700.(none)" - } + }, + "added": ["CHANGELOG"], + "modified": ["app/controller/application.rb"], + "removed": [] } ], - "total_commits_count": 4, - "added": ["CHANGELOG"], - "modified": ["app/controller/application.rb"], - "removed": [] + "total_commits_count": 4 + } ``` @@ -184,7 +188,7 @@ X-Gitlab-Event: Note Hook { "object_kind": "note", "user": { - "name": "Adminstrator", + "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" }, @@ -337,7 +341,7 @@ X-Gitlab-Event: Note Hook { "object_kind": "note", "user": { - "name": "Adminstrator", + "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" }, diff --git a/doc/workflow/README.md b/doc/workflow/README.md index a6b4d95118..3651b55f43 100644 --- a/doc/workflow/README.md +++ b/doc/workflow/README.md @@ -17,4 +17,6 @@ - [Milestones](milestones.md) - [Merge Requests](merge_requests.md) - ["Work In Progress" Merge Requests](wip_merge_requests.md) +- [Merge When Build Succeeds](merge_when_build_succeeds.md) - [Manage large binaries with Git LFS](lfs/manage_large_binaries_with_git_lfs.md) +- [Importing from SVN, GitHub, BitBucket, etc](importing/README.md) diff --git a/doc/workflow/importing/README.md b/doc/workflow/importing/README.md index 7ccf06fbd6..18e5d95086 100644 --- a/doc/workflow/importing/README.md +++ b/doc/workflow/importing/README.md @@ -1,13 +1,17 @@ # Migrating projects to a GitLab instance 1. [Bitbucket](import_projects_from_bitbucket.md) -2. [GitHub](import_projects_from_github.md) -3. [GitLab.com](import_projects_from_gitlab_com.md) -4. [FogBugz](import_projects_from_fogbugz.md) -4. [SVN](migrating_from_svn.md) +1. [GitHub](import_projects_from_github.md) +1. [GitLab.com](import_projects_from_gitlab_com.md) +1. [FogBugz](import_projects_from_fogbugz.md) +1. [SVN](migrating_from_svn.md) -### Note -* If you'd like to migrate from a self-hosted GitLab instance to GitLab.com, you can copy your repos by changing the remote and pushing to the new server; but issues and merge requests can't be imported. +In addition to the specific migration documentation above, you can import any +Git repository via HTTP from the New Project page. Be aware that if the +repository is too large the import can timeout. + +### Migrating from self-hosted GitLab to GitLab.com + +You can copy your repos by changing the remote and pushing to the new server; +but issues and merge requests can't be imported. -* You can import any Git repository via HTTP from the New Project page. -If the repository is too large, it can timeout. diff --git a/doc/workflow/importing/migrating_from_svn.md b/doc/workflow/importing/migrating_from_svn.md index 1938ccd0c2..b355a91b5a 100644 --- a/doc/workflow/importing/migrating_from_svn.md +++ b/doc/workflow/importing/migrating_from_svn.md @@ -1,17 +1,78 @@ # Migrating from SVN to GitLab -SVN stands for Subversion and is a version control system (VCS). -Git is a distributed version control system. +Subversion (SVN) is a central version control system (VCS) while +Git is a distributed version control system. There are some major differences +between the two, for more information consult your favorite search engine. -There are some major differences between the two, for more information consult your favorite search engine. +If you are currently using an SVN repository, you can migrate the repository +to Git and GitLab. We recommend a hard cut over - run the migration command once +and then have all developers start using the new GitLab repository immediately. +Otherwise, it's hard to keep changing in sync in both directions. The conversion +process should be run on a local workstation. -Git has tools for migrating SVN repositories to git, namely `git svn`. You can read more about this at -[git documentation pages](https://git-scm.com/book/en/Git-and-Other-Systems-Git-and-Subversion). +Install `svn2git`. On all systems you can install as a Ruby gem if you already +have Ruby and Git installed. -Apart from the [official git documentation](https://git-scm.com/book/en/Git-and-Other-Systems-Migrating-to-Git) there is also -user created step by step guide for migrating from SVN to GitLab. +```bash +sudo gem install svn2git +``` -[Benjamin New](https://github.com/leftclickben) wrote [a guide that shows how to do a migration](https://gist.github.com/leftclickben/322b7a3042cbe97ed2af). Mirrors can be found [here](https://gitlab.com/snippets/2168) and [here](https://gist.github.com/maxlazio/f1b593b0d00aa966e9ca). +On Debian-based Linux distributions you can install the native packages: + +```bash +sudo apt-get install git-core git-svn ruby +``` + +Optionally, prepare an authors file so `svn2git` can map SVN authors to Git authors. +If you choose not to create the authors file then commits will not be attributed +to the correct GitLab user. Some users may not consider this a big issue while +others will want to ensure they complete this step. If you choose to map authors +you will be required to map every author that is present on changes in the SVN +repository. If you don't, the conversion will fail and you will have to update +the author file accordingly. The following command will search through the +repository and output a list of authors. + +```bash +svn log --quiet | grep -E "r[0-9]+ \| .+ \|" | cut -d'|' -f2 | sed 's/ //g' | sort | uniq +``` + +Use the output from the last command to construct the authors file. +Create a file called `authors.txt` and add one mapping per line. + +``` +janedoe = Jane Doe +johndoe = John Doe +``` + +If your SVN repository is in the standard format (trunk, branches, tags, +not nested) the conversion is simple. For a non-standard repository see +[svn2git documentation](https://github.com/nirvdrum/svn2git). The following +command will checkout the repository and do the conversion in the current +working directory. Be sure to create a new directory for each repository before +running the `svn2git` command. The conversion process will take some time. + +```bash +svn2git https://svn.example.com/path/to/repo --authors /path/to/authors.txt +``` + +If your SVN repository requires a username and password add the +`--username ` and `--password /.git +git push --all origin +``` ## Contribute to this guide -We welcome all contributions that would expand this guide with instructions on how to migrate from SVN and other version control systems. +We welcome all contributions that would expand this guide with instructions on +how to migrate from SVN and other version control systems. + + diff --git a/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md b/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md index 210a8f71c3..b59e92cb31 100644 --- a/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md +++ b/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md @@ -121,6 +121,6 @@ git config --global credential.helper 'cache --timeout=3600' This will remember the credentials for an hour after which Git operations will require re-authentication. -If you are using OS X you can use `osxkeychain` to store and encrypt your credentials. For Windows, `wincred` is available. +If you are using OS X you can use `osxkeychain` to store and encrypt your credentials. For Windows, you can use `wincred` or Microsoft's [Git Credential Manager for Windows](https://github.com/Microsoft/Git-Credential-Manager-for-Windows/releases). -More details about various methods of storing the user credentials can be found on [Git Credential Storage documentation](https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage). +More details about various methods of storing the user credentials can be found on [Git Credential Storage documentation](https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage). \ No newline at end of file diff --git a/doc/workflow/merge_when_build_succeeds.md b/doc/workflow/merge_when_build_succeeds.md new file mode 100644 index 0000000000..75e1fdff2b --- /dev/null +++ b/doc/workflow/merge_when_build_succeeds.md @@ -0,0 +1,15 @@ +# Merge When Build Succeeds + +When reviewing a merge request that looks ready to merge but still has one or more CI builds running, you can set it to be merged automatically when all builds succeed. This way, you don't have to wait for the builds to finish and remember to merge the request manually. + +![Enable](merge_when_build_succeeds/enable.png) + +When you hit the "Merge When Build Succeeds" button, the status of the merge request will be updated to represent the impending merge. If you cannot wait for the build to succeed and want to merge immediately, this option is available in the dropdown menu on the right of the main button. + +Both team developers and the author of the merge request have the option to cancel the automatic merge if they find a reason why it shouldn't be merged after all. + +![Status](merge_when_build_succeeds/status.png) + +When the build succeeds, the merge request will automatically be merged. When the build fails, the author gets a chance to retry any failed builds, or to push new commits to fix the failure. + +When the builds are retried and succeed on the second try, the merge request will automatically be merged after all. When the merge request is updated with new commits, the automatic merge is automatically canceled to allow the new changes to be reviewed. diff --git a/doc/workflow/merge_when_build_succeeds/enable.png b/doc/workflow/merge_when_build_succeeds/enable.png new file mode 100644 index 0000000000000000000000000000000000000000..633efa1246f997ba0070c5ca483c9ac4057dc20b GIT binary patch literal 151112 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 literal 0 HcmV?d00001 diff --git a/doc/workflow/merge_when_build_succeeds/status.png b/doc/workflow/merge_when_build_succeeds/status.png new file mode 100644 index 0000000000000000000000000000000000000000..c856c7d14dc6ba2f0c89f3e6d7c0e3de39e0dcfe GIT binary patch literal 180318 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

M$^a^8jm41-_{C#PI0dj6faq1`ClUL&ToH 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 DsM0JO literal 0 HcmV?d00001 diff --git a/features/admin/groups.feature b/features/admin/groups.feature index 973918086a..2edb3964f7 100644 --- a/features/admin/groups.feature +++ b/features/admin/groups.feature @@ -33,3 +33,19 @@ Feature: Admin Groups When I visit admin group page When I select user "johndoe@gitlab.com" from user list as "Reporter" Then I should see "johndoe@gitlab.com" in team list in every project as "Reporter" + + @javascript + Scenario: Signed in admin should be able to add himself to a group + Given "John Doe" is owner of group "Owned" + When I visit group "Owned" members page + When I select current user as "Developer" + Then I should see current user as "Developer" + + @javascript + Scenario: Signed in admin should be able to remove himself from group + Given current user is developer of group "Owned" + When I visit group "Owned" members page + Then I should see current user as "Developer" + When I click on the "Remove User From Group" button for current user + When I visit group "Owned" members page + Then I should not see current user as "Developer" diff --git a/features/admin/projects.feature b/features/admin/projects.feature index f7cec04eb7..c5ee80136c 100644 --- a/features/admin/projects.feature +++ b/features/admin/projects.feature @@ -27,3 +27,19 @@ Feature: Admin Projects And I visit admin project page When I transfer project to group 'Web' Then I should see project transfered + + @javascript + Scenario: Signed in admin should be able to add himself to a project + Given "John Doe" owns private project "Enterprise" + When I visit project "Enterprise" members page + When I select current user as "Developer" + Then I should see current user as "Developer" + + @javascript + Scenario: Signed in admin should be able to remove himself from a project + Given "John Doe" owns private project "Enterprise" + And current user is developer of project "Enterprise" + When I visit project "Enterprise" members page + Then I should see current user as "Developer" + When I click on the "Remove User From Project" button for current user + Then I should not see current user as "Developer" diff --git a/features/explore/projects.feature b/features/explore/projects.feature index 5d3870827f..629859e960 100644 --- a/features/explore/projects.feature +++ b/features/explore/projects.feature @@ -31,8 +31,17 @@ Feature: Explore Projects Then I should see empty public project details And I should see empty public project details with http clone info - Scenario: I visit an empty public project page as user + Scenario: I visit an empty public project page as user with no ssh-keys Given I sign in as a user + And I have no ssh keys + And public empty project "Empty Public Project" + When I visit empty project page + Then I should see empty public project details + And I should see empty public project details with http clone info + + Scenario: I visit an empty public project page as user with an ssh-key + Given I sign in as a user + And I have an ssh key And public empty project "Empty Public Project" When I visit empty project page Then I should see empty public project details @@ -57,8 +66,16 @@ Feature: Explore Projects Then I should see project "Community" home page And I should see an http link to the repository - Scenario: I visit public project page as user + Scenario: I visit public project page as user with no ssh-keys Given I sign in as a user + And I have no ssh keys + When I visit project "Community" page + Then I should see project "Community" home page + And I should see an http link to the repository + + Scenario: I visit public project page as user with an ssh-key + Given I sign in as a user + And I have an ssh key When I visit project "Community" page Then I should see project "Community" home page And I should see an ssh link to the repository diff --git a/features/group/members.feature b/features/group/members.feature new file mode 100644 index 0000000000..1f9514bac3 --- /dev/null +++ b/features/group/members.feature @@ -0,0 +1,105 @@ +Feature: Group Members + Background: + Given I sign in as "John Doe" + And "John Doe" is owner of group "Owned" + And "John Doe" is guest of group "Guest" + + @javascript + Scenario: I should add user to group "Owned" + Given User "Mary Jane" exists + When I visit group "Owned" members page + And I select user "Mary Jane" from list with role "Reporter" + Then I should see user "Mary Jane" in team list + + @javascript + Scenario: Add user to group + Given gitlab user "Mike" + When I visit group "Owned" members page + When I select "Mike" as "Reporter" + Then I should see "Mike" in team list as "Reporter" + + @javascript + Scenario: Ignore add user to group when is already Owner + Given gitlab user "Mike" + When I visit group "Owned" members page + When I select "Mike" as "Reporter" + Then I should see "Mike" in team list as "Owner" + + @javascript + Scenario: Invite user to group + When I visit group "Owned" members page + When I select "sjobs@apple.com" as "Reporter" + Then I should see "sjobs@apple.com" in team list as invited "Reporter" + + @javascript + Scenario: Edit group member permissions + Given "Mary Jane" is guest of group "Owned" + And I visit group "Owned" members page + When I change the "Mary Jane" role to "Developer" + Then I should see "Mary Jane" as "Developer" + + # Leave + + @javascript + Scenario: Owner should be able to remove himself from group if he is not the last owner + Given "Mary Jane" is owner of group "Owned" + When I visit group "Owned" members page + Then I should see user "John Doe" in team list + Then I should see user "Mary Jane" in team list + When I click on the "Remove User From Group" button for "John Doe" + And I visit group "Owned" members page + Then I should not see user "John Doe" in team list + Then I should see user "Mary Jane" in team list + + @javascript + Scenario: Owner should not be able to remove himself from group if he is the last owner + Given "Mary Jane" is guest of group "Owned" + When I visit group "Owned" members page + Then I should see user "John Doe" in team list + Then I should see user "Mary Jane" in team list + Then I should not see the "Remove User From Group" button for "John Doe" + + @javascript + Scenario: Guest should be able to remove himself from group + Given "Mary Jane" is guest of group "Guest" + When I visit group "Guest" members page + Then I should see user "John Doe" in team list + Then I should see user "Mary Jane" in team list + When I click on the "Remove User From Group" button for "John Doe" + When I visit group "Guest" members page + Then I should not see user "John Doe" in team list + Then I should see user "Mary Jane" in team list + + @javascript + Scenario: Guest should be able to remove himself from group even if he is the only user in the group + When I visit group "Guest" members page + Then I should see user "John Doe" in team list + When I click on the "Remove User From Group" button for "John Doe" + When I visit group "Guest" members page + Then I should not see user "John Doe" in team list + + # Remove others + + Scenario: Owner should be able to remove other users from group + Given "Mary Jane" is owner of group "Owned" + When I visit group "Owned" members page + Then I should see user "John Doe" in team list + Then I should see user "Mary Jane" in team list + When I click on the "Remove User From Group" button for "Mary Jane" + When I visit group "Owned" members page + Then I should see user "John Doe" in team list + Then I should not see user "Mary Jane" in team list + + Scenario: Guest should not be able to remove other users from group + Given "Mary Jane" is guest of group "Guest" + When I visit group "Guest" members page + Then I should see user "John Doe" in team list + Then I should see user "Mary Jane" in team list + Then I should not see the "Remove User From Group" button for "Mary Jane" + + Scenario: Search member by name + Given "Mary Jane" is guest of group "Guest" + And I visit group "Guest" members page + When I search for 'Mary' member + Then I should see user "Mary Jane" in team list + Then I should not see user "John Doe" in team list diff --git a/features/group/milestones.feature b/features/group/milestones.feature new file mode 100644 index 0000000000..62ea66a783 --- /dev/null +++ b/features/group/milestones.feature @@ -0,0 +1,30 @@ +Feature: Group Milestones + Background: + Given I sign in as "John Doe" + And "John Doe" is owner of group "Owned" + + Scenario: I should see group "Owned" milestone index page with no milestones + When I visit group "Owned" page + And I click on group milestones + Then I should see group milestones index page has no milestones + + Scenario: I should see group "Owned" milestone index page with milestones + Given Group has projects with milestones + When I visit group "Owned" page + And I click on group milestones + Then I should see group milestones index page with milestones + + Scenario: I should see group "Owned" milestone show page + Given Group has projects with milestones + When I visit group "Owned" page + And I click on group milestones + And I click on one group milestone + Then I should see group milestone with descriptions and expiry date + And I should see group milestone with all issues and MRs assigned to that milestone + + Scenario: Create multiple milestones with one form + Given I visit group "Owned" milestones page + And I click new milestone button + And I fill milestone name + When I press create mileston button + Then milestone in each project should be created diff --git a/features/groups.feature b/features/groups.feature index abf3769a84..c803e95298 100644 --- a/features/groups.feature +++ b/features/groups.feature @@ -2,7 +2,6 @@ Feature: Groups Background: Given I sign in as "John Doe" And "John Doe" is owner of group "Owned" - And "John Doe" is guest of group "Guest" Scenario: I should have back to group button When I visit group "Owned" page @@ -24,13 +23,6 @@ Feature: Groups When I visit group "Owned" merge requests page Then I should see merge requests from group "Owned" assigned to me - @javascript - Scenario: I should add user to projects in group "Owned" - Given User "Mary Jane" exists - When I visit group "Owned" members page - And I select user "Mary Jane" from list with role "Reporter" - Then I should see user "Mary Jane" in team list - Scenario: I should see edit group "Owned" page When I visit group "Owned" settings page And I change group "Owned" name to "new-name" @@ -51,123 +43,6 @@ Feature: Groups Then I should not see group "Owned" avatar And I should not see the "Remove avatar" button - @javascript - Scenario: Add user to group - Given gitlab user "Mike" - When I visit group "Owned" members page - And I click link "Add members" - When I select "Mike" as "Reporter" - Then I should see "Mike" in team list as "Reporter" - - @javascript - Scenario: Ignore add user to group when is already Owner - Given gitlab user "Mike" - When I visit group "Owned" members page - And I click link "Add members" - When I select "Mike" as "Reporter" - Then I should see "Mike" in team list as "Owner" - - @javascript - Scenario: Invite user to group - When I visit group "Owned" members page - And I click link "Add members" - When I select "sjobs@apple.com" as "Reporter" - Then I should see "sjobs@apple.com" in team list as invited "Reporter" - - # Leave - - @javascript - Scenario: Owner should be able to remove himself from group if he is not the last owner - Given "Mary Jane" is owner of group "Owned" - When I visit group "Owned" members page - Then I should see user "John Doe" in team list - Then I should see user "Mary Jane" in team list - When I click on the "Remove User From Group" button for "John Doe" - And I visit group "Owned" members page - Then I should not see user "John Doe" in team list - Then I should see user "Mary Jane" in team list - - @javascript - Scenario: Owner should not be able to remove himself from group if he is the last owner - Given "Mary Jane" is guest of group "Owned" - When I visit group "Owned" members page - Then I should see user "John Doe" in team list - Then I should see user "Mary Jane" in team list - Then I should not see the "Remove User From Group" button for "John Doe" - - @javascript - Scenario: Guest should be able to remove himself from group - Given "Mary Jane" is guest of group "Guest" - When I visit group "Guest" members page - Then I should see user "John Doe" in team list - Then I should see user "Mary Jane" in team list - When I click on the "Remove User From Group" button for "John Doe" - When I visit group "Guest" members page - Then I should not see user "John Doe" in team list - Then I should see user "Mary Jane" in team list - - @javascript - Scenario: Guest should be able to remove himself from group even if he is the only user in the group - When I visit group "Guest" members page - Then I should see user "John Doe" in team list - When I click on the "Remove User From Group" button for "John Doe" - When I visit group "Guest" members page - Then I should not see user "John Doe" in team list - - # Remove others - - Scenario: Owner should be able to remove other users from group - Given "Mary Jane" is owner of group "Owned" - When I visit group "Owned" members page - Then I should see user "John Doe" in team list - Then I should see user "Mary Jane" in team list - When I click on the "Remove User From Group" button for "Mary Jane" - When I visit group "Owned" members page - Then I should see user "John Doe" in team list - Then I should not see user "Mary Jane" in team list - - Scenario: Guest should not be able to remove other users from group - Given "Mary Jane" is guest of group "Guest" - When I visit group "Guest" members page - Then I should see user "John Doe" in team list - Then I should see user "Mary Jane" in team list - Then I should not see the "Remove User From Group" button for "Mary Jane" - - Scenario: Search member by name - Given "Mary Jane" is guest of group "Guest" - And I visit group "Guest" members page - When I search for 'Mary' member - Then I should see user "Mary Jane" in team list - Then I should not see user "John Doe" in team list - - # Group milestones - - Scenario: I should see group "Owned" milestone index page with no milestones - When I visit group "Owned" page - And I click on group milestones - Then I should see group milestones index page has no milestones - - Scenario: I should see group "Owned" milestone index page with milestones - Given Group has projects with milestones - When I visit group "Owned" page - And I click on group milestones - Then I should see group milestones index page with milestones - - Scenario: I should see group "Owned" milestone show page - Given Group has projects with milestones - When I visit group "Owned" page - And I click on group milestones - And I click on one group milestone - Then I should see group milestone with descriptions and expiry date - And I should see group milestone with all issues and MRs assigned to that milestone - - Scenario: Create multiple milestones with one form - Given I visit group "Owned" milestones page - And I click new milestone button - And I fill milestone name - When I press create mileston button - Then milestone in each project should be created - # Group projects in settings Scenario: I should see all projects in the project list in settings Given Group "Owned" has archived project diff --git a/features/project/active_tab.feature b/features/project/active_tab.feature index 8661ea98c2..2fd097d100 100644 --- a/features/project/active_tab.feature +++ b/features/project/active_tab.feature @@ -20,11 +20,6 @@ Feature: Project Active Tab Then the active main tab should be Commits And no other main tabs should be active - Scenario: On Project Network - Given I visit my project's network page - Then the active main tab should be Network - And no other main tabs should be active - Scenario: On Project Issues Given I visit my project's issues page Then the active main tab should be Issues @@ -83,6 +78,12 @@ Feature: Project Active Tab And no other sub tabs should be active And the active main tab should be Commits + Scenario: On Project Commits/Network + Given I visit my project's network page + Then the active sub tab should be Network + And no other sub tabs should be active + And the active main tab should be Commits + Scenario: On Project Commits/Compare Given I visit my project's commits page And I click the "Compare" tab diff --git a/features/project/commits/branches.feature b/features/project/commits/branches.feature index 65d8e48b9b..5103ca1294 100644 --- a/features/project/commits/branches.feature +++ b/features/project/commits/branches.feature @@ -1,3 +1,4 @@ +@project_commits Feature: Project Commits Branches Background: Given I sign in as a user diff --git a/features/project/commits/comments.feature b/features/project/commits/comments.feature index 320f008abb..fafb54b183 100644 --- a/features/project/commits/comments.feature +++ b/features/project/commits/comments.feature @@ -1,3 +1,4 @@ +@project_commits Feature: Project Commits Comments Background: Given I sign in as a user diff --git a/features/project/commits/commits.feature b/features/project/commits/commits.feature index e4beeb59ad..5bb2d0e976 100644 --- a/features/project/commits/commits.feature +++ b/features/project/commits/commits.feature @@ -1,3 +1,4 @@ +@project_commits Feature: Project Commits Background: Given I sign in as a user @@ -18,7 +19,8 @@ Feature: Project Commits Scenario: I browse commit with ci from list Given commit has ci status - And I click on commit link + And repository contains ".gitlab-ci.yml" file + When I click on commit link Then I see commit ci info And I click status link Then I see builds list diff --git a/features/project/commits/diff_comments.feature b/features/project/commits/diff_comments.feature index 4a2b870e08..2bde4c8a99 100644 --- a/features/project/commits/diff_comments.feature +++ b/features/project/commits/diff_comments.feature @@ -1,3 +1,4 @@ +@project_commits Feature: Project Commits Diff Comments Background: Given I sign in as a user @@ -13,6 +14,12 @@ Feature: Project Commits Diff Comments Given I leave a diff comment like "Typo, please fix" Then I should see a diff comment saying "Typo, please fix" + @javascript + Scenario: I can add a diff comment with a single emoji + Given I open a diff comment form + And I write a diff comment like ":smile:" + Then I should see a diff comment with an emoji image + @javascript Scenario: I get a temporary form for the first comment on a diff line Given I open a diff comment form diff --git a/features/project/commits/tags.feature b/features/project/commits/tags.feature index 56ee091acc..a4be39b2d4 100644 --- a/features/project/commits/tags.feature +++ b/features/project/commits/tags.feature @@ -1,3 +1,4 @@ +@project_commits Feature: Project Commits Tags Background: Given I sign in as a user diff --git a/features/project/commits/user_lookup.feature b/features/project/commits/user_lookup.feature index db51d4a6cf..c18f4e070f 100644 --- a/features/project/commits/user_lookup.feature +++ b/features/project/commits/user_lookup.feature @@ -1,3 +1,4 @@ +@project_commits Feature: Project Commits User Lookup Background: Given I sign in as a user diff --git a/features/project/create.feature b/features/project/create.feature index e9dc4fe6b3..a86079143e 100644 --- a/features/project/create.feature +++ b/features/project/create.feature @@ -7,6 +7,7 @@ Feature: Project Create Scenario: User create a project Given I sign in as a user When I visit new project page + And I have an ssh key And fill project form with valid data Then I should see project page And I should see empty project instuctions @@ -14,6 +15,7 @@ Feature: Project Create @javascript Scenario: Empty project instructions Given I sign in as a user + And I have an ssh key When I visit new project page And fill project form with valid data Then I see empty project instuctions diff --git a/features/project/graph.feature b/features/project/graph.feature index 2acd65aea5..63793d6f98 100644 --- a/features/project/graph.feature +++ b/features/project/graph.feature @@ -18,3 +18,8 @@ Feature: Project Graph Given project "Shop" has CI enabled When I visit project "Shop" CI graph page Then page should have CI graphs + + @javascript + Scenario: I should see project languages graphs + When I visit project "Shop" languages graph page + Then page should have languages graphs diff --git a/features/project/issues/award_emoji.feature b/features/project/issues/award_emoji.feature index a9bc8ffb9b..0ce99e855c 100644 --- a/features/project/issues/award_emoji.feature +++ b/features/project/issues/award_emoji.feature @@ -1,3 +1,4 @@ +@project_issues Feature: Award Emoji Background: Given I sign in as a user @@ -11,4 +12,8 @@ Feature: Award Emoji And I click to emoji in the picker Then I have award added And I can remove it by clicking to icon - \ No newline at end of file + + @javascript + Scenario: I add award emoji using regular comment + Given I leave comment with a single emoji + Then I have award added diff --git a/features/project/issues/filter_labels.feature b/features/project/issues/filter_labels.feature index e316f51986..e07f8053fb 100644 --- a/features/project/issues/filter_labels.feature +++ b/features/project/issues/filter_labels.feature @@ -1,3 +1,4 @@ +@project_issues Feature: Project Issues Filter Labels Background: Given I sign in as a user diff --git a/features/project/issues/issues.feature b/features/project/issues/issues.feature index 28cc43ef71..ab234bc750 100644 --- a/features/project/issues/issues.feature +++ b/features/project/issues/issues.feature @@ -1,3 +1,4 @@ +@project_issues Feature: Project Issues Background: Given I sign in as a user @@ -197,3 +198,8 @@ Feature: Project Issues And I submit new issue "500 error on profile" Then I should see issue "500 error on profile" + @javascript + Scenario: Another user adds a comment to issue I'm currently viewing + Given I visit issue page "Release 0.4" + And another user adds a comment with text "Yay!" to issue "Release 0.4" + Then I should see a new comment with text "Yay!" diff --git a/features/project/issues/labels.feature b/features/project/issues/labels.feature index 039a7d83cb..45de57f18e 100644 --- a/features/project/issues/labels.feature +++ b/features/project/issues/labels.feature @@ -1,3 +1,4 @@ +@project_issues Feature: Project Issues Labels Background: Given I sign in as a user diff --git a/features/project/issues/milestones.feature b/features/project/issues/milestones.feature index c1a20e9b48..1af05b3c32 100644 --- a/features/project/issues/milestones.feature +++ b/features/project/issues/milestones.feature @@ -1,3 +1,4 @@ +@project_issues Feature: Project Issues Milestones Background: Given I sign in as a user diff --git a/features/project/merge_requests.feature b/features/project/merge_requests.feature index 6cd081c868..aa9078b878 100644 --- a/features/project/merge_requests.feature +++ b/features/project/merge_requests.feature @@ -1,3 +1,4 @@ +@project_merge_requests Feature: Project Merge Requests Background: Given I sign in as a user @@ -83,6 +84,26 @@ Feature: Project Merge Requests And I switch to the merge request's comments tab Then I should see a discussion has started on diff + @javascript + Scenario: I edit a comment on a merge request diff + Given project "Shop" have "Bug NS-05" open merge request with diffs inside + And I visit merge request page "Bug NS-05" + And I click on the Changes tab + And I leave a comment like "Line is wrong" on diff + And I change the comment "Line is wrong" to "Typo, please fix" on diff + Then I should not see a diff comment saying "Line is wrong" + And I should see a diff comment saying "Typo, please fix" + + @javascript + Scenario: I delete a comment on a merge request diff + Given project "Shop" have "Bug NS-05" open merge request with diffs inside + And I visit merge request page "Bug NS-05" + And I click on the Changes tab + And I leave a comment like "Line is wrong" on diff + And I delete the comment "Line is wrong" on diff + And I click on the Discussion tab + Then I should not see any discussion + @javascript Scenario: I comment on a line of a commit in merge request Given project "Shop" have "Bug NS-05" open merge request with diffs inside diff --git a/features/project/merge_requests/accept.feature b/features/project/merge_requests/accept.feature new file mode 100644 index 0000000000..d5e4f2b0bd --- /dev/null +++ b/features/project/merge_requests/accept.feature @@ -0,0 +1,20 @@ +@project_merge_requests +Feature: Project Merge Requests Acceptance + Background: + Given There is an open Merge Request + And I am signed in as a developer of the project + + @javascript + Scenario: Accepting the Merge Request and removing the source branch + Given I am on the Merge Request detail page + When I click on "Remove source branch" option + And I click on Accept Merge Request + Then I should see merge request merged + And I should not see the Remove Source Branch button + + @javascript + Scenario: Accepting the Merge Request without removing the source branch + Given I am on the Merge Request detail page + When I click on Accept Merge Request + Then I should see merge request merged + And I should see the Remove Source Branch button diff --git a/features/project/service.feature b/features/project/service.feature index 5014b52b9f..3a7b830852 100644 --- a/features/project/service.feature +++ b/features/project/service.feature @@ -7,12 +7,6 @@ Feature: Project Services When I visit project "Shop" services page Then I should see list of available services - Scenario: Activate gitlab-ci service - When I visit project "Shop" services page - And I click gitlab-ci service link - And I fill gitlab-ci settings - Then I should see service settings saved - Scenario: Activate hipchat service When I visit project "Shop" services page And I click hipchat service link @@ -61,6 +55,12 @@ Feature: Project Services And I fill email on push settings Then I should see email on push service settings saved + Scenario: Activate JIRA service + When I visit project "Shop" services page + And I click jira service link + And I fill jira settings + Then I should see jira service settings saved + Scenario: Activate Irker (IRC Gateway) service When I visit project "Shop" services page And I click Irker service link diff --git a/features/project/shortcuts.feature b/features/project/shortcuts.feature index 0f71c32380..10e7c23461 100644 --- a/features/project/shortcuts.feature +++ b/features/project/shortcuts.feature @@ -19,7 +19,8 @@ Feature: Project Shortcuts @javascript Scenario: Navigate to network tab Given I press "g" and "n" - Then the active main tab should be Network + Then the active sub tab should be Network + And the active main tab should be Commits @javascript Scenario: Navigate to graphs tab diff --git a/features/project/source/browse_files.feature b/features/project/source/browse_files.feature index e545ea63ca..02159ee377 100644 --- a/features/project/source/browse_files.feature +++ b/features/project/source/browse_files.feature @@ -34,6 +34,17 @@ Feature: Project Source Browse Files Then I am redirected to the new file And I should see its new content + @javascript + Scenario: I can create and commit file with new lines at the end of file + Given I click on "New file" link in repo + And I edit code with new lines at end of file + And I fill the new file name + And I fill the commit message + And I click on "Commit Changes" + Then I am redirected to the new file + And I click button "Edit" + And I should see its content with new lines preserved at end of file + @javascript Scenario: I can upload file and commit Given I click on "Upload file" link in repo @@ -110,12 +121,6 @@ Feature: Project Source Browse Files Given I visit a binary file in the repo Then I cannot see the edit button - Scenario: If I don't have edit permission the edit link is disabled - Given public project "Community" - And I visit project "Community" source page - And I click on ".gitignore" file in repo - Then The edit button is disabled - @javascript Scenario: I can edit and commit file Given I click on ".gitignore" file in repo @@ -221,3 +226,9 @@ Feature: Project Source Browse Files Given I switch ref to fix And I visit the fix tree Then I see the commit data for a directory with a leading dot + + Scenario: I browse LFS object + Given I click on "files/lfs/lfs_object.iso" file in repo + Then I should see download link and object size + And I should not see lfs pointer details + And I should see buttons for allowed commands diff --git a/features/project/team_management.feature b/features/project/team_management.feature index 09a7df59df..06fb45c8bd 100644 --- a/features/project/team_management.feature +++ b/features/project/team_management.feature @@ -13,14 +13,12 @@ Feature: Project Team Management @javascript Scenario: Add user to project - Given I click link "Add members" - And I select "Mike" as "Reporter" + When I select "Mike" as "Reporter" Then I should see "Mike" in team list as "Reporter" @javascript Scenario: Invite user to project - Given I click link "Add members" - And I select "sjobs@apple.com" as "Reporter" + When I select "sjobs@apple.com" as "Reporter" Then I should see "sjobs@apple.com" in team list as invited "Reporter" @javascript diff --git a/features/steps/admin/groups.rb b/features/steps/admin/groups.rb index d27634858a..43fd91d0d4 100644 --- a/features/steps/admin/groups.rb +++ b/features/steps/admin/groups.rb @@ -1,5 +1,6 @@ class Spinach::Features::AdminGroups < Spinach::FeatureSteps include SharedAuthentication + include SharedGroup include SharedPaths include SharedUser include SharedActiveTab @@ -88,6 +89,34 @@ class Spinach::Features::AdminGroups < Spinach::FeatureSteps end end + step 'I select current user as "Developer"' do + page.within ".users-group-form" do + select2(current_user.id, from: "#user_ids", multiple: true) + select "Developer", from: "access_level" + end + + click_button "Add users to group" + end + + step 'I should see current user as "Developer"' do + page.within '.content-list' do + expect(page).to have_content(current_user.name) + expect(page).to have_content('Developer') + end + end + + step 'I click on the "Remove User From Group" button for current user' do + find(:css, 'li', text: current_user.name).find(:css, 'a.btn-remove').click + # poltergeist always confirms popups. + end + + step 'I should not see current user as "Developer"' do + page.within '.content-list' do + expect(page).not_to have_content(current_user.name) + expect(page).not_to have_content('Developer') + end + end + protected def current_group diff --git a/features/steps/admin/labels.rb b/features/steps/admin/labels.rb index b45d98658b..55ddcc2508 100644 --- a/features/steps/admin/labels.rb +++ b/features/steps/admin/labels.rb @@ -17,7 +17,7 @@ class Spinach::Features::AdminIssuesLabels < Spinach::FeatureSteps step 'I remove label \'bug\'' do page.within "#label_#{bug_label.id}" do - click_link 'Remove' + click_link 'Delete' end end @@ -45,21 +45,21 @@ class Spinach::Features::AdminIssuesLabels < Spinach::FeatureSteps step 'I submit new label \'support\'' do visit new_admin_label_path fill_in 'Title', with: 'support' - fill_in 'Background Color', with: '#F95610' + fill_in 'Background color', with: '#F95610' click_button 'Save' end step 'I submit new label \'bug\'' do visit new_admin_label_path fill_in 'Title', with: 'bug' - fill_in 'Background Color', with: '#F95610' + fill_in 'Background color', with: '#F95610' click_button 'Save' end step 'I submit new label with invalid color' do visit new_admin_label_path fill_in 'Title', with: 'support' - fill_in 'Background Color', with: '#12' + fill_in 'Background color', with: '#12' click_button 'Save' end @@ -71,7 +71,7 @@ class Spinach::Features::AdminIssuesLabels < Spinach::FeatureSteps step 'I should see label color error message' do page.within '.label-form' do - expect(page).to have_content 'Color is invalid' + expect(page).to have_content 'Color must be a valid color code' end end @@ -101,7 +101,7 @@ class Spinach::Features::AdminIssuesLabels < Spinach::FeatureSteps step 'I change label \'bug\' to \'fix\'' do fill_in 'Title', with: 'fix' - fill_in 'Background Color', with: '#F15610' + fill_in 'Background color', with: '#F15610' click_button 'Save' end diff --git a/features/steps/admin/projects.rb b/features/steps/admin/projects.rb index 5a1cc9aa15..a7a28755a6 100644 --- a/features/steps/admin/projects.rb +++ b/features/steps/admin/projects.rb @@ -3,6 +3,8 @@ class Spinach::Features::AdminProjects < Spinach::FeatureSteps include SharedPaths include SharedAdmin include SharedProject + include SharedUser + include Select2Helper step 'I should see all non-archived projects' do Project.non_archived.each do |p| @@ -56,6 +58,41 @@ class Spinach::Features::AdminProjects < Spinach::FeatureSteps expect(page).to have_content 'Namespace: Web' end + step 'I visit project "Enterprise" members page' do + project = Project.find_by!(name: "Enterprise") + visit namespace_project_project_members_path(project.namespace, project) + end + + step 'I select current user as "Developer"' do + page.within ".users-project-form" do + select2(current_user.id, from: "#user_ids", multiple: true) + select "Developer", from: "access_level" + end + + click_button "Add users to project" + end + + step 'I should see current user as "Developer"' do + page.within '.content-list' do + expect(page).to have_content(current_user.name) + expect(page).to have_content('Developer') + end + end + + step 'current user is developer of project "Enterprise"' do + project = Project.find_by!(name: "Enterprise") + project.team << [current_user, :developer] + end + + step 'I click on the "Remove User From Project" button for current user' do + find(:css, 'li', text: current_user.name).find(:css, 'a.btn-remove').click + # poltergeist always confirms popups. + end + + step 'I should not see current_user as "Developer"' do + expect(page).not_to have_selector(:css, '.content-list') + end + def project @project ||= Project.first end diff --git a/features/steps/admin/settings.rb b/features/steps/admin/settings.rb index 6acbf46eb2..037f7494a7 100644 --- a/features/steps/admin/settings.rb +++ b/features/steps/admin/settings.rb @@ -32,6 +32,7 @@ class Spinach::Features::AdminSettings < Spinach::FeatureSteps page.check('Comments') page.check('Issues events') page.check('Merge Request events') + page.check('Build events') click_on 'Save' end @@ -39,6 +40,7 @@ class Spinach::Features::AdminSettings < Spinach::FeatureSteps fill_in 'Webhook', with: 'http://localhost' fill_in 'Username', with: 'test_user' fill_in 'Channel', with: '#test_channel' + page.check('Notify only broken builds') end step 'I should see service template settings saved' do diff --git a/features/steps/dashboard/dashboard.rb b/features/steps/dashboard/dashboard.rb index f0fbd8a826..63f0ec2b6e 100644 --- a/features/steps/dashboard/dashboard.rb +++ b/features/steps/dashboard/dashboard.rb @@ -12,7 +12,7 @@ class Spinach::Features::Dashboard < Spinach::FeatureSteps end step 'I should see "Shop" project CI status' do - expect(page).to have_link "Build status: skipped" + expect(page).to have_link "Build skipped" end step 'I should see last push widget' do diff --git a/features/steps/explore/groups.rb b/features/steps/explore/groups.rb index 87cd33c37e..87f32e70d5 100644 --- a/features/steps/explore/groups.rb +++ b/features/steps/explore/groups.rb @@ -75,18 +75,18 @@ class Spinach::Features::ExploreGroups < Spinach::FeatureSteps name: projectname, path: "#{groupname}-#{projectname}", visibility_level: visibility_level - ) + ) create(:issue, title: "#{projectname} feature", project: project - ) + ) create(:merge_request, title: "#{projectname} feature implemented", source_project: project, target_project: project - ) + ) create(:closed_issue_event, project: project - ) + ) end end diff --git a/features/steps/explore/projects.rb b/features/steps/explore/projects.rb index 8b498e7b4a..742ba5d71f 100644 --- a/features/steps/explore/projects.rb +++ b/features/steps/explore/projects.rb @@ -2,6 +2,7 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps include SharedAuthentication include SharedPaths include SharedProject + include SharedUser step 'I should see project "Empty Public Project"' do expect(page).to have_content "Empty Public Project" @@ -60,11 +61,11 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps create(:issue, title: "Bug", project: public_project - ) + ) create(:issue, title: "New feature", project: public_project - ) + ) visit namespace_project_issues_path(public_project.namespace, public_project) end @@ -79,11 +80,11 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps create(:issue, title: "Internal Bug", project: internal_project - ) + ) create(:issue, title: "New internal feature", project: internal_project - ) + ) visit namespace_project_issues_path(internal_project.namespace, internal_project) end @@ -103,7 +104,7 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps title: "Bug fix for public project", source_project: public_project, target_project: public_project, - ) + ) end step 'I should see list of merge requests for "Community" project' do @@ -120,7 +121,7 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps title: "Feature implemented", source_project: internal_project, target_project: internal_project - ) + ) end step 'I should see list of merge requests for "Internal" project' do diff --git a/features/steps/group/members.rb b/features/steps/group/members.rb new file mode 100644 index 0000000000..0706df3aec --- /dev/null +++ b/features/steps/group/members.rb @@ -0,0 +1,147 @@ +class Spinach::Features::GroupMembers < Spinach::FeatureSteps + include SharedAuthentication + include SharedPaths + include SharedGroup + include SharedUser + include Select2Helper + + step 'I select "Mike" as "Reporter"' do + user = User.find_by(name: "Mike") + + page.within ".users-group-form" do + select2(user.id, from: "#user_ids", multiple: true) + select "Reporter", from: "access_level" + end + + click_button "Add users to group" + end + + step 'I select "Mike" as "Master"' do + user = User.find_by(name: "Mike") + + page.within ".users-group-form" do + select2(user.id, from: "#user_ids", multiple: true) + select "Master", from: "access_level" + end + + click_button "Add users to group" + end + + step 'I should see "Mike" in team list as "Reporter"' do + page.within '.content-list' do + expect(page).to have_content('Mike') + expect(page).to have_content('Reporter') + end + end + + step 'I should see "Mike" in team list as "Owner"' do + page.within '.content-list' do + expect(page).to have_content('Mike') + expect(page).to have_content('Owner') + end + end + + step 'I select "sjobs@apple.com" as "Reporter"' do + page.within ".users-group-form" do + select2("sjobs@apple.com", from: "#user_ids", multiple: true) + select "Reporter", from: "access_level" + end + + click_button "Add users to group" + end + + step 'I should see "sjobs@apple.com" in team list as invited "Reporter"' do + page.within '.content-list' do + expect(page).to have_content('sjobs@apple.com') + expect(page).to have_content('invited') + expect(page).to have_content('Reporter') + end + end + + step 'I select user "Mary Jane" from list with role "Reporter"' do + user = User.find_by(name: "Mary Jane") || create(:user, name: "Mary Jane") + + page.within ".users-group-form" do + select2(user.id, from: "#user_ids", multiple: true) + select "Reporter", from: "access_level" + end + + click_button "Add users to group" + end + + step 'I should see user "John Doe" in team list' do + expect(group_members_list).to have_content("John Doe") + end + + step 'I should not see user "John Doe" in team list' do + expect(group_members_list).not_to have_content("John Doe") + end + + step 'I should see user "Mary Jane" in team list' do + expect(group_members_list).to have_content("Mary Jane") + end + + step 'I should not see user "Mary Jane" in team list' do + expect(group_members_list).not_to have_content("Mary Jane") + end + + step 'I click on the "Remove User From Group" button for "John Doe"' do + find(:css, 'li', text: "John Doe").find(:css, 'a.btn-remove').click + # poltergeist always confirms popups. + end + + step 'I click on the "Remove User From Group" button for "Mary Jane"' do + find(:css, 'li', text: "Mary Jane").find(:css, 'a.btn-remove').click + # poltergeist always confirms popups. + end + + step 'I should not see the "Remove User From Group" button for "John Doe"' do + expect(find(:css, 'li', text: "John Doe")).not_to have_selector(:css, 'a.btn-remove') + # poltergeist always confirms popups. + end + + step 'I should not see the "Remove User From Group" button for "Mary Jane"' do + expect(find(:css, 'li', text: "Mary Jane")).not_to have_selector(:css, 'a.btn-remove') + # poltergeist always confirms popups. + end + + step 'I search for \'Mary\' member' do + page.within '.member-search-form' do + fill_in 'search', with: 'Mary' + click_button 'Search' + end + end + + step 'I change the "Mary Jane" role to "Developer"' do + member = mary_jane_member + + page.within "#group_member_#{member.id}" do + find(".js-toggle-button").click + page.within "#edit_group_member_#{member.id}" do + select 'Developer', from: 'group_member_access_level' + click_on 'Save' + end + end + end + + step 'I should see "Mary Jane" as "Developer"' do + member = mary_jane_member + + page.within "#group_member_#{member.id}" do + page.within '.member-access-level' do + expect(page).to have_content "Developer" + end + end + end + + private + + def mary_jane_member + user = User.find_by(name: "Mary Jane") + owned_group.members.find_by(user_id: user.id) + end + + def group_members_list + find(".panel .content-list") + end +end diff --git a/features/steps/group/milestones.rb b/features/steps/group/milestones.rb new file mode 100644 index 0000000000..6e57b16ccb --- /dev/null +++ b/features/steps/group/milestones.rb @@ -0,0 +1,90 @@ +class Spinach::Features::GroupMilestones < Spinach::FeatureSteps + include SharedAuthentication + include SharedPaths + include SharedGroup + include SharedUser + + step 'I click on group milestones' do + click_link 'Milestones' + end + + step 'I should see group milestones index page has no milestones' do + expect(page).to have_content('No milestones to show') + end + + step 'Group has projects with milestones' do + group_milestone + end + + step 'I should see group milestones index page with milestones' do + expect(page).to have_content('Version 7.2') + expect(page).to have_content('GL-113') + expect(page).to have_link('3 Issues', href: issues_group_path("owned", milestone_title: "Version 7.2")) + expect(page).to have_link('0 Merge Requests', href: merge_requests_group_path("owned", milestone_title: "GL-113")) + end + + step 'I click on one group milestone' do + click_link 'GL-113' + end + + step 'I should see group milestone with descriptions and expiry date' do + expect(page).to have_content('expires at Aug 20, 2114') + end + + step 'I should see group milestone with all issues and MRs assigned to that milestone' do + expect(page).to have_content('Milestone GL-113') + expect(page).to have_content('Progress: 0 closed – 3 open') + issue = Milestone.find_by(name: 'GL-113').issues.first + expect(page).to have_link(issue.title, href: namespace_project_issue_path(issue.project.namespace, issue.project, issue)) + end + + step 'I fill milestone name' do + fill_in 'milestone_title', with: 'v2.9.0' + end + + step 'I click new milestone button' do + click_link "New Milestone" + end + + step 'I press create mileston button' do + click_button "Create Milestone" + end + + step 'milestone in each project should be created' do + group = Group.find_by(name: 'Owned') + expect(page).to have_content "Milestone v2.9.0" + expect(group.projects).to be_present + + group.projects.each do |project| + expect(page).to have_content project.name + end + end + + private + + def group_milestone + group = owned_group + + %w(gitlabhq gitlab-ci cookbook-gitlab).each do |path| + project = create :project, path: path, group: group + milestone = create :milestone, title: "Version 7.2", project: project + create :issue, + project: project, + assignee: current_user, + author: current_user, + milestone: milestone + + milestone = create :milestone, + title: "GL-113", + project: project, + due_date: '2114-08-20', + description: 'Lorem Ipsum is simply dummy text' + + create :issue, + project: project, + assignee: current_user, + author: current_user, + milestone: milestone + end + end +end diff --git a/features/steps/groups.rb b/features/steps/groups.rb index 9c0313537b..4c5122d1b7 100644 --- a/features/steps/groups.rb +++ b/features/steps/groups.rb @@ -3,20 +3,11 @@ class Spinach::Features::Groups < Spinach::FeatureSteps include SharedPaths include SharedGroup include SharedUser - include Select2Helper step 'I should see back to dashboard button' do expect(page).to have_content 'Go to dashboard' end - step 'gitlab user "Mike"' do - create(:user, name: "Mike") - end - - step 'I click link "Add members"' do - find(:css, 'button.btn-new').click - end - step 'I should see group "Owned"' do expect(page).to have_content '@owned' end @@ -26,7 +17,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps end step 'Group "Owned" has a public project "Public-project"' do - group = Group.find_by(name: "Owned") + group = owned_group @project = create :empty_project, :public, group: group, @@ -37,61 +28,8 @@ class Spinach::Features::Groups < Spinach::FeatureSteps expect(page).to have_content 'Public-project' end - step 'I select "Mike" as "Reporter"' do - user = User.find_by(name: "Mike") - - page.within ".users-group-form" do - select2(user.id, from: "#user_ids", multiple: true) - select "Reporter", from: "access_level" - end - - click_button "Add users to group" - end - - step 'I select "Mike" as "Master"' do - user = User.find_by(name: "Mike") - - page.within ".users-group-form" do - select2(user.id, from: "#user_ids", multiple: true) - select "Master", from: "access_level" - end - - click_button "Add users to group" - end - - step 'I should see "Mike" in team list as "Reporter"' do - page.within '.well-list' do - expect(page).to have_content('Mike') - expect(page).to have_content('Reporter') - end - end - - step 'I should see "Mike" in team list as "Owner"' do - page.within '.well-list' do - expect(page).to have_content('Mike') - expect(page).to have_content('Owner') - end - end - - step 'I select "sjobs@apple.com" as "Reporter"' do - page.within ".users-group-form" do - select2("sjobs@apple.com", from: "#user_ids", multiple: true) - select "Reporter", from: "access_level" - end - - click_button "Add users to group" - end - - step 'I should see "sjobs@apple.com" in team list as invited "Reporter"' do - page.within '.well-list' do - expect(page).to have_content('sjobs@apple.com') - expect(page).to have_content('invited') - expect(page).to have_content('Reporter') - end - end - step 'I should see group "Owned" projects list' do - Group.find_by(name: "Owned").projects.each do |project| + owned_group.projects.each do |project| expect(page).to have_link project.name end end @@ -112,36 +50,6 @@ class Spinach::Features::Groups < Spinach::FeatureSteps end end - step 'I select user "Mary Jane" from list with role "Reporter"' do - user = User.find_by(name: "Mary Jane") || create(:user, name: "Mary Jane") - click_button 'Add members' - page.within ".users-group-form" do - select2(user.id, from: "#user_ids", multiple: true) - select "Reporter", from: "access_level" - end - click_button "Add users to group" - end - - step 'I should see user "John Doe" in team list' do - projects_with_access = find(".panel .well-list") - expect(projects_with_access).to have_content("John Doe") - end - - step 'I should not see user "John Doe" in team list' do - projects_with_access = find(".panel .well-list") - expect(projects_with_access).not_to have_content("John Doe") - end - - step 'I should see user "Mary Jane" in team list' do - projects_with_access = find(".panel .well-list") - expect(projects_with_access).to have_content("Mary Jane") - end - - step 'I should not see user "Mary Jane" in team list' do - projects_with_access = find(".panel .well-list") - expect(projects_with_access).not_to have_content("Mary Jane") - end - step 'project from group "Owned" has issues assigned to me' do create :issue, project: project, @@ -172,12 +80,12 @@ class Spinach::Features::Groups < Spinach::FeatureSteps step 'I change group "Owned" avatar' do attach_file(:group_avatar, File.join(Rails.root, 'spec', 'fixtures', 'banana_sample.gif')) click_button "Save group" - Group.find_by(name: "Owned").reload + owned_group.reload end step 'I should see new group "Owned" avatar' do - expect(Group.find_by(name: "Owned").avatar).to be_instance_of AvatarUploader - expect(Group.find_by(name: "Owned").avatar.url).to eq "/uploads/group/avatar/#{ Group.find_by(name:"Owned").id }/banana_sample.gif" + expect(owned_group.avatar).to be_instance_of AvatarUploader + expect(owned_group.avatar.url).to eq "/uploads/group/avatar/#{Group.find_by(name:"Owned").id}/banana_sample.gif" end step 'I should see the "Remove avatar" button' do @@ -187,83 +95,22 @@ class Spinach::Features::Groups < Spinach::FeatureSteps step 'I have group "Owned" avatar' do attach_file(:group_avatar, File.join(Rails.root, 'spec', 'fixtures', 'banana_sample.gif')) click_button "Save group" - Group.find_by(name: "Owned").reload + owned_group.reload end step 'I remove group "Owned" avatar' do click_link "Remove avatar" - Group.find_by(name: "Owned").reload + owned_group.reload end step 'I should not see group "Owned" avatar' do - expect(Group.find_by(name: "Owned").avatar?).to eq false + expect(owned_group.avatar?).to eq false end step 'I should not see the "Remove avatar" button' do expect(page).not_to have_link("Remove avatar") end - step 'I click on the "Remove User From Group" button for "John Doe"' do - find(:css, 'li', text: "John Doe").find(:css, 'a.btn-remove').click - # poltergeist always confirms popups. - end - - step 'I click on the "Remove User From Group" button for "Mary Jane"' do - find(:css, 'li', text: "Mary Jane").find(:css, 'a.btn-remove').click - # poltergeist always confirms popups. - end - - step 'I should not see the "Remove User From Group" button for "John Doe"' do - expect(find(:css, 'li', text: "John Doe")).not_to have_selector(:css, 'a.btn-remove') - # poltergeist always confirms popups. - end - - step 'I should not see the "Remove User From Group" button for "Mary Jane"' do - expect(find(:css, 'li', text: "Mary Jane")).not_to have_selector(:css, 'a.btn-remove') - # poltergeist always confirms popups. - end - - step 'I search for \'Mary\' member' do - page.within '.member-search-form' do - fill_in 'search', with: 'Mary' - click_button 'Search' - end - end - - step 'I click on group milestones' do - click_link 'Milestones' - end - - step 'I should see group milestones index page has no milestones' do - expect(page).to have_content('No milestones to show') - end - - step 'Group has projects with milestones' do - group_milestone - end - - step 'I should see group milestones index page with milestones' do - expect(page).to have_content('Version 7.2') - expect(page).to have_content('GL-113') - expect(page).to have_link('2 Issues', href: issues_group_path("owned", milestone_title: "Version 7.2")) - expect(page).to have_link('3 Merge Requests', href: merge_requests_group_path("owned", milestone_title: "GL-113")) - end - - step 'I click on one group milestone' do - click_link 'GL-113' - end - - step 'I should see group milestone with descriptions and expiry date' do - expect(page).to have_content('expires at Aug 20, 2114') - end - - step 'I should see group milestone with all issues and MRs assigned to that milestone' do - expect(page).to have_content('Milestone GL-113') - expect(page).to have_content('Progress: 0 closed – 4 open') - expect(page).to have_link(@issue1.title, href: namespace_project_issue_path(@project1.namespace, @project1, @issue1)) - expect(page).to have_link(@mr3.title, href: namespace_project_merge_request_path(@project3.namespace, @project3, @mr3)) - end - step 'Group "Owned" has archived project' do group = Group.find_by(name: 'Owned') create(:project, namespace: group, archived: true, path: "archived-project") @@ -273,101 +120,13 @@ class Spinach::Features::Groups < Spinach::FeatureSteps expect(page).to have_xpath("//span[@class='label label-warning']", text: 'archived') end - step 'I fill milestone name' do - fill_in 'milestone_title', with: 'v2.9.0' - end - - step 'I click new milestone button' do - click_link "New Milestone" - end - - step 'I press create mileston button' do - click_button "Create Milestone" - end - - step 'milestone in each project should be created' do - group = Group.find_by(name: 'Owned') - expect(page).to have_content "Milestone v2.9.0" - expect(group.projects).to be_present - - group.projects.each do |project| - expect(page).to have_content project.name - end - end - - protected + private def assigned_to_me(key) project.send(key).where(assignee_id: current_user.id) end def project - Group.find_by(name: "Owned").projects.first - end - - def group_milestone - group = Group.find_by(name: "Owned") - - @project1 = create :project, - group: group - project2 = create :project, - path: 'gitlab-ci', - group: group - @project3 = create :project, - path: 'cookbook-gitlab', - group: group - milestone1_project1 = create :milestone, - title: "Version 7.2", - project: @project1 - milestone1_project2 = create :milestone, - title: "Version 7.2", - project: project2 - create :milestone, - title: "Version 7.2", - project: @project3 - milestone2_project1 = create :milestone, - title: "GL-113", - project: @project1 - milestone2_project2 = create :milestone, - title: "GL-113", - project: project2 - milestone2_project3 = create :milestone, - title: "GL-113", - project: @project3, - due_date: '2114-08-20', - description: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry' - @issue1 = create :issue, - project: @project1, - assignee: current_user, - author: current_user, - milestone: milestone2_project1 - create :issue, - project: project2, - assignee: current_user, - author: current_user, - milestone: milestone1_project2 - create :issue, - project: @project3, - assignee: current_user, - author: current_user, - milestone: milestone1_project1 - create :merge_request, - source_project: @project1, - target_project: @project1, - assignee: current_user, - author: current_user, - milestone: milestone2_project1 - create :merge_request, - source_project: project2, - target_project: project2, - assignee: current_user, - author: current_user, - milestone: milestone2_project2 - @mr3 = create :merge_request, - source_project: @project3, - target_project: @project3, - assignee: current_user, - author: current_user, - milestone: milestone2_project3 + owned_group.projects.first end end diff --git a/features/steps/profile/profile.rb b/features/steps/profile/profile.rb index 40b2aa7c35..0305f7e6da 100644 --- a/features/steps/profile/profile.rb +++ b/features/steps/profile/profile.rb @@ -34,7 +34,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps step 'I should see new avatar' do expect(@user.avatar).to be_instance_of AvatarUploader - expect(@user.avatar.url).to eq "/uploads/user/avatar/#{ @user.id }/banana_sample.gif" + expect(@user.avatar.url).to eq "/uploads/user/avatar/#{@user.id}/banana_sample.gif" end step 'I should see the "Remove avatar" button' do diff --git a/features/steps/project/commits/commits.rb b/features/steps/project/commits/commits.rb index e5b3f27135..a3141fe3be 100644 --- a/features/steps/project/commits/commits.rb +++ b/features/steps/project/commits/commits.rb @@ -104,10 +104,14 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps step 'commit has ci status' do @project.enable_ci - ci_commit = create :ci_commit, gl_project: @project, sha: sample_commit.id + ci_commit = create :ci_commit, project: @project, sha: sample_commit.id create :ci_build, commit: ci_commit end + step 'repository contains ".gitlab-ci.yml" file' do + allow_any_instance_of(Ci::Commit).to receive(:ci_yaml_file).and_return(String.new) + end + step 'I see commit ci info' do expect(page).to have_content "build: pending" end @@ -118,6 +122,6 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps step 'I see builds list' do expect(page).to have_content "build: pending" - expect(page).to have_content "Latest builds" + expect(page).to have_content "1 build" end end diff --git a/features/steps/project/create.rb b/features/steps/project/create.rb index 0d39e1997b..f90218f379 100644 --- a/features/steps/project/create.rb +++ b/features/steps/project/create.rb @@ -1,6 +1,7 @@ class Spinach::Features::ProjectCreate < Spinach::FeatureSteps include SharedAuthentication include SharedPaths + include SharedUser step 'fill project form with valid data' do fill_in 'project_path', with: 'Empty' diff --git a/features/steps/project/forked_merge_requests.rb b/features/steps/project/forked_merge_requests.rb index 2a333222fb..cbdce78dc0 100644 --- a/features/steps/project/forked_merge_requests.rb +++ b/features/steps/project/forked_merge_requests.rb @@ -39,14 +39,15 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps select "fix", from: "merge_request_source_branch" select "master", from: "merge_request_target_branch" - click_button "Compare branches" + click_button "Compare branches and continue" + + expect(page).to have_css("h3.page-title", text: "New Merge Request") - expect(page).to have_content "New merge request" fill_in "merge_request_title", with: "Merge Request On Forked Project" end step 'I submit the merge request' do - click_button "Submit new merge request" + click_button "Submit merge request" end step 'I follow the target commit link' do @@ -112,11 +113,10 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps end step 'I fill out an invalid "Merge Request On Forked Project" merge request' do - select "Select branch", from: "merge_request_target_branch" expect(find(:select, "merge_request_source_project_id", {}).value).to eq @forked_project.id.to_s expect(find(:select, "merge_request_target_project_id", {}).value).to eq @project.id.to_s expect(find(:select, "merge_request_source_branch", {}).value).to eq "" - expect(find(:select, "merge_request_target_branch", {}).value).to eq "" + expect(find(:select, "merge_request_target_branch", {}).value).to eq "master" click_button "Compare branches" end diff --git a/features/steps/project/graph.rb b/features/steps/project/graph.rb index 98f31f3b76..b09ec86e5d 100644 --- a/features/steps/project/graph.rb +++ b/features/steps/project/graph.rb @@ -14,6 +14,15 @@ class Spinach::Features::ProjectGraph < Spinach::FeatureSteps visit commits_namespace_project_graph_path(project.namespace, project, "master") end + step 'I visit project "Shop" languages graph page' do + visit languages_namespace_project_graph_path(project.namespace, project, "master") + end + + step 'page should have languages graphs' do + expect(page).to have_content "Ruby 66.63 %" + expect(page).to have_content "JavaScript 22.96 %" + end + step 'page should have commits graphs' do expect(page).to have_content "Commit statistics for master" expect(page).to have_content "Commits per day of month" diff --git a/features/steps/project/hooks.rb b/features/steps/project/hooks.rb index df4a23a371..be4db77094 100644 --- a/features/steps/project/hooks.rb +++ b/features/steps/project/hooks.rb @@ -70,8 +70,6 @@ class Spinach::Features::ProjectHooks < Spinach::FeatureSteps step 'I should see hook service down error message' do expect(page).to have_selector '.flash-alert', - text: 'Hook execution failed. '\ - 'Ensure hook URL is correct and '\ - 'service is up.' + text: 'Hook execution failed: Exception from' end end diff --git a/features/steps/project/issues/award_emoji.rb b/features/steps/project/issues/award_emoji.rb index 8f7a45dec0..325eaf2ea6 100644 --- a/features/steps/project/issues/award_emoji.rb +++ b/features/steps/project/issues/award_emoji.rb @@ -9,33 +9,40 @@ class Spinach::Features::AwardEmoji < Spinach::FeatureSteps end step 'I click to emoji-picker' do - page.within ".awards-controls" do - page.find(".add-award").click + page.within '.awards-controls' do + page.find('.add-award').click end end step 'I click to emoji in the picker' do - page.within ".awards-menu" do - page.first("img").click + page.within '.awards-menu' do + page.first('img').click end end step 'I can remove it by clicking to icon' do - page.within ".awards" do - page.first(".award").click - expect(page).to_not have_selector ".award" + page.within '.awards' do + page.first('.award').click + expect(page).to_not have_selector '.award' end end step 'I have award added' do - page.within ".awards" do - expect(page).to have_selector ".award" - expect(page.find(".award .counter")).to have_content "1" + page.within '.awards' do + expect(page).to have_selector '.award' + expect(page.find('.award .counter')).to have_content '1' end end step 'project "Shop" has issue "Bugfix"' do - @project = Project.find_by(name: "Shop") - @issue = create(:issue, title: "Bugfix", project: project) + @project = Project.find_by(name: 'Shop') + @issue = create(:issue, title: 'Bugfix', project: project) + end + + step 'I leave comment with a single emoji' do + page.within('.js-main-target-form') do + fill_in 'note[note]', with: ':smile:' + click_button 'Add Comment' + end end end diff --git a/features/steps/project/issues/issues.rb b/features/steps/project/issues/issues.rb index af2da41bad..4a7ff21d38 100644 --- a/features/steps/project/issues/issues.rb +++ b/features/steps/project/issues/issues.rb @@ -65,20 +65,20 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps step 'I see current user as the first user' do expect(page).to have_selector('.user-result', visible: true, count: 4) users = page.all('.user-name') - expect(users[0].text).to eq 'Any' + expect(users[0].text).to eq 'Any Assignee' expect(users[1].text).to eq 'Unassigned' expect(users[2].text).to eq current_user.name end step 'I submit new issue "500 error on profile"' do fill_in "issue_title", with: "500 error on profile" - click_button "Submit new issue" + click_button "Submit issue" end step 'I submit new issue "500 error on profile" with label \'bug\'' do fill_in "issue_title", with: "500 error on profile" select 'bug', from: "Labels" - click_button "Submit new issue" + click_button "Submit issue" end step 'I click link "500 error on profile"' do @@ -86,7 +86,7 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps end step 'I should see label \'bug\' with issue' do - page.within '.issue-show-labels' do + page.within '.issuable-show-labels' do expect(page).to have_content 'bug' end end @@ -284,6 +284,16 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps end end + step 'another user adds a comment with text "Yay!" to issue "Release 0.4"' do + issue = Issue.find_by!(title: 'Release 0.4') + create(:note_on_issue, noteable: issue, note: 'Yay!') + end + + step 'I should see a new comment with text "Yay!"' do + page.within '#notes' do + expect(page).to have_content('Yay!') + end + end def filter_issue(text) fill_in 'issue_search', with: text end diff --git a/features/steps/project/issues/labels.rb b/features/steps/project/issues/labels.rb index d656acf422..2ab8956867 100644 --- a/features/steps/project/issues/labels.rb +++ b/features/steps/project/issues/labels.rb @@ -9,7 +9,7 @@ class Spinach::Features::ProjectIssuesLabels < Spinach::FeatureSteps step 'I remove label \'bug\'' do page.within "#label_#{bug_label.id}" do - click_link 'Remove' + click_link 'Delete' end end @@ -31,20 +31,20 @@ class Spinach::Features::ProjectIssuesLabels < Spinach::FeatureSteps step 'I submit new label \'support\'' do fill_in 'Title', with: 'support' - fill_in 'Background Color', with: '#F95610' - click_button 'Save' + fill_in 'Background color', with: '#F95610' + click_button 'Create Label' end step 'I submit new label \'bug\'' do fill_in 'Title', with: 'bug' - fill_in 'Background Color', with: '#F95610' - click_button 'Save' + fill_in 'Background color', with: '#F95610' + click_button 'Create Label' end step 'I submit new label with invalid color' do fill_in 'Title', with: 'support' - fill_in 'Background Color', with: '#12' - click_button 'Save' + fill_in 'Background color', with: '#12' + click_button 'Create Label' end step 'I should see label label exist error message' do @@ -55,7 +55,7 @@ class Spinach::Features::ProjectIssuesLabels < Spinach::FeatureSteps step 'I should see label color error message' do page.within '.label-form' do - expect(page).to have_content 'Color is invalid' + expect(page).to have_content 'Color must be a valid color code' end end @@ -85,8 +85,8 @@ class Spinach::Features::ProjectIssuesLabels < Spinach::FeatureSteps step 'I change label \'bug\' to \'fix\'' do fill_in 'Title', with: 'fix' - fill_in 'Background Color', with: '#F15610' - click_button 'Save' + fill_in 'Background color', with: '#F15610' + click_button 'Save changes' end step 'I should see label \'fix\'' do diff --git a/features/steps/project/issues/milestones.rb b/features/steps/project/issues/milestones.rb index c8708572ec..e2eda51149 100644 --- a/features/steps/project/issues/milestones.rb +++ b/features/steps/project/issues/milestones.rb @@ -63,7 +63,7 @@ class Spinach::Features::ProjectIssuesMilestones < Spinach::FeatureSteps end step 'I click link to remove milestone' do - click_link 'Remove' + click_link 'Delete' end step 'I should see no milestones' do diff --git a/features/steps/project/merge_requests.rb b/features/steps/project/merge_requests.rb index d5f2c4209a..be993d1109 100644 --- a/features/steps/project/merge_requests.rb +++ b/features/steps/project/merge_requests.rb @@ -86,7 +86,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps select "feature", from: "merge_request_target_branch" click_button "Compare branches" fill_in "merge_request_title", with: "Wiki Feature" - click_button "Submit new merge request" + click_button "Submit merge request" end step 'project "Shop" have "Bug NS-04" open merge request' do @@ -186,6 +186,50 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps leave_comment "Line is wrong" end + step 'I change the comment "Line is wrong" to "Typo, please fix" on diff' do + page.within('.diff-file:nth-of-type(5) .note') do + find('.js-note-edit').click + + page.within('.current-note-edit-form', visible: true) do + fill_in 'note_note', with: 'Typo, please fix' + click_button 'Save Comment' + end + + expect(page).not_to have_button 'Save Comment', disabled: true, visible: true + end + end + + step 'I should not see a diff comment saying "Line is wrong"' do + page.within('.diff-file:nth-of-type(5) .note') do + expect(page).not_to have_visible_content 'Line is wrong' + end + end + + step 'I should see a diff comment saying "Typo, please fix"' do + page.within('.diff-file:nth-of-type(5) .note') do + expect(page).to have_visible_content 'Typo, please fix' + end + end + + step 'I delete the comment "Line is wrong" on diff' do + page.within('.diff-file:nth-of-type(5) .note') do + find('.js-note-delete').click + end + end + + step 'I click on the Discussion tab' do + page.within '.merge-request-tabs' do + click_link 'Discussion' + end + + # Waits for load + expect(page).to have_css('.tab-content #notes.active') + end + + step 'I should not see any discussion' do + expect(page).not_to have_css('.notes .discussion') + end + step 'I should see a discussion has started on diff' do page.within(".notes .discussion") do page.should have_content "#{current_user.name} started a discussion" @@ -229,7 +273,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps end step 'I should see merged request' do - page.within '.issue-box' do + page.within '.status-box' do expect(page).to have_content "Merged" end end @@ -239,7 +283,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps end step 'I should see reopened merge request "Bug NS-04"' do - page.within '.issue-box' do + page.within '.status-box' do expect(page).to have_content "Open" end end @@ -361,13 +405,13 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps step '"Bug NS-05" has CI status' do project = merge_request.source_project project.enable_ci - ci_commit = create :ci_commit, gl_project: project, sha: merge_request.last_commit.id + ci_commit = create :ci_commit, project: project, sha: merge_request.last_commit.id create :ci_build, commit: ci_commit end step 'I should see merge request "Bug NS-05" with CI status' do page.within ".mr-list" do - expect(page).to have_link "Build status: pending" + expect(page).to have_link "Build pending" end end diff --git a/features/steps/project/merge_requests/acceptance.rb b/features/steps/project/merge_requests/acceptance.rb new file mode 100644 index 0000000000..383c055c4e --- /dev/null +++ b/features/steps/project/merge_requests/acceptance.rb @@ -0,0 +1,39 @@ +class Spinach::Features::ProjectMergeRequestsAcceptance < Spinach::FeatureSteps + include LoginHelpers + include GitlabRoutingHelper + + step 'I am on the Merge Request detail page' do + visit merge_request_path(@merge_request) + end + + step 'I click on "Remove source branch" option' do + check('Remove source branch') + end + + step 'I click on Accept Merge Request' do + click_button('Accept Merge Request') + end + + step 'I should see the Remove Source Branch button' do + expect(page).to have_link('Remove Source Branch') + end + + step 'I should not see the Remove Source Branch button' do + expect(page).not_to have_link('Remove Source Branch') + end + + step 'There is an open Merge Request' do + @user = create(:user) + @project = create(:project, :public) + @project_member = create(:project_member, user: @user, project: @project, access_level: ProjectMember::DEVELOPER) + @merge_request = create(:merge_request, :with_diffs, :simple, source_project: @project) + end + + step 'I am signed in as a developer of the project' do + login_as(@user) + end + + step 'I should see merge request merged' do + expect(page).to have_content('The changes were merged into') + end +end diff --git a/features/steps/project/project.rb b/features/steps/project/project.rb index 9ca7c8ebbc..37bf52b4a9 100644 --- a/features/steps/project/project.rb +++ b/features/steps/project/project.rb @@ -37,7 +37,7 @@ class Spinach::Features::Project < Spinach::FeatureSteps step 'I should see new project avatar' do expect(@project.avatar).to be_instance_of AvatarUploader url = @project.avatar.url - expect(url).to eq "/uploads/project/avatar/#{ @project.id }/banana_sample.gif" + expect(url).to eq "/uploads/project/avatar/#{@project.id}/banana_sample.gif" end step 'I should see the "Remove avatar" button' do diff --git a/features/steps/project/services.rb b/features/steps/project/services.rb index 1c700df0c6..536199ddb4 100644 --- a/features/steps/project/services.rb +++ b/features/steps/project/services.rb @@ -11,7 +11,6 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps expect(page).to have_content 'Project services' expect(page).to have_content 'Campfire' expect(page).to have_content 'HipChat' - expect(page).to have_content 'GitLab CI' expect(page).to have_content 'Assembla' expect(page).to have_content 'Pushover' expect(page).to have_content 'Atlassian Bamboo' @@ -20,15 +19,6 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps expect(page).to have_content 'Irker (IRC gateway)' end - step 'I click gitlab-ci service link' do - click_link 'GitLab CI' - end - - step 'I fill gitlab-ci settings' do - check 'Active' - click_button 'Save' - end - step 'I should see service settings saved' do expect(find_field('Active').value).to eq '1' end @@ -183,6 +173,24 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps expect(find_field('Sound').find('option[selected]').value).to eq 'bike' end + step 'I click jira service link' do + click_link 'JIRA' + end + + step 'I fill jira settings' do + fill_in 'Project url', with: 'http://jira.example' + fill_in 'Username', with: 'gitlab' + fill_in 'Password', with: 'gitlab' + fill_in 'Api url', with: 'http://jira.example/rest/api/2' + click_button 'Save' + end + + step 'I should see jira service settings saved' do + expect(find_field('Project url').value).to eq 'http://jira.example' + expect(find_field('Username').value).to eq 'gitlab' + expect(find_field('Api url').value).to eq 'http://jira.example/rest/api/2' + end + step 'I click Atlassian Bamboo CI service link' do click_link 'Atlassian Bamboo CI' end diff --git a/features/steps/project/snippets.rb b/features/steps/project/snippets.rb index a3aef9bf8c..504654f90d 100644 --- a/features/steps/project/snippets.rb +++ b/features/steps/project/snippets.rb @@ -42,7 +42,7 @@ class Spinach::Features::ProjectSnippets < Spinach::FeatureSteps end step 'I click link "Edit"' do - page.within ".page-title" do + page.within ".detail-page-header" do click_link "Edit" end end diff --git a/features/steps/project/source/browse_files.rb b/features/steps/project/source/browse_files.rb index f40e0f0d52..0c6df18ce2 100644 --- a/features/steps/project/source/browse_files.rb +++ b/features/steps/project/source/browse_files.rb @@ -37,6 +37,10 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps expect(page).to have_content new_gitignore_content end + step 'I should see its content with new lines preserved at end of file' do + expect(evaluate_script('blob.editor.getValue()')).to eq "Sample\n\n\n" + end + step 'I click link "Raw"' do click_link 'Raw' end @@ -53,10 +57,6 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps expect(page).not_to have_link 'edit' end - step 'The edit button is disabled' do - expect(page).to have_css '.disabled', text: 'Edit' - end - step 'I can edit code' do set_new_content expect(evaluate_script('blob.editor.getValue()')).to eq new_gitignore_content @@ -66,6 +66,10 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps set_new_content end + step 'I edit code with new lines at end of file' do + execute_script('blob.editor.setValue("Sample\n\n\n")') + end + step 'I fill the new file name' do fill_in :file_name, with: new_file_name end @@ -87,7 +91,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps end step 'I click link "Diff"' do - click_link 'Preview changes' + click_link 'Preview Changes' end step 'I click on "Commit Changes"' do @@ -142,7 +146,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps end step 'I can see new file page' do - expect(page).to have_content "Create New File" + expect(page).to have_content "New File" expect(page).to have_content "Commit message" end @@ -192,7 +196,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps end step 'I see Browse dir link' do - expect(page).to have_link 'Browse Dir »' + expect(page).to have_link 'Browse Directory »' expect(page).not_to have_link 'Browse Code »' end @@ -204,13 +208,13 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps step 'I see Browse file link' do expect(page).to have_link 'Browse File »' - expect(page).not_to have_link 'Browse Code »' + expect(page).not_to have_link 'Browse Files »' end step 'I see Browse code link' do - expect(page).to have_link 'Browse Code »' + expect(page).to have_link 'Browse Files »' expect(page).not_to have_link 'Browse File »' - expect(page).not_to have_link 'Browse Dir »' + expect(page).not_to have_link 'Browse Directory »' end step 'I click on Permalink' do @@ -234,13 +238,13 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps end step 'I am redirected to the new file' do - expect(current_path).to eq(namespace_project_blob_path( - @project.namespace, @project, 'master/' + new_file_name)) + expect(current_path).to eq( + namespace_project_blob_path(@project.namespace, @project, 'master/' + new_file_name)) end step 'I am redirected to the new file with directory' do - expect(current_path).to eq(namespace_project_blob_path( - @project.namespace, @project, 'master/' + new_file_name_with_directory)) + expect(current_path).to eq( + namespace_project_blob_path(@project.namespace, @project, 'master/' + new_file_name_with_directory)) end step 'I am redirected to the new merge request page' do @@ -248,8 +252,8 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps end step 'I am redirected to the root directory' do - expect(current_path).to eq(namespace_project_tree_path( - @project.namespace, @project, 'master/')) + expect(current_path).to eq( + namespace_project_tree_path(@project.namespace, @project, 'master/')) end step "I don't see the permalink link" do @@ -305,6 +309,33 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps expect(page).not_to have_content('Loading commit data...') end + step 'I click on "files/lfs/lfs_object.iso" file in repo' do + visit namespace_project_tree_path(@project.namespace, @project, "lfs") + click_link 'files' + click_link "lfs" + click_link "lfs_object.iso" + end + + step 'I should see download link and object size' do + expect(page).to have_content 'Download (1.5 MB)' + end + + step 'I should not see lfs pointer details' do + expect(page).not_to have_content 'version https://git-lfs.github.com/spec/v1' + expect(page).not_to have_content 'oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897' + expect(page).not_to have_content 'size 1575078' + end + + step 'I should see buttons for allowed commands' do + expect(page).to have_content 'Raw' + expect(page).to have_content 'History' + expect(page).to have_content 'Permalink' + expect(page).not_to have_content 'Edit' + expect(page).not_to have_content 'Blame' + expect(page).not_to have_content 'Delete' + expect(page).not_to have_content 'Replace' + end + private def set_new_content diff --git a/features/steps/project/source/markdown_render.rb b/features/steps/project/source/markdown_render.rb index c78e86fa1a..3a4f7a6e01 100644 --- a/features/steps/project/source/markdown_render.rb +++ b/features/steps/project/source/markdown_render.rb @@ -238,7 +238,7 @@ class Spinach::Features::ProjectSourceMarkdownRender < Spinach::FeatureSteps step 'I see new wiki page named test' do expect(current_path).to eq namespace_project_wiki_path(@project.namespace, @project, "test") - expect(page).to have_content "Editing" + expect(page).to have_content "Edit Page test" end When 'I go back to wiki page home' do @@ -252,7 +252,7 @@ class Spinach::Features::ProjectSourceMarkdownRender < Spinach::FeatureSteps step 'I see Gitlab API document' do expect(current_path).to eq namespace_project_wiki_path(@project.namespace, @project, "api") - expect(page).to have_content "Editing" + expect(page).to have_content "Edit Page api" end step 'I click on Rake tasks link' do @@ -261,7 +261,7 @@ class Spinach::Features::ProjectSourceMarkdownRender < Spinach::FeatureSteps step 'I see Rake tasks directory' do expect(current_path).to eq namespace_project_wiki_path(@project.namespace, @project, "raketasks") - expect(page).to have_content "Editing" + expect(page).to have_content "Edit Page raketasks" end step 'I go directory which contains README file' do diff --git a/features/steps/project/team_management.rb b/features/steps/project/team_management.rb index 97d6301645..caad52def7 100644 --- a/features/steps/project/team_management.rb +++ b/features/steps/project/team_management.rb @@ -15,10 +15,6 @@ class Spinach::Features::ProjectTeamManagement < Spinach::FeatureSteps expect(page).to have_content(user.username) end - step 'I click link "Add members"' do - find(:css, 'button.btn-new').click - end - step 'I select "Mike" as "Reporter"' do user = User.find_by(name: "Mike") diff --git a/features/steps/project/wiki.rb b/features/steps/project/wiki.rb index 02207dbffa..91d227fadb 100644 --- a/features/steps/project/wiki.rb +++ b/features/steps/project/wiki.rb @@ -5,7 +5,7 @@ class Spinach::Features::ProjectWiki < Spinach::FeatureSteps include SharedPaths step 'I click on the Cancel button' do - page.within(:css, ".form-actions") do + page.within(:css, ".wiki-form .form-actions") do click_on "Cancel" end end @@ -24,7 +24,7 @@ class Spinach::Features::ProjectWiki < Spinach::FeatureSteps expect(page).to have_content "link test" click_link "link test" - expect(page).to have_content "Editing" + expect(page).to have_content "Edit Page" end step 'I have an existing Wiki page' do @@ -68,7 +68,7 @@ class Spinach::Features::ProjectWiki < Spinach::FeatureSteps end step 'I click on the "Delete this page" button' do - click_on "Delete this page" + click_on "Delete" end step 'The page should be deleted' do @@ -120,13 +120,13 @@ class Spinach::Features::ProjectWiki < Spinach::FeatureSteps step 'I should see the new wiki page form' do expect(current_path).to match('wikis/image.jpg') expect(page).to have_content('New Wiki Page') - expect(page).to have_content('Editing - image.jpg') + expect(page).to have_content('Edit Page image.jpg') end step 'I create a New page with paths' do click_on 'New Page' fill_in 'Page slug', with: 'one/two/three' - click_on 'Build' + click_on 'Create Page' fill_in "wiki_content", with: 'wiki content' click_on "Create page" expect(current_path).to include 'one/two/three' @@ -135,7 +135,7 @@ class Spinach::Features::ProjectWiki < Spinach::FeatureSteps step 'I create a New page with an invalid name' do click_on 'New Page' fill_in 'Page slug', with: 'invalid name' - click_on 'Build' + click_on 'Create Page' end step 'I should see an error message' do @@ -156,7 +156,7 @@ class Spinach::Features::ProjectWiki < Spinach::FeatureSteps end step 'I should see the Editing page' do - expect(page).to have_content('Editing') + expect(page).to have_content('Edit Page') end step 'I view the page history of a Wiki page that has a path' do diff --git a/features/steps/shared/diff_note.rb b/features/steps/shared/diff_note.rb index 72621911a3..c6a0ae2ba3 100644 --- a/features/steps/shared/diff_note.rb +++ b/features/steps/shared/diff_note.rb @@ -87,6 +87,17 @@ module SharedDiffNote end end + step 'I write a diff comment like ":smile:"' do + page.within(diff_file_selector) do + click_diff_line(sample_commit.line_code) + + page.within("form[rel$='#{sample_commit.line_code}']") do + fill_in 'note[note]', with: ':smile:' + click_button('Add Comment') + end + end + end + step 'I submit the diff comment' do page.within(diff_file_selector) do click_button("Add Comment") @@ -155,7 +166,7 @@ module SharedDiffNote end step 'I should see add a diff comment button' do - expect(page).to have_css('.js-add-diff-note-button', visible: true) + expect(page).to have_css('.js-add-diff-note-button') end step 'I should see an empty diff comment form' do @@ -197,6 +208,12 @@ module SharedDiffNote end end + step 'I should see a diff comment with an emoji image' do + page.within("#{diff_file_selector} .note") do + expect(page).to have_xpath("//img[@alt=':smile:']") + end + end + step 'I click side-by-side diff button' do find('#parallel-diff-btn').trigger('click') end diff --git a/features/steps/shared/group.rb b/features/steps/shared/group.rb index 83a0457697..fe6736dacd 100644 --- a/features/steps/shared/group.rb +++ b/features/steps/shared/group.rb @@ -1,6 +1,10 @@ module SharedGroup include Spinach::DSL + step 'current user is developer of group "Owned"' do + is_member_of(current_user.name, "Owned", Gitlab::Access::DEVELOPER) + end + step '"John Doe" is owner of group "Owned"' do is_member_of("John Doe", "Owned", Gitlab::Access::OWNER) end @@ -41,4 +45,8 @@ module SharedGroup project.team << [user, :master] @project_count += 1 end + + def owned_group + @owned_group ||= Group.find_by(name: "Owned") + end end diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb index c74a5fd3bc..b33bd33265 100644 --- a/features/steps/shared/paths.rb +++ b/features/steps/shared/paths.rb @@ -212,8 +212,8 @@ module SharedPaths end step 'I visit a binary file in the repo' do - visit namespace_project_blob_path(@project.namespace, @project, File.join( - root_ref, 'files/images/logo-black.png')) + visit namespace_project_blob_path(@project.namespace, @project, + File.join(root_ref, 'files/images/logo-black.png')) end step "I visit my project's commits page" do @@ -316,8 +316,8 @@ module SharedPaths end step 'I am on the ".gitignore" edit file page' do - expect(current_path).to eq(namespace_project_edit_blob_path( - @project.namespace, @project, File.join(root_ref, '.gitignore'))) + expect(current_path).to eq( + namespace_project_edit_blob_path(@project.namespace, @project, File.join(root_ref, '.gitignore'))) end step 'I visit project source page for "6d39438"' do diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb index 7021fac5fe..da643bf3ba 100644 --- a/features/steps/shared/project.rb +++ b/features/steps/shared/project.rb @@ -204,7 +204,7 @@ module SharedProject step 'project "Shop" has CI build' do project = Project.find_by(name: "Shop") - create :ci_commit, gl_project: project, sha: project.commit.sha + create :ci_commit, project: project, sha: project.commit.sha end step 'I should see last commit with CI status' do diff --git a/features/steps/shared/project_tab.rb b/features/steps/shared/project_tab.rb index 33ff7084e3..4fc2ece79f 100644 --- a/features/steps/shared/project_tab.rb +++ b/features/steps/shared/project_tab.rb @@ -16,10 +16,6 @@ module SharedProjectTab ensure_active_main_tab('Commits') end - step 'the active main tab should be Network' do - ensure_active_main_tab('Network') - end - step 'the active main tab should be Graphs' do ensure_active_main_tab('Graphs') end @@ -53,4 +49,8 @@ module SharedProjectTab step 'the active main tab should be Activity' do ensure_active_main_tab('Activity') end + + step 'the active sub tab should be Network' do + ensure_active_sub_tab('Network') + end end diff --git a/features/steps/shared/user.rb b/features/steps/shared/user.rb index fc1e8d6e88..f0721094ee 100644 --- a/features/steps/shared/user.rb +++ b/features/steps/shared/user.rb @@ -9,9 +9,21 @@ module SharedUser user_exists("Mary Jane", { username: "mary_jane" }) end + step 'gitlab user "Mike"' do + create(:user, name: "Mike") + end + protected def user_exists(name, options = {}) User.find_by(name: name) || create(:user, { name: name, admin: false }.merge(options)) end + + step 'I have an ssh key' do + create(:personal_key, user: @user) + end + + step 'I have no ssh keys' do + @user.keys.delete_all + end end diff --git a/features/steps/snippets/snippets.rb b/features/steps/snippets/snippets.rb index 80d1ddeef0..023032e679 100644 --- a/features/steps/snippets/snippets.rb +++ b/features/steps/snippets/snippets.rb @@ -13,7 +13,7 @@ class Spinach::Features::Snippets < Spinach::FeatureSteps end step 'I click link "Edit"' do - page.within ".page-title" do + page.within ".detail-page-header" do click_link "Edit" end end diff --git a/features/support/capybara.rb b/features/support/capybara.rb index 31dbf0feb2..4156c7ec48 100644 --- a/features/support/capybara.rb +++ b/features/support/capybara.rb @@ -2,7 +2,7 @@ require 'spinach/capybara' require 'capybara/poltergeist' # Give CI some extra time -timeout = (ENV['CI'] || ENV['CI_SERVER']) ? 90 : 10 +timeout = (ENV['CI'] || ENV['CI_SERVER']) ? 90 : 15 Capybara.javascript_driver = :poltergeist Capybara.register_driver :poltergeist do |app| diff --git a/lib/api/api.rb b/lib/api/api.rb index fe1bf8a481..7834262d61 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -53,5 +53,6 @@ module API mount Settings mount Keys mount Tags + mount Triggers end end diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb index 2c0596c9df..1162271f5f 100644 --- a/lib/api/commit_statuses.rb +++ b/lib/api/commit_statuses.rb @@ -53,7 +53,7 @@ module API name = params[:name] || params[:context] status = GenericCommitStatus.running_or_pending.find_by(commit: ci_commit, name: name, ref: params[:ref]) - status ||= GenericCommitStatus.new(commit: ci_commit, user: current_user) + status ||= GenericCommitStatus.new(project: @project, commit: ci_commit, user: current_user) status.update(attrs) case params[:state].to_s diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 9f337bc3cc..f8511ac5f5 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -45,7 +45,8 @@ module API class ProjectHook < Hook expose :project_id, :push_events - expose :issues_events, :merge_requests_events, :tag_push_events, :note_events, :enable_ssl_verification + expose :issues_events, :merge_requests_events, :tag_push_events, :note_events, :build_events + expose :enable_ssl_verification end class ForkedFromProject < Grape::Entity @@ -63,11 +64,13 @@ module API expose :name, :name_with_namespace expose :path, :path_with_namespace expose :issues_enabled, :merge_requests_enabled, :wiki_enabled, :builds_enabled, :snippets_enabled, :created_at, :last_activity_at + expose :shared_runners_enabled expose :creator_id expose :namespace - expose :forked_from_project, using: Entities::ForkedFromProject, if: lambda{ | project, options | project.forked? } + expose :forked_from_project, using: Entities::ForkedFromProject, if: lambda{ |project, options| project.forked? } expose :avatar_url expose :star_count, :forks_count + expose :open_issues_count, if: lambda { |project, options| project.issues_enabled? && project.default_issues_tracker? } end class ProjectMember < UserBasic @@ -171,6 +174,7 @@ module API expose :description expose :work_in_progress?, as: :work_in_progress expose :milestone, using: Entities::Milestone + expose :merge_when_build_succeeds end class MergeRequestChanges < MergeRequest @@ -194,6 +198,7 @@ module API expose :author, using: Entities::UserBasic expose :created_at expose :system?, as: :system + expose :noteable_id, :noteable_type # upvote? and downvote? are deprecated, always return false expose :upvote?, as: :upvote expose :downvote?, as: :downvote @@ -224,6 +229,8 @@ module API expose :target_id, :target_type, :author_id expose :data, :target_title expose :created_at + expose :note, using: Entities::Note, if: ->(event, options) { event.note? } + expose :author, using: Entities::UserBasic, if: ->(event, options) { event.author } expose :author_username do |event, options| if event.author @@ -248,7 +255,7 @@ module API class ProjectService < Grape::Entity expose :id, :title, :created_at, :updated_at, :active - expose :push_events, :issues_events, :merge_requests_events, :tag_push_events, :note_events + expose :push_events, :issues_events, :merge_requests_events, :tag_push_events, :note_events, :build_events # Expose serialized properties expose :properties do |service, options| field_names = service.fields. @@ -355,5 +362,9 @@ module API end end end + + class TriggerRequest < Grape::Entity + expose :id, :variables + end end end diff --git a/lib/api/groups.rb b/lib/api/groups.rb index 024aeec2e1..1a14d870a4 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -65,6 +65,18 @@ module API DestroyGroupService.new(group, current_user).execute end + # Get a list of projects in this group + # + # Example Request: + # GET /groups/:id/projects + get ":id/projects" do + group = find_group(params[:id]) + projects = group.projects + projects = filter_projects(projects) + projects = paginate projects + present projects, with: Entities::Project + end + # Transfer a project to the Group namespace # # Parameters: diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 92540ccf2b..a4df810e75 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -266,12 +266,7 @@ module API projects = projects.search(params[:search]) end - if params[:ci_enabled_first].present? - projects.includes(:gitlab_ci_service). - reorder("services.active DESC, projects.#{project_order_by} #{project_sort}") - else - projects.reorder(project_order_by => project_sort) - end + projects.reorder(project_order_by => project_sort) end def project_order_by diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index 6eb84baf9c..3c1c6bda26 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -76,6 +76,22 @@ module API present merge_request, with: Entities::MergeRequest end + # Show MR commits + # + # Parameters: + # id (required) - The ID of a project + # merge_request_id (required) - The ID of MR + # + # Example: + # GET /projects/:id/merge_request/:merge_request_id/commits + # + get ':id/merge_request/:merge_request_id/commits' do + merge_request = user_project.merge_requests. + find(params[:merge_request_id]) + authorize! :read_merge_request, merge_request + present merge_request.commits, with: Entities::RepoCommit + end + # Show MR changes # # Parameters: @@ -179,46 +195,54 @@ module API # Merge MR # # Parameters: - # id (required) - The ID of a project - # merge_request_id (required) - ID of MR - # merge_commit_message (optional) - Custom merge commit message + # id (required) - The ID of a project + # merge_request_id (required) - ID of MR + # merge_commit_message (optional) - Custom merge commit message + # should_remove_source_branch (optional) - When true, the source branch will be deleted if possible + # merge_when_build_succeeds (optional) - When true, this MR will be merged when the build succeeds # Example: # PUT /projects/:id/merge_request/:merge_request_id/merge # put ":id/merge_request/:merge_request_id/merge" do merge_request = user_project.merge_requests.find(params[:merge_request_id]) - allowed = ::Gitlab::GitAccess.new(current_user, user_project). - can_push_to_branch?(merge_request.target_branch) + # Merge request can not be merged + # because user dont have permissions to push into target branch + unauthorized! unless merge_request.can_be_merged_by?(current_user) + not_allowed! if !merge_request.open? || merge_request.work_in_progress? - if allowed - if merge_request.unchecked? - merge_request.check_if_can_be_merged - end + merge_request.check_if_can_be_merged if merge_request.unchecked? - if merge_request.open? && !merge_request.work_in_progress? - if merge_request.can_be_merged? - commit_message = params[:merge_commit_message] || merge_request.merge_commit_message + render_api_error!('Branch cannot be merged', 406) unless merge_request.can_be_merged? - ::MergeRequests::MergeService.new(merge_request.target_project, current_user). - execute(merge_request, commit_message) + merge_params = { + commit_message: params[:merge_commit_message], + should_remove_source_branch: params[:should_remove_source_branch] + } - present merge_request, with: Entities::MergeRequest - else - render_api_error!('Branch cannot be merged', 405) - end - else - # Merge request can not be merged - # because it is already closed/merged or marked as WIP - not_allowed! - end + if parse_boolean(params[:merge_when_build_succeeds]) && merge_request.ci_commit && merge_request.ci_commit.active? + ::MergeRequests::MergeWhenBuildSucceedsService.new(merge_request.target_project, current_user, merge_params). + execute(merge_request) else - # Merge request can not be merged - # because user dont have permissions to push into target branch - unauthorized! + ::MergeRequests::MergeService.new(merge_request.target_project, current_user, merge_params). + execute(merge_request) end + + present merge_request, with: Entities::MergeRequest end + # Cancel Merge if Merge When build succeeds is enabled + # Parameters: + # id (required) - The ID of a project + # merge_request_id (required) - ID of MR + # + post ":id/merge_request/:merge_request_id/cancel_merge_when_build_succeeds" do + merge_request = user_project.merge_requests.find(params[:merge_request_id]) + + unauthorized! unless merge_request.can_cancel_merge_when_build_succeeds?(current_user) + + ::MergeRequest::MergeWhenBuildSucceedsService.new(merge_request.target_project, current_user).cancel(merge_request) + end # Get a merge request's comments # diff --git a/lib/api/project_hooks.rb b/lib/api/project_hooks.rb index 882d1a083a..cf9938d25a 100644 --- a/lib/api/project_hooks.rb +++ b/lib/api/project_hooks.rb @@ -45,6 +45,7 @@ module API :merge_requests_events, :tag_push_events, :note_events, + :build_events, :enable_ssl_verification ] @hook = user_project.hooks.new(attrs) @@ -77,6 +78,7 @@ module API :merge_requests_events, :tag_push_events, :note_events, + :build_events, :enable_ssl_verification ] diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 2b4ada6e2e..5e75cd35c5 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -7,8 +7,12 @@ module API helpers do def map_public_to_visibility_level(attrs) publik = attrs.delete(:public) - publik = parse_boolean(publik) - attrs[:visibility_level] = Gitlab::VisibilityLevel::PUBLIC if !attrs[:visibility_level].present? && publik == true + if publik.present? && !attrs[:visibility_level].present? + publik = parse_boolean(publik) + # Since setting the public attribute to private could mean either + # private or internal, use the more conservative option, private. + attrs[:visibility_level] = (publik == true) ? Gitlab::VisibilityLevel::PUBLIC : Gitlab::VisibilityLevel::PRIVATE + end attrs end end @@ -35,6 +39,17 @@ module API present @projects, with: Entities::Project end + # Gets starred project for the authenticated user + # + # Example Request: + # GET /projects/starred + get '/starred' do + @projects = current_user.starred_projects + @projects = filter_projects(@projects) + @projects = paginate @projects + present @projects, with: Entities::Project + end + # Get all projects for admin user # # Example Request: @@ -78,6 +93,7 @@ module API # builds_enabled (optional) # wiki_enabled (optional) # snippets_enabled (optional) + # shared_runners_enabled (optional) # namespace_id (optional) - defaults to user namespace # public (optional) - if true same as setting visibility_level = 20 # visibility_level (optional) - 0 by default @@ -94,6 +110,7 @@ module API :builds_enabled, :wiki_enabled, :snippets_enabled, + :shared_runners_enabled, :namespace_id, :public, :visibility_level, @@ -122,6 +139,7 @@ module API # builds_enabled (optional) # wiki_enabled (optional) # snippets_enabled (optional) + # shared_runners_enabled (optional) # public (optional) - if true same as setting visibility_level = 20 # visibility_level (optional) # import_url (optional) @@ -138,6 +156,7 @@ module API :builds_enabled, :wiki_enabled, :snippets_enabled, + :shared_runners_enabled, :public, :visibility_level, :import_url] @@ -179,6 +198,7 @@ module API # builds_enabled (optional) # wiki_enabled (optional) # snippets_enabled (optional) + # shared_runners_enabled (optional) # public (optional) - if true same as setting visibility_level = 20 # visibility_level (optional) - visibility level of a project # Example Request @@ -193,6 +213,7 @@ module API :builds_enabled, :wiki_enabled, :snippets_enabled, + :shared_runners_enabled, :public, :visibility_level] attrs = map_public_to_visibility_level(attrs) diff --git a/lib/api/triggers.rb b/lib/api/triggers.rb new file mode 100644 index 0000000000..2781f1cf19 --- /dev/null +++ b/lib/api/triggers.rb @@ -0,0 +1,48 @@ +module API + # Triggers API + class Triggers < Grape::API + resource :projects do + # Trigger a GitLab project build + # + # Parameters: + # id (required) - The ID of a CI project + # ref (required) - The name of project's branch or tag + # token (required) - The uniq token of trigger + # variables (optional) - The list of variables to be injected into build + # Example Request: + # POST /projects/:id/trigger/builds + post ":id/trigger/builds" do + required_attributes! [:ref, :token] + + project = Project.find_with_namespace(params[:id]) || Project.find_by(id: params[:id]) + trigger = Ci::Trigger.find_by_token(params[:token].to_s) + not_found! unless project && trigger + unauthorized! unless trigger.project == project + + # validate variables + variables = params[:variables] + if variables + unless variables.is_a?(Hash) + render_api_error!('variables needs to be a hash', 400) + end + + unless variables.all? { |key, value| key.is_a?(String) && value.is_a?(String) } + render_api_error!('variables needs to be a map of key-valued strings', 400) + end + + # convert variables from Mash to Hash + variables = variables.to_h + end + + # create request and trigger builds + trigger_request = Ci::CreateTriggerRequestService.new.execute(project, trigger, params[:ref].to_s, variables) + if trigger_request + present trigger_request, with: Entities::TriggerRequest + else + errors = 'No builds created' + render_api_error!(errors, 400) + end + end + end + end +end diff --git a/lib/award_emoji.rb b/lib/award_emoji.rb index d58a196c4e..4d99164bc3 100644 --- a/lib/award_emoji.rb +++ b/lib/award_emoji.rb @@ -6,7 +6,42 @@ class AwardEmoji "ambulance", "anguished", "two_hearts", "wink" ] + ALIASES = { + pout: "rage", + satisfied: "laughing", + hankey: "shit", + poop: "shit", + collision: "boom", + thumbsup: "+1", + thumbsdown: "-1", + punch: "facepunch", + raised_hand: "hand", + running: "runner", + ng_woman: "no_good", + shoe: "mans_shoe", + tshirt: "shirt", + honeybee: "bee", + flipper: "dolphin", + paw_prints: "feet", + waxing_gibbous_moon: "moon", + telephone: "phone", + knife: "hocho", + envelope: "email", + pencil: "memo", + open_book: "book", + sailboat: "boat", + red_car: "car", + lantern: "izakaya_lantern", + uk: "gb", + heavy_exclamation_mark: "exclamation", + squirrel: "shipit" + }.with_indifferent_access + def self.path_to_emoji_image(name) "emoji/#{Emoji.emoji_filename(name)}.png" end + + def self.normilize_emoji_name(name) + ALIASES[name] || name + end end diff --git a/lib/banzai.rb b/lib/banzai.rb new file mode 100644 index 0000000000..093382261a --- /dev/null +++ b/lib/banzai.rb @@ -0,0 +1,13 @@ +module Banzai + def self.render(text, context = {}) + Renderer.render(text, context) + end + + def self.render_result(text, context = {}) + Renderer.render_result(text, context) + end + + def self.post_process(html, context) + Renderer.post_process(html, context) + end +end diff --git a/lib/banzai/cross_project_reference.rb b/lib/banzai/cross_project_reference.rb new file mode 100644 index 0000000000..ba2866e1ef --- /dev/null +++ b/lib/banzai/cross_project_reference.rb @@ -0,0 +1,22 @@ +require 'banzai' + +module Banzai + # Common methods for ReferenceFilters that support an optional cross-project + # reference. + module CrossProjectReference + # Given a cross-project reference string, get the Project record + # + # Defaults to value of `context[:project]` if: + # * No reference is given OR + # * Reference given doesn't exist + # + # ref - String reference. + # + # Returns a Project, or nil if the reference can't be found + def project_from_ref(ref) + return context[:project] unless ref + + Project.find_with_namespace(ref) + end + end +end diff --git a/lib/banzai/filter.rb b/lib/banzai/filter.rb new file mode 100644 index 0000000000..fd4fe02425 --- /dev/null +++ b/lib/banzai/filter.rb @@ -0,0 +1,10 @@ +require 'active_support/core_ext/string/output_safety' +require 'banzai' + +module Banzai + module Filter + def self.[](name) + const_get("#{name.to_s.camelize}Filter") + end + end +end diff --git a/lib/banzai/filter/abstract_reference_filter.rb b/lib/banzai/filter/abstract_reference_filter.rb new file mode 100644 index 0000000000..bdaa4721b4 --- /dev/null +++ b/lib/banzai/filter/abstract_reference_filter.rb @@ -0,0 +1,145 @@ +require 'banzai' + +module Banzai + module Filter + # Issues, Merge Requests, Snippets, Commits and Commit Ranges share + # similar functionality in reference filtering. + class AbstractReferenceFilter < ReferenceFilter + include CrossProjectReference + + def self.object_class + # Implement in child class + # Example: MergeRequest + end + + def self.object_name + object_class.name.underscore + end + + def self.object_sym + object_name.to_sym + end + + def self.data_reference + "data-#{object_name.dasherize}" + end + + # Public: Find references in text (like `!123` for merge requests) + # + # AnyReferenceFilter.references_in(text) do |match, id, project_ref, matches| + # object = find_object(project_ref, id) + # "#{object.to_reference}" + # end + # + # text - String text to search. + # + # Yields the String match, the Integer referenced object ID, an optional String + # of the external project reference, and all of the matchdata. + # + # Returns a String replaced with the return of the block. + def self.references_in(text, pattern = object_class.reference_pattern) + text.gsub(pattern) do |match| + yield match, $~[object_sym].to_i, $~[:project], $~ + end + end + + def self.referenced_by(node) + { object_sym => LazyReference.new(object_class, node.attr(data_reference)) } + end + + delegate :object_class, :object_sym, :references_in, to: :class + + def find_object(project, id) + # Implement in child class + # Example: project.merge_requests.find + end + + def url_for_object(object, project) + # Implement in child class + # Example: project_merge_request_url + end + + def call + # `#123` + replace_text_nodes_matching(object_class.reference_pattern) do |content| + object_link_filter(content, object_class.reference_pattern) + end + + # `[Issue](#123)`, which is turned into + # `Issue` + replace_link_nodes_with_href(object_class.reference_pattern) do |link, text| + object_link_filter(link, object_class.reference_pattern, link_text: text) + end + + # `http://gitlab.example.com/namespace/project/issues/123`, which is turned into + # `http://gitlab.example.com/namespace/project/issues/123` + replace_link_nodes_with_text(object_class.link_reference_pattern) do |text| + object_link_filter(text, object_class.link_reference_pattern) + end + + # `[Issue](http://gitlab.example.com/namespace/project/issues/123)`, which is turned into + # `Issue` + replace_link_nodes_with_href(object_class.link_reference_pattern) do |link, text| + object_link_filter(link, object_class.link_reference_pattern, link_text: text) + end + end + + # Replace references (like `!123` for merge requests) in text with links + # to the referenced object's details page. + # + # text - String text to replace references in. + # pattern - Reference pattern to match against. + # link_text - Original content of the link being replaced. + # + # Returns a String with references replaced with links. All links + # have `gfm` and `gfm-OBJECT_NAME` class names attached for styling. + def object_link_filter(text, pattern, link_text: nil) + references_in(text, pattern) do |match, id, project_ref, matches| + project = project_from_ref(project_ref) + + if project && object = find_object(project, id) + title = escape_once(object_link_title(object)) + klass = reference_class(object_sym) + + data = data_attribute( + original: link_text || match, + project: project.id, + object_sym => object.id + ) + + url = matches[:url] if matches.names.include?("url") + url ||= url_for_object(object, project) + + text = link_text + unless text + text = object.reference_link_text(context[:project]) + + extras = object_link_text_extras(object, matches) + text += " (#{extras.join(", ")})" if extras.any? + end + + %(#{text}) + else + match + end + end + end + + def object_link_text_extras(object, matches) + extras = [] + + if matches.names.include?("anchor") && matches[:anchor] && matches[:anchor] =~ /\A\#note_(\d+)\z/ + extras << "comment #{$1}" + end + + extras + end + + def object_link_title(object) + "#{object_class.name.titleize}: #{object.title}" + end + end + end +end diff --git a/lib/gitlab/markdown/autolink_filter.rb b/lib/banzai/filter/autolink_filter.rb similarity index 98% rename from lib/gitlab/markdown/autolink_filter.rb rename to lib/banzai/filter/autolink_filter.rb index c37c3bc55b..da4ee80c1b 100644 --- a/lib/gitlab/markdown/autolink_filter.rb +++ b/lib/banzai/filter/autolink_filter.rb @@ -1,9 +1,9 @@ -require 'gitlab/markdown' +require 'banzai' require 'html/pipeline/filter' require 'uri' -module Gitlab - module Markdown +module Banzai + module Filter # HTML Filter for auto-linking URLs in HTML. # # Based on HTML::Pipeline::AutolinkFilter diff --git a/lib/banzai/filter/commit_range_reference_filter.rb b/lib/banzai/filter/commit_range_reference_filter.rb new file mode 100644 index 0000000000..e67cd45ab9 --- /dev/null +++ b/lib/banzai/filter/commit_range_reference_filter.rb @@ -0,0 +1,58 @@ +require 'banzai' + +module Banzai + module Filter + # HTML filter that replaces commit range references with links. + # + # This filter supports cross-project references. + class CommitRangeReferenceFilter < AbstractReferenceFilter + def self.object_class + CommitRange + end + + def self.references_in(text, pattern = CommitRange.reference_pattern) + text.gsub(pattern) do |match| + yield match, $~[:commit_range], $~[:project], $~ + end + end + + def self.referenced_by(node) + project = Project.find(node.attr("data-project")) rescue nil + return unless project + + id = node.attr("data-commit-range") + range = find_object(project, id) + + return unless range + + { commit_range: range } + end + + def initialize(*args) + super + + @commit_map = {} + end + + def self.find_object(project, id) + range = CommitRange.new(id, project) + + range.valid_commits? ? range : nil + end + + def find_object(*args) + self.class.find_object(*args) + end + + def url_for_object(range, project) + h = Gitlab::Application.routes.url_helpers + h.namespace_project_compare_url(project.namespace, project, + range.to_param.merge(only_path: context[:only_path])) + end + + def object_link_title(range) + range.reference_title + end + end + end +end diff --git a/lib/banzai/filter/commit_reference_filter.rb b/lib/banzai/filter/commit_reference_filter.rb new file mode 100644 index 0000000000..9e57608b48 --- /dev/null +++ b/lib/banzai/filter/commit_reference_filter.rb @@ -0,0 +1,63 @@ +require 'banzai' + +module Banzai + module Filter + # HTML filter that replaces commit references with links. + # + # This filter supports cross-project references. + class CommitReferenceFilter < AbstractReferenceFilter + def self.object_class + Commit + end + + def self.references_in(text, pattern = Commit.reference_pattern) + text.gsub(pattern) do |match| + yield match, $~[:commit], $~[:project], $~ + end + end + + def self.referenced_by(node) + project = Project.find(node.attr("data-project")) rescue nil + return unless project + + id = node.attr("data-commit") + commit = find_object(project, id) + + return unless commit + + { commit: commit } + end + + def self.find_object(project, id) + if project && project.valid_repo? + project.commit(id) + end + end + + def find_object(*args) + self.class.find_object(*args) + end + + def url_for_object(commit, project) + h = Gitlab::Application.routes.url_helpers + h.namespace_project_commit_url(project.namespace, project, commit, + only_path: context[:only_path]) + end + + def object_link_title(commit) + commit.link_title + end + + def object_link_text_extras(object, matches) + extras = super + + path = matches[:path] if matches.names.include?("path") + if path == '/builds' + extras.unshift "builds" + end + + extras + end + end + end +end diff --git a/lib/gitlab/markdown/emoji_filter.rb b/lib/banzai/filter/emoji_filter.rb similarity index 97% rename from lib/gitlab/markdown/emoji_filter.rb rename to lib/banzai/filter/emoji_filter.rb index da10e4d376..86838e1483 100644 --- a/lib/gitlab/markdown/emoji_filter.rb +++ b/lib/banzai/filter/emoji_filter.rb @@ -1,10 +1,10 @@ require 'action_controller' -require 'gitlab/markdown' +require 'banzai' require 'gitlab_emoji' require 'html/pipeline/filter' -module Gitlab - module Markdown +module Banzai + module Filter # HTML filter that replaces :emoji: with images. # # Based on HTML::Pipeline::EmojiFilter diff --git a/lib/gitlab/markdown/external_issue_reference_filter.rb b/lib/banzai/filter/external_issue_reference_filter.rb similarity index 65% rename from lib/gitlab/markdown/external_issue_reference_filter.rb rename to lib/banzai/filter/external_issue_reference_filter.rb index 8f86f13976..f5942740cd 100644 --- a/lib/gitlab/markdown/external_issue_reference_filter.rb +++ b/lib/banzai/filter/external_issue_reference_filter.rb @@ -1,7 +1,7 @@ -require 'gitlab/markdown' +require 'banzai' -module Gitlab - module Markdown +module Banzai + module Filter # HTML filter that replaces external issue tracker references with links. # References are ignored if the project doesn't use an external issue # tracker. @@ -23,6 +23,18 @@ module Gitlab end end + def self.referenced_by(node) + project = Project.find(node.attr("data-project")) rescue nil + return unless project + + id = node.attr("data-external-issue") + external_issue = ExternalIssue.new(id, project) + + return unless external_issue + + { external_issue: external_issue } + end + def call # Early return if the project isn't using an external tracker return doc if project.nil? || project.default_issues_tracker? @@ -30,6 +42,10 @@ module Gitlab replace_text_nodes_matching(ExternalIssue.reference_pattern) do |content| issue_link_filter(content) end + + replace_link_nodes_with_href(ExternalIssue.reference_pattern) do |link, text| + issue_link_filter(link, link_text: text) + end end # Replace `JIRA-123` issue references in text with links to the referenced @@ -39,19 +55,23 @@ module Gitlab # # Returns a String with `JIRA-123` references replaced with links. All # links have `gfm` and `gfm-issue` class names attached for styling. - def issue_link_filter(text) + def issue_link_filter(text, link_text: nil) project = context[:project] - self.class.references_in(text) do |match, issue| - url = url_for_issue(issue, project, only_path: context[:only_path]) + self.class.references_in(text) do |match, id| + ExternalIssue.new(id, project) + + url = url_for_issue(id, project, only_path: context[:only_path]) title = escape_once("Issue in #{project.external_issue_tracker.title}") klass = reference_class(:issue) - data = data_attribute(project: project.id) + data = data_attribute(project: project.id, external_issue: id) + + text = link_text || match %(#{match}) + class="#{klass}">#{text}) end end diff --git a/lib/gitlab/markdown/external_link_filter.rb b/lib/banzai/filter/external_link_filter.rb similarity index 79% rename from lib/gitlab/markdown/external_link_filter.rb rename to lib/banzai/filter/external_link_filter.rb index 29e51b6ade..ac87b9820a 100644 --- a/lib/gitlab/markdown/external_link_filter.rb +++ b/lib/banzai/filter/external_link_filter.rb @@ -1,16 +1,16 @@ -require 'gitlab/markdown' +require 'banzai' require 'html/pipeline/filter' -module Gitlab - module Markdown +module Banzai + module Filter # HTML Filter to add a `rel="nofollow"` attribute to external links # class ExternalLinkFilter < HTML::Pipeline::Filter def call doc.search('a').each do |node| - next unless node.has_attribute?('href') + link = node.attr('href') - link = node.attribute('href').value + next unless link # Skip non-HTTP(S) links next unless link.start_with?('http') diff --git a/lib/banzai/filter/issue_reference_filter.rb b/lib/banzai/filter/issue_reference_filter.rb new file mode 100644 index 0000000000..51180cb901 --- /dev/null +++ b/lib/banzai/filter/issue_reference_filter.rb @@ -0,0 +1,23 @@ +require 'banzai' + +module Banzai + module Filter + # HTML filter that replaces issue references with links. References to + # issues that do not exist are ignored. + # + # This filter supports cross-project references. + class IssueReferenceFilter < AbstractReferenceFilter + def self.object_class + Issue + end + + def find_object(project, id) + project.get_issue(id) + end + + def url_for_object(issue, project) + IssuesHelper.url_for_issue(issue.iid, project, only_path: context[:only_path]) + end + end + end +end diff --git a/lib/gitlab/markdown/label_reference_filter.rb b/lib/banzai/filter/label_reference_filter.rb similarity index 76% rename from lib/gitlab/markdown/label_reference_filter.rb rename to lib/banzai/filter/label_reference_filter.rb index 618acb7a57..07bac2dd7f 100644 --- a/lib/gitlab/markdown/label_reference_filter.rb +++ b/lib/banzai/filter/label_reference_filter.rb @@ -1,7 +1,7 @@ -require 'gitlab/markdown' +require 'banzai' -module Gitlab - module Markdown +module Banzai + module Filter # HTML filter that replaces label references with links. class LabelReferenceFilter < ReferenceFilter # Public: Find label references in text @@ -30,6 +30,10 @@ module Gitlab replace_text_nodes_matching(Label.reference_pattern) do |content| label_link_filter(content) end + + replace_link_nodes_with_href(Label.reference_pattern) do |link, text| + label_link_filter(link, link_text: text) + end end # Replace label references in text with links to the label specified. @@ -38,7 +42,7 @@ module Gitlab # # Returns a String with label references replaced with links. All links # have `gfm` and `gfm-label` class names attached for styling. - def label_link_filter(text) + def label_link_filter(text, link_text: nil) project = context[:project] self.class.references_in(text) do |match, id, name| @@ -47,10 +51,16 @@ module Gitlab if label = project.labels.find_by(params) url = url_for_label(project, label) klass = reference_class(:label) - data = data_attribute(project: project.id, label: label.id) + data = data_attribute( + original: link_text || match, + project: project.id, + label: label.id + ) + + text = link_text || render_colored_label(label) %(#{render_colored_label(label)}) + class="#{klass}">#{text}) else match end @@ -59,9 +69,8 @@ module Gitlab def url_for_label(project, label) h = Gitlab::Application.routes.url_helpers - h.namespace_project_issues_path(project.namespace, project, - label_name: label.name, - only_path: context[:only_path]) + h.namespace_project_issues_url( project.namespace, project, label_name: label.name, + only_path: context[:only_path]) end def render_colored_label(label) diff --git a/lib/banzai/filter/markdown_filter.rb b/lib/banzai/filter/markdown_filter.rb new file mode 100644 index 0000000000..d09cf41df3 --- /dev/null +++ b/lib/banzai/filter/markdown_filter.rb @@ -0,0 +1,42 @@ +require 'banzai' +require 'html/pipeline/filter' + +module Banzai + module Filter + class MarkdownFilter < HTML::Pipeline::TextFilter + def initialize(text, context = nil, result = nil) + super text, context, result + @text = @text.delete "\r" + end + + def call + html = self.class.renderer.render(@text) + html.rstrip! + html + end + + private + + def self.redcarpet_options + # https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use + @redcarpet_options ||= { + fenced_code_blocks: true, + footnotes: true, + lax_spacing: true, + no_intra_emphasis: true, + space_after_headers: true, + strikethrough: true, + superscript: true, + tables: true + }.freeze + end + + def self.renderer + @renderer ||= begin + renderer = Redcarpet::Render::HTML.new + Redcarpet::Markdown.new(renderer, redcarpet_options) + end + end + end + end +end diff --git a/lib/banzai/filter/merge_request_reference_filter.rb b/lib/banzai/filter/merge_request_reference_filter.rb new file mode 100644 index 0000000000..755b946a34 --- /dev/null +++ b/lib/banzai/filter/merge_request_reference_filter.rb @@ -0,0 +1,41 @@ +require 'banzai' + +module Banzai + module Filter + # HTML filter that replaces merge request references with links. References + # to merge requests that do not exist are ignored. + # + # This filter supports cross-project references. + class MergeRequestReferenceFilter < AbstractReferenceFilter + def self.object_class + MergeRequest + end + + def find_object(project, id) + project.merge_requests.find_by(iid: id) + end + + def url_for_object(mr, project) + h = Gitlab::Application.routes.url_helpers + h.namespace_project_merge_request_url(project.namespace, project, mr, + only_path: context[:only_path]) + end + + def object_link_text_extras(object, matches) + extras = super + + path = matches[:path] if matches.names.include?("path") + case path + when '/diffs' + extras.unshift "diffs" + when '/commits' + extras.unshift "commits" + when '/builds' + extras.unshift "builds" + end + + extras + end + end + end +end diff --git a/lib/gitlab/markdown/redactor_filter.rb b/lib/banzai/filter/redactor_filter.rb similarity index 70% rename from lib/gitlab/markdown/redactor_filter.rb rename to lib/banzai/filter/redactor_filter.rb index a1f3a8a8eb..89e7a79789 100644 --- a/lib/gitlab/markdown/redactor_filter.rb +++ b/lib/banzai/filter/redactor_filter.rb @@ -1,8 +1,8 @@ -require 'gitlab/markdown' +require 'banzai' require 'html/pipeline/filter' -module Gitlab - module Markdown +module Banzai + module Filter # HTML filter that removes references to records that the current user does # not have permission to view. # @@ -12,7 +12,10 @@ module Gitlab def call doc.css('a.gfm').each do |node| unless user_can_reference?(node) - node.replace(node.text) + # The reference should be replaced by the original text, + # which is not always the same as the rendered text. + text = node.attr('data-original') || node.text + node.replace(text) end end @@ -24,7 +27,7 @@ module Gitlab def user_can_reference?(node) if node.has_attribute?('data-reference-filter') reference_type = node.attr('data-reference-filter') - reference_filter = reference_type.constantize + reference_filter = Banzai::Filter.const_get(reference_type) reference_filter.user_can_reference?(current_user, node, context) else diff --git a/lib/gitlab/markdown/reference_filter.rb b/lib/banzai/filter/reference_filter.rb similarity index 57% rename from lib/gitlab/markdown/reference_filter.rb rename to lib/banzai/filter/reference_filter.rb index a4c560f578..33457a3f36 100644 --- a/lib/gitlab/markdown/reference_filter.rb +++ b/lib/banzai/filter/reference_filter.rb @@ -1,9 +1,9 @@ require 'active_support/core_ext/string/output_safety' -require 'gitlab/markdown' +require 'banzai' require 'html/pipeline/filter' -module Gitlab - module Markdown +module Banzai + module Filter # Base class for GitLab Flavored Markdown reference filters. # # References within

, , , and