diff options
350 files changed, 1828 insertions, 3211 deletions
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml index 5acfdb4e832..fd179f77e26 100644 --- a/.gitlab/ci/frontend.gitlab-ci.yml +++ b/.gitlab/ci/frontend.gitlab-ci.yml @@ -104,6 +104,7 @@ gitlab:ui:visual: artifacts: paths: - tests/__image_snapshots__/ + when: always karma: extends: .dedicated-no-docs-pull-cache-job diff --git a/.gitlab/ci/reports.gitlab-ci.yml b/.gitlab/ci/reports.gitlab-ci.yml index df1fec61c25..8bcf8d4cb48 100644 --- a/.gitlab/ci/reports.gitlab-ci.yml +++ b/.gitlab/ci/reports.gitlab-ci.yml @@ -1,5 +1,5 @@ include: - - local: /lib/gitlab/ci/templates/Code-Quality.gitlab-ci.yml + - template: Code-Quality.gitlab-ci.yml code_quality: extends: .dedicated-no-docs-no-db-pull-cache-job diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml index a7f6caedd37..dee72930a28 100644 --- a/.gitlab/ci/review.gitlab-ci.yml +++ b/.gitlab/ci/review.gitlab-ci.yml @@ -83,7 +83,6 @@ schedule:review-build-cng: <<: *review-schedules-only <<: *review-build-cng-base - .review-deploy-base: &review-deploy-base <<: *review-base allow_failure: true @@ -145,6 +144,7 @@ schedule:review-deploy: review-qa-smoke: <<: *review-qa-base + retry: 2 script: - wait_for_job_to_be_done "review-deploy" - gitlab-qa Test::Instance::Smoke "${QA_IMAGE}" "${CI_ENVIRONMENT_URL}" @@ -175,6 +175,7 @@ review-performance: <<: *review-performance-base review-stop: + <<: *review-base extends: .single-script-job-dedicated-runner image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-charts-build-base allow_failure: true @@ -229,4 +230,3 @@ danger-review: - node --version - yarn install --frozen-lockfile --cache-folder .yarn-cache - danger --fail-on-errors=true - diff --git a/CHANGELOG.md b/CHANGELOG.md index 41506746c98..c512585ff6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,237 @@ documentation](doc/development/changelog.md) for instructions on adding your own entry. +## 11.10.0 (2019-04-22) + +### Security (9 changes) + +- Update Rails to 5.0.7.2. !27022 +- Disallow guest users from accessing Releases. +- Return cached languages if they've been detected before. +- Added rake task for removing EXIF data from existing uploads. +- Disallow updating namespace when updating a project. +- Fix XSS in resolve conflicts form. +- Hide "related branches" when user does not have permission. +- Fix PDF.js vulnerability. +- Use UntrustedRegexp for matching refs policy. + +### Fixed (81 changes, 21 of them are from the community) + +- Update `border-radius` of form controls and remove extra space above page titles. !24497 +- Disallow reopening of a locked merge request. !24882 (Jan Beckmann) +- Align EmailValidator to validate_email gem implementation. !24971 (Horatiu Eugen Vlad) +- add a uniq constraints on issues and mrs labels. !25435 (Antoine Huret) +- Display draft when toggling replies. !25563 +- Fix markdown table header and table content borders. !25666 +- Fix authorized application count. !25715 (moyuru) +- Added "Add List" checkbox to create label dropdown to make creation of list optional. !25716 (Tucker Chapman) +- Makes emoji picker full width on mobile. !25883 (Jacopo Beschi @jacopo-beschi) +- Don't cutoff letters in MR and Issue links. !25910 (gfyoung) +- Fix unwanted character replacement on project members page caused by usage of sanitize function. !25946 (Elias Werberich) +- Fix UI for closed MR when source project is removed. !25967 (Takuya Noguchi) +- Keep inline as much as possible in system notes on issuable. !25968 (Takuya Noguchi) +- Fixes long review app subdomains. !25990 (walkafwalka) +- Fix counting of groups in admin dashboard. !26009 +- Disable inaccessible navigation links upon archiving a project. !26020 (Elias Werberich) +- Fixed - Create project label window is cut off at the bottom. !26049 +- Fix error shown when loading links to specific comments. !26092 +- Fix group transfer selection possibilities. !26123 (Peter Marko) +- Fix UI layout on Commits on mobile. !26133 (Takuya Noguchi) +- Fix continuous bitbucket import loading spinner. !26175 +- Resolves Branch name is lost if I change commit mode in Web IDE. !26180 +- Fix removing remote mirror failure which leaves unnecessary refs behind. !26213 +- Fix Error 500 when user commits Wiki page with no commit message. !26247 +- Handle missing keys in sentry api response. !26264 +- Implemented whitespace-trimming for file names in Web IDE. !26270 +- Fix misalignment of group overview page buttons. !26292 +- Reject HEAD requests to info/refs endpoint. !26334 +- Prevent namespace dropdown in new project form from exceeding container. !26343 +- Fix hover animation consistency in top navbar items. !26345 +- Exclude system notes from commits in merge request discussions. !26396 +- Resolve Code in other column of side-by-side diff is highlighted when selecting code on one side. !26423 +- Prevent fade out transition on loading-button component. !26428 +- Fix merge commits being used as default squash commit messages. !26445 +- Expand resolved discussion when linking to a comment in the discussion. !26483 +- Show statistics also when repository is disabled. !26509 (Peter Marko) +- Fix multiple series queries on metrics dashboard. !26514 +- Releases will now be automatically deleted when deleting corresponding tag. !26530 +- Make stylistic improvements to diff nav header. !26557 +- Clear pipeline status cache after destruction of pipeline. !26575 +- Update fugit which fixes a potential infinite loop. !26579 +- Fixes job link in artifacts page breadcrumb. !26592 +- Fix quick actions add label name middle word overlaps. !26602 (Jacopo Beschi @jacopo-beschi) +- Fix Auto DevOps missing domain error handling. !26627 +- Fix jupyter rendering bug that ended in an infinite loop. !26656 (ROSPARS Benoit) +- Use a fixed git abbrev parameter when we fetch a git revision. !26707 +- Enabled text selection highlighting in diffs in Web IDE. !26721 (Isaac Smith) +- Remove `path` and `branch` labels from metrics. !26744 +- Resolve "Hide Kubernetes cluster warning if project has cluster related". !26749 +- Fix long label overflow on metrics dashboard. !26775 +- Group transfer now properly redirects to edit on failure. !26837 +- Only execute system hooks once when pushing tags. !26888 +- Fix UI anchor links after docs refactor. !26890 +- Fix MWPS does not work for merge request pipelines. !26906 +- Create pipelines for merge requests only when source branch is updated. !26921 +- Fix notfication emails having wrong encoding. !26931 +- Allow task lists that follow a blockquote to work correctly. !26937 +- Fix image diff swipe view on commit and compare pages. !26968 (ftab) +- Fix IDE detection of MR from fork with same branch name. !26986 +- Fix single string values for the 'include' keyword validation of gitlab-ci.yml. !26998 (Paul Bonaud (@paulrbr)) +- Do not display Ingress IP help text when there isn’t an Ingress IP assigned. !27057 +- Fix real-time updates for projects that contain a reserved word. !27060 +- Remove duplicates from issue related merge requests. !27067 +- Add to white-space nowrap to all buttons. !27069 +- Handle possible HTTP exception for Sentry client. !27080 +- Guard against nil dereferenced_target. !27192 +- Update GitLab Workhorse to v8.5.1. !27217 +- Fix long file header names bug in diffs. !27233 +- Always return the deployment in the UpdateDeploymentService#execute method. !27322 +- Fix remove_source_branch merge request API handling. !27392 +- Fixed bug with hashes in urls in WebIDE. !54376 (Kieran Andrews) +- Fix bug where MR popover doesn't go away on mouse leave. +- Only consider active milestones when using the special Started milestone filter. +- Scroll to diff file content when clicking on file header name and it is not a link to other page. +- Remove non-functional add issue button on welcome list. +- Fixed expand full file button showing on images. +- Fixed Web IDE web workers not working with relative URLs. +- Fixed Web IDE not loading merge request files. +- Fixed duplicated diff too large error message. +- Fixed sticky headers in merge request creation diffs. +- Fix bug when reopening milestone from index page. + +### Deprecated (1 change) + +- Allow to use untrusted Regexp via feature flag. !26905 + +### Changed (35 changes, 4 of them are from the community) + +- Create MR pipelines with `refs/merge-requests/:iid/head`. !25504 +- Create Kubernetes resources for projects when their deployment jobs run. !25586 +- Remove unnecessary folder prefix from environment name. !25600 +- Update deploy boards to additionally select on "app.gitlab.com" annotations. !25623 +- Allow failed custom hook script errors to safely appear in GitLab UI by filtering error messages by the prefix GL-HOOK-ERR:. !25625 +- Add link on two-factor authorization settings page to leave group that enforces two-factor authorization. !25731 +- Reduce height of instance system header and footer. !25752 +- Unify behaviour of 'Copy commit SHA to clipboard' to use full commit SHA. !25829 (Max Winterstein) +- Show loading spinner while Ingress/Knative IP is being assigned. !25912 +- Hashed Storage: Prevent a migration and rollback running at the same time. !25976 +- Make time counters show 'just now' for everything under one minute. !25992 (Sergiu Marton) +- Allow filtering labels list by one or two characters. !26012 +- Implements the creation strategy for multi-line suggestions. !26057 +- Automate base domain help text on Clusters page. !26124 +- Set user.name limit to 128 characters. !26146 +- Update gitlab-markup to 1.7.0 which requies python3. !26246 +- Update system message banner font size to 12px. !26293 +- Extend timezone dropdown. !26311 +- Upgrade to Gitaly v1.29.0. !26406 +- Automatically set Prometheus step interval. !26441 +- Knative version bump 0.2.2 -> 0.3.0. !26459 (Chris Baumbauer) +- Display cluster form validation error messages inline. !26502 +- Split Auto-DevOps.gitlab-ci.yml into reusable templates. !26520 +- Update spinners in group list component. !26572 +- Allow removing last owner from subgroup if parent group has owners. !26718 +- Check mergeability in MergeToRefService. !26757 +- Show download diff links for closed MRs. !26772 +- Fix Container Scanning in Kubernetes Runners. !26793 +- Move "Authorize project access with external service" to Core. !26823 +- Localize notifications dropdown. !26844 +- Order labels alphabetically in issue boards. !26927 +- Upgrade to Gitaly v1.32.0. !26989 +- Upgrade to Gitaly v1.33.0. !27065 +- collapse file tree by default if the merge request changes only one file. (Riccardo Padovani <riccardo@rpadovani.com>) +- Removes the undescriptive CI Charts header. + +### Performance (17 changes) + +- Drop legacy artifacts usage as there are no leftovers. !24294 +- Cache Repository#root_ref within a request. !25903 +- Allow ref name caching CommitService#find_commit. !26248 +- Avoid loading pipeline status in project search. !26342 +- Fix some N+1s in loading routes and counting members for groups in @-autocomplete. !26491 +- GitHub import: Run housekeeping after initial import. !26600 +- Add initial complexity limits to GraphQL queries. !26629 +- Cache FindCommit results in pipelines view. !26776 +- Fix and expand Gitaly FindCommit caching. !27018 +- Enable FindCommit caching for project and commits pages. !27048 +- Expand FindCommit caching to blob and refs. !27084 +- Enable Gitaly FindCommit caching for TreeController. !27100 +- Improve performance of PR import. !27121 +- Process at most 4 pipelines during push. !27205 +- Disable method instrumentation for diffs. !27235 +- Speed up filtering issues in a project when searching. +- Speed up generation of avatar URLs when using object storage. + +### Added (35 changes, 6 of them are from the community) + +- Add users search results to global search. !21197 (Alexis Reigel) +- Add target branch filter to merge requests search bar. !24380 (Hiroyuki Sato) +- Add Knative metrics to Prometheus. !24663 (Chris Baumbauer <cab@cabnetworks.net>) +- Support multi-line suggestions. !25211 +- Allow to sort wiki pages by date and title. !25365 +- Allow external diffs to be used conditionally. !25432 +- Add usage counts for error tracking feature. !25472 +- Enable/disable Auto DevOps at the Group level. !25533 +- Update pipeline list view to accommodate post-merge pipeline information. !25690 +- GraphQL Types can be made to always authorize access to resources of that Type. !25724 +- Update clair-local-scan to 2.0.6. !25743 (Takuya Noguchi) +- Update pipeline block on merge request page to accommodate post-merge pipeline information. !25745 +- Support multiple queries per chart on metrics dash. !25758 +- Update pipeline detail view to accommodate post-merge pipelines. !25775 +- Update job detail sidebar to accommodate post-merge pipeline information. !25777 +- Add merge request pipeline flag to pipeline entity. !25846 +- Expose group id on home panel. !25897 (Peter Marko) +- Move allow developers to create projects in groups to Core. !25975 +- Add two new warning messages to the MR widget about merge request pipelines. !25983 +- Support installing Group runner on group-level cluster. !26260 +- Improve the Knative installation on Clusters. !26339 +- Show error when namespace/svc account missing. !26362 +- Add select by title to milestones API. !26573 +- Implemented support for creation of new files from URL in Web IDE. !26622 +- Add control for masking variable values in runner logs. !26751 +- Allow merge requests to be created via git push options. !26752 +- Create a shortcut for a new MR in the Web IDE. !26792 +- Allow reactive caching to be used in services. !26839 +- Add a Prometheus API per environment. !26841 +- Allow merge requests to be set to merge when pipeline succeeds via git push options. !26842 +- Use gitlabktl to build and deploy GitLab Serverless Functions. !26926 +- Make touch events work on image diff swipe view and onion skin. !26971 (ftab) +- Add extended merge request tooltip. +- Added prometheus monitoring to GraphQL. +- Adding highest role property to admin's user details page. + +### Other (29 changes, 6 of them are from the community) + +- Update rack-oauth2 1.2.1 -> 1.9.3. !17868 +- Merge the gitlab-shell "gitlab-keys" functionality into GitLab CE. !25598 +- Refactor all_pipelines in Merge request. !25676 +- Show error backtrace when logging errors to kubernetes.log. !25726 +- Apply recaptcha API change in 4.0. !25921 (Praveen Arimbrathodiyil) +- Remove fake repository_path response. !25942 (Fabio Papa) +- Use curl silent/show-error options on Auto DevOps. !25954 (Takuya Noguchi) +- Explicitly set master_auth setting to enable basic auth and client certificate for new GKE clusters. !26018 +- Project: Improve empty repository state UI. !26024 +- Externalize strings from `/app/views/projects/pipelines`. !26035 (George Tsiolis) +- Prepare multi-line suggestions for rendering in Markdown. !26107 +- Improve mobile UI on User Profile page. !26240 (Takuya Noguchi) +- Update GitLab Runner Helm Chart to 0.3.0/11.9.0. !26467 +- Improve project merge request settings. !26495 +- Bump kubectl to 1.11.9 and Helm to 2.13.1 in Auto-DevOps.gitlab-ci.yml. !26534 +- Upgrade bootstrap_form Gem. !26568 +- Add API access check to Graphql. !26570 +- Change project avatar remove button to a link. !26589 +- Log Gitaly RPC duration to api_json.log and production_json.log. !26652 +- Add cluster domain to Project Cluster API. !26735 +- Move project tags to separate line. !26797 +- Changed button label at /pipelines/new. !26893 (antfobe,leonardofl) +- Update GitLab Shell to v9.0.0. !27002 +- Migrate clusters tests to jest. !27013 +- Rewrite related MRs widget with Vue. !27027 +- Restore HipChat project service. !27172 +- Externalize admin deploy keys strings. +- Removes EE differences for environments_table.vue. +- Removes EE differences for environment_item.vue. + + ## 11.9.8 (2019-04-11) ### Deprecated (1 change) diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 7aa332e4163..2b17ffd5042 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -1.33.0 +1.34.0 @@ -274,6 +274,9 @@ gem 'sentry-raven', '~> 2.7' gem 'premailer-rails', '~> 1.9.7' +# LabKit: Tracing and Correlation +gem 'gitlab-labkit', '~> 0.1.2' + # I18n gem 'ruby_parser', '~> 3.8', require: false gem 'rails-i18n', '~> 5.1' @@ -301,12 +304,6 @@ group :metrics do gem 'raindrops', '~> 0.18' end -group :tracing do - # OpenTracing - gem 'opentracing', '~> 0.4.3' - gem 'jaeger-client', '~> 0.10.0' -end - group :development do gem 'foreman', '~> 0.84.0' gem 'brakeman', '~> 4.2', require: false diff --git a/Gemfile.lock b/Gemfile.lock index 95c377e2725..ba4418cd8b3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -286,6 +286,12 @@ GEM github-markup (1.7.0) gitlab-default_value_for (3.1.1) activerecord (>= 3.2.0, < 6.0) + gitlab-labkit (0.1.2) + actionpack (~> 5) + activesupport (~> 5) + grpc (~> 1.15) + jaeger-client (~> 0.10) + opentracing (~> 0.4) gitlab-markup (1.7.0) gitlab-sidekiq-fetcher (0.4.0) sidekiq (~> 5) @@ -571,7 +577,7 @@ GEM validate_email validate_url webfinger (>= 1.0.1) - opentracing (0.4.3) + opentracing (0.5.0) optimist (3.0.0) org-ruby (0.9.12) rubypants (~> 0.2) @@ -1050,6 +1056,7 @@ DEPENDENCIES gitaly-proto (~> 1.19.0) github-markup (~> 1.7.0) gitlab-default_value_for (~> 3.1.1) + gitlab-labkit (~> 0.1.2) gitlab-markup (~> 1.7.0) gitlab-sidekiq-fetcher (~> 0.4.0) gitlab-styles (~> 2.5) @@ -1076,7 +1083,6 @@ DEPENDENCIES httparty (~> 0.16.4) icalendar influxdb (~> 0.2) - jaeger-client (~> 0.10.0) jira-ruby (~> 1.4) js_regex (~> 3.1) json-schema (~> 2.8.0) @@ -1117,7 +1123,6 @@ DEPENDENCIES omniauth-twitter (~> 1.4) omniauth-ultraauth (~> 0.0.1) omniauth_crowd (~> 2.2.0) - opentracing (~> 0.4.3) org-ruby (~> 0.9.12) peek (~> 1.0.1) peek-gc (~> 0.0.2) @@ -1 +1 @@ -11.10.0-pre +11.11.0-pre diff --git a/app/assets/javascripts/boards/components/board_blank_state.vue b/app/assets/javascripts/boards/components/board_blank_state.vue index 667eea17d44..47a46502bff 100644 --- a/app/assets/javascripts/boards/components/board_blank_state.vue +++ b/app/assets/javascripts/boards/components/board_blank_state.vue @@ -60,11 +60,15 @@ export default { </script> <template> - <div class="board-blank-state"> + <div class="board-blank-state p-3"> <p>Add the following default lists to your Issue Board with one click:</p> - <ul class="board-blank-state-list"> + <ul class="list-unstyled board-blank-state-list"> <li v-for="(label, index) in predefinedLabels" :key="index"> - <span :style="{ backgroundColor: label.color }" class="label-color"> </span> + <span + :style="{ backgroundColor: label.color }" + class="label-color position-relative d-inline-block rounded" + > + </span> {{ label.title }} </li> </ul> diff --git a/app/assets/javascripts/boards/components/board_card.vue b/app/assets/javascripts/boards/components/board_card.vue index f569322ab70..c9effa0639b 100644 --- a/app/assets/javascripts/boards/components/board_card.vue +++ b/app/assets/javascripts/boards/components/board_card.vue @@ -83,7 +83,7 @@ export default { }" :index="index" :data-issue-id="issue.id" - class="board-card" + class="board-card position-relative p-3 rounded" @mousedown="mouseDown" @mousemove="mouseMove" @mouseup="showIssue($event)" diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue index f3f341ece5c..c9972d051aa 100644 --- a/app/assets/javascripts/boards/components/board_list.vue +++ b/app/assets/javascripts/boards/components/board_list.vue @@ -221,7 +221,10 @@ export default { </script> <template> - <div class="board-list-component"> + <div + :class="{ 'd-none': !list.isExpanded, 'd-flex flex-column': list.isExpanded }" + class="board-list-component position-relative h-100" + > <div v-if="loading" class="board-list-loading text-center" aria-label="Loading issues"> <gl-loading-icon /> </div> @@ -236,7 +239,7 @@ export default { :data-board="list.id" :data-board-type="list.type" :class="{ 'is-smaller': showIssueForm }" - class="board-list js-board-list" + class="board-list w-100 h-100 list-unstyled mb-0 p-1 js-board-list" > <board-card v-for="(issue, index) in issues" diff --git a/app/assets/javascripts/boards/components/board_new_issue.vue b/app/assets/javascripts/boards/components/board_new_issue.vue index 28d96dab605..70daba352f9 100644 --- a/app/assets/javascripts/boards/components/board_new_issue.vue +++ b/app/assets/javascripts/boards/components/board_new_issue.vue @@ -95,7 +95,7 @@ export default { <template> <div class="board-new-issue-form"> - <div class="board-card"> + <div class="board-card position-relative p-3 rounded"> <form @submit="submit($event)"> <div v-if="error" class="flash-container"> <div class="flash-alert">An error occurred. Please try again.</div> diff --git a/app/assets/javascripts/boards/components/issue_card_inner.vue b/app/assets/javascripts/boards/components/issue_card_inner.vue index be0de63e772..6aa689b4056 100644 --- a/app/assets/javascripts/boards/components/issue_card_inner.vue +++ b/app/assets/javascripts/boards/components/issue_card_inner.vue @@ -4,6 +4,7 @@ import { GlTooltipDirective } from '@gitlab/ui'; import { sprintf, __ } from '~/locale'; import Icon from '~/vue_shared/components/icon.vue'; import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue'; +import issueCardInner from 'ee_else_ce/boards/mixins/issue_card_inner'; import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue'; import eventHub from '../eventhub'; import IssueDueDate from './issue_due_date.vue'; @@ -19,11 +20,13 @@ export default { TooltipOnTruncate, IssueDueDate, IssueTimeEstimate, + IssueCardWeight: () => import('ee_component/boards/components/issue_card_weight.vue'), IssueCardInnerScopedLabel, }, directives: { GlTooltip: GlTooltipDirective, }, + mixins: [issueCardInner], props: { issue: { type: Object, @@ -135,14 +138,6 @@ export default { this.applyFilter(filter); }, - filterByWeight(weight) { - if (!this.updateFilters) return; - - const issueWeight = encodeURIComponent(weight); - const filter = `weight=${issueWeight}`; - - this.applyFilter(filter); - }, applyFilter(filter) { const filterPath = boardsStore.filter.path.split('&'); const filterIndex = filterPath.indexOf(filter); @@ -173,7 +168,7 @@ export default { </script> <template> <div> - <div class="board-card-header"> + <div class="d-flex board-card-header"> <h4 class="board-card-title append-bottom-0 prepend-top-0"> <icon v-if="issue.confidential" @@ -214,11 +209,11 @@ export default { </div> <div class="board-card-footer d-flex justify-content-between align-items-end"> <div - class="d-flex align-items-start flex-wrap-reverse board-card-number-container js-board-card-number-container" + class="d-flex align-items-start flex-wrap-reverse board-card-number-container overflow-hidden js-board-card-number-container" > <span v-if="issue.referencePath" - class="board-card-number d-flex append-right-8 prepend-top-8" + class="board-card-number overflow-hidden d-flex append-right-8 prepend-top-8" > <tooltip-on-truncate v-if="issueReferencePath" @@ -232,10 +227,14 @@ export default { <issue-due-date v-if="issue.dueDate" :date="issue.dueDate" /><issue-time-estimate v-if="issue.timeEstimate" :estimate="issue.timeEstimate" + /><issue-card-weight + v-if="issue.weight" + :weight="issue.weight" + @click="filterByWeight(issue.weight)" /> </span> </div> - <div class="board-card-assignee"> + <div class="board-card-assignee d-flex"> <user-avatar-link v-for="(assignee, index) in issue.assignees" v-if="shouldRenderAssignee(index)" diff --git a/app/assets/javascripts/boards/components/issue_due_date.vue b/app/assets/javascripts/boards/components/issue_due_date.vue index 9bc66978198..3bc7f13a9e6 100644 --- a/app/assets/javascripts/boards/components/issue_due_date.vue +++ b/app/assets/javascripts/boards/components/issue_due_date.vue @@ -82,7 +82,11 @@ export default { <template> <span> <span ref="issueDueDate" :class="cssClass" class="board-card-info card-number"> - <icon :class="{ 'text-danger': isPastDue, 'board-card-info-icon': true }" name="calendar" /> + <icon + :class="{ 'text-danger': isPastDue }" + class="board-card-info-icon align-top" + name="calendar" + /> <time :class="{ 'text-danger': isPastDue }" datetime="date" class="board-card-info-text">{{ body }}</time> diff --git a/app/assets/javascripts/boards/components/issue_time_estimate.vue b/app/assets/javascripts/boards/components/issue_time_estimate.vue index 5acc3025b2c..98c1d29db16 100644 --- a/app/assets/javascripts/boards/components/issue_time_estimate.vue +++ b/app/assets/javascripts/boards/components/issue_time_estimate.vue @@ -28,7 +28,7 @@ export default { <template> <span> <span ref="issueTimeEstimate" class="board-card-info card-number"> - <icon name="hourglass" css-classes="board-card-info-icon" /><time + <icon name="hourglass" css-classes="board-card-info-icon align-top" /><time class="board-card-info-text" >{{ timeEstimate }}</time > diff --git a/app/assets/javascripts/boards/components/modal/empty_state.vue b/app/assets/javascripts/boards/components/modal/empty_state.vue index 2a0008467c4..091700de93f 100644 --- a/app/assets/javascripts/boards/components/modal/empty_state.vue +++ b/app/assets/javascripts/boards/components/modal/empty_state.vue @@ -42,8 +42,8 @@ export default { </script> <template> - <section class="empty-state"> - <div class="row"> + <section class="empty-state d-flex mt-0 h-100"> + <div class="row w-100 my-auto mx-0"> <div class="col-12 col-md-6 order-md-last"> <aside class="svg-content d-none d-md-block"><img :src="emptyStateSvg" /></aside> </div> diff --git a/app/assets/javascripts/boards/components/modal/header.vue b/app/assets/javascripts/boards/components/modal/header.vue index 1f0961e02d8..1cfa6d39362 100644 --- a/app/assets/javascripts/boards/components/modal/header.vue +++ b/app/assets/javascripts/boards/components/modal/header.vue @@ -50,8 +50,8 @@ export default { </script> <template> <div> - <header class="add-issues-header form-actions"> - <h2> + <header class="add-issues-header border-top-0 form-actions"> + <h2 class="m-0"> Add issues <button type="button" @@ -65,7 +65,7 @@ export default { </h2> </header> <modal-tabs v-if="!loading && issuesCount > 0" /> - <div v-if="showSearch" class="add-issues-search append-bottom-10"> + <div v-if="showSearch" class="d-flex append-bottom-10"> <modal-filters :store="filter" /> <button ref="selectAllBtn" diff --git a/app/assets/javascripts/boards/components/modal/index.vue b/app/assets/javascripts/boards/components/modal/index.vue index 1e5761cf268..8e09e265cfb 100644 --- a/app/assets/javascripts/boards/components/modal/index.vue +++ b/app/assets/javascripts/boards/components/modal/index.vue @@ -143,8 +143,11 @@ export default { }; </script> <template> - <div v-if="showAddIssuesModal" class="add-issues-modal"> - <div class="add-issues-container"> + <div + v-if="showAddIssuesModal" + class="add-issues-modal d-flex position-fixed position-top-0 position-bottom-0 position-left-0 position-right-0 h-100" + > + <div class="add-issues-container d-flex flex-column m-auto rounded"> <modal-header :project-id="projectId" :milestone-path="milestonePath" @@ -161,8 +164,10 @@ export default { :new-issue-path="newIssuePath" :empty-state-svg="emptyStateSvg" /> - <section v-if="loading || filterLoading" class="add-issues-list text-center"> - <div class="add-issues-list-loading"><gl-loading-icon /></div> + <section v-if="loading || filterLoading" class="add-issues-list d-flex h-100 text-center"> + <div class="add-issues-list-loading w-100 align-self-center"> + <gl-loading-icon size="md" /> + </div> </section> <modal-footer /> </div> diff --git a/app/assets/javascripts/boards/components/modal/list.vue b/app/assets/javascripts/boards/components/modal/list.vue index e9ed2de859d..28d2019af2f 100644 --- a/app/assets/javascripts/boards/components/modal/list.vue +++ b/app/assets/javascripts/boards/components/modal/list.vue @@ -117,7 +117,7 @@ export default { }; </script> <template> - <section ref="list" class="add-issues-list add-issues-list-columns"> + <section ref="list" class="add-issues-list add-issues-list-columns d-flex h-100"> <div v-if="issuesCount > 0 && issues.length === 0" class="empty-state add-issues-empty-state-filter text-center" @@ -129,7 +129,7 @@ export default { <div v-for="issue in group" v-if="showIssue(issue)" :key="issue.id" class="board-card-parent"> <div :class="{ 'is-active': issue.selected }" - class="board-card" + class="board-card position-relative p-3 rounded" @click="toggleIssue($event, issue)" > <issue-card-inner :issue="issue" :issue-link-base="issueLinkBase" :root-path="rootPath" /> diff --git a/app/assets/javascripts/boards/mixins/issue_card_inner.js b/app/assets/javascripts/boards/mixins/issue_card_inner.js new file mode 100644 index 00000000000..8000237da6d --- /dev/null +++ b/app/assets/javascripts/boards/mixins/issue_card_inner.js @@ -0,0 +1,5 @@ +export default { + methods: { + filterByWeight() {}, + }, +}; diff --git a/app/assets/javascripts/clusters/components/application_row.vue b/app/assets/javascripts/clusters/components/application_row.vue index 19e5ac1567d..937e4c3bfc3 100644 --- a/app/assets/javascripts/clusters/components/application_row.vue +++ b/app/assets/javascripts/clusters/components/application_row.vue @@ -6,6 +6,8 @@ import { s__, sprintf } from '../../locale'; import eventHub from '../event_hub'; import identicon from '../../vue_shared/components/identicon.vue'; import loadingButton from '../../vue_shared/components/loading_button.vue'; +import UninstallApplicationButton from './uninstall_application_button.vue'; + import { APPLICATION_STATUS, REQUEST_SUBMITTED, @@ -19,6 +21,7 @@ export default { identicon, TimeagoTooltip, GlLink, + UninstallApplicationButton, }, props: { id: { @@ -47,6 +50,11 @@ export default { required: false, default: false, }, + uninstallable: { + type: Boolean, + required: false, + default: false, + }, status: { type: String, required: false, @@ -63,6 +71,11 @@ export default { type: String, required: false, }, + installed: { + type: Boolean, + required: false, + default: false, + }, version: { type: String, required: false, @@ -92,15 +105,7 @@ export default { return ( this.status === APPLICATION_STATUS.SCHEDULED || this.status === APPLICATION_STATUS.INSTALLING || - (this.requestStatus === REQUEST_SUBMITTED && !this.statusReason && !this.isInstalled) - ); - }, - isInstalled() { - return ( - this.status === APPLICATION_STATUS.INSTALLED || - this.status === APPLICATION_STATUS.UPDATED || - this.status === APPLICATION_STATUS.UPDATING || - this.status === APPLICATION_STATUS.UPDATE_ERRORED + (this.requestStatus === REQUEST_SUBMITTED && !this.statusReason && !this.installed) ); }, canInstall() { @@ -125,6 +130,12 @@ export default { rowJsClass() { return `js-cluster-application-row-${this.id}`; }, + displayUninstallButton() { + return this.installed && this.uninstallable; + }, + displayInstallButton() { + return !this.installed || !this.uninstallable; + }, installButtonLoading() { return !this.status || this.status === APPLICATION_STATUS.SCHEDULED || this.isInstalling; }, @@ -145,7 +156,7 @@ export default { label = s__('ClusterIntegration|Install'); } else if (this.isInstalling) { label = s__('ClusterIntegration|Installing'); - } else if (this.isInstalled) { + } else if (this.installed) { label = s__('ClusterIntegration|Installed'); } @@ -257,7 +268,7 @@ export default { <div :class="[ rowJsClass, - isInstalled && 'cluster-application-installed', + installed && 'cluster-application-installed', disabled && 'cluster-application-disabled', ]" class="cluster-application-row gl-responsive-table-row gl-responsive-table-row-col-span" @@ -280,10 +291,9 @@ export default { target="blank" rel="noopener noreferrer" class="js-cluster-application-title" + >{{ title }}</a > - {{ title }} - </a> - <span v-else class="js-cluster-application-title"> {{ title }} </span> + <span v-else class="js-cluster-application-title">{{ title }}</span> </strong> <slot name="description"></slot> <div @@ -308,17 +318,15 @@ export default { class="form-text text-muted label p-0 js-cluster-application-upgrade-details" > {{ versionLabel }} - - <span v-if="upgradeSuccessful"> to</span> + <span v-if="upgradeSuccessful">to</span> <gl-link v-if="upgradeSuccessful" :href="chartRepo" target="_blank" class="js-cluster-application-upgrade-version" + >chart v{{ version }}</gl-link > - chart v{{ version }} - </gl-link> </div> <div @@ -333,7 +341,6 @@ export default { class="bs-callout bs-callout-success cluster-application-banner mt-2 mb-0 p-0 pl-3" > {{ upgradeSuccessDescription }} - <button class="close cluster-application-banner-close" @click="dismissUpgradeSuccess"> × </button> @@ -354,18 +361,23 @@ export default { role="gridcell" > <div v-if="showManageButton" class="btn-group table-action-buttons"> - <a :href="manageLink" :class="{ disabled: disabled }" class="btn"> - {{ manageButtonLabel }} - </a> + <a :href="manageLink" :class="{ disabled: disabled }" class="btn">{{ + manageButtonLabel + }}</a> </div> <div class="btn-group table-action-buttons"> <loading-button + v-if="displayInstallButton" :loading="installButtonLoading" :disabled="disabled || installButtonDisabled" :label="installButtonLabel" class="js-cluster-application-install-button" @click="installClicked" /> + <uninstall-application-button + v-if="displayUninstallButton" + class="js-cluster-application-uninstall-button" + /> </div> </div> </div> diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue index d54f9ce552c..ae4fe11c6ae 100644 --- a/app/assets/javascripts/clusters/components/applications.vue +++ b/app/assets/javascripts/clusters/components/applications.vue @@ -238,6 +238,7 @@ export default { :status-reason="applications.helm.statusReason" :request-status="applications.helm.requestStatus" :request-reason="applications.helm.requestReason" + :installed="applications.helm.installed" class="rounded-top" title-link="https://docs.helm.sh/" > @@ -265,6 +266,7 @@ export default { :status-reason="applications.ingress.statusReason" :request-status="applications.ingress.requestStatus" :request-reason="applications.ingress.requestReason" + :installed="applications.ingress.installed" :disabled="!helmInstalled" title-link="https://kubernetes.io/docs/concepts/services-networking/ingress/" > @@ -341,6 +343,7 @@ export default { :status-reason="applications.cert_manager.statusReason" :request-status="applications.cert_manager.requestStatus" :request-reason="applications.cert_manager.requestReason" + :installed="applications.cert_manager.installed" :install-application-request-params="{ email: applications.cert_manager.email }" :disabled="!helmInstalled" title-link="https://cert-manager.readthedocs.io/en/latest/#" @@ -387,6 +390,7 @@ export default { :status-reason="applications.prometheus.statusReason" :request-status="applications.prometheus.requestStatus" :request-reason="applications.prometheus.requestReason" + :installed="applications.prometheus.installed" :disabled="!helmInstalled" title-link="https://prometheus.io/docs/introduction/overview/" > @@ -403,6 +407,7 @@ export default { :version="applications.runner.version" :chart-repo="applications.runner.chartRepo" :upgrade-available="applications.runner.upgradeAvailable" + :installed="applications.runner.installed" :disabled="!helmInstalled" title-link="https://docs.gitlab.com/runner/" > @@ -424,6 +429,7 @@ export default { :status-reason="applications.jupyter.statusReason" :request-status="applications.jupyter.requestStatus" :request-reason="applications.jupyter.requestReason" + :installed="applications.jupyter.installed" :install-application-request-params="{ hostname: applications.jupyter.hostname }" :disabled="!helmInstalled" title-link="https://jupyterhub.readthedocs.io/en/stable/" @@ -483,6 +489,7 @@ export default { :status-reason="applications.knative.statusReason" :request-status="applications.knative.requestStatus" :request-reason="applications.knative.requestReason" + :installed="applications.knative.installed" :install-application-request-params="{ hostname: applications.knative.hostname }" :disabled="!helmInstalled" title-link="https://github.com/knative/docs" diff --git a/app/assets/javascripts/clusters/components/uninstall_application_button.vue b/app/assets/javascripts/clusters/components/uninstall_application_button.vue new file mode 100644 index 00000000000..30918d1d115 --- /dev/null +++ b/app/assets/javascripts/clusters/components/uninstall_application_button.vue @@ -0,0 +1,14 @@ +<script> +// TODO: Implement loading button component +import LoadingButton from '~/vue_shared/components/loading_button.vue'; + +export default { + components: { + LoadingButton, + }, +}; +</script> + +<template> + <loading-button @click="$emit('click')" /> +</template> diff --git a/app/assets/javascripts/clusters/constants.js b/app/assets/javascripts/clusters/constants.js index 67f481f2afb..17849497c87 100644 --- a/app/assets/javascripts/clusters/constants.js +++ b/app/assets/javascripts/clusters/constants.js @@ -15,9 +15,24 @@ export const APPLICATION_STATUS = { UPDATING: 'updating', UPDATED: 'updated', UPDATE_ERRORED: 'update_errored', + UNINSTALLING: 'uninstalling', + UNINSTALL_ERRORED: 'uninstall_errored', ERROR: 'errored', }; +/* + * The application cannot be in any of the following states without + * not being installed. + */ +export const APPLICATION_INSTALLED_STATUSES = [ + APPLICATION_STATUS.INSTALLED, + APPLICATION_STATUS.UPDATING, + APPLICATION_STATUS.UPDATED, + APPLICATION_STATUS.UPDATE_ERRORED, + APPLICATION_STATUS.UNINSTALLING, + APPLICATION_STATUS.UNINSTALL_ERRORED, +]; + // These are only used client-side export const REQUEST_SUBMITTED = 'request-submitted'; export const REQUEST_FAILURE = 'request-failure'; diff --git a/app/assets/javascripts/clusters/stores/clusters_store.js b/app/assets/javascripts/clusters/stores/clusters_store.js index 92993337f02..38512ac28c2 100644 --- a/app/assets/javascripts/clusters/stores/clusters_store.js +++ b/app/assets/javascripts/clusters/stores/clusters_store.js @@ -1,6 +1,23 @@ import { s__ } from '../../locale'; import { parseBoolean } from '../../lib/utils/common_utils'; -import { INGRESS, JUPYTER, KNATIVE, CERT_MANAGER, RUNNER } from '../constants'; +import { + INGRESS, + JUPYTER, + KNATIVE, + CERT_MANAGER, + RUNNER, + APPLICATION_INSTALLED_STATUSES, +} from '../constants'; + +const isApplicationInstalled = appStatus => APPLICATION_INSTALLED_STATUSES.includes(appStatus); + +const applicationInitialState = { + status: null, + statusReason: null, + requestReason: null, + requestStatus: null, + installed: false, +}; export default class ClusterStore { constructor() { @@ -12,60 +29,39 @@ export default class ClusterStore { statusReason: null, applications: { helm: { + ...applicationInitialState, title: s__('ClusterIntegration|Helm Tiller'), - status: null, - statusReason: null, - requestStatus: null, - requestReason: null, }, ingress: { + ...applicationInitialState, title: s__('ClusterIntegration|Ingress'), - status: null, - statusReason: null, - requestStatus: null, - requestReason: null, externalIp: null, externalHostname: null, }, cert_manager: { + ...applicationInitialState, title: s__('ClusterIntegration|Cert-Manager'), - status: null, - statusReason: null, - requestStatus: null, - requestReason: null, email: null, }, runner: { + ...applicationInitialState, title: s__('ClusterIntegration|GitLab Runner'), - status: null, - statusReason: null, - requestStatus: null, - requestReason: null, version: null, chartRepo: 'https://gitlab.com/charts/gitlab-runner', upgradeAvailable: null, }, prometheus: { + ...applicationInitialState, title: s__('ClusterIntegration|Prometheus'), - status: null, - statusReason: null, - requestStatus: null, - requestReason: null, }, jupyter: { + ...applicationInitialState, title: s__('ClusterIntegration|JupyterHub'), - status: null, - statusReason: null, - requestStatus: null, - requestReason: null, hostname: null, }, knative: { + ...applicationInitialState, title: s__('ClusterIntegration|Knative'), - status: null, - statusReason: null, - requestStatus: null, - requestReason: null, hostname: null, isEditingHostName: false, externalIp: null, @@ -118,6 +114,7 @@ export default class ClusterStore { ...(this.state.applications[appId] || {}), status, statusReason, + installed: isApplicationInstalled(status), }; if (appId === INGRESS) { diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js index c81e754df4c..f1e26cdfa21 100644 --- a/app/assets/javascripts/gfm_auto_complete.js +++ b/app/assets/javascripts/gfm_auto_complete.js @@ -461,7 +461,10 @@ class GfmAutoComplete { // We can ignore this for quick actions because they are processed // before Markdown. if (!this.setting.skipMarkdownCharacterTest) { - withoutAt = withoutAt.replace(/([~\-_*`])/g, '\\$&'); + withoutAt = withoutAt + .replace(/(~~|`|\*)/g, '\\$1') + .replace(/(\b)(_+)/g, '$1\\$2') // only escape underscores at the start + .replace(/(_+)(\b)/g, '\\$1$2'); // or end of words } return `${at}${withoutAt}`; diff --git a/app/assets/javascripts/monitoring/stores/monitoring_store.js b/app/assets/javascripts/monitoring/stores/monitoring_store.js index 9761fe168be..013fb0d4540 100644 --- a/app/assets/javascripts/monitoring/stores/monitoring_store.js +++ b/app/assets/javascripts/monitoring/stores/monitoring_store.js @@ -45,14 +45,13 @@ function removeTimeSeriesNoData(queries) { // ] function groupQueriesByChartInfo(metrics) { const metricsByChart = metrics.reduce((accumulator, metric) => { - const { id, queries, ...chart } = metric; + const { queries, ...chart } = metric; + const metricId = chart.id ? chart.id.toString() : null; const chartKey = `${chart.title}|${chart.y_label}`; accumulator[chartKey] = accumulator[chartKey] || { ...chart, queries: [] }; - queries.forEach(queryAttrs => - accumulator[chartKey].queries.push({ metricId: id.toString(), ...queryAttrs }), - ); + queries.forEach(queryAttrs => accumulator[chartKey].queries.push({ metricId, ...queryAttrs })); return accumulator; }, {}); diff --git a/app/assets/javascripts/notes/components/discussion_actions.vue b/app/assets/javascripts/notes/components/discussion_actions.vue new file mode 100644 index 00000000000..22cca756ef6 --- /dev/null +++ b/app/assets/javascripts/notes/components/discussion_actions.vue @@ -0,0 +1,58 @@ +<script> +import ReplyPlaceholder from './discussion_reply_placeholder.vue'; +import ResolveDiscussionButton from './discussion_resolve_button.vue'; +import ResolveWithIssueButton from './discussion_resolve_with_issue_button.vue'; +import JumpToNextDiscussionButton from './discussion_jump_to_next_button.vue'; + +export default { + name: 'DiscussionActions', + components: { + ReplyPlaceholder, + ResolveDiscussionButton, + ResolveWithIssueButton, + JumpToNextDiscussionButton, + }, + props: { + discussion: { + type: Object, + required: true, + }, + isResolving: { + type: Boolean, + required: true, + }, + resolveButtonTitle: { + type: String, + required: true, + }, + resolveWithIssuePath: { + type: String, + required: false, + default: '', + }, + shouldShowJumpToNextDiscussion: { + type: Boolean, + required: true, + }, + }, +}; +</script> + +<template> + <div class="discussion-with-resolve-btn"> + <reply-placeholder class="qa-discussion-reply" @onClick="$emit('showReplyForm')" /> + <resolve-discussion-button + v-if="discussion.resolvable" + :is-resolving="isResolving" + :button-title="resolveButtonTitle" + @onClick="$emit('resolve')" + /> + <div v-if="discussion.resolvable" class="btn-group discussion-actions ml-sm-2" role="group"> + <resolve-with-issue-button v-if="resolveWithIssuePath" :url="resolveWithIssuePath" /> + <jump-to-next-discussion-button + v-if="shouldShowJumpToNextDiscussion" + @onClick="$emit('jumpToNextDiscussion')" + /> + </div> + </div> +</template> diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue index a3d664a738f..89563711bcd 100644 --- a/app/assets/javascripts/notes/components/noteable_discussion.vue +++ b/app/assets/javascripts/notes/components/noteable_discussion.vue @@ -14,7 +14,6 @@ import { SYSTEM_NOTE } from '../constants'; import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue'; import noteableNote from './noteable_note.vue'; import noteHeader from './note_header.vue'; -import resolveDiscussionButton from './discussion_resolve_button.vue'; import toggleRepliesWidget from './toggle_replies_widget.vue'; import noteSignedOutWidget from './note_signed_out_widget.vue'; import noteEditedText from './note_edited_text.vue'; @@ -25,10 +24,8 @@ import placeholderSystemNote from '../../vue_shared/components/notes/placeholder import noteable from '../mixins/noteable'; import resolvable from '../mixins/resolvable'; import discussionNavigation from '../mixins/discussion_navigation'; -import ReplyPlaceholder from './discussion_reply_placeholder.vue'; -import ResolveWithIssueButton from './discussion_resolve_with_issue_button.vue'; -import jumpToNextDiscussionButton from './discussion_jump_to_next_button.vue'; import eventHub from '../event_hub'; +import DiscussionActions from './discussion_actions.vue'; export default { name: 'NoteableDiscussion', @@ -40,16 +37,13 @@ export default { noteSignedOutWidget, noteEditedText, noteForm, - resolveDiscussionButton, - jumpToNextDiscussionButton, toggleRepliesWidget, - ReplyPlaceholder, placeholderNote, placeholderSystemNote, - ResolveWithIssueButton, systemNote, DraftNote: () => import('ee_component/batch_comments/components/draft_note.vue'), TimelineEntryItem, + DiscussionActions, }, directives: { GlTooltip: GlTooltipDirective, @@ -465,31 +459,17 @@ Please check your network connection and try again.`; :class="{ 'is-replying': isReplying }" class="discussion-reply-holder" > - <template v-if="!isReplying && canReply"> - <div class="discussion-with-resolve-btn"> - <reply-placeholder class="qa-discussion-reply" @onClick="showReplyForm" /> - <resolve-discussion-button - v-if="discussion.resolvable" - :is-resolving="isResolving" - :button-title="resolveButtonTitle" - @onClick="resolveHandler" - /> - <div - v-if="discussion.resolvable" - class="btn-group discussion-actions ml-sm-2" - role="group" - > - <resolve-with-issue-button - v-if="resolveWithIssuePath" - :url="resolveWithIssuePath" - /> - <jump-to-next-discussion-button - v-if="shouldShowJumpToNextDiscussion" - @onClick="jumpToNextDiscussion" - /> - </div> - </div> - </template> + <discussion-actions + v-if="!isReplying && canReply" + :discussion="discussion" + :is-resolving="isResolving" + :resolve-button-title="resolveButtonTitle" + :resolve-with-issue-path="resolveWithIssuePath" + :should-show-jump-to-next-discussion="shouldShowJumpToNextDiscussion" + @showReplyForm="showReplyForm" + @resolve="resolveHandler" + @jumpToNextDiscussion="jumpToNextDiscussion" + /> <note-form v-if="isReplying" ref="noteForm" diff --git a/app/assets/stylesheets/components/dashboard_skeleton.scss b/app/assets/stylesheets/components/dashboard_skeleton.scss index 42ede599bc6..9775c329922 100644 --- a/app/assets/stylesheets/components/dashboard_skeleton.scss +++ b/app/assets/stylesheets/components/dashboard_skeleton.scss @@ -8,10 +8,6 @@ &-warning { background-color: $orange-100; } - - &-failed { - background-color: $red-100; - } } &-body { @@ -36,10 +32,6 @@ border-radius: $gl-padding; height: $gl-padding-32; - &-failed { - background-color: $red-100; - } - &-arrow { color: $gray-300; } @@ -56,6 +48,13 @@ } } + &-header, + &-footer { + &-failed { + background-color: $red-100; + } + } + &-skeleton-info { border-radius: $gl-padding; height: $gl-padding; diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss index fc1c1bd9962..61fab445793 100644 --- a/app/assets/stylesheets/pages/boards.scss +++ b/app/assets/stylesheets/pages/boards.scss @@ -1,7 +1,3 @@ -[v-cloak] { - display: none; -} - .user-can-drag { cursor: grab; } @@ -40,35 +36,15 @@ margin: 0 8px 10px; padding-bottom: 10px; border-bottom: 1px solid $dropdown-divider-bg; - - > p { - margin: 0; - font-size: 14px; - } } .issue-boards-page { .content-wrapper { padding-bottom: 0; } - - .issues-details-filters { - display: flex; - } - - .filter-form { - width: 100%; - } -} - -.board-extra-actions { - font-size: 0; - white-space: nowrap; } .boards-app { - position: relative; - @include media-breakpoint-up(sm) { transition: width $sidebar-transition-duration; width: 100%; @@ -79,17 +55,9 @@ } } -.boards-app-loading { - width: 100%; - font-size: 34px; -} - .boards-list { height: calc(100vh - #{$issue-board-list-difference-xs}); - width: 100%; - padding: $gl-padding ($gl-padding / 2); overflow-x: scroll; - white-space: nowrap; min-height: 200px; @include media-breakpoint-only(sm) { @@ -114,13 +82,7 @@ } .board { - display: inline-block; width: calc(85vw - 15px); - height: 100%; - padding-right: ($gl-padding / 2); - padding-left: ($gl-padding / 2); - white-space: normal; - vertical-align: top; @include media-breakpoint-up(sm) { width: 400px; @@ -135,23 +97,7 @@ &.is-collapsed { width: 50px; - .board-header { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - - button { - display: none; - } - } - .board-title { - padding: 0; - border-bottom: 0; - justify-content: center; - > span { width: 100%; margin-top: -12px; @@ -167,34 +113,16 @@ left: 50%; margin-left: -10px; } - - .board-list-component, - .issue-count-badge { - display: none; - } - } - - &:not(.is-collapsed) { - .board-list-component { - display: flex; - flex-direction: column; - } } } .board-inner { - position: relative; - height: 100%; font-size: $issue-boards-font-size; background: $gray-light; border: 1px solid $border-color; - border-radius: $border-radius-default; - flex: 1; } .board-header { - position: relative; - &.has-border::before { border-top: 3px solid; border-color: inherit; @@ -219,18 +147,9 @@ } } -.board-inner-container { - border-bottom: 1px solid $border-color; - padding: $gl-padding; -} - .board-title { - margin: 0; - padding: $gl-padding-8 $gl-padding; font-size: 1em; border-bottom: 1px solid $border-color; - display: flex; - align-items: center; } .board-title-text { @@ -239,10 +158,8 @@ .board-delete { margin-right: 10px; - padding: 0; color: $gray-darkest; background-color: transparent; - border: 0; outline: 0; &:hover { @@ -252,7 +169,6 @@ .board-blank-state, .board-promotion-state { - padding: $gl-padding; background-color: $white-light; flex: 1; overflow-y: auto; @@ -260,35 +176,23 @@ } .board-blank-state-list { - list-style: none; - > li:not(:last-child) { margin-bottom: 8px; } .label-color { - position: relative; top: 2px; - display: inline-block; width: 16px; height: 16px; margin-right: 3px; - border-radius: $border-radius-default; } } .board-list-component { - position: relative; - flex: 1; min-height: 0; // firefox fix } .board-list { - height: 100%; - width: 100%; - margin-bottom: 0; - padding: $gl-padding-4; - list-style: none; overflow-y: auto; overflow-x: hidden; } @@ -299,13 +203,9 @@ } .board-card { - position: relative; - padding: $gl-padding; background: $white-light; - border-radius: $border-radius-default; border: 1px solid $gray-200; box-shadow: 0 1px 2px $issue-boards-card-shadow; - list-style: none; line-height: $gl-padding; &:not(:last-child) { @@ -333,10 +233,6 @@ } } - svg { - vertical-align: top; - } - .confidential-icon { color: $orange-600; cursor: help; @@ -360,12 +256,7 @@ } } -.board-card-header { - display: flex; -} - .board-card-assignee { - display: flex; margin-top: -$gl-padding-4; margin-bottom: -$gl-padding-4; @@ -425,34 +316,16 @@ .board-card-number { font-size: $gl-font-size-xs; color: $gl-text-color-secondary; - overflow: hidden; @include media-breakpoint-up(md) { font-size: $label-font-size; } } -.board-card-number-container { - overflow: hidden; -} - -.issue-boards-search { - width: 395px; - - .form-control { - display: inline-block; - width: 210px; - } -} - .board-list-count { padding: 10px 0; color: $gl-text-color-secondary; font-size: 13px; - - > .fa { - margin-right: 5px; - } } .board-new-issue-form { @@ -460,16 +333,9 @@ margin: 5px; } -.page-with-contextual-sidebar.layout-page .issue-boards-sidebar { - .issuable-sidebar-header { - position: relative; - } - +.issue-boards-sidebar { .gutter-toggle { - position: absolute; - top: 0; bottom: 15px; - right: 0; width: 22px; color: $gray-darkest; @@ -489,10 +355,6 @@ .issuable-header-text { @include overflow-break-word(); padding-right: 35px; - - > strong { - font-weight: $gl-font-weight-bold; - } } } @@ -511,44 +373,25 @@ } .add-issues-modal { - display: flex; - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; background-color: rgba($black, 0.3); z-index: 9999; } .add-issues-container { - display: flex; - flex-direction: column; width: 90vw; height: 85vh; max-width: 1100px; min-height: 500px; - margin: auto; padding: 25px 15px 0; background-color: $white-light; - border-radius: $border-radius-default; box-shadow: 0 2px 12px rgba($black, 0.5); .empty-state { - display: flex; - flex: 1; - margin-top: 0; - &.add-issues-empty-state-filter { flex-direction: column; justify-content: center; } - > .row { - width: 100%; - margin: auto 0; - } - .svg-content { margin-top: -40px; } @@ -557,25 +400,15 @@ .add-issues-header { margin: -25px -15px -5px; - border-top: 0; border-bottom: 1px solid $border-color; border-top-right-radius: $border-radius-default; border-top-left-radius: $border-radius-default; > h2 { - margin: 0; font-size: 18px; } } -.add-issues-search { - display: flex; - - .issues-filters { - flex: 1; - } -} - .add-issues-list-column { width: 100%; @@ -589,8 +422,6 @@ } .add-issues-list { - display: flex; - flex: 1; padding-top: 3px; margin-left: -$gl-vert-padding; margin-right: -$gl-vert-padding; @@ -607,14 +438,6 @@ } } -.add-issues-list-loading { - align-self: center; - width: 100%; - padding-left: $gl-vert-padding; - padding-right: $gl-vert-padding; - font-size: 35px; -} - .add-issues-footer { margin: auto -15px 0; padding-left: 15px; @@ -642,27 +465,6 @@ border-radius: 50%; } -.modal-filters { - display: flex; - - > .dropdown { - display: none; - margin-right: 10px; - - @include media-breakpoint-up(sm) { - display: block; - } - } - - .dropdown-menu-toggle { - width: 100px; - - @include media-breakpoint-up(md) { - width: 140px; - } - } -} - .board-card-info { color: $gl-text-color-secondary; white-space: nowrap; diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d5f1e35a79b..ceaa84acaba 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -128,7 +128,7 @@ class ApplicationController < ActionController::Base payload[:ua] = request.env["HTTP_USER_AGENT"] payload[:remote_ip] = request.remote_ip - payload[Gitlab::CorrelationId::LOG_KEY] = Gitlab::CorrelationId.current_id + payload[Labkit::Correlation::CorrelationId::LOG_KEY] = Labkit::Correlation::CorrelationId.current_id logged_user = auth_user diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 5cf9bb4979a..e5236051118 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -15,6 +15,7 @@ module Ci include Gitlab::Utils::StrongMemoize include Deployable include HasRef + include UpdateProjectStatistics BuildArchivedError = Class.new(StandardError) @@ -157,8 +158,7 @@ module Ci run_after_commit { BuildHooksWorker.perform_async(build.id) } end - after_save :update_project_statistics_after_save, if: :artifacts_size_changed? - after_destroy :update_project_statistics_after_destroy, unless: :project_destroyed? + update_project_statistics stat: :build_artifacts_size, attribute: :artifacts_size class << self # This is needed for url_for to work, @@ -847,21 +847,5 @@ module Ci pipeline.config_processor.build_attributes(name) end - - def update_project_statistics_after_save - update_project_statistics(read_attribute(:artifacts_size).to_i - artifacts_size_was.to_i) - end - - def update_project_statistics_after_destroy - update_project_statistics(-artifacts_size) - end - - def update_project_statistics(difference) - ProjectStatistics.increment_statistic(project_id, :build_artifacts_size, difference) - end - - def project_destroyed? - project.pending_delete? - end end end diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb index 9695d49d18b..7c836c6f95c 100644 --- a/app/models/ci/job_artifact.rb +++ b/app/models/ci/job_artifact.rb @@ -4,6 +4,7 @@ module Ci class JobArtifact < ApplicationRecord include AfterCommitQueue include ObjectStorage::BackgroundMove + include UpdateProjectStatistics extend Gitlab::Ci::Model NotSupportedAdapterError = Class.new(StandardError) @@ -52,8 +53,8 @@ module Ci validates :file_format, presence: true, unless: :trace?, on: :create validate :valid_file_format?, unless: :trace?, on: :create before_save :set_size, if: :file_changed? - after_save :update_project_statistics_after_save, if: :size_changed? - after_destroy :update_project_statistics_after_destroy, unless: :project_destroyed? + + update_project_statistics stat: :build_artifacts_size after_save :update_file_store, if: :file_changed? @@ -176,18 +177,6 @@ module Ci self.size = file.size end - def update_project_statistics_after_save - update_project_statistics(size.to_i - size_was.to_i) - end - - def update_project_statistics_after_destroy - update_project_statistics(-self.size.to_i) - end - - def update_project_statistics(difference) - ProjectStatistics.increment_statistic(project_id, :build_artifacts_size, difference) - end - def project_destroyed? # Use job.project to avoid extra DB query for project job.project.pending_delete? diff --git a/app/models/concerns/update_project_statistics.rb b/app/models/concerns/update_project_statistics.rb new file mode 100644 index 00000000000..bffc711c886 --- /dev/null +++ b/app/models/concerns/update_project_statistics.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +# This module is providing helpers for updating `ProjectStatistics` with `after_save` and `before_destroy` hooks. +# +# It deals with `ProjectStatistics.increment_statistic` making sure not to update statistics on a cascade delete from the +# project, and keeping track of value deltas on each save. It updates the DB only when a change is needed. +# +# How to use +# - Invoke `update_project_statistics stat: :a_project_statistics_column, attribute: :an_attr_to_track` in a model class body. +# +# Expectation +# - `attribute` must be an ActiveRecord attribute +# - The model must implement `project` and `project_id`. i.e. direct Project relationship or delegation +module UpdateProjectStatistics + extend ActiveSupport::Concern + + class_methods do + attr_reader :statistic_name, :statistic_attribute + + # Configure the model to update +stat+ on ProjectStatistics when +attribute+ changes + # + # +stat+:: a column of ProjectStatistics to update + # +attribute+:: an attribute of the current model, default to +:size+ + def update_project_statistics(stat:, attribute: :size) + @statistic_name = stat + @statistic_attribute = attribute + + after_save(:update_project_statistics_after_save, if: :update_project_statistics_attribute_changed?) + after_destroy(:update_project_statistics_after_destroy, unless: :project_destroyed?) + end + private :update_project_statistics + end + + included do + private + + def project_destroyed? + project.pending_delete? + end + + def update_project_statistics_attribute_changed? + attribute_changed?(self.class.statistic_attribute) + end + + def update_project_statistics_after_save + attr = self.class.statistic_attribute + delta = read_attribute(attr).to_i - attribute_was(attr).to_i + + update_project_statistics(delta) + end + + def update_project_statistics_after_destroy + update_project_statistics(-read_attribute(self.class.statistic_attribute).to_i) + end + + def update_project_statistics(delta) + ProjectStatistics.increment_statistic(project_id, self.class.statistic_name, delta) + end + end +end diff --git a/app/models/namespace.rb b/app/models/namespace.rb index dea34e812ca..8638c5a9c53 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -51,6 +51,7 @@ class Namespace < ApplicationRecord validate :nesting_level_allowed delegate :name, to: :owner, allow_nil: true, prefix: true + delegate :avatar_url, to: :owner, allow_nil: true after_commit :refresh_access_of_projects_invited_groups, on: :update, if: -> { previous_changes.key?('share_with_group_lock') } @@ -149,6 +150,10 @@ class Namespace < ApplicationRecord type == 'Group' ? 'group' : 'user' end + def user? + kind == 'user' + end + def find_fork_of(project) return unless project.fork_network diff --git a/app/views/projects/_merge_request_merge_checks_settings.html.haml b/app/views/projects/_merge_request_merge_checks_settings.html.haml new file mode 100644 index 00000000000..1ab467a3710 --- /dev/null +++ b/app/views/projects/_merge_request_merge_checks_settings.html.haml @@ -0,0 +1,19 @@ +- form = local_assigns.fetch(:form) + +.form-group + %b= s_('ProjectSettings|Merge checks') + %p.text-secondary= s_('ProjectSettings|These checks must pass before merge requests can be merged') + .form-check.mb-2.builds-feature{ class: ("hidden" if @project && @project.project_feature.send(:builds_access_level) == 0) } + = form.check_box :only_allow_merge_if_pipeline_succeeds, class: 'form-check-input' + = form.label :only_allow_merge_if_pipeline_succeeds, class: 'form-check-label' do + = s_('ProjectSettings|Pipelines must succeed') + .descr.text-secondary + = s_('ProjectSettings|Pipelines need to be configured to enable this feature.') + = link_to icon('question-circle'), + help_page_path('ci/merge_request_pipelines/index.md', + anchor: 'pipelines-for-merge-requests'), + target: '_blank' + .form-check.mb-2 + = form.check_box :only_allow_merge_if_all_discussions_are_resolved, class: 'form-check-input' + = form.label :only_allow_merge_if_all_discussions_are_resolved, class: 'form-check-label' do + = s_('ProjectSettings|All discussions must be resolved') diff --git a/app/views/projects/_merge_request_merge_method_settings.html.haml b/app/views/projects/_merge_request_merge_method_settings.html.haml index 9082bfc409d..47c311f42d0 100644 --- a/app/views/projects/_merge_request_merge_method_settings.html.haml +++ b/app/views/projects/_merge_request_merge_method_settings.html.haml @@ -1,30 +1,33 @@ - form = local_assigns.fetch(:form) .form-group - = label_tag :merge_method_merge, class: 'label-bold' do - = _('Merge method') - .form-check + %b= s_('ProjectSettings|Merge method') + %p.text-secondary= s_('ProjectSettings|This will dictate the commit history when you merge a merge request') + .form-check.mb-2 = form.radio_button :merge_method, :merge, class: "js-merge-method-radio form-check-input" = label_tag :project_merge_method_merge, class: 'form-check-label' do - .mb-3 - = _('Merge commit') - .text-secondary - = _('A merge commit is created for every merge, and merging is allowed as long as there are no conflicts.') + = s_('ProjectSettings|Merge commit') + .descr.text-secondary + = s_('ProjectSettings|Every merge creates a merge commit') -.form-check - = form.radio_button :merge_method, :rebase_merge, class: "js-merge-method-radio form-check-input" - = label_tag :project_merge_method_rebase_merge, class: 'form-check-label' do - .mb-3 - = _('Merge commit with semi-linear history') - .text-secondary - = _('A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build.') - .text-secondary - = _('When fast-forward merge is not possible, the user is given the option to rebase.') + .form-check.mb-2 + = form.radio_button :merge_method, :rebase_merge, class: "js-merge-method-radio form-check-input" + = label_tag :project_merge_method_rebase_merge, class: 'form-check-label' do + = s_('ProjectSettings|Merge commit with semi-linear history') + .descr.text-secondary + = s_('ProjectSettings|Every merge creates a merge commit') + %br + = s_('ProjectSettings|Fast-forward merges only') + %br + = s_('ProjectSettings|When conflicts arise the user is given the option to rebase') -.form-check - = form.radio_button :merge_method, :ff, class: "js-merge-method-radio qa-radio-button-merge-ff form-check-input" - = label_tag :project_merge_method_ff, class: 'form-check-label' do - .mb-3 - = _('Fast-forward merge') - .text-secondary - = _('No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase.') + .form-check.mb-2 + = form.radio_button :merge_method, :ff, class: "js-merge-method-radio qa-radio-button-merge-ff form-check-input" + = label_tag :project_merge_method_ff, class: 'form-check-label' do + = s_('ProjectSettings|Fast-forward merge') + .descr.text-secondary + = s_('ProjectSettings|No merge commits are created') + %br + = s_('ProjectSettings|Fast-forward merges only') + %br + = s_('ProjectSettings|When conflicts arise the user is given the option to rebase') diff --git a/app/views/projects/_merge_request_merge_options_settings.html.haml b/app/views/projects/_merge_request_merge_options_settings.html.haml new file mode 100644 index 00000000000..5ab475822de --- /dev/null +++ b/app/views/projects/_merge_request_merge_options_settings.html.haml @@ -0,0 +1,14 @@ +- form = local_assigns.fetch(:form) + +.form-group + %b= s_('ProjectSettings|Merge options') + %p.text-secondary= s_('ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed') + = render_if_exists 'projects/merge_pipelines_settings', form: form + .form-check.mb-2 + = form.check_box :resolve_outdated_diff_discussions, class: 'form-check-input' + = form.label :resolve_outdated_diff_discussions, class: 'form-check-label' do + = s_('ProjectSettings|Automatically resolve merge request diff discussions when they become outdated') + .form-check.mb-2 + = form.check_box :printing_merge_request_link_enabled, class: 'form-check-input' + = form.label :printing_merge_request_link_enabled, class: 'form-check-label' do + = s_('ProjectSettings|Show link to create/view merge request when pushing from the command line') diff --git a/app/views/projects/_merge_request_merge_settings.html.haml b/app/views/projects/_merge_request_merge_settings.html.haml deleted file mode 100644 index 3a9f7ca42db..00000000000 --- a/app/views/projects/_merge_request_merge_settings.html.haml +++ /dev/null @@ -1,24 +0,0 @@ -- form = local_assigns.fetch(:form) - -.form-group - .form-check.builds-feature{ class: ("hidden" if @project && @project.project_feature.send(:builds_access_level) == 0) } - = form.check_box :only_allow_merge_if_pipeline_succeeds, class: 'form-check-input' - = form.label :only_allow_merge_if_pipeline_succeeds, class: 'form-check-label' do - .mb-3 - = _('Only allow merge requests to be merged if the pipeline succeeds') - .text-secondary - = _('Pipelines need to be configured to enable this feature.') - = link_to icon('question-circle'), help_page_path('user/project/merge_requests/merge_when_pipeline_succeeds', anchor: 'only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds'), target: '_blank' - = render_if_exists 'projects/merge_pipelines_settings', form: form - .form-check - = form.check_box :only_allow_merge_if_all_discussions_are_resolved, class: 'form-check-input' - = form.label :only_allow_merge_if_all_discussions_are_resolved, class: 'form-check-label' do - %p= _('Only allow merge requests to be merged if all discussions are resolved') - .form-check - = form.check_box :resolve_outdated_diff_discussions, class: 'form-check-input' - = form.label :resolve_outdated_diff_discussions, class: 'form-check-label' do - %p= _('Automatically resolve merge request diff discussions when they become outdated') - .form-check - = form.check_box :printing_merge_request_link_enabled, class: 'form-check-input' - = form.label :printing_merge_request_link_enabled, class: 'form-check-label' do - %p= _('Show link to create/view merge request when pushing from the command line') diff --git a/app/views/projects/_merge_request_settings.html.haml b/app/views/projects/_merge_request_settings.html.haml index c80e831dd33..f2ba38387a3 100644 --- a/app/views/projects/_merge_request_settings.html.haml +++ b/app/views/projects/_merge_request_settings.html.haml @@ -2,4 +2,6 @@ = render 'projects/merge_request_merge_method_settings', project: @project, form: form -= render 'projects/merge_request_merge_settings', form: form += render 'projects/merge_request_merge_options_settings', project: @project, form: form + += render 'projects/merge_request_merge_checks_settings', project: @project, form: form diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 1a3e4a5d608..c04530dc62c 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -27,7 +27,7 @@ .settings-header %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Merge requests') %button.btn.btn-default.js-settings-toggle{ type: 'button' }= expanded ? _('Collapse') : _('Expand') - %p= _('Choose your merge method, set up a default merge request description template.') + %p= _('Choose your merge method, options, checks, and set up a default merge request description template.') .settings-content = render_if_exists 'shared/promotions/promote_mr_features' diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index 2c95ac6dbb3..4bf1d8702af 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -77,7 +77,7 @@ = edited_time_ago_with_tooltip(@issue, placement: 'bottom', html_class: 'issue-edited-ago js-issue-edited-ago') - #js-related-merge-requests{ data: { endpoint: api_v4_projects_issues_related_merge_requests_path(id: @project.id, issue_iid: @issue.iid), project_namespace: @project.namespace.path, project_path: @project.path } } + #js-related-merge-requests{ data: { endpoint: expose_url(api_v4_projects_issues_related_merge_requests_path(id: @project.id, issue_iid: @issue.iid)), project_namespace: @project.namespace.path, project_path: @project.path } } - if can?(current_user, :download_code, @project) #related-branches{ data: { url: related_branches_project_issue_path(@project, @issue) } } diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index ff7c36c2d5b..95027634de2 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -48,7 +48,12 @@ = form_for @project, html: { class: 'new_project' } do |f| = render 'new_project_fields', f: f, project_name_id: "blank-project-name" - .tab-pane.no-padding{ id: 'create-from-template-pane', class: active_when(active_tab == 'template'), role: 'tabpanel' } + #create-from-template-pane.tab-pane.px-0.pb-0{ class: active_when(active_tab == 'template'), role: 'tabpanel' } + .card-slim.m-4.p-4 + %div + - contributing_templates_url = 'https://gitlab.com/gitlab-org/project-templates/contributing' + - link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: contributing_templates_url } + = _('Learn how to %{link_start}contribute to the built-in templates%{link_end}').html_safe % { link_start: link_start, link_end: '</a>'.html_safe } = form_for @project, html: { class: 'new_project' } do |f| .project-template .form-group diff --git a/app/views/shared/_label_row.html.haml b/app/views/shared/_label_row.html.haml index 6651f12f6de..9d1648fbf70 100644 --- a/app/views/shared/_label_row.html.haml +++ b/app/views/shared/_label_row.html.haml @@ -1,13 +1,11 @@ - subject = local_assigns[:subject] - force_priority = local_assigns.fetch(:force_priority, false) -- show_label_issues_link = defined?(@project) && show_label_issuables_link?(label, :issues, project: @project) -- show_label_merge_requests_link = defined?(@project) && show_label_issuables_link?(label, :merge_requests, project: @project) +- subject_or_group_defined = defined?(@project) || defined?(@group) +- show_label_issues_link = subject_or_group_defined && show_label_issuables_link?(label, :issues, project: @project) +- show_label_merge_requests_link = subject_or_group_defined && show_label_issuables_link?(label, :merge_requests, project: @project) .label-name - - if defined?(@project) - = link_to_label(label, subject: @project, tooltip: false) - - else - = render_label(label, tooltip: false) + = render_label(label, tooltip: false) .label-description .append-right-default.prepend-left-default - if label.description.present? @@ -22,5 +20,6 @@ %li.label-link-item.inline = link_to_label(label, subject: subject, type: :merge_request) { _('Merge requests') } - if force_priority + · %li.label-link-item.priority-badge.js-priority-badge.inline.prepend-left-10 .label-badge.label-badge-blue= _('Prioritized label') diff --git a/app/views/shared/boards/_show.html.haml b/app/views/shared/boards/_show.html.haml index f0d1dd162df..813fccd217b 100644 --- a/app/views/shared/boards/_show.html.haml +++ b/app/views/shared/boards/_show.html.haml @@ -13,14 +13,14 @@ %script#js-board-modal-filter{ type: "text/x-template" }= render "shared/issuable/search_bar", type: :boards_modal, show_sorting_dropdown: false %script#js-board-promotion{ type: "text/x-template" }= render_if_exists "shared/promotions/promote_issue_board" -#board-app.boards-app{ "v-cloak" => true, data: board_data, ":class" => "{ 'is-compact': detailIssueVisible }" } +#board-app.boards-app.position-relative{ "v-cloak" => "true", data: board_data, ":class" => "{ 'is-compact': detailIssueVisible }" } .d-none.d-sm-none.d-md-block = render 'shared/issuable/search_bar', type: :boards, board: board - .boards-list - .boards-app-loading.text-center{ "v-if" => "loading" } - = icon("spinner spin") - %board{ "v-cloak" => true, + .boards-list.w-100.py-3.px-2.text-nowrap + .boards-app-loading.w-100.text-center{ "v-if" => "loading" } + = icon("spinner spin 2x") + %board{ "v-cloak" => "true", "v-for" => "list in state.lists", "ref" => "board", ":list" => "list", diff --git a/app/views/shared/boards/components/_board.html.haml b/app/views/shared/boards/components/_board.html.haml index 307a0919a4c..f9cfcabc015 100644 --- a/app/views/shared/boards/components/_board.html.haml +++ b/app/views/shared/boards/components/_board.html.haml @@ -1,8 +1,8 @@ -.board{ ":class" => '{ "is-draggable": !list.preset, "is-expandable": list.isExpandable, "is-collapsed": !list.isExpanded, "board-type-assignee": list.type === "assignee" }', +.board.d-inline-block.h-100.px-2.align-top.ws-normal{ ":class" => '{ "is-draggable": !list.preset, "is-expandable": list.isExpandable, "is-collapsed": !list.isExpanded, "board-type-assignee": list.type === "assignee" }', ":data-id" => "list.id" } - .board-inner.d-flex.flex-column - %header.board-header{ ":class" => '{ "has-border": list.label && list.label.color }', ":style" => "{ borderTopColor: (list.label && list.label.color ? list.label.color : null) }", "@click" => "toggleExpanded($event)" } - %h3.board-title.js-board-handle{ ":class" => '{ "user-can-drag": (!disabled && !list.preset) }' } + .board-inner.d-flex.flex-column.position-relative.h-100.rounded + %header.board-header{ ":class" => '{ "has-border": list.label && list.label.color, "position-relative": list.isExpanded, "position-absolute position-top-0 position-left-0 w-100 h-100": !list.isExpanded }', ":style" => "{ borderTopColor: (list.label && list.label.color ? list.label.color : null) }", "@click" => "toggleExpanded($event)" } + %h3.board-title.m-0.d-flex.align-items-center.py-2.px-3.js-board-handle{ ":class" => '{ "user-can-drag": (!disabled && !list.preset), "p-0 border-bottom-0 justify-content-center": !list.isExpanded }' } %i.fa.fa-fw.board-title-expandable-toggle{ "v-if": "list.isExpandable", ":class": "{ \"fa-caret-down\": list.isExpanded, \"fa-caret-right\": !list.isExpanded }", "aria-hidden": "true" } @@ -31,9 +31,9 @@ %board-delete{ "inline-template" => true, ":list" => "list", "v-if" => "!list.preset && list.id" } - %button.board-delete.has-tooltip.float-right{ type: "button", title: _("Delete list"), "aria-label" => _("Delete list"), data: { placement: "bottom" }, "@click.stop" => "deleteBoard" } + %button.board-delete.p-0.border-0.has-tooltip.float-right{ type: "button", title: _("Delete list"), ":class": "{ 'd-none': !list.isExpanded }", "aria-label" => _("Delete list"), data: { placement: "bottom" }, "@click.stop" => "deleteBoard" } = icon("trash") - .issue-count-badge.text-secondary{ "v-if" => 'list.type !== "blank" && list.type !== "promotion"', ":title": "counterTooltip", "v-tooltip": true, data: { placement: "top" } } + .issue-count-badge.text-secondary{ "v-if" => 'list.type !== "blank" && list.type !== "promotion"', ":title": "counterTooltip", ":class": "{ 'd-none': !list.isExpanded }", "v-tooltip": true, data: { placement: "top" } } %span.issue-count-badge-count %icon.mr-1{ name: "issues" } {{ list.issuesSize }} @@ -42,6 +42,7 @@ %button.issue-count-badge-add-button.btn.btn-sm.btn-default.ml-1.has-tooltip.js-no-trigger-collapse{ type: "button", "@click" => "showNewIssueForm", "v-if" => "isNewIssueShown", + ":class": "{ 'd-none': !list.isExpanded }", "aria-label" => _("New issue"), "title" => _("New issue"), data: { placement: "top", container: "body" } } diff --git a/app/views/shared/boards/components/_sidebar.html.haml b/app/views/shared/boards/components/_sidebar.html.haml index 30e51ecc261..b4f75967a67 100644 --- a/app/views/shared/boards/components/_sidebar.html.haml +++ b/app/views/shared/boards/components/_sidebar.html.haml @@ -2,16 +2,16 @@ %transition{ name: "boards-sidebar-slide" } %aside.right-sidebar.right-sidebar-expanded.issue-boards-sidebar{ "v-show" => "showSidebar" } .issuable-sidebar - .block.issuable-sidebar-header + .block.issuable-sidebar-header.position-relative %span.issuable-header-text.hide-collapsed.float-left - %strong + %strong.bold {{ issue.title }} %br/ %span = render_if_exists "shared/boards/components/sidebar/issue_project_path" = precede "#" do {{ issue.iid }} - %a.gutter-toggle.float-right{ role: "button", + %a.gutter-toggle.position-absolute.position-top-0.position-right-0{ role: "button", href: "#", "@click.prevent" => "closeSidebar", "aria-label" => "Toggle sidebar" } diff --git a/app/views/shared/issuable/_label_page_default.html.haml b/app/views/shared/issuable/_label_page_default.html.haml index aa4a5f0e0d3..a0fb5229fc3 100644 --- a/app/views/shared/issuable/_label_page_default.html.haml +++ b/app/views/shared/issuable/_label_page_default.html.haml @@ -11,7 +11,7 @@ = dropdown_title(title) - if show_boards_content .issue-board-dropdown-content - %p + %p.m-0 = content_title = dropdown_filter(filter_placeholder) = dropdown_content diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml index 2bcfcb6fa7c..3d6c5d29d44 100644 --- a/app/views/shared/issuable/_search_bar.html.haml +++ b/app/views/shared/issuable/_search_bar.html.haml @@ -3,11 +3,11 @@ - block_css_class = type != :boards_modal ? 'row-content-block second-block' : '' - user_can_admin_list = board && can?(current_user, :admin_list, board.parent) -.issues-filters - .issues-details-filters.filtered-search-block{ class: block_css_class, "v-pre" => type == :boards_modal } +.issues-filters{ class: ("w-100" if type == :boards_modal) } + .issues-details-filters.filtered-search-block.d-flex{ class: block_css_class, "v-pre" => type == :boards_modal } - if type == :boards = render_if_exists "shared/boards/switcher", board: board - = form_tag page_filter_path, method: :get, class: 'filter-form js-filter-form' do + = form_tag page_filter_path, method: :get, class: 'filter-form js-filter-form w-100' do - if params[:search].present? = hidden_field_tag :search, params[:search] - if @can_bulk_update diff --git a/changelogs/unreleased/10012-move-ee-diff-for-boards-issue-card-inner.yml b/changelogs/unreleased/10012-move-ee-diff-for-boards-issue-card-inner.yml new file mode 100644 index 00000000000..f15375e83f4 --- /dev/null +++ b/changelogs/unreleased/10012-move-ee-diff-for-boards-issue-card-inner.yml @@ -0,0 +1,5 @@ +--- +title: Move ee-specific code from boards/components/issue_card_inner.vue +merge_request: 27394 +author: Roman Rodionov +type: other diff --git a/changelogs/unreleased/10029-env-item.yml b/changelogs/unreleased/10029-env-item.yml deleted file mode 100644 index f4e742d3e17..00000000000 --- a/changelogs/unreleased/10029-env-item.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Removes EE differences for environment_item.vue -merge_request: -author: -type: other diff --git a/changelogs/unreleased/10081-env-table.yml b/changelogs/unreleased/10081-env-table.yml deleted file mode 100644 index b27a1be8cca..00000000000 --- a/changelogs/unreleased/10081-env-table.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Removes EE differences for environments_table.vue -merge_request: -author: -type: other diff --git a/changelogs/unreleased/10735-geo-gitlab-revision-can-return-not-consistent-results.yml b/changelogs/unreleased/10735-geo-gitlab-revision-can-return-not-consistent-results.yml deleted file mode 100644 index 2360295b022..00000000000 --- a/changelogs/unreleased/10735-geo-gitlab-revision-can-return-not-consistent-results.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Use a fixed git abbrev parameter when we fetch a git revision -merge_request: 26707 -author: -type: fixed diff --git a/changelogs/unreleased/11124-update-deployment-service-fails-if-project-is-nil.yml b/changelogs/unreleased/11124-update-deployment-service-fails-if-project-is-nil.yml deleted file mode 100644 index 355743f4cb0..00000000000 --- a/changelogs/unreleased/11124-update-deployment-service-fails-if-project-is-nil.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Always return the deployment in the UpdateDeploymentService#execute method -merge_request: 27322 -author: -type: fixed diff --git a/changelogs/unreleased/13784-validate-variables-for-masking.yml b/changelogs/unreleased/13784-validate-variables-for-masking.yml deleted file mode 100644 index e8e97fac3d2..00000000000 --- a/changelogs/unreleased/13784-validate-variables-for-masking.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add control for masking variable values in runner logs -merge_request: 26751 -author: -type: added diff --git a/changelogs/unreleased/24936-remove-type-from-review-app-name.yml b/changelogs/unreleased/24936-remove-type-from-review-app-name.yml deleted file mode 100644 index 639333264f6..00000000000 --- a/changelogs/unreleased/24936-remove-type-from-review-app-name.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Remove unnecessary folder prefix from environment name -merge_request: 25600 -author: -type: changed diff --git a/changelogs/unreleased/24971-align-emailvalidator-to-validate_email-gem-implementation.yml b/changelogs/unreleased/24971-align-emailvalidator-to-validate_email-gem-implementation.yml deleted file mode 100644 index 04dbc3a1d5a..00000000000 --- a/changelogs/unreleased/24971-align-emailvalidator-to-validate_email-gem-implementation.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Align EmailValidator to validate_email gem implementation -merge_request: 24971 -author: Horatiu Eugen Vlad -type: fixed diff --git a/changelogs/unreleased/25942-remove-fake-repository-path-response.yml b/changelogs/unreleased/25942-remove-fake-repository-path-response.yml deleted file mode 100644 index e1da28ab03c..00000000000 --- a/changelogs/unreleased/25942-remove-fake-repository-path-response.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Remove fake repository_path response -merge_request: 25942 -author: Fabio Papa -type: other diff --git a/changelogs/unreleased/29249-show-download-diff-even-when-merge-request-is-closed.yml b/changelogs/unreleased/29249-show-download-diff-even-when-merge-request-is-closed.yml deleted file mode 100644 index 5942860a20f..00000000000 --- a/changelogs/unreleased/29249-show-download-diff-even-when-merge-request-is-closed.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Show download diff links for closed MRs -merge_request: 26772 -author: -type: changed diff --git a/changelogs/unreleased/38564-cant-leave-subgroup.yml b/changelogs/unreleased/38564-cant-leave-subgroup.yml deleted file mode 100644 index a6397062343..00000000000 --- a/changelogs/unreleased/38564-cant-leave-subgroup.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Allow removing last owner from subgroup if parent group has owners -merge_request: 26718 -author: -type: changed diff --git a/changelogs/unreleased/43263-git-push-option-to-create-mr.yml b/changelogs/unreleased/43263-git-push-option-to-create-mr.yml deleted file mode 100644 index d50c33da162..00000000000 --- a/changelogs/unreleased/43263-git-push-option-to-create-mr.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Allow merge requests to be created via git push options -merge_request: 26752 -author: -type: added diff --git a/changelogs/unreleased/43297-authorized-application-count.yml b/changelogs/unreleased/43297-authorized-application-count.yml deleted file mode 100644 index d22e155fb14..00000000000 --- a/changelogs/unreleased/43297-authorized-application-count.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix authorized application count -merge_request: 25715 -author: moyuru -type: fixed diff --git a/changelogs/unreleased/46787-create-project-label-window-is-cut-off-at-the-bottom.yml b/changelogs/unreleased/46787-create-project-label-window-is-cut-off-at-the-bottom.yml deleted file mode 100644 index dca1d57d14e..00000000000 --- a/changelogs/unreleased/46787-create-project-label-window-is-cut-off-at-the-bottom.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fixed - Create project label window is cut off at the bottom -merge_request: 26049 -author: -type: fixed diff --git a/changelogs/unreleased/47234-composable-auto-devops.yml b/changelogs/unreleased/47234-composable-auto-devops.yml deleted file mode 100644 index 9403c5ae6d3..00000000000 --- a/changelogs/unreleased/47234-composable-auto-devops.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Split Auto-DevOps.gitlab-ci.yml into reusable templates -merge_request: 26520 -author: -type: changed diff --git a/changelogs/unreleased/47771-highlighting-in-diff.yml b/changelogs/unreleased/47771-highlighting-in-diff.yml deleted file mode 100644 index a8e8cbf0174..00000000000 --- a/changelogs/unreleased/47771-highlighting-in-diff.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Enabled text selection highlighting in diffs in Web IDE -merge_request: 26721 -author: Isaac Smith -type: fixed diff --git a/changelogs/unreleased/48090-filter-sensitive-metric-labels.yml b/changelogs/unreleased/48090-filter-sensitive-metric-labels.yml deleted file mode 100644 index e588fa79619..00000000000 --- a/changelogs/unreleased/48090-filter-sensitive-metric-labels.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Remove `path` and `branch` labels from metrics -merge_request: 26744 -author: -type: fixed diff --git a/changelogs/unreleased/48132-display-output-from-pre-receive-scripts.yml b/changelogs/unreleased/48132-display-output-from-pre-receive-scripts.yml deleted file mode 100644 index e06a4d5ee75..00000000000 --- a/changelogs/unreleased/48132-display-output-from-pre-receive-scripts.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: "Allow failed custom hook script errors to safely appear in GitLab UI by filtering error messages by the prefix GL-HOOK-ERR:" -merge_request: 25625 -author: -type: changed diff --git a/changelogs/unreleased/48297-fix-code-selection.yml b/changelogs/unreleased/48297-fix-code-selection.yml deleted file mode 100644 index 14841b00969..00000000000 --- a/changelogs/unreleased/48297-fix-code-selection.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: Resolve Code in other column of side-by-side diff is highlighted when selecting - code on one side -merge_request: 26423 -author: -type: fixed diff --git a/changelogs/unreleased/49856-upgrade-bootstrap-form-gem.yml b/changelogs/unreleased/49856-upgrade-bootstrap-form-gem.yml deleted file mode 100644 index 1dc8d5b4179..00000000000 --- a/changelogs/unreleased/49856-upgrade-bootstrap-form-gem.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Upgrade bootstrap_form Gem -merge_request: 26568 -author: -type: other diff --git a/changelogs/unreleased/49863-ingress-ip-loading-state.yml b/changelogs/unreleased/49863-ingress-ip-loading-state.yml deleted file mode 100644 index 51bb27d3153..00000000000 --- a/changelogs/unreleased/49863-ingress-ip-loading-state.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Show loading spinner while Ingress/Knative IP is being assigned -merge_request: 25912 -author: -type: changed diff --git a/changelogs/unreleased/49910-reopening-a-closed-milestone-from-the-closed-milestones-page-fails2.yml b/changelogs/unreleased/49910-reopening-a-closed-milestone-from-the-closed-milestones-page-fails2.yml deleted file mode 100644 index 68d38cd56c5..00000000000 --- a/changelogs/unreleased/49910-reopening-a-closed-milestone-from-the-closed-milestones-page-fails2.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix bug when reopening milestone from index page -merge_request: -author: -type: fixed diff --git a/changelogs/unreleased/51988-install-group-runner-on-group-cluster.yml b/changelogs/unreleased/51988-install-group-runner-on-group-cluster.yml deleted file mode 100644 index 86f08dd1798..00000000000 --- a/changelogs/unreleased/51988-install-group-runner-on-group-cluster.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Support installing Group runner on group-level cluster -merge_request: 26260 -author: -type: added diff --git a/changelogs/unreleased/52258-labels-with-long-names-overflow-on-metrics-dashboard.yml b/changelogs/unreleased/52258-labels-with-long-names-overflow-on-metrics-dashboard.yml deleted file mode 100644 index 5dd25d0ffc1..00000000000 --- a/changelogs/unreleased/52258-labels-with-long-names-overflow-on-metrics-dashboard.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix long label overflow on metrics dashboard -merge_request: 26775 -author: -type: fixed diff --git a/changelogs/unreleased/52366-improved-group-lists-ui-spinners.yml b/changelogs/unreleased/52366-improved-group-lists-ui-spinners.yml deleted file mode 100644 index ab09272eaf4..00000000000 --- a/changelogs/unreleased/52366-improved-group-lists-ui-spinners.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update spinners in group list component -merge_request: 26572 -author: -type: changed diff --git a/changelogs/unreleased/52447-auto-devops-at-group-level.yml b/changelogs/unreleased/52447-auto-devops-at-group-level.yml deleted file mode 100644 index 0a21c6a2b7b..00000000000 --- a/changelogs/unreleased/52447-auto-devops-at-group-level.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Enable/disable Auto DevOps at the Group level -merge_request: 25533 -author: -type: added diff --git a/changelogs/unreleased/52560-fix-duplicate-tag-system-hooks.yml b/changelogs/unreleased/52560-fix-duplicate-tag-system-hooks.yml deleted file mode 100644 index b8d58d6bd30..00000000000 --- a/changelogs/unreleased/52560-fix-duplicate-tag-system-hooks.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Only execute system hooks once when pushing tags -merge_request: 26888 -author: -type: fixed diff --git a/changelogs/unreleased/53139-hide-tree-single-file.yml b/changelogs/unreleased/53139-hide-tree-single-file.yml deleted file mode 100644 index 17fe957e42e..00000000000 --- a/changelogs/unreleased/53139-hide-tree-single-file.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: collapse file tree by default if the merge request changes only one file -merge_request: -author: Riccardo Padovani <riccardo@rpadovani.com> -type: changed diff --git a/changelogs/unreleased/53198-git-push-option-merge-when-pipeline-succeeds.yml b/changelogs/unreleased/53198-git-push-option-merge-when-pipeline-succeeds.yml deleted file mode 100644 index 6fefd05049c..00000000000 --- a/changelogs/unreleased/53198-git-push-option-merge-when-pipeline-succeeds.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: Allow merge requests to be set to merge when pipeline succeeds via git push - options -merge_request: 26842 -author: -type: added diff --git a/changelogs/unreleased/53210-add-uniq-constraints-on-issues-and-mrs-labels.yml b/changelogs/unreleased/53210-add-uniq-constraints-on-issues-and-mrs-labels.yml deleted file mode 100644 index f9cd8716b92..00000000000 --- a/changelogs/unreleased/53210-add-uniq-constraints-on-issues-and-mrs-labels.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: add a uniq constraints on issues and mrs labels -merge_request: 25435 -author: Antoine Huret -type: fixed diff --git a/changelogs/unreleased/53459-quick-action-adds-multiple-labels-to-issue-if-middle-words-overlap-with-existing-label.yml b/changelogs/unreleased/53459-quick-action-adds-multiple-labels-to-issue-if-middle-words-overlap-with-existing-label.yml deleted file mode 100644 index 30d8c0e95d7..00000000000 --- a/changelogs/unreleased/53459-quick-action-adds-multiple-labels-to-issue-if-middle-words-overlap-with-existing-label.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix quick actions add label name middle word overlaps -merge_request: 26602 -author: Jacopo Beschi @jacopo-beschi -type: fixed diff --git a/changelogs/unreleased/54417-graphql-type-authorization.yml b/changelogs/unreleased/54417-graphql-type-authorization.yml deleted file mode 100644 index 528b58a858a..00000000000 --- a/changelogs/unreleased/54417-graphql-type-authorization.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: GraphQL Types can be made to always authorize access to resources of that Type -merge_request: 25724 -author: -type: added diff --git a/changelogs/unreleased/54506-show-error-when-namespace-svc-missing.yml b/changelogs/unreleased/54506-show-error-when-namespace-svc-missing.yml deleted file mode 100644 index 3e3784d5413..00000000000 --- a/changelogs/unreleased/54506-show-error-when-namespace-svc-missing.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Show error when namespace/svc account missing -merge_request: 26362 -author: -type: added diff --git a/changelogs/unreleased/54670-external-diffs-when-outdated.yml b/changelogs/unreleased/54670-external-diffs-when-outdated.yml deleted file mode 100644 index 2a0b9e75cb4..00000000000 --- a/changelogs/unreleased/54670-external-diffs-when-outdated.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: 'Allow external diffs to be used conditionally' -merge_request: 25432 -author: -type: added diff --git a/changelogs/unreleased/54916-extended-tooltip-for-merge-request-links.yml b/changelogs/unreleased/54916-extended-tooltip-for-merge-request-links.yml deleted file mode 100644 index 7fd0bcd1c00..00000000000 --- a/changelogs/unreleased/54916-extended-tooltip-for-merge-request-links.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add extended merge request tooltip -merge_request: !25221 -author: -type: added diff --git a/changelogs/unreleased/55268-exclude-system-notes-from-commits-in-mr.yml b/changelogs/unreleased/55268-exclude-system-notes-from-commits-in-mr.yml deleted file mode 100644 index 7af4739136b..00000000000 --- a/changelogs/unreleased/55268-exclude-system-notes-from-commits-in-mr.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Exclude system notes from commits in merge request discussions -merge_request: 26396 -author: -type: fixed diff --git a/changelogs/unreleased/55964-fix-email-encoding.yml b/changelogs/unreleased/55964-fix-email-encoding.yml deleted file mode 100644 index 2195a853702..00000000000 --- a/changelogs/unreleased/55964-fix-email-encoding.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix notfication emails having wrong encoding -merge_request: 26931 -author: -type: fixed diff --git a/changelogs/unreleased/55980-remove-add-issue-on-blank-list.yml b/changelogs/unreleased/55980-remove-add-issue-on-blank-list.yml deleted file mode 100644 index 4c16b635297..00000000000 --- a/changelogs/unreleased/55980-remove-add-issue-on-blank-list.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Remove non-functional add issue button on welcome list -merge_request: !26742 -author: -type: fixed diff --git a/changelogs/unreleased/56015-remove-remote-timeout.yml b/changelogs/unreleased/56015-remove-remote-timeout.yml deleted file mode 100644 index 9b40ada5291..00000000000 --- a/changelogs/unreleased/56015-remove-remote-timeout.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix removing remote mirror failure which leaves unnecessary refs behind -merge_request: 26213 -author: -type: fixed diff --git a/changelogs/unreleased/56089-merge-gitlab-keys.yml b/changelogs/unreleased/56089-merge-gitlab-keys.yml deleted file mode 100644 index 5e2cafd3254..00000000000 --- a/changelogs/unreleased/56089-merge-gitlab-keys.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Merge the gitlab-shell "gitlab-keys" functionality into GitLab CE -merge_request: 25598 -author: -type: other diff --git a/changelogs/unreleased/56762-fix-commit-swipe-view-26968.yml b/changelogs/unreleased/56762-fix-commit-swipe-view-26968.yml deleted file mode 100644 index 18bd51711d9..00000000000 --- a/changelogs/unreleased/56762-fix-commit-swipe-view-26968.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: "Fix image diff swipe view on commit and compare pages" -merge_request: 26968 -author: ftab -type: fixed
\ No newline at end of file diff --git a/changelogs/unreleased/56833-project-improve-empty-repository-state-ui-fe.yml b/changelogs/unreleased/56833-project-improve-empty-repository-state-ui-fe.yml deleted file mode 100644 index 19cf3d69db1..00000000000 --- a/changelogs/unreleased/56833-project-improve-empty-repository-state-ui-fe.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: 'Project: Improve empty repository state UI' -merge_request: 26024 -author: -type: other diff --git a/changelogs/unreleased/56864-reopen-locked-mr.yml b/changelogs/unreleased/56864-reopen-locked-mr.yml deleted file mode 100644 index d1d71531ac8..00000000000 --- a/changelogs/unreleased/56864-reopen-locked-mr.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Disallow reopening of a locked merge request -merge_request: 24882 -author: Jan Beckmann -type: fixed diff --git a/changelogs/unreleased/56954-improve-knative-after-installing-tiller.yml b/changelogs/unreleased/56954-improve-knative-after-installing-tiller.yml deleted file mode 100644 index b9fb27c3218..00000000000 --- a/changelogs/unreleased/56954-improve-knative-after-installing-tiller.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Improve the Knative installation on Clusters -merge_request: 26339 -author: -type: added diff --git a/changelogs/unreleased/57115-just-in-time-k8s-resource-creation.yml b/changelogs/unreleased/57115-just-in-time-k8s-resource-creation.yml deleted file mode 100644 index 2141c75ec72..00000000000 --- a/changelogs/unreleased/57115-just-in-time-k8s-resource-creation.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Create Kubernetes resources for projects when their deployment jobs run. -merge_request: 25586 -author: -type: changed diff --git a/changelogs/unreleased/57131-external_auth_to_core.yml b/changelogs/unreleased/57131-external_auth_to_core.yml deleted file mode 100644 index aacd3916c82..00000000000 --- a/changelogs/unreleased/57131-external_auth_to_core.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Move "Authorize project access with external service" to Core -merge_request: 26823 -author: -type: changed diff --git a/changelogs/unreleased/57319-hide-kubernetes-cluster-warning-if-project-has-cluster-related.yml b/changelogs/unreleased/57319-hide-kubernetes-cluster-warning-if-project-has-cluster-related.yml deleted file mode 100644 index a6953a68a76..00000000000 --- a/changelogs/unreleased/57319-hide-kubernetes-cluster-warning-if-project-has-cluster-related.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Resolve "Hide Kubernetes cluster warning if project has cluster related" -merge_request: 26749 -author: -type: fixed diff --git a/changelogs/unreleased/57357-automate-base-domain-help-text.yml b/changelogs/unreleased/57357-automate-base-domain-help-text.yml deleted file mode 100644 index fa1831b66ea..00000000000 --- a/changelogs/unreleased/57357-automate-base-domain-help-text.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Automate base domain help text on Clusters page -merge_request: 26124 -author: -type: changed diff --git a/changelogs/unreleased/57364-improve-diff-nav-header.yml b/changelogs/unreleased/57364-improve-diff-nav-header.yml deleted file mode 100644 index 95d119b949c..00000000000 --- a/changelogs/unreleased/57364-improve-diff-nav-header.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Make stylistic improvements to diff nav header -merge_request: 26557 -author: -type: fixed diff --git a/changelogs/unreleased/57409-loading-button-transition.yml b/changelogs/unreleased/57409-loading-button-transition.yml deleted file mode 100644 index 3cf169d79de..00000000000 --- a/changelogs/unreleased/57409-loading-button-transition.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Prevent fade out transition on loading-button component. -merge_request: 26428 -author: -type: fixed diff --git a/changelogs/unreleased/57482-shortcut-to-create-merge-request-from-web-ide.yml b/changelogs/unreleased/57482-shortcut-to-create-merge-request-from-web-ide.yml deleted file mode 100644 index c188d59fe94..00000000000 --- a/changelogs/unreleased/57482-shortcut-to-create-merge-request-from-web-ide.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Create a shortcut for a new MR in the Web IDE -merge_request: 26792 -author: -type: added diff --git a/changelogs/unreleased/57493-add-limit-to-user-name.yml b/changelogs/unreleased/57493-add-limit-to-user-name.yml deleted file mode 100644 index e6c78572d23..00000000000 --- a/changelogs/unreleased/57493-add-limit-to-user-name.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Set user.name limit to 128 characters -merge_request: 26146 -author: -type: changed diff --git a/changelogs/unreleased/57540-filename-trailing-space.yml b/changelogs/unreleased/57540-filename-trailing-space.yml deleted file mode 100644 index db85fb350db..00000000000 --- a/changelogs/unreleased/57540-filename-trailing-space.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Implemented whitespace-trimming for file names in Web IDE -merge_request: 26270 -author: -type: fixed diff --git a/changelogs/unreleased/57602-create-cluster-validations.yml b/changelogs/unreleased/57602-create-cluster-validations.yml deleted file mode 100644 index 35349c1e9f4..00000000000 --- a/changelogs/unreleased/57602-create-cluster-validations.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Display cluster form validation error messages inline -merge_request: 26502 -author: -type: changed diff --git a/changelogs/unreleased/57648-make-emoji-picker-full-width-on-mobile.yml b/changelogs/unreleased/57648-make-emoji-picker-full-width-on-mobile.yml deleted file mode 100644 index d92fd2a762e..00000000000 --- a/changelogs/unreleased/57648-make-emoji-picker-full-width-on-mobile.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Makes emoji picker full width on mobile. -merge_request: 25883 -author: Jacopo Beschi @jacopo-beschi -type: fixed diff --git a/changelogs/unreleased/57655-fix-markdown-tables-border.yml b/changelogs/unreleased/57655-fix-markdown-tables-border.yml deleted file mode 100644 index 6a8ba8c4353..00000000000 --- a/changelogs/unreleased/57655-fix-markdown-tables-border.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix markdown table header and table content borders -merge_request: 25666 -author: -type: fixed diff --git a/changelogs/unreleased/57668-create-file-from-url.yml b/changelogs/unreleased/57668-create-file-from-url.yml deleted file mode 100644 index b6033fa24ca..00000000000 --- a/changelogs/unreleased/57668-create-file-from-url.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Implemented support for creation of new files from URL in Web IDE -merge_request: 26622 -author: -type: added diff --git a/changelogs/unreleased/57669-fix-bug-clicking-file-header-refreshes-page.yml b/changelogs/unreleased/57669-fix-bug-clicking-file-header-refreshes-page.yml deleted file mode 100644 index c6161870096..00000000000 --- a/changelogs/unreleased/57669-fix-bug-clicking-file-header-refreshes-page.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: Scroll to diff file content when clicking on file header name and it is not - a link to other page -merge_request: !26422 -author: -type: fixed diff --git a/changelogs/unreleased/57894-buttons-on-group-page-are-misaligned.yml b/changelogs/unreleased/57894-buttons-on-group-page-are-misaligned.yml deleted file mode 100644 index ca0f529df6c..00000000000 --- a/changelogs/unreleased/57894-buttons-on-group-page-are-misaligned.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix misalignment of group overview page buttons -merge_request: 26292 -author: -type: fixed diff --git a/changelogs/unreleased/57984-store-branch-name.yml b/changelogs/unreleased/57984-store-branch-name.yml deleted file mode 100644 index 26dfdb7a5d6..00000000000 --- a/changelogs/unreleased/57984-store-branch-name.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Resolves Branch name is lost if I change commit mode in Web IDE -merge_request: 26180 -author: -type: fixed diff --git a/changelogs/unreleased/58208-explicitly-set-masterauth.yml b/changelogs/unreleased/58208-explicitly-set-masterauth.yml deleted file mode 100644 index e3512d11113..00000000000 --- a/changelogs/unreleased/58208-explicitly-set-masterauth.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: Explicitly set master_auth setting to enable basic auth and client certificate - for new GKE clusters -merge_request: 26018 -author: -type: other diff --git a/changelogs/unreleased/58293-extract-discussion-actions.yml b/changelogs/unreleased/58293-extract-discussion-actions.yml new file mode 100644 index 00000000000..2ca4716a6de --- /dev/null +++ b/changelogs/unreleased/58293-extract-discussion-actions.yml @@ -0,0 +1,5 @@ +--- +title: Extract DiscussionActions component from NoteableDiscussion +merge_request: 27227 +author: +type: other diff --git a/changelogs/unreleased/58375-api-controller.yml b/changelogs/unreleased/58375-api-controller.yml deleted file mode 100644 index 60f21b37ae7..00000000000 --- a/changelogs/unreleased/58375-api-controller.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add a Prometheus API per environment -merge_request: 26841 -author: -type: added diff --git a/changelogs/unreleased/58375-reactive-caching-changes.yml b/changelogs/unreleased/58375-reactive-caching-changes.yml deleted file mode 100644 index cf73736b8ef..00000000000 --- a/changelogs/unreleased/58375-reactive-caching-changes.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Allow reactive caching to be used in services -merge_request: 26839 -author: -type: added diff --git a/changelogs/unreleased/58405-basic-limiting-complexity-of-graphql-queries.yml b/changelogs/unreleased/58405-basic-limiting-complexity-of-graphql-queries.yml deleted file mode 100644 index 058a120b500..00000000000 --- a/changelogs/unreleased/58405-basic-limiting-complexity-of-graphql-queries.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add initial complexity limits to GraphQL queries -merge_request: 26629 -author: -type: performance diff --git a/changelogs/unreleased/58410-change-pixel-size-of-instance-header-footer-message-to-16px.yml b/changelogs/unreleased/58410-change-pixel-size-of-instance-header-footer-message-to-16px.yml deleted file mode 100644 index 3e494847e75..00000000000 --- a/changelogs/unreleased/58410-change-pixel-size-of-instance-header-footer-message-to-16px.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Reduce height of instance system header and footer -merge_request: 25752 -author: -type: changed diff --git a/changelogs/unreleased/58482-update-airminc-clair-local-scan-to-2-0-6.yml b/changelogs/unreleased/58482-update-airminc-clair-local-scan-to-2-0-6.yml deleted file mode 100644 index be9c38aba1e..00000000000 --- a/changelogs/unreleased/58482-update-airminc-clair-local-scan-to-2-0-6.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update clair-local-scan to 2.0.6 -merge_request: 25743 -author: Takuya Noguchi -type: added diff --git a/changelogs/unreleased/58717-checkbox-cannot-be-checked-if-a-blockquote-is-above.yml b/changelogs/unreleased/58717-checkbox-cannot-be-checked-if-a-blockquote-is-above.yml deleted file mode 100644 index 9f5881966c7..00000000000 --- a/changelogs/unreleased/58717-checkbox-cannot-be-checked-if-a-blockquote-is-above.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Allow task lists that follow a blockquote to work correctly -merge_request: 26937 -author: -type: fixed diff --git a/changelogs/unreleased/58739-hashed-storage-prevent-a-migration-and-rollback-running-at-the-same-time.yml b/changelogs/unreleased/58739-hashed-storage-prevent-a-migration-and-rollback-running-at-the-same-time.yml deleted file mode 100644 index 765a991bb6a..00000000000 --- a/changelogs/unreleased/58739-hashed-storage-prevent-a-migration-and-rollback-running-at-the-same-time.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: 'Hashed Storage: Prevent a migration and rollback running at the same time' -merge_request: 25976 -author: -type: changed diff --git a/changelogs/unreleased/58751-fix-project-name-members-page.yml b/changelogs/unreleased/58751-fix-project-name-members-page.yml deleted file mode 100644 index a295afc5c48..00000000000 --- a/changelogs/unreleased/58751-fix-project-name-members-page.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: "Fix unwanted character replacement on project members page caused by usage of sanitize function" -merge_request: 25946 -author: Elias Werberich -type: fixed diff --git a/changelogs/unreleased/58781-silent-progress-in-auto-devops.yml b/changelogs/unreleased/58781-silent-progress-in-auto-devops.yml deleted file mode 100644 index e45db8eafc3..00000000000 --- a/changelogs/unreleased/58781-silent-progress-in-auto-devops.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Use curl silent/show-error options on Auto DevOps -merge_request: 25954 -author: Takuya Noguchi -type: other diff --git a/changelogs/unreleased/58789-some-system-notes-on-issuable-are-folded-on-mobile.yml b/changelogs/unreleased/58789-some-system-notes-on-issuable-are-folded-on-mobile.yml deleted file mode 100644 index ebfb7aeaa1f..00000000000 --- a/changelogs/unreleased/58789-some-system-notes-on-issuable-are-folded-on-mobile.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Keep inline as much as possible in system notes on issuable -merge_request: 25968 -author: Takuya Noguchi -type: fixed diff --git a/changelogs/unreleased/58793-fix-nav-links-archived-project.yml b/changelogs/unreleased/58793-fix-nav-links-archived-project.yml deleted file mode 100644 index a8250804c34..00000000000 --- a/changelogs/unreleased/58793-fix-nav-links-archived-project.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: "Disable inaccessible navigation links upon archiving a project" -merge_request: 26020 -author: Elias Werberich -type: fixed diff --git a/changelogs/unreleased/58797-broken-ui-on-a-closed-merge-request-from-a-deleted-source-project.yml b/changelogs/unreleased/58797-broken-ui-on-a-closed-merge-request-from-a-deleted-source-project.yml deleted file mode 100644 index e30f48ed1a8..00000000000 --- a/changelogs/unreleased/58797-broken-ui-on-a-closed-merge-request-from-a-deleted-source-project.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix UI for closed MR when source project is removed -merge_request: 25967 -author: Takuya Noguchi -type: fixed diff --git a/changelogs/unreleased/58805-allow-incomplete-commit-data-to-be-fetched-from-collection.yml b/changelogs/unreleased/58805-allow-incomplete-commit-data-to-be-fetched-from-collection.yml deleted file mode 100644 index 4377ebfdbdf..00000000000 --- a/changelogs/unreleased/58805-allow-incomplete-commit-data-to-be-fetched-from-collection.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix merge commits being used as default squash commit messages -merge_request: 26445 -author: -type: fixed diff --git a/changelogs/unreleased/58835-button-run-pipeline.yml b/changelogs/unreleased/58835-button-run-pipeline.yml deleted file mode 100644 index 39407a60780..00000000000 --- a/changelogs/unreleased/58835-button-run-pipeline.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Changed button label at /pipelines/new -merge_request: 26893 -author: antfobe,leonardofl -type: other diff --git a/changelogs/unreleased/58839-automatically-set-prometheus-step-interval.yml b/changelogs/unreleased/58839-automatically-set-prometheus-step-interval.yml deleted file mode 100644 index 2c6edf45ae2..00000000000 --- a/changelogs/unreleased/58839-automatically-set-prometheus-step-interval.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Automatically set Prometheus step interval -merge_request: 26441 -author: -type: changed diff --git a/changelogs/unreleased/58883-fix-fetching-comments.yml b/changelogs/unreleased/58883-fix-fetching-comments.yml deleted file mode 100644 index 14c0f1687f2..00000000000 --- a/changelogs/unreleased/58883-fix-fetching-comments.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix error shown when loading links to specific comments -merge_request: 26092 -author: -type: fixed diff --git a/changelogs/unreleased/58889-spinners-are-active-prematurely-in-bitbucket-cloud-import.yml b/changelogs/unreleased/58889-spinners-are-active-prematurely-in-bitbucket-cloud-import.yml deleted file mode 100644 index ec357d9a832..00000000000 --- a/changelogs/unreleased/58889-spinners-are-active-prematurely-in-bitbucket-cloud-import.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix continuous bitbucket import loading spinner -merge_request: 26175 -author: -type: fixed diff --git a/changelogs/unreleased/58933-broken-ui-on-commits-on-mobile.yml b/changelogs/unreleased/58933-broken-ui-on-commits-on-mobile.yml deleted file mode 100644 index ca9f9dd21c9..00000000000 --- a/changelogs/unreleased/58933-broken-ui-on-commits-on-mobile.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix UI layout on Commits on mobile -merge_request: 26133 -author: Takuya Noguchi -type: fixed diff --git a/changelogs/unreleased/58971-sentry-api-keyerror.yml b/changelogs/unreleased/58971-sentry-api-keyerror.yml deleted file mode 100644 index 0f195c4b4f7..00000000000 --- a/changelogs/unreleased/58971-sentry-api-keyerror.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Handle missing keys in sentry api response -merge_request: 26264 -author: -type: fixed diff --git a/changelogs/unreleased/58981-migrate-clusters-tests-to-jest.yml b/changelogs/unreleased/58981-migrate-clusters-tests-to-jest.yml deleted file mode 100644 index 3df13dbb960..00000000000 --- a/changelogs/unreleased/58981-migrate-clusters-tests-to-jest.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Migrate clusters tests to jest -merge_request: 27013 -author: -type: other diff --git a/changelogs/unreleased/59057-buttons-on-top-from-a-user-profile-page-on-mobile.yml b/changelogs/unreleased/59057-buttons-on-top-from-a-user-profile-page-on-mobile.yml deleted file mode 100644 index febbbce2139..00000000000 --- a/changelogs/unreleased/59057-buttons-on-top-from-a-user-profile-page-on-mobile.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Improve mobile UI on User Profile page -merge_request: 26240 -author: Takuya Noguchi -type: other diff --git a/changelogs/unreleased/59062-update-gitlab-markup-python-3.yml b/changelogs/unreleased/59062-update-gitlab-markup-python-3.yml deleted file mode 100644 index 265a7e36841..00000000000 --- a/changelogs/unreleased/59062-update-gitlab-markup-python-3.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update gitlab-markup to 1.7.0 which requies python3 -merge_request: 26246 -author: -type: changed diff --git a/changelogs/unreleased/59079-fix-jupyter-render-loop.yml b/changelogs/unreleased/59079-fix-jupyter-render-loop.yml deleted file mode 100644 index 29264b33dfa..00000000000 --- a/changelogs/unreleased/59079-fix-jupyter-render-loop.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix jupyter rendering bug that ended in an infinite loop -merge_request: 26656 -author: ROSPARS Benoit -type: fixed diff --git a/changelogs/unreleased/59117-inconsistent-hover-behavior-on-navbar-items.yml b/changelogs/unreleased/59117-inconsistent-hover-behavior-on-navbar-items.yml deleted file mode 100644 index eb9dcef4a89..00000000000 --- a/changelogs/unreleased/59117-inconsistent-hover-behavior-on-navbar-items.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix hover animation consistency in top navbar items -merge_request: 26345 -author: -type: fixed diff --git a/changelogs/unreleased/59131-set-the-size-of-instance-system-message-text-12px.yml b/changelogs/unreleased/59131-set-the-size-of-instance-system-message-text-12px.yml deleted file mode 100644 index 688190f4458..00000000000 --- a/changelogs/unreleased/59131-set-the-size-of-instance-system-message-text-12px.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update system message banner font size to 12px -merge_request: 26293 -author: -type: changed diff --git a/changelogs/unreleased/59189-long-names-in-project-path-namespace-dropdown-breaks-past-container.yml b/changelogs/unreleased/59189-long-names-in-project-path-namespace-dropdown-breaks-past-container.yml deleted file mode 100644 index bed7fcf2651..00000000000 --- a/changelogs/unreleased/59189-long-names-in-project-path-namespace-dropdown-breaks-past-container.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Prevent namespace dropdown in new project form from exceeding container -merge_request: 26343 -author: -type: fixed diff --git a/changelogs/unreleased/59273-update-fugit.yml b/changelogs/unreleased/59273-update-fugit.yml deleted file mode 100644 index 3a1c64d87ef..00000000000 --- a/changelogs/unreleased/59273-update-fugit.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update fugit which fixes a potential infinite loop -merge_request: 26579 -author: -type: fixed diff --git a/changelogs/unreleased/59296-add-filter-by-title-milestones-api.yml b/changelogs/unreleased/59296-add-filter-by-title-milestones-api.yml deleted file mode 100644 index 440b24a548c..00000000000 --- a/changelogs/unreleased/59296-add-filter-by-title-milestones-api.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add select by title to milestones API -merge_request: 26573 -author: -type: added diff --git a/changelogs/unreleased/59324-queries-which-return-multiple-series-are-not-working-correctly.yml b/changelogs/unreleased/59324-queries-which-return-multiple-series-are-not-working-correctly.yml deleted file mode 100644 index 9ab8d2b8596..00000000000 --- a/changelogs/unreleased/59324-queries-which-return-multiple-series-are-not-working-correctly.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix multiple series queries on metrics dashboard -merge_request: 26514 -author: -type: fixed diff --git a/changelogs/unreleased/59352-fix-mr-discussion-expansion.yml b/changelogs/unreleased/59352-fix-mr-discussion-expansion.yml deleted file mode 100644 index ab9ad53835c..00000000000 --- a/changelogs/unreleased/59352-fix-mr-discussion-expansion.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Expand resolved discussion when linking to a comment in the discussion -merge_request: 26483 -author: -type: fixed diff --git a/changelogs/unreleased/59441-add-base-domain-to-cluster-api.yml b/changelogs/unreleased/59441-add-base-domain-to-cluster-api.yml deleted file mode 100644 index cb5cbba4e92..00000000000 --- a/changelogs/unreleased/59441-add-base-domain-to-cluster-api.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add cluster domain to Project Cluster API -merge_request: 26735 -author: -type: other diff --git a/changelogs/unreleased/59502-fix-breadcrumb-artifacts.yml b/changelogs/unreleased/59502-fix-breadcrumb-artifacts.yml deleted file mode 100644 index da65c3bc870..00000000000 --- a/changelogs/unreleased/59502-fix-breadcrumb-artifacts.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fixes job link in artifacts page breadcrumb -merge_request: 26592 -author: -type: fixed diff --git a/changelogs/unreleased/59546-fix-error-handling-for-missing-domain.yml b/changelogs/unreleased/59546-fix-error-handling-for-missing-domain.yml deleted file mode 100644 index 8f0ce5d57c5..00000000000 --- a/changelogs/unreleased/59546-fix-error-handling-for-missing-domain.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix Auto DevOps missing domain error handling -merge_request: 26627 -author: -type: fixed diff --git a/changelogs/unreleased/59621-order-labels-alphabetically-in-issue-boards.yml b/changelogs/unreleased/59621-order-labels-alphabetically-in-issue-boards.yml deleted file mode 100644 index 8b82d757303..00000000000 --- a/changelogs/unreleased/59621-order-labels-alphabetically-in-issue-boards.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Order labels alphabetically in issue boards -merge_request: 26927 -author: -type: changed diff --git a/changelogs/unreleased/60006-add-touch-events-to-image-diff-26971.yml b/changelogs/unreleased/60006-add-touch-events-to-image-diff-26971.yml deleted file mode 100644 index bfea3ac52af..00000000000 --- a/changelogs/unreleased/60006-add-touch-events-to-image-diff-26971.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: "Make touch events work on image diff swipe view and onion skin" -merge_request: 26971 -author: ftab -type: added diff --git a/changelogs/unreleased/60068-avoid-null-domain-help-text.yml b/changelogs/unreleased/60068-avoid-null-domain-help-text.yml deleted file mode 100644 index 5305b8584a8..00000000000 --- a/changelogs/unreleased/60068-avoid-null-domain-help-text.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Do not display Ingress IP help text when there isn’t an Ingress IP assigned -merge_request: 27057 -author: -type: fixed diff --git a/changelogs/unreleased/60116-fix-button-wrapping.yml b/changelogs/unreleased/60116-fix-button-wrapping.yml deleted file mode 100644 index d6df920b51d..00000000000 --- a/changelogs/unreleased/60116-fix-button-wrapping.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add to white-space nowrap to all buttons -merge_request: 27069 -author: -type: fixed diff --git a/changelogs/unreleased/60149-nameerror-uninitialized-constant-sentry-client-sentryerror.yml b/changelogs/unreleased/60149-nameerror-uninitialized-constant-sentry-client-sentryerror.yml deleted file mode 100644 index 8c3a47cf62c..00000000000 --- a/changelogs/unreleased/60149-nameerror-uninitialized-constant-sentry-client-sentryerror.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Handle possible HTTP exception for Sentry client -merge_request: 27080 -author: -type: fixed diff --git a/changelogs/unreleased/60241-merge-request-popover-doesn-t-go-away-on-mouse-leave.yml b/changelogs/unreleased/60241-merge-request-popover-doesn-t-go-away-on-mouse-leave.yml deleted file mode 100644 index ce942777dca..00000000000 --- a/changelogs/unreleased/60241-merge-request-popover-doesn-t-go-away-on-mouse-leave.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix bug where MR popover doesn't go away on mouse leave -merge_request: -author: -type: fixed diff --git a/changelogs/unreleased/60304-long-file-names-in-mr-diffs-cause-horizontal-scrolling.yml b/changelogs/unreleased/60304-long-file-names-in-mr-diffs-cause-horizontal-scrolling.yml deleted file mode 100644 index ec5e9e4703b..00000000000 --- a/changelogs/unreleased/60304-long-file-names-in-mr-diffs-cause-horizontal-scrolling.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix long file header names bug in diffs -merge_request: 27233 -author: -type: fixed diff --git a/changelogs/unreleased/MaxWinterstein-master-patch-23232.yml b/changelogs/unreleased/MaxWinterstein-master-patch-23232.yml deleted file mode 100644 index 8fb9f1057fe..00000000000 --- a/changelogs/unreleased/MaxWinterstein-master-patch-23232.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Unify behaviour of 'Copy commit SHA to clipboard' to use full commit SHA. -merge_request: 25829 -author: Max Winterstein -type: changed diff --git a/changelogs/unreleased/_acet-related-mrs-widget-rewrite.yml b/changelogs/unreleased/_acet-related-mrs-widget-rewrite.yml deleted file mode 100644 index b773eb2720c..00000000000 --- a/changelogs/unreleased/_acet-related-mrs-widget-rewrite.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Rewrite related MRs widget with Vue -merge_request: 27027 -author: -type: other diff --git a/changelogs/unreleased/add-runner-access-level-registration.yml b/changelogs/unreleased/add-runner-access-level-registration.yml new file mode 100644 index 00000000000..7ae95025abb --- /dev/null +++ b/changelogs/unreleased/add-runner-access-level-registration.yml @@ -0,0 +1,5 @@ +--- +title: Add option to set access_level of runners upon registration +merge_request: 27490 +author: Zelin L +type: added diff --git a/changelogs/unreleased/add_backtrace_to_kubernetes_log.yml b/changelogs/unreleased/add_backtrace_to_kubernetes_log.yml deleted file mode 100644 index 26b8ac4b1ef..00000000000 --- a/changelogs/unreleased/add_backtrace_to_kubernetes_log.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Show error backtrace when logging errors to kubernetes.log -merge_request: 25726 -author: -type: other diff --git a/changelogs/unreleased/allow-filtering-labels-by-a-single-character.yml b/changelogs/unreleased/allow-filtering-labels-by-a-single-character.yml deleted file mode 100644 index 31165bbadb7..00000000000 --- a/changelogs/unreleased/allow-filtering-labels-by-a-single-character.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Allow filtering labels list by one or two characters -merge_request: 26012 -author: -type: changed diff --git a/changelogs/unreleased/allow-ref-name-caching-projects-controller.yml b/changelogs/unreleased/allow-ref-name-caching-projects-controller.yml deleted file mode 100644 index 61236b9b82b..00000000000 --- a/changelogs/unreleased/allow-ref-name-caching-projects-controller.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Enable FindCommit caching for project and commits pages -merge_request: 27048 -author: -type: performance diff --git a/changelogs/unreleased/an-use-labkit.yml b/changelogs/unreleased/an-use-labkit.yml new file mode 100644 index 00000000000..ab293c15787 --- /dev/null +++ b/changelogs/unreleased/an-use-labkit.yml @@ -0,0 +1,5 @@ +--- +title: Migrate correlation and tracing code to LabKit +merge_request: 25379 +author: +type: other diff --git a/changelogs/unreleased/avoid_es_loading_project_ci_status.yml b/changelogs/unreleased/avoid_es_loading_project_ci_status.yml deleted file mode 100644 index 514909c730d..00000000000 --- a/changelogs/unreleased/avoid_es_loading_project_ci_status.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Avoid loading pipeline status in project search -merge_request: 26342 -author: -type: performance diff --git a/changelogs/unreleased/ce-10725-restructure-project-merge-request-settings-page.yml b/changelogs/unreleased/ce-10725-restructure-project-merge-request-settings-page.yml new file mode 100644 index 00000000000..7aa9204fe4e --- /dev/null +++ b/changelogs/unreleased/ce-10725-restructure-project-merge-request-settings-page.yml @@ -0,0 +1,5 @@ +--- +title: Reorganize project merge request settings +merge_request: 26834 +author: +type: changed diff --git a/changelogs/unreleased/ce-56153-error-tracking-counts.yml b/changelogs/unreleased/ce-56153-error-tracking-counts.yml deleted file mode 100644 index fc3d8c01d7f..00000000000 --- a/changelogs/unreleased/ce-56153-error-tracking-counts.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add usage counts for error tracking feature -merge_request: 25472 -author: -type: added diff --git a/changelogs/unreleased/ce-proj-settings-ok-avatar-only.yml b/changelogs/unreleased/ce-proj-settings-ok-avatar-only.yml deleted file mode 100644 index 10475824a75..00000000000 --- a/changelogs/unreleased/ce-proj-settings-ok-avatar-only.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Change project avatar remove button to a link -merge_request: 26589 -author: -type: other diff --git a/changelogs/unreleased/ce-proj-settings-ok-mr-settings-only.yml b/changelogs/unreleased/ce-proj-settings-ok-mr-settings-only.yml deleted file mode 100644 index 4bbbc706e62..00000000000 --- a/changelogs/unreleased/ce-proj-settings-ok-mr-settings-only.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Improve project merge request settings -merge_request: 26495 -author: -type: other diff --git a/changelogs/unreleased/check-mergeability-in-merge-to-ref-service.yml b/changelogs/unreleased/check-mergeability-in-merge-to-ref-service.yml deleted file mode 100644 index 9f615bbb54a..00000000000 --- a/changelogs/unreleased/check-mergeability-in-merge-to-ref-service.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Check mergeability in MergeToRefService -merge_request: 26757 -author: -type: changed diff --git a/changelogs/unreleased/create-label-and-list-checkbox.yml b/changelogs/unreleased/create-label-and-list-checkbox.yml deleted file mode 100644 index 330372df1be..00000000000 --- a/changelogs/unreleased/create-label-and-list-checkbox.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: 'Added "Add List" checkbox to create label dropdown to make creation of list optional' -merge_request: 25716 -author: Tucker Chapman -type: fixed diff --git a/changelogs/unreleased/delete-release-when-delete-tag.yml b/changelogs/unreleased/delete-release-when-delete-tag.yml deleted file mode 100644 index 58acd449bf1..00000000000 --- a/changelogs/unreleased/delete-release-when-delete-tag.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Releases will now be automatically deleted when deleting corresponding tag -merge_request: 26530 -author: -type: fixed diff --git a/changelogs/unreleased/deploy-keys-ext.yml b/changelogs/unreleased/deploy-keys-ext.yml deleted file mode 100644 index e1d2fe08425..00000000000 --- a/changelogs/unreleased/deploy-keys-ext.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Externalize admin deploy keys strings -merge_request: -author: -type: other diff --git a/changelogs/unreleased/disallow-guests-to-access-releases.yml b/changelogs/unreleased/disallow-guests-to-access-releases.yml deleted file mode 100644 index f2d518108d2..00000000000 --- a/changelogs/unreleased/disallow-guests-to-access-releases.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Disallow guest users from accessing Releases -merge_request: -author: -type: security diff --git a/changelogs/unreleased/do-not-force-2fa.yml b/changelogs/unreleased/do-not-force-2fa.yml deleted file mode 100644 index f9be40e8f37..00000000000 --- a/changelogs/unreleased/do-not-force-2fa.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: Add link on two-factor authorization settings page to leave group that enforces - two-factor authorization -merge_request: 25731 -author: -type: changed diff --git a/changelogs/unreleased/drop-usage-of-leagcy-artifacts.yml b/changelogs/unreleased/drop-usage-of-leagcy-artifacts.yml deleted file mode 100644 index d99187d8d41..00000000000 --- a/changelogs/unreleased/drop-usage-of-leagcy-artifacts.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Drop legacy artifacts usage as there are no leftovers -merge_request: 24294 -author: -type: performance diff --git a/changelogs/unreleased/duplicate-related-mrs.yml b/changelogs/unreleased/duplicate-related-mrs.yml deleted file mode 100644 index 0f5f6ede9f8..00000000000 --- a/changelogs/unreleased/duplicate-related-mrs.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Remove duplicates from issue related merge requests -merge_request: 27067 -author: -type: fixed diff --git a/changelogs/unreleased/ekigbo-extend-timezone-dropdown.yml b/changelogs/unreleased/ekigbo-extend-timezone-dropdown.yml deleted file mode 100644 index 42bc320a542..00000000000 --- a/changelogs/unreleased/ekigbo-extend-timezone-dropdown.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Extend timezone dropdown -merge_request: 26311 -author: -type: changed diff --git a/changelogs/unreleased/expose-group-id-on-home-panel.yml b/changelogs/unreleased/expose-group-id-on-home-panel.yml deleted file mode 100644 index 1efe15a6e1a..00000000000 --- a/changelogs/unreleased/expose-group-id-on-home-panel.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Expose group id on home panel -merge_request: 25897 -author: Peter Marko -type: added diff --git a/changelogs/unreleased/extend-cte-optimisations-to-projects.yml b/changelogs/unreleased/extend-cte-optimisations-to-projects.yml deleted file mode 100644 index e5407127b2f..00000000000 --- a/changelogs/unreleased/extend-cte-optimisations-to-projects.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Speed up filtering issues in a project when searching -merge_request: -author: -type: performance diff --git a/changelogs/unreleased/feature-gb-serverless-switch-to-gitlabktl.yml b/changelogs/unreleased/feature-gb-serverless-switch-to-gitlabktl.yml deleted file mode 100644 index 81cf5cb810d..00000000000 --- a/changelogs/unreleased/feature-gb-serverless-switch-to-gitlabktl.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Use gitlabktl to build and deploy GitLab Serverless Functions -merge_request: 26926 -author: -type: added diff --git a/changelogs/unreleased/feature-users-search-results.yml b/changelogs/unreleased/feature-users-search-results.yml deleted file mode 100644 index 151d08bce12..00000000000 --- a/changelogs/unreleased/feature-users-search-results.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add users search results to global search -merge_request: 21197 -author: Alexis Reigel -type: added diff --git a/changelogs/unreleased/feature-webide_escaping.yml b/changelogs/unreleased/feature-webide_escaping.yml deleted file mode 100644 index 88fa1bd948e..00000000000 --- a/changelogs/unreleased/feature-webide_escaping.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fixed bug with hashes in urls in WebIDE -merge_request: 54376 -author: Kieran Andrews -type: fixed diff --git a/changelogs/unreleased/filter-merge-requests-by-target-branch.yml b/changelogs/unreleased/filter-merge-requests-by-target-branch.yml deleted file mode 100644 index d0aba631c96..00000000000 --- a/changelogs/unreleased/filter-merge-requests-by-target-branch.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add target branch filter to merge requests search bar -merge_request: 24380 -author: Hiroyuki Sato -type: added diff --git a/changelogs/unreleased/fix-UI-links-to-route-map-info.yml b/changelogs/unreleased/fix-UI-links-to-route-map-info.yml deleted file mode 100644 index bb506507080..00000000000 --- a/changelogs/unreleased/fix-UI-links-to-route-map-info.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix UI anchor links after docs refactor -merge_request: 26890 -author: -type: fixed diff --git a/changelogs/unreleased/fix-container-scanning-on-k8s.yml b/changelogs/unreleased/fix-container-scanning-on-k8s.yml deleted file mode 100644 index f4500370a0b..00000000000 --- a/changelogs/unreleased/fix-container-scanning-on-k8s.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix Container Scanning in Kubernetes Runners -merge_request: 26793 -author: -type: changed diff --git a/changelogs/unreleased/fix-expand-full-file-on-image.yml b/changelogs/unreleased/fix-expand-full-file-on-image.yml deleted file mode 100644 index a88d30cfa38..00000000000 --- a/changelogs/unreleased/fix-expand-full-file-on-image.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fixed expand full file button showing on images -merge_request: -author: -type: fixed diff --git a/changelogs/unreleased/fix-hidden-statistics.yml b/changelogs/unreleased/fix-hidden-statistics.yml deleted file mode 100644 index 4d99bd00136..00000000000 --- a/changelogs/unreleased/fix-hidden-statistics.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Show statistics also when repository is disabled -merge_request: 26509 -author: Peter Marko -type: fixed diff --git a/changelogs/unreleased/fix-ide-web-worker-relative-url.yml b/changelogs/unreleased/fix-ide-web-worker-relative-url.yml deleted file mode 100644 index 2accad68c4e..00000000000 --- a/changelogs/unreleased/fix-ide-web-worker-relative-url.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fixed Web IDE web workers not working with relative URLs -merge_request: -author: -type: fixed diff --git a/changelogs/unreleased/fix-include-ci-yaml.yml b/changelogs/unreleased/fix-include-ci-yaml.yml deleted file mode 100644 index 042413b89aa..00000000000 --- a/changelogs/unreleased/fix-include-ci-yaml.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix single string values for the 'include' keyword validation of gitlab-ci.yml. -merge_request: 26998 -author: Paul Bonaud (@paulrbr) -type: fixed diff --git a/changelogs/unreleased/fix-issues-time-counter.yml b/changelogs/unreleased/fix-issues-time-counter.yml deleted file mode 100644 index 76f17063db5..00000000000 --- a/changelogs/unreleased/fix-issues-time-counter.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Make time counters show 'just now' for everything under one minute -merge_request: 25992 -author: Sergiu Marton -type: changed diff --git a/changelogs/unreleased/fix-merge-request-relations-with-pipeline-on-mwps.yml b/changelogs/unreleased/fix-merge-request-relations-with-pipeline-on-mwps.yml deleted file mode 100644 index 9ccc79109d8..00000000000 --- a/changelogs/unreleased/fix-merge-request-relations-with-pipeline-on-mwps.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix MWPS does not work for merge request pipelines -merge_request: 26906 -author: -type: fixed diff --git a/changelogs/unreleased/fix-new-merge-request-diff-headers-sticky-position.yml b/changelogs/unreleased/fix-new-merge-request-diff-headers-sticky-position.yml deleted file mode 100644 index dadbd5c940f..00000000000 --- a/changelogs/unreleased/fix-new-merge-request-diff-headers-sticky-position.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fixed sticky headers in merge request creation diffs -merge_request: -author: -type: fixed diff --git a/changelogs/unreleased/fix-pipeline-entity.yml b/changelogs/unreleased/fix-pipeline-entity.yml deleted file mode 100644 index b429139402c..00000000000 --- a/changelogs/unreleased/fix-pipeline-entity.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add merge request pipeline flag to pipeline entity -merge_request: 25846 -author: -type: added diff --git a/changelogs/unreleased/fix-review-app-env-url.yml b/changelogs/unreleased/fix-review-app-env-url.yml deleted file mode 100644 index 963cd0c2992..00000000000 --- a/changelogs/unreleased/fix-review-app-env-url.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fixes long review app subdomains -merge_request: 25990 -author: walkafwalka -type: fixed diff --git a/changelogs/unreleased/fix-routes-n-plus-one-in-user-autocomplete.yml b/changelogs/unreleased/fix-routes-n-plus-one-in-user-autocomplete.yml deleted file mode 100644 index ae097e859d9..00000000000 --- a/changelogs/unreleased/fix-routes-n-plus-one-in-user-autocomplete.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix some N+1s in loading routes and counting members for groups in @-autocomplete -merge_request: 26491 -author: -type: performance diff --git a/changelogs/unreleased/fix-transfer-group-possibilities.yml b/changelogs/unreleased/fix-transfer-group-possibilities.yml deleted file mode 100644 index ebefb47b3da..00000000000 --- a/changelogs/unreleased/fix-transfer-group-possibilities.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix group transfer selection possibilities -merge_request: 26123 -author: Peter Marko -type: fixed diff --git a/changelogs/unreleased/fixed-duplicated-large-text-on-diffs.yml b/changelogs/unreleased/fixed-duplicated-large-text-on-diffs.yml deleted file mode 100644 index 770186a64b0..00000000000 --- a/changelogs/unreleased/fixed-duplicated-large-text-on-diffs.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fixed duplicated diff too large error message -merge_request: -author: -type: fixed diff --git a/changelogs/unreleased/fixed-web-ide-merge-request-review.yml b/changelogs/unreleased/fixed-web-ide-merge-request-review.yml deleted file mode 100644 index 2799f5ee38a..00000000000 --- a/changelogs/unreleased/fixed-web-ide-merge-request-review.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fixed Web IDE not loading merge request files -merge_request: -author: -type: fixed diff --git a/changelogs/unreleased/gitaly-version-v1.29.0.yml b/changelogs/unreleased/gitaly-version-v1.29.0.yml deleted file mode 100644 index b6ce14c33a2..00000000000 --- a/changelogs/unreleased/gitaly-version-v1.29.0.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Upgrade to Gitaly v1.29.0 -merge_request: 26406 -author: -type: changed diff --git a/changelogs/unreleased/gitaly-version-v1.32.0.yml b/changelogs/unreleased/gitaly-version-v1.32.0.yml deleted file mode 100644 index 8413f31278e..00000000000 --- a/changelogs/unreleased/gitaly-version-v1.32.0.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Upgrade to Gitaly v1.32.0 -merge_request: 26989 -author: -type: changed diff --git a/changelogs/unreleased/gitaly-version-v1.33.0.yml b/changelogs/unreleased/gitaly-version-v1.33.0.yml deleted file mode 100644 index d21e521a0bb..00000000000 --- a/changelogs/unreleased/gitaly-version-v1.33.0.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Upgrade to Gitaly v1.33.0 -merge_request: 27065 -author: -type: changed diff --git a/changelogs/unreleased/gitlab-issue-54894.yml b/changelogs/unreleased/gitlab-issue-54894.yml new file mode 100644 index 00000000000..513c0163c0e --- /dev/null +++ b/changelogs/unreleased/gitlab-issue-54894.yml @@ -0,0 +1,6 @@ +--- +title: Fix some label links not appearing on group labels page and label title being + a link on project labels page +merge_request: 24060 +author: Tanya Pazitny +type: fixed diff --git a/changelogs/unreleased/graphql-prometheus.yml b/changelogs/unreleased/graphql-prometheus.yml deleted file mode 100644 index 180577f3aec..00000000000 --- a/changelogs/unreleased/graphql-prometheus.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Added prometheus monitoring to GraphQL -merge_request: -author: -type: added diff --git a/changelogs/unreleased/gt-externalize-app-views-projects-pipelines.yml b/changelogs/unreleased/gt-externalize-app-views-projects-pipelines.yml deleted file mode 100644 index 094cd3ab751..00000000000 --- a/changelogs/unreleased/gt-externalize-app-views-projects-pipelines.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Externalize strings from `/app/views/projects/pipelines` -merge_request: 26035 -author: George Tsiolis -type: other diff --git a/changelogs/unreleased/id-51433-sort-wiki-by-date.yml b/changelogs/unreleased/id-51433-sort-wiki-by-date.yml deleted file mode 100644 index 86fcf195fa7..00000000000 --- a/changelogs/unreleased/id-51433-sort-wiki-by-date.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Allow to sort wiki pages by date and title -merge_request: 25365 -author: -type: added diff --git a/changelogs/unreleased/ide-fix-detect-mr-from-fork.yml b/changelogs/unreleased/ide-fix-detect-mr-from-fork.yml deleted file mode 100644 index 8f4f49896d7..00000000000 --- a/changelogs/unreleased/ide-fix-detect-mr-from-fork.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix IDE detection of MR from fork with same branch name -merge_request: 26986 -author: -type: fixed diff --git a/changelogs/unreleased/issue_58547.yml b/changelogs/unreleased/issue_58547.yml deleted file mode 100644 index 553c752e72d..00000000000 --- a/changelogs/unreleased/issue_58547.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add API access check to Graphql -merge_request: 26570 -author: -type: other diff --git a/changelogs/unreleased/jc-guard-against-empty-dereferenced_target.yml b/changelogs/unreleased/jc-guard-against-empty-dereferenced_target.yml deleted file mode 100644 index 94e5b4a81b7..00000000000 --- a/changelogs/unreleased/jc-guard-against-empty-dereferenced_target.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Guard against nil dereferenced_target -merge_request: 27192 -author: -type: fixed diff --git a/changelogs/unreleased/jc-upgrade-gitaly-1-34-0.yml b/changelogs/unreleased/jc-upgrade-gitaly-1-34-0.yml new file mode 100644 index 00000000000..c1669a484aa --- /dev/null +++ b/changelogs/unreleased/jc-upgrade-gitaly-1-34-0.yml @@ -0,0 +1,5 @@ +--- +title: Upgrade Gitaly to 1.34.0 +merge_request: 27494 +author: +type: fixed diff --git a/changelogs/unreleased/k8s_new_deployment_labels.yml b/changelogs/unreleased/k8s_new_deployment_labels.yml deleted file mode 100644 index e9ef3ee0082..00000000000 --- a/changelogs/unreleased/k8s_new_deployment_labels.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update deploy boards to additionally select on "app.gitlab.com" annotations -merge_request: 25623 -author: -type: changed diff --git a/changelogs/unreleased/knative-prometheus.yml b/changelogs/unreleased/knative-prometheus.yml deleted file mode 100644 index e24f53b7225..00000000000 --- a/changelogs/unreleased/knative-prometheus.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add Knative metrics to Prometheus -merge_request: 24663 -author: Chris Baumbauer <cab@cabnetworks.net> -type: added diff --git a/changelogs/unreleased/knative-update.yml b/changelogs/unreleased/knative-update.yml deleted file mode 100644 index e84940ae7e0..00000000000 --- a/changelogs/unreleased/knative-update.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Knative version bump 0.2.2 -> 0.3.0 -merge_request: 26459 -author: Chris Baumbauer -type: changed diff --git a/changelogs/unreleased/kube_helm_auto_devops_213.yml b/changelogs/unreleased/kube_helm_auto_devops_213.yml deleted file mode 100644 index 3c718d4a22c..00000000000 --- a/changelogs/unreleased/kube_helm_auto_devops_213.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Bump kubectl to 1.11.9 and Helm to 2.13.1 in Auto-DevOps.gitlab-ci.yml -merge_request: 26534 -author: -type: other diff --git a/changelogs/unreleased/limit-amount-of-created-pipelines.yml b/changelogs/unreleased/limit-amount-of-created-pipelines.yml deleted file mode 100644 index 51fdbb4d7ff..00000000000 --- a/changelogs/unreleased/limit-amount-of-created-pipelines.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Process at most 4 pipelines during push -merge_request: 27205 -author: -type: performance diff --git a/changelogs/unreleased/localize-notification-dropdown.yml b/changelogs/unreleased/localize-notification-dropdown.yml deleted file mode 100644 index 9599aaf344b..00000000000 --- a/changelogs/unreleased/localize-notification-dropdown.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Localize notifications dropdown -merge_request: 26844 -author: -type: changed diff --git a/changelogs/unreleased/markdown-autocomplete-escaping.yml b/changelogs/unreleased/markdown-autocomplete-escaping.yml new file mode 100644 index 00000000000..0ea034b14ee --- /dev/null +++ b/changelogs/unreleased/markdown-autocomplete-escaping.yml @@ -0,0 +1,5 @@ +--- +title: Only escape Markdown emphasis characters in autocomplete when necessary +merge_request: 27457 +author: +type: changed diff --git a/changelogs/unreleased/minimized-multiple-queries-ce.yml b/changelogs/unreleased/minimized-multiple-queries-ce.yml deleted file mode 100644 index d8c20d492d6..00000000000 --- a/changelogs/unreleased/minimized-multiple-queries-ce.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Support multiple queries per chart on metrics dash -merge_request: 25758 -author: -type: added diff --git a/changelogs/unreleased/move-allow-developers-to-create-projects-in-groups-to-core.yml b/changelogs/unreleased/move-allow-developers-to-create-projects-in-groups-to-core.yml deleted file mode 100644 index 34fd0c1b787..00000000000 --- a/changelogs/unreleased/move-allow-developers-to-create-projects-in-groups-to-core.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Move allow developers to create projects in groups to Core -merge_request: 25975 -author: -type: added diff --git a/changelogs/unreleased/nfriend-css-updates-for-gitlab-design-system-compliance.yml b/changelogs/unreleased/nfriend-css-updates-for-gitlab-design-system-compliance.yml deleted file mode 100644 index 8cde0958f7a..00000000000 --- a/changelogs/unreleased/nfriend-css-updates-for-gitlab-design-system-compliance.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update `border-radius` of form controls and remove extra space above page titles -merge_request: 24497 -author: -type: fixed diff --git a/changelogs/unreleased/nfriend-update-job-detail-view-sidebar.yml b/changelogs/unreleased/nfriend-update-job-detail-view-sidebar.yml deleted file mode 100644 index 5364d29710a..00000000000 --- a/changelogs/unreleased/nfriend-update-job-detail-view-sidebar.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update job detail sidebar to accommodate post-merge pipeline information -merge_request: 25777 -author: -type: added diff --git a/changelogs/unreleased/nfriend-update-merge-request-widget-for-post-merge-pipelines.yml b/changelogs/unreleased/nfriend-update-merge-request-widget-for-post-merge-pipelines.yml deleted file mode 100644 index 420c8f2923c..00000000000 --- a/changelogs/unreleased/nfriend-update-merge-request-widget-for-post-merge-pipelines.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add two new warning messages to the MR widget about merge request pipelines -merge_request: 25983 -author: -type: added diff --git a/changelogs/unreleased/nfriend-update-merge-request-widget-pipeline-block.yml b/changelogs/unreleased/nfriend-update-merge-request-widget-pipeline-block.yml deleted file mode 100644 index bd4120eb06f..00000000000 --- a/changelogs/unreleased/nfriend-update-merge-request-widget-pipeline-block.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: Update pipeline block on merge request page to accommodate post-merge pipeline - information -merge_request: 25745 -author: -type: added diff --git a/changelogs/unreleased/nfriend-update-pipeline-detail-view.yml b/changelogs/unreleased/nfriend-update-pipeline-detail-view.yml deleted file mode 100644 index a24325c4eb6..00000000000 --- a/changelogs/unreleased/nfriend-update-pipeline-detail-view.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update pipeline detail view to accommodate post-merge pipelines -merge_request: 25775 -author: -type: added diff --git a/changelogs/unreleased/nfriend-update-pipeline-list-view.yml b/changelogs/unreleased/nfriend-update-pipeline-list-view.yml deleted file mode 100644 index 34e43162b5c..00000000000 --- a/changelogs/unreleased/nfriend-update-pipeline-list-view.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update pipeline list view to accommodate post-merge pipeline information -merge_request: 25690 -author: -type: added diff --git a/changelogs/unreleased/only-counted-active-milestones-as-started.yml b/changelogs/unreleased/only-counted-active-milestones-as-started.yml deleted file mode 100644 index 1a9c4b9023b..00000000000 --- a/changelogs/unreleased/only-counted-active-milestones-as-started.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Only consider active milestones when using the special Started milestone filter -merge_request: -author: -type: fixed diff --git a/changelogs/unreleased/osw-multi-line-suggestions-creation-strategy.yml b/changelogs/unreleased/osw-multi-line-suggestions-creation-strategy.yml deleted file mode 100644 index 01bd7ede270..00000000000 --- a/changelogs/unreleased/osw-multi-line-suggestions-creation-strategy.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Implements the creation strategy for multi-line suggestions -merge_request: 26057 -author: -type: changed diff --git a/changelogs/unreleased/osw-multi-line-suggestions-parsing.yml b/changelogs/unreleased/osw-multi-line-suggestions-parsing.yml deleted file mode 100644 index 985b01e9254..00000000000 --- a/changelogs/unreleased/osw-multi-line-suggestions-parsing.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Prepare multi-line suggestions for rendering in Markdown -merge_request: 26107 -author: -type: other diff --git a/changelogs/unreleased/osw-support-multi-line-suggestions.yml b/changelogs/unreleased/osw-support-multi-line-suggestions.yml deleted file mode 100644 index 8c8206c3822..00000000000 --- a/changelogs/unreleased/osw-support-multi-line-suggestions.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Support multi-line suggestions -merge_request: 25211 -author: -type: added diff --git a/changelogs/unreleased/persist-fulll-ref-path-for-mr-pipelines.yml b/changelogs/unreleased/persist-fulll-ref-path-for-mr-pipelines.yml deleted file mode 100644 index ca42a26e8ff..00000000000 --- a/changelogs/unreleased/persist-fulll-ref-path-for-mr-pipelines.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Create MR pipelines with `refs/merge-requests/:iid/head` -merge_request: 25504 -author: -type: changed diff --git a/changelogs/unreleased/pravi-gitlab-ce-update-recaptcha.yml b/changelogs/unreleased/pravi-gitlab-ce-update-recaptcha.yml deleted file mode 100644 index 95379fb2ec1..00000000000 --- a/changelogs/unreleased/pravi-gitlab-ce-update-recaptcha.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Apply recaptcha API change in 4.0 -merge_request: 25921 -author: Praveen Arimbrathodiyil -type: other diff --git a/changelogs/unreleased/prevent-running-mr-pipelines-when-target-updated.yml b/changelogs/unreleased/prevent-running-mr-pipelines-when-target-updated.yml deleted file mode 100644 index d003ca55feb..00000000000 --- a/changelogs/unreleased/prevent-running-mr-pipelines-when-target-updated.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Create pipelines for merge requests only when source branch is updated -merge_request: 26921 -author: -type: fixed diff --git a/changelogs/unreleased/related-mr-link-cutoff.yml b/changelogs/unreleased/related-mr-link-cutoff.yml deleted file mode 100644 index 8cf77b6231a..00000000000 --- a/changelogs/unreleased/related-mr-link-cutoff.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Don't cutoff letters in MR and Issue links -merge_request: 25910 -author: gfyoung -type: fixed diff --git a/changelogs/unreleased/remove-ci-charts-undescriptive-header.yml b/changelogs/unreleased/remove-ci-charts-undescriptive-header.yml deleted file mode 100644 index 0e090592101..00000000000 --- a/changelogs/unreleased/remove-ci-charts-undescriptive-header.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Removes the undescriptive CI Charts header -merge_request: !26869 -author: -type: changed diff --git a/changelogs/unreleased/rename_auto_deploy_app_links.yml b/changelogs/unreleased/rename_auto_deploy_app_links.yml new file mode 100644 index 00000000000..c56b5fb5e5c --- /dev/null +++ b/changelogs/unreleased/rename_auto_deploy_app_links.yml @@ -0,0 +1,5 @@ +--- +title: Move location of charts/auto-deploy-app -> gitlab-org/charts/auto-deploy-app +merge_request: 27477 +author: +type: changed diff --git a/changelogs/unreleased/security-55503-fix-pdf-js-vulnerability.yml b/changelogs/unreleased/security-55503-fix-pdf-js-vulnerability.yml deleted file mode 100644 index e5d0cd4fee1..00000000000 --- a/changelogs/unreleased/security-55503-fix-pdf-js-vulnerability.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix PDF.js vulnerability -merge_request: -author: -type: security diff --git a/changelogs/unreleased/security-56224.yml b/changelogs/unreleased/security-56224.yml deleted file mode 100644 index a4e274e6ca5..00000000000 --- a/changelogs/unreleased/security-56224.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Hide "related branches" when user does not have permission -merge_request: -author: -type: security diff --git a/changelogs/unreleased/security-56927-xss-resolve-conflicts-branch-name.yml b/changelogs/unreleased/security-56927-xss-resolve-conflicts-branch-name.yml deleted file mode 100644 index f92d2c0dcb1..00000000000 --- a/changelogs/unreleased/security-56927-xss-resolve-conflicts-branch-name.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix XSS in resolve conflicts form -merge_request: -author: -type: security diff --git a/changelogs/unreleased/security-exif-migration.yml b/changelogs/unreleased/security-exif-migration.yml deleted file mode 100644 index cc529099df5..00000000000 --- a/changelogs/unreleased/security-exif-migration.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Added rake task for removing EXIF data from existing uploads. -merge_request: -author: -type: security diff --git a/changelogs/unreleased/security-id-potential-denial-languages.yml b/changelogs/unreleased/security-id-potential-denial-languages.yml deleted file mode 100644 index 2194ecb97dc..00000000000 --- a/changelogs/unreleased/security-id-potential-denial-languages.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Return cached languages if they've been detected before -merge_request: -author: -type: security diff --git a/changelogs/unreleased/security-mass-assignment-on-project-update.yml b/changelogs/unreleased/security-mass-assignment-on-project-update.yml deleted file mode 100644 index 93561cd91b3..00000000000 --- a/changelogs/unreleased/security-mass-assignment-on-project-update.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Disallow updating namespace when updating a project -merge_request: -author: -type: security diff --git a/changelogs/unreleased/sh-add-gitaly-duration-logs.yml b/changelogs/unreleased/sh-add-gitaly-duration-logs.yml deleted file mode 100644 index eea50384278..00000000000 --- a/changelogs/unreleased/sh-add-gitaly-duration-logs.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Log Gitaly RPC duration to api_json.log and production_json.log -merge_request: 26652 -author: -type: other diff --git a/changelogs/unreleased/sh-add-gitaly-ref-name-caching-tree-controller.yml b/changelogs/unreleased/sh-add-gitaly-ref-name-caching-tree-controller.yml deleted file mode 100644 index a051c1f70a8..00000000000 --- a/changelogs/unreleased/sh-add-gitaly-ref-name-caching-tree-controller.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Enable Gitaly FindCommit caching for TreeController -merge_request: 27100 -author: -type: performance diff --git a/changelogs/unreleased/sh-bump-ruby-required-version-check.yml b/changelogs/unreleased/sh-bump-ruby-required-version-check.yml new file mode 100644 index 00000000000..b5b6eb87650 --- /dev/null +++ b/changelogs/unreleased/sh-bump-ruby-required-version-check.yml @@ -0,0 +1,5 @@ +--- +title: Bump required Ruby version check to 2.5.3 +merge_request: 27495 +author: +type: other diff --git a/changelogs/unreleased/sh-cache-pipeline-find-commits.yml b/changelogs/unreleased/sh-cache-pipeline-find-commits.yml deleted file mode 100644 index 2acf180d6fa..00000000000 --- a/changelogs/unreleased/sh-cache-pipeline-find-commits.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Cache FindCommit results in pipelines view -merge_request: 26776 -author: -type: performance diff --git a/changelogs/unreleased/sh-cache-root-ref-asymetrically.yml b/changelogs/unreleased/sh-cache-root-ref-asymetrically.yml deleted file mode 100644 index 106d070cc05..00000000000 --- a/changelogs/unreleased/sh-cache-root-ref-asymetrically.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Cache Repository#root_ref within a request -merge_request: 25903 -author: -type: performance diff --git a/changelogs/unreleased/sh-clear-pipeline-status-cache-upon-destroy.yml b/changelogs/unreleased/sh-clear-pipeline-status-cache-upon-destroy.yml deleted file mode 100644 index 55779f0f9d3..00000000000 --- a/changelogs/unreleased/sh-clear-pipeline-status-cache-upon-destroy.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Clear pipeline status cache after destruction of pipeline -merge_request: 26575 -author: -type: fixed diff --git a/changelogs/unreleased/sh-fix-gitaly-find-commit-caching.yml b/changelogs/unreleased/sh-fix-gitaly-find-commit-caching.yml deleted file mode 100644 index 16d349c407c..00000000000 --- a/changelogs/unreleased/sh-fix-gitaly-find-commit-caching.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Allow ref name caching CommitService#find_commit -merge_request: 26248 -author: -type: performance diff --git a/changelogs/unreleased/sh-fix-issue-59065.yml b/changelogs/unreleased/sh-fix-issue-59065.yml deleted file mode 100644 index 41cd5ce0960..00000000000 --- a/changelogs/unreleased/sh-fix-issue-59065.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix Error 500 when user commits Wiki page with no commit message -merge_request: 26247 -author: -type: fixed diff --git a/changelogs/unreleased/sh-fix-merge-requests-api-remove-branch-param.yml b/changelogs/unreleased/sh-fix-merge-requests-api-remove-branch-param.yml deleted file mode 100644 index d13c972ccc9..00000000000 --- a/changelogs/unreleased/sh-fix-merge-requests-api-remove-branch-param.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix remove_source_branch merge request API handling -merge_request: 27392 -author: -type: fixed diff --git a/changelogs/unreleased/sh-fix-realtime-changes-with-reserved-words.yml b/changelogs/unreleased/sh-fix-realtime-changes-with-reserved-words.yml deleted file mode 100644 index 3d1501cd667..00000000000 --- a/changelogs/unreleased/sh-fix-realtime-changes-with-reserved-words.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix real-time updates for projects that contain a reserved word -merge_request: 27060 -author: -type: fixed diff --git a/changelogs/unreleased/sh-fix-ref-name-caching.yml b/changelogs/unreleased/sh-fix-ref-name-caching.yml deleted file mode 100644 index 6abd86688b4..00000000000 --- a/changelogs/unreleased/sh-fix-ref-name-caching.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix and expand Gitaly FindCommit caching -merge_request: 27018 -author: -type: performance diff --git a/changelogs/unreleased/sh-git-gc-after-initial-fetch.yml b/changelogs/unreleased/sh-git-gc-after-initial-fetch.yml deleted file mode 100644 index 867d7e6b9df..00000000000 --- a/changelogs/unreleased/sh-git-gc-after-initial-fetch.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: 'GitHub import: Run housekeeping after initial import' -merge_request: 26600 -author: -type: performance diff --git a/changelogs/unreleased/sh-improve-find-commit-caching.yml b/changelogs/unreleased/sh-improve-find-commit-caching.yml deleted file mode 100644 index 1b38684d018..00000000000 --- a/changelogs/unreleased/sh-improve-find-commit-caching.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Expand FindCommit caching to blob and refs -merge_request: 27084 -author: -type: performance diff --git a/changelogs/unreleased/sh-reject-info-refs-head-requests.yml b/changelogs/unreleased/sh-reject-info-refs-head-requests.yml deleted file mode 100644 index 0dca18e2fd8..00000000000 --- a/changelogs/unreleased/sh-reject-info-refs-head-requests.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Reject HEAD requests to info/refs endpoint -merge_request: 26334 -author: -type: fixed diff --git a/changelogs/unreleased/sh-skip-sti-tables-reltuples.yml b/changelogs/unreleased/sh-skip-sti-tables-reltuples.yml deleted file mode 100644 index 5bf0ccf3e9d..00000000000 --- a/changelogs/unreleased/sh-skip-sti-tables-reltuples.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix counting of groups in admin dashboard -merge_request: 26009 -author: -type: fixed diff --git a/changelogs/unreleased/sh-update-rails-5-0-7-2.yml b/changelogs/unreleased/sh-update-rails-5-0-7-2.yml deleted file mode 100644 index b0bc08d4760..00000000000 --- a/changelogs/unreleased/sh-update-rails-5-0-7-2.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update Rails to 5.0.7.2 -merge_request: 27022 -author: -type: security diff --git a/changelogs/unreleased/stop-signing-avatar-paths.yml b/changelogs/unreleased/stop-signing-avatar-paths.yml deleted file mode 100644 index 2c2493f0f21..00000000000 --- a/changelogs/unreleased/stop-signing-avatar-paths.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Speed up generation of avatar URLs when using object storage -merge_request: -author: -type: performance diff --git a/changelogs/unreleased/tpresa-add-highest-role-to-user.yml b/changelogs/unreleased/tpresa-add-highest-role-to-user.yml deleted file mode 100644 index 9714d8dcc99..00000000000 --- a/changelogs/unreleased/tpresa-add-highest-role-to-user.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Adding highest role property to admin's user details page -merge_request: -author: -type: added diff --git a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-3-0.yml b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-3-0.yml deleted file mode 100644 index 2e1adb1e1e9..00000000000 --- a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-3-0.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update GitLab Runner Helm Chart to 0.3.0/11.9.0 -merge_request: 26467 -author: -type: other diff --git a/changelogs/unreleased/update-gitlab-shell.yml b/changelogs/unreleased/update-gitlab-shell.yml deleted file mode 100644 index 446a5fe1ea9..00000000000 --- a/changelogs/unreleased/update-gitlab-shell.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update GitLab Shell to v9.0.0 -merge_request: 27002 -author: -type: other diff --git a/changelogs/unreleased/update-rack-oauth2.yml b/changelogs/unreleased/update-rack-oauth2.yml deleted file mode 100644 index dc2e7017695..00000000000 --- a/changelogs/unreleased/update-rack-oauth2.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update rack-oauth2 1.2.1 -> 1.9.3 -merge_request: 17868 -author: -type: other diff --git a/changelogs/unreleased/update-workhorse-8-5-1.yml b/changelogs/unreleased/update-workhorse-8-5-1.yml deleted file mode 100644 index 18193701678..00000000000 --- a/changelogs/unreleased/update-workhorse-8-5-1.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update GitLab Workhorse to v8.5.1 -merge_request: 27217 -author: -type: fixed diff --git a/changelogs/unreleased/use-only-all-pipelines.yml b/changelogs/unreleased/use-only-all-pipelines.yml deleted file mode 100644 index 68364d2a923..00000000000 --- a/changelogs/unreleased/use-only-all-pipelines.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Refactor all_pipelines in Merge request -merge_request: 25676 -author: -type: other diff --git a/changelogs/unreleased/use-untrusted-regexp.yml b/changelogs/unreleased/use-untrusted-regexp.yml deleted file mode 100644 index dd7f1bcaca1..00000000000 --- a/changelogs/unreleased/use-untrusted-regexp.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Use UntrustedRegexp for matching refs policy -merge_request: -author: -type: security diff --git a/changelogs/unreleased/winh-toggle-comment-draft.yml b/changelogs/unreleased/winh-toggle-comment-draft.yml deleted file mode 100644 index 6b4aad55a05..00000000000 --- a/changelogs/unreleased/winh-toggle-comment-draft.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Display draft when toggling replies -merge_request: 25563 -author: -type: fixed diff --git a/changelogs/unreleased/xanf-gitlab-ce-add-template-link.yml b/changelogs/unreleased/xanf-gitlab-ce-add-template-link.yml new file mode 100644 index 00000000000..b868758dcd2 --- /dev/null +++ b/changelogs/unreleased/xanf-gitlab-ce-add-template-link.yml @@ -0,0 +1,5 @@ +--- +title: Add instructions on how to contribute a Built-In template for project +merge_request: 26976 +author: +type: other diff --git a/changelogs/unreleased/xanf-gitlab-ce-move-project-tags.yml b/changelogs/unreleased/xanf-gitlab-ce-move-project-tags.yml deleted file mode 100644 index 124584c9bd4..00000000000 --- a/changelogs/unreleased/xanf-gitlab-ce-move-project-tags.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Move project tags to separate line -merge_request: 26797 -author: -type: other diff --git a/changelogs/unreleased/xanf-gitlab-ce-transfer-disables-js.yml b/changelogs/unreleased/xanf-gitlab-ce-transfer-disables-js.yml deleted file mode 100644 index 57c9a1aaa48..00000000000 --- a/changelogs/unreleased/xanf-gitlab-ce-transfer-disables-js.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Group transfer now properly redirects to edit on failure -merge_request: 26837 -author: -type: fixed diff --git a/config/initializers/lograge.rb b/config/initializers/lograge.rb index 5e790a9eccb..1ad93e14f7e 100644 --- a/config/initializers/lograge.rb +++ b/config/initializers/lograge.rb @@ -35,7 +35,7 @@ unless Sidekiq.server? end payload[:response] = event.payload[:response] if event.payload[:response] - payload[Gitlab::CorrelationId::LOG_KEY] = Gitlab::CorrelationId.current_id + payload[Labkit::Correlation::CorrelationId::LOG_KEY] = Labkit::Correlation::CorrelationId.current_id payload end diff --git a/config/initializers/peek.rb b/config/initializers/peek.rb index e051e5c68c4..eeb45fae753 100644 --- a/config/initializers/peek.rb +++ b/config/initializers/peek.rb @@ -19,7 +19,7 @@ Peek.into Peek::Views::Gitaly Peek.into Peek::Views::Rblineprof Peek.into Peek::Views::Redis Peek.into Peek::Views::GC -Peek.into Peek::Views::Tracing if Gitlab::Tracing.tracing_url_enabled? +Peek.into Peek::Views::Tracing if Labkit::Tracing.tracing_url_enabled? # rubocop:disable Naming/ClassAndModuleCamelCase class PEEK_DB_CLIENT diff --git a/config/initializers/tracing.rb b/config/initializers/tracing.rb index ddd91150c90..3c8779f238f 100644 --- a/config/initializers/tracing.rb +++ b/config/initializers/tracing.rb @@ -1,16 +1,14 @@ # frozen_string_literal: true -if Gitlab::Tracing.enabled? - require 'opentracing' - +if Labkit::Tracing.enabled? Rails.application.configure do |config| - config.middleware.insert_after Gitlab::Middleware::CorrelationId, ::Gitlab::Tracing::RackMiddleware + config.middleware.insert_after Gitlab::Middleware::CorrelationId, ::Labkit::Tracing::RackMiddleware end # Instrument the Sidekiq client Sidekiq.configure_client do |config| config.client_middleware do |chain| - chain.add Gitlab::Tracing::Sidekiq::ClientMiddleware + chain.add Labkit::Tracing::Sidekiq::ClientMiddleware end end @@ -18,20 +16,20 @@ if Gitlab::Tracing.enabled? if Sidekiq.server? Sidekiq.configure_server do |config| config.server_middleware do |chain| - chain.add Gitlab::Tracing::Sidekiq::ServerMiddleware + chain.add Labkit::Tracing::Sidekiq::ServerMiddleware end end end # Instrument Rails - Gitlab::Tracing::Rails::ActiveRecordSubscriber.instrument - Gitlab::Tracing::Rails::ActionViewSubscriber.instrument + Labkit::Tracing::Rails::ActiveRecordSubscriber.instrument + Labkit::Tracing::Rails::ActionViewSubscriber.instrument # In multi-processed clustered architectures (puma, unicorn) don't # start tracing until the worker processes are spawned. This works # around issues when the opentracing implementation spawns threads Gitlab::Cluster::LifecycleEvents.on_worker_start do - tracer = Gitlab::Tracing::Factory.create_tracer(Gitlab.process_name, Gitlab::Tracing.connection_string) + tracer = Labkit::Tracing::Factory.create_tracer(Gitlab.process_name, Labkit::Tracing.connection_string) OpenTracing.global_tracer = tracer if tracer end end diff --git a/config/prometheus/common_metrics.yml b/config/prometheus/common_metrics.yml index 356f573c5e9..3c67ca36791 100644 --- a/config/prometheus/common_metrics.yml +++ b/config/prometheus/common_metrics.yml @@ -1,42 +1,33 @@ - # NGINX Ingress metrics for pre-0.16.0 versions +dashboard: 'Environment metrics' +priority: 1 +panel_groups: +# NGINX Ingress metrics for pre-0.16.0 versions - group: Response metrics (NGINX Ingress VTS) priority: 10 - metrics: + panels: - title: "Throughput" + type: "area-chart" y_label: "Requests / Sec" - required_metrics: - - nginx_upstream_responses_total weight: 1 - queries: + metrics: - id: response_metrics_nginx_ingress_throughput_status_code query_range: 'sum(rate(nginx_upstream_responses_total{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) by (status_code)' unit: req / sec label: Status Code - series: - - label: status_code - when: - - value: 2xx - color: green - - value: 4xx - color: orange - - value: 5xx - color: red - title: "Latency" + type: "area-chart" y_label: "Latency (ms)" - required_metrics: - - nginx_upstream_response_msecs_avg weight: 1 - queries: + metrics: - id: response_metrics_nginx_ingress_latency_pod_average query_range: 'avg(nginx_upstream_response_msecs_avg{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"})' label: Pod average unit: ms - title: "HTTP Error Rate" + type: "area-chart" y_label: "HTTP Errors" - required_metrics: - - nginx_upstream_responses_total weight: 1 - queries: + metrics: - id: response_metrics_nginx_ingress_http_error_rate query_range: 'sum(rate(nginx_upstream_responses_total{status_code="5xx", upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) / sum(rate(nginx_upstream_responses_total{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) * 100' label: 5xx Errors @@ -44,227 +35,179 @@ # NGINX Ingress metrics for post-0.16.0 versions - group: Response metrics (NGINX Ingress) priority: 10 - metrics: + panels: - title: "Throughput" + type: "area-chart" y_label: "Requests / Sec" - required_metrics: - - nginx_ingress_controller_requests weight: 1 - queries: + metrics: - id: response_metrics_nginx_ingress_16_throughput_status_code query_range: 'sum(label_replace(rate(nginx_ingress_controller_requests{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m]), "status_code", "${1}xx", "status", "(.)..")) by (status_code)' unit: req / sec label: Status Code - series: - - label: status_code - when: - - value: 2xx - color: green - - value: 3xx - color: blue - - value: 4xx - color: orange - - value: 5xx - color: red - title: "Latency" + type: "area-chart" y_label: "Latency (ms)" - required_metrics: - - nginx_ingress_controller_ingress_upstream_latency_seconds_sum weight: 1 - queries: + metrics: - id: response_metrics_nginx_ingress_16_latency_pod_average query_range: 'sum(rate(nginx_ingress_controller_ingress_upstream_latency_seconds_sum{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) / sum(rate(nginx_ingress_controller_ingress_upstream_latency_seconds_count{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) * 1000' label: Pod average unit: ms - title: "HTTP Error Rate" + type: "area-chart" y_label: "HTTP Errors" - required_metrics: - - nginx_ingress_controller_requests weight: 1 - queries: + metrics: - id: response_metrics_nginx_ingress_16_http_error_rate query_range: 'sum(rate(nginx_ingress_controller_requests{status=~"5.*",namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) / sum(rate(nginx_ingress_controller_requests{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) * 100' label: 5xx Errors unit: "%" - group: Response metrics (HA Proxy) priority: 10 - metrics: + panels: - title: "Throughput" + type: "area-chart" y_label: "Requests / Sec" - required_metrics: - - haproxy_frontend_http_requests_total weight: 1 - queries: + metrics: - id: response_metrics_ha_proxy_throughput_status_code query_range: 'sum(rate(haproxy_frontend_http_requests_total{%{environment_filter}}[2m])) by (code)' unit: req / sec label: Status Code - series: - - label: status_code - when: - - value: 2xx - color: green - - value: 4xx - color: yellow - - value: 5xx - color: red - title: "HTTP Error Rate" + type: "area-chart" y_label: "Error Rate (%)" - required_metrics: - - haproxy_frontend_http_responses_total weight: 1 - queries: + metrics: - id: response_metrics_ha_proxy_http_error_rate query_range: 'sum(rate(haproxy_frontend_http_responses_total{code="5xx",%{environment_filter}}[2m])) / sum(rate(haproxy_frontend_http_responses_total{%{environment_filter}}[2m]))' label: HTTP Errors unit: "%" - group: Response metrics (AWS ELB) priority: 10 - metrics: + panels: - title: "Throughput" + type: "area-chart" y_label: "Requests / Sec" - required_metrics: - - aws_elb_request_count_sum weight: 1 - queries: + metrics: - id: response_metrics_aws_elb_throughput_requests query_range: 'sum(aws_elb_request_count_sum{%{environment_filter}}) / 60' label: Total unit: req / sec - title: "Latency" + type: "area-chart" y_label: "Latency (ms)" - required_metrics: - - aws_elb_latency_average weight: 1 - queries: + metrics: - id: response_metrics_aws_elb_latency_average query_range: 'avg(aws_elb_latency_average{%{environment_filter}}) * 1000' label: Average unit: ms - title: "HTTP Error Rate" + type: "area-chart" y_label: "Error Rate (%)" - required_metrics: - - aws_elb_request_count_sum - - aws_elb_httpcode_backend_5_xx_sum weight: 1 - queries: + metrics: - id: response_metrics_aws_elb_http_error_rate query_range: 'sum(aws_elb_httpcode_backend_5_xx_sum{%{environment_filter}}) / sum(aws_elb_request_count_sum{%{environment_filter}})' label: HTTP Errors unit: "%" - group: Response metrics (NGINX) priority: 10 - metrics: + panels: - title: "Throughput" + type: "area-chart" y_label: "Requests / Sec" - required_metrics: - - nginx_server_requests weight: 1 - queries: + metrics: - id: response_metrics_nginx_throughput_status_code query_range: 'sum(rate(nginx_server_requests{server_zone!="*", server_zone!="_", %{environment_filter}}[2m])) by (code)' unit: req / sec label: Status Code - series: - - label: status_code - when: - - value: 2xx - color: green - - value: 4xx - color: orange - - value: 5xx - color: red - title: "Latency" + type: "area-chart" y_label: "Latency (ms)" - required_metrics: - - nginx_server_requestMsec weight: 1 - queries: + metrics: - id: response_metrics_nginx_latency query_range: 'avg(nginx_server_requestMsec{%{environment_filter}})' label: Upstream unit: ms - title: "HTTP Error Rate" + type: "area-chart" y_label: "HTTP 500 Errors / Sec" - required_metrics: - - nginx_server_requests weight: 1 - queries: + metrics: - id: response_metrics_nginx_http_error_rate query_range: 'sum(rate(nginx_server_requests{code="5xx", %{environment_filter}}[2m]))' label: HTTP Errors unit: "errors / sec" - group: System metrics (Kubernetes) priority: 5 - metrics: + panels: - title: "Memory Usage (Total)" + type: "area-chart" y_label: "Total Memory Used" - required_metrics: - - container_memory_usage_bytes weight: 4 - queries: + metrics: - id: system_metrics_kubernetes_container_memory_total query_range: 'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) /1024/1024/1024' label: Total unit: GB - title: "Core Usage (Total)" + type: "area-chart" y_label: "Total Cores" - required_metrics: - - container_cpu_usage_seconds_total weight: 3 - queries: + metrics: - id: system_metrics_kubernetes_container_cores_total query_range: 'avg(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}[15m])) by (job)) without (job)' label: Total unit: "cores" - title: "Memory Usage (Pod average)" + type: "area-chart" y_label: "Memory Used per Pod" - required_metrics: - - container_memory_usage_bytes weight: 2 - queries: + metrics: - id: system_metrics_kubernetes_container_memory_average query_range: 'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) / count(avg(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}) without (job)) /1024/1024' label: Pod average unit: MB - title: "Canary: Memory Usage (Pod Average)" + type: "area-chart" y_label: "Memory Used per Pod" - required_metrics: - - container_memory_usage_bytes weight: 2 - queries: + metrics: - id: system_metrics_kubernetes_container_memory_average_canary query_range: 'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-canary-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) / count(avg(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-canary-(.*)",namespace="%{kube_namespace}"}) without (job)) /1024/1024' label: Pod average unit: MB track: canary - title: "Core Usage (Pod Average)" + type: "area-chart" y_label: "Cores per Pod" - required_metrics: - - container_cpu_usage_seconds_total weight: 1 - queries: + metrics: - id: system_metrics_kubernetes_container_core_usage query_range: 'avg(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}[15m])) by (job)) without (job) / count(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}[15m])) by (pod_name))' label: Pod average unit: "cores" - title: "Canary: Core Usage (Pod Average)" + type: "area-chart" y_label: "Cores per Pod" - required_metrics: - - container_cpu_usage_seconds_total weight: 1 - queries: + metrics: - id: system_metrics_kubernetes_container_core_usage_canary query_range: 'avg(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-canary-(.*)",namespace="%{kube_namespace}"}[15m])) by (job)) without (job) / count(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-canary-(.*)",namespace="%{kube_namespace}"}[15m])) by (pod_name))' label: Pod average unit: "cores" track: canary - title: "Knative function invocations" + type: "area-chart" y_label: "Invocations" - required_metrics: - - istio_revision_request_count weight: 1 - queries: + metrics: - id: system_metrics_knative_function_invocation_count query_range: 'floor(sum(rate(istio_revision_request_count{destination_configuration="%{function_name}", destination_namespace="%{kube_namespace}"}[1m])/3))' label: invocations / minute diff --git a/db/importers/common_metrics_importer.rb b/db/importers/common_metrics_importer.rb index deadd653ae9..195bde8f34a 100644 --- a/db/importers/common_metrics_importer.rb +++ b/db/importers/common_metrics_importer.rb @@ -53,7 +53,7 @@ module Importers private def process_content(&blk) - content.map do |group| + content['panel_groups'].map do |group| process_group(group, &blk) end end @@ -63,28 +63,28 @@ module Importers group: find_group_title_key(group['group']) } - group['metrics'].map do |metric| - process_metric(metric, attributes, &blk) + group['panels'].map do |panel| + process_panel(panel, attributes, &blk) end end - def process_metric(metric, attributes, &blk) + def process_panel(panel, attributes, &blk) attributes = attributes.merge( - title: metric['title'], - y_label: metric['y_label']) + title: panel['title'], + y_label: panel['y_label']) - metric['queries'].map do |query| - process_metric_query(query, attributes, &blk) + panel['metrics'].map do |metric_details| + process_metric_details(metric_details, attributes, &blk) end end - def process_metric_query(query, attributes, &blk) + def process_metric_details(metric_details, attributes, &blk) attributes = attributes.merge( - legend: query['label'], - query: query['query_range'], - unit: query['unit']) + legend: metric_details['label'], + query: metric_details['query_range'], + unit: metric_details['unit']) - yield(query['id'], attributes) + yield(metric_details['id'], attributes) end def find_or_build_metric!(id) diff --git a/doc/api/projects.md b/doc/api/projects.md index 0a950352ecf..951961e45ff 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -494,7 +494,9 @@ GET /projects/:id "name": "Diaspora", "path": "diaspora", "kind": "group", - "full_path": "diaspora" + "full_path": "diaspora", + "avatar_url": "http://localhost:3000/uploads/group/avatar/3/foo.jpg", + "web_url": "http://localhost:3000/groups/diaspora" }, "import_status": "none", "import_error": null, @@ -561,6 +563,8 @@ GET /projects/:id } ``` +**Note**: The `web_url` and `avatar_url` attributes on `namespace` were [introduced][ce-27427] in GitLab 11.11. + If the project is a fork, and you provide a valid token to authenticate, the `forked_from_project` field will appear in the response. @@ -1587,3 +1591,4 @@ GET /projects/:id/snapshot [eep]: https://about.gitlab.com/pricing/ "Available only in GitLab Premium" [ee-6137]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/6137 +[ce-27427]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/27427 diff --git a/doc/api/runners.md b/doc/api/runners.md index 46f7b1d2a25..2d91428d1c1 100644 --- a/doc/api/runners.md +++ b/doc/api/runners.md @@ -486,6 +486,7 @@ POST /runners | `locked` | boolean| no | Whether the Runner should be locked for current project | | `run_untagged` | boolean | no | Whether the Runner should handle untagged jobs | | `tag_list` | Array[String] | no | List of Runner's tags | +| `access_level` | string | no | The access_level of the runner; `not_protected` or `ref_protected` | | `maximum_timeout` | integer | no | Maximum timeout set when this Runner will handle the job | ``` diff --git a/doc/ci/examples/code_quality.md b/doc/ci/examples/code_quality.md index 3e7d6e7e3f7..186d4527bb6 100644 --- a/doc/ci/examples/code_quality.md +++ b/doc/ci/examples/code_quality.md @@ -1,7 +1,7 @@ # Analyze your project's Code Quality CAUTION: **Caution:** -The job definition shown below is supported on GitLab 11.5 and later versions. +The job definition shown below is supported on GitLab 11.11 and later versions. It also requires the GitLab Runner 11.5 or later. For earlier versions, use the [previous job definitions](#previous-job-definitions). @@ -11,27 +11,11 @@ and Docker. First, you need GitLab Runner with [docker-in-docker executor](../docker/using_docker_build.md#use-docker-in-docker-executor). -Once you set up the Runner, add a new job to `.gitlab-ci.yml` that -generates the expected report: +Once you set up the Runner, include the CodeQuality template in your CI config: ```yaml -code_quality: - image: docker:stable - variables: - DOCKER_DRIVER: overlay2 - allow_failure: true - services: - - docker:stable-dind - script: - - export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/') - - docker run - --env SOURCE_CODE="$PWD" - --volume "$PWD":/code - --volume /var/run/docker.sock:/var/run/docker.sock - "registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code - artifacts: - reports: - codequality: gl-code-quality-report.json +include: + - template: Code-Quality.gitlab-ci.yml ``` The above example will create a `code_quality` job in your CI/CD pipeline which @@ -54,6 +38,28 @@ While these old job definitions are still maintained they have been deprecated and may be removed in next major release, GitLab 12.0. You are advised to update your current `.gitlab-ci.yml` configuration to reflect that change. +For GitLab 11.5 and earlier, the job should look like: + +```yaml +code_quality: + image: docker:stable + variables: + DOCKER_DRIVER: overlay2 + allow_failure: true + services: + - docker:stable-dind + script: + - export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/') + - docker run + --env SOURCE_CODE="$PWD" + --volume "$PWD":/code + --volume /var/run/docker.sock:/var/run/docker.sock + "registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code + artifacts: + reports: + codequality: gl-code-quality-report.json +``` + For GitLab 11.4 and earlier, the job should look like: ```yaml diff --git a/doc/ci/merge_request_pipelines/index.md b/doc/ci/merge_request_pipelines/index.md index 2de751c9e62..6a03ab910fc 100644 --- a/doc/ci/merge_request_pipelines/index.md +++ b/doc/ci/merge_request_pipelines/index.md @@ -69,7 +69,7 @@ when a merge request was created or updated. For example: ## Combined ref pipelines **[PREMIUM]** -> [GitLab Premium](https://about.gitlab.com/pricing/) 11.10. +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/7380) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.10. It's possible for your source and target branches to diverge, which can result in the scenario that source branch's pipeline was green, the target's pipeline was green, diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md index 3a6f4bd8ed2..52a4bb27817 100644 --- a/doc/development/documentation/index.md +++ b/doc/development/documentation/index.md @@ -50,9 +50,7 @@ Adhere to the [Documentation Style Guide](styleguide.md). If a style standard is ## Folder structure and files -Beyond the top-level directories under /doc, which mainly pertain to audiences (`user`, `administration`, `development`), we organize by product area and subject, not type. - -For complete details, see the [Content](styleguide.md#content) section of the [Documentation Style Guide](styleguide.md). +See the [Structure](styleguide.md#structure) section of the [Documentation Style Guide](styleguide.md). ## Changing document location diff --git a/doc/development/documentation/styleguide.md b/doc/development/documentation/styleguide.md index d16a8243def..e36ad01d4f8 100644 --- a/doc/development/documentation/styleguide.md +++ b/doc/development/documentation/styleguide.md @@ -13,12 +13,9 @@ For programmatic help adhering to the guidelines, see [linting](index.md#linting See the GitLab handbook for further [writing style guidelines](https://about.gitlab.com/handbook/communication/#writing-style-guidelines) that apply to all GitLab content, not just documentation. -## Content +## Documentation is the single source of truth (SSOT) -These guidelines help toward the goal of having every user's search of documentation -yield a useful result, and ensuring content is consistent, helpful, and easy to consume. - -### Single source of truth (SSOT) on the GitLab product +### Why a single source of truth The documentation is the SSOT for all information related to the implementation, usage, and troubleshooting of GitLab products and features. It evolves continually, in keeping with new products and features, and with improvements for clarity, accuracy, and completeness. @@ -26,31 +23,43 @@ This policy prevents information silos, ensuring that it remains easy to find in It also informs decisions about the kinds of content we include in our documentation. -### All helpful information +The documentation is a continually evolving SSOT for all information related to the implementation, usage, and troubleshooting of GitLab products and features. + +### All information Include problem-solving actions that may address rare cases or be considered 'risky', so long as proper context is provided in the form of fully detailed warnings and caveats. This kind of content should be included as it could be helpful to others and, when properly explained, its benefits outweigh the risks. If you think you have found an exception to this rule, contact the Technical Writing team. -### All helpful media types and sources +We will add all troubleshooting information to the documentation, no matter how unlikely a user is to encounter a situation. +For the Troubleshooting sections, people in GitLab Support can merge additions themselves. + +### All media types Include any media types/sources if the content is relevant to readers. You can freely include or link presentations, diagrams, videos, etc.; no matter who it was originally composed for, if it is helpful to any of our audiences, we can include it. - If you use an image that has a separate source file (for example, a vector or diagram format), link the image to the source file so that it may be reused or updated by anyone. - Do not copy and paste content from other sources unless it is a limited quotation with the source cited. Typically it is better to either rephrase relevant information in your own words or link out to the other source. + +### No special types -### Markdown +In the software industry, it is a best practice to organize documentatioin in different types. For example, [Divio recommends](https://www.divio.com/blog/documentation/): -All GitLab documentation is written using [Markdown](https://en.wikipedia.org/wiki/Markdown). +1. Tutorials +2. How-to guides +3. Explanation +4. Reference (for example, a glossary) -The [documentation website](https://docs.gitlab.com) uses GitLab Kramdown as its Markdown rendering engine. For a complete Kramdown reference, see the [GitLab Markdown Kramdown Guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/). +At GitLab, we have so many product changes in our monthly releases that we can't afford to continually update multiple types of information. +If we have multiple types, the information will become outdated. Therefore, we have a [single template](structure.md) for documentation. -The [`gitlab-kramdown`](https://gitlab.com/gitlab-org/gitlab_kramdown) -Ruby gem will support all [GFM markup](../../user/markdown.md) in the future. That is, -all markup that is supported for display in the GitLab application itself. For now, -use regular Markdown markup, following the rules in the linked style guide. +We currently do not distinguish specific document types, although we are open to reconsidering this policy +once the documentation has reached a future stage of maturity and quality. If you are reading this, then despite our +continual improvement efforts, that point hasn't been reached. -Note that Kramdown-specific markup (e.g., `{:.class}`) will not render properly on GitLab instances under [`/help`](index.md#gitlab-help). +### Link instead of summarize -## Structure +There is a temptation to summarize the information on another page. +This will cause the information to live in two places. +Instead, link to the SSOT and explain why it is important to consume the information. ### Organize by topic, not by type @@ -63,6 +72,40 @@ it difficult to browse for the information you need and difficult to maintain up Instead, organize content by its subject (e.g. everything related to CI goes together) and cross-link between any related content. +### Docs-first methodology + +We employ a **docs-first methodology** to help ensure that the docs remain a complete and trusted resource, and to make communicating about the use of GitLab more efficient. + +* If the answer to a question exists in documentation, share the link to the docs instead of rephrasing the information. +* When you encounter new information not available in GitLab’s documentation (for example, when working on a support case or testing a feature), your first step should be to create a merge request to add this information to the docs. You can then share the MR in order to communicate this information. + +New information that would be useful toward the future usage or troubleshooting of GitLab should not be written directly in a forum or other messaging system, but added to a docs MR and then referenced, as described above. Note that among any other doc changes, you can always add a Troubleshooting section to a doc if none exists, or un-comment and use the placeholder Troubleshooting section included as part of our [doc template](structure.md#template-for-new-docs), if present. + +The more we reflexively add useful information to the docs, the more (and more successfully) the docs will be used to efficiently accomplish tasks and solve problems. + +If you have questions when considering, authoring, or editing docs, ask the Technical Writing team on Slack in `#docs` or in GitLab by mentioning the writer for the applicable [DevOps stage](https://about.gitlab.com/handbook/product/categories/#devops-stages). Otherwise, forge ahead with your best effort. It does not need to be perfect; the team is happy to review and improve upon your content. Please review the [Documentation guidelines](index.md) before you begin your first documentation MR. + +Having a knowledge base is any form that is separate from the documentation would be against the docs-first methodology because the content would overlap with the documentation. + +## Markdown + +All GitLab documentation is written using [Markdown](https://en.wikipedia.org/wiki/Markdown). + +The [documentation website](https://docs.gitlab.com) uses GitLab Kramdown as its Markdown rendering engine. For a complete Kramdown reference, see the [GitLab Markdown Kramdown Guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/). + +The [`gitlab-kramdown`](https://gitlab.com/gitlab-org/gitlab_kramdown) +Ruby gem will support all [GFM markup](../../user/markdown.md) in the future. That is, +all markup that is supported for display in the GitLab application itself. For now, +use regular Markdown markup, following the rules in the linked style guide. + +Note that Kramdown-specific markup (e.g., `{:.class}`) will not render properly on GitLab instances under [`/help`](index.md#gitlab-help). + +## Structure + +### Organize by topic, not by type + +Because we want documentation to be a SSOT, we should [organize by topic, not by type](#organize-by-topic-not-by-type). + ### Folder structure overview The documentation is separated by top-level audience folders [`user`](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/user), @@ -133,7 +176,7 @@ changes, regardless, and can move content if there is a better place for it. ### Avoid duplication -Do not include the same information in multiple places. Instead, choose one single-source-of-truth location and link from other relevant locations. +Do not include the same information in multiple places. [Link to a SSOT instead.](#link-instead-of-summarize) ### References across documents diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md index 1d517a65ce2..0ab9406c681 100644 --- a/doc/topics/autodevops/index.md +++ b/doc/topics/autodevops/index.md @@ -460,7 +460,7 @@ for example after the merge request is merged, the Review App will automatically be deleted. Review apps are deployed using the -[auto-deploy-app](https://gitlab.com/charts/auto-deploy-app) chart with +[auto-deploy-app](https://gitlab.com/gitlab-org/charts/auto-deploy-app) chart with Helm. The app will be deployed into the [Kubernetes namespace](../../user/project/clusters/index.md#deployment-variables) for the environment. @@ -528,7 +528,7 @@ You can make use of [environment variables](#environment-variables) to automatic scale your pod replicas. Apps are deployed using the -[auto-deploy-app](https://gitlab.com/charts/auto-deploy-app) chart with +[auto-deploy-app](https://gitlab.com/gitlab-org/charts/auto-deploy-app) chart with Helm. The app will be deployed into the [Kubernetes namespace](../../user/project/clusters/index.md#deployment-variables) for the environment. @@ -667,7 +667,7 @@ repo or by specifying a project variable: - **Bundled chart** - If your project has a `./chart` directory with a `Chart.yaml` file in it, Auto DevOps will detect the chart and use it instead of the [default - one](https://gitlab.com/charts/auto-deploy-app). + one](https://gitlab.com/gitlab-org/charts/auto-deploy-app). This can be a great way to control exactly how your application is deployed. - **Project variable** - Create a [project variable](../../ci/variables/README.md#gitlab-cicd-environment-variables) `AUTO_DEVOPS_CHART` with the URL of a custom chart to use or create two project variables `AUTO_DEVOPS_CHART_REPOSITORY` with the URL of a custom chart repository and `AUTO_DEVOPS_CHART` with the path to the chart. @@ -735,7 +735,7 @@ also be customized, and you can easily use a [custom buildpack](#custom-buildpac | **Variable** | **Description** | | ------------ | --------------- | | `AUTO_DEVOPS_DOMAIN` | The [Auto DevOps domain](#auto-devops-base-domain). By default, set automatically by the [Auto DevOps setting](#enablingdisabling-auto-devops). This variable is deprecated and [is scheduled to be removed](https://gitlab.com/gitlab-org/gitlab-ce/issues/56959). Use `KUBE_INGRESS_BASE_DOMAIN` instead. | -| `AUTO_DEVOPS_CHART` | The Helm Chart used to deploy your apps; defaults to the one [provided by GitLab](https://gitlab.com/charts/auto-deploy-app). | +| `AUTO_DEVOPS_CHART` | The Helm Chart used to deploy your apps; defaults to the one [provided by GitLab](https://gitlab.com/gitlab-org/charts/auto-deploy-app). | | `AUTO_DEVOPS_CHART_REPOSITORY` | The Helm Chart repository used to search for charts; defaults to `https://charts.gitlab.io`. | | `REPLICAS` | The number of replicas to deploy; defaults to 1. | | `PRODUCTION_REPLICAS` | The number of replicas to deploy in the production environment. This takes precedence over `REPLICAS`; defaults to 1. | diff --git a/doc/user/admin_area/settings/external_authorization.md b/doc/user/admin_area/settings/external_authorization.md new file mode 100644 index 00000000000..72e76ac2a84 --- /dev/null +++ b/doc/user/admin_area/settings/external_authorization.md @@ -0,0 +1,112 @@ +# External authorization control + +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/4216) in +> [GitLab Premium](https://about.gitlab.com/pricing) 10.6. +> [Moved](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/27056) to +> [GitLab Core](https://about.gitlab.com/pricing/) in 11.10. + +In highly controlled environments, it may be necessary for access policy to be +controlled by an external service that permits access based on project +classification and user access. GitLab provides a way to check project +authorization with your own defined service. + +## Overview + +Once the external service is configured and enabled, when a project is accessed, +a request is made to the external service with the user information and project +classification label assigned to the project. When the service replies with a +known response, the result is cached for 6 hours. + +If the external authorization is enabled, GitLab will further block pages and +functionality that render cross-project data. That includes: + +- most pages under Dashboard (Activity, Milestones, Snippets, Assigned merge + requests, Assigned issues, Todos) +- under a specific group (Activity, Contribution analytics, Issues, Issue boards, + Labels, Milestones, Merge requests) +- Global and Group search will be disabled + +This is to prevent performing to many requests at once to the external +authorization service. + +Whenever access is granted or denied this is logged in a logfile called +`external-policy-access-control.log`. +Read more about logs GitLab keeps in the [omnibus documentation][omnibus-log-docs]. + +## Configuration + +The external authorization service can be enabled by an admin on the GitLab's +admin area under the settings page: + +![Enable external authorization service](img/external_authorization_service_settings.png) + +The available required properties are: + +- **Service URL**: The URL to make authorization requests to. When leaving the + URL blank, cross project features will remain available while still being able + to specify classification labels for projects. +- **External authorization request timeout**: The timeout after which an + authorization request is aborted. When a request times out, access is denied + to the user. +- **Client authentication certificate**: The certificate to use to authenticate + with the external authorization service. +- **Client authentication key**: Private key for the certificate when + authentication is required for the external authorization service, this is + encrypted when stored. +- **Client authentication key password**: Passphrase to use for the private key when authenticating with the external service this is encrypted when stored. +- **Default classification label**: The classification label to use when + requesting authorization if no specific label is defined on the project + +When using TLS Authentication with a self signed certificate, the CA certificate +needs to be trused by the openssl installation. When using GitLab installed using +Omnibus, learn to install a custom CA in the +[omnibus documentation][omnibus-ssl-docs]. Alternatively learn where to install +custom certificates using `openssl version -d`. + +## How it works + +When GitLab requests access, it will send a JSON POST request to the external +service with this body: + +```json +{ + "user_identifier": "jane@acme.org", + "project_classification_label": "project-label", + "user_ldap_dn": "CN=Jane Doe,CN=admin,DC=acme" +} +``` + +The `user_ldap_dn` is optional and is only sent when the user is logged in +through LDAP. + +When the external authorization service responds with a status code 200, the +user is granted access. When the external service responds with a status code +401 or 403, the user is denied access. In any case, the request is cached for 6 hours. + +When denying access, a `reason` can be optionally specified in the JSON body: + +```json +{ + "reason": "You are not allowed access to this project." +} +``` + +Any other status code than 200, 401 or 403 will also deny access to the user, but the +response will not be cached. + +If the service times out (after 500ms), a message "External Policy Server did +not respond" will be displayed. + +## Classification labels + +You can use your own classification label in the project's +**Settings > General > General project settings** page in the "Classification +label" box. When no classification label is specified on a project, the default +label defined in the [global settings](#configuration) will be used. + +The label will be shown on all project pages in the upper right corner. + +![classification label on project page](img/classification_label_on_project_page.png) + +[omnibus-ssl-docs]: https://docs.gitlab.com/omnibus/settings/ssl.html +[omnibus-log-docs]: https://docs.gitlab.com/omnibus/settings/logs.html diff --git a/doc/user/admin_area/settings/img/classification_label_on_project_page.png b/doc/user/admin_area/settings/img/classification_label_on_project_page.png Binary files differnew file mode 100644 index 00000000000..4aedb332cec --- /dev/null +++ b/doc/user/admin_area/settings/img/classification_label_on_project_page.png diff --git a/doc/user/admin_area/settings/img/external_authorization_service_settings.png b/doc/user/admin_area/settings/img/external_authorization_service_settings.png Binary files differnew file mode 100644 index 00000000000..9b8658fd1a1 --- /dev/null +++ b/doc/user/admin_area/settings/img/external_authorization_service_settings.png diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md index bf41fdecd10..c7e8bb5b33b 100644 --- a/doc/user/discussions/index.md +++ b/doc/user/discussions/index.md @@ -348,19 +348,23 @@ Custom commit messages will be introduced by > [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/53310) in GitLab 11.10. -Reviewers can also suggest changes to -multiple lines with a single suggestion within Merge Request diff discussions. +Reviewers can also suggest changes to multiple lines with a single suggestion +within Merge Request diff discussions by adjusting the range offsets. The +offsets are relative to the position of the diff discussion, and specify the +range to be replaced by the suggestion when it is applied. ![Multi-line suggestion syntax](img/multi-line-suggestion-syntax.png) -In the example above, the suggestion covers three lines above and four lines below the commented diff line. -It'd change from 3 lines _above_ to 4 lines _below_ the commented Diff line. +In the example above, the suggestion covers three lines above and four lines +below the commented line. When applied, it would replace from 3 lines _above_ +to 4 lines _below_ the commented line, with the suggested change. ![Multi-line suggestion preview](img/multi-line-suggestion-preview.png) NOTE: **Note:** -Suggestions covering multiple lines are limited to 100 lines _above_ and 100 lines _below_ -the commented diff line, allowing up to 200 changed lines per suggestion. +Suggestions covering multiple lines are limited to 100 lines _above_ and 100 +lines _below_ the commented diff line, allowing up to 200 changed lines per +suggestion. ## Start a discussion by replying to a standard comment diff --git a/doc/user/project/clusters/serverless/index.md b/doc/user/project/clusters/serverless/index.md index 5b7e9ef906f..dfbed0ec95f 100644 --- a/doc/user/project/clusters/serverless/index.md +++ b/doc/user/project/clusters/serverless/index.md @@ -158,21 +158,6 @@ Follow these steps to deploy a function using the Node.js runtime to your Knativ description: "node.js runtime function" environment: MY_FUNCTION: echo-js - - echo-rb: - handler: MyEcho.my_function - source: ./echo-rb - runtime: https://gitlab.com/gitlab-org/serverless/runtimes/ruby - description: "Ruby runtime function" - environment: - MY_FUNCTION: echo-rb - - echo-docker: - handler: echo-docker - source: ./echo-docker - description: "Dockerfile runtime function" - environment: - MY_FUNCTION: echo-docker ``` Explanation of the fields used above: diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 4bdac278add..ee8480122c4 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -922,7 +922,15 @@ module API end class NamespaceBasic < Grape::Entity - expose :id, :name, :path, :kind, :full_path, :parent_id + expose :id, :name, :path, :kind, :full_path, :parent_id, :avatar_url + + expose :web_url do |namespace| + if namespace.user? + Gitlab::Routing.url_helpers.user_url(namespace.owner) + else + namespace.web_url + end + end end class Namespace < NamespaceBasic diff --git a/lib/api/runner.rb b/lib/api/runner.rb index c60d25b88cb..ea36c24eca2 100644 --- a/lib/api/runner.rb +++ b/lib/api/runner.rb @@ -15,12 +15,14 @@ module API optional :info, type: Hash, desc: %q(Runner's metadata) optional :active, type: Boolean, desc: 'Should Runner be active' optional :locked, type: Boolean, desc: 'Should Runner be locked for current project' + optional :access_level, type: String, values: Ci::Runner.access_levels.keys, + desc: 'The access_level of the runner' optional :run_untagged, type: Boolean, desc: 'Should Runner handle untagged jobs' optional :tag_list, type: Array[String], desc: %q(List of Runner's tags) optional :maximum_timeout, type: Integer, desc: 'Maximum timeout set when this Runner will handle the job' end post '/' do - attributes = attributes_for_keys([:description, :active, :locked, :run_untagged, :tag_list, :maximum_timeout]) + attributes = attributes_for_keys([:description, :active, :locked, :run_untagged, :tag_list, :access_level, :maximum_timeout]) .merge(get_runner_details_from_request) attributes = diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb index 726c4d95da9..c432317eb24 100644 --- a/lib/gitlab/gitaly_client.rb +++ b/lib/gitlab/gitaly_client.rb @@ -52,9 +52,9 @@ module Gitlab end def self.interceptors - return [] unless Gitlab::Tracing.enabled? + return [] unless Labkit::Tracing.enabled? - [Gitlab::Tracing::GRPCInterceptor.instance] + [Labkit::Tracing::GRPCInterceptor.instance] end private_class_method :interceptors @@ -218,7 +218,7 @@ module Gitlab feature = feature_stack && feature_stack[0] metadata['call_site'] = feature.to_s if feature metadata['gitaly-servers'] = address_metadata(remote_storage) if remote_storage - metadata['x-gitlab-correlation-id'] = Gitlab::CorrelationId.current_id if Gitlab::CorrelationId.current_id + metadata['x-gitlab-correlation-id'] = Labkit::Correlation::CorrelationId.current_id if Labkit::Correlation::CorrelationId.current_id metadata.merge!(server_feature_flags) diff --git a/lib/gitlab/grape_logging/loggers/correlation_id_logger.rb b/lib/gitlab/grape_logging/loggers/correlation_id_logger.rb index fa4c5d86d44..bbe4b24c7d4 100644 --- a/lib/gitlab/grape_logging/loggers/correlation_id_logger.rb +++ b/lib/gitlab/grape_logging/loggers/correlation_id_logger.rb @@ -6,7 +6,7 @@ module Gitlab module Loggers class CorrelationIdLogger < ::GrapeLogging::Loggers::Base def parameters(_, _) - { Gitlab::CorrelationId::LOG_KEY => Gitlab::CorrelationId.current_id } + { Labkit::Correlation::CorrelationId::LOG_KEY => Labkit::Correlation::CorrelationId.current_id } end end end diff --git a/lib/gitlab/graphql/authorize.rb b/lib/gitlab/graphql/authorize.rb index f62813db82c..f8d0208e275 100644 --- a/lib/gitlab/graphql/authorize.rb +++ b/lib/gitlab/graphql/authorize.rb @@ -8,7 +8,7 @@ module Gitlab extend ActiveSupport::Concern def self.use(schema_definition) - schema_definition.instrument(:field, Instrumentation.new) + schema_definition.instrument(:field, Instrumentation.new, after_built_ins: true) end end end diff --git a/lib/gitlab/graphql/authorize/authorize_field_service.rb b/lib/gitlab/graphql/authorize/authorize_field_service.rb index 8deff79fc84..03d6aabb0e3 100644 --- a/lib/gitlab/graphql/authorize/authorize_field_service.rb +++ b/lib/gitlab/graphql/authorize/authorize_field_service.rb @@ -15,15 +15,10 @@ module Gitlab def authorized_resolve proc do |parent_typed_object, args, ctx| - resolved_obj = @old_resolve_proc.call(parent_typed_object, args, ctx) - authorizing_obj = authorize_against(parent_typed_object) - checker = build_checker(ctx[:current_user], authorizing_obj) - - if resolved_obj.respond_to?(:then) - resolved_obj.then(&checker) - else - checker.call(resolved_obj) - end + resolved_type = @old_resolve_proc.call(parent_typed_object, args, ctx) + authorizing_object = authorize_against(parent_typed_object, resolved_type) + + filter_allowed(ctx[:current_user], resolved_type, authorizing_object) end end @@ -38,7 +33,7 @@ module Gitlab type = @field.type # When the return type of @field is a collection, find the singular type - if type.get_field('edges') + if @field.connection? type = node_type_for_relay_connection(type) elsif type.list? type = node_type_for_basic_connection(type) @@ -52,43 +47,60 @@ module Gitlab Array.wrap(@field.metadata[:authorize]) end - # If it's a built-in/scalar type, authorize using its parent object. - # nil means authorize using the resolved object - def authorize_against(parent_typed_object) - parent_typed_object.object if built_in_type? && parent_typed_object.respond_to?(:object) + def authorize_against(parent_typed_object, resolved_type) + if built_in_type? + # The field is a built-in/scalar type, or a list of scalars + # authorize using the parent's object + parent_typed_object.object + elsif resolved_type.respond_to?(:object) + # The field is a type representing a single object, we'll authorize + # against the object directly + resolved_type.object + elsif @field.connection? || resolved_type.is_a?(Array) + # The field is a connection or a list of non-built-in types, we'll + # authorize each element when rendering + nil + else + # Resolved type is a single object that might not be loaded yet by + # the batchloader, we'll authorize that + resolved_type + end end - def build_checker(current_user, authorizing_obj) - lambda do |resolved_obj| - # Load the elements if they were not loaded by BatchLoader yet - resolved_obj = resolved_obj.sync if resolved_obj.respond_to?(:sync) - - check = lambda do |object| - authorizations.all? do |ability| - Ability.allowed?(current_user, ability, authorizing_obj || object) - end + def filter_allowed(current_user, resolved_type, authorizing_object) + if authorizing_object + # Authorizing fields representing scalars, or a simple field with an object + resolved_type if allowed_access?(current_user, authorizing_object) + elsif @field.connection? + # A connection with pagination, modify the visible nodes in on the + # connection type in place + resolved_type.edge_nodes.to_a.keep_if { |node| allowed_access?(current_user, node) } + resolved_type + elsif resolved_type.is_a? Array + # A simple list of rendered types each object being an object to authorize + resolved_type.select do |single_object_type| + allowed_access?(current_user, single_object_type.object) end + elsif resolved_type.nil? + # We're not rendering anything, for example when a record was not found + # no need to do anything + else + raise "Can't authorize #{@field}" + end + end - case resolved_obj - when Array, ActiveRecord::Relation - resolved_obj.select(&check) - else - resolved_obj if check.call(resolved_obj) - end + def allowed_access?(current_user, object) + object = object.sync if object.respond_to?(:sync) + + authorizations.all? do |ability| + Ability.allowed?(current_user, ability, object) end end # Returns the singular type for relay connections. # This will be the type class of edges.node def node_type_for_relay_connection(type) - type = type.get_field('edges').type.unwrap.get_field('node')&.type - - if type.nil? - raise Gitlab::Graphql::Errors::ConnectionDefinitionError, - 'Connection Type must conform to the Relay Cursor Connections Specification' - end - - type + type.unwrap.get_field('edges').type.unwrap.get_field('node').type end # Returns the singular type for basic connections, for example `[Types::ProjectType]` diff --git a/lib/gitlab/graphql/connections/keyset_connection.rb b/lib/gitlab/graphql/connections/keyset_connection.rb index 851054c0393..715963a44c1 100644 --- a/lib/gitlab/graphql/connections/keyset_connection.rb +++ b/lib/gitlab/graphql/connections/keyset_connection.rb @@ -22,8 +22,17 @@ module Gitlab end # rubocop: enable CodeReuse/ActiveRecord - # rubocop: disable CodeReuse/ActiveRecord def paged_nodes + # These are the nodes that will be loaded into memory for rendering + # So we're ok loading them into memory here as that's bound to happen + # anyway. Having them ready means we can modify the result while + # rendering the fields. + @paged_nodes ||= load_paged_nodes.to_a + end + + private + + def load_paged_nodes if first && last raise Gitlab::Graphql::Errors::ArgumentError.new("Can only provide either `first` or `last`, not both") end @@ -31,12 +40,9 @@ module Gitlab if last sliced_nodes.last(limit_value) else - sliced_nodes.limit(limit_value) + sliced_nodes.limit(limit_value) # rubocop: disable CodeReuse/ActiveRecord end end - # rubocop: enable CodeReuse/ActiveRecord - - private def before_slice if sort_direction == :asc diff --git a/lib/gitlab/graphql/errors.rb b/lib/gitlab/graphql/errors.rb index bcbba72e017..fe74549e322 100644 --- a/lib/gitlab/graphql/errors.rb +++ b/lib/gitlab/graphql/errors.rb @@ -6,7 +6,6 @@ module Gitlab BaseError = Class.new(GraphQL::ExecutionError) ArgumentError = Class.new(BaseError) ResourceNotAvailable = Class.new(BaseError) - ConnectionDefinitionError = Class.new(BaseError) end end end diff --git a/lib/gitlab/json_logger.rb b/lib/gitlab/json_logger.rb index a5a5759cc89..ab34fb03158 100644 --- a/lib/gitlab/json_logger.rb +++ b/lib/gitlab/json_logger.rb @@ -10,7 +10,7 @@ module Gitlab data = {} data[:severity] = severity data[:time] = timestamp.utc.iso8601(3) - data[Gitlab::CorrelationId::LOG_KEY] = Gitlab::CorrelationId.current_id + data[Labkit::Correlation::CorrelationId::LOG_KEY] = Labkit::Correlation::CorrelationId.current_id case message when String diff --git a/lib/gitlab/middleware/correlation_id.rb b/lib/gitlab/middleware/correlation_id.rb index 80dddc41c12..fffd5da827f 100644 --- a/lib/gitlab/middleware/correlation_id.rb +++ b/lib/gitlab/middleware/correlation_id.rb @@ -12,7 +12,7 @@ module Gitlab end def call(env) - ::Gitlab::CorrelationId.use_id(correlation_id(env)) do + ::Labkit::Correlation::CorrelationId.use_id(correlation_id(env)) do @app.call(env) end end diff --git a/lib/gitlab/sentry.rb b/lib/gitlab/sentry.rb index 956c16117f5..356e6445e0e 100644 --- a/lib/gitlab/sentry.rb +++ b/lib/gitlab/sentry.rb @@ -45,7 +45,7 @@ module Gitlab context # Make sure we've set everything we know in the context tags = { - Gitlab::CorrelationId::LOG_KEY.to_sym => Gitlab::CorrelationId.current_id + Labkit::Correlation::CorrelationId::LOG_KEY.to_sym => Labkit::Correlation::CorrelationId.current_id } Raven.capture_exception(exception, tags: tags, extra: extra) diff --git a/lib/gitlab/sidekiq_middleware/correlation_injector.rb b/lib/gitlab/sidekiq_middleware/correlation_injector.rb index b807b3a03ed..1539fd706ab 100644 --- a/lib/gitlab/sidekiq_middleware/correlation_injector.rb +++ b/lib/gitlab/sidekiq_middleware/correlation_injector.rb @@ -4,8 +4,8 @@ module Gitlab module SidekiqMiddleware class CorrelationInjector def call(worker_class, job, queue, redis_pool) - job[Gitlab::CorrelationId::LOG_KEY] ||= - Gitlab::CorrelationId.current_or_new_id + job[Labkit::Correlation::CorrelationId::LOG_KEY] ||= + Labkit::Correlation::CorrelationId.current_or_new_id yield end diff --git a/lib/gitlab/sidekiq_middleware/correlation_logger.rb b/lib/gitlab/sidekiq_middleware/correlation_logger.rb index cb8ff4a6284..cffc4483573 100644 --- a/lib/gitlab/sidekiq_middleware/correlation_logger.rb +++ b/lib/gitlab/sidekiq_middleware/correlation_logger.rb @@ -4,9 +4,9 @@ module Gitlab module SidekiqMiddleware class CorrelationLogger def call(worker, job, queue) - correlation_id = job[Gitlab::CorrelationId::LOG_KEY] + correlation_id = job[Labkit::Correlation::CorrelationId::LOG_KEY] - Gitlab::CorrelationId.use_id(correlation_id) do + Labkit::Correlation::CorrelationId.use_id(correlation_id) do yield end end diff --git a/lib/gitlab/tracing/common.rb b/lib/gitlab/tracing/common.rb deleted file mode 100644 index 3a08ede8138..00000000000 --- a/lib/gitlab/tracing/common.rb +++ /dev/null @@ -1,69 +0,0 @@ -# frozen_string_literal: true - -require 'opentracing' - -module Gitlab - module Tracing - module Common - def tracer - OpenTracing.global_tracer - end - - # Convience method for running a block with a span - def in_tracing_span(operation_name:, tags:, child_of: nil) - scope = tracer.start_active_span( - operation_name, - child_of: child_of, - tags: tags - ) - span = scope.span - - # Add correlation details to the span if we have them - correlation_id = Gitlab::CorrelationId.current_id - if correlation_id - span.set_tag('correlation_id', correlation_id) - end - - begin - yield span - rescue => e - log_exception_on_span(span, e) - raise e - ensure - scope.close - end - end - - def postnotify_span(operation_name, start_time, end_time, tags: nil, child_of: nil, exception: nil) - span = OpenTracing.start_span(operation_name, start_time: start_time, tags: tags, child_of: child_of) - - log_exception_on_span(span, exception) if exception - - span.finish(end_time: end_time) - end - - def log_exception_on_span(span, exception) - span.set_tag('error', true) - span.log_kv(kv_tags_for_exception(exception)) - end - - def kv_tags_for_exception(exception) - case exception - when Exception - { - 'event': 'error', - 'error.kind': exception.class.to_s, - 'message': Gitlab::UrlSanitizer.sanitize(exception.message), - 'stack': exception.backtrace&.join("\n") - } - else - { - 'event': 'error', - 'error.kind': exception.class.to_s, - 'error.object': Gitlab::UrlSanitizer.sanitize(exception.to_s) - } - end - end - end - end -end diff --git a/lib/gitlab/tracing/factory.rb b/lib/gitlab/tracing/factory.rb deleted file mode 100644 index fc714164353..00000000000 --- a/lib/gitlab/tracing/factory.rb +++ /dev/null @@ -1,61 +0,0 @@ -# frozen_string_literal: true - -require "cgi" - -module Gitlab - module Tracing - class Factory - OPENTRACING_SCHEME = "opentracing" - - def self.create_tracer(service_name, connection_string) - return unless connection_string.present? - - begin - opentracing_details = parse_connection_string(connection_string) - driver_name = opentracing_details[:driver_name] - - case driver_name - when "jaeger" - JaegerFactory.create_tracer(service_name, opentracing_details[:options]) - else - raise "Unknown driver: #{driver_name}" - end - rescue => e - # Can't create the tracer? Warn and continue sans tracer - warn "Unable to instantiate tracer: #{e}" - nil - end - end - - def self.parse_connection_string(connection_string) - parsed = URI.parse(connection_string) - - unless valid_uri?(parsed) - raise "Invalid tracing connection string" - end - - { - driver_name: parsed.host, - options: parse_query(parsed.query) - } - end - private_class_method :parse_connection_string - - def self.parse_query(query) - return {} unless query - - CGI.parse(query).symbolize_keys.transform_values(&:first) - end - private_class_method :parse_query - - def self.valid_uri?(uri) - return false unless uri - - uri.scheme == OPENTRACING_SCHEME && - uri.host.to_s =~ /^[a-z0-9_]+$/ && - uri.path.empty? - end - private_class_method :valid_uri? - end - end -end diff --git a/lib/gitlab/tracing/grpc_interceptor.rb b/lib/gitlab/tracing/grpc_interceptor.rb deleted file mode 100644 index 6c2aab73125..00000000000 --- a/lib/gitlab/tracing/grpc_interceptor.rb +++ /dev/null @@ -1,54 +0,0 @@ -# frozen_string_literal: true - -require 'opentracing' -require 'grpc' - -module Gitlab - module Tracing - class GRPCInterceptor < GRPC::ClientInterceptor - include Common - include Singleton - - def request_response(request:, call:, method:, metadata:) - wrap_with_tracing(method, 'unary', metadata) do - yield - end - end - - def client_streamer(requests:, call:, method:, metadata:) - wrap_with_tracing(method, 'client_stream', metadata) do - yield - end - end - - def server_streamer(request:, call:, method:, metadata:) - wrap_with_tracing(method, 'server_stream', metadata) do - yield - end - end - - def bidi_streamer(requests:, call:, method:, metadata:) - wrap_with_tracing(method, 'bidi_stream', metadata) do - yield - end - end - - private - - def wrap_with_tracing(method, grpc_type, metadata) - tags = { - 'component' => 'grpc', - 'span.kind' => 'client', - 'grpc.method' => method, - 'grpc.type' => grpc_type - } - - in_tracing_span(operation_name: "grpc:#{method}", tags: tags) do |span| - OpenTracing.inject(span.context, OpenTracing::FORMAT_TEXT_MAP, metadata) - - yield - end - end - end - end -end diff --git a/lib/gitlab/tracing/jaeger_factory.rb b/lib/gitlab/tracing/jaeger_factory.rb deleted file mode 100644 index 93520d5667b..00000000000 --- a/lib/gitlab/tracing/jaeger_factory.rb +++ /dev/null @@ -1,97 +0,0 @@ -# frozen_string_literal: true - -require 'jaeger/client' - -module Gitlab - module Tracing - class JaegerFactory - # When the probabilistic sampler is used, by default 0.1% of requests will be traced - DEFAULT_PROBABILISTIC_RATE = 0.001 - - # The default port for the Jaeger agent UDP listener - DEFAULT_UDP_PORT = 6831 - - # Reduce this from default of 10 seconds as the Ruby jaeger - # client doesn't have overflow control, leading to very large - # messages which fail to send over UDP (max packet = 64k) - # Flush more often, with smaller packets - FLUSH_INTERVAL = 5 - - def self.create_tracer(service_name, options) - kwargs = { - service_name: service_name, - sampler: get_sampler(options[:sampler], options[:sampler_param]), - reporter: get_reporter(service_name, options[:http_endpoint], options[:udp_endpoint]) - }.compact - - extra_params = options.except(:sampler, :sampler_param, :http_endpoint, :udp_endpoint, :strict_parsing, :debug) # rubocop: disable CodeReuse/ActiveRecord - if extra_params.present? - message = "jaeger tracer: invalid option: #{extra_params.keys.join(", ")}" - - if options[:strict_parsing] - raise message - else - warn message - end - end - - Jaeger::Client.build(kwargs) - end - - def self.get_sampler(sampler_type, sampler_param) - case sampler_type - when "probabilistic" - sampler_rate = sampler_param ? sampler_param.to_f : DEFAULT_PROBABILISTIC_RATE - Jaeger::Samplers::Probabilistic.new(rate: sampler_rate) - when "const" - const_value = sampler_param == "1" - Jaeger::Samplers::Const.new(const_value) - else - nil - end - end - private_class_method :get_sampler - - def self.get_reporter(service_name, http_endpoint, udp_endpoint) - encoder = Jaeger::Encoders::ThriftEncoder.new(service_name: service_name) - - if http_endpoint.present? - sender = get_http_sender(encoder, http_endpoint) - elsif udp_endpoint.present? - sender = get_udp_sender(encoder, udp_endpoint) - else - return - end - - Jaeger::Reporters::RemoteReporter.new( - sender: sender, - flush_interval: FLUSH_INTERVAL - ) - end - private_class_method :get_reporter - - def self.get_http_sender(encoder, address) - Jaeger::HttpSender.new( - url: address, - encoder: encoder, - logger: Logger.new(STDOUT) - ) - end - private_class_method :get_http_sender - - def self.get_udp_sender(encoder, address) - pair = address.split(":", 2) - host = pair[0] - port = pair[1] ? pair[1].to_i : DEFAULT_UDP_PORT - - Jaeger::UdpSender.new( - host: host, - port: port, - encoder: encoder, - logger: Logger.new(STDOUT) - ) - end - private_class_method :get_udp_sender - end - end -end diff --git a/lib/gitlab/tracing/rack_middleware.rb b/lib/gitlab/tracing/rack_middleware.rb deleted file mode 100644 index e6a31293f7b..00000000000 --- a/lib/gitlab/tracing/rack_middleware.rb +++ /dev/null @@ -1,46 +0,0 @@ -# frozen_string_literal: true - -require 'opentracing' - -module Gitlab - module Tracing - class RackMiddleware - include Common - - REQUEST_METHOD = 'REQUEST_METHOD' - - def initialize(app) - @app = app - end - - def call(env) - method = env[REQUEST_METHOD] - - context = tracer.extract(OpenTracing::FORMAT_RACK, env) - tags = { - 'component' => 'rack', - 'span.kind' => 'server', - 'http.method' => method, - 'http.url' => self.class.build_sanitized_url_from_env(env) - } - - in_tracing_span(operation_name: "http:#{method}", child_of: context, tags: tags) do |span| - @app.call(env).tap do |status_code, _headers, _body| - span.set_tag('http.status_code', status_code) - end - end - end - - # Generate a sanitized (safe) request URL from the rack environment - def self.build_sanitized_url_from_env(env) - request = ActionDispatch::Request.new(env) - - original_url = request.original_url - uri = URI.parse(original_url) - uri.query = request.filtered_parameters.to_query if uri.query.present? - - uri.to_s - end - end - end -end diff --git a/lib/gitlab/tracing/rails/action_view_subscriber.rb b/lib/gitlab/tracing/rails/action_view_subscriber.rb deleted file mode 100644 index 88816e1fb32..00000000000 --- a/lib/gitlab/tracing/rails/action_view_subscriber.rb +++ /dev/null @@ -1,75 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Tracing - module Rails - class ActionViewSubscriber - include RailsCommon - - COMPONENT_TAG = 'ActionView' - RENDER_TEMPLATE_NOTIFICATION_TOPIC = 'render_template.action_view' - RENDER_COLLECTION_NOTIFICATION_TOPIC = 'render_collection.action_view' - RENDER_PARTIAL_NOTIFICATION_TOPIC = 'render_partial.action_view' - - # Instruments Rails ActionView events for opentracing. - # Returns a lambda, which, when called will unsubscribe from the notifications - def self.instrument - subscriber = new - - subscriptions = [ - ActiveSupport::Notifications.subscribe(RENDER_TEMPLATE_NOTIFICATION_TOPIC) do |_, start, finish, _, payload| - subscriber.notify_render_template(start, finish, payload) - end, - ActiveSupport::Notifications.subscribe(RENDER_COLLECTION_NOTIFICATION_TOPIC) do |_, start, finish, _, payload| - subscriber.notify_render_collection(start, finish, payload) - end, - ActiveSupport::Notifications.subscribe(RENDER_PARTIAL_NOTIFICATION_TOPIC) do |_, start, finish, _, payload| - subscriber.notify_render_partial(start, finish, payload) - end - ] - - create_unsubscriber subscriptions - end - - # For more information on the payloads: https://guides.rubyonrails.org/active_support_instrumentation.html - def notify_render_template(start, finish, payload) - generate_span_for_notification("render_template", start, finish, payload, tags_for_render_template(payload)) - end - - def notify_render_collection(start, finish, payload) - generate_span_for_notification("render_collection", start, finish, payload, tags_for_render_collection(payload)) - end - - def notify_render_partial(start, finish, payload) - generate_span_for_notification("render_partial", start, finish, payload, tags_for_render_partial(payload)) - end - - private - - def tags_for_render_template(payload) - { - 'component' => COMPONENT_TAG, - 'template.id' => payload[:identifier], - 'template.layout' => payload[:layout] - } - end - - def tags_for_render_collection(payload) - { - 'component' => COMPONENT_TAG, - 'template.id' => payload[:identifier], - 'template.count' => payload[:count] || 0, - 'template.cache.hits' => payload[:cache_hits] || 0 - } - end - - def tags_for_render_partial(payload) - { - 'component' => COMPONENT_TAG, - 'template.id' => payload[:identifier] - } - end - end - end - end -end diff --git a/lib/gitlab/tracing/rails/active_record_subscriber.rb b/lib/gitlab/tracing/rails/active_record_subscriber.rb deleted file mode 100644 index 32f5658e57e..00000000000 --- a/lib/gitlab/tracing/rails/active_record_subscriber.rb +++ /dev/null @@ -1,49 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Tracing - module Rails - class ActiveRecordSubscriber - include RailsCommon - - ACTIVE_RECORD_NOTIFICATION_TOPIC = 'sql.active_record' - OPERATION_NAME_PREFIX = 'active_record:' - DEFAULT_OPERATION_NAME = 'sqlquery' - - # Instruments Rails ActiveRecord events for opentracing. - # Returns a lambda, which, when called will unsubscribe from the notifications - def self.instrument - subscriber = new - - subscription = ActiveSupport::Notifications.subscribe(ACTIVE_RECORD_NOTIFICATION_TOPIC) do |_, start, finish, _, payload| - subscriber.notify(start, finish, payload) - end - - create_unsubscriber [subscription] - end - - # For more information on the payloads: https://guides.rubyonrails.org/active_support_instrumentation.html - def notify(start, finish, payload) - generate_span_for_notification(notification_name(payload), start, finish, payload, tags_for_notification(payload)) - end - - private - - def notification_name(payload) - OPERATION_NAME_PREFIX + (payload[:name].presence || DEFAULT_OPERATION_NAME) - end - - def tags_for_notification(payload) - { - 'component' => 'ActiveRecord', - 'span.kind' => 'client', - 'db.type' => 'sql', - 'db.connection_id' => payload[:connection_id], - 'db.cached' => payload[:cached] || false, - 'db.statement' => payload[:sql] - } - end - end - end - end -end diff --git a/lib/gitlab/tracing/rails/rails_common.rb b/lib/gitlab/tracing/rails/rails_common.rb deleted file mode 100644 index 88e914f62f8..00000000000 --- a/lib/gitlab/tracing/rails/rails_common.rb +++ /dev/null @@ -1,24 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Tracing - module Rails - module RailsCommon - extend ActiveSupport::Concern - include Gitlab::Tracing::Common - - class_methods do - def create_unsubscriber(subscriptions) - -> { subscriptions.each { |subscriber| ActiveSupport::Notifications.unsubscribe(subscriber) } } - end - end - - def generate_span_for_notification(operation_name, start, finish, payload, tags) - exception = payload[:exception] - - postnotify_span(operation_name, start, finish, tags: tags, exception: exception) - end - end - end - end -end diff --git a/lib/gitlab/tracing/sidekiq/client_middleware.rb b/lib/gitlab/tracing/sidekiq/client_middleware.rb deleted file mode 100644 index 2b71c1ea21e..00000000000 --- a/lib/gitlab/tracing/sidekiq/client_middleware.rb +++ /dev/null @@ -1,26 +0,0 @@ -# frozen_string_literal: true - -require 'opentracing' - -module Gitlab - module Tracing - module Sidekiq - class ClientMiddleware - include SidekiqCommon - - SPAN_KIND = 'client' - - def call(worker_class, job, queue, redis_pool) - in_tracing_span( - operation_name: "sidekiq:#{job['class']}", - tags: tags_from_job(job, SPAN_KIND)) do |span| - # Inject the details directly into the job - tracer.inject(span.context, OpenTracing::FORMAT_TEXT_MAP, job) - - yield - end - end - end - end - end -end diff --git a/lib/gitlab/tracing/sidekiq/server_middleware.rb b/lib/gitlab/tracing/sidekiq/server_middleware.rb deleted file mode 100644 index 5b43c4310e6..00000000000 --- a/lib/gitlab/tracing/sidekiq/server_middleware.rb +++ /dev/null @@ -1,26 +0,0 @@ -# frozen_string_literal: true - -require 'opentracing' - -module Gitlab - module Tracing - module Sidekiq - class ServerMiddleware - include SidekiqCommon - - SPAN_KIND = 'server' - - def call(worker, job, queue) - context = tracer.extract(OpenTracing::FORMAT_TEXT_MAP, job) - - in_tracing_span( - operation_name: "sidekiq:#{job['class']}", - child_of: context, - tags: tags_from_job(job, SPAN_KIND)) do |span| - yield - end - end - end - end - end -end diff --git a/lib/gitlab/tracing/sidekiq/sidekiq_common.rb b/lib/gitlab/tracing/sidekiq/sidekiq_common.rb deleted file mode 100644 index a911a29d773..00000000000 --- a/lib/gitlab/tracing/sidekiq/sidekiq_common.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Tracing - module Sidekiq - module SidekiqCommon - include Gitlab::Tracing::Common - - def tags_from_job(job, kind) - { - 'component' => 'sidekiq', - 'span.kind' => kind, - 'sidekiq.queue' => job['queue'], - 'sidekiq.jid' => job['jid'], - 'sidekiq.retry' => job['retry'].to_s, - 'sidekiq.args' => job['args']&.join(", ") - } - end - end - end - end -end diff --git a/lib/peek/views/tracing.rb b/lib/peek/views/tracing.rb index 0de32a8fdda..94726a498ea 100644 --- a/lib/peek/views/tracing.rb +++ b/lib/peek/views/tracing.rb @@ -4,9 +4,9 @@ module Peek module Views class Tracing < View def results - { - tracing_url: Gitlab::Tracing.tracing_url - } + tracing_url = Labkit::Tracing.tracing_url(Gitlab.process_name) + + { tracing_url: tracing_url } end end end diff --git a/lib/system_check/app/ruby_version_check.rb b/lib/system_check/app/ruby_version_check.rb index 60e07718338..53da62df176 100644 --- a/lib/system_check/app/ruby_version_check.rb +++ b/lib/system_check/app/ruby_version_check.rb @@ -7,7 +7,7 @@ module SystemCheck set_check_pass -> { "yes (#{self.current_version})" } def self.required_version - @required_version ||= Gitlab::VersionInfo.new(2, 3, 5) + @required_version ||= Gitlab::VersionInfo.new(2, 5, 3) end def self.current_version diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 0d6cb4c85b5..54c40e48084 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -375,12 +375,6 @@ msgstr "" msgid "A member of GitLab's abuse team will review your report as soon as possible." msgstr "" -msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts." -msgstr "" - -msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build." -msgstr "" - msgid "A new branch will be created in your fork and a new merge request will be started." msgstr "" @@ -1173,9 +1167,6 @@ msgstr "" msgid "Automatically marked as default internal user" msgstr "" -msgid "Automatically resolve merge request diff discussions when they become outdated" -msgstr "" - msgid "Automatically resolved" msgstr "" @@ -1722,7 +1713,7 @@ msgstr "" msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions." msgstr "" -msgid "Choose your merge method, set up a default merge request description template." +msgid "Choose your merge method, options, checks, and set up a default merge request description template." msgstr "" msgid "CiStatusLabel|canceled" @@ -4003,9 +3994,6 @@ msgstr "" msgid "Failure" msgstr "" -msgid "Fast-forward merge" -msgstr "" - msgid "Fast-forward merge without a merge commit" msgstr "" @@ -5260,6 +5248,9 @@ msgstr "" msgid "Lead" msgstr "" +msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}" +msgstr "" + msgid "Learn more" msgstr "" @@ -5505,15 +5496,9 @@ msgstr "" msgid "Merge Requests" msgstr "" -msgid "Merge commit" -msgstr "" - msgid "Merge commit message" msgstr "" -msgid "Merge commit with semi-linear history" -msgstr "" - msgid "Merge events" msgstr "" @@ -5523,9 +5508,6 @@ msgstr "" msgid "Merge in progress" msgstr "" -msgid "Merge method" -msgstr "" - msgid "Merge request" msgstr "" @@ -5990,9 +5972,6 @@ msgstr "" msgid "No license. All rights reserved" msgstr "" -msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase." -msgstr "" - msgid "No merge requests found" msgstr "" @@ -6187,12 +6166,6 @@ msgstr "" msgid "Only admins" msgstr "" -msgid "Only allow merge requests to be merged if all discussions are resolved" -msgstr "" - -msgid "Only allow merge requests to be merged if the pipeline succeeds" -msgstr "" - msgid "Only mirror protected branches" msgstr "" @@ -6457,9 +6430,6 @@ msgstr "" msgid "Pipelines for last year" msgstr "" -msgid "Pipelines need to be configured to enable this feature." -msgstr "" - msgid "Pipelines settings for '%{project_name}' were successfully updated." msgstr "" @@ -7093,15 +7063,69 @@ msgstr "" msgid "ProjectPage|Project ID: %{project_id}" msgstr "" +msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed" +msgstr "" + +msgid "ProjectSettings|All discussions must be resolved" +msgstr "" + +msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated" +msgstr "" + msgid "ProjectSettings|Badges" msgstr "" msgid "ProjectSettings|Customize your project badges." msgstr "" +msgid "ProjectSettings|Every merge creates a merge commit" +msgstr "" + +msgid "ProjectSettings|Fast-forward merge" +msgstr "" + +msgid "ProjectSettings|Fast-forward merges only" +msgstr "" + msgid "ProjectSettings|Learn more about badges." msgstr "" +msgid "ProjectSettings|Merge checks" +msgstr "" + +msgid "ProjectSettings|Merge commit" +msgstr "" + +msgid "ProjectSettings|Merge commit with semi-linear history" +msgstr "" + +msgid "ProjectSettings|Merge method" +msgstr "" + +msgid "ProjectSettings|Merge options" +msgstr "" + +msgid "ProjectSettings|No merge commits are created" +msgstr "" + +msgid "ProjectSettings|Pipelines must succeed" +msgstr "" + +msgid "ProjectSettings|Pipelines need to be configured to enable this feature." +msgstr "" + +msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line" +msgstr "" + +msgid "ProjectSettings|These checks must pass before merge requests can be merged" +msgstr "" + +msgid "ProjectSettings|This will dictate the commit history when you merge a merge request" +msgstr "" + +msgid "ProjectSettings|When conflicts arise the user is given the option to rebase" +msgstr "" + msgid "Projects" msgstr "" @@ -8144,9 +8168,6 @@ msgstr "" msgid "Show latest version" msgstr "" -msgid "Show link to create/view merge request when pushing from the command line" -msgstr "" - msgid "Show parent pages" msgstr "" @@ -10165,9 +10186,6 @@ msgstr "" msgid "When enabled, users cannot use GitLab until the terms have been accepted." msgstr "" -msgid "When fast-forward merge is not possible, the user is given the option to rebase." -msgstr "" - msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks." msgstr "" diff --git a/qa/qa/page/component/note.rb b/qa/qa/page/component/note.rb index f5add6bc9b5..07e191f1c9b 100644 --- a/qa/qa/page/component/note.rb +++ b/qa/qa/page/component/note.rb @@ -15,7 +15,7 @@ module QA element :reply_comment_button end - base.view 'app/assets/javascripts/notes/components/noteable_discussion.vue' do + base.view 'app/assets/javascripts/notes/components/discussion_actions.vue' do element :discussion_reply end diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index a5ecb475ce3..7296a4b4526 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -462,7 +462,7 @@ describe ApplicationController do end it 'does log correlation id' do - Gitlab::CorrelationId.use_id('new-id') do + Labkit::Correlation::CorrelationId.use_id('new-id') do get :index end diff --git a/spec/db/importers/common_metrics_importer_spec.rb b/spec/db/importers/common_metrics_importer_spec.rb index 6133b17ac61..a717c8cd04d 100644 --- a/spec/db/importers/common_metrics_importer_spec.rb +++ b/spec/db/importers/common_metrics_importer_spec.rb @@ -23,10 +23,10 @@ describe Importers::CommonMetricsImporter do subject { described_class.new } context "does import common_metrics.yml" do - let(:groups) { subject.content } - let(:metrics) { groups.map { |group| group['metrics'] }.flatten } - let(:queries) { metrics.map { |group| group['queries'] }.flatten } - let(:query_ids) { queries.map { |query| query['id'] } } + let(:groups) { subject.content['panel_groups'] } + let(:panels) { groups.map { |group| group['panels'] }.flatten } + let(:metrics) { panels.map { |group| group['metrics'] }.flatten } + let(:metric_ids) { metrics.map { |metric| metric['id'] } } before do subject.execute @@ -36,20 +36,20 @@ describe Importers::CommonMetricsImporter do expect(PrometheusMetric.common.group(:group).count.count).to eq(groups.count) end - it "has the same amount of metrics" do - expect(PrometheusMetric.common.group(:group, :title).count.count).to eq(metrics.count) + it "has the same amount of panels" do + expect(PrometheusMetric.common.group(:group, :title).count.count).to eq(panels.count) end - it "has the same amount of queries" do - expect(PrometheusMetric.common.count).to eq(queries.count) + it "has the same amount of metrics" do + expect(PrometheusMetric.common.count).to eq(metrics.count) end it "does not have duplicate IDs" do - expect(query_ids).to eq(query_ids.uniq) + expect(metric_ids).to eq(metric_ids.uniq) end it "imports all IDs" do - expect(PrometheusMetric.common.pluck(:identifier)).to contain_exactly(*query_ids) + expect(PrometheusMetric.common.pluck(:identifier)).to contain_exactly(*metric_ids) end end @@ -65,24 +65,26 @@ describe Importers::CommonMetricsImporter do context 'does import properly all fields' do let(:query_identifier) { 'response-metric' } - let(:group) do + let(:dashboard) do { - group: 'Response metrics (NGINX Ingress)', - metrics: [{ - title: "Throughput", - y_label: "Requests / Sec", - queries: [{ - id: query_identifier, - query_range: 'my-query', - unit: 'my-unit', - label: 'status code' + panel_groups: [{ + group: 'Response metrics (NGINX Ingress)', + panels: [{ + title: "Throughput", + y_label: "Requests / Sec", + metrics: [{ + id: query_identifier, + query_range: 'my-query', + unit: 'my-unit', + label: 'status code' + }] }] }] } end before do - expect(subject).to receive(:content) { [group.deep_stringify_keys] } + expect(subject).to receive(:content) { dashboard.deep_stringify_keys } end shared_examples 'stores metric' do diff --git a/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb b/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb index b1c2bab08c0..28d52f25f56 100644 --- a/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb +++ b/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'spec_helper' describe 'Projects > Settings > User manages merge request settings' do @@ -30,16 +31,16 @@ describe 'Projects > Settings > User manages merge request settings' do context 'when Merge Request and Pipelines are initially enabled', :js do context 'when Pipelines are initially enabled' do it 'shows the Merge Requests settings' do - expect(page).to have_content('Only allow merge requests to be merged if the pipeline succeeds') - expect(page).to have_content('Only allow merge requests to be merged if all discussions are resolved') + expect(page).to have_content 'Pipelines must succeed' + expect(page).to have_content 'All discussions must be resolved' within('.sharing-permissions-form') do find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .project-feature-toggle').click find('input[value="Save changes"]').send_keys(:return) end - expect(page).not_to have_content('Only allow merge requests to be merged if the pipeline succeeds') - expect(page).not_to have_content('Only allow merge requests to be merged if all discussions are resolved') + expect(page).not_to have_content 'Pipelines must succeed' + expect(page).not_to have_content 'All discussions must be resolved' end end @@ -50,16 +51,16 @@ describe 'Projects > Settings > User manages merge request settings' do end it 'shows the Merge Requests settings that do not depend on Builds feature' do - expect(page).not_to have_content('Only allow merge requests to be merged if the pipeline succeeds') - expect(page).to have_content('Only allow merge requests to be merged if all discussions are resolved') + expect(page).not_to have_content 'Pipelines must succeed' + expect(page).to have_content 'All discussions must be resolved' within('.sharing-permissions-form') do find('.project-feature-controls[data-for="project[project_feature_attributes][builds_access_level]"] .project-feature-toggle').click find('input[value="Save changes"]').send_keys(:return) end - expect(page).to have_content('Only allow merge requests to be merged if the pipeline succeeds') - expect(page).to have_content('Only allow merge requests to be merged if all discussions are resolved') + expect(page).to have_content 'Pipelines must succeed' + expect(page).to have_content 'All discussions must be resolved' end end end @@ -71,16 +72,16 @@ describe 'Projects > Settings > User manages merge request settings' do end it 'does not show the Merge Requests settings' do - expect(page).not_to have_content('Only allow merge requests to be merged if the pipeline succeeds') - expect(page).not_to have_content('Only allow merge requests to be merged if all discussions are resolved') + expect(page).not_to have_content 'Pipelines must succeed' + expect(page).not_to have_content 'All discussions must be resolved' within('.sharing-permissions-form') do find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .project-feature-toggle').click find('input[value="Save changes"]').send_keys(:return) end - expect(page).to have_content('Only allow merge requests to be merged if the pipeline succeeds') - expect(page).to have_content('Only allow merge requests to be merged if all discussions are resolved') + expect(page).to have_content 'Pipelines must succeed' + expect(page).to have_content 'All discussions must be resolved' end end diff --git a/spec/frontend/clusters/components/application_row_spec.js b/spec/frontend/clusters/components/application_row_spec.js index b28d0075d06..038d2be9e98 100644 --- a/spec/frontend/clusters/components/application_row_spec.js +++ b/spec/frontend/clusters/components/application_row_spec.js @@ -114,10 +114,12 @@ describe('Application Row', () => { expect(vm.installButtonDisabled).toEqual(true); }); - it('has disabled "Installed" when APPLICATION_STATUS.INSTALLED', () => { + it('has disabled "Installed" when application is installed and not uninstallable', () => { vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, status: APPLICATION_STATUS.INSTALLED, + installed: true, + uninstallable: false, }); expect(vm.installButtonLabel).toEqual('Installed'); @@ -125,15 +127,16 @@ describe('Application Row', () => { expect(vm.installButtonDisabled).toEqual(true); }); - it('has disabled "Installed" when APPLICATION_STATUS.UPDATING', () => { + it('hides when application is installed and uninstallable', () => { vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, - status: APPLICATION_STATUS.UPDATING, + status: APPLICATION_STATUS.INSTALLED, + installed: true, + uninstallable: true, }); + const installBtn = vm.$el.querySelector('.js-cluster-application-install-button'); - expect(vm.installButtonLabel).toEqual('Installed'); - expect(vm.installButtonLoading).toEqual(false); - expect(vm.installButtonDisabled).toEqual(true); + expect(installBtn).toBe(null); }); it('has enabled "Install" when APPLICATION_STATUS.ERROR', () => { @@ -208,6 +211,19 @@ describe('Application Row', () => { }); }); + describe('Uninstall button', () => { + it('displays button when app is installed and uninstallable', () => { + vm = mountComponent(ApplicationRow, { + ...DEFAULT_APPLICATION_STATE, + installed: true, + uninstallable: true, + }); + const uninstallButton = vm.$el.querySelector('.js-cluster-application-uninstall-button'); + + expect(uninstallButton).toBeTruthy(); + }); + }); + describe('Upgrade button', () => { it('has indeterminate state on page load', () => { vm = mountComponent(ApplicationRow, { diff --git a/spec/frontend/clusters/stores/clusters_store_spec.js b/spec/frontend/clusters/stores/clusters_store_spec.js index 161722ec571..c0e8b737ea2 100644 --- a/spec/frontend/clusters/stores/clusters_store_spec.js +++ b/spec/frontend/clusters/stores/clusters_store_spec.js @@ -1,5 +1,5 @@ import ClustersStore from '~/clusters/stores/clusters_store'; -import { APPLICATION_STATUS } from '~/clusters/constants'; +import { APPLICATION_INSTALLED_STATUSES, APPLICATION_STATUS, RUNNER } from '~/clusters/constants'; import { CLUSTERS_MOCK_DATA } from '../services/mock_data'; describe('Clusters Store', () => { @@ -70,6 +70,7 @@ describe('Clusters Store', () => { statusReason: mockResponseData.applications[0].status_reason, requestStatus: null, requestReason: null, + installed: false, }, ingress: { title: 'Ingress', @@ -79,6 +80,7 @@ describe('Clusters Store', () => { requestReason: null, externalIp: null, externalHostname: null, + installed: false, }, runner: { title: 'GitLab Runner', @@ -89,6 +91,7 @@ describe('Clusters Store', () => { version: mockResponseData.applications[2].version, upgradeAvailable: mockResponseData.applications[2].update_available, chartRepo: 'https://gitlab.com/charts/gitlab-runner', + installed: false, }, prometheus: { title: 'Prometheus', @@ -96,6 +99,7 @@ describe('Clusters Store', () => { statusReason: mockResponseData.applications[3].status_reason, requestStatus: null, requestReason: null, + installed: false, }, jupyter: { title: 'JupyterHub', @@ -104,6 +108,7 @@ describe('Clusters Store', () => { requestStatus: null, requestReason: null, hostname: '', + installed: false, }, knative: { title: 'Knative', @@ -115,6 +120,7 @@ describe('Clusters Store', () => { isEditingHostName: false, externalIp: null, externalHostname: null, + installed: false, }, cert_manager: { title: 'Cert-Manager', @@ -123,11 +129,26 @@ describe('Clusters Store', () => { requestStatus: null, requestReason: null, email: mockResponseData.applications[6].email, + installed: false, }, }, }); }); + describe.each(APPLICATION_INSTALLED_STATUSES)('given the current app status is %s', () => { + it('marks application as installed', () => { + const mockResponseData = + CLUSTERS_MOCK_DATA.GET['/gitlab-org/gitlab-shell/clusters/2/status.json'].data; + const runnerAppIndex = 2; + + mockResponseData.applications[runnerAppIndex].status = APPLICATION_STATUS.INSTALLED; + + store.updateStateFromServer(mockResponseData); + + expect(store.state.applications[RUNNER].installed).toBe(true); + }); + }); + it('sets default hostname for jupyter when ingress has a ip address', () => { const mockResponseData = CLUSTERS_MOCK_DATA.GET['/gitlab-org/gitlab-shell/clusters/2/status.json'].data; diff --git a/spec/frontend/gfm_auto_complete_spec.js b/spec/frontend/gfm_auto_complete_spec.js index ed12af925f1..841aff0d7ff 100644 --- a/spec/frontend/gfm_auto_complete_spec.js +++ b/spec/frontend/gfm_auto_complete_spec.js @@ -94,7 +94,7 @@ describe('GfmAutoComplete', () => { }); it('should quote if value contains any non-alphanumeric characters', () => { - expect(beforeInsert(atwhoInstance, '~label-20')).toBe('~"label\\-20"'); + expect(beforeInsert(atwhoInstance, '~label-20')).toBe('~"label-20"'); expect(beforeInsert(atwhoInstance, '~label 20')).toBe('~"label 20"'); }); @@ -102,12 +102,21 @@ describe('GfmAutoComplete', () => { expect(beforeInsert(atwhoInstance, '~1234')).toBe('~"1234"'); }); - it('should escape Markdown emphasis characters, except in the first character', () => { - expect(beforeInsert(atwhoInstance, '@_group')).toEqual('@\\_group'); - expect(beforeInsert(atwhoInstance, '~_bug')).toEqual('~\\_bug'); + it('escapes Markdown strikethroughs when needed', () => { + expect(beforeInsert(atwhoInstance, '~a~bug')).toEqual('~"a~bug"'); + expect(beforeInsert(atwhoInstance, '~a~~bug~~')).toEqual('~"a\\~~bug\\~~"'); + }); + + it('escapes Markdown emphasis when needed', () => { + expect(beforeInsert(atwhoInstance, '~a_bug_')).toEqual('~a_bug\\_'); + expect(beforeInsert(atwhoInstance, '~a _bug_')).toEqual('~"a \\_bug\\_"'); + expect(beforeInsert(atwhoInstance, '~a*bug*')).toEqual('~"a\\*bug\\*"'); + expect(beforeInsert(atwhoInstance, '~a *bug*')).toEqual('~"a \\*bug\\*"'); + }); + + it('escapes Markdown code spans when needed', () => { + expect(beforeInsert(atwhoInstance, '~a`bug`')).toEqual('~"a\\`bug\\`"'); expect(beforeInsert(atwhoInstance, '~a `bug`')).toEqual('~"a \\`bug\\`"'); - expect(beforeInsert(atwhoInstance, '~a ~bug')).toEqual('~"a \\~bug"'); - expect(beforeInsert(atwhoInstance, '~a **bug')).toEqual('~"a \\*\\*bug"'); }); }); diff --git a/spec/frontend/notes/components/discussion_actions_spec.js b/spec/frontend/notes/components/discussion_actions_spec.js new file mode 100644 index 00000000000..0a52c81571e --- /dev/null +++ b/spec/frontend/notes/components/discussion_actions_spec.js @@ -0,0 +1,104 @@ +import createStore from '~/notes/stores'; +import { shallowMount, mount, createLocalVue } from '@vue/test-utils'; +import { discussionMock } from '../../../javascripts/notes/mock_data'; +import DiscussionActions from '~/notes/components/discussion_actions.vue'; +import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue'; +import ResolveDiscussionButton from '~/notes/components/discussion_resolve_button.vue'; +import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_issue_button.vue'; +import JumpToNextDiscussionButton from '~/notes/components/discussion_jump_to_next_button.vue'; + +describe('DiscussionActions', () => { + let wrapper; + const createComponentFactory = (shallow = true) => props => { + const localVue = createLocalVue(); + const store = createStore(); + const mountFn = shallow ? shallowMount : mount; + + wrapper = mountFn(DiscussionActions, { + localVue, + store, + propsData: { + discussion: discussionMock, + isResolving: false, + resolveButtonTitle: 'Resolve discussion', + resolveWithIssuePath: '/some/issue/path', + shouldShowJumpToNextDiscussion: true, + ...props, + }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + describe('rendering', () => { + const createComponent = createComponentFactory(); + + it('renders reply placeholder, resolve discussion button, resolve with issue button and jump to next discussion button', () => { + createComponent(); + expect(wrapper.find(ReplyPlaceholder).exists()).toBe(true); + expect(wrapper.find(ResolveDiscussionButton).exists()).toBe(true); + expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(true); + expect(wrapper.find(JumpToNextDiscussionButton).exists()).toBe(true); + }); + + it('only renders reply placholder if disccusion is not resolvable', () => { + const discussion = { ...discussionMock }; + discussion.resolvable = false; + createComponent({ discussion }); + + expect(wrapper.find(ReplyPlaceholder).exists()).toBe(true); + expect(wrapper.find(ResolveDiscussionButton).exists()).toBe(false); + expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(false); + expect(wrapper.find(JumpToNextDiscussionButton).exists()).toBe(false); + }); + + it('does not render resolve with issue button if resolveWithIssuePath is falsy', () => { + createComponent({ resolveWithIssuePath: '' }); + + expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(false); + }); + + it('does not render jump to next discussion button if shouldShowJumpToNextDiscussion is false', () => { + createComponent({ shouldShowJumpToNextDiscussion: false }); + + expect(wrapper.find(JumpToNextDiscussionButton).exists()).toBe(false); + }); + }); + + describe('events handling', () => { + const createComponent = createComponentFactory(false); + + beforeEach(() => { + createComponent(); + }); + + it('emits showReplyForm event when clicking on reply placeholder', () => { + jest.spyOn(wrapper.vm, '$emit'); + wrapper + .find(ReplyPlaceholder) + .find('button') + .trigger('click'); + expect(wrapper.vm.$emit).toHaveBeenCalledWith('showReplyForm'); + }); + + it('emits resolve event when clicking on resolve button', () => { + jest.spyOn(wrapper.vm, '$emit'); + wrapper + .find(ResolveDiscussionButton) + .find('button') + .trigger('click'); + expect(wrapper.vm.$emit).toHaveBeenCalledWith('resolve'); + }); + + it('emits jumpToNextDiscussion event when clicking on jump to next discussion button', () => { + jest.spyOn(wrapper.vm, '$emit'); + wrapper + .find(JumpToNextDiscussionButton) + .find('button') + .trigger('click'); + expect(wrapper.vm.$emit).toHaveBeenCalledWith('jumpToNextDiscussion'); + }); + }); +}); diff --git a/spec/frontend/pages/admin/abuse_reports/abuse_reports_spec.js b/spec/frontend/pages/admin/abuse_reports/abuse_reports_spec.js index 7e9aec84016..f163bdd9913 100644 --- a/spec/frontend/pages/admin/abuse_reports/abuse_reports_spec.js +++ b/spec/frontend/pages/admin/abuse_reports/abuse_reports_spec.js @@ -1,6 +1,9 @@ import $ from 'jquery'; import '~/lib/utils/text_utility'; import AbuseReports from '~/pages/admin/abuse_reports/abuse_reports'; +import { setTestTimeout } from 'helpers/timeout'; + +setTestTimeout(500); describe('Abuse Reports', () => { const FIXTURE = 'abuse_reports/abuse_reports_list.html'; diff --git a/spec/graphql/features/authorization_spec.rb b/spec/graphql/features/authorization_spec.rb index 00e31568a9e..f5eb628a982 100644 --- a/spec/graphql/features/authorization_spec.rb +++ b/spec/graphql/features/authorization_spec.rb @@ -177,6 +177,7 @@ describe 'Gitlab::Graphql::Authorization' do describe 'type authorizations when applied to a relay connection' do let(:query_string) { '{ object() { edges { node { name } } } }' } + let(:second_test_object) { double(name: 'Second thing') } let(:type) do type_factory do |type| @@ -186,22 +187,41 @@ describe 'Gitlab::Graphql::Authorization' do let(:query_type) do query_factory do |query| - query.field :object, type.connection_type, null: true, resolve: ->(obj, args, ctx) { [test_object] } + query.field :object, type.connection_type, null: true, resolve: ->(obj, args, ctx) { [test_object, second_test_object] } end end subject { result.dig('object', 'edges') } - it 'returns the protected field when user has permission' do + it 'returns only the elements visible to the user' do permit(permission_single) - expect(subject).not_to be_empty + expect(subject.size).to eq 1 expect(subject.first['node']).to eq('name' => test_object.name) end it 'returns nil when user is not authorized' do expect(subject).to be_empty end + + describe 'limiting connections with multiple objects' do + let(:query_type) do + query_factory do |query| + query.field :object, type.connection_type, null: true, resolve: ->(obj, args, ctx) do + [test_object, second_test_object] + end + end + end + + let(:query_string) { '{ object(first: 1) { edges { node { name } } } }' } + + it 'only checks permissions for the first object' do + expect(Ability).to receive(:allowed?).with(user, permission_single, test_object) { true } + expect(Ability).not_to receive(:allowed?).with(user, permission_single, second_test_object) + + expect(subject.size).to eq(1) + end + end end describe 'type authorizations when applied to a basic connection' do @@ -222,28 +242,53 @@ describe 'Gitlab::Graphql::Authorization' do include_examples 'authorization with a single permission' end - describe 'when connections do not follow the correct specification' do - let(:query_string) { '{ object() { edges { node { name }} } }' } + describe 'Authorizations on active record relations' do + let!(:visible_project) { create(:project, :private) } + let!(:other_project) { create(:project, :private) } + let!(:visible_issues) { create_list(:issue, 2, project: visible_project) } + let!(:other_issues) { create_list(:issue, 2, project: other_project) } + let!(:user) { visible_project.owner } - let(:type) do - bad_node = type_factory do |type| - type.graphql_name 'BadNode' - type.field :bad_node, GraphQL::STRING_TYPE, null: true + let(:issue_type) do + type_factory do |type| + type.graphql_name 'FakeIssueType' + type.authorize :read_issue + type.field :id, GraphQL::ID_TYPE, null: false end - + end + let(:project_type) do |type| type_factory do |type| - type.field :edges, [bad_node], null: true + type.graphql_name 'FakeProjectType' + type.field :test_issues, issue_type.connection_type, null: false, resolve: -> (_, _, _) { Issue.where(project: [visible_project, other_project]) } end end - let(:query_type) do query_factory do |query| - query.field :object, type, null: true + query.field :test_project, project_type, null: false, resolve: -> (_, _, _) { visible_project } end end + let(:query_string) do + <<~QRY + { testProject { testIssues(first: 3) { edges { node { id } } } } } + QRY + end + + before do + allow(Ability).to receive(:allowed?).and_call_original + end + + it 'renders the issues the user has access to' do + issue_edges = result['testProject']['testIssues']['edges'] + issue_ids = issue_edges.map { |issue_edge| issue_edge['node']&.fetch('id') } + + expect(issue_edges.size).to eq(visible_issues.size) + expect(issue_ids).to eq(visible_issues.map { |i| i.id.to_s }) + end + + it 'does not check access on fields that will not be rendered' do + expect(Ability).not_to receive(:allowed?).with(user, :read_issue, other_issues.last) - it 'throws an error' do - expect { result }.to raise_error(Gitlab::Graphql::Errors::ConnectionDefinitionError) + result end end @@ -276,6 +321,8 @@ describe 'Gitlab::Graphql::Authorization' do def execute_query(query_type) schema = Class.new(GraphQL::Schema) do use Gitlab::Graphql::Authorize + use Gitlab::Graphql::Connections + query(query_type) end diff --git a/spec/graphql/gitlab_schema_spec.rb b/spec/graphql/gitlab_schema_spec.rb index 74e93b2c4df..05f10fb40f0 100644 --- a/spec/graphql/gitlab_schema_spec.rb +++ b/spec/graphql/gitlab_schema_spec.rb @@ -74,6 +74,6 @@ describe GitlabSchema do end def field_instrumenters - described_class.instrumenters[:field] + described_class.instrumenters[:field] + described_class.instrumenters[:field_after_built_ins] end end diff --git a/spec/javascripts/boards/board_list_common_spec.js b/spec/javascripts/boards/board_list_common_spec.js new file mode 100644 index 00000000000..cb337e4cc83 --- /dev/null +++ b/spec/javascripts/boards/board_list_common_spec.js @@ -0,0 +1,58 @@ +/* global List */ +/* global ListIssue */ + +import MockAdapter from 'axios-mock-adapter'; +import Vue from 'vue'; +import axios from '~/lib/utils/axios_utils'; +import Sortable from 'sortablejs'; +import BoardList from '~/boards/components/board_list.vue'; + +import '~/boards/models/issue'; +import '~/boards/models/list'; +import { listObj, boardsMockInterceptor, mockBoardService } from './mock_data'; +import boardsStore from '~/boards/stores/boards_store'; + +window.Sortable = Sortable; + +export default function createComponent({ done, listIssueProps = {}, componentProps = {} }) { + const el = document.createElement('div'); + + document.body.appendChild(el); + const mock = new MockAdapter(axios); + mock.onAny().reply(boardsMockInterceptor); + gl.boardService = mockBoardService(); + boardsStore.create(); + + const BoardListComp = Vue.extend(BoardList); + const list = new List(listObj); + const issue = new ListIssue({ + title: 'Testing', + id: 1, + iid: 1, + confidential: false, + labels: [], + assignees: [], + ...listIssueProps, + }); + list.issuesSize = 1; + list.issues.push(issue); + + const component = new BoardListComp({ + el, + propsData: { + disabled: false, + list, + issues: list.issues, + loading: false, + issueLinkBase: '/issues', + rootPath: '/', + ...componentProps, + }, + }).$mount(); + + Vue.nextTick(() => { + done(); + }); + + return { component, mock }; +} diff --git a/spec/javascripts/boards/board_list_spec.js b/spec/javascripts/boards/board_list_spec.js index 396fc823ef5..9c9b435d7fd 100644 --- a/spec/javascripts/boards/board_list_spec.js +++ b/spec/javascripts/boards/board_list_spec.js @@ -1,60 +1,13 @@ -/* global List */ -/* global ListIssue */ - import Vue from 'vue'; -import MockAdapter from 'axios-mock-adapter'; -import axios from '~/lib/utils/axios_utils'; -import Sortable from 'sortablejs'; -import BoardList from '~/boards/components/board_list.vue'; import eventHub from '~/boards/eventhub'; -import '~/boards/models/issue'; -import '~/boards/models/list'; -import boardsStore from '~/boards/stores/boards_store'; -import { listObj, boardsMockInterceptor, mockBoardService } from './mock_data'; - -window.Sortable = Sortable; +import createComponent from './board_list_common_spec'; describe('Board list component', () => { let mock; let component; beforeEach(done => { - const el = document.createElement('div'); - - document.body.appendChild(el); - mock = new MockAdapter(axios); - mock.onAny().reply(boardsMockInterceptor); - gl.boardService = mockBoardService(); - boardsStore.create(); - - const BoardListComp = Vue.extend(BoardList); - const list = new List(listObj); - const issue = new ListIssue({ - title: 'Testing', - id: 1, - iid: 1, - confidential: false, - labels: [], - assignees: [], - }); - list.issuesSize = 1; - list.issues.push(issue); - - component = new BoardListComp({ - el, - propsData: { - disabled: false, - list, - issues: list.issues, - loading: false, - issueLinkBase: '/issues', - rootPath: '/', - }, - }).$mount(); - - Vue.nextTick(() => { - done(); - }); + ({ mock, component } = createComponent({ done })); }); afterEach(() => { diff --git a/spec/javascripts/boards/issue_card_spec.js b/spec/javascripts/boards/issue_card_spec.js index 6eda5047dd0..a5bf97bdcc2 100644 --- a/spec/javascripts/boards/issue_card_spec.js +++ b/spec/javascripts/boards/issue_card_spec.js @@ -285,4 +285,10 @@ describe('Issue card component', () => { .catch(done.fail); }); }); + + describe('weights', () => { + it('not shows weight component', () => { + expect(component.$el.querySelector('.board-card-weight')).toBeNull(); + }); + }); }); diff --git a/spec/javascripts/monitoring/monitoring_store_spec.js b/spec/javascripts/monitoring/monitoring_store_spec.js index d8a980c874d..5bf6937c92e 100644 --- a/spec/javascripts/monitoring/monitoring_store_spec.js +++ b/spec/javascripts/monitoring/monitoring_store_spec.js @@ -32,4 +32,28 @@ describe('MonitoringStore', () => { it('removes the data if all the values from a query are not defined', () => { expect(store.groups[1].metrics[0].queries[0].result.length).toEqual(0); }); + + it('assigns queries a metric id', () => { + expect(store.groups[1].metrics[0].queries[0].metricId).toEqual('100'); + }); + + it('assigns metric id of null if metric has no id', () => { + const noId = MonitoringMock.data.map(group => ({ + ...group, + ...{ + metrics: group.metrics.map(metric => { + const { id, ...metricWithoutId } = metric; + + return metricWithoutId; + }), + }, + })); + store.storeMetrics(noId); + + store.groups.forEach(group => { + group.metrics.forEach(metric => { + expect(metric.queries.every(query => query.metricId === null)).toBe(true); + }); + }); + }); }); diff --git a/spec/lib/gitlab/correlation_id_spec.rb b/spec/lib/gitlab/correlation_id_spec.rb deleted file mode 100644 index 584d1f48386..00000000000 --- a/spec/lib/gitlab/correlation_id_spec.rb +++ /dev/null @@ -1,77 +0,0 @@ -# frozen_string_literal: true - -require 'fast_spec_helper' - -describe Gitlab::CorrelationId do - describe '.use_id' do - it 'yields when executed' do - expect { |blk| described_class.use_id('id', &blk) }.to yield_control - end - - it 'stacks correlation ids' do - described_class.use_id('id1') do - described_class.use_id('id2') do |current_id| - expect(current_id).to eq('id2') - end - end - end - - it 'for missing correlation id it generates random one' do - described_class.use_id('id1') do - described_class.use_id(nil) do |current_id| - expect(current_id).not_to be_empty - expect(current_id).not_to eq('id1') - end - end - end - end - - describe '.current_id' do - subject { described_class.current_id } - - it 'returns last correlation id' do - described_class.use_id('id1') do - described_class.use_id('id2') do - is_expected.to eq('id2') - end - end - end - end - - describe '.current_or_new_id' do - subject { described_class.current_or_new_id } - - context 'when correlation id is set' do - it 'returns last correlation id' do - described_class.use_id('id1') do - is_expected.to eq('id1') - end - end - end - - context 'when correlation id is missing' do - it 'returns a new correlation id' do - expect(described_class).to receive(:new_id) - .and_call_original - - is_expected.not_to be_empty - end - end - end - - describe '.ids' do - subject { described_class.send(:ids) } - - it 'returns empty list if not correlation is used' do - is_expected.to be_empty - end - - it 'returns list if correlation ids are used' do - described_class.use_id('id1') do - described_class.use_id('id2') do - is_expected.to eq(%w(id1 id2)) - end - end - end - end -end diff --git a/spec/lib/gitlab/graphql/authorize/authorize_field_service_spec.rb b/spec/lib/gitlab/graphql/authorize/authorize_field_service_spec.rb index 6114aca0616..95a4eb296fb 100644 --- a/spec/lib/gitlab/graphql/authorize/authorize_field_service_spec.rb +++ b/spec/lib/gitlab/graphql/authorize/authorize_field_service_spec.rb @@ -5,92 +5,104 @@ require 'spec_helper' # Also see spec/graphql/features/authorization_spec.rb for # integration tests of AuthorizeFieldService describe Gitlab::Graphql::Authorize::AuthorizeFieldService do - describe '#build_checker' do - let(:current_user) { double(:current_user) } - let(:abilities) { [double(:first_ability), double(:last_ability)] } - - context 'when authorizing against the object' do - let(:checker) do - service = described_class.new(double(resolve_proc: proc {})) - allow(service).to receive(:authorizations).and_return(abilities) - service.__send__(:build_checker, current_user, nil) - end + def type(type_authorizations = []) + Class.new(Types::BaseObject) do + graphql_name "TestType" - it 'returns a checker which checks for a single object' do - object = double(:object) + authorize type_authorizations + end + end - abilities.each do |ability| - spy_ability_check_for(ability, object, passed: true) - end + def type_with_field(field_type, field_authorizations = [], resolved_value = "Resolved value") + Class.new(Types::BaseObject) do + graphql_name "TestTypeWithField" + field :test_field, field_type, null: true, authorize: field_authorizations, resolve: -> (_, _, _) { resolved_value} + end + end - expect(checker.call(object)).to eq(object) - end + let(:current_user) { double(:current_user) } + subject(:service) { described_class.new(field) } - it 'returns a checker which checks for all objects' do - objects = [double(:first), double(:last)] + describe "#authorized_resolve" do + let(:presented_object) { double("presented object") } + let(:presented_type) { double("parent type", object: presented_object) } + subject(:resolved) { service.authorized_resolve.call(presented_type, {}, { current_user: current_user }) } - abilities.each do |ability| - objects.each do |object| - spy_ability_check_for(ability, object, passed: true) + context "scalar types" do + shared_examples "checking permissions on the presented object" do + it "checks the abilities on the object being presented and returns the value" do + expected_permissions.each do |permission| + spy_ability_check_for(permission, presented_object, passed: true) end + + expect(resolved).to eq("Resolved value") end - expect(checker.call(objects)).to eq(objects) + it "returns nil if the value wasn't authorized" do + allow(Ability).to receive(:allowed?).and_return false + + expect(resolved).to be_nil + end end - context 'when some objects would not pass the check' do - it 'returns nil when it is single object' do - disallowed = double(:object) + context "when the field is a scalar type" do + let(:field) { type_with_field(GraphQL::STRING_TYPE, :read_field).fields["testField"].to_graphql } + let(:expected_permissions) { [:read_field] } - spy_ability_check_for(abilities.first, disallowed, passed: false) + it_behaves_like "checking permissions on the presented object" + end - expect(checker.call(disallowed)).to be_nil - end + context "when the field is a list of scalar types" do + let(:field) { type_with_field([GraphQL::STRING_TYPE], :read_field).fields["testField"].to_graphql } + let(:expected_permissions) { [:read_field] } - it 'returns only objects which passed when there are more than one' do - allowed = double(:allowed) - disallowed = double(:disallowed) + it_behaves_like "checking permissions on the presented object" + end + end - spy_ability_check_for(abilities.first, disallowed, passed: false) + context "when the field is a specific type" do + let(:custom_type) { type(:read_type) } + let(:object_in_field) { double("presented in field") } + let(:field) { type_with_field(custom_type, :read_field, object_in_field).fields["testField"].to_graphql } - abilities.each do |ability| - spy_ability_check_for(ability, allowed, passed: true) - end + it "checks both field & type permissions" do + spy_ability_check_for(:read_field, object_in_field, passed: true) + spy_ability_check_for(:read_type, object_in_field, passed: true) - expect(checker.call([disallowed, allowed])).to contain_exactly(allowed) - end + expect(resolved).to eq(object_in_field) end - end - context 'when authorizing against another object' do - let(:authorizing_obj) { double(:object) } + it "returns nil if viewing was not allowed" do + spy_ability_check_for(:read_field, object_in_field, passed: false) + spy_ability_check_for(:read_type, object_in_field, passed: true) - let(:checker) do - service = described_class.new(double(resolve_proc: proc {})) - allow(service).to receive(:authorizations).and_return(abilities) - service.__send__(:build_checker, current_user, authorizing_obj) + expect(resolved).to be_nil end - it 'returns a checker which checks for a single object' do - object = double(:object) + context "when the field is a list" do + let(:object_1) { double("presented in field 1") } + let(:object_2) { double("presented in field 2") } + let(:presented_types) { [double(object: object_1), double(object: object_2)] } + let(:field) { type_with_field([custom_type], :read_field, presented_types).fields["testField"].to_graphql } - abilities.each do |ability| - spy_ability_check_for(ability, authorizing_obj, passed: true) + it "checks all permissions" do + allow(Ability).to receive(:allowed?) { true } + + spy_ability_check_for(:read_field, object_1, passed: true) + spy_ability_check_for(:read_type, object_1, passed: true) + spy_ability_check_for(:read_field, object_2, passed: true) + spy_ability_check_for(:read_type, object_2, passed: true) + + expect(resolved).to eq(presented_types) end - expect(checker.call(object)).to eq(object) - end + it "filters out objects that the user cannot see" do + allow(Ability).to receive(:allowed?) { true } - it 'returns a checker which checks for all objects' do - objects = [double(:first), double(:last)] + spy_ability_check_for(:read_type, object_1, passed: false) - abilities.each do |ability| - objects.each do |object| - spy_ability_check_for(ability, authorizing_obj, passed: true) - end + expect(resolved.map(&:object)).to contain_exactly(object_2) end - - expect(checker.call(objects)).to eq(objects) end end end diff --git a/spec/lib/gitlab/graphql/connections/keyset_connection_spec.rb b/spec/lib/gitlab/graphql/connections/keyset_connection_spec.rb index 9bcc1e78a78..fefa2881b18 100644 --- a/spec/lib/gitlab/graphql/connections/keyset_connection_spec.rb +++ b/spec/lib/gitlab/graphql/connections/keyset_connection_spec.rb @@ -85,6 +85,11 @@ describe Gitlab::Graphql::Connections::KeysetConnection do expect(subject.paged_nodes.size).to eq(3) end + it 'is a loaded memoized array' do + expect(subject.paged_nodes).to be_an(Array) + expect(subject.paged_nodes.object_id).to eq(subject.paged_nodes.object_id) + end + context 'when `first` is passed' do let(:arguments) { { first: 2 } } diff --git a/spec/lib/gitlab/json_logger_spec.rb b/spec/lib/gitlab/json_logger_spec.rb index cff7dd58c8c..d3d9fe9948a 100644 --- a/spec/lib/gitlab/json_logger_spec.rb +++ b/spec/lib/gitlab/json_logger_spec.rb @@ -8,7 +8,7 @@ describe Gitlab::JsonLogger do describe '#format_message' do before do - allow(Gitlab::CorrelationId).to receive(:current_id).and_return('new-correlation-id') + allow(Labkit::Correlation::CorrelationId).to receive(:current_id).and_return('new-correlation-id') end it 'formats strings' do diff --git a/spec/lib/gitlab/sentry_spec.rb b/spec/lib/gitlab/sentry_spec.rb index 1128eaf8560..ae522a588ee 100644 --- a/spec/lib/gitlab/sentry_spec.rb +++ b/spec/lib/gitlab/sentry_spec.rb @@ -27,7 +27,7 @@ describe Gitlab::Sentry do context 'when exceptions should not be raised' do before do allow(described_class).to receive(:should_raise_for_dev?).and_return(false) - allow(Gitlab::CorrelationId).to receive(:current_id).and_return('cid') + allow(Labkit::Correlation::CorrelationId).to receive(:current_id).and_return('cid') end it 'logs the exception with all attributes passed' do @@ -65,7 +65,7 @@ describe Gitlab::Sentry do before do allow(described_class).to receive(:enabled?).and_return(true) - allow(Gitlab::CorrelationId).to receive(:current_id).and_return('cid') + allow(Labkit::Correlation::CorrelationId).to receive(:current_id).and_return('cid') end it 'calls Raven.capture_exception' do diff --git a/spec/lib/gitlab/sidekiq_middleware/correlation_injector_spec.rb b/spec/lib/gitlab/sidekiq_middleware/correlation_injector_spec.rb index a138ad7c910..0ff694d409b 100644 --- a/spec/lib/gitlab/sidekiq_middleware/correlation_injector_spec.rb +++ b/spec/lib/gitlab/sidekiq_middleware/correlation_injector_spec.rb @@ -30,7 +30,7 @@ describe Gitlab::SidekiqMiddleware::CorrelationInjector do it 'injects into payload the correlation id' do expect_any_instance_of(described_class).to receive(:call).and_call_original - Gitlab::CorrelationId.use_id('new-correlation-id') do + Labkit::Correlation::CorrelationId.use_id('new-correlation-id') do TestWorker.perform_async(1234) end diff --git a/spec/lib/gitlab/sidekiq_middleware/correlation_logger_spec.rb b/spec/lib/gitlab/sidekiq_middleware/correlation_logger_spec.rb index 94ae4ffa184..8410467ef1f 100644 --- a/spec/lib/gitlab/sidekiq_middleware/correlation_logger_spec.rb +++ b/spec/lib/gitlab/sidekiq_middleware/correlation_logger_spec.rb @@ -23,7 +23,7 @@ describe Gitlab::SidekiqMiddleware::CorrelationLogger do expect_any_instance_of(described_class).to receive(:call).and_call_original expect_any_instance_of(TestWorker).to receive(:perform).with(1234) do - expect(Gitlab::CorrelationId.current_id).to eq('new-correlation-id') + expect(Labkit::Correlation::CorrelationId.current_id).to eq('new-correlation-id') end Sidekiq::Client.push( diff --git a/spec/lib/gitlab/tracing/factory_spec.rb b/spec/lib/gitlab/tracing/factory_spec.rb deleted file mode 100644 index 945490f0988..00000000000 --- a/spec/lib/gitlab/tracing/factory_spec.rb +++ /dev/null @@ -1,43 +0,0 @@ -# frozen_string_literal: true - -require 'fast_spec_helper' - -describe Gitlab::Tracing::Factory do - describe '.create_tracer' do - let(:service_name) { 'rspec' } - - context "when tracing is not configured" do - it 'ignores null connection strings' do - expect(described_class.create_tracer(service_name, nil)).to be_nil - end - - it 'ignores empty connection strings' do - expect(described_class.create_tracer(service_name, '')).to be_nil - end - - it 'ignores unknown implementations' do - expect(described_class.create_tracer(service_name, 'opentracing://invalid_driver')).to be_nil - end - - it 'ignores invalid connection strings' do - expect(described_class.create_tracer(service_name, 'open?tracing')).to be_nil - end - end - - context "when tracing is configured with jaeger" do - let(:mock_tracer) { double('tracer') } - - it 'processes default connections' do - expect(Gitlab::Tracing::JaegerFactory).to receive(:create_tracer).with(service_name, {}).and_return(mock_tracer) - - expect(described_class.create_tracer(service_name, 'opentracing://jaeger')).to be(mock_tracer) - end - - it 'processes connections with parameters' do - expect(Gitlab::Tracing::JaegerFactory).to receive(:create_tracer).with(service_name, { a: '1', b: '2', c: '3' }).and_return(mock_tracer) - - expect(described_class.create_tracer(service_name, 'opentracing://jaeger?a=1&b=2&c=3')).to be(mock_tracer) - end - end - end -end diff --git a/spec/lib/gitlab/tracing/grpc_interceptor_spec.rb b/spec/lib/gitlab/tracing/grpc_interceptor_spec.rb deleted file mode 100644 index 7f5aecb7baa..00000000000 --- a/spec/lib/gitlab/tracing/grpc_interceptor_spec.rb +++ /dev/null @@ -1,47 +0,0 @@ -# frozen_string_literal: true - -require 'fast_spec_helper' - -describe Gitlab::Tracing::GRPCInterceptor do - subject { described_class.instance } - - shared_examples_for "a grpc interceptor method" do - let(:custom_error) { Class.new(StandardError) } - - it 'yields' do - expect { |b| method.call(kwargs, &b) }.to yield_control - end - - it 'propagates exceptions' do - expect { method.call(kwargs) { raise custom_error } }.to raise_error(custom_error) - end - end - - describe '#request_response' do - let(:method) { subject.method(:request_response) } - let(:kwargs) { { request: {}, call: {}, method: 'grc_method', metadata: {} } } - - it_behaves_like 'a grpc interceptor method' - end - - describe '#client_streamer' do - let(:method) { subject.method(:client_streamer) } - let(:kwargs) { { requests: [], call: {}, method: 'grc_method', metadata: {} } } - - it_behaves_like 'a grpc interceptor method' - end - - describe '#server_streamer' do - let(:method) { subject.method(:server_streamer) } - let(:kwargs) { { request: {}, call: {}, method: 'grc_method', metadata: {} } } - - it_behaves_like 'a grpc interceptor method' - end - - describe '#bidi_streamer' do - let(:method) { subject.method(:bidi_streamer) } - let(:kwargs) { { requests: [], call: {}, method: 'grc_method', metadata: {} } } - - it_behaves_like 'a grpc interceptor method' - end -end diff --git a/spec/lib/gitlab/tracing/jaeger_factory_spec.rb b/spec/lib/gitlab/tracing/jaeger_factory_spec.rb deleted file mode 100644 index 3d6a007cfd9..00000000000 --- a/spec/lib/gitlab/tracing/jaeger_factory_spec.rb +++ /dev/null @@ -1,71 +0,0 @@ -# frozen_string_literal: true - -require 'fast_spec_helper' - -describe Gitlab::Tracing::JaegerFactory do - describe '.create_tracer' do - let(:service_name) { 'rspec' } - - shared_examples_for 'a jaeger tracer' do - it 'responds to active_span methods' do - expect(tracer).to respond_to(:active_span) - end - - it 'yields control' do - expect { |b| tracer.start_active_span('operation_name', &b) }.to yield_control - end - end - - context 'processes default connections' do - it_behaves_like 'a jaeger tracer' do - let(:tracer) { described_class.create_tracer(service_name, {}) } - end - end - - context 'handles debug options' do - it_behaves_like 'a jaeger tracer' do - let(:tracer) { described_class.create_tracer(service_name, { debug: "1" }) } - end - end - - context 'handles const sampler' do - it_behaves_like 'a jaeger tracer' do - let(:tracer) { described_class.create_tracer(service_name, { sampler: "const", sampler_param: "1" }) } - end - end - - context 'handles probabilistic sampler' do - it_behaves_like 'a jaeger tracer' do - let(:tracer) { described_class.create_tracer(service_name, { sampler: "probabilistic", sampler_param: "0.5" }) } - end - end - - context 'handles http_endpoint configurations' do - it_behaves_like 'a jaeger tracer' do - let(:tracer) { described_class.create_tracer(service_name, { http_endpoint: "http://localhost:1234" }) } - end - end - - context 'handles udp_endpoint configurations' do - it_behaves_like 'a jaeger tracer' do - let(:tracer) { described_class.create_tracer(service_name, { udp_endpoint: "localhost:4321" }) } - end - end - - context 'ignores invalid parameters' do - it_behaves_like 'a jaeger tracer' do - let(:tracer) { described_class.create_tracer(service_name, { invalid: "true" }) } - end - end - - context 'accepts the debug parameter when strict_parser is set' do - it_behaves_like 'a jaeger tracer' do - let(:tracer) { described_class.create_tracer(service_name, { debug: "1", strict_parsing: "1" }) } - end - end - - it 'rejects invalid parameters when strict_parser is set' do - expect { described_class.create_tracer(service_name, { invalid: "true", strict_parsing: "1" }) }.to raise_error(StandardError) - end - end -end diff --git a/spec/lib/gitlab/tracing/rack_middleware_spec.rb b/spec/lib/gitlab/tracing/rack_middleware_spec.rb deleted file mode 100644 index 13d4d8a89f7..00000000000 --- a/spec/lib/gitlab/tracing/rack_middleware_spec.rb +++ /dev/null @@ -1,62 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe Gitlab::Tracing::RackMiddleware do - using RSpec::Parameterized::TableSyntax - - describe '#call' do - context 'for normal middleware flow' do - let(:fake_app) { -> (env) { fake_app_response } } - subject { described_class.new(fake_app) } - let(:request) { } - - context 'for 200 responses' do - let(:fake_app_response) { [200, { 'Content-Type': 'text/plain' }, ['OK']] } - - it 'delegates correctly' do - expect(subject.call(Rack::MockRequest.env_for("/"))).to eq(fake_app_response) - end - end - - context 'for 500 responses' do - let(:fake_app_response) { [500, { 'Content-Type': 'text/plain' }, ['Error']] } - - it 'delegates correctly' do - expect(subject.call(Rack::MockRequest.env_for("/"))).to eq(fake_app_response) - end - end - end - - context 'when an application is raising an exception' do - let(:custom_error) { Class.new(StandardError) } - let(:fake_app) { ->(env) { raise custom_error } } - - subject { described_class.new(fake_app) } - - it 'delegates propagates exceptions correctly' do - expect { subject.call(Rack::MockRequest.env_for("/")) }.to raise_error(custom_error) - end - end - end - - describe '.build_sanitized_url_from_env' do - def env_for_url(url) - env = Rack::MockRequest.env_for(input_url) - env['action_dispatch.parameter_filter'] = [/token/] - - env - end - - where(:input_url, :output_url) do - '/gitlab-org/gitlab-ce' | 'http://example.org/gitlab-org/gitlab-ce' - '/gitlab-org/gitlab-ce?safe=1' | 'http://example.org/gitlab-org/gitlab-ce?safe=1' - '/gitlab-org/gitlab-ce?private_token=secret' | 'http://example.org/gitlab-org/gitlab-ce?private_token=%5BFILTERED%5D' - '/gitlab-org/gitlab-ce?mixed=1&private_token=secret' | 'http://example.org/gitlab-org/gitlab-ce?mixed=1&private_token=%5BFILTERED%5D' - end - - with_them do - it { expect(described_class.build_sanitized_url_from_env(env_for_url(input_url))).to eq(output_url) } - end - end -end diff --git a/spec/lib/gitlab/tracing/rails/action_view_subscriber_spec.rb b/spec/lib/gitlab/tracing/rails/action_view_subscriber_spec.rb deleted file mode 100644 index 0bbaf5968ed..00000000000 --- a/spec/lib/gitlab/tracing/rails/action_view_subscriber_spec.rb +++ /dev/null @@ -1,147 +0,0 @@ -# frozen_string_literal: true - -require 'fast_spec_helper' -require 'rspec-parameterized' - -describe Gitlab::Tracing::Rails::ActionViewSubscriber do - using RSpec::Parameterized::TableSyntax - - shared_examples 'an actionview notification' do - it 'notifies the tracer when the hash contains null values' do - expect(subject).to receive(:postnotify_span).with(notification_name, start, finish, tags: expected_tags, exception: exception) - - subject.public_send(notify_method, start, finish, payload) - end - - it 'notifies the tracer when the payload is missing values' do - expect(subject).to receive(:postnotify_span).with(notification_name, start, finish, tags: expected_tags, exception: exception) - - subject.public_send(notify_method, start, finish, payload.compact) - end - - it 'does not throw exceptions when with the default tracer' do - expect { subject.public_send(notify_method, start, finish, payload) }.not_to raise_error - end - end - - describe '.instrument' do - it 'is unsubscribeable' do - unsubscribe = described_class.instrument - - expect(unsubscribe).not_to be_nil - expect { unsubscribe.call }.not_to raise_error - end - end - - describe '#notify_render_template' do - subject { described_class.new } - let(:start) { Time.now } - let(:finish) { Time.now } - let(:notification_name) { 'render_template' } - let(:notify_method) { :notify_render_template } - - where(:identifier, :layout, :exception) do - nil | nil | nil - "" | nil | nil - "show.haml" | nil | nil - nil | "" | nil - nil | "layout.haml" | nil - nil | nil | StandardError.new - end - - with_them do - let(:payload) do - { - exception: exception, - identifier: identifier, - layout: layout - } - end - - let(:expected_tags) do - { - 'component' => 'ActionView', - 'template.id' => identifier, - 'template.layout' => layout - } - end - - it_behaves_like 'an actionview notification' - end - end - - describe '#notify_render_collection' do - subject { described_class.new } - let(:start) { Time.now } - let(:finish) { Time.now } - let(:notification_name) { 'render_collection' } - let(:notify_method) { :notify_render_collection } - - where( - :identifier, :count, :expected_count, :cache_hits, :expected_cache_hits, :exception) do - nil | nil | 0 | nil | 0 | nil - "" | nil | 0 | nil | 0 | nil - "show.haml" | nil | 0 | nil | 0 | nil - nil | 0 | 0 | nil | 0 | nil - nil | 1 | 1 | nil | 0 | nil - nil | nil | 0 | 0 | 0 | nil - nil | nil | 0 | 1 | 1 | nil - nil | nil | 0 | nil | 0 | StandardError.new - end - - with_them do - let(:payload) do - { - exception: exception, - identifier: identifier, - count: count, - cache_hits: cache_hits - } - end - - let(:expected_tags) do - { - 'component' => 'ActionView', - 'template.id' => identifier, - 'template.count' => expected_count, - 'template.cache.hits' => expected_cache_hits - } - end - - it_behaves_like 'an actionview notification' - end - end - - describe '#notify_render_partial' do - subject { described_class.new } - let(:start) { Time.now } - let(:finish) { Time.now } - let(:notification_name) { 'render_partial' } - let(:notify_method) { :notify_render_partial } - - where(:identifier, :exception) do - nil | nil - "" | nil - "show.haml" | nil - nil | StandardError.new - end - - with_them do - let(:payload) do - { - exception: exception, - identifier: identifier - } - end - - let(:expected_tags) do - { - 'component' => 'ActionView', - 'template.id' => identifier - } - end - - it_behaves_like 'an actionview notification' - end - end -end diff --git a/spec/lib/gitlab/tracing/rails/active_record_subscriber_spec.rb b/spec/lib/gitlab/tracing/rails/active_record_subscriber_spec.rb deleted file mode 100644 index 7bd0875fa68..00000000000 --- a/spec/lib/gitlab/tracing/rails/active_record_subscriber_spec.rb +++ /dev/null @@ -1,73 +0,0 @@ -# frozen_string_literal: true - -require 'fast_spec_helper' -require 'rspec-parameterized' - -describe Gitlab::Tracing::Rails::ActiveRecordSubscriber do - using RSpec::Parameterized::TableSyntax - - describe '.instrument' do - it 'is unsubscribeable' do - unsubscribe = described_class.instrument - - expect(unsubscribe).not_to be_nil - expect { unsubscribe.call }.not_to raise_error - end - end - - describe '#notify' do - subject { described_class.new } - let(:start) { Time.now } - let(:finish) { Time.now } - - where(:name, :operation_name, :exception, :connection_id, :cached, :cached_response, :sql) do - nil | "active_record:sqlquery" | nil | nil | nil | false | nil - "" | "active_record:sqlquery" | nil | nil | nil | false | nil - "User Load" | "active_record:User Load" | nil | nil | nil | false | nil - "Repo Load" | "active_record:Repo Load" | StandardError.new | nil | nil | false | nil - nil | "active_record:sqlquery" | nil | 123 | nil | false | nil - nil | "active_record:sqlquery" | nil | nil | false | false | nil - nil | "active_record:sqlquery" | nil | nil | true | true | nil - nil | "active_record:sqlquery" | nil | nil | true | true | "SELECT * FROM users" - end - - with_them do - def payload - { - name: name, - exception: exception, - connection_id: connection_id, - cached: cached, - sql: sql - } - end - - def expected_tags - { - "component" => "ActiveRecord", - "span.kind" => "client", - "db.type" => "sql", - "db.connection_id" => connection_id, - "db.cached" => cached_response, - "db.statement" => sql - } - end - - it 'notifies the tracer when the hash contains null values' do - expect(subject).to receive(:postnotify_span).with(operation_name, start, finish, tags: expected_tags, exception: exception) - - subject.notify(start, finish, payload) - end - - it 'notifies the tracer when the payload is missing values' do - expect(subject).to receive(:postnotify_span).with(operation_name, start, finish, tags: expected_tags, exception: exception) - - subject.notify(start, finish, payload.compact) - end - - it 'does not throw exceptions when with the default tracer' do - expect { subject.notify(start, finish, payload) }.not_to raise_error - end - end - end -end diff --git a/spec/lib/gitlab/tracing/sidekiq/client_middleware_spec.rb b/spec/lib/gitlab/tracing/sidekiq/client_middleware_spec.rb deleted file mode 100644 index 3755860b5ba..00000000000 --- a/spec/lib/gitlab/tracing/sidekiq/client_middleware_spec.rb +++ /dev/null @@ -1,43 +0,0 @@ -# frozen_string_literal: true - -require 'fast_spec_helper' - -describe Gitlab::Tracing::Sidekiq::ClientMiddleware do - describe '#call' do - let(:worker_class) { 'test_worker_class' } - let(:job) do - { - 'class' => "jobclass", - 'queue' => "jobqueue", - 'retry' => 0, - 'args' => %w{1 2 3} - } - end - let(:queue) { 'test_queue' } - let(:redis_pool) { double("redis_pool") } - let(:custom_error) { Class.new(StandardError) } - let(:span) { OpenTracing.start_span('test', ignore_active_scope: true) } - - subject { described_class.new } - - it 'yields' do - expect(subject).to receive(:in_tracing_span).with( - operation_name: "sidekiq:jobclass", - tags: { - "component" => "sidekiq", - "span.kind" => "client", - "sidekiq.queue" => "jobqueue", - "sidekiq.jid" => nil, - "sidekiq.retry" => "0", - "sidekiq.args" => "1, 2, 3" - } - ).and_yield(span) - - expect { |b| subject.call(worker_class, job, queue, redis_pool, &b) }.to yield_control - end - - it 'propagates exceptions' do - expect { subject.call(worker_class, job, queue, redis_pool) { raise custom_error } }.to raise_error(custom_error) - end - end -end diff --git a/spec/lib/gitlab/tracing/sidekiq/server_middleware_spec.rb b/spec/lib/gitlab/tracing/sidekiq/server_middleware_spec.rb deleted file mode 100644 index c3087de785a..00000000000 --- a/spec/lib/gitlab/tracing/sidekiq/server_middleware_spec.rb +++ /dev/null @@ -1,43 +0,0 @@ -# frozen_string_literal: true - -require 'fast_spec_helper' - -describe Gitlab::Tracing::Sidekiq::ServerMiddleware do - describe '#call' do - let(:worker_class) { 'test_worker_class' } - let(:job) do - { - 'class' => "jobclass", - 'queue' => "jobqueue", - 'retry' => 0, - 'args' => %w{1 2 3} - } - end - let(:queue) { 'test_queue' } - let(:custom_error) { Class.new(StandardError) } - let(:span) { OpenTracing.start_span('test', ignore_active_scope: true) } - subject { described_class.new } - - it 'yields' do - expect(subject).to receive(:in_tracing_span).with( - hash_including( - operation_name: "sidekiq:jobclass", - tags: { - "component" => "sidekiq", - "span.kind" => "server", - "sidekiq.queue" => "jobqueue", - "sidekiq.jid" => nil, - "sidekiq.retry" => "0", - "sidekiq.args" => "1, 2, 3" - } - ) - ).and_yield(span) - - expect { |b| subject.call(worker_class, job, queue, &b) }.to yield_control - end - - it 'propagates exceptions' do - expect { subject.call(worker_class, job, queue) { raise custom_error } }.to raise_error(custom_error) - end - end -end diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 66be192ab21..95b9bd4a4d9 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -31,6 +31,10 @@ describe Ci::Build do it { is_expected.to be_a(ArtifactMigratable) } + it_behaves_like 'UpdateProjectStatistics' do + subject { FactoryBot.build(:ci_build, pipeline: pipeline, artifacts_size: 23) } + end + describe 'associations' do it 'has a bidirectional relationship with projects' do expect(described_class.reflect_on_association(:project).has_inverse?).to eq(:builds) @@ -2119,54 +2123,6 @@ describe Ci::Build do end end - context 'when updating the build' do - let(:build) { create(:ci_build, artifacts_size: 23) } - - it 'updates project statistics' do - build.artifacts_size = 42 - - expect(build).to receive(:update_project_statistics_after_save).and_call_original - - expect { build.save! } - .to change { build.project.statistics.reload.build_artifacts_size } - .by(19) - end - - context 'when the artifact size stays the same' do - it 'does not update project statistics' do - build.name = 'changed' - - expect(build).not_to receive(:update_project_statistics_after_save) - - build.save! - end - end - end - - context 'when destroying the build' do - let!(:build) { create(:ci_build, artifacts_size: 23) } - - it 'updates project statistics' do - expect(ProjectStatistics) - .to receive(:increment_statistic) - .and_call_original - - expect { build.destroy! } - .to change { build.project.statistics.reload.build_artifacts_size } - .by(-23) - end - - context 'when the build is destroyed due to the project being destroyed' do - it 'does not update the project statistics' do - expect(ProjectStatistics) - .not_to receive(:increment_statistic) - - build.project.update(pending_delete: true) - build.project.destroy! - end - end - end - describe '#variables' do let(:container_registry_enabled) { false } diff --git a/spec/models/ci/job_artifact_spec.rb b/spec/models/ci/job_artifact_spec.rb index d7abd54eec1..5964f66c398 100644 --- a/spec/models/ci/job_artifact_spec.rb +++ b/spec/models/ci/job_artifact_spec.rb @@ -5,6 +5,10 @@ require 'spec_helper' describe Ci::JobArtifact do let(:artifact) { create(:ci_job_artifact, :archive) } + it_behaves_like 'UpdateProjectStatistics' do + subject { build(:ci_job_artifact, :archive, size: 106365) } + end + describe "Associations" do it { is_expected.to belong_to(:project) } it { is_expected.to belong_to(:job) } @@ -102,12 +106,6 @@ describe Ci::JobArtifact do it 'sets the size from the file size' do expect(artifact.size).to eq(106365) end - - it 'updates the project statistics' do - expect { artifact } - .to change { project.statistics.reload.build_artifacts_size } - .by(106365) - end end context 'updating the artifact file' do @@ -115,12 +113,6 @@ describe Ci::JobArtifact do artifact.update!(file: fixture_file_upload('spec/fixtures/dk.png')) expect(artifact.size).to eq(1062) end - - it 'updates the project statistics' do - expect { artifact.update!(file: fixture_file_upload('spec/fixtures/dk.png')) } - .to change { artifact.project.statistics.reload.build_artifacts_size } - .by(1062 - 106365) - end end describe 'validates file format' do @@ -259,34 +251,6 @@ describe Ci::JobArtifact do end end - context 'when destroying the artifact' do - let(:project) { create(:project, :repository) } - let(:pipeline) { create(:ci_pipeline, project: project) } - let!(:build) { create(:ci_build, :artifacts, pipeline: pipeline) } - - it 'updates the project statistics' do - artifact = build.job_artifacts.first - - expect(ProjectStatistics) - .to receive(:increment_statistic) - .and_call_original - - expect { artifact.destroy } - .to change { project.statistics.reload.build_artifacts_size } - .by(-106365) - end - - context 'when it is destroyed from the project level' do - it 'does not update the project statistics' do - expect(ProjectStatistics) - .not_to receive(:increment_statistic) - - project.update(pending_delete: true) - project.destroy! - end - end - end - describe 'file is being stored' do subject { create(:ci_job_artifact, :archive) } diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb index 387d1221c76..95a4b0f6d71 100644 --- a/spec/models/namespace_spec.rb +++ b/spec/models/namespace_spec.rb @@ -63,6 +63,11 @@ describe Namespace do end end + describe 'delegate' do + it { is_expected.to delegate_method(:name).to(:owner).with_prefix.with_arguments(allow_nil: true) } + it { is_expected.to delegate_method(:avatar_url).to(:owner).with_arguments(allow_nil: true) } + end + describe "Respond to" do it { is_expected.to respond_to(:human_name) } it { is_expected.to respond_to(:to_param) } @@ -801,4 +806,21 @@ describe Namespace do end end end + + describe '#user?' do + subject { namespace.user? } + + context 'when type is a user' do + let(:user) { create(:user) } + let(:namespace) { user.namespace } + + it { is_expected.to be_truthy } + end + + context 'when type is a group' do + let(:namespace) { create(:group) } + + it { is_expected.to be_falsy } + end + end end diff --git a/spec/requests/api/graphql/project/issues_spec.rb b/spec/requests/api/graphql/project/issues_spec.rb index c2934430821..4f9f916f22e 100644 --- a/spec/requests/api/graphql/project/issues_spec.rb +++ b/spec/requests/api/graphql/project/issues_spec.rb @@ -7,8 +7,8 @@ describe 'getting an issue list for a project' do let(:current_user) { create(:user) } let(:issues_data) { graphql_data['project']['issues']['edges'] } let!(:issues) do - create(:issue, project: project, discussion_locked: true) - create(:issue, project: project) + [create(:issue, project: project, discussion_locked: true), + create(:issue, project: project)] end let(:fields) do <<~QUERY @@ -47,6 +47,30 @@ describe 'getting an issue list for a project' do expect(issues_data[1]['node']['discussionLocked']).to eq true end + context 'when limiting the number of results' do + let(:query) do + graphql_query_for( + 'project', + { 'fullPath' => project.full_path }, + "issues(first: 1) { #{fields} }" + ) + end + + it_behaves_like 'a working graphql query' do + before do + post_graphql(query, current_user: current_user) + end + end + + it "is expected to check permissions on the first issue only" do + allow(Ability).to receive(:allowed?).and_call_original + # Newest first, we only want to see the newest checked + expect(Ability).not_to receive(:allowed?).with(current_user, :read_issue, issues.first) + + post_graphql(query, current_user: current_user) + end + end + context 'when the user does not have access to the issue' do it 'returns nil' do project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE) diff --git a/spec/requests/api/helpers_spec.rb b/spec/requests/api/helpers_spec.rb index a0c64d295c0..25a312cb734 100644 --- a/spec/requests/api/helpers_spec.rb +++ b/spec/requests/api/helpers_spec.rb @@ -251,7 +251,7 @@ describe API::Helpers do correlation_id: 'new-correlation-id' }, extra: {}) - Gitlab::CorrelationId.use_id('new-correlation-id') do + Labkit::Correlation::CorrelationId.use_id('new-correlation-id') do handle_api_exception(exception) end end diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 352ea448c00..577f61ae8d0 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -1047,7 +1047,6 @@ describe API::Projects do expect(json_response['http_url_to_repo']).to be_present expect(json_response['web_url']).to be_present expect(json_response['owner']).to be_a Hash - expect(json_response['owner']).to be_a Hash expect(json_response['name']).to eq(project.name) expect(json_response['path']).to be_present expect(json_response['issues_enabled']).to be_present @@ -1135,7 +1134,9 @@ describe API::Projects do 'path' => user.namespace.path, 'kind' => user.namespace.kind, 'full_path' => user.namespace.full_path, - 'parent_id' => nil + 'parent_id' => nil, + 'avatar_url' => user.avatar_url, + 'web_url' => Gitlab::Routing.url_helpers.user_url(user) }) end @@ -1337,6 +1338,37 @@ describe API::Projects do end end end + + context 'when project belongs to a group namespace' do + let(:group) { create(:group, :with_avatar) } + let(:project) { create(:project, namespace: group) } + let!(:project_member) { create(:project_member, :developer, user: user, project: project) } + + it 'returns group web_url and avatar_url' do + get api("/projects/#{project.id}", user) + + expect(response).to have_gitlab_http_status(200) + + group_data = json_response['namespace'] + expect(group_data['web_url']).to eq(group.web_url) + expect(group_data['avatar_url']).to eq(group.avatar_url) + end + end + + context 'when project belongs to a user namespace' do + let(:user) { create(:user) } + let(:project) { create(:project, namespace: user.namespace) } + + it 'returns user web_url and avatar_url' do + get api("/projects/#{project.id}", user) + + expect(response).to have_gitlab_http_status(200) + + user_data = json_response['namespace'] + expect(user_data['web_url']).to eq("http://localhost/#{user.username}") + expect(user_data['avatar_url']).to eq(user.avatar_url) + end + end end context 'with external authorization' do diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb index 3585a827838..29515709a74 100644 --- a/spec/requests/api/runner_spec.rb +++ b/spec/requests/api/runner_spec.rb @@ -168,6 +168,32 @@ describe API::Runner, :clean_gitlab_redis_shared_state do end end + context 'when access_level is provided for Runner' do + context 'when access_level is set to ref_protected' do + it 'creates runner' do + post api('/runners'), params: { + token: registration_token, + access_level: 'ref_protected' + } + + expect(response).to have_gitlab_http_status 201 + expect(Ci::Runner.first.ref_protected?).to be true + end + end + + context 'when access_level is set to not_protected' do + it 'creates runner' do + post api('/runners'), params: { + token: registration_token, + access_level: 'not_protected' + } + + expect(response).to have_gitlab_http_status 201 + expect(Ci::Runner.first.ref_protected?).to be false + end + end + end + context 'when maximum job timeout is specified' do it 'creates runner' do post api('/runners'), params: { diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 60db3e1bc46..8ca4c172707 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -83,6 +83,7 @@ RSpec.configure do |config| config.include Devise::Test::IntegrationHelpers, type: :feature config.include LoginHelpers, type: :feature config.include SearchHelpers, type: :feature + config.include WaitHelpers, type: :feature config.include EmailHelpers, :mailer, type: :mailer config.include Warden::Test::Helpers, type: :request config.include Gitlab::Routing, type: :routing diff --git a/spec/support/helpers/wait_for_requests.rb b/spec/support/helpers/wait_for_requests.rb index c7f878b7371..45b9faa0fea 100644 --- a/spec/support/helpers/wait_for_requests.rb +++ b/spec/support/helpers/wait_for_requests.rb @@ -50,20 +50,6 @@ module WaitForRequests finished_all_vue_resource_requests? end - # Waits until the passed block returns true - def wait_for(condition_name, max_wait_time: Capybara.default_max_wait_time, polling_interval: 0.01) - wait_until = Time.now + max_wait_time.seconds - loop do - break if yield - - if Time.now > wait_until - raise "Condition not met: #{condition_name}" - else - sleep(polling_interval) - end - end - end - def finished_all_vue_resource_requests? Capybara.page.evaluate_script('window.activeVueResources || 0').zero? end diff --git a/spec/support/helpers/wait_helpers.rb b/spec/support/helpers/wait_helpers.rb new file mode 100644 index 00000000000..7e8e25798e8 --- /dev/null +++ b/spec/support/helpers/wait_helpers.rb @@ -0,0 +1,20 @@ +module WaitHelpers + extend self + + # Waits until the passed block returns true + def wait_for(condition_name, max_wait_time: Capybara.default_max_wait_time, polling_interval: 0.01, reload: false) + wait_until = Time.now + max_wait_time.seconds + loop do + result = yield + break if result + + page.refresh if reload + + if Time.now > wait_until + raise "Condition not met: #{condition_name}" + else + sleep(polling_interval) + end + end + end +end diff --git a/spec/support/shared_examples/models/update_project_statistics_spec.rb b/spec/support/shared_examples/models/update_project_statistics_spec.rb new file mode 100644 index 00000000000..7a04e940ee5 --- /dev/null +++ b/spec/support/shared_examples/models/update_project_statistics_spec.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true + +require 'spec_helper' + +shared_examples_for 'UpdateProjectStatistics' do + let(:project) { subject.project } + let(:stat) { described_class.statistic_name } + let(:attribute) { described_class.statistic_attribute } + + def reload_stat + project.statistics.reload.send(stat).to_i + end + + def read_attribute + subject.read_attribute(attribute).to_i + end + + it { is_expected.to be_new_record } + + context 'when creating' do + it 'updates the project statistics' do + delta = read_attribute + + expect { subject.save! } + .to change { reload_stat } + .by(delta) + end + end + + context 'when updating' do + before do + subject.save! + end + + it 'updates project statistics' do + delta = 42 + + expect(ProjectStatistics) + .to receive(:increment_statistic) + .and_call_original + + subject.write_attribute(attribute, read_attribute + delta) + expect { subject.save! } + .to change { reload_stat } + .by(delta) + end + end + + context 'when destroying' do + before do + subject.save! + end + + it 'updates the project statistics' do + delta = -read_attribute + + expect(ProjectStatistics) + .to receive(:increment_statistic) + .and_call_original + + expect { subject.destroy } + .to change { reload_stat } + .by(delta) + end + + context 'when it is destroyed from the project level' do + it 'does not update the project statistics' do + expect(ProjectStatistics) + .not_to receive(:increment_statistic) + + project.update(pending_delete: true) + project.destroy! + end + end + end +end diff --git a/spec/views/shared/_label_row.html.haml.rb b/spec/views/shared/_label_row.html.haml.rb new file mode 100644 index 00000000000..a58d5efc1e3 --- /dev/null +++ b/spec/views/shared/_label_row.html.haml.rb @@ -0,0 +1,32 @@ +require 'spec_helper' + +describe 'shared/_label_row.html.haml' do + label_types = { + 'project label': :label, + 'group label': :group_label + } + + label_types.each do |label_type, label_factory| + let!(:label) { create(label_factory) } + + context "for a #{label_type}" do + it 'has a non-linked label title' do + render 'shared/label_row', label: label + + expect(rendered).not_to have_css('a', text: label.title) + end + + it "has Issues link for #{label_type}" do + render 'shared/label_row', label: label + + expect(rendered).to have_css('a', text: 'Issues') + end + + it "has Merge request link for #{label_type}" do + render 'shared/label_row', label: label + + expect(rendered).to have_css('a', text: 'Merge requests') + end + end + end +end |