diff options
437 files changed, 3305 insertions, 2038 deletions
diff --git a/.gitlab/issue_templates/Test plan.md b/.gitlab/issue_templates/Test plan.md new file mode 100644 index 00000000000..580fab206b3 --- /dev/null +++ b/.gitlab/issue_templates/Test plan.md @@ -0,0 +1,96 @@ +# Test Plan + +<!-- This issue outlines testing activities related to a particular issue or epic. + +[Here is an example test plan](https://gitlab.com/gitlab-org/gitlab-ce/issues/50353) + +This and other comments should be removed as you write the plan --> + +## Introduction + +<!-- Briefly outline what is being tested + +Mention the issue(s) this test plan is related to --> + +## Scope + +<!-- State any limits on aspects of the feature being tested +Outline the types of data to be included +Outline the types of tests to be performed (functional, security, performance, +database, automated, etc) --> + +## ACC Matrix + +<!-- Use the matrix below as a template to identify the Attributes, Components, and +Capabilities relevant to the scope of this test plan. Add or remove Attributes +and Components as required and list Capabilities in the next section + +Attributes (columns) are adverbs or adjectives that describe (at a high level) +the qualities testing is meant to ensure Components have. + +Components (rows) are nouns that define major parts of the product being tested. + +Capabilities link Attributes and Components. They are what your product needs to +do to make sure a Component fulfills an Attribute + +For more information see the [Google Testing Blog article about the 10 minute +test plan](https://testing.googleblog.com/2011/09/10-minute-test-plan.html) and +[this wiki page from an open-source tool that implements the ACC +model](https://code.google.com/archive/p/test-analytics/wikis/AccExplained.wiki). --> + +| | Simple | Secure | Responsive | Obvious | Stable | +|------------|:------:|:------:|:----------:|:-------:|:------:| +| Admin | | | | | | +| Groups | | | | | | +| Project | | | | | | +| Repository | | | | | | +| Issues | | | | | | +| MRs | | | | | | +| CI/CD | | | | | | +| Ops | | | | | | +| Registry | | | | | | +| Wiki | | | | | | +| Snippets | | | | | | +| Settings | | | | | | +| Tracking | | | | | | +| API | | | | | | + +## Capabilities + +<!-- Use the ACC matrix above to help you identify Capabilities at each relevant +intersection of Components and Attributes. + +Some features might be simple enough that they only involve one Component, while +more complex features could involve multiple or even all. + +Example (from https://gitlab.com/gitlab-org/gitlab-ce/issues/50353): +* Respository is + * Simple + * It's easy to select the desired file template + * It doesn't require unnecessary actions to save the change + * It's easy to undo the change after selecting a template + * Responsive + * The list of templates can be restricted to allow a user to find a specific template among many + * Once a template is selected the file content updates quickly and smoothly +--> + +## Test Plan + +<!-- If the scope is small enough you may not need to write a list of tests to +perform. It might be enough to use the Capabilities to guide your testing. + +If the feature is more complex, especially if it involves multiple Components, +briefly outline a set of tests here. When identifying tests to perform be sure +to consider risk. Note inherent/known levels of risk so that testing can focus +on high risk areas first. + +New end-to-end and integration tests (Selenium and API) should be added to the +[Test Coverage sheet](https://docs.google.com/spreadsheets/d/1RlLfXGboJmNVIPP9jgFV5sXIACGfdcFq1tKd7xnlb74/) + +Please note if automated tests already exist. + +When adding new automated tests, please keep [testing levels](https://docs.gitlab.com/ce/development/testing_guide/testing_levels.html) +in mind. +--> + +/label ~Quality
\ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 7be28a9ac0e..256dd913435 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,258 @@ documentation](doc/development/changelog.md) for instructions on adding your own entry. +## 11.2.1 (2018-08-22) + +### Fixed (2 changes) + +- Fix wrong commit count in push event payload. !21338 +- Fix broken Git over HTTP clones with LDAP users. !21352 + +### Performance (1 change) + +- Eliminate unnecessary and duplicate system hook fires. !21337 + + +## 11.2.0 (2018-08-22) + +### Security (5 changes) + +- Bump Gitaly to 0.117.1 for Rouge update. !21277 +- Fix symlink vulnerability in project import. +- Bump rugged to 0.27.4 for security fixes. +- Fixed XSS in branch name in Web IDE. +- Adding CSRF protection to Hooks test action. + +### Removed (1 change) + +- Remove gitlab:user:check_repos, gitlab:check_repo, gitlab:git:prune, gitlab:git:gc, and gitlab:git:repack. !20806 + +### Fixed (81 changes, 26 of them are from the community) + +- Fix namespace move callback behavior, especially to fix Geo replication of namespace moves during certain exceptions. !19297 +- Fix breadcrumbs in Admin/User interface. !19608 (Robin Naundorf) +- Remove changes_count from MR API documentation where necessary. !19745 (Jan Beckmann) +- Fix email confirmation bug when user adds additional email to account. !20084 (muhammadn) +- Add support for daylight savings time to pipleline schedules. !20145 +- Fixing milestone date change when editing. !20279 (Orlando Del Aguila) +- Add missing maximum_timeout parameter. !20355 (gfyoung) +- [Rails5] Fix 'Invalid single-table inheritance type: Group is not a subclass of Gitlab::BackgroundMigration::FixCrossProjectLabelLinks::Namespace'. !20462 (@blackst0ne) +- Rails5 fix mysql milliseconds problem in specs. !20464 (Jasper Maes) +- Update Gemfile.rails5.lock with latest Gemfile.lock changes. !20466 (Jasper Maes) +- Rails5 mysql fix milliseconds problem in pull request importer spec. !20475 (Jasper Maes) +- Rails5 MySQL fix rename_column as part of cleanup_concurrent_column_type_change. !20514 (Jasper Maes) +- Process commits as normal in forks when the upstream project is deleted. !20534 +- Fix project visibility tooltip. !20535 (Jamie Schembri) +- Fix archived parameter for projects API. !20566 (Peter Marko) +- Limit maximum project build timeout setting to 1 month. !20591 +- Fix GitLab project imports not loading due to API timeouts. !20599 +- Avoid process deadlock in popen by consuming input pipes. !20600 +- Disable SAML and Bitbucket if OmniAuth is disabled. !20608 +- Support multiple scopes when authing container registry scopes. !20617 +- Adds the ability to view group milestones on the dashboard milestone page. !20618 +- Allow issues API to receive an internal ID (iid) on create. !20626 (Jamie Schembri) +- Fix typo in CSS transform property for Memory Graph component. !20650 +- Update design for system metrics popovers. !20655 +- Toggle Show / Hide Button for Kubernetes Password. !20659 (gfyoung) +- Board label edit dropdown shows incorrect selected labels summary. !20673 +- Resolve "Unable to save user profile update with Safari". !20676 +- Escape username and password in UrlSanitizer#full_url. !20684 +- Remove background color from card-body style. !20689 (George Tsiolis) +- Update total storage size when changing size of artifacts. !20697 (Peter Marko) +- Rails5 fix user sees revert modal spec. !20706 (Jasper Maes) +- Fix Web IDE crashing on directories named 'blob'. !20712 +- Fix accessing imported pipeline builds. !20713 +- Fixed bug with invalid repository reference using the wiki search. !20722 +- Resolve Copy diff file path as GFM is broken. !20725 +- Chart versions for applications installed by one click install buttons should be version locked. !20765 +- Fix misalignment of broadcast message on login page. !20794 (Robin Naundorf) +- Fix Vue datatype errors for markdownVersion parsing. !20800 +- Fix authorization for interactive web terminals. !20811 +- Increase width of Web IDE sidebar resize handles. !20818 +- Fix new MR card styles. !20822 +- Fix link color in markdown code brackets. !20841 +- Rails5 update Gemfile.rails5.lock. !20858 (Jasper Maes) +- fix height of full-width Metrics charts on large screens. !20866 +- Fix sorting by name on milestones page. !20881 +- Permit concurrent loads in gpg keychain mutex. !20894 (Jasper Maes) +- Prevent editing and updating wiki pages with non UTF-8 encoding via web interface. !20906 +- Retrieve merge request closing issues from database cache. !20911 +- Fix LFS uploads not working with git-lfs 2.5.0. !20923 +- Fix bug setting http headers in Files API. !20938 +- Rails5: fix flaky spec. !20953 (Jasper Maes) +- Fixed list of projects not loading in group boards. !20955 +- Fix autosave and ESC confirmation issues for MR discussions. !20968 +- Fix navigation to First and Next discussion on MR Changes tab. !20968 +- Fix rendering of the context lines in MR diffs page. !20968 +- fix error caused when using the search bar while unauthenticated. !20970 +- Fix GPG status badge loading regressions. !20987 +- Ensure links in notifications footer are not escaped. !21000 +- Rails5: update Rails5 lock for forgotten gem rouge. !21010 (Jasper Maes) +- Fix UI error whereby prometheus application status is updated. !21029 +- Solves group dashboard line height is too tall for group names. !21033 +- Fix rendering of pipeline failure view when directly navigationg to it. !21043 +- Fix missing and duplicates on project milestone listing page. !21058 +- Fix merge requests not showing any diff files for big patches. !21125 +- Auto-DevOps.gitlab-ci.yml: Update glibc package signing key URL. !21182 (sgerrand) +- Fix issue stopping Instance Statistics javascript to be executed. !21211 +- Fix broken JavaScript in IE11. !21214 +- Improve JUnit test reports in merge request widgets. !49966 +- Properly handle colons in URL passwords. +- Renders test reports for resolved failures and resets error state. +- Fix handling of annotated tags when Gitaly is not in use. +- Fix serialization of LegacyDiffNote. +- Escapes milestone and label's names on flash notice when promoting them. +- Allow to toggle notifications for issues due soon. +- Sanitize git URL in import errors. (Jamie Schembri) +- Add missing predefined variable and fix docs. +- Allow updating a project's avatar without other params. (Jamie Schembri) +- Fix the UI for listing system-level labels. +- Update hamlit to fix ruby 2.5 incompatibilities, fixes #42045. (Matthew Dawson) +- Fix updated_at if created_at is set for Note API. +- Fix search bar text input alignment. + +### Changed (32 changes, 7 of them are from the community) + +- Rack attack is now disabled by default. !16669 +- Include full image URL in webhooks for uploaded images. !18109 (Satish Perala) +- Enable hashed storage for all newly created or renamed projects. !19747 +- Support manually stopping any environment from the UI. !20077 +- Close revert and cherry pick modal on escape keypress. !20341 (George Tsiolis) +- Adds with_projects optional parameter to GET /groups/:id API endpoint. !20494 +- Improve feedback when a developer is unable to push to an empty repository. !20519 +- Display GPG status on repository and blob pages. !20524 +- Updated design of new entry dropdown in Web IDE. !20526 +- UX improvements to top nav search bar. !20537 +- Update issue closing pattern. !20554 (George Tsiolis) +- Add merge request header branch actions left margin. !20643 (George Tsiolis) +- Rubix, scikit-learn, tensorflow & other useful libraries pre-installed with JupyterHub. !20714 (Amit Rathi) +- Show decimal place up to single digit in Stacked Progress Bar. !20776 +- Wrap job name on pipeline job sidebar. !20804 (George Tsiolis) +- Redesign Web IDE back button and context header. !20850 +- Removes "show all" on reports and adds an actionButtons slot. !20855 +- Put fallback reply-key address first in the References header. !20871 +- Allow non-admins to view instance statistics (if permitted by the instance admins). !20874 +- Adds the project and group name to the return type for project and group milestones. !20890 +- Restyle status message input on profile settings. !20903 +- Ensure installed Helm Tiller For GitLab Managed Apps Is protected by mutual auth. !20928 +- Allow multiple JIRA transition ids. !20939 +- Use Helm 2.7.2 for GitLab Managed Apps. !20956 +- Create branch and MR picker for Web IDE. !20978 +- Update commit message styles with monospace font and overflow-x. !20988 +- Update to Rouge 3.2.0, including Terraform and Crystal lexer and bug fixes. !20991 +- Update design of project templates. !21012 +- Update to Rouge 3.2.1, which includes a critical fix to the Perl Lexer. !21263 +- Add a 10 ms bucket for SQL timings. +- Show one digit after dot in commit_per_day value in charts page. (msdundar) +- Redesign GCP offer banner. + +### Performance (30 changes, 10 of them are from the community) + +- Stop dynamically creating project and namespace routes. !20313 +- Tracking the number of repositories and wikis with a cached counter for site-wide statistics. !20413 +- Optimize ProjectWiki#empty? check. !20573 +- Delete UserActivities and related workers. !20597 +- Enable frozen string in app/services/**/*.rb. !20656 (gfyoung) +- Enable more frozen string in app/services/**/*.rb. !20677 (gfyoung) +- Limit the TTL for anonymous sessions to 1 hour. !20700 +- Enable even more frozen string in app/services/**/*.rb. !20702 (gfyoung) +- Enable frozen string in app/serializers/**/*.rb. !20726 (gfyoung) +- Enable frozen string in newly added files to previously processed directories. !20763 (gfyoung) +- Use limit parameter to retrieve Wikis from Gitaly. !20764 +- Add Dangerfile for frozen_string_literal. !20767 (gfyoung) +- Remove method instrumentation for Banzai filters and reference parsers. !20770 +- Enable frozen strings in lib/banzai/filter/*.rb. !20775 +- Enable frozen strings in remaining lib/banzai/filter/*.rb files. !20777 +- DNS prefetching if asset_host for CDN hosting is set. !20781 +- Bump nokogiri to 1.8.4 and sanitize to 4.6.6 for performance. !20795 +- Enable frozen string in app/presenters and app/policies. !20819 (gfyoung) +- Bump haml gem to 5.0.4. !20847 +- Enable frozen string in app/models/*.rb. !20851 (gfyoung) +- Performing Commit GPG signature calculation in bulk. !20870 +- Fix /admin/jobs failing to load due to statement timeout. !20909 +- refactor pipeline job log animation to reduce CPU usage. !20915 +- Improve performance when fetching collapsed diffs and commenting in merge requests. !20940 +- Enable frozen string for app/models/**/*.rb. !21001 (gfyoung) +- Don't set gon variables in JSON requests. !21016 (Peter Leitzen) +- Improve performance and memory footprint of Changes tab of Merge Requests. !21028 +- Avoid N+1 on MRs page when metrics merging date cannot be found. !21053 +- Bump Gitaly to 0.117.0. !21055 +- Access metadata directly from Object Storage. + +### Added (41 changes, 18 of them are from the community) + +- Show repository languages for projects. !19480 +- Adds API endpoint /api/v4/(project/group)/:id/members/all to list also inherited members. !19748 (Jacopo Beschi @jacopo-beschi) +- Added live preview for JavaScript projects in the Web IDE. !19764 +- Add support for SSH certificate authentication. !19911 (Ævar Arnfjörð Bjarmason) +- Add Hangouts Chat integration. !20290 (Kukovskii Vladimir) +- Add ability to import multiple repositories by uploading a manifest file. !20304 +- Show Project ID on project home panel. !20305 (Tuğçe Nur Taş) +- Add an option to have a private profile on GitLab. !20387 (jxterry) +- Extend gitlab-ci.yml to request junit.xml test reports. !20390 +- Add the first mutations for merge requests to GraphQL. !20443 +- Add /-/health basic health check endpoint. !20456 +- Add filter for minimal access level in groups and projects API. !20478 (Marko, Peter) +- Add download button for single file (including raw files) in repository. !20480 (Kia Mei Somabes) +- Gitaly Servers link into Admin > Overview navigation menu. !20550 +- Adds foreign key to notification_settings.user_id. !20567 (Jacopo Beschi @jacopo-beschi) +- JUnit XML Test Summary In MR widget. !20576 +- Cleans up display of Deploy Tokens to match Personal Access Tokens. !20578 (Marcel Amirault) +- Users can set a status message and emoji. !20614 (niedermyer & davamr) +- Add emails delivery Prometheus metrics. !20638 +- Verify runner feature set. !20664 +- Add more comprehensive metrics tracking authentication activity. !20668 +- Add support for tar.gz AUTO_DEVOPS_CHART charts (#49324). !20691 (@kondi1) +- Adds Vuex store for reports section in MR widget. !20709 +- Redirect commits to root if no ref is provided (31576). !20738 (Kia Mei Somabes) +- Search for labels by title or description on project labels page. !20749 +- Add object storage logic to project import. !20773 +- Enable renaming files and folders in Web IDE. !20835 +- Warn user when reload IDE with staged changes. !20857 +- Add local project uploads cleanup task. !20863 +- Improve error message when adding invalid user to a project. !20885 (Jacopo Beschi @jacopo-beschi) +- Add link to homepage on static http status pages (404, 500, etc). !20898 (Jason Funk) +- Clean orphaned files in object storage. !20918 +- Adds frontend support to render test reports on the MR widget. !20936 +- Trigger system hooks when project is archived/unarchived. !20995 +- Custom Wiki Sidebar Support Issue 14995. (Josh Sooter) +- Emails on push recipients now accepts formats like John Doe <johndoe@example.com>. (George Thomas) +- Add new model for tracking label events. +- Improve danger confirmation modals by focusing input field. (Jamie Schembri) +- Clicking CI icon in Web IDE now opens up pipelines panel. +- Enabled deletion of files in the Web IDE. +- Added button to regenerate 2FA codes. (Luke Picciau) + +### Other (26 changes, 7 of them are from the community) + +- Update specific runners help URL. !20213 (George Tsiolis) +- Enable frozen string in apps/uploaders/*.rb. !20401 (gfyoung) +- Update docs of Helm Tiller. !20515 (Takuya Noguchi) +- Persist 'Auto DevOps' banner dismissal globally. !20540 +- Move xterm to a node dependency and remove it from vendor's folder. !20588 +- Upgrade grape-path-helpers to 1.0.6. !20601 +- Delete todos when user loses access to read the target. !20665 +- Remove tooltips from commit author avatar and name in commit lists. !20674 +- Allow cloning LFS repositories through DeployTokens. !20729 +- Replace 'Sidekiq::Testing.inline!' with 'perform_enqueued_jobs'. !20768 (@blackst0ne) +- Replace author_link snake case in stylesheets, specs, and helpers. !20797 (George Tsiolis) +- Replace snake case in SCSS variables. !20799 (George Tsiolis) +- Add rbtrace to Gemfile. !20831 +- Add support for searching users by confirmed e-mails. !20893 +- Changes poll.js to keep polling on any 2xx http status code. !20904 +- Remove todos of users without access to targets migration. !20927 +- Improve and simplify Auto DevOps settings flow. !20946 +- Keep admin settings sections open after submitting forms. !21040 +- CE port of "List groups with developer maintainer access on project creation". !21051 +- Update git rerere link in docs. !21060 (gfyoung) +- Add 'tabindex' attribute support on Icon component to show BS4 popover on trigger type 'focus'. !21066 +- Add a Gitlab::Profiler.print_by_total_time convenience method for profiling from a Rails console. +- Automatically expand runner's settings block when linking to the runner's settings page. +- Increases title column on modal for reports. +- Disables toggle comments button if diff has no discussions. +- Moves help_popover component to a common location. + + ## 11.1.4 (2018-07-30) ### Fixed (4 changes, 1 of them is from the community) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fb7c0c88629..1b9e9d4a5a3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -314,7 +314,7 @@ This [documentation](doc/development/contributing/merge_request_workflow.md) has ## Definition of done -This [documentation](doc/development/contributing/merge_request_workflow.md)) has been moved. +This [documentation](doc/development/contributing/merge_request_workflow.md) has been moved. ## Style guides @@ -116,14 +116,14 @@ gem 'dropzonejs-rails', '~> 0.7.1' # for backups gem 'fog-aws', '~> 2.0.1' gem 'fog-core', '~> 1.44' -gem 'fog-google', '~> 1.3.3' +gem 'fog-google', '~> 1.7.1' gem 'fog-local', '~> 0.3' gem 'fog-openstack', '~> 0.1' gem 'fog-rackspace', '~> 0.1.1' gem 'fog-aliyun', '~> 0.2.0' # for Google storage -gem 'google-api-client', '~> 0.19.8' +gem 'google-api-client', '~> 0.23' # for aws storage gem 'unf', '~> 0.1.4' diff --git a/Gemfile.lock b/Gemfile.lock index 15a105579fb..77effb63d2e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -239,11 +239,11 @@ GEM builder excon (~> 0.58) formatador (~> 0.2) - fog-google (1.3.3) + fog-google (1.7.1) fog-core fog-json fog-xml - google-api-client (~> 0.19.1) + google-api-client (~> 0.23.0) fog-json (1.0.2) fog-core (~> 1.0) multi_json (~> 1.10) @@ -329,7 +329,7 @@ GEM actionpack (>= 3.0) multi_json request_store (>= 1.0) - google-api-client (0.19.8) + google-api-client (0.23.4) addressable (~> 2.5, >= 2.5.1) googleauth (>= 0.5, < 0.7.0) httpclient (>= 2.8.1, < 3.0) @@ -738,7 +738,7 @@ GEM http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) netrc (~> 0.8) - retriable (3.1.1) + retriable (3.1.2) rinku (2.0.0) rotp (2.1.2) rouge (3.2.1) @@ -1031,7 +1031,7 @@ DEPENDENCIES fog-aliyun (~> 0.2.0) fog-aws (~> 2.0.1) fog-core (~> 1.44) - fog-google (~> 1.3.3) + fog-google (~> 1.7.1) fog-local (~> 0.3) fog-openstack (~> 0.1) fog-rackspace (~> 0.1.1) @@ -1051,7 +1051,7 @@ DEPENDENCIES gitlab-styles (~> 2.4) gitlab_omniauth-ldap (~> 2.0.4) gon (~> 6.2) - google-api-client (~> 0.19.8) + google-api-client (~> 0.23) google-protobuf (= 3.5.1) gpgme grape (~> 1.0) diff --git a/Gemfile.rails5.lock b/Gemfile.rails5.lock index 7803d12c6b4..63b450d3f62 100644 --- a/Gemfile.rails5.lock +++ b/Gemfile.rails5.lock @@ -126,7 +126,7 @@ GEM numerizer (~> 0.1.1) chunky_png (1.3.5) citrus (3.0.2) - coderay (1.1.1) + coderay (1.1.2) coercible (1.0.0) descendants_tracker (~> 0.0.1) commonmarker (0.17.8) @@ -242,11 +242,11 @@ GEM builder excon (~> 0.58) formatador (~> 0.2) - fog-google (1.3.3) + fog-google (1.7.1) fog-core fog-json fog-xml - google-api-client (~> 0.19.1) + google-api-client (~> 0.23.0) fog-json (1.0.2) fog-core (~> 1.0) multi_json (~> 1.10) @@ -332,7 +332,7 @@ GEM actionpack (>= 3.0) multi_json request_store (>= 1.0) - google-api-client (0.19.8) + google-api-client (0.23.4) addressable (~> 2.5, >= 2.5.1) googleauth (>= 0.5, < 0.7.0) httpclient (>= 2.8.1, < 3.0) @@ -495,7 +495,7 @@ GEM memoist (0.16.0) memoizable (0.4.2) thread_safe (~> 0.3, >= 0.3.1) - method_source (0.8.2) + method_source (0.9.0) mime-types (3.1) mime-types-data (~> 3.2015) mime-types-data (3.2016.0521) @@ -638,12 +638,11 @@ GEM unparser procto (0.0.3) prometheus-client-mmap (0.9.4) - pry (0.10.4) + pry (0.11.3) coderay (~> 1.1.0) - method_source (~> 0.8.1) - slop (~> 3.4) - pry-byebug (3.4.2) - byebug (~> 9.0) + method_source (~> 0.9.0) + pry-byebug (3.4.3) + byebug (>= 9.0, < 9.1) pry (~> 0.10) pry-rails (0.3.5) pry (>= 0.9.10) @@ -748,10 +747,10 @@ GEM http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) netrc (~> 0.8) - retriable (3.1.1) + retriable (3.1.2) rinku (2.0.0) rotp (2.1.2) - rouge (3.2.0) + rouge (3.2.1) rqrcode (0.7.0) chunky_png rqrcode-rails3 (0.1.7) @@ -817,7 +816,7 @@ GEM rubyzip (1.2.1) rufus-scheduler (3.4.0) et-orbi (~> 1.0) - rugged (0.27.2) + rugged (0.27.4) safe_yaml (1.0.4) sanitize (4.6.6) crass (~> 1.0.2) @@ -878,7 +877,6 @@ GEM simplecov-html (~> 0.10.0) simplecov-html (0.10.0) slack-notifier (1.5.1) - slop (3.6.0) spring (2.0.1) activesupport (>= 4.2) spring-commands-rspec (1.0.4) @@ -1043,7 +1041,7 @@ DEPENDENCIES fog-aliyun (~> 0.2.0) fog-aws (~> 2.0.1) fog-core (~> 1.44) - fog-google (~> 1.3.3) + fog-google (~> 1.7.1) fog-local (~> 0.3) fog-openstack (~> 0.1) fog-rackspace (~> 0.1.1) @@ -1063,7 +1061,7 @@ DEPENDENCIES gitlab-styles (~> 2.4) gitlab_omniauth-ldap (~> 2.0.4) gon (~> 6.2) - google-api-client (~> 0.19.8) + google-api-client (~> 0.23) google-protobuf (= 3.5.1) gpgme grape (~> 1.0) @@ -1 +1 @@ -11.2.0-pre +11.3.0-pre diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js index 25fe2ae553e..cd800d75f7a 100644 --- a/app/assets/javascripts/api.js +++ b/app/assets/javascripts/api.js @@ -15,6 +15,7 @@ const Api = { mergeRequestChangesPath: '/api/:version/projects/:id/merge_requests/:mrid/changes', mergeRequestVersionsPath: '/api/:version/projects/:id/merge_requests/:mrid/versions', groupLabelsPath: '/groups/:namespace_path/-/labels', + templatesPath: '/api/:version/templates/:key', licensePath: '/api/:version/templates/licenses/:key', gitignorePath: '/api/:version/templates/gitignores/:key', gitlabCiYmlPath: '/api/:version/templates/gitlab_ci_ymls/:key', @@ -265,6 +266,12 @@ const Api = { }); }, + templates(key, params = {}) { + const url = Api.buildUrl(this.templatesPath).replace(':key', key); + + return axios.get(url, { params }); + }, + buildUrl(url) { let urlRoot = ''; if (gon.relative_url_root != null) { diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js index e34db893989..5b0c4285339 100644 --- a/app/assets/javascripts/awards_handler.js +++ b/app/assets/javascripts/awards_handler.js @@ -109,8 +109,6 @@ export class AwardsHandler { } const $menu = $(`.${this.menuClass}`); - const $thumbsBtn = $menu.find('[data-name="thumbsup"], [data-name="thumbsdown"]').parent(); - const $userAuthored = this.isUserAuthored($addBtn); if ($menu.length) { if ($menu.is('.is-visible')) { $addBtn.removeClass('is-active'); @@ -134,9 +132,6 @@ export class AwardsHandler { }, 200); }); } - - $thumbsBtn.toggleClass('disabled', $userAuthored); - $thumbsBtn.prop('disabled', $userAuthored); } // Create the emoji menu with the first category of emojis. @@ -364,10 +359,6 @@ export class AwardsHandler { return $emojiButton.hasClass('active'); } - isUserAuthored($button) { - return $button.hasClass('js-user-authored'); - } - decrementCounter($emojiButton, emoji) { const counter = $('.js-counter', $emojiButton); const counterNumber = parseInt(counter.text(), 10); @@ -474,20 +465,16 @@ export class AwardsHandler { } postEmoji($emojiButton, awardUrl, emoji, callback) { - if (this.isUserAuthored($emojiButton)) { - this.userAuthored($emojiButton); - } else { - axios - .post(awardUrl, { - name: emoji, - }) - .then(({ data }) => { - if (data.ok) { - callback(); - } - }) - .catch(() => flash(__('Something went wrong on our end.'))); - } + axios + .post(awardUrl, { + name: emoji, + }) + .then(({ data }) => { + if (data.ok) { + callback(); + } + }) + .catch(() => flash(__('Something went wrong on our end.'))); } findEmojiIcon(votesBlock, emoji) { diff --git a/app/assets/javascripts/ide/stores/modules/file_templates/actions.js b/app/assets/javascripts/ide/stores/modules/file_templates/actions.js new file mode 100644 index 00000000000..43237a29466 --- /dev/null +++ b/app/assets/javascripts/ide/stores/modules/file_templates/actions.js @@ -0,0 +1,82 @@ +import Api from '~/api'; +import { __ } from '~/locale'; +import * as types from './mutation_types'; + +export const requestTemplateTypes = ({ commit }) => commit(types.REQUEST_TEMPLATE_TYPES); +export const receiveTemplateTypesError = ({ commit, dispatch }) => { + commit(types.RECEIVE_TEMPLATE_TYPES_ERROR); + dispatch( + 'setErrorMessage', + { + text: __('Error loading template types.'), + action: () => + dispatch('fetchTemplateTypes').then(() => + dispatch('setErrorMessage', null, { root: true }), + ), + actionText: __('Please try again'), + }, + { root: true }, + ); +}; +export const receiveTemplateTypesSuccess = ({ commit }, templates) => + commit(types.RECEIVE_TEMPLATE_TYPES_SUCCESS, templates); + +export const fetchTemplateTypes = ({ dispatch, state }) => { + if (!Object.keys(state.selectedTemplateType).length) return Promise.reject(); + + dispatch('requestTemplateTypes'); + + return Api.templates(state.selectedTemplateType.key) + .then(({ data }) => dispatch('receiveTemplateTypesSuccess', data)) + .catch(() => dispatch('receiveTemplateTypesError')); +}; + +export const setSelectedTemplateType = ({ commit }, type) => + commit(types.SET_SELECTED_TEMPLATE_TYPE, type); + +export const receiveTemplateError = ({ dispatch }, template) => { + dispatch( + 'setErrorMessage', + { + text: __('Error loading template.'), + action: payload => + dispatch('fetchTemplateTypes', payload).then(() => + dispatch('setErrorMessage', null, { root: true }), + ), + actionText: __('Please try again'), + actionPayload: template, + }, + { root: true }, + ); +}; + +export const fetchTemplate = ({ dispatch, state }, template) => { + if (template.content) { + return dispatch('setFileTemplate', template); + } + + return Api.templates(`${state.selectedTemplateType.key}/${template.key || template.name}`) + .then(({ data }) => { + dispatch('setFileTemplate', data); + }) + .catch(() => dispatch('receiveTemplateError', template)); +}; + +export const setFileTemplate = ({ dispatch, commit, rootGetters }, template) => { + dispatch( + 'changeFileContent', + { path: rootGetters.activeFile.path, content: template.content }, + { root: true }, + ); + commit(types.SET_UPDATE_SUCCESS, true); +}; + +export const undoFileTemplate = ({ dispatch, commit, rootGetters }) => { + const file = rootGetters.activeFile; + + dispatch('changeFileContent', { path: file.path, content: file.raw }, { root: true }); + commit(types.SET_UPDATE_SUCCESS, false); +}; + +// prevent babel-plugin-rewire from generating an invalid default during karma tests +export default () => {}; diff --git a/app/assets/javascripts/ide/stores/modules/file_templates/getters.js b/app/assets/javascripts/ide/stores/modules/file_templates/getters.js new file mode 100644 index 00000000000..38318fd49bf --- /dev/null +++ b/app/assets/javascripts/ide/stores/modules/file_templates/getters.js @@ -0,0 +1,23 @@ +export const templateTypes = () => [ + { + name: '.gitlab-ci.yml', + key: 'gitlab_ci_ymls', + }, + { + name: '.gitignore', + key: 'gitignores', + }, + { + name: 'LICENSE', + key: 'licenses', + }, + { + name: 'Dockerfile', + key: 'dockerfiles', + }, +]; + +export const showFileTemplatesBar = (_, getters) => name => + getters.templateTypes.find(t => t.name === name); + +export default () => {}; diff --git a/app/assets/javascripts/ide/stores/modules/file_templates/index.js b/app/assets/javascripts/ide/stores/modules/file_templates/index.js new file mode 100644 index 00000000000..dfa5ef54413 --- /dev/null +++ b/app/assets/javascripts/ide/stores/modules/file_templates/index.js @@ -0,0 +1,12 @@ +import createState from './state'; +import * as actions from './actions'; +import * as getters from './getters'; +import mutations from './mutations'; + +export default { + namespaced: true, + actions, + state: createState(), + getters, + mutations, +}; diff --git a/app/assets/javascripts/ide/stores/modules/file_templates/mutation_types.js b/app/assets/javascripts/ide/stores/modules/file_templates/mutation_types.js new file mode 100644 index 00000000000..cf4499c0264 --- /dev/null +++ b/app/assets/javascripts/ide/stores/modules/file_templates/mutation_types.js @@ -0,0 +1,7 @@ +export const REQUEST_TEMPLATE_TYPES = 'REQUEST_TEMPLATE_TYPES'; +export const RECEIVE_TEMPLATE_TYPES_ERROR = 'RECEIVE_TEMPLATE_TYPES_ERROR'; +export const RECEIVE_TEMPLATE_TYPES_SUCCESS = 'RECEIVE_TEMPLATE_TYPES_SUCCESS'; + +export const SET_SELECTED_TEMPLATE_TYPE = 'SET_SELECTED_TEMPLATE_TYPE'; + +export const SET_UPDATE_SUCCESS = 'SET_UPDATE_SUCCESS'; diff --git a/app/assets/javascripts/ide/stores/modules/file_templates/mutations.js b/app/assets/javascripts/ide/stores/modules/file_templates/mutations.js new file mode 100644 index 00000000000..e413e61eaaa --- /dev/null +++ b/app/assets/javascripts/ide/stores/modules/file_templates/mutations.js @@ -0,0 +1,21 @@ +/* eslint-disable no-param-reassign */ +import * as types from './mutation_types'; + +export default { + [types.REQUEST_TEMPLATE_TYPES](state) { + state.isLoading = true; + }, + [types.RECEIVE_TEMPLATE_TYPES_ERROR](state) { + state.isLoading = false; + }, + [types.RECEIVE_TEMPLATE_TYPES_SUCCESS](state, templates) { + state.isLoading = false; + state.templates = templates; + }, + [types.SET_SELECTED_TEMPLATE_TYPE](state, type) { + state.selectedTemplateType = type; + }, + [types.SET_UPDATE_SUCCESS](state, success) { + state.updateSuccess = success; + }, +}; diff --git a/app/assets/javascripts/ide/stores/modules/file_templates/state.js b/app/assets/javascripts/ide/stores/modules/file_templates/state.js new file mode 100644 index 00000000000..bd4b7d7bc52 --- /dev/null +++ b/app/assets/javascripts/ide/stores/modules/file_templates/state.js @@ -0,0 +1,6 @@ +export default () => ({ + isLoading: false, + templates: [], + selectedTemplateType: {}, + updateSuccess: false, +}); diff --git a/app/assets/javascripts/notes/components/note_awards_list.vue b/app/assets/javascripts/notes/components/note_awards_list.vue index 225d9f18612..e111d3b9ac2 100644 --- a/app/assets/javascripts/notes/components/note_awards_list.vue +++ b/app/assets/javascripts/notes/components/note_awards_list.vue @@ -82,29 +82,17 @@ export default { getAwardHTML(name) { return glEmojiTag(name); }, - getAwardClassBindings(awardList, awardName) { + getAwardClassBindings(awardList) { return { active: this.hasReactionByCurrentUser(awardList), - disabled: !this.canInteractWithEmoji(awardList, awardName), + disabled: !this.canInteractWithEmoji(), }; }, - canInteractWithEmoji(awardList, awardName) { - let isAllowed = true; - const restrictedEmojis = ['thumbsup', 'thumbsdown']; - - // Users can not add :+1: and :-1: to their own notes - if ( - this.getUserData.id === this.noteAuthorId && - restrictedEmojis.indexOf(awardName) > -1 - ) { - isAllowed = false; - } - - return this.getUserData.id && isAllowed; + canInteractWithEmoji() { + return this.getUserData.id; }, hasReactionByCurrentUser(awardList) { - return awardList.filter(award => award.user.id === this.getUserData.id) - .length; + return awardList.filter(award => award.user.id === this.getUserData.id).length; }, awardTitle(awardsList) { const hasReactionByCurrentUser = this.hasReactionByCurrentUser( @@ -197,7 +185,7 @@ export default { v-tooltip v-for="(awardList, awardName, index) in groupedAwards" :key="index" - :class="getAwardClassBindings(awardList, awardName)" + :class="getAwardClassBindings(awardList)" :title="awardTitle(awardList)" class="btn award-control" data-boundary="viewport" diff --git a/app/assets/javascripts/pipelines/components/pipelines_table_row.vue b/app/assets/javascripts/pipelines/components/pipelines_table_row.vue index 804822a3ea8..29b347824de 100644 --- a/app/assets/javascripts/pipelines/components/pipelines_table_row.vue +++ b/app/assets/javascripts/pipelines/components/pipelines_table_row.vue @@ -330,7 +330,7 @@ export default { <pipelines-artifacts-component v-if="pipeline.details.artifacts.length" :artifacts="pipeline.details.artifacts" - class="d-none d-sm-none d-md-block" + class="d-md-block" /> <loading-button diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue index 21f21232596..d530ab2767b 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue @@ -1,5 +1,6 @@ <script> import Icon from '~/vue_shared/components/icon.vue'; +import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue'; import timeagoMixin from '../../vue_shared/mixins/timeago'; import tooltip from '../../vue_shared/directives/tooltip'; import LoadingButton from '../../vue_shared/components/loading_button.vue'; @@ -16,6 +17,7 @@ export default { MemoryUsage, StatusIcon, Icon, + TooltipOnTruncate, }, directives: { tooltip, @@ -88,14 +90,20 @@ export default { <span> Deployed to </span> - <a - :href="deployment.url" - target="_blank" - rel="noopener noreferrer nofollow" - class="deploy-link js-deploy-meta" + <tooltip-on-truncate + :title="deployment.name" + truncate-target="child" + class="deploy-link label-truncate" > - {{ deployment.name }} - </a> + <a + :href="deployment.url" + target="_blank" + rel="noopener noreferrer nofollow" + class="js-deploy-meta" + > + {{ deployment.name }} + </a> + </tooltip-on-truncate> </template> <span v-tooltip diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue index a4c2289c590..72bd28ae03f 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue @@ -1,18 +1,17 @@ <script> -import tooltip from '~/vue_shared/directives/tooltip'; -import { n__ } from '~/locale'; +import _ from 'underscore'; +import { n__, s__, sprintf } from '~/locale'; import { mergeUrlParams, webIDEUrl } from '~/lib/utils/url_utility'; import Icon from '~/vue_shared/components/icon.vue'; import clipboardButton from '~/vue_shared/components/clipboard_button.vue'; +import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue'; export default { name: 'MRWidgetHeader', - directives: { - tooltip, - }, components: { Icon, clipboardButton, + TooltipOnTruncate, }, props: { mr: { @@ -24,8 +23,12 @@ export default { shouldShowCommitsBehindText() { return this.mr.divergedCommitsCount > 0; }, - commitsText() { - return n__('%d commit behind', '%d commits behind', this.mr.divergedCommitsCount); + commitsBehindText() { + return sprintf(s__('mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch'), { + commitsBehindLinkStart: `<a href="${_.escape(this.mr.targetBranchPath)}">`, + commitsBehind: n__('%d commit behind', '%d commits behind', this.mr.divergedCommitsCount), + commitsBehindLinkEnd: '</a>', + }, false); }, branchNameClipboardData() { // This supports code in app/assets/javascripts/copy_to_clipboard.js that @@ -36,12 +39,6 @@ export default { gfm: `\`${this.mr.sourceBranch}\``, }); }, - isSourceBranchLong() { - return this.isBranchTitleLong(this.mr.sourceBranch); - }, - isTargetBranchLong() { - return this.isBranchTitleLong(this.mr.targetBranch); - }, webIdePath() { return mergeUrlParams({ target_project: this.mr.sourceProjectFullPath !== this.mr.targetProjectFullPath ? @@ -49,11 +46,6 @@ export default { }, webIDEUrl(`/${this.mr.sourceProjectFullPath}/merge_requests/${this.mr.iid}`)); }, }, - methods: { - isBranchTitleLong(branchTitle) { - return branchTitle.length > 32; - }, - }, }; </script> <template> @@ -65,30 +57,21 @@ export default { <div class="normal"> <strong> {{ s__("mrWidget|Request to merge") }} - <span - :class="{ 'label-truncated': isSourceBranchLong }" - :title="isSourceBranchLong ? mr.sourceBranch : ''" - :v-tooltip="isSourceBranchLong" - class="label-branch js-source-branch" - data-placement="bottom" + <tooltip-on-truncate + :title="mr.sourceBranch" + truncate-target="child" + class="label-branch label-truncate js-source-branch" v-html="mr.sourceBranchLink" - > - </span> - - <clipboard-button + /><clipboard-button :text="branchNameClipboardData" :title="__('Copy branch name to clipboard')" css-class="btn-default btn-transparent btn-clipboard" /> - {{ s__("mrWidget|into") }} - - <span - :v-tooltip="isTargetBranchLong" - :class="{ 'label-truncatedtooltip': isTargetBranchLong }" - :title="isTargetBranchLong ? mr.targetBranch : ''" - class="label-branch" - data-placement="bottom" + <tooltip-on-truncate + :title="mr.targetBranch" + truncate-target="child" + class="label-branch label-truncate" > <a :href="mr.targetBranchTreePath" @@ -96,15 +79,13 @@ export default { > {{ mr.targetBranch }} </a> - </span> + </tooltip-on-truncate> </strong> <div v-if="shouldShowCommitsBehindText" class="diverged-commits-count" + v-html="commitsBehindText" > - <span class="monospace">{{ mr.sourceBranch }}</span> - is {{ commitsText }} - <span class="monospace">{{ mr.targetBranch }}</span> </div> </div> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue index 4a3fd01fa39..fee41b239e8 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue @@ -3,6 +3,7 @@ import PipelineStage from '~/pipelines/components/stage.vue'; import CiIcon from '~/vue_shared/components/ci_icon.vue'; import Icon from '~/vue_shared/components/icon.vue'; +import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue'; export default { name: 'MRWidgetPipeline', @@ -10,6 +11,7 @@ export default { PipelineStage, CiIcon, Icon, + TooltipOnTruncate, }, props: { pipeline: { @@ -30,6 +32,10 @@ export default { type: String, required: false, }, + sourceBranch: { + type: String, + required: false, + }, }, computed: { hasPipeline() { @@ -107,11 +113,12 @@ export default { > {{ pipeline.commit.short_id }}</a> on - <span - class="label-branch" + <tooltip-on-truncate + :title="sourceBranch" + truncate-target="child" + class="label-branch label-truncate" v-html="sourceBranchLink" - > - </span> + /> </template> </div> <div diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue index 80593d1f34a..dc6be025f11 100644 --- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue +++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue @@ -254,6 +254,7 @@ export default { :pipeline="mr.pipeline" :ci-status="mr.ciStatus" :has-ci="mr.hasCI" + :source-branch="mr.sourceBranch" :source-branch-link="mr.sourceBranchLink" /> <deployment diff --git a/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue b/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue index f44d361c47e..78fde463507 100644 --- a/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue +++ b/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue @@ -71,7 +71,11 @@ export default { }, methods: { getPercent(count) { - return roundOffFloat((count / this.totalCount) * 100, 1); + const percent = roundOffFloat((count / this.totalCount) * 100, 1); + if (percent > 0 && percent < 1) { + return '< 1'; + } + return percent; }, barStyle(percent) { return `width: ${percent}%;`; diff --git a/app/assets/javascripts/vue_shared/components/tooltip_on_truncate.vue b/app/assets/javascripts/vue_shared/components/tooltip_on_truncate.vue new file mode 100644 index 00000000000..125826da6c3 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/tooltip_on_truncate.vue @@ -0,0 +1,67 @@ +<script> +import _ from 'underscore'; +import tooltip from '../directives/tooltip'; + +export default { + directives: { + tooltip, + }, + props: { + title: { + type: String, + required: false, + default: '', + }, + placement: { + type: String, + required: false, + default: 'top', + }, + truncateTarget: { + type: [String, Function], + required: false, + default: '', + }, + }, + data() { + return { + showTooltip: false, + }; + }, + mounted() { + const target = this.selectTarget(); + + if (target && target.scrollWidth > target.offsetWidth) { + this.showTooltip = true; + } + }, + methods: { + selectTarget() { + if (_.isFunction(this.truncateTarget)) { + return this.truncateTarget(this.$el); + } else if (this.truncateTarget === 'child') { + return this.$el.childNodes[0]; + } + + return this.$el; + }, + }, +}; +</script> + +<template> + <span + v-tooltip + v-if="showTooltip" + :title="title" + :data-placement="placement" + class="js-show-tooltip" + > + <slot></slot> + </span> + <span + v-else + > + <slot></slot> + </span> +</template> diff --git a/app/assets/stylesheets/bootstrap_migration.scss b/app/assets/stylesheets/bootstrap_migration.scss index e8e707cf90c..c91f5e279ea 100644 --- a/app/assets/stylesheets/bootstrap_migration.scss +++ b/app/assets/stylesheets/bootstrap_migration.scss @@ -4,11 +4,11 @@ $text-color: $gl-text-color; -$brand-primary: $gl-primary; -$brand-success: $gl-success; -$brand-info: $gl-info; -$brand-warning: $gl-warning; -$brand-danger: $gl-danger; +$brand-primary: $blue-500; +$brand-success: $green-500; +$brand-info: $blue-500; +$brand-warning: $orange-500; +$brand-danger: $red-500; $border-radius-base: 3px !default; diff --git a/app/assets/stylesheets/framework/avatar.scss b/app/assets/stylesheets/framework/avatar.scss index 4c7c399a3ca..9dd0384a228 100644 --- a/app/assets/stylesheets/framework/avatar.scss +++ b/app/assets/stylesheets/framework/avatar.scss @@ -8,7 +8,7 @@ float: left; margin-right: 15px; border-radius: $avatar-radius; - border: 1px solid $avatar-border; + border: 1px solid $gray-normal; &.s16 { @include avatar-size(16px, 6px); } &.s18 { @include avatar-size(18px, 6px); } &.s19 { @include avatar-size(19px, 6px); } @@ -36,7 +36,7 @@ width: 40px; height: 40px; padding: 0; - background: $avatar-background; + background: $gray-lightest; overflow: hidden; &.avatar-inline { @@ -62,7 +62,7 @@ } &:not([href]):hover { - border-color: darken($avatar-border, 10%); + border-color: darken($gray-normal, 10%); } } @@ -70,7 +70,7 @@ text-align: center; vertical-align: top; color: $identicon-fg-color; - background-color: $identicon-gray; + background-color: $gray-darker; // Sizes &.s16 { font-size: 12px; line-height: 1.33; } @@ -94,7 +94,7 @@ &.bg4 { background-color: $identicon-blue; } &.bg5 { background-color: $identicon-teal; } &.bg6 { background-color: $identicon-orange; } - &.bg7 { background-color: $identicon-gray; } + &.bg7 { background-color: $gray-darker; } } .avatar-container { @@ -122,7 +122,7 @@ .avatar-counter { background-color: $gray-darkest; color: $white-light; - border: 1px solid $avatar-border; + border: 1px solid $gray-normal; border-radius: 1em; font-family: $regular-font; font-size: 9px; diff --git a/app/assets/stylesheets/framework/badges.scss b/app/assets/stylesheets/framework/badges.scss index 57df9b969c3..c6060161dec 100644 --- a/app/assets/stylesheets/framework/badges.scss +++ b/app/assets/stylesheets/framework/badges.scss @@ -1,6 +1,6 @@ .badge.badge-pill { font-weight: $gl-font-weight-normal; background-color: $badge-bg; - color: $badge-color; + color: $gl-text-color-secondary; vertical-align: baseline; } diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index 0dc7aa4ef68..72b4ed0ac33 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -452,14 +452,14 @@ } .btn-missing { - color: $notes-light-color; + color: $gl-text-color-secondary; border: 1px dashed $border-gray-normal-dashed; border-radius: $border-radius-default; &:hover, &:active, &:focus { - color: $notes-light-color; + color: $gl-text-color-secondary; background-color: $white-normal; } } diff --git a/app/assets/stylesheets/framework/callout.scss b/app/assets/stylesheets/framework/callout.scss index 1bd94c0acba..bdd7f09d926 100644 --- a/app/assets/stylesheets/framework/callout.scss +++ b/app/assets/stylesheets/framework/callout.scss @@ -25,25 +25,25 @@ /* Variations */ .bs-callout-danger { - background-color: $callout-danger-bg; - border-color: $callout-danger-border; - color: $callout-danger-color; + background-color: $red-100; + border-color: $red-200; + color: $red-700; } .bs-callout-warning { - background-color: $callout-warning-bg; - border-color: $callout-warning-border; - color: $callout-warning-color; + background-color: $orange-100; + border-color: $orange-200; + color: $orange-700; } .bs-callout-info { - background-color: $callout-info-bg; - border-color: $callout-info-border; - color: $callout-info-color; + background-color: $blue-100; + border-color: $blue-200; + color: $blue-700; } .bs-callout-success { - background-color: $callout-success-bg; - border-color: $callout-success-border; - color: $callout-success-color; + background-color: $green-100; + border-color: $green-200; + color: $green-700; } diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index 79ca6e61e9a..72e27f9ad16 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -1,8 +1,8 @@ /** COLORS **/ -.cgray { color: $common-gray; } +.cgray { color: $gl-text-color; } .clgray { color: $common-gray-light; } -.cred { color: $common-red; } -.cgreen { color: $common-green; } +.cred { color: $red-500; } +.cgreen { color: $green-600; } .cdark { color: $common-gray-dark; } .text-plain, @@ -44,10 +44,10 @@ } .hint { font-style: italic; color: $hint-color; } -.light { color: $common-gray; } +.light { color: $gl-text-color; } .slead { - color: $common-gray; + color: $gl-text-color; font-size: 14px; margin-bottom: 12px; font-weight: $gl-font-weight-normal; @@ -352,7 +352,7 @@ img.emoji { border-color: $border-color !important; .dz-upload { - background: $gl-success !important; + background: $green-500 !important; } } diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index 83bc3776178..8a224dc517e 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -147,7 +147,7 @@ } @mixin dropdown-item-hover { - background-color: $dropdown-item-hover-bg; + background-color: $gray-darker; color: $gl-text-color; outline: 0; @@ -195,7 +195,7 @@ text-decoration: none; .badge.badge-pill { - background-color: darken($dropdown-link-hover-bg, 5%); + background-color: darken($blue-50, 5%); } } @@ -233,7 +233,7 @@ font-weight: $gl-font-weight-normal; padding: 8px 0; background-color: $white-light; - border: 1px solid $dropdown-border-color; + border: 1px solid $border-color; border-radius: $border-radius-base; box-shadow: 0 2px 4px $dropdown-shadow-color; @@ -874,7 +874,7 @@ header.header-content .dropdown-menu.frequent-items-dropdown-menu { overflow-y: auto; li.section-empty.section-failure { - color: $callout-danger-color; + color: $red-700; } .frequent-items-list-item-container a { diff --git a/app/assets/stylesheets/framework/feature_highlight.scss b/app/assets/stylesheets/framework/feature_highlight.scss index cad915bc86f..85cabf43e9e 100644 --- a/app/assets/stylesheets/framework/feature_highlight.scss +++ b/app/assets/stylesheets/framework/feature_highlight.scss @@ -72,11 +72,11 @@ .feature-highlight-popover { width: 240px; padding: 0; - border: 1px solid $dropdown-border-color; + border: 1px solid $border-color; box-shadow: 0 2px 4px $dropdown-shadow-color; &.right > .arrow { - border-right-color: $dropdown-border-color; + border-right-color: $border-color; } .popover-body { diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss index 3bdf5bfc93a..1d3512bbb4c 100644 --- a/app/assets/stylesheets/framework/files.scss +++ b/app/assets/stylesheets/framework/files.scss @@ -312,11 +312,11 @@ span.idiff { text-decoration: none; .new-file { - color: $notify-new-file; + color: $green-600; } .deleted-file { - color: $notify-deleted-file; + color: $red-700; } } } diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss index 9b09ed0ed0a..abfe350677e 100644 --- a/app/assets/stylesheets/framework/filters.scss +++ b/app/assets/stylesheets/framework/filters.scss @@ -206,7 +206,7 @@ &.focus, &.focus:hover { border-color: $blue-300; - box-shadow: 0 0 4px $search-input-focus-shadow-color; + box-shadow: 0 0 4px $dropdown-input-focus-shadow; } gl-emoji { diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss index a70eece8f68..afd888af672 100644 --- a/app/assets/stylesheets/framework/forms.scss +++ b/app/assets/stylesheets/framework/forms.scss @@ -8,7 +8,7 @@ input { input[type='text'].danger { background: $input-danger-bg !important; - border-color: $input-danger-border; + border-color: $red-400; text-shadow: 0 1px 1px $white-light; } diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index e7e13d35d8e..11a30d83f03 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -554,7 +554,7 @@ float: left; margin-right: 5px; border-radius: 50%; - border: 1px solid $avatar-border; + border: 1px solid $gray-normal; } .with-performance-bar .navbar-gitlab { diff --git a/app/assets/stylesheets/framework/icons.scss b/app/assets/stylesheets/framework/icons.scss index d1f7ff4438b..f002edced8a 100644 --- a/app/assets/stylesheets/framework/icons.scss +++ b/app/assets/stylesheets/framework/icons.scss @@ -11,7 +11,7 @@ .ci-status-icon-failed { svg { - fill: $gl-danger; + fill: $red-500; } &.add-border { diff --git a/app/assets/stylesheets/framework/issue_box.scss b/app/assets/stylesheets/framework/issue_box.scss index da5f80d9d37..2d672e62e08 100644 --- a/app/assets/stylesheets/framework/issue_box.scss +++ b/app/assets/stylesheets/framework/issue_box.scss @@ -26,12 +26,12 @@ &.status-box-closed, &.status-box-mr-closed { - background-color: $gl-danger; + background-color: $red-500; } &.status-box-issue-closed, &.status-box-mr-merged { - background-color: $gl-primary; + background-color: $blue-500; } &.status-box-open { diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss index 88d2f0aaf85..3ae2c7078d6 100644 --- a/app/assets/stylesheets/framework/selects.scss +++ b/app/assets/stylesheets/framework/selects.scss @@ -58,7 +58,7 @@ .select2-drop.select2-drop-above { box-shadow: 0 2px 4px $dropdown-shadow-color; border-radius: $border-radius-base; - border: 1px solid $dropdown-border-color; + border: 1px solid $border-color; min-width: 175px; color: $gl-text-color; z-index: 999; @@ -69,7 +69,7 @@ } .select2-drop.select2-drop-above.select2-drop-active { - border-top: 1px solid $dropdown-border-color; + border-top: 1px solid $border-color; margin-top: -6px; } @@ -193,7 +193,7 @@ color: $gl-text-color; .select2-result-label { - background: $dropdown-item-hover-bg; + background: $gray-darker; } } diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 96508a71bd8..2781d910b8d 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -297,19 +297,9 @@ $tanuki-yellow: #fca326; /* * State colors: */ -$gl-primary: $blue-500; -$gl-success: $green-500; -$gl-success-focus: rgba($gl-success, 0.4); -$gl-info: $blue-500; -$gl-warning: $orange-500; -$gl-danger: $red-500; +$green-500-focus: rgba($green-500, 0.4); $gl-btn-active-background: rgba(0, 0, 0, 0.16); $gl-btn-active-gradient: inset 0 2px 3px $gl-btn-active-background; -// Bootstrap override states -$success: $gl-success; -$info: $gl-info; -$warning: $gl-warning; -$danger: $gl-danger; /* * Commit Diff Colors @@ -329,10 +319,9 @@ $line-select-yellow-dark: #f0e2bd; $dark-diff-match-bg: rgba(255, 255, 255, 0.3); $dark-diff-match-color: rgba(255, 255, 255, 0.1); $file-mode-changed: #777; -$file-mode-changed: #777; -$diff-image-info-color: grey; +$diff-image-info-color: gray; $diff-swipe-border: #999; -$diff-view-modes-color: grey; +$diff-view-modes-color: gray; $diff-view-modes-border: #c1c1c1; $diff-jagged-border-gradient-color: darken($white-normal, 8%); @@ -352,9 +341,7 @@ $dropdown-min-height: 40px; $dropdown-max-height: 312px; $dropdown-vertical-offset: 4px; $dropdown-link-color: #555; -$dropdown-link-hover-bg: $blue-50; $dropdown-empty-row-bg: rgba(#000, 0.04); -$dropdown-border-color: $border-color; $dropdown-shadow-color: rgba(#000, 0.1); $dropdown-divider-color: rgba(#000, 0.1); $dropdown-title-btn-color: #bfbfbf; @@ -364,7 +351,6 @@ $dropdown-input-focus-shadow: rgba($blue-300, 0.4); $dropdown-loading-bg: rgba(#fff, 0.6); $dropdown-chevron-size: 10px; $dropdown-toggle-active-border-color: darken($border-color, 14%); -$dropdown-item-hover-bg: $gray-darker; $dropdown-fade-mask-height: 32px; $dropdown-member-form-control-width: 163px; @@ -372,7 +358,6 @@ $dropdown-member-form-control-width: 163px; * Filtered Search */ $filtered-search-term-shadow-color: rgba(0, 0, 0, 0.09); -$dropdown-hover-color: $blue-400; /* * Contextual Sidebar @@ -387,7 +372,7 @@ $sidebar-milestone-toggle-bottom-margin: 10px; * Buttons */ $btn-active-gray: #ececec; -$btn-active-gray-light: e4e7ed; +$btn-active-gray-light: #e4e7ed; $btn-white-active: #848484; $gl-btn-padding: 10px; $gl-btn-line-height: 16px; @@ -398,7 +383,6 @@ $gl-btn-horz-padding: 12px; * Badges */ $badge-bg: rgba(0, 0, 0, 0.07); -$badge-color: $gl-text-color-secondary; /* * Pagination @@ -406,21 +390,12 @@ $badge-color: $gl-text-color-secondary; $pagination-padding-y: 6px; $pagination-padding-x: 16px; $pagination-line-height: 20px; -$pagination-border-color: $border-color; -$pagination-active-bg: $blue-600; -$pagination-active-border-color: $blue-600; -$pagination-hover-bg: $blue-50; -$pagination-hover-border-color: $border-color; -$pagination-hover-color: $gl-text-color; $pagination-disabled-color: #cdcdcd; -$pagination-disabled-bg: $gray-light; -$pagination-disabled-border-color: $border-color; /* * Status icons */ $status-icon-size: 22px; -$status-icon-margin: $gl-btn-padding; /* * Award emoji @@ -433,16 +408,13 @@ $award-emoji-positive-add-lines: #bb9c13; * Search Box */ $search-input-border-color: rgba($blue-400, 0.8); -$search-input-focus-shadow-color: $dropdown-input-focus-shadow; $search-input-width: 240px; $search-input-active-width: 320px; -$location-badge-active-bg: $blue-500; $location-icon-color: #e7e9ed; /* * Notes */ -$notes-light-color: $gl-text-color-secondary; $note-disabled-comment-color: #b2b2b2; $note-targe3-outside: #fffff0; $note-targe3-inside: #ffffd3; @@ -463,7 +435,6 @@ $identicon-indigo: #e8eaf6; $identicon-blue: #e3f2fd; $identicon-teal: #e0f2f1; $identicon-orange: #fbe9e7; -$identicon-gray: $gray-darker; $identicon-fg-color: #555555; /* @@ -479,7 +450,6 @@ $calendar-user-contrib-text: #959494; $cycle-analytics-box-padding: 30px; $cycle-analytics-box-text-color: #8c8c8c; $cycle-analytics-big-font: 19px; -$cycle-analytics-dark-text: $gl-text-color; $cycle-analytics-light-gray: #bfbfbf; $cycle-analytics-dismiss-icon-color: #b2b2b2; @@ -507,9 +477,6 @@ $issue-board-list-difference-md: $issue-board-list-difference-sm + $issue-boards * Avatar */ $avatar-radius: 50%; -$avatar-border: $gray-normal; -$avatar-border-hover: $gray-darker; -$avatar-background: $gray-lightest; $gl-avatar-size: 40px; /* @@ -525,22 +492,6 @@ $blame-blue: #254e77; $builds-trace-bg: #111; /* -* Callout -*/ -$callout-danger-bg: $red-100; -$callout-danger-border: $red-200; -$callout-danger-color: $red-700; -$callout-warning-bg: $orange-100; -$callout-warning-border: $orange-200; -$callout-warning-color: $orange-700; -$callout-info-bg: $blue-100; -$callout-info-border: $blue-200; -$callout-info-color: $blue-700; -$callout-success-bg: $green-100; -$callout-success-border: $green-200; -$callout-success-color: $green-700; - -/* * Commit Page */ $commit-max-width-marker-color: rgba(0, 0, 0, 0); @@ -549,16 +500,8 @@ $commit-message-text-area-bg: rgba(0, 0, 0, 0); /* * Common */ -$common-gray: $gl-text-color; $common-gray-light: #bbb; $common-gray-dark: #444; -$common-red: $red-500; -$common-green: $green-600; - -/* -* Editor -*/ -$editor-cancel-color: $red-600; /* * Events @@ -579,7 +522,6 @@ $logs-p-color: #333; */ $input-height: 34px; $input-danger-bg: #f2dede; -$input-danger-border: $red-400; $input-group-addon-bg: #f7f8fa; $gl-field-focus-shadow: rgba(0, 0, 0, 0.075); $gl-field-focus-shadow-error: rgba($red-500, 0.6); @@ -626,16 +568,9 @@ $fade-mask-transition-duration: 0.1s; $fade-mask-transition-curve: ease-in-out; /* -* Lint -*/ -$lint-incorrect-color: $red-500; -$lint-correct-color: $green-500; - -/* * Login */ $login-brand-holder-color: #888; -$login-devise-error-color: $red-700; /* * Nav @@ -648,15 +583,12 @@ $nav-toggle-gray: #666; */ $notify-details: #777; $notify-footer: #777; -$notify-new-file: $green-600; -$notify-deleted-file: $red-700; /* * Projects */ $project-option-descr-color: #54565b; $project-breadcrumb-color: #999; -$project-private-forks-notice-odd: $green-600; $project-network-controls-color: #888; $feature-toggle-color: #fff; @@ -665,21 +597,10 @@ $feature-toggle-color-disabled: #999; $feature-toggle-color-enabled: #4a8bee; /* -* Runners -*/ -$runner-state-shared-bg: $green-400; -$runner-state-specific-bg: $blue-400; -$runner-status-online-color: $green-600; -$runner-status-offline-color: $gray-darkest; -$runner-status-paused-color: $red-500; - -/* Stat Graph */ $stat-graph-common-bg: #f3f3f3; -$stat-graph-area-fill: $green-500; $stat-graph-axis-fill: #aaa; -$stat-graph-orange-fill: $orange-500; $stat-graph-selection-fill: #333; $stat-graph-selection-stroke: #333; @@ -692,7 +613,6 @@ $select2-drop-shadow2: rgba(31, 37, 50, 0.317647); /* * Todo */ -$todo-alert-blue: $blue-500; $todo-body-pre-color: #777; $todo-body-border: #ddd; @@ -715,7 +635,6 @@ $ui-dev-kit-example-border: #ddd; /* Pipeline Graph */ -$stage-hover-bg: $gray-darker; $ci-action-icon-size: 22px; $ci-action-icon-size-lg: 24px; $pipeline-dropdown-line-height: 20px; @@ -743,13 +662,6 @@ Animation Functions $dropdown-animation-timing: cubic-bezier(0.23, 1, 0.32, 1); /* -Convdev Index -*/ -$color-high-score: $green-400; -$color-average-score: $orange-400; -$color-low-score: $red-400; - -/* Performance Bar */ $perf-bar-text: #999; @@ -790,9 +702,5 @@ Modals */ $modal-body-height: 134px; -/* -Prometheus -*/ -$prometheus-table-row-highlight-color: $theme-gray-100; $priority-label-empty-state-width: 114px; diff --git a/app/assets/stylesheets/framework/variables_overrides.scss b/app/assets/stylesheets/framework/variables_overrides.scss index b9c343fa2e9..7d90452e1f4 100644 --- a/app/assets/stylesheets/framework/variables_overrides.scss +++ b/app/assets/stylesheets/framework/variables_overrides.scss @@ -14,3 +14,7 @@ $btn-line-height: 20px; $table-accent-bg: $gray-light; $card-border-color: $border-color; $card-cap-bg: $gray-light; +$success: $green-500; +$info: $blue-500; +$warning: $orange-500; +$danger: $red-500; diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index 1696d18584d..14ba8b1df83 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -397,7 +397,7 @@ } &:hover { - background-color: $dropdown-item-hover-bg; + background-color: $gray-darker; } .icon-retry { diff --git a/app/assets/stylesheets/pages/convdev_index.scss b/app/assets/stylesheets/pages/convdev_index.scss index bd338326154..52fcdf4a405 100644 --- a/app/assets/stylesheets/pages/convdev_index.scss +++ b/app/assets/stylesheets/pages/convdev_index.scss @@ -80,7 +80,7 @@ $space-between-cards: 8px; } .convdev-card-low { - border-top-color: $color-low-score; + border-top-color: $red-400; .board-card-score-big { background-color: $red-50; @@ -88,7 +88,7 @@ $space-between-cards: 8px; } .convdev-card-average { - border-top-color: $color-average-score; + border-top-color: $orange-400; .board-card-score-big { background-color: $orange-50; @@ -96,7 +96,7 @@ $space-between-cards: 8px; } .convdev-card-high { - border-top-color: $color-high-score; + border-top-color: $green-400; .board-card-score-big { background-color: $green-50; @@ -243,13 +243,13 @@ $space-between-cards: 8px; } .convdev-high-score { - color: $color-high-score; + color: $green-400; } .convdev-average-score { - color: $color-average-score; + color: $orange-400; } .convdev-low-score { - color: $color-low-score; + color: $red-400; } diff --git a/app/assets/stylesheets/pages/cycle_analytics.scss b/app/assets/stylesheets/pages/cycle_analytics.scss index bc4c90711d7..f0228768b5a 100644 --- a/app/assets/stylesheets/pages/cycle_analytics.scss +++ b/app/assets/stylesheets/pages/cycle_analytics.scss @@ -285,7 +285,7 @@ .total-time { font-size: $cycle-analytics-big-font; - color: $cycle-analytics-dark-text; + color: $gl-text-color; span { color: $gl-text-color; diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss index 892da152b5f..04570c057d1 100644 --- a/app/assets/stylesheets/pages/editor.scss +++ b/app/assets/stylesheets/pages/editor.scss @@ -23,10 +23,10 @@ } .cancel-btn { - color: $editor-cancel-color; + color: $red-600; &:hover { - color: $editor-cancel-color; + color: $red-600; } } diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss index 179c0964567..196f6ae6d8c 100644 --- a/app/assets/stylesheets/pages/environments.scss +++ b/app/assets/stylesheets/pages/environments.scss @@ -501,5 +501,5 @@ } .prometheus-table-row-highlight { - background-color: $prometheus-table-row-highlight-color; + background-color: $theme-gray-100; } diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 6f0f82964c8..9ac47a771a5 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -144,7 +144,7 @@ color: $blue-800; .avatar { - border-color: rgba($avatar-border, .2); + border-color: rgba($gray-normal, .2); } } @@ -231,7 +231,7 @@ } a.edit-link:not([href]):hover { - color: rgba($avatar-border, .2); + color: rgba($gray-normal, .2); } .lock-edit, // uses same style, different js behaviour diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss index d32943fceec..d2b9470be69 100644 --- a/app/assets/stylesheets/pages/labels.scss +++ b/app/assets/stylesheets/pages/labels.scss @@ -67,7 +67,7 @@ .dropdown-labels-error { padding: 5px 10px; margin-bottom: 10px; - background-color: $gl-danger; + background-color: $red-500; color: $white-light; } @@ -117,7 +117,7 @@ color: $blue-600; &.remove-row { - color: $gl-danger; + color: $red-500; } } } diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss index 8a4a2caa6c9..c9e5fb9c579 100644 --- a/app/assets/stylesheets/pages/login.scss +++ b/app/assets/stylesheets/pages/login.scss @@ -186,7 +186,7 @@ h2 { margin-top: 0; font-size: 14px; - color: $login-devise-error-color; + color: $red-700; } } } diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index 621321101cd..7b8cad254c7 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -195,12 +195,13 @@ .ci-widget-content { display: flex; align-items: center; + flex: 1; } } .mr-widget-icon { font-size: 22px; - margin-right: $status-icon-margin; + margin-right: $gl-btn-padding; } .ci-status-icon svg { @@ -222,6 +223,7 @@ .normal { flex: 1; + flex-basis: auto; } .capitalize { @@ -235,22 +237,23 @@ font-weight: normal; overflow: hidden; word-break: break-all; + } - &.label-truncated { - position: relative; - display: inline-block; - width: 250px; - margin-bottom: -3px; - white-space: nowrap; - text-overflow: clip; - line-height: 14px; - - &::after { - position: absolute; - content: '...'; - right: 0; - font-family: $regular-font; - background-color: $gray-light; + .deploy-link, + .label-branch { + &.label-truncate { + // NOTE: This selector targets its children because some of the HTML comes from + // 'source_branch_link'. Once this external HTML is no longer used, we could + // simplify this. + > a, + > span { + display: inline-block; + max-width: 12.5em; + margin-bottom: -3px; + white-space: nowrap; + text-overflow: ellipsis; + line-height: 14px; + overflow: hidden; } } } @@ -281,7 +284,7 @@ margin-bottom: 0; &.has-conflicts .fa-exclamation-triangle { - color: $gl-warning; + color: $orange-500; } time { @@ -313,7 +316,7 @@ } .danger { - color: $gl-danger; + color: $red-500; } .spacing, @@ -514,7 +517,7 @@ } .mr-links { - padding-left: $status-icon-size + $status-icon-margin; + padding-left: $status-icon-size + $gl-btn-padding; } .mr-info-list { @@ -582,7 +585,7 @@ @include media-breakpoint-down(md) { flex-direction: column; - align-items: flex-start; + align-items: stretch; .branch-actions { margin-top: 16px; @@ -593,13 +596,13 @@ .branch-actions { align-self: center; margin-left: $gl-padding; + white-space: nowrap; } } } .diverged-commits-count { color: $gl-text-color-secondary; - font-size: 12px; } } @@ -918,7 +921,7 @@ flex: 1; flex-direction: row; - @include media-breakpoint-down(md) { + @include media-breakpoint-down(sm) { flex-direction: column; .stage-cell .stage-container { diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss index 4f861d43f55..ac7b701c2e2 100644 --- a/app/assets/stylesheets/pages/note_form.scss +++ b/app/assets/stylesheets/pages/note_form.scss @@ -74,13 +74,13 @@ } &.is-dropzone-hover { - border-color: $gl-success; + border-color: $green-500; box-shadow: 0 0 2px $black-transparent, - 0 0 4px $gl-success-focus; + 0 0 4px $green-500-focus; .comment-toolbar, .nav-links { - border-color: $gl-success; + border-color: $green-500; } } } diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index 2e1b2126887..fce04c58c24 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -443,7 +443,7 @@ ul.notes { .note-headline-light, .discussion-headline-light { - color: $notes-light-color; + color: $gl-text-color-secondary; } .discussion-headline-light { diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index ad057ed3c83..8bb8b83dc5e 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -19,7 +19,7 @@ background-color: $white-light; &:hover { - background-color: $stage-hover-bg; + background-color: $gray-darker; border: 1px solid $dropdown-toggle-active-border-color; color: $gl-text-color; } @@ -595,7 +595,7 @@ a.build-content:hover, button.build-content:hover { - background-color: $stage-hover-bg; + background-color: $gray-darker; border: 1px solid $dropdown-toggle-active-border-color; } @@ -668,7 +668,7 @@ display: block; &:hover { - background-color: $stage-hover-bg; + background-color: $gray-darker; border: 1px solid $dropdown-toggle-active-border-color; svg { @@ -835,7 +835,7 @@ button.mini-pipeline-graph-dropdown-toggle { display: block; &:hover { - background-color: $stage-hover-bg; + background-color: $gray-darker; border: 1px solid $dropdown-toggle-active-border-color; svg { @@ -934,7 +934,7 @@ button.mini-pipeline-graph-dropdown-toggle { &:focus { outline: none; text-decoration: none; - background-color: $stage-hover-bg; + background-color: $gray-darker; } } } diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index c11916454c8..a95e78931b1 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -394,23 +394,23 @@ } .vs-public { - color: $gl-primary; + color: $blue-500; } .vs-internal { - color: $gl-warning; + color: $orange-500; } .vs-private { - color: $gl-success; + color: $green-500; } .lfs-enabled { - color: $gl-success; + color: $green-500; } .lfs-disabled { - color: $gl-warning; + color: $orange-500; } .breadcrumb.repo-breadcrumb { @@ -731,7 +731,7 @@ background-color: transparent; font-size: $gl-font-size; line-height: $gl-btn-line-height; - color: $notes-light-color; + color: $gl-text-color-secondary; } .stat-link { @@ -900,7 +900,7 @@ pre.light-well { .private-forks-notice .private-fork-icon { i:nth-child(1) { - color: $project-private-forks-notice-odd; + color: $green-600; } i:nth-child(2) { @@ -1128,12 +1128,12 @@ pre.light-well { .project-ci-body { .incorrect-syntax { font-size: 18px; - color: $lint-incorrect-color; + color: $red-500; } .correct-syntax { font-size: 18px; - color: $lint-correct-color; + color: $green-500; } } diff --git a/app/assets/stylesheets/pages/runners.scss b/app/assets/stylesheets/pages/runners.scss index 2734faec558..59f01f3e958 100644 --- a/app/assets/stylesheets/pages/runners.scss +++ b/app/assets/stylesheets/pages/runners.scss @@ -4,24 +4,24 @@ color: $white-light; &.runner-state-shared { - background: $runner-state-shared-bg; + background: $green-400; } &.runner-state-specific { - background: $runner-state-specific-bg; + background: $blue-400; } } .runner-status-online { - color: $runner-status-online-color; + color: $green-600; } .runner-status-offline { - color: $runner-status-offline-color; + color: $gray-darkest; } .runner-status-paused { - color: $runner-status-paused-color; + color: $red-500; } .runner { diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss index 5b3a468cd1c..77119aea9e2 100644 --- a/app/assets/stylesheets/pages/search.scss +++ b/app/assets/stylesheets/pages/search.scss @@ -24,12 +24,12 @@ $search-avatar-size: 16px; .form-control:hover, :not[readonly] { border-color: lighten($blue-300, 20%); - box-shadow: 0 0 4px lighten($search-input-focus-shadow-color, 20%); + box-shadow: 0 0 4px lighten($dropdown-input-focus-shadow, 20%); } input[type='checkbox']:hover { - box-shadow: 0 0 2px 2px lighten($search-input-focus-shadow-color, 20%), - 0 0 0 1px lighten($search-input-focus-shadow-color, 20%); + box-shadow: 0 0 2px 2px lighten($dropdown-input-focus-shadow, 20%), + 0 0 0 1px lighten($dropdown-input-focus-shadow, 20%); } .search { @@ -181,7 +181,7 @@ input[type='checkbox']:hover { width: $search-avatar-size; height: $search-avatar-size; border-radius: 50%; - border: 1px solid $avatar-border; + border: 1px solid $gray-normal; } } diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss index 5aa4cdec9c3..e351dd7c0bb 100644 --- a/app/assets/stylesheets/pages/settings.scss +++ b/app/assets/stylesheets/pages/settings.scss @@ -120,11 +120,11 @@ } .warning-title { - color: $gl-warning; + color: $orange-500; } .danger-title { - color: $gl-danger; + color: $red-500; } .integration-settings-form { diff --git a/app/assets/stylesheets/pages/stat_graph.scss b/app/assets/stylesheets/pages/stat_graph.scss index 3f6f5f06075..d331edaa302 100644 --- a/app/assets/stylesheets/pages/stat_graph.scss +++ b/app/assets/stylesheets/pages/stat_graph.scss @@ -5,7 +5,7 @@ } .area { - fill: $stat-graph-area-fill; + fill: $green-500; fill-opacity: 0.5; } @@ -54,7 +54,7 @@ } .area-contributor { - fill: $stat-graph-orange-fill; + fill: $orange-500; } } } diff --git a/app/controllers/concerns/renders_commits.rb b/app/controllers/concerns/renders_commits.rb index fb41dc1e8a8..b1c9b1e532f 100644 --- a/app/controllers/concerns/renders_commits.rb +++ b/app/controllers/concerns/renders_commits.rb @@ -1,4 +1,24 @@ module RendersCommits + def limited_commits(commits) + if commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE + [ + commits.first(MergeRequestDiff::COMMITS_SAFE_SIZE), + commits.size - MergeRequestDiff::COMMITS_SAFE_SIZE + ] + else + [commits, 0] + end + end + + # This is used as a helper method in a controller. + # rubocop: disable Gitlab/ModuleWithInstanceVariables + def set_commits_for_rendering(commits) + @total_commit_count = commits.size + limited, @hidden_commit_count = limited_commits(commits) + prepare_commits_for_rendering(limited) + end + # rubocop: enable Gitlab/ModuleWithInstanceVariables + def prepare_commits_for_rendering(commits) Banzai::CommitRenderer.render(commits, @project, current_user) # rubocop:disable Gitlab/ModuleWithInstanceVariables diff --git a/app/controllers/concerns/toggle_award_emoji.rb b/app/controllers/concerns/toggle_award_emoji.rb index ba5b7d33f87..ae0b815f85e 100644 --- a/app/controllers/concerns/toggle_award_emoji.rb +++ b/app/controllers/concerns/toggle_award_emoji.rb @@ -5,7 +5,7 @@ module ToggleAwardEmoji authenticate_user! name = params.require(:name) - if awardable.user_can_award?(current_user, name) + if awardable.user_can_award?(current_user) awardable.toggle_award_emoji(name, current_user) todoable = to_todoable(awardable) diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index 44b176d304e..53637780a07 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -101,7 +101,7 @@ class Projects::CommitController < Projects::ApplicationController @branch_name = create_new_branch? ? @commit.cherry_pick_branch_name : @start_branch - create_commit(Commits::CherryPickService, success_notice: "The #{@commit.change_type_title(current_user)} has been successfully cherry-picked.", + create_commit(Commits::CherryPickService, success_notice: "The #{@commit.change_type_title(current_user)} has been successfully cherry-picked into #{@branch_name}.", success_path: -> { successful_change_path }, failure_path: failed_change_path) end diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb index 36faea8056e..5546bef850b 100644 --- a/app/controllers/projects/commits_controller.rb +++ b/app/controllers/projects/commits_controller.rb @@ -63,7 +63,7 @@ class Projects::CommitsController < Projects::ApplicationController end @commits = @commits.with_pipeline_status - @commits = prepare_commits_for_rendering(@commits) + @commits = set_commits_for_rendering(@commits) end # Rails 5 sets request.format from the extension. diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb index f93e500a07a..a1e12821caf 100644 --- a/app/controllers/projects/compare_controller.rb +++ b/app/controllers/projects/compare_controller.rb @@ -78,7 +78,7 @@ class Projects::CompareController < Projects::ApplicationController end def define_commits - @commits = compare.present? ? prepare_commits_for_rendering(compare.commits) : [] + @commits = compare.present? ? set_commits_for_rendering(@compare.commits) : [] end def define_diffs diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index ef8159aa553..c3ac8e107fb 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -113,7 +113,7 @@ class Projects::IssuesController < Projects::ApplicationController end def referenced_merge_requests - @merge_requests, @closed_by_merge_requests = ::Issues::FetchReferencedMergeRequestsService.new(project, current_user).execute(issue) + @merge_requests, @closed_by_merge_requests = ::Issues::ReferencedMergeRequestsService.new(project, current_user).execute(issue) respond_to do |format| format.json do diff --git a/app/controllers/projects/merge_requests/creations_controller.rb b/app/controllers/projects/merge_requests/creations_controller.rb index 81129456ad8..03d0290ac1d 100644 --- a/app/controllers/projects/merge_requests/creations_controller.rb +++ b/app/controllers/projects/merge_requests/creations_controller.rb @@ -101,7 +101,7 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap @target_project = @merge_request.target_project @source_project = @merge_request.source_project - @commits = prepare_commits_for_rendering(@merge_request.commits) + @commits = set_commits_for_rendering(@merge_request.commits) @commit = @merge_request.diff_head_commit @labels = LabelsFinder.new(current_user, project_id: @project.id).execute diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 1b069fe507b..d31b58972ca 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -79,7 +79,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo # Get commits from repository # or from cache if already merged @commits = - prepare_commits_for_rendering(@merge_request.commits.with_pipeline_status) + set_commits_for_rendering(@merge_request.commits.with_pipeline_status) render json: { html: view_to_html_string('projects/merge_requests/_commits') } end diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index 89fe90fd801..7a942c44ac4 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -210,17 +210,6 @@ module CommitsHelper Sanitize.clean(string, remove_contents: true) end - def limited_commits(commits) - if commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE - [ - commits.first(MergeRequestDiff::COMMITS_SAFE_SIZE), - commits.size - MergeRequestDiff::COMMITS_SAFE_SIZE - ] - else - [commits, 0] - end - end - def commit_path(project, commit, merge_request: nil) if merge_request&.persisted? diffs_project_merge_request_path(project, merge_request, commit_id: commit.id) diff --git a/app/helpers/import_helper.rb b/app/helpers/import_helper.rb index 4664b1728c4..c65f1565425 100644 --- a/app/helpers/import_helper.rb +++ b/app/helpers/import_helper.rb @@ -5,6 +5,10 @@ module ImportHelper false end + def sanitize_project_name(name) + name.gsub(/[^\w\-]/, '-') + end + def import_project_target(owner, name) namespace = current_user.can_create_group? ? owner : current_user.namespace_path "#{namespace}/#{name}" diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 96dc7ae1185..5b27d1d9404 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -92,14 +92,6 @@ module IssuesHelper end end - def award_user_authored_class(award) - if award == 'thumbsdown' || award == 'thumbsup' - 'user-authored js-user-authored' - else - '' - end - end - def awards_sort(awards) awards.sort_by do |award, award_emojis| if award == "thumbsup" diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 6b4079b4113..18b3badda8d 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -447,7 +447,7 @@ module ProjectsHelper end def project_permissions_panel_data(project) - data = { + { currentSettings: project_permissions_settings(project), canChangeVisibilityLevel: can_change_visibility_level?(project, current_user), allowedVisibilityOptions: project_allowed_visibility_levels(project), @@ -457,8 +457,10 @@ module ProjectsHelper lfsAvailable: Gitlab.config.lfs.enabled, lfsHelpPath: help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs') } + end - data.to_json.html_safe + def project_permissions_panel_data_json(project) + project_permissions_panel_data(project).to_json.html_safe end def project_allowed_visibility_levels(project) diff --git a/app/models/commit.rb b/app/models/commit.rb index 27fbdc3e386..594972ad344 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -193,6 +193,7 @@ class Commit # otherwise returns commit message without first line def description return safe_message if full_title.length >= 100 + return no_commit_message if safe_message.blank? safe_message.split("\n", 2)[1].try(:chomp) end diff --git a/app/models/concerns/awardable.rb b/app/models/concerns/awardable.rb index 49981db0d80..4200253053a 100644 --- a/app/models/concerns/awardable.rb +++ b/app/models/concerns/awardable.rb @@ -76,12 +76,8 @@ module Awardable true end - def awardable_votes?(name) - AwardEmoji::UPVOTE_NAME == name || AwardEmoji::DOWNVOTE_NAME == name - end - - def user_can_award?(current_user, name) - awardable_by_user?(current_user, name) && Ability.allowed?(current_user, :award_emoji, self) + def user_can_award?(current_user) + Ability.allowed?(current_user, :award_emoji, self) end def user_authored?(current_user) @@ -117,12 +113,4 @@ module Awardable def normalize_name(name) Gitlab::Emoji.normalize_emoji_name(name) end - - def awardable_by_user?(current_user, name) - if user_authored?(current_user) - !awardable_votes?(normalize_name(name)) - else - true - end - end end diff --git a/app/models/issue.rb b/app/models/issue.rb index 94cf12f3c2b..d0cd7461daa 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -170,27 +170,6 @@ class Issue < ActiveRecord::Base "#{project.to_reference(from, full: full)}#{reference}" end - def referenced_merge_requests(current_user = nil) - ext = all_references(current_user) - - notes_with_associations.each do |object| - object.all_references(current_user, extractor: ext) - end - - merge_requests = ext.merge_requests.sort_by(&:iid) - - cross_project_filter = -> (merge_requests) do - merge_requests.select { |mr| mr.target_project == project } - end - - Ability.merge_requests_readable_by_user( - merge_requests, current_user, - filters: { - read_cross_project: cross_project_filter - } - ) - end - # All branches containing the current issue's ID, except for # those with a merge request open referencing the current issue. def related_branches(current_user) @@ -198,7 +177,11 @@ class Issue < ActiveRecord::Base branch =~ /\A#{iid}-(?!\d+-stable)/i end - branches_with_merge_request = self.referenced_merge_requests(current_user).map(&:source_branch) + branches_with_merge_request = + Issues::ReferencedMergeRequestsService + .new(project, current_user) + .referenced_merge_requests(self) + .map(&:source_branch) branches_with_iid - branches_with_merge_request end @@ -225,26 +208,6 @@ class Issue < ActiveRecord::Base project end - # From all notes on this issue, we'll select the system notes about linked - # merge requests. Of those, the MRs closing `self` are returned. - def closed_by_merge_requests(current_user = nil) - return [] unless open? - - ext = all_references(current_user) - - notes.system.each do |note| - note.all_references(current_user, extractor: ext) - end - - merge_requests = ext.merge_requests.select(&:open?) - if merge_requests.any? - ids = MergeRequestsClosingIssues.where(merge_request_id: merge_requests.map(&:id), issue_id: id).pluck(:merge_request_id) - merge_requests.select { |mr| mr.id.in?(ids) } - else - [] - end - end - def moved? !moved_to.nil? end diff --git a/app/models/member.rb b/app/models/member.rb index 05c0bc8cb97..d9b4e8d2ac6 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -103,7 +103,7 @@ class Member < ActiveRecord::Base def filter_by_2fa(value) case value when 'enabled' - left_join_users.merge(User.with_two_factor_indistinct) + left_join_users.merge(User.with_two_factor) when 'disabled' left_join_users.merge(User.without_two_factor) else diff --git a/app/models/project.rb b/app/models/project.rb index 8f631d7f0ed..178d70757a1 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -2072,13 +2072,19 @@ class Project < ActiveRecord::Base private def rename_or_migrate_repository! - if Gitlab::CurrentSettings.hashed_storage_enabled? && storage_version != LATEST_STORAGE_VERSION + if Gitlab::CurrentSettings.hashed_storage_enabled? && + storage_upgradable? && + Feature.disabled?(:skip_hashed_storage_upgrade) # kill switch in case we need to disable upgrade behavior ::Projects::HashedStorageMigrationService.new(self, full_path_was).execute else storage.rename_repo end end + def storage_upgradable? + storage_version != LATEST_STORAGE_VERSION + end + def after_rename_repository(full_path_before, path_before) execute_rename_repository_hooks!(full_path_before) diff --git a/app/models/protected_tag.rb b/app/models/protected_tag.rb index a36f0d36262..94746141945 100644 --- a/app/models/protected_tag.rb +++ b/app/models/protected_tag.rb @@ -4,6 +4,8 @@ class ProtectedTag < ActiveRecord::Base include Gitlab::ShellAdapter include ProtectedRef + validates :name, uniqueness: { scope: :project_id } + protected_ref_access_levels :create def self.protected?(project, ref_name) diff --git a/app/models/remote_mirror.rb b/app/models/remote_mirror.rb index 833faf3bc82..c1f53b5da4f 100644 --- a/app/models/remote_mirror.rb +++ b/app/models/remote_mirror.rb @@ -150,6 +150,15 @@ class RemoteMirror < ActiveRecord::Base result.to_s end + def ensure_remote! + return unless project + return unless remote_name && url + + # If this fails or the remote already exists, we won't know due to + # https://gitlab.com/gitlab-org/gitaly/issues/1317 + project.repository.add_remote(remote_name, url) + end + private def raw diff --git a/app/models/user.rb b/app/models/user.rb index a6ba90794d6..f21ca1c569f 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -289,13 +289,16 @@ class User < ActiveRecord::Base end end - def self.with_two_factor_indistinct - joins("LEFT OUTER JOIN u2f_registrations AS u2f ON u2f.user_id = users.id") - .where("u2f.id IS NOT NULL OR users.otp_required_for_login = ?", true) - end - def self.with_two_factor - with_two_factor_indistinct.distinct(arel_table[:id]) + with_u2f_registrations = <<-SQL + EXISTS ( + SELECT * + FROM u2f_registrations AS u2f + WHERE u2f.user_id = users.id + ) OR users.otp_required_for_login = ? + SQL + + where(with_u2f_registrations, true) end def self.without_two_factor diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index 637c1df4ad9..26e90e8cf8c 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -140,7 +140,6 @@ class GitPushService < BaseService EventCreateService.new.push(project, current_user, build_push_data) Ci::CreatePipelineService.new(project, current_user, build_push_data).execute(:push) - SystemHookPushWorker.perform_async(build_push_data.dup, :push_hooks) project.execute_hooks(build_push_data.dup, :push_hooks) project.execute_services(build_push_data.dup, :push_hooks) @@ -159,7 +158,7 @@ class GitPushService < BaseService end def process_default_branch - offset = [push_commits_count - PROCESS_COMMIT_LIMIT, 0].max + offset = [push_commits_count_for_ref - PROCESS_COMMIT_LIMIT, 0].max @push_commits = project.repository.commits(params[:newrev], offset: offset, limit: PROCESS_COMMIT_LIMIT) project.after_create_default_branch @@ -173,7 +172,7 @@ class GitPushService < BaseService params[:newrev], params[:ref], @push_commits, - commits_count: push_commits_count) + commits_count: commits_count) end def push_to_existing_branch? @@ -214,8 +213,14 @@ class GitPushService < BaseService end end - def push_commits_count - strong_memoize(:push_commits_count) do + def commits_count + return push_commits_count_for_ref if default_branch? && push_to_new_branch? + + Array(@push_commits).size + end + + def push_commits_count_for_ref + strong_memoize(:push_commits_count_for_ref) do project.repository.commit_count_for_ref(params[:ref]) end end diff --git a/app/services/issues/fetch_referenced_merge_requests_service.rb b/app/services/issues/fetch_referenced_merge_requests_service.rb deleted file mode 100644 index 5e84f3c81c9..00000000000 --- a/app/services/issues/fetch_referenced_merge_requests_service.rb +++ /dev/null @@ -1,14 +0,0 @@ -# frozen_string_literal: true - -module Issues - class FetchReferencedMergeRequestsService < Issues::BaseService - def execute(issue) - referenced_merge_requests = issue.referenced_merge_requests(current_user) - referenced_merge_requests = Gitlab::IssuableSorter.sort(project, referenced_merge_requests) { |i| i.iid.to_s } - closed_by_merge_requests = issue.closed_by_merge_requests(current_user) - closed_by_merge_requests = Gitlab::IssuableSorter.sort(project, closed_by_merge_requests) { |i| i.iid.to_s } - - [referenced_merge_requests, closed_by_merge_requests] - end - end -end diff --git a/app/services/issues/referenced_merge_requests_service.rb b/app/services/issues/referenced_merge_requests_service.rb new file mode 100644 index 00000000000..40d78502697 --- /dev/null +++ b/app/services/issues/referenced_merge_requests_service.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +module Issues + class ReferencedMergeRequestsService < Issues::BaseService + def execute(issue) + referenced = referenced_merge_requests(issue) + closed_by = closed_by_merge_requests(issue) + preloader = ActiveRecord::Associations::Preloader.new + + preloader.preload(referenced + closed_by, + head_pipeline: { project: [:route, { namespace: :route }] }) + + [sort_by_iid(referenced), sort_by_iid(closed_by)] + end + + def referenced_merge_requests(issue) + merge_requests = extract_merge_requests(issue) + + cross_project_filter = -> (merge_requests) do + merge_requests.select { |mr| mr.target_project == project } + end + + Ability.merge_requests_readable_by_user( + merge_requests, + current_user, + filters: { + read_cross_project: cross_project_filter + } + ) + end + + def closed_by_merge_requests(issue) + return [] unless issue.open? + + merge_requests = extract_merge_requests(issue, filter: :system).select(&:open?) + + return [] if merge_requests.empty? + + ids = MergeRequestsClosingIssues.where(merge_request_id: merge_requests.map(&:id), issue_id: issue.id).pluck(:merge_request_id) + merge_requests.select { |mr| mr.id.in?(ids) } + end + + private + + def extract_merge_requests(issue, filter: nil) + ext = issue.all_references(current_user) + notes = issue_notes(issue) + notes = notes.select(&filter) if filter + + notes.each do |note| + note.all_references(current_user, extractor: ext) + end + + ext.merge_requests + end + + def issue_notes(issue) + @issue_notes ||= {} + @issue_notes[issue] ||= issue.notes.includes(:author) + end + + def sort_by_iid(merge_requests) + Gitlab::IssuableSorter.sort(project, merge_requests) { |mr| mr.iid.to_s } + end + end +end diff --git a/app/services/projects/update_remote_mirror_service.rb b/app/services/projects/update_remote_mirror_service.rb index 4651f7c4f8f..591b38b8151 100644 --- a/app/services/projects/update_remote_mirror_service.rb +++ b/app/services/projects/update_remote_mirror_service.rb @@ -10,6 +10,7 @@ module Projects return success unless remote_mirror.enabled? begin + remote_mirror.ensure_remote! repository.fetch_remote(remote_mirror.remote_name, no_tags: true) opts = {} diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb index 8838ed06324..a4c4c9e4812 100644 --- a/app/services/quick_actions/interpret_service.rb +++ b/app/services/quick_actions/interpret_service.rb @@ -402,7 +402,7 @@ module QuickActions match[1] if match end command :award do |name| - if name && issuable.user_can_award?(current_user, name) + if name && issuable.user_can_award?(current_user) @updates[:emoji_award] = name end end diff --git a/app/views/award_emoji/_awards_block.html.haml b/app/views/award_emoji/_awards_block.html.haml index 8ca9fb4512e..30d7b21b1b8 100644 --- a/app/views/award_emoji/_awards_block.html.haml +++ b/app/views/award_emoji/_awards_block.html.haml @@ -3,7 +3,7 @@ .awards.js-awards-block{ class: ("hidden" if !inline && grouped_emojis.empty?), data: { award_url: toggle_award_url(awardable) } } - awards_sort(grouped_emojis).each do |emoji, awards| %button.btn.award-control.js-emoji-btn.has-tooltip{ type: "button", - class: [(award_state_class(awardable, awards, current_user)), (award_user_authored_class(emoji) if user_authored)], + class: [(award_state_class(awardable, awards, current_user))], data: { placement: "bottom", title: award_user_list(awards, current_user) } } = emoji_icon(emoji) %span.award-control-text.js-counter @@ -13,7 +13,6 @@ .award-menu-holder.js-award-holder %button.btn.award-control.has-tooltip.js-add-award{ type: 'button', 'aria-label': _('Add reaction'), - class: ("js-user-authored" if user_authored), data: { title: _('Add reaction'), placement: "bottom" } } %span{ class: "award-control-icon award-control-icon-neutral" }= custom_icon('emoji_slightly_smiling_face') %span{ class: "award-control-icon award-control-icon-positive" }= custom_icon('emoji_smiley') diff --git a/app/views/import/_githubish_status.html.haml b/app/views/import/_githubish_status.html.haml index f0d1e837317..f4a29ed18dc 100644 --- a/app/views/import/_githubish_status.html.haml +++ b/app/views/import/_githubish_status.html.haml @@ -45,7 +45,7 @@ = text_field_tag :path, current_user.namespace_path, class: "input-group-text input-large form-control", tabindex: 1, disabled: true %span.input-group-prepend .input-group-text / - = text_field_tag :path, repo.name, class: "input-mini form-control", tabindex: 2, autofocus: true, required: true + = text_field_tag :path, sanitize_project_name(repo.name), class: "input-mini form-control", tabindex: 2, autofocus: true, required: true %td.import-actions.job-status = button_tag class: "btn btn-import js-add-to-import" do = has_ci_cd_only_params? ? _('Connect') : _('Import') diff --git a/app/views/import/bitbucket/status.html.haml b/app/views/import/bitbucket/status.html.haml index a75b7aa9dd2..3b1b5e55302 100644 --- a/app/views/import/bitbucket/status.html.haml +++ b/app/views/import/bitbucket/status.html.haml @@ -63,7 +63,7 @@ = text_field_tag :path, current_user.namespace_path, class: "input-group-text input-large form-control", tabindex: 1, disabled: true %span.input-group-prepend .input-group-text / - = text_field_tag :path, repo.name, class: "input-mini form-control", tabindex: 2, autofocus: true, required: true + = text_field_tag :path, sanitize_project_name(repo.slug), class: "input-mini form-control", tabindex: 2, autofocus: true, required: true %td.import-actions.job-status = button_tag class: 'btn btn-import js-add-to-import' do = _('Import') diff --git a/app/views/import/bitbucket_server/status.html.haml b/app/views/import/bitbucket_server/status.html.haml index 3d05a5e696f..ae09e0dfa18 100644 --- a/app/views/import/bitbucket_server/status.html.haml +++ b/app/views/import/bitbucket_server/status.html.haml @@ -61,7 +61,7 @@ = text_field_tag :path, current_user.namespace_path, class: "input-group-text input-large form-control", tabindex: 1, disabled: true %span.input-group-prepend .input-group-text / - = text_field_tag :path, repo.name, class: "input-mini form-control", tabindex: 2, autofocus: true, required: true + = text_field_tag :path, sanitize_project_name(repo.slug), class: "input-mini form-control", tabindex: 2, autofocus: true, required: true %td.import-actions.job-status = button_tag class: 'btn btn-import js-add-to-import' do Import diff --git a/app/views/projects/commits/_commit_list.html.haml b/app/views/projects/commits/_commit_list.html.haml index 8f8eb2c3d5a..6ed65d07202 100644 --- a/app/views/projects/commits/_commit_list.html.haml +++ b/app/views/projects/commits/_commit_list.html.haml @@ -1,9 +1,10 @@ -- commits, hidden = limited_commits(@commits) +- commits = @commits +- hidden = @hidden_commit_count - commits = Commit.decorate(commits, @project) .card .card-header - Commits (#{@commits.count}) + Commits (#{@total_commit_count}) - if hidden > 0 %ul.content-list - commits.each do |commit| diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml index ac6852751be..ec05ff50f25 100644 --- a/app/views/projects/commits/_commits.html.haml +++ b/app/views/projects/commits/_commits.html.haml @@ -2,7 +2,8 @@ - project = local_assigns.fetch(:project) { merge_request&.project } - ref = local_assigns.fetch(:ref) { merge_request&.source_branch } -- commits, hidden = limited_commits(@commits) +- commits = @commits +- hidden = @hidden_commit_count - commits.chunk { |c| c.committed_date.in_time_zone.to_date }.each do |day, commits| %li.commit-header.js-commit-header{ data: { day: day } } diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 30544dde451..e37a444c1c9 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -78,7 +78,7 @@ = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "sharing-permissions-form" }, authenticity_token: true do |f| %input{ name: 'update_section', type: 'hidden', value: 'js-shared-permissions' } -# haml-lint:disable InlineJavaScript - %script.js-project-permissions-form-data{ type: "application/json" }= project_permissions_panel_data(@project) + %script.js-project-permissions-form-data{ type: "application/json" }= project_permissions_panel_data_json(@project) .js-project-permissions-form = f.submit 'Save changes', class: "btn btn-save" diff --git a/app/views/projects/merge_requests/creations/_new_submit.html.haml b/app/views/projects/merge_requests/creations/_new_submit.html.haml index f7a5d85500f..d5c4134dee2 100644 --- a/app/views/projects/merge_requests/creations/_new_submit.html.haml +++ b/app/views/projects/merge_requests/creations/_new_submit.html.haml @@ -33,7 +33,7 @@ %li.commits-tab.new-tab = link_to url_for(safe_params), data: {target: 'div#commits', action: 'new', toggle: 'tabvue'} do Commits - %span.badge.badge-pill= @commits.size + %span.badge.badge-pill= @total_commit_count - if @pipelines.any? %li.builds-tab = link_to url_for(safe_params.merge(action: 'pipelines')), data: {target: 'div#pipelines', action: 'pipelines', toggle: 'tabvue'} do diff --git a/app/views/projects/notes/_actions.html.haml b/app/views/projects/notes/_actions.html.haml index b4fe1cabdfd..e9008d60098 100644 --- a/app/views/projects/notes/_actions.html.haml +++ b/app/views/projects/notes/_actions.html.haml @@ -40,7 +40,7 @@ - if note.emoji_awardable? - user_authored = note.user_authored?(current_user) .note-actions-item - = button_tag title: 'Add reaction', class: "note-action-button note-emoji-button js-add-award js-note-emoji #{'js-user-authored' if user_authored} has-tooltip btn btn-transparent", data: { position: 'right', container: 'body' } do + = button_tag title: 'Add reaction', class: "note-action-button note-emoji-button js-add-award js-note-emoji} has-tooltip btn btn-transparent", data: { position: 'right', container: 'body' } do = icon('spinner spin') %span{ class: 'link-highlight award-control-icon-neutral' }= custom_icon('emoji_slightly_smiling_face') %span{ class: 'link-highlight award-control-icon-positive' }= custom_icon('emoji_smiley') diff --git a/app/views/snippets/notes/_actions.html.haml b/app/views/snippets/notes/_actions.html.haml index 3a50324770d..e1f7ee80ebb 100644 --- a/app/views/snippets/notes/_actions.html.haml +++ b/app/views/snippets/notes/_actions.html.haml @@ -2,7 +2,7 @@ - if note.emoji_awardable? - user_authored = note.user_authored?(current_user) .note-actions-item - = link_to '#', title: 'Add reaction', class: "note-action-button note-emoji-button js-add-award js-note-emoji #{'js-user-authored' if user_authored} has-tooltip", data: { position: 'right' } do + = link_to '#', title: 'Add reaction', class: "note-action-button note-emoji-button js-add-award js-note-emoji has-tooltip", data: { position: 'right' } do = icon('spinner spin') %span{ class: 'link-highlight award-control-icon-neutral' }= custom_icon('emoji_slightly_smiling_face') %span{ class: 'link-highlight award-control-icon-positive' }= custom_icon('emoji_smiley') diff --git a/changelogs/unreleased/1756-set-iid-via-api.yml b/changelogs/unreleased/1756-set-iid-via-api.yml deleted file mode 100644 index 680a9464ab4..00000000000 --- a/changelogs/unreleased/1756-set-iid-via-api.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Allow issues API to receive an internal ID (iid) on create -merge_request: 20626 -author: Jamie Schembri -type: fixed diff --git a/changelogs/unreleased/21326-avoid-nil-safe-message.yml b/changelogs/unreleased/21326-avoid-nil-safe-message.yml new file mode 100644 index 00000000000..ca1a89191a8 --- /dev/null +++ b/changelogs/unreleased/21326-avoid-nil-safe-message.yml @@ -0,0 +1,5 @@ +--- +title: "Avoid nil safe message" +merge_request: 21326 +author: Yi Siliang +type: fixed diff --git a/changelogs/unreleased/23705-add-single-file-download-in-repo.yml b/changelogs/unreleased/23705-add-single-file-download-in-repo.yml deleted file mode 100644 index f156bfb1101..00000000000 --- a/changelogs/unreleased/23705-add-single-file-download-in-repo.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add download button for single file (including raw files) in repository -merge_request: 20480 -author: Kia Mei Somabes -type: added diff --git a/changelogs/unreleased/25990-improve-web-terminal.yml b/changelogs/unreleased/25990-improve-web-terminal.yml deleted file mode 100644 index 3f8a8c6211c..00000000000 --- a/changelogs/unreleased/25990-improve-web-terminal.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Move xterm to a node dependency and remove it from vendor's folder -merge_request: 20588 -author: -type: other diff --git a/changelogs/unreleased/25990-interactive-web-terminals-authorization.yml b/changelogs/unreleased/25990-interactive-web-terminals-authorization.yml deleted file mode 100644 index 0a2853c20c6..00000000000 --- a/changelogs/unreleased/25990-interactive-web-terminals-authorization.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix authorization for interactive web terminals -merge_request: 20811 -author: -type: fixed diff --git a/changelogs/unreleased/27456-improve-feedback-when-dev-cannot-push-to-empty-repo.yml b/changelogs/unreleased/27456-improve-feedback-when-dev-cannot-push-to-empty-repo.yml deleted file mode 100644 index 55d82c4ee5d..00000000000 --- a/changelogs/unreleased/27456-improve-feedback-when-dev-cannot-push-to-empty-repo.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Improve feedback when a developer is unable to push to an empty repository -merge_request: 20519 -author: -type: changed diff --git a/changelogs/unreleased/29278-commits-page-tooltips.yml b/changelogs/unreleased/29278-commits-page-tooltips.yml deleted file mode 100644 index d54301a1cf0..00000000000 --- a/changelogs/unreleased/29278-commits-page-tooltips.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Remove tooltips from commit author avatar and name in commit lists -merge_request: 20674 -author: -type: other diff --git a/changelogs/unreleased/31576-redirect-commits-to-root-if-no-ref.yml b/changelogs/unreleased/31576-redirect-commits-to-root-if-no-ref.yml deleted file mode 100644 index 21d9d25d342..00000000000 --- a/changelogs/unreleased/31576-redirect-commits-to-root-if-no-ref.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Redirect commits to root if no ref is provided (31576) -merge_request: 20738 -author: Kia Mei Somabes -type: added diff --git a/changelogs/unreleased/32783-api-all-members-with-ancestors.yml b/changelogs/unreleased/32783-api-all-members-with-ancestors.yml deleted file mode 100644 index ca53d02845d..00000000000 --- a/changelogs/unreleased/32783-api-all-members-with-ancestors.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: Adds API endpoint /api/v4/(project/group)/:id/members/all to list also inherited - members -merge_request: 19748 -author: Jacopo Beschi @jacopo-beschi -type: added diff --git a/changelogs/unreleased/32821-better-error-message-add-invalid-user-to-project.yml b/changelogs/unreleased/32821-better-error-message-add-invalid-user-to-project.yml deleted file mode 100644 index 587d7209c2f..00000000000 --- a/changelogs/unreleased/32821-better-error-message-add-invalid-user-to-project.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Improve error message when adding invalid user to a project -merge_request: 20885 -author: Jacopo Beschi @jacopo-beschi -type: added diff --git a/changelogs/unreleased/34572-ssh-certificates.yml b/changelogs/unreleased/34572-ssh-certificates.yml deleted file mode 100644 index 76a08a188de..00000000000 --- a/changelogs/unreleased/34572-ssh-certificates.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add support for SSH certificate authentication -merge_request: 19911 -author: Ævar Arnfjörð Bjarmason -type: added diff --git a/changelogs/unreleased/35952-keep-admin-settings-open-after-submit.yml b/changelogs/unreleased/35952-keep-admin-settings-open-after-submit.yml deleted file mode 100644 index e1e5c8db046..00000000000 --- a/changelogs/unreleased/35952-keep-admin-settings-open-after-submit.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Keep admin settings sections open after submitting forms -merge_request: 21040 -author: -type: other diff --git a/changelogs/unreleased/36409-frontend-for-clarifying-the-usefulness-of-the-search-bar.yml b/changelogs/unreleased/36409-frontend-for-clarifying-the-usefulness-of-the-search-bar.yml deleted file mode 100644 index efa13c9ab3c..00000000000 --- a/changelogs/unreleased/36409-frontend-for-clarifying-the-usefulness-of-the-search-bar.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: UX improvements to top nav search bar -merge_request: 20537 -author: -type: changed diff --git a/changelogs/unreleased/38604-add-private-profile.yml b/changelogs/unreleased/38604-add-private-profile.yml deleted file mode 100644 index e40e7d9321e..00000000000 --- a/changelogs/unreleased/38604-add-private-profile.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add an option to have a private profile on GitLab. -merge_request: 20387 -author: jxterry -type: added diff --git a/changelogs/unreleased/40973-disable-rack-attack-by-default.yml b/changelogs/unreleased/40973-disable-rack-attack-by-default.yml deleted file mode 100644 index 681aa761e2a..00000000000 --- a/changelogs/unreleased/40973-disable-rack-attack-by-default.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Rack attack is now disabled by default -merge_request: 16669 -author: -type: changed diff --git a/changelogs/unreleased/41416-making-instance-wide-data-tools-more-accessible.yml b/changelogs/unreleased/41416-making-instance-wide-data-tools-more-accessible.yml deleted file mode 100644 index b980b719d68..00000000000 --- a/changelogs/unreleased/41416-making-instance-wide-data-tools-more-accessible.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Allow non-admins to view instance statistics (if permitted by the instance admins) -merge_request: 20874 -author: -type: changed diff --git a/changelogs/unreleased/41441-add-target-branch-name-to-cherrypick-confirmation.yml b/changelogs/unreleased/41441-add-target-branch-name-to-cherrypick-confirmation.yml new file mode 100644 index 00000000000..c23676a3104 --- /dev/null +++ b/changelogs/unreleased/41441-add-target-branch-name-to-cherrypick-confirmation.yml @@ -0,0 +1,5 @@ +--- +title: Add target branch name to cherrypick confirmation message +merge_request: 20846 +author: George Andrinopoulos +type: other diff --git a/changelogs/unreleased/41671-fixing-milestone-date-change-when-editing.yml b/changelogs/unreleased/41671-fixing-milestone-date-change-when-editing.yml deleted file mode 100644 index c6a0dc4f129..00000000000 --- a/changelogs/unreleased/41671-fixing-milestone-date-change-when-editing.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: "Fixing milestone date change when editing" -merge_request: 20279 -author: Orlando Del Aguila -type: fixed
\ No newline at end of file diff --git a/changelogs/unreleased/41784-monitoring-graph-popovers.yml b/changelogs/unreleased/41784-monitoring-graph-popovers.yml deleted file mode 100644 index 757445d7e0c..00000000000 --- a/changelogs/unreleased/41784-monitoring-graph-popovers.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update design for system metrics popovers -merge_request: 20655 -author: -type: fixed diff --git a/changelogs/unreleased/42415-omit-projects-from-get-group-endpoint.yml b/changelogs/unreleased/42415-omit-projects-from-get-group-endpoint.yml deleted file mode 100644 index cabe5216045..00000000000 --- a/changelogs/unreleased/42415-omit-projects-from-get-group-endpoint.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Adds with_projects optional parameter to GET /groups/:id API endpoint -merge_request: 20494 -author: -type: changed diff --git a/changelogs/unreleased/43011-typecast-markdownversion-prop-notesapp.yml b/changelogs/unreleased/43011-typecast-markdownversion-prop-notesapp.yml deleted file mode 100644 index b60aeba860a..00000000000 --- a/changelogs/unreleased/43011-typecast-markdownversion-prop-notesapp.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix Vue datatype errors for markdownVersion parsing -merge_request: 20800 -author: -type: fixed diff --git a/changelogs/unreleased/43096-controller-projects-issuescontroller-referenced_merge_requests-json-executes-more-than-100-sql-queries.yml b/changelogs/unreleased/43096-controller-projects-issuescontroller-referenced_merge_requests-json-executes-more-than-100-sql-queries.yml new file mode 100644 index 00000000000..f4744c868ef --- /dev/null +++ b/changelogs/unreleased/43096-controller-projects-issuescontroller-referenced_merge_requests-json-executes-more-than-100-sql-queries.yml @@ -0,0 +1,5 @@ +--- +title: Improve performance when fetching related merge requests for an issue +merge_request: 21237 +author: +type: performance diff --git a/changelogs/unreleased/43312-remove_user_activity_workers.yml b/changelogs/unreleased/43312-remove_user_activity_workers.yml deleted file mode 100644 index 6dfd018e350..00000000000 --- a/changelogs/unreleased/43312-remove_user_activity_workers.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Delete UserActivities and related workers -merge_request: 20597 -author: -type: performance diff --git a/changelogs/unreleased/44127-board-label-edit-drop-down-is-showing-incorrect-selected-labels-summary.yml b/changelogs/unreleased/44127-board-label-edit-drop-down-is-showing-incorrect-selected-labels-summary.yml deleted file mode 100644 index de991ef475a..00000000000 --- a/changelogs/unreleased/44127-board-label-edit-drop-down-is-showing-incorrect-selected-labels-summary.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Board label edit dropdown shows incorrect selected labels summary -merge_request: 20673 -author: -type: fixed diff --git a/changelogs/unreleased/44824-remove-ghost-notification-settings-for-group-and-project.yml b/changelogs/unreleased/44824-remove-ghost-notification-settings-for-group-and-project.yml deleted file mode 100644 index ddc878ee710..00000000000 --- a/changelogs/unreleased/44824-remove-ghost-notification-settings-for-group-and-project.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Adds foreign key to notification_settings.user_id -merge_request: 20567 -author: Jacopo Beschi @jacopo-beschi -type: added diff --git a/changelogs/unreleased/45318-junit-FE.yml b/changelogs/unreleased/45318-junit-FE.yml deleted file mode 100644 index bbc08f54484..00000000000 --- a/changelogs/unreleased/45318-junit-FE.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Adds frontend support to render test reports on the MR widget -merge_request: 20936 -author: -type: added diff --git a/changelogs/unreleased/45318-vuex-store.yml b/changelogs/unreleased/45318-vuex-store.yml deleted file mode 100644 index 5ea89034bce..00000000000 --- a/changelogs/unreleased/45318-vuex-store.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Adds Vuex store for reports section in MR widget -merge_request: 20709 -author: -type: added diff --git a/changelogs/unreleased/45443-unable-to-save-user-profile-update-with-safari.yml b/changelogs/unreleased/45443-unable-to-save-user-profile-update-with-safari.yml deleted file mode 100644 index b18f7aec546..00000000000 --- a/changelogs/unreleased/45443-unable-to-save-user-profile-update-with-safari.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Resolve "Unable to save user profile update with Safari" -merge_request: 20676 -author: -type: fixed diff --git a/changelogs/unreleased/46165-web-ide-branch-picker.yml b/changelogs/unreleased/46165-web-ide-branch-picker.yml deleted file mode 100644 index ff879cb3d37..00000000000 --- a/changelogs/unreleased/46165-web-ide-branch-picker.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Create branch and MR picker for Web IDE -merge_request: 20978 -author: -type: changed diff --git a/changelogs/unreleased/46535-orphaned-uploads.yml b/changelogs/unreleased/46535-orphaned-uploads.yml deleted file mode 100644 index 1cd087a6aad..00000000000 --- a/changelogs/unreleased/46535-orphaned-uploads.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Clean orphaned files in object storage -merge_request: 20918 -author: -type: added diff --git a/changelogs/unreleased/46703-group-dashboard-line-height-is-too-tall-for-group-names.yml b/changelogs/unreleased/46703-group-dashboard-line-height-is-too-tall-for-group-names.yml deleted file mode 100644 index 5b91c6d5a9f..00000000000 --- a/changelogs/unreleased/46703-group-dashboard-line-height-is-too-tall-for-group-names.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Solves group dashboard line height is too tall for group names. -merge_request: 21033 -author: -type: fixed diff --git a/changelogs/unreleased/46869-deploy-tokens-failed-to-clone-lfs-repository.yml b/changelogs/unreleased/46869-deploy-tokens-failed-to-clone-lfs-repository.yml deleted file mode 100644 index d490df58144..00000000000 --- a/changelogs/unreleased/46869-deploy-tokens-failed-to-clone-lfs-repository.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Allow cloning LFS repositories through DeployTokens -merge_request: 20729 -author: -type: other diff --git a/changelogs/unreleased/46930-fix-updated_at-if-created_at-is-set-note-api.yml b/changelogs/unreleased/46930-fix-updated_at-if-created_at-is-set-note-api.yml deleted file mode 100644 index d95714a5267..00000000000 --- a/changelogs/unreleased/46930-fix-updated_at-if-created_at-is-set-note-api.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix updated_at if created_at is set for Note API -merge_request: -author: -type: fixed diff --git a/changelogs/unreleased/46940-hashed-storage-extend-enable-hashed-storage-for-all-new-projects-to-for-all-new-and-renamed-projects.yml b/changelogs/unreleased/46940-hashed-storage-extend-enable-hashed-storage-for-all-new-projects-to-for-all-new-and-renamed-projects.yml deleted file mode 100644 index 71e523e6de8..00000000000 --- a/changelogs/unreleased/46940-hashed-storage-extend-enable-hashed-storage-for-all-new-projects-to-for-all-new-and-renamed-projects.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Enable hashed storage for all newly created or renamed projects -merge_request: 19747 -author: -type: changed diff --git a/changelogs/unreleased/47156-improve-auto-devops-settings.yml b/changelogs/unreleased/47156-improve-auto-devops-settings.yml deleted file mode 100644 index d8993565047..00000000000 --- a/changelogs/unreleased/47156-improve-auto-devops-settings.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Improve and simplify Auto DevOps settings flow -merge_request: 20946 -author: -type: other diff --git a/changelogs/unreleased/47419-Fix-breadcrumbs.yml b/changelogs/unreleased/47419-Fix-breadcrumbs.yml deleted file mode 100644 index 1a7f8196683..00000000000 --- a/changelogs/unreleased/47419-Fix-breadcrumbs.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix breadcrumbs in Admin/User interface. -merge_request: 19608 -author: Robin Naundorf -type: fixed diff --git a/changelogs/unreleased/47548-monospace-commit-messages.yml b/changelogs/unreleased/47548-monospace-commit-messages.yml deleted file mode 100644 index 7344f72207b..00000000000 --- a/changelogs/unreleased/47548-monospace-commit-messages.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update commit message styles with monospace font and overflow-x -merge_request: 20988 -author: -type: changed diff --git a/changelogs/unreleased/47728-mr-api-documentation-changes.yml b/changelogs/unreleased/47728-mr-api-documentation-changes.yml deleted file mode 100644 index 12720f280a1..00000000000 --- a/changelogs/unreleased/47728-mr-api-documentation-changes.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Remove changes_count from MR API documentation where necessary -merge_request: 19745 -author: Jan Beckmann -type: fixed diff --git a/changelogs/unreleased/47768-web-ide-redesign-header.yml b/changelogs/unreleased/47768-web-ide-redesign-header.yml deleted file mode 100644 index 49133158164..00000000000 --- a/changelogs/unreleased/47768-web-ide-redesign-header.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Redesign Web IDE back button and context header -merge_request: 20850 -author: -type: changed diff --git a/changelogs/unreleased/48036-fix-web-ide-blob-crash.yml b/changelogs/unreleased/48036-fix-web-ide-blob-crash.yml deleted file mode 100644 index 6ff209b5181..00000000000 --- a/changelogs/unreleased/48036-fix-web-ide-blob-crash.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix Web IDE crashing on directories named 'blob' -merge_request: 20712 -author: -type: fixed diff --git a/changelogs/unreleased/48055-web-ide-resize-handles.yml b/changelogs/unreleased/48055-web-ide-resize-handles.yml deleted file mode 100644 index 0f650cdda6f..00000000000 --- a/changelogs/unreleased/48055-web-ide-resize-handles.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Increase width of Web IDE sidebar resize handles -merge_request: 20818 -author: -type: fixed diff --git a/changelogs/unreleased/48098-mutual-auth-cluster-applications.yml b/changelogs/unreleased/48098-mutual-auth-cluster-applications.yml deleted file mode 100644 index 43125ef25c4..00000000000 --- a/changelogs/unreleased/48098-mutual-auth-cluster-applications.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: Ensure installed Helm Tiller For GitLab Managed Apps Is protected by mutual - auth -merge_request: 20928 -author: -type: changed diff --git a/changelogs/unreleased/48246-osw-load-diffs-improvement.yml b/changelogs/unreleased/48246-osw-load-diffs-improvement.yml deleted file mode 100644 index c4292ab0d29..00000000000 --- a/changelogs/unreleased/48246-osw-load-diffs-improvement.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Improve performance when fetching collapsed diffs and commenting in merge requests -merge_request: 20940 -author: -type: performance diff --git a/changelogs/unreleased/48419-charts-with-long-label-appear-oversized.yml b/changelogs/unreleased/48419-charts-with-long-label-appear-oversized.yml deleted file mode 100644 index b3ccbb121f0..00000000000 --- a/changelogs/unreleased/48419-charts-with-long-label-appear-oversized.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: fix height of full-width Metrics charts on large screens -merge_request: 20866 -author: -type: fixed diff --git a/changelogs/unreleased/48456-fix-system-level-labels-admin-ui.yml b/changelogs/unreleased/48456-fix-system-level-labels-admin-ui.yml deleted file mode 100644 index c34750a3b88..00000000000 --- a/changelogs/unreleased/48456-fix-system-level-labels-admin-ui.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix the UI for listing system-level labels -merge_request: -author: -type: fixed diff --git a/changelogs/unreleased/48537-update-avatar-only-via-api.yml b/changelogs/unreleased/48537-update-avatar-only-via-api.yml deleted file mode 100644 index 9b3ab946cc1..00000000000 --- a/changelogs/unreleased/48537-update-avatar-only-via-api.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Allow updating a project's avatar without other params -merge_request: -author: Jamie Schembri -type: fixed diff --git a/changelogs/unreleased/48542-code-link.yml b/changelogs/unreleased/48542-code-link.yml deleted file mode 100644 index 8d8d9bf8d74..00000000000 --- a/changelogs/unreleased/48542-code-link.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix link color in markdown code brackets -merge_request: 20841 -author: -type: fixed diff --git a/changelogs/unreleased/48617-promoting-milestone.yml b/changelogs/unreleased/48617-promoting-milestone.yml deleted file mode 100644 index 7fbc15051cf..00000000000 --- a/changelogs/unreleased/48617-promoting-milestone.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Escapes milestone and label's names on flash notice when promoting them -merge_request: -author: -type: fixed diff --git a/changelogs/unreleased/48636-new-mr-card-styles.yml b/changelogs/unreleased/48636-new-mr-card-styles.yml deleted file mode 100644 index 94f62e677fb..00000000000 --- a/changelogs/unreleased/48636-new-mr-card-styles.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix new MR card styles -merge_request: 20822 -author: -type: fixed diff --git a/changelogs/unreleased/48657-persist-auto-devops-banner-dismissal-per-user-cookie.yml b/changelogs/unreleased/48657-persist-auto-devops-banner-dismissal-per-user-cookie.yml deleted file mode 100644 index 7ee018ef679..00000000000 --- a/changelogs/unreleased/48657-persist-auto-devops-banner-dismissal-per-user-cookie.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Persist 'Auto DevOps' banner dismissal globally -merge_request: 20540 -author: -type: other diff --git a/changelogs/unreleased/48773-gitlab-project-import-should-use-object-storage.yml b/changelogs/unreleased/48773-gitlab-project-import-should-use-object-storage.yml deleted file mode 100644 index f298380b920..00000000000 --- a/changelogs/unreleased/48773-gitlab-project-import-should-use-object-storage.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add object storage logic to project import -merge_request: 20773 -author: -type: added diff --git a/changelogs/unreleased/48804-redesign-gcp-banner.yml b/changelogs/unreleased/48804-redesign-gcp-banner.yml deleted file mode 100644 index 729f959badc..00000000000 --- a/changelogs/unreleased/48804-redesign-gcp-banner.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Redesign GCP offer banner -merge_request: -author: -type: changed diff --git a/changelogs/unreleased/48823-copy-gfm.yml b/changelogs/unreleased/48823-copy-gfm.yml deleted file mode 100644 index b6137e2e3f9..00000000000 --- a/changelogs/unreleased/48823-copy-gfm.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Resolve Copy diff file path as GFM is broken -merge_request: 20725 -author: -type: fixed diff --git a/changelogs/unreleased/48834-chart-versions-for-applications-installed-by-one-click-install-buttons-should-be-version-locked.yml b/changelogs/unreleased/48834-chart-versions-for-applications-installed-by-one-click-install-buttons-should-be-version-locked.yml deleted file mode 100644 index d79b95411aa..00000000000 --- a/changelogs/unreleased/48834-chart-versions-for-applications-installed-by-one-click-install-buttons-should-be-version-locked.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: Chart versions for applications installed by one click install buttons should - be version locked -merge_request: 20765 -author: -type: fixed diff --git a/changelogs/unreleased/48932-disable-saml-if-omniauth-is-disabled.yml b/changelogs/unreleased/48932-disable-saml-if-omniauth-is-disabled.yml deleted file mode 100644 index 0466debea65..00000000000 --- a/changelogs/unreleased/48932-disable-saml-if-omniauth-is-disabled.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Disable SAML and Bitbucket if OmniAuth is disabled -merge_request: 20608 -author: -type: fixed diff --git a/changelogs/unreleased/48934.yml b/changelogs/unreleased/48934.yml deleted file mode 100644 index 8e2e53ed198..00000000000 --- a/changelogs/unreleased/48934.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Improve danger confirmation modals by focusing input field -merge_request: -author: Jamie Schembri -type: added diff --git a/changelogs/unreleased/48976-fix-sti-background-migration.yml b/changelogs/unreleased/48976-fix-sti-background-migration.yml deleted file mode 100644 index e95536b213c..00000000000 --- a/changelogs/unreleased/48976-fix-sti-background-migration.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: "[Rails5] Fix 'Invalid single-table inheritance type: Group is not a subclass - of Gitlab::BackgroundMigration::FixCrossProjectLabelLinks::Namespace'" -merge_request: 20462 -author: "@blackst0ne" -type: fixed diff --git a/changelogs/unreleased/49025-docs-kubernetes-tiller.yml b/changelogs/unreleased/49025-docs-kubernetes-tiller.yml deleted file mode 100644 index c4f01490cfa..00000000000 --- a/changelogs/unreleased/49025-docs-kubernetes-tiller.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update docs of Helm Tiller -merge_request: 20515 -author: Takuya Noguchi -type: other diff --git a/changelogs/unreleased/49107-prefetching-of-assets-and-cdn-domain.yml b/changelogs/unreleased/49107-prefetching-of-assets-and-cdn-domain.yml deleted file mode 100644 index 541b562adac..00000000000 --- a/changelogs/unreleased/49107-prefetching-of-assets-and-cdn-domain.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: DNS prefetching if asset_host for CDN hosting is set -merge_request: 20781 -author: -type: performance diff --git a/changelogs/unreleased/49110-update-mr-widget-styles.yml b/changelogs/unreleased/49110-update-mr-widget-styles.yml new file mode 100644 index 00000000000..e54866a0908 --- /dev/null +++ b/changelogs/unreleased/49110-update-mr-widget-styles.yml @@ -0,0 +1,5 @@ +--- +title: Truncate branch names and update "commits behind" text in MR page +merge_request: 21206 +author: +type: changed diff --git a/changelogs/unreleased/49114-add-gitaly-servers-to-admin-overview-navigation-menu.yml b/changelogs/unreleased/49114-add-gitaly-servers-to-admin-overview-navigation-menu.yml deleted file mode 100644 index ab320450a1a..00000000000 --- a/changelogs/unreleased/49114-add-gitaly-servers-to-admin-overview-navigation-menu.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Gitaly Servers link into Admin > Overview navigation menu -merge_request: 20550 -author: -type: added diff --git a/changelogs/unreleased/49161-disable-toggle-comments.yml b/changelogs/unreleased/49161-disable-toggle-comments.yml deleted file mode 100644 index 5ec16191f07..00000000000 --- a/changelogs/unreleased/49161-disable-toggle-comments.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Disables toggle comments button if diff has no discussions -merge_request: -author: -type: other diff --git a/changelogs/unreleased/49272-sanitize-git-url-in-import-errors.yml b/changelogs/unreleased/49272-sanitize-git-url-in-import-errors.yml deleted file mode 100644 index c757e55f1cd..00000000000 --- a/changelogs/unreleased/49272-sanitize-git-url-in-import-errors.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Sanitize git URL in import errors -merge_request: -author: Jamie Schembri -type: fixed diff --git a/changelogs/unreleased/49291-fix-memory-graph-component-typo.yml b/changelogs/unreleased/49291-fix-memory-graph-component-typo.yml deleted file mode 100644 index f21bd454e84..00000000000 --- a/changelogs/unreleased/49291-fix-memory-graph-component-typo.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix typo in CSS transform property for Memory Graph component -merge_request: 20650 -author: -type: fixed diff --git a/changelogs/unreleased/49324-add-support-for-tar-gz-autodevops-charts.yml b/changelogs/unreleased/49324-add-support-for-tar-gz-autodevops-charts.yml deleted file mode 100644 index a87eef3f7f3..00000000000 --- a/changelogs/unreleased/49324-add-support-for-tar-gz-autodevops-charts.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add support for tar.gz AUTO_DEVOPS_CHART charts (#49324) -merge_request: 20691 -author: '@kondi1' -type: added diff --git a/changelogs/unreleased/49364-fix-broadcast-margin.yml b/changelogs/unreleased/49364-fix-broadcast-margin.yml deleted file mode 100644 index 821fb9df1af..00000000000 --- a/changelogs/unreleased/49364-fix-broadcast-margin.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix misalignment of broadcast message on login page -merge_request: 20794 -author: Robin Naundorf -type: fixed diff --git a/changelogs/unreleased/49375-move-help-popover.yml b/changelogs/unreleased/49375-move-help-popover.yml deleted file mode 100644 index 2547d5768bf..00000000000 --- a/changelogs/unreleased/49375-move-help-popover.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Moves help_popover component to a common location -merge_request: -author: -type: other diff --git a/changelogs/unreleased/49499-list-of-projects-not-loading-when-trying-to-create-an-issue-from-a-board-typeerror.yml b/changelogs/unreleased/49499-list-of-projects-not-loading-when-trying-to-create-an-issue-from-a-board-typeerror.yml deleted file mode 100644 index 043698269e2..00000000000 --- a/changelogs/unreleased/49499-list-of-projects-not-loading-when-trying-to-create-an-issue-from-a-board-typeerror.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fixed list of projects not loading in group boards -merge_request: 20955 -author: -type: fixed diff --git a/changelogs/unreleased/49701-sorting-by-name-on-milestones-page-error.yml b/changelogs/unreleased/49701-sorting-by-name-on-milestones-page-error.yml deleted file mode 100644 index 7eb73110d60..00000000000 --- a/changelogs/unreleased/49701-sorting-by-name-on-milestones-page-error.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix sorting by name on milestones page -merge_request: 20881 -author: -type: fixed diff --git a/changelogs/unreleased/49747-update-poll-2xx.yml b/changelogs/unreleased/49747-update-poll-2xx.yml deleted file mode 100644 index 359d1b80447..00000000000 --- a/changelogs/unreleased/49747-update-poll-2xx.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Changes poll.js to keep polling on any 2xx http status code -merge_request: 20904 -author: -type: other diff --git a/changelogs/unreleased/49776-pipeline-job-log-page-uses-too-much-cpu-for-loading-animation.yml b/changelogs/unreleased/49776-pipeline-job-log-page-uses-too-much-cpu-for-loading-animation.yml deleted file mode 100644 index 96da2436a9f..00000000000 --- a/changelogs/unreleased/49776-pipeline-job-log-page-uses-too-much-cpu-for-loading-animation.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: refactor pipeline job log animation to reduce CPU usage -merge_request: 20915 -author: -type: performance diff --git a/changelogs/unreleased/49830-use-helm-272.yml b/changelogs/unreleased/49830-use-helm-272.yml deleted file mode 100644 index f6ecc12dbfa..00000000000 --- a/changelogs/unreleased/49830-use-helm-272.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Use Helm 2.7.2 for GitLab Managed Apps -merge_request: 20956 -author: -type: changed diff --git a/changelogs/unreleased/49835-increase-width.yml b/changelogs/unreleased/49835-increase-width.yml deleted file mode 100644 index f963c0c5e47..00000000000 --- a/changelogs/unreleased/49835-increase-width.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Increases title column on modal for reports -merge_request: -author: -type: other diff --git a/changelogs/unreleased/49851-link-to-runners.yml b/changelogs/unreleased/49851-link-to-runners.yml deleted file mode 100644 index 89fd6853bc8..00000000000 --- a/changelogs/unreleased/49851-link-to-runners.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: Automatically expand runner's settings block when linking to the runner's settings - page -merge_request: -author: -type: other diff --git a/changelogs/unreleased/49854-recover-mr-regression-fixes-safe-1.yml b/changelogs/unreleased/49854-recover-mr-regression-fixes-safe-1.yml deleted file mode 100644 index ffa4a3bc710..00000000000 --- a/changelogs/unreleased/49854-recover-mr-regression-fixes-safe-1.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix rendering of the context lines in MR diffs page. -merge_request: 20968 -author: -type: fixed diff --git a/changelogs/unreleased/49854-recover-mr-regression-fixes-safe-2.yml b/changelogs/unreleased/49854-recover-mr-regression-fixes-safe-2.yml deleted file mode 100644 index 42b0e4194f1..00000000000 --- a/changelogs/unreleased/49854-recover-mr-regression-fixes-safe-2.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix autosave and ESC confirmation issues for MR discussions. -merge_request: 20968 -author: -type: fixed diff --git a/changelogs/unreleased/49854-recover-mr-regression-fixes-safe-3.yml b/changelogs/unreleased/49854-recover-mr-regression-fixes-safe-3.yml deleted file mode 100644 index 29419091d02..00000000000 --- a/changelogs/unreleased/49854-recover-mr-regression-fixes-safe-3.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix navigation to First and Next discussion on MR Changes tab. -merge_request: 20968 -author: -type: fixed diff --git a/changelogs/unreleased/49861-top-nav-search-bar-produces-console-error-when-unauthenticated.yml b/changelogs/unreleased/49861-top-nav-search-bar-produces-console-error-when-unauthenticated.yml deleted file mode 100644 index 30f5002c5b5..00000000000 --- a/changelogs/unreleased/49861-top-nav-search-bar-produces-console-error-when-unauthenticated.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: fix error caused when using the search bar while unauthenticated -merge_request: 20970 -author: -type: fixed diff --git a/changelogs/unreleased/49899-merge-request-e-mail-link-has-full-url.yml b/changelogs/unreleased/49899-merge-request-e-mail-link-has-full-url.yml deleted file mode 100644 index 856a7c579f3..00000000000 --- a/changelogs/unreleased/49899-merge-request-e-mail-link-has-full-url.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Ensure links in notifications footer are not escaped -merge_request: 21000 -author: -type: fixed diff --git a/changelogs/unreleased/49907-commits-and-merge-requests-does-not-list-all-files-when-one-file-exceeds-size-limits.yml b/changelogs/unreleased/49907-commits-and-merge-requests-does-not-list-all-files-when-one-file-exceeds-size-limits.yml deleted file mode 100644 index 2fce00a662f..00000000000 --- a/changelogs/unreleased/49907-commits-and-merge-requests-does-not-list-all-files-when-one-file-exceeds-size-limits.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix merge requests not showing any diff files for big patches -merge_request: 21125 -author: -type: fixed diff --git a/changelogs/unreleased/49966-improve-junit-fe.yml b/changelogs/unreleased/49966-improve-junit-fe.yml deleted file mode 100644 index 48971d3bfd6..00000000000 --- a/changelogs/unreleased/49966-improve-junit-fe.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Renders test reports for resolved failures and resets error state -merge_request: -author: -type: fixed diff --git a/changelogs/unreleased/50257-fix-auto-devops-glibc-pubkey-url.yml b/changelogs/unreleased/50257-fix-auto-devops-glibc-pubkey-url.yml deleted file mode 100644 index e081dfe6093..00000000000 --- a/changelogs/unreleased/50257-fix-auto-devops-glibc-pubkey-url.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: 'Auto-DevOps.gitlab-ci.yml: Update glibc package signing key URL' -merge_request: 21182 -author: sgerrand -type: fixed diff --git a/changelogs/unreleased/50281-js-pages-do-not-load-on-windows-8-ie-11.yml b/changelogs/unreleased/50281-js-pages-do-not-load-on-windows-8-ie-11.yml deleted file mode 100644 index eb20e34c466..00000000000 --- a/changelogs/unreleased/50281-js-pages-do-not-load-on-windows-8-ie-11.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix broken JavaScript in IE11 -merge_request: 21214 -author: -type: fixed diff --git a/changelogs/unreleased/50312-instance-statistics-convdev-index-intro-banner-is-not-dismissable.yml b/changelogs/unreleased/50312-instance-statistics-convdev-index-intro-banner-is-not-dismissable.yml deleted file mode 100644 index 50a3b9c9aff..00000000000 --- a/changelogs/unreleased/50312-instance-statistics-convdev-index-intro-banner-is-not-dismissable.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix issue stopping Instance Statistics javascript to be executed -merge_request: 21211 -author: -type: fixed diff --git a/changelogs/unreleased/50345-hashed-storage-feature-flag.yml b/changelogs/unreleased/50345-hashed-storage-feature-flag.yml new file mode 100644 index 00000000000..4c5182b843b --- /dev/null +++ b/changelogs/unreleased/50345-hashed-storage-feature-flag.yml @@ -0,0 +1,5 @@ +--- +title: Feature flag to disable Hashed Storage migration when renaming a repository +merge_request: 21291 +author: +type: added diff --git a/changelogs/unreleased/50524-artifacts-sm.yml b/changelogs/unreleased/50524-artifacts-sm.yml new file mode 100644 index 00000000000..22bd097f911 --- /dev/null +++ b/changelogs/unreleased/50524-artifacts-sm.yml @@ -0,0 +1,5 @@ +--- +title: Shows download artifacts button for pipelines on small screens +merge_request: +author: +type: changed diff --git a/changelogs/unreleased/6028-show-generic-percent-stacked-progress-bar.yml b/changelogs/unreleased/6028-show-generic-percent-stacked-progress-bar.yml new file mode 100644 index 00000000000..94098dd0144 --- /dev/null +++ b/changelogs/unreleased/6028-show-generic-percent-stacked-progress-bar.yml @@ -0,0 +1,6 @@ +--- +title: Show '< 1%' when percent value evaluated is less than 1 on Stacked Progress + Bar +merge_request: 21306 +author: +type: fixed diff --git a/changelogs/unreleased/6860-FE-instance-level-project-templates.yml b/changelogs/unreleased/6860-FE-instance-level-project-templates.yml deleted file mode 100644 index 74e0daee71b..00000000000 --- a/changelogs/unreleased/6860-FE-instance-level-project-templates.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update design of project templates -merge_request: 21012 -author: -type: changed diff --git a/changelogs/unreleased/accept-rf3-2822-compliant-addresses.yml b/changelogs/unreleased/accept-rf3-2822-compliant-addresses.yml deleted file mode 100644 index 97d017613ba..00000000000 --- a/changelogs/unreleased/accept-rf3-2822-compliant-addresses.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Emails on push recipients now accepts formats like John Doe <johndoe@example.com> -merge_request: -author: George Thomas -type: added diff --git a/changelogs/unreleased/add-dst-support-to-pipeline-schedule.yml b/changelogs/unreleased/add-dst-support-to-pipeline-schedule.yml deleted file mode 100644 index 08376014ad7..00000000000 --- a/changelogs/unreleased/add-dst-support-to-pipeline-schedule.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add support for daylight savings time to pipleline schedules -merge_request: 20145 -author: -type: fixed diff --git a/changelogs/unreleased/add-homepage-link-to-status-pages.yml b/changelogs/unreleased/add-homepage-link-to-status-pages.yml deleted file mode 100644 index 0e7375f2061..00000000000 --- a/changelogs/unreleased/add-homepage-link-to-status-pages.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add link to homepage on static http status pages (404, 500, etc) -merge_request: 20898 -author: Jason Funk -type: added diff --git a/changelogs/unreleased/add-merge-request-header-branch-details-right-margin.yml b/changelogs/unreleased/add-merge-request-header-branch-details-right-margin.yml deleted file mode 100644 index 4f9a551d13e..00000000000 --- a/changelogs/unreleased/add-merge-request-header-branch-details-right-margin.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add merge request header branch actions left margin -merge_request: 20643 -author: George Tsiolis -type: changed diff --git a/changelogs/unreleased/add-total-time-flat-printer-for-profiling.yml b/changelogs/unreleased/add-total-time-flat-printer-for-profiling.yml deleted file mode 100644 index 37a4e31896e..00000000000 --- a/changelogs/unreleased/add-total-time-flat-printer-for-profiling.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: Add a Gitlab::Profiler.print_by_total_time convenience method for profiling - from a Rails console -merge_request: -author: -type: other diff --git a/changelogs/unreleased/api-empty-commit-message.yml b/changelogs/unreleased/api-empty-commit-message.yml new file mode 100644 index 00000000000..34ddc020644 --- /dev/null +++ b/changelogs/unreleased/api-empty-commit-message.yml @@ -0,0 +1,5 @@ +--- +title: 'API: Catch empty commit messages' +merge_request: 21322 +author: Robert Schilling +type: fixed diff --git a/changelogs/unreleased/api-empty-project-snippets.yml b/changelogs/unreleased/api-empty-project-snippets.yml new file mode 100644 index 00000000000..7b8c7c9e48d --- /dev/null +++ b/changelogs/unreleased/api-empty-project-snippets.yml @@ -0,0 +1,5 @@ +--- +title: 'API: Catch empty code content for project snippets' +merge_request: 21325 +author: Robert Schilling +type: fixed diff --git a/changelogs/unreleased/api-minimal-access-level.yml b/changelogs/unreleased/api-minimal-access-level.yml deleted file mode 100644 index 43cab246d69..00000000000 --- a/changelogs/unreleased/api-minimal-access-level.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add filter for minimal access level in groups and projects API -merge_request: 20478 -author: Marko, Peter -type: added diff --git a/changelogs/unreleased/api-protected-tags.yml b/changelogs/unreleased/api-protected-tags.yml new file mode 100644 index 00000000000..6e7ecf24b6e --- /dev/null +++ b/changelogs/unreleased/api-protected-tags.yml @@ -0,0 +1,5 @@ +--- +title: 'API: Protected tags' +merge_request: 14986 +author: Robert Schilling +type: added diff --git a/changelogs/unreleased/api-shared_group_expires-at.yml b/changelogs/unreleased/api-shared_group_expires-at.yml new file mode 100644 index 00000000000..3d569de65fa --- /dev/null +++ b/changelogs/unreleased/api-shared_group_expires-at.yml @@ -0,0 +1,5 @@ +--- +title: 'API: Add expiration date for shared projects to the project entity' +merge_request: 21104 +author: Robert Schilling +type: added diff --git a/changelogs/unreleased/arguments-keyword-sast.yml b/changelogs/unreleased/arguments-keyword-sast.yml new file mode 100644 index 00000000000..2ecbc5e8174 --- /dev/null +++ b/changelogs/unreleased/arguments-keyword-sast.yml @@ -0,0 +1,5 @@ +--- +title: Don't use arguments keyword in gettext script +merge_request: 21296 +author: gfyoung +type: fixed diff --git a/changelogs/unreleased/artifact-format-v2-with-parser.yml b/changelogs/unreleased/artifact-format-v2-with-parser.yml deleted file mode 100644 index e1a779cf6dd..00000000000 --- a/changelogs/unreleased/artifact-format-v2-with-parser.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: JUnit XML Test Summary In MR widget -merge_request: 20576 -author: -type: added diff --git a/changelogs/unreleased/artifact-format-v2.yml b/changelogs/unreleased/artifact-format-v2.yml deleted file mode 100644 index e264e0a9fa1..00000000000 --- a/changelogs/unreleased/artifact-format-v2.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Extend gitlab-ci.yml to request junit.xml test reports -merge_request: 20390 -author: -type: added diff --git a/changelogs/unreleased/blackst0ne-replace-sidekiq-inline-with-perform-enqueued-jobs.yml b/changelogs/unreleased/blackst0ne-replace-sidekiq-inline-with-perform-enqueued-jobs.yml deleted file mode 100644 index 69e6b7d815a..00000000000 --- a/changelogs/unreleased/blackst0ne-replace-sidekiq-inline-with-perform-enqueued-jobs.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Replace 'Sidekiq::Testing.inline!' with 'perform_enqueued_jobs' -merge_request: 20768 -author: "@blackst0ne" -type: other diff --git a/changelogs/unreleased/bvl-graphql-wip-mutation.yml b/changelogs/unreleased/bvl-graphql-wip-mutation.yml deleted file mode 100644 index 00aa1c48677..00000000000 --- a/changelogs/unreleased/bvl-graphql-wip-mutation.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add the first mutations for merge requests to GraphQL -merge_request: 20443 -author: -type: added diff --git a/changelogs/unreleased/bvl-user-status-message-35463.yml b/changelogs/unreleased/bvl-user-status-message-35463.yml deleted file mode 100644 index c844e7ea0e4..00000000000 --- a/changelogs/unreleased/bvl-user-status-message-35463.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Users can set a status message and emoji -merge_request: 20614 -author: niedermyer & davamr -type: added diff --git a/changelogs/unreleased/ccr-43283_allow_author_upvote.yml b/changelogs/unreleased/ccr-43283_allow_author_upvote.yml new file mode 100644 index 00000000000..12ef6e3f790 --- /dev/null +++ b/changelogs/unreleased/ccr-43283_allow_author_upvote.yml @@ -0,0 +1,5 @@ +--- +title: Allow author to vote on their own issue and MRs +merge_request: 21203 +author: +type: changed diff --git a/changelogs/unreleased/ccr-48800-ping_for_boards.yml b/changelogs/unreleased/ccr-48800-ping_for_boards.yml new file mode 100644 index 00000000000..c08578cddba --- /dev/null +++ b/changelogs/unreleased/ccr-48800-ping_for_boards.yml @@ -0,0 +1,6 @@ +--- +title: Adds count for different board list types (label lists, assignee lists, and + milestone lists) to usage statistics. +merge_request: 21208 +author: +type: changed diff --git a/changelogs/unreleased/ce-5666-backport.yml b/changelogs/unreleased/ce-5666-backport.yml deleted file mode 100644 index 344f1a1983f..00000000000 --- a/changelogs/unreleased/ce-5666-backport.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: CE port of "List groups with developer maintainer access on project creation" -merge_request: 21051 -author: -type: other diff --git a/changelogs/unreleased/ce-6064-geo-sql-query-for-counting-projects-with-wikis-is-very-slow.yml b/changelogs/unreleased/ce-6064-geo-sql-query-for-counting-projects-with-wikis-is-very-slow.yml deleted file mode 100644 index b76437a8773..00000000000 --- a/changelogs/unreleased/ce-6064-geo-sql-query-for-counting-projects-with-wikis-is-very-slow.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Tracking the number of repositories and wikis with a cached counter for site-wide statistics -merge_request: 20413 -author: -type: performance diff --git a/changelogs/unreleased/close-revert-and-cherry-pick-modal-on-escape-keypress.yml b/changelogs/unreleased/close-revert-and-cherry-pick-modal-on-escape-keypress.yml deleted file mode 100644 index 49648cdfcfc..00000000000 --- a/changelogs/unreleased/close-revert-and-cherry-pick-modal-on-escape-keypress.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Close revert and cherry pick modal on escape keypress -merge_request: 20341 -author: George Tsiolis -type: changed diff --git a/changelogs/unreleased/cr-add-group-milestone-to-dashboard.yml b/changelogs/unreleased/cr-add-group-milestone-to-dashboard.yml deleted file mode 100644 index b87a1e5faf7..00000000000 --- a/changelogs/unreleased/cr-add-group-milestone-to-dashboard.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Adds the ability to view group milestones on the dashboard milestone page. -merge_request: 20618 -author: -type: fixed diff --git a/changelogs/unreleased/cr-add-path-of-group-milestone.yml b/changelogs/unreleased/cr-add-path-of-group-milestone.yml deleted file mode 100644 index 5ce240110ef..00000000000 --- a/changelogs/unreleased/cr-add-path-of-group-milestone.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Adds the project and group name to the return type for project and group milestones. -merge_request: 20890 -author: -type: changed diff --git a/changelogs/unreleased/custom_wiki_sidebar.yml b/changelogs/unreleased/custom_wiki_sidebar.yml deleted file mode 100644 index 988fccc929c..00000000000 --- a/changelogs/unreleased/custom_wiki_sidebar.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: "Custom Wiki Sidebar Support Issue 14995" -merge_request: -author: Josh Sooter -type: added diff --git a/changelogs/unreleased/dz-fix-sql-error-admin-users-2fa.yml b/changelogs/unreleased/dz-fix-sql-error-admin-users-2fa.yml new file mode 100644 index 00000000000..67926f3738a --- /dev/null +++ b/changelogs/unreleased/dz-fix-sql-error-admin-users-2fa.yml @@ -0,0 +1,5 @@ +--- +title: Fix SQL error when sorting 2FA-enabled users by name in admin area +merge_request: 21324 +author: +type: fixed diff --git a/changelogs/unreleased/dz-labels-search.yml b/changelogs/unreleased/dz-labels-search.yml deleted file mode 100644 index 49c1b6c1a86..00000000000 --- a/changelogs/unreleased/dz-labels-search.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Search for labels by title or description on project labels page -merge_request: 20749 -author: -type: added diff --git a/changelogs/unreleased/dz-manifest-import.yml b/changelogs/unreleased/dz-manifest-import.yml deleted file mode 100644 index b0d29b0869f..00000000000 --- a/changelogs/unreleased/dz-manifest-import.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add ability to import multiple repositories by uploading a manifest file -merge_request: 20304 -author: -type: added diff --git a/changelogs/unreleased/feature-gb-email-delivery-metrics.yml b/changelogs/unreleased/feature-gb-email-delivery-metrics.yml deleted file mode 100644 index 9d0d08a471d..00000000000 --- a/changelogs/unreleased/feature-gb-email-delivery-metrics.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add emails delivery Prometheus metrics -merge_request: 20638 -author: -type: added diff --git a/changelogs/unreleased/feature-gb-login-activity-metrics.yml b/changelogs/unreleased/feature-gb-login-activity-metrics.yml deleted file mode 100644 index 5d687b984eb..00000000000 --- a/changelogs/unreleased/feature-gb-login-activity-metrics.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add more comprehensive metrics tracking authentication activity -merge_request: 20668 -author: -type: added diff --git a/changelogs/unreleased/features-show-project-id-on-home-panel.yml b/changelogs/unreleased/features-show-project-id-on-home-panel.yml deleted file mode 100644 index f592be07a52..00000000000 --- a/changelogs/unreleased/features-show-project-id-on-home-panel.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Show Project ID on project home panel -merge_request: 20305 -author: Tuğçe Nur Taş -type: added diff --git a/changelogs/unreleased/fix-diff-note.yml b/changelogs/unreleased/fix-diff-note.yml deleted file mode 100644 index 6f10f86b9bc..00000000000 --- a/changelogs/unreleased/fix-diff-note.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix serialization of LegacyDiffNote -merge_request: -author: -type: fixed diff --git a/changelogs/unreleased/fix-email-confirmation-addtional-email.yml b/changelogs/unreleased/fix-email-confirmation-addtional-email.yml deleted file mode 100644 index 56a2efa4d60..00000000000 --- a/changelogs/unreleased/fix-email-confirmation-addtional-email.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix email confirmation bug when user adds additional email to account -merge_request: 20084 -author: muhammadn -type: fixed diff --git a/changelogs/unreleased/fix-gb-add-missing-before-sha-predefined-variable.yml b/changelogs/unreleased/fix-gb-add-missing-before-sha-predefined-variable.yml deleted file mode 100644 index 7e9e8c33a71..00000000000 --- a/changelogs/unreleased/fix-gb-add-missing-before-sha-predefined-variable.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add missing predefined variable and fix docs -merge_request: -author: -type: fixed diff --git a/changelogs/unreleased/fix-gb-fix-deserializing-ci-yaml-variables.yml b/changelogs/unreleased/fix-gb-fix-deserializing-ci-yaml-variables.yml deleted file mode 100644 index 80b069c9251..00000000000 --- a/changelogs/unreleased/fix-gb-fix-deserializing-ci-yaml-variables.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix accessing imported pipeline builds -merge_request: 20713 -author: -type: fixed diff --git a/changelogs/unreleased/fix-gb-fix-project-settings-build-time-validation.yml b/changelogs/unreleased/fix-gb-fix-project-settings-build-time-validation.yml deleted file mode 100644 index adf582e34a2..00000000000 --- a/changelogs/unreleased/fix-gb-fix-project-settings-build-time-validation.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Limit maximum project build timeout setting to 1 month -merge_request: 20591 -author: -type: fixed diff --git a/changelogs/unreleased/fix-multiple-scopes.yml b/changelogs/unreleased/fix-multiple-scopes.yml deleted file mode 100644 index 24e5172d9a1..00000000000 --- a/changelogs/unreleased/fix-multiple-scopes.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Support multiple scopes when authing container registry scopes -merge_request: 20617 -author: -type: fixed diff --git a/changelogs/unreleased/fix-project-api-archived.yml b/changelogs/unreleased/fix-project-api-archived.yml deleted file mode 100644 index 9d119fd3429..00000000000 --- a/changelogs/unreleased/fix-project-api-archived.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix archived parameter for projects API -merge_request: 20566 -author: Peter Marko -type: fixed diff --git a/changelogs/unreleased/fix-prometheus-updated-status.yml b/changelogs/unreleased/fix-prometheus-updated-status.yml deleted file mode 100644 index 7261c3429c8..00000000000 --- a/changelogs/unreleased/fix-prometheus-updated-status.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix UI error whereby prometheus application status is updated -merge_request: 21029 -author: -type: fixed diff --git a/changelogs/unreleased/fix-search-bar.yml b/changelogs/unreleased/fix-search-bar.yml deleted file mode 100644 index d4c0c1efddf..00000000000 --- a/changelogs/unreleased/fix-search-bar.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix search bar text input alignment -merge_request: -author: -type: fixed diff --git a/changelogs/unreleased/fix-storage-size-for-artifacts-change.yml b/changelogs/unreleased/fix-storage-size-for-artifacts-change.yml deleted file mode 100644 index 6a3e1420726..00000000000 --- a/changelogs/unreleased/fix-storage-size-for-artifacts-change.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update total storage size when changing size of artifacts -merge_request: 20697 -author: Peter Marko -type: fixed diff --git a/changelogs/unreleased/fj-37736-improve-performance-post-receive-create-gpg-siganture-worker.yml b/changelogs/unreleased/fj-37736-improve-performance-post-receive-create-gpg-siganture-worker.yml deleted file mode 100644 index 0b35c5c6786..00000000000 --- a/changelogs/unreleased/fj-37736-improve-performance-post-receive-create-gpg-siganture-worker.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Performing Commit GPG signature calculation in bulk -merge_request: 20870 -author: -type: performance diff --git a/changelogs/unreleased/fj-48123-fix-gitlab-import.yml b/changelogs/unreleased/fj-48123-fix-gitlab-import.yml deleted file mode 100644 index 896db2cdcb8..00000000000 --- a/changelogs/unreleased/fj-48123-fix-gitlab-import.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix GitLab project imports not loading due to API timeouts -merge_request: 20599 -author: -type: fixed diff --git a/changelogs/unreleased/fj-49014-wiki-search-error.yml b/changelogs/unreleased/fj-49014-wiki-search-error.yml deleted file mode 100644 index a76805cb7f9..00000000000 --- a/changelogs/unreleased/fj-49014-wiki-search-error.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fixed bug with invalid repository reference using the wiki search -merge_request: 20722 -author: -type: fixed diff --git a/changelogs/unreleased/fj-49512-fix-gitlab-git-pages-encoding.yml b/changelogs/unreleased/fj-49512-fix-gitlab-git-pages-encoding.yml deleted file mode 100644 index 3af90fff3f6..00000000000 --- a/changelogs/unreleased/fj-49512-fix-gitlab-git-pages-encoding.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Prevent editing and updating wiki pages with non UTF-8 encoding via web interface -merge_request: 20906 -author: -type: fixed diff --git a/changelogs/unreleased/fj-49802-bug-api-set-http-headers.yml b/changelogs/unreleased/fj-49802-bug-api-set-http-headers.yml deleted file mode 100644 index ba61d378cda..00000000000 --- a/changelogs/unreleased/fj-49802-bug-api-set-http-headers.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix bug setting http headers in Files API -merge_request: 20938 -author: -type: fixed diff --git a/changelogs/unreleased/floating-avarage-commit-numbers.yml b/changelogs/unreleased/floating-avarage-commit-numbers.yml deleted file mode 100644 index 7f91ab16af4..00000000000 --- a/changelogs/unreleased/floating-avarage-commit-numbers.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Show one digit after dot in commit_per_day value in charts page. -merge_request: -author: msdundar -type: changed diff --git a/changelogs/unreleased/frozen-string-danger.yml b/changelogs/unreleased/frozen-string-danger.yml deleted file mode 100644 index 9910139b8a9..00000000000 --- a/changelogs/unreleased/frozen-string-danger.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add Dangerfile for frozen_string_literal -merge_request: 20767 -author: gfyoung -type: performance diff --git a/changelogs/unreleased/frozen-string-enable-app-models-more.yml b/changelogs/unreleased/frozen-string-enable-app-models-more.yml deleted file mode 100644 index c0466984134..00000000000 --- a/changelogs/unreleased/frozen-string-enable-app-models-more.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Enable frozen string for app/models/**/*.rb -merge_request: 21001 -author: gfyoung -type: performance diff --git a/changelogs/unreleased/frozen-string-enable-app-models.yml b/changelogs/unreleased/frozen-string-enable-app-models.yml deleted file mode 100644 index 4c149ea55ef..00000000000 --- a/changelogs/unreleased/frozen-string-enable-app-models.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Enable frozen string in app/models/*.rb -merge_request: 20851 -author: gfyoung -type: performance diff --git a/changelogs/unreleased/frozen-string-enable-app-presenters-policies.yml b/changelogs/unreleased/frozen-string-enable-app-presenters-policies.yml deleted file mode 100644 index 5c6b1b1a904..00000000000 --- a/changelogs/unreleased/frozen-string-enable-app-presenters-policies.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Enable frozen string in app/presenters and app/policies -merge_request: 20819 -author: gfyoung -type: performance diff --git a/changelogs/unreleased/frozen-string-enable-app-serializers.yml b/changelogs/unreleased/frozen-string-enable-app-serializers.yml deleted file mode 100644 index 40c7b695d39..00000000000 --- a/changelogs/unreleased/frozen-string-enable-app-serializers.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Enable frozen string in app/serializers/**/*.rb -merge_request: 20726 -author: gfyoung -type: performance diff --git a/changelogs/unreleased/frozen-string-enable-app-services.yml b/changelogs/unreleased/frozen-string-enable-app-services.yml deleted file mode 100644 index cfc1f356e3a..00000000000 --- a/changelogs/unreleased/frozen-string-enable-app-services.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Enable frozen string in apps/uploaders/*.rb -merge_request: 20401 -author: gfyoung -type: other diff --git a/changelogs/unreleased/frozen-string-enable-apps-services-inner-even-more.yml b/changelogs/unreleased/frozen-string-enable-apps-services-inner-even-more.yml deleted file mode 100644 index cee790a07ff..00000000000 --- a/changelogs/unreleased/frozen-string-enable-apps-services-inner-even-more.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Enable even more frozen string in app/services/**/*.rb -merge_request: 20702 -author: gfyoung -type: performance diff --git a/changelogs/unreleased/frozen-string-enable-apps-services-inner-more.yml b/changelogs/unreleased/frozen-string-enable-apps-services-inner-more.yml deleted file mode 100644 index ea962cf8edc..00000000000 --- a/changelogs/unreleased/frozen-string-enable-apps-services-inner-more.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Enable more frozen string in app/services/**/*.rb -merge_request: 20677 -author: gfyoung -type: performance diff --git a/changelogs/unreleased/frozen-string-enable-apps-services-inner.yml b/changelogs/unreleased/frozen-string-enable-apps-services-inner.yml deleted file mode 100644 index 16b8ec3908f..00000000000 --- a/changelogs/unreleased/frozen-string-enable-apps-services-inner.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Enable frozen string in app/services/**/*.rb -merge_request: 20656 -author: gfyoung -type: performance diff --git a/changelogs/unreleased/frozen-string-vestigial.yml b/changelogs/unreleased/frozen-string-vestigial.yml deleted file mode 100644 index 79e92a19a7a..00000000000 --- a/changelogs/unreleased/frozen-string-vestigial.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Enable frozen string in newly added files to previously processed directories -merge_request: 20763 -author: gfyoung -type: performance diff --git a/changelogs/unreleased/full-list-of-vulnerabilities-5239.yml b/changelogs/unreleased/full-list-of-vulnerabilities-5239.yml deleted file mode 100644 index b26eb82b6c9..00000000000 --- a/changelogs/unreleased/full-list-of-vulnerabilities-5239.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Removes "show all" on reports and adds an actionButtons slot -merge_request: 20855 -author: -type: changed diff --git a/changelogs/unreleased/git-rerere-link-doc-update.yml b/changelogs/unreleased/git-rerere-link-doc-update.yml deleted file mode 100644 index 06093e8ec13..00000000000 --- a/changelogs/unreleased/git-rerere-link-doc-update.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update git rerere link in docs -merge_request: 21060 -author: gfyoung -type: other diff --git a/changelogs/unreleased/hangouts_chat_integration.yml b/changelogs/unreleased/hangouts_chat_integration.yml deleted file mode 100644 index bf3484a6d02..00000000000 --- a/changelogs/unreleased/hangouts_chat_integration.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add Hangouts Chat integration -merge_request: 20290 -author: Kukovskii Vladimir -type: added diff --git a/changelogs/unreleased/ide-codesandbox-poc.yml b/changelogs/unreleased/ide-codesandbox-poc.yml deleted file mode 100644 index 7da1f4e6472..00000000000 --- a/changelogs/unreleased/ide-codesandbox-poc.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Added live preview for JavaScript projects in the Web IDE -merge_request: 19764 -author: -type: added diff --git a/changelogs/unreleased/ide-delete-entries.yml b/changelogs/unreleased/ide-delete-entries.yml deleted file mode 100644 index 8cbc0739406..00000000000 --- a/changelogs/unreleased/ide-delete-entries.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Enabled deletion of files in the Web IDE -merge_request: -author: -type: added diff --git a/changelogs/unreleased/ide-pipeline-icon-open.yml b/changelogs/unreleased/ide-pipeline-icon-open.yml deleted file mode 100644 index 3a73ff2170f..00000000000 --- a/changelogs/unreleased/ide-pipeline-icon-open.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Clicking CI icon in Web IDE now opens up pipelines panel -merge_request: -author: -type: added diff --git a/changelogs/unreleased/ide-rename-files.yml b/changelogs/unreleased/ide-rename-files.yml deleted file mode 100644 index c2db284e07c..00000000000 --- a/changelogs/unreleased/ide-rename-files.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Enable renaming files and folders in Web IDE -merge_request: 20835 -author: -type: added diff --git a/changelogs/unreleased/ide-row-dropdown-design-update.yml b/changelogs/unreleased/ide-row-dropdown-design-update.yml deleted file mode 100644 index e0fe64c944e..00000000000 --- a/changelogs/unreleased/ide-row-dropdown-design-update.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Updated design of new entry dropdown in Web IDE -merge_request: 20526 -author: -type: changed diff --git a/changelogs/unreleased/ide-warn-staged-files.yml b/changelogs/unreleased/ide-warn-staged-files.yml deleted file mode 100644 index ae3c4f392c0..00000000000 --- a/changelogs/unreleased/ide-warn-staged-files.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Warn user when reload IDE with staged changes -merge_request: 20857 -author: -type: added diff --git a/changelogs/unreleased/improve-junit-support-be.yml b/changelogs/unreleased/improve-junit-support-be.yml deleted file mode 100644 index db4d47caa7c..00000000000 --- a/changelogs/unreleased/improve-junit-support-be.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Improve JUnit test reports in merge request widgets -merge_request: 49966 -author: -type: fixed diff --git a/changelogs/unreleased/improve-metadata-access-performance.yml b/changelogs/unreleased/improve-metadata-access-performance.yml deleted file mode 100644 index b16fa99dd3b..00000000000 --- a/changelogs/unreleased/improve-metadata-access-performance.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Access metadata directly from Object Storage -merge_request: -author: -type: performance diff --git a/changelogs/unreleased/issue_43602.yml b/changelogs/unreleased/issue_43602.yml deleted file mode 100644 index 0482606db0a..00000000000 --- a/changelogs/unreleased/issue_43602.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Allow multiple JIRA transition ids -merge_request: 20939 -author: -type: changed diff --git a/changelogs/unreleased/issue_44821.yml b/changelogs/unreleased/issue_44821.yml deleted file mode 100644 index b1807e069af..00000000000 --- a/changelogs/unreleased/issue_44821.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Retrieve merge request closing issues from database cache -merge_request: 20911 -author: -type: fixed diff --git a/changelogs/unreleased/issue_47709.yml b/changelogs/unreleased/issue_47709.yml deleted file mode 100644 index c3ef55fd692..00000000000 --- a/changelogs/unreleased/issue_47709.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: 'Allow to toggle notifications for issues due soon' -merge_request: -author: -type: fixed diff --git a/changelogs/unreleased/jprovazn-fix-form-uploads.yml b/changelogs/unreleased/jprovazn-fix-form-uploads.yml new file mode 100644 index 00000000000..8bcee335e93 --- /dev/null +++ b/changelogs/unreleased/jprovazn-fix-form-uploads.yml @@ -0,0 +1,5 @@ +--- +title: Accept upload files in public/uplaods/tmp when using accelerated uploads. +merge_request: +author: +type: fixed diff --git a/changelogs/unreleased/jprovazn-resource-events.yml b/changelogs/unreleased/jprovazn-resource-events.yml deleted file mode 100644 index 05643150f16..00000000000 --- a/changelogs/unreleased/jprovazn-resource-events.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add new model for tracking label events. -merge_request: -author: -type: added diff --git a/changelogs/unreleased/jr-archive-hook.yml b/changelogs/unreleased/jr-archive-hook.yml deleted file mode 100644 index 56c13f1370e..00000000000 --- a/changelogs/unreleased/jr-archive-hook.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Trigger system hooks when project is archived/unarchived -merge_request: 20995 -author: -type: added diff --git a/changelogs/unreleased/jupyter-image.yml b/changelogs/unreleased/jupyter-image.yml deleted file mode 100644 index 8aeefd603d8..00000000000 --- a/changelogs/unreleased/jupyter-image.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Rubix, scikit-learn, tensorflow & other useful libraries pre-installed with JupyterHub -merge_request: 20714 -author: Amit Rathi -type: changed diff --git a/changelogs/unreleased/kp-6927-epic-dates-from-milestone.yml b/changelogs/unreleased/kp-6927-epic-dates-from-milestone.yml deleted file mode 100644 index c15d73a0c12..00000000000 --- a/changelogs/unreleased/kp-6927-epic-dates-from-milestone.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add 'tabindex' attribute support on Icon component to show BS4 popover on trigger type 'focus' -merge_request: 21066 -author: -type: other diff --git a/changelogs/unreleased/kp-stacked-progress-bar-decimal-places.yml b/changelogs/unreleased/kp-stacked-progress-bar-decimal-places.yml deleted file mode 100644 index a2fca4c5b91..00000000000 --- a/changelogs/unreleased/kp-stacked-progress-bar-decimal-places.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Show decimal place up to single digit in Stacked Progress Bar -merge_request: 20776 -author: -type: changed diff --git a/changelogs/unreleased/leipert-fix-pipelines-view.yml b/changelogs/unreleased/leipert-fix-pipelines-view.yml deleted file mode 100644 index 7bcc2e84cd2..00000000000 --- a/changelogs/unreleased/leipert-fix-pipelines-view.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix rendering of pipeline failure view when directly navigationg to it -merge_request: 21043 -author: -type: fixed diff --git a/changelogs/unreleased/mk-add-local-project-uploads-cleanup-task.yml b/changelogs/unreleased/mk-add-local-project-uploads-cleanup-task.yml deleted file mode 100644 index 9d38b353a41..00000000000 --- a/changelogs/unreleased/mk-add-local-project-uploads-cleanup-task.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add local project uploads cleanup task -merge_request: 20863 -author: -type: added diff --git a/changelogs/unreleased/mk-fix-callback-canceling-in-namespace-move-dir.yml b/changelogs/unreleased/mk-fix-callback-canceling-in-namespace-move-dir.yml deleted file mode 100644 index 8e71377d93f..00000000000 --- a/changelogs/unreleased/mk-fix-callback-canceling-in-namespace-move-dir.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix namespace move callback behavior, especially to fix Geo replication of namespace moves during certain exceptions. -merge_request: 19297 -author: -type: fixed diff --git a/changelogs/unreleased/osw-fix-missing-and-duplicated-milestones-on-list.yml b/changelogs/unreleased/osw-fix-missing-and-duplicated-milestones-on-list.yml deleted file mode 100644 index 62416b7f87e..00000000000 --- a/changelogs/unreleased/osw-fix-missing-and-duplicated-milestones-on-list.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix missing and duplicates on project milestone listing page -merge_request: 21058 -author: -type: fixed diff --git a/changelogs/unreleased/osw-fix-n-plus-1-for-mrs-without-merge-info.yml b/changelogs/unreleased/osw-fix-n-plus-1-for-mrs-without-merge-info.yml deleted file mode 100644 index dc8148fa1a5..00000000000 --- a/changelogs/unreleased/osw-fix-n-plus-1-for-mrs-without-merge-info.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Avoid N+1 on MRs page when metrics merging date cannot be found -merge_request: 21053 -author: -type: performance diff --git a/changelogs/unreleased/pl-json-gon.yml b/changelogs/unreleased/pl-json-gon.yml deleted file mode 100644 index c0f93006c07..00000000000 --- a/changelogs/unreleased/pl-json-gon.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Don't set gon variables in JSON requests -merge_request: 21016 -author: Peter Leitzen -type: performance diff --git a/changelogs/unreleased/process-commits-as-normal-in-forks-with-missing-upstream.yml b/changelogs/unreleased/process-commits-as-normal-in-forks-with-missing-upstream.yml deleted file mode 100644 index 6994a238074..00000000000 --- a/changelogs/unreleased/process-commits-as-normal-in-forks-with-missing-upstream.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Process commits as normal in forks when the upstream project is deleted -merge_request: 20534 -author: -type: fixed diff --git a/changelogs/unreleased/project-visibility-tooltip.yml b/changelogs/unreleased/project-visibility-tooltip.yml deleted file mode 100644 index 806c93e493a..00000000000 --- a/changelogs/unreleased/project-visibility-tooltip.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix project visibility tooltip -merge_request: 20535 -author: Jamie Schembri -type: fixed diff --git a/changelogs/unreleased/rails5-fix-48977.yml b/changelogs/unreleased/rails5-fix-48977.yml deleted file mode 100644 index bfd86f20e24..00000000000 --- a/changelogs/unreleased/rails5-fix-48977.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Rails5 fix mysql milliseconds problem in specs -merge_request: 20464 -author: Jasper Maes -type: fixed diff --git a/changelogs/unreleased/rails5-fix-flaky-spec-user-uses-shortcuts.yml b/changelogs/unreleased/rails5-fix-flaky-spec-user-uses-shortcuts.yml deleted file mode 100644 index 5f2504c604d..00000000000 --- a/changelogs/unreleased/rails5-fix-flaky-spec-user-uses-shortcuts.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: 'Rails5: fix flaky spec' -merge_request: 20953 -author: Jasper Maes -type: fixed diff --git a/changelogs/unreleased/rails5-fix-revert-modal-spec.yml b/changelogs/unreleased/rails5-fix-revert-modal-spec.yml deleted file mode 100644 index 0637e503ca9..00000000000 --- a/changelogs/unreleased/rails5-fix-revert-modal-spec.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Rails5 fix user sees revert modal spec -merge_request: 20706 -author: Jasper Maes -type: fixed diff --git a/changelogs/unreleased/rails5-gpg-permit-concurrent.yml b/changelogs/unreleased/rails5-gpg-permit-concurrent.yml deleted file mode 100644 index cf1b0023f86..00000000000 --- a/changelogs/unreleased/rails5-gpg-permit-concurrent.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Permit concurrent loads in gpg keychain mutex -merge_request: 20894 -author: Jasper Maes -type: fixed diff --git a/changelogs/unreleased/rails5-mysql-fix-pr-importer-spec.yml b/changelogs/unreleased/rails5-mysql-fix-pr-importer-spec.yml deleted file mode 100644 index afd9865ee45..00000000000 --- a/changelogs/unreleased/rails5-mysql-fix-pr-importer-spec.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Rails5 mysql fix milliseconds problem in pull request importer spec -merge_request: 20475 -author: Jasper Maes -type: fixed diff --git a/changelogs/unreleased/rails5-mysql-rename-column.yml b/changelogs/unreleased/rails5-mysql-rename-column.yml deleted file mode 100644 index cbae9250744..00000000000 --- a/changelogs/unreleased/rails5-mysql-rename-column.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Rails5 MySQL fix rename_column as part of cleanup_concurrent_column_type_change -merge_request: 20514 -author: Jasper Maes -type: fixed diff --git a/changelogs/unreleased/rails5-update-gemfile-lock-2.yml b/changelogs/unreleased/rails5-update-gemfile-lock-2.yml deleted file mode 100644 index 1f3e9bd2238..00000000000 --- a/changelogs/unreleased/rails5-update-gemfile-lock-2.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Rails5 update Gemfile.rails5.lock -merge_request: 20858 -author: Jasper Maes -type: fixed diff --git a/changelogs/unreleased/rails5-update-gemfile-lock.yml b/changelogs/unreleased/rails5-update-gemfile-lock.yml index 58931587fff..3891b16e2b8 100644 --- a/changelogs/unreleased/rails5-update-gemfile-lock.yml +++ b/changelogs/unreleased/rails5-update-gemfile-lock.yml @@ -1,5 +1,5 @@ --- -title: Update Gemfile.rails5.lock with latest Gemfile.lock changes -merge_request: 20466 +title: Rails5 update Gemfile.rails5.lock +merge_request: 21388 author: Jasper Maes -type: fixed +type: other diff --git a/changelogs/unreleased/rails5-update-rouge.yml b/changelogs/unreleased/rails5-update-rouge.yml deleted file mode 100644 index 1173b3b7e9a..00000000000 --- a/changelogs/unreleased/rails5-update-rouge.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: 'Rails5: update Rails5 lock for forgotten gem rouge' -merge_request: 21010 -author: Jasper Maes -type: fixed diff --git a/changelogs/unreleased/ravlen-deploy-tokens-display-update.yml b/changelogs/unreleased/ravlen-deploy-tokens-display-update.yml deleted file mode 100644 index fd5a6521882..00000000000 --- a/changelogs/unreleased/ravlen-deploy-tokens-display-update.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: "Cleans up display of Deploy Tokens to match Personal Access Tokens" -merge_request: 20578 -author: Marcel Amirault -type: added
\ No newline at end of file diff --git a/changelogs/unreleased/regen-2fa-codes.yml b/changelogs/unreleased/regen-2fa-codes.yml deleted file mode 100644 index 596f759df0f..00000000000 --- a/changelogs/unreleased/regen-2fa-codes.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Added button to regenerate 2FA codes -merge_request: -author: Luke Picciau -type: added diff --git a/changelogs/unreleased/replace-all-snake-case-in-scss-variables.yml b/changelogs/unreleased/replace-all-snake-case-in-scss-variables.yml deleted file mode 100644 index 8d5ecdfa57e..00000000000 --- a/changelogs/unreleased/replace-all-snake-case-in-scss-variables.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Replace snake case in SCSS variables -merge_request: 20799 -author: George Tsiolis -type: other diff --git a/changelogs/unreleased/replace-snake-case-css-classes.yml b/changelogs/unreleased/replace-snake-case-css-classes.yml deleted file mode 100644 index 28ec5ee097f..00000000000 --- a/changelogs/unreleased/replace-snake-case-css-classes.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Replace author_link snake case in stylesheets, specs, and helpers -merge_request: 20797 -author: George Tsiolis -type: other diff --git a/changelogs/unreleased/rouge-3-2-0.yml b/changelogs/unreleased/rouge-3-2-0.yml deleted file mode 100644 index 15ac4cc1e76..00000000000 --- a/changelogs/unreleased/rouge-3-2-0.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update to Rouge 3.2.0, including Terraform and Crystal lexer and bug fixes -merge_request: 20991 -author: -type: changed diff --git a/changelogs/unreleased/rouge_3-2-1.yml b/changelogs/unreleased/rouge_3-2-1.yml deleted file mode 100644 index b281a4f0e95..00000000000 --- a/changelogs/unreleased/rouge_3-2-1.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update to Rouge 3.2.1, which includes a critical fix to the Perl Lexer -merge_request: 21263 -author: -type: changed diff --git a/changelogs/unreleased/runner-features.yml b/changelogs/unreleased/runner-features.yml deleted file mode 100644 index c5e0fff5a18..00000000000 --- a/changelogs/unreleased/runner-features.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Verify runner feature set -merge_request: 20664 -author: -type: added diff --git a/changelogs/unreleased/runners-max-timeout-param.yml b/changelogs/unreleased/runners-max-timeout-param.yml deleted file mode 100644 index 875f805d849..00000000000 --- a/changelogs/unreleased/runners-max-timeout-param.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add missing maximum_timeout parameter -merge_request: 20355 -author: gfyoung -type: fixed diff --git a/changelogs/unreleased/satishperala-gitlab-ce-20720_webhooks_full_image_url.yml b/changelogs/unreleased/satishperala-gitlab-ce-20720_webhooks_full_image_url.yml deleted file mode 100644 index 7bfe1b5778f..00000000000 --- a/changelogs/unreleased/satishperala-gitlab-ce-20720_webhooks_full_image_url.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Include full image URL in webhooks for uploaded images -merge_request: 18109 -author: Satish Perala -type: changed diff --git a/changelogs/unreleased/security-fj-missing-csrf-system-hooks.yml b/changelogs/unreleased/security-fj-missing-csrf-system-hooks.yml deleted file mode 100644 index fabf48acbbc..00000000000 --- a/changelogs/unreleased/security-fj-missing-csrf-system-hooks.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Adding CSRF protection to Hooks test action -merge_request: -author: -type: security diff --git a/changelogs/unreleased/security-ide-branch-name-xss.yml b/changelogs/unreleased/security-ide-branch-name-xss.yml deleted file mode 100644 index 51742ffa4e9..00000000000 --- a/changelogs/unreleased/security-ide-branch-name-xss.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fixed XSS in branch name in Web IDE -merge_request: -author: -type: security diff --git a/changelogs/unreleased/sh-bump-fog-google.yml b/changelogs/unreleased/sh-bump-fog-google.yml new file mode 100644 index 00000000000..b5fa55e53a5 --- /dev/null +++ b/changelogs/unreleased/sh-bump-fog-google.yml @@ -0,0 +1,5 @@ +--- +title: Bump fog-google to 1.7.0 and google-api-client to 0.23.0 +merge_request: 21295 +author: +type: fixed diff --git a/changelogs/unreleased/sh-bump-gitaly-0-117.yml b/changelogs/unreleased/sh-bump-gitaly-0-117.yml deleted file mode 100644 index 90ca86d076b..00000000000 --- a/changelogs/unreleased/sh-bump-gitaly-0-117.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Bump Gitaly to 0.117.0 -merge_request: 21055 -author: -type: performance diff --git a/changelogs/unreleased/sh-bump-gitaly-for-11-2.yml b/changelogs/unreleased/sh-bump-gitaly-for-11-2.yml deleted file mode 100644 index 0e748c3a346..00000000000 --- a/changelogs/unreleased/sh-bump-gitaly-for-11-2.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Bump Gitaly to 0.117.1 for Rouge update -merge_request: 21277 -author: -type: security diff --git a/changelogs/unreleased/sh-bump-haml-5-0-4.yml b/changelogs/unreleased/sh-bump-haml-5-0-4.yml deleted file mode 100644 index 269b1e55417..00000000000 --- a/changelogs/unreleased/sh-bump-haml-5-0-4.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Bump haml gem to 5.0.4 -merge_request: 20847 -author: -type: performance diff --git a/changelogs/unreleased/sh-bump-rugged-0-27-4.yml b/changelogs/unreleased/sh-bump-rugged-0-27-4.yml deleted file mode 100644 index 50373cb81ad..00000000000 --- a/changelogs/unreleased/sh-bump-rugged-0-27-4.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Bump rugged to 0.27.4 for security fixes -merge_request: -author: -type: security diff --git a/changelogs/unreleased/sh-bump-sanitize-4-6-6.yml b/changelogs/unreleased/sh-bump-sanitize-4-6-6.yml deleted file mode 100644 index b9444440cb9..00000000000 --- a/changelogs/unreleased/sh-bump-sanitize-4-6-6.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Bump nokogiri to 1.8.4 and sanitize to 4.6.6 for performance -merge_request: 20795 -author: -type: performance diff --git a/changelogs/unreleased/sh-enable-frozen-literals-banzi-filters.yml b/changelogs/unreleased/sh-enable-frozen-literals-banzi-filters.yml deleted file mode 100644 index 897d673e97d..00000000000 --- a/changelogs/unreleased/sh-enable-frozen-literals-banzi-filters.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Enable frozen strings in remaining lib/banzai/filter/*.rb files -merge_request: 20777 -author: -type: performance diff --git a/changelogs/unreleased/sh-fix-admin-jobs-controller-timing-out.yml b/changelogs/unreleased/sh-fix-admin-jobs-controller-timing-out.yml deleted file mode 100644 index e1adebbf076..00000000000 --- a/changelogs/unreleased/sh-fix-admin-jobs-controller-timing-out.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix /admin/jobs failing to load due to statement timeout -merge_request: 20909 -author: -type: performance diff --git a/changelogs/unreleased/sh-fix-issue-47797-ce.yml b/changelogs/unreleased/sh-fix-issue-47797-ce.yml deleted file mode 100644 index 456d96acacb..00000000000 --- a/changelogs/unreleased/sh-fix-issue-47797-ce.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix handling of annotated tags when Gitaly is not in use -merge_request: -author: -type: fixed diff --git a/changelogs/unreleased/sh-fix-issue-49133.yml b/changelogs/unreleased/sh-fix-issue-49133.yml deleted file mode 100644 index 847220d88b2..00000000000 --- a/changelogs/unreleased/sh-fix-issue-49133.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix symlink vulnerability in project import -merge_request: -author: -type: security diff --git a/changelogs/unreleased/sh-fix-issue-50562.yml b/changelogs/unreleased/sh-fix-issue-50562.yml new file mode 100644 index 00000000000..a207dd28622 --- /dev/null +++ b/changelogs/unreleased/sh-fix-issue-50562.yml @@ -0,0 +1,5 @@ +--- +title: Fix remote mirrors failing if Git remotes have not been added +merge_request: 21351 +author: +type: fixed diff --git a/changelogs/unreleased/sh-fix-stderr-pipe-consumption.yml b/changelogs/unreleased/sh-fix-stderr-pipe-consumption.yml deleted file mode 100644 index b7366cf2569..00000000000 --- a/changelogs/unreleased/sh-fix-stderr-pipe-consumption.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Avoid process deadlock in popen by consuming input pipes -merge_request: 20600 -author: -type: fixed diff --git a/changelogs/unreleased/sh-freeze-banzai-filter-strings.yml b/changelogs/unreleased/sh-freeze-banzai-filter-strings.yml deleted file mode 100644 index 37b397ea49f..00000000000 --- a/changelogs/unreleased/sh-freeze-banzai-filter-strings.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Enable frozen strings in lib/banzai/filter/*.rb -merge_request: 20775 -author: -type: performance diff --git a/changelogs/unreleased/sh-handle-colons-in-url-passwords.yml b/changelogs/unreleased/sh-handle-colons-in-url-passwords.yml deleted file mode 100644 index 7717d0aab37..00000000000 --- a/changelogs/unreleased/sh-handle-colons-in-url-passwords.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Properly handle colons in URL passwords -merge_request: -author: -type: fixed diff --git a/changelogs/unreleased/sh-include-rbtrace.yml b/changelogs/unreleased/sh-include-rbtrace.yml deleted file mode 100644 index 41f0655e3f8..00000000000 --- a/changelogs/unreleased/sh-include-rbtrace.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add rbtrace to Gemfile -merge_request: 20831 -author: -type: other diff --git a/changelogs/unreleased/sh-insert-git-data-in-separate-transaction.yml b/changelogs/unreleased/sh-insert-git-data-in-separate-transaction.yml new file mode 100644 index 00000000000..116929b2f53 --- /dev/null +++ b/changelogs/unreleased/sh-insert-git-data-in-separate-transaction.yml @@ -0,0 +1,5 @@ +--- +title: 'Bitbucket Server importer: Eliminate most idle-in-transaction issues' +merge_request: +author: +type: performance diff --git a/changelogs/unreleased/sh-lfs-fix-content-type.yml b/changelogs/unreleased/sh-lfs-fix-content-type.yml deleted file mode 100644 index a839be9b3ae..00000000000 --- a/changelogs/unreleased/sh-lfs-fix-content-type.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix LFS uploads not working with git-lfs 2.5.0 -merge_request: 20923 -author: -type: fixed diff --git a/changelogs/unreleased/sh-limit-commit-renderering.yml b/changelogs/unreleased/sh-limit-commit-renderering.yml new file mode 100644 index 00000000000..c44c67bcc90 --- /dev/null +++ b/changelogs/unreleased/sh-limit-commit-renderering.yml @@ -0,0 +1,5 @@ +--- +title: Speed up diff comparisons by limiting number of commit messages rendered +merge_request: 21335 +author: +type: performance diff --git a/changelogs/unreleased/sh-limit-unauthenticated-session-times.yml b/changelogs/unreleased/sh-limit-unauthenticated-session-times.yml deleted file mode 100644 index 44a46b4115e..00000000000 --- a/changelogs/unreleased/sh-limit-unauthenticated-session-times.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Limit the TTL for anonymous sessions to 1 hour -merge_request: 20700 -author: -type: performance diff --git a/changelogs/unreleased/sh-normalize-urls.yml b/changelogs/unreleased/sh-normalize-urls.yml deleted file mode 100644 index b0d1120e10b..00000000000 --- a/changelogs/unreleased/sh-normalize-urls.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Escape username and password in UrlSanitizer#full_url -merge_request: 20684 -author: -type: fixed diff --git a/changelogs/unreleased/sh-optimize-wiki-empty-check.yml b/changelogs/unreleased/sh-optimize-wiki-empty-check.yml deleted file mode 100644 index 31ca7497b5a..00000000000 --- a/changelogs/unreleased/sh-optimize-wiki-empty-check.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Optimize ProjectWiki#empty? check -merge_request: 20573 -author: -type: performance diff --git a/changelogs/unreleased/sh-remove-banzai-instrumentation.yml b/changelogs/unreleased/sh-remove-banzai-instrumentation.yml deleted file mode 100644 index 8bb3cd5942b..00000000000 --- a/changelogs/unreleased/sh-remove-banzai-instrumentation.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Remove method instrumentation for Banzai filters and reference parsers -merge_request: 20770 -author: -type: performance diff --git a/changelogs/unreleased/sh-sanitize-project-import-names.yml b/changelogs/unreleased/sh-sanitize-project-import-names.yml new file mode 100644 index 00000000000..6e0284bda08 --- /dev/null +++ b/changelogs/unreleased/sh-sanitize-project-import-names.yml @@ -0,0 +1,5 @@ +--- +title: Use slugs for default project path and sanitize names before import +merge_request: 21367 +author: +type: fixed diff --git a/changelogs/unreleased/sh-simplify-liveness-check.yml b/changelogs/unreleased/sh-simplify-liveness-check.yml deleted file mode 100644 index 225e3dc1378..00000000000 --- a/changelogs/unreleased/sh-simplify-liveness-check.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add /-/health basic health check endpoint -merge_request: 20456 -author: -type: added diff --git a/changelogs/unreleased/sh-support-users-find-by-confirmed-emails.yml b/changelogs/unreleased/sh-support-users-find-by-confirmed-emails.yml deleted file mode 100644 index 4b0c8117b3e..00000000000 --- a/changelogs/unreleased/sh-support-users-find-by-confirmed-emails.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add support for searching users by confirmed e-mails -merge_request: 20893 -author: -type: other diff --git a/changelogs/unreleased/sh-use-wiki-limit-parameter-gitaly.yml b/changelogs/unreleased/sh-use-wiki-limit-parameter-gitaly.yml deleted file mode 100644 index e8c2e11ad31..00000000000 --- a/changelogs/unreleased/sh-use-wiki-limit-parameter-gitaly.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Use limit parameter to retrieve Wikis from Gitaly -merge_request: 20764 -author: -type: performance diff --git a/changelogs/unreleased/stop-dynamic-routable-creation.yml b/changelogs/unreleased/stop-dynamic-routable-creation.yml deleted file mode 100644 index 8bfcb5b2d11..00000000000 --- a/changelogs/unreleased/stop-dynamic-routable-creation.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Stop dynamically creating project and namespace routes -merge_request: 20313 -author: -type: performance diff --git a/changelogs/unreleased/tc-reorder-mail-notify-references.yml b/changelogs/unreleased/tc-reorder-mail-notify-references.yml deleted file mode 100644 index 689afda0259..00000000000 --- a/changelogs/unreleased/tc-reorder-mail-notify-references.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Put fallback reply-key address first in the References header -merge_request: 20871 -author: -type: changed diff --git a/changelogs/unreleased/todos-visibility-change.yml b/changelogs/unreleased/todos-visibility-change.yml deleted file mode 100644 index b7632b94771..00000000000 --- a/changelogs/unreleased/todos-visibility-change.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Delete todos when user loses access to read the target -merge_request: 20665 -author: -type: other diff --git a/changelogs/unreleased/todos-visibility-migration.yml b/changelogs/unreleased/todos-visibility-migration.yml deleted file mode 100644 index 651facc4ec8..00000000000 --- a/changelogs/unreleased/todos-visibility-migration.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Remove todos of users without access to targets migration -merge_request: 20927 -author: -type: other diff --git a/changelogs/unreleased/toggle-password-cluster.yml b/changelogs/unreleased/toggle-password-cluster.yml deleted file mode 100644 index 1a43c4baa25..00000000000 --- a/changelogs/unreleased/toggle-password-cluster.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Toggle Show / Hide Button for Kubernetes Password -merge_request: 20659 -author: gfyoung -type: fixed diff --git a/changelogs/unreleased/tweak-sql-buckets.yml b/changelogs/unreleased/tweak-sql-buckets.yml deleted file mode 100644 index 00a0f733ee1..00000000000 --- a/changelogs/unreleased/tweak-sql-buckets.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add a 10 ms bucket for SQL timings -merge_request: -author: -type: changed diff --git a/changelogs/unreleased/tz-mr-port-memory-fixes.yml b/changelogs/unreleased/tz-mr-port-memory-fixes.yml deleted file mode 100644 index 61d3c9abf71..00000000000 --- a/changelogs/unreleased/tz-mr-port-memory-fixes.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Improve performance and memory footprint of Changes tab of Merge Requests -merge_request: 21028 -author: -type: performance diff --git a/changelogs/unreleased/update-card-body-style.yml b/changelogs/unreleased/update-card-body-style.yml deleted file mode 100644 index d9197c18502..00000000000 --- a/changelogs/unreleased/update-card-body-style.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Remove background color from card-body style -merge_request: 20689 -author: George Tsiolis -type: fixed diff --git a/changelogs/unreleased/update-issue-closing-pattern.yml b/changelogs/unreleased/update-issue-closing-pattern.yml deleted file mode 100644 index 95488adf449..00000000000 --- a/changelogs/unreleased/update-issue-closing-pattern.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update issue closing pattern -merge_request: 20554 -author: George Tsiolis -type: changed diff --git a/changelogs/unreleased/update-specific-runners-help-url.yml b/changelogs/unreleased/update-specific-runners-help-url.yml deleted file mode 100644 index 0ccbc3b2d65..00000000000 --- a/changelogs/unreleased/update-specific-runners-help-url.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update specific runners help URL -merge_request: 20213 -author: George Tsiolis -type: other diff --git a/changelogs/unreleased/upgrade-hamlit-for-ruby25.yml b/changelogs/unreleased/upgrade-hamlit-for-ruby25.yml deleted file mode 100644 index 39e10121507..00000000000 --- a/changelogs/unreleased/upgrade-hamlit-for-ruby25.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: 'Update hamlit to fix ruby 2.5 incompatibilities, fixes #42045' -merge_request: -author: Matthew Dawson -type: fixed diff --git a/changelogs/unreleased/winh-fix-gpg-regressions.yml b/changelogs/unreleased/winh-fix-gpg-regressions.yml deleted file mode 100644 index 75d28321259..00000000000 --- a/changelogs/unreleased/winh-fix-gpg-regressions.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix GPG status badge loading regressions -merge_request: 20987 -author: -type: fixed diff --git a/changelogs/unreleased/winh-restyle-user-status.yml b/changelogs/unreleased/winh-restyle-user-status.yml deleted file mode 100644 index 90370e87825..00000000000 --- a/changelogs/unreleased/winh-restyle-user-status.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Restyle status message input on profile settings -merge_request: 20903 -author: -type: changed diff --git a/changelogs/unreleased/winh-stop-all-environments.yml b/changelogs/unreleased/winh-stop-all-environments.yml deleted file mode 100644 index 6e5f2f506d9..00000000000 --- a/changelogs/unreleased/winh-stop-all-environments.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Support manually stopping any environment from the UI -merge_request: 20077 -author: -type: changed diff --git a/changelogs/unreleased/winh-tree-view-gpg.yml b/changelogs/unreleased/winh-tree-view-gpg.yml deleted file mode 100644 index 84d63814a47..00000000000 --- a/changelogs/unreleased/winh-tree-view-gpg.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Display GPG status on repository and blob pages -merge_request: 20524 -author: -type: changed diff --git a/changelogs/unreleased/winh-upgrade-grape-path-helpers.yml b/changelogs/unreleased/winh-upgrade-grape-path-helpers.yml deleted file mode 100644 index 62addff1d0f..00000000000 --- a/changelogs/unreleased/winh-upgrade-grape-path-helpers.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Upgrade grape-path-helpers to 1.0.6 -merge_request: 20601 -author: -type: other diff --git a/changelogs/unreleased/wrap-job-name-on-jobs-sidebar.yml b/changelogs/unreleased/wrap-job-name-on-jobs-sidebar.yml deleted file mode 100644 index 97fa1592753..00000000000 --- a/changelogs/unreleased/wrap-job-name-on-jobs-sidebar.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Wrap job name on pipeline job sidebar -merge_request: 20804 -author: George Tsiolis -type: changed diff --git a/changelogs/unreleased/zj-remove-git-rake-tasks.yml b/changelogs/unreleased/zj-remove-git-rake-tasks.yml deleted file mode 100644 index 8c90fc7d0fe..00000000000 --- a/changelogs/unreleased/zj-remove-git-rake-tasks.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Remove gitlab:user:check_repos, gitlab:check_repo, gitlab:git:prune, gitlab:git:gc, and gitlab:git:repack -merge_request: 20806 -author: -type: removed diff --git a/changelogs/unreleased/zj-repository-languages.yml b/changelogs/unreleased/zj-repository-languages.yml deleted file mode 100644 index c42ba60be29..00000000000 --- a/changelogs/unreleased/zj-repository-languages.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Show repository languages for projects -merge_request: 19480 -author: -type: added diff --git a/config/initializers/fog_google_https_private_urls.rb b/config/initializers/fog_google_https_private_urls.rb index f92e623a5d2..c65a534b536 100644 --- a/config/initializers/fog_google_https_private_urls.rb +++ b/config/initializers/fog_google_https_private_urls.rb @@ -7,7 +7,7 @@ module Fog class GoogleXML class File < Fog::Model module MonkeyPatch - def url(expires) + def url(expires, options = {}) requires :key collection.get_https_url(key, expires) end diff --git a/danger/changelog/Dangerfile b/danger/changelog/Dangerfile index a1f94dc6004..713ed95a04c 100644 --- a/danger/changelog/Dangerfile +++ b/danger/changelog/Dangerfile @@ -53,9 +53,11 @@ end changelog_needed = (gitlab.mr_labels & NO_CHANGELOG_LABELS).empty? changelog_found = git.added_files.find { |path| path =~ %r{\A(ee/)?(changelogs/unreleased)(-ee)?/} } +mr_title = gitlab.mr_json["title"].gsub(/^WIP: */, '') + if git.modified_files.include?("CHANGELOG.md") fail "**CHANGELOG.md was edited.** Please remove the additions and create a CHANGELOG entry.\n\n" + - format(CREATE_CHANGELOG_MESSAGE, mr_iid: gitlab.mr_json["iid"], mr_title: gitlab.mr_json["title"], labels: presented_no_changelog_labels) + format(CREATE_CHANGELOG_MESSAGE, mr_iid: gitlab.mr_json["iid"], mr_title: mr_title, labels: presented_no_changelog_labels) end if changelog_needed @@ -63,6 +65,6 @@ if changelog_needed check_changelog(changelog_found) else warn "**[CHANGELOG missing](https://docs.gitlab.com/ce/development/changelog.html).**\n\n" + - format(CREATE_CHANGELOG_MESSAGE, mr_iid: gitlab.mr_json["iid"], mr_title: gitlab.mr_json["title"], labels: presented_no_changelog_labels) + format(CREATE_CHANGELOG_MESSAGE, mr_iid: gitlab.mr_json["iid"], mr_title: mr_title, labels: presented_no_changelog_labels) end end diff --git a/db/migrate/20180711103851_drop_duplicate_protected_tags.rb b/db/migrate/20180711103851_drop_duplicate_protected_tags.rb new file mode 100644 index 00000000000..8fa2137551e --- /dev/null +++ b/db/migrate/20180711103851_drop_duplicate_protected_tags.rb @@ -0,0 +1,45 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class DropDuplicateProtectedTags < ActiveRecord::Migration + DOWNTIME = false + + disable_ddl_transaction! + + BATCH_SIZE = 1000 + + class Project < ActiveRecord::Base + self.table_name = 'projects' + + include ::EachBatch + end + + class ProtectedTag < ActiveRecord::Base + self.table_name = 'protected_tags' + end + + def up + Project.each_batch(of: BATCH_SIZE) do |projects| + ids = ProtectedTag + .where(project_id: projects) + .group(:name, :project_id) + .select('max(id)') + + tags = ProtectedTag + .where(project_id: projects) + .where.not(id: ids) + + if Gitlab::Database.postgresql? + tags.delete_all + else + # Workaround needed for MySQL + sql = "SELECT id FROM (#{tags.to_sql}) protected_tags" + + ProtectedTag.where("id IN (#{sql})").delete_all # rubocop:disable GitlabSecurity/SqlInjection + end + end + end + + def down + end +end diff --git a/db/migrate/20180711103922_add_protected_tags_index.rb b/db/migrate/20180711103922_add_protected_tags_index.rb new file mode 100644 index 00000000000..7ed2258ebaf --- /dev/null +++ b/db/migrate/20180711103922_add_protected_tags_index.rb @@ -0,0 +1,18 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class AddProtectedTagsIndex < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + add_concurrent_index :protected_tags, [:project_id, :name], unique: true + end + + def down + remove_concurrent_index :protected_tags, [:project_id, :name] + end +end diff --git a/db/migrate/20180815175440_add_index_on_list_type.rb b/db/migrate/20180815175440_add_index_on_list_type.rb new file mode 100644 index 00000000000..aad805e436e --- /dev/null +++ b/db/migrate/20180815175440_add_index_on_list_type.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true +class AddIndexOnListType < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + add_concurrent_index :lists, :list_type + end + + def down + remove_concurrent_index :lists, :list_type + end +end diff --git a/db/schema.rb b/db/schema.rb index 6168a1be29e..380d4e49ddf 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1135,6 +1135,7 @@ ActiveRecord::Schema.define(version: 20180816193530) do add_index "lists", ["board_id", "label_id"], name: "index_lists_on_board_id_and_label_id", unique: true, using: :btree add_index "lists", ["label_id"], name: "index_lists_on_label_id", using: :btree + add_index "lists", ["list_type"], name: "index_lists_on_list_type", using: :btree create_table "members", force: :cascade do |t| t.integer "access_level", null: false @@ -1740,6 +1741,7 @@ ActiveRecord::Schema.define(version: 20180816193530) do t.datetime "updated_at", null: false end + add_index "protected_tags", ["project_id", "name"], name: "index_protected_tags_on_project_id_and_name", unique: true, using: :btree add_index "protected_tags", ["project_id"], name: "index_protected_tags_on_project_id", using: :btree create_table "push_event_payloads", id: false, force: :cascade do |t| diff --git a/doc/api/README.md b/doc/api/README.md index 45e926d3b6b..e2a6e87a2c3 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -53,6 +53,7 @@ following locations: - [Project Members](members.md) - [Project Snippets](project_snippets.md) - [Protected Branches](protected_branches.md) +- [Protected Tags](protected_tags.md) - [Repositories](repositories.md) - [Repository Files](repository_files.md) - [Runners](runners.md) diff --git a/doc/api/groups.md b/doc/api/groups.md index 87be36cc815..64e0d78788d 100644 --- a/doc/api/groups.md +++ b/doc/api/groups.md @@ -351,12 +351,14 @@ Example response: { "group_id": 4, "group_name": "Twitter", - "group_access_level": 30 + "group_access_level": 30, + "expires_at": null }, { "group_id": 3, "group_name": "Gitlab Org", - "group_access_level": 10 + "group_access_level": 10, + "expires_at": "2018-08-14" } ] } diff --git a/doc/api/protected_tags.md b/doc/api/protected_tags.md new file mode 100644 index 00000000000..aa750e467f8 --- /dev/null +++ b/doc/api/protected_tags.md @@ -0,0 +1,128 @@ +# Protected tags API + +>**Note:** This feature was introduced in GitLab 11.3 + +**Valid access levels** + +Currently, these levels are recognized: +``` +0 => No access +30 => Developer access +40 => Maintainer access +``` + +## List protected tags + +Gets a list of protected tags from a project. +This function takes pagination parameters `page` and `per_page` to restrict the list of protected tags. + +``` +GET /projects/:id/protected_tags +``` + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | + +```bash +curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" 'https://gitlab.example.com/api/v4/projects/5/protected_tags' +``` + +Example response: + +```json +[ + { + "name": "release-1-0", + "create_access_levels": [ + { + "access_level": 40, + "access_level_description": "Maintainers" + } + ] + }, + ... +] +``` + +## Get a single protected tag or wildcard protected tag + +Gets a single protected tag or wildcard protected tag. +The pagination parameters `page` and `per_page` can be used to restrict the list of protected tags. + +``` +GET /projects/:id/protected_tags/:name +``` + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | +| `name` | string | yes | The name of the tag or wildcard | + +```bash +curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" 'https://gitlab.example.com/api/v4/projects/5/protected_tags/release-1-0' +``` + +Example response: + +```json +{ + "name": "release-1-0", + "create_access_levels": [ + { + "access_level": 40, + "access_level_description": "Maintainers" + } + ] +} +``` + +## Protect repository tags + +Protects a single repository tag or several project repository +tags using a wildcard protected tag. + +``` +POST /projects/:id/protected_tags +``` + +```bash +curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" 'https://gitlab.example.com/api/v4/projects/5/protected_tags?name=*-stable&create_access_level=30' +``` + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | +| `name` | string | yes | The name of the tag or wildcard | +| `create_access_level` | string | no | Access levels allowed to create (defaults: `40`, maintainer access level) | + +Example response: + +```json +{ + "name": "*-stable", + "create_access_levels": [ + { + "access_level": 30, + "access_level_description": "Developers + Maintainers" + } + ] +} +``` + +## Unprotect repository tags + +Unprotects the given protected tag or wildcard protected tag. + +``` +DELETE /projects/:id/protected_tags/:name +``` + +```bash +curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" 'https://gitlab.example.com/api/v4/projects/5/protected_tags/*-stable' +``` + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | +| `name` | string | yes | The name of the tag | diff --git a/doc/development/README.md b/doc/development/README.md index ee9a9852205..20f8fa1d368 100644 --- a/doc/development/README.md +++ b/doc/development/README.md @@ -54,6 +54,7 @@ description: 'Learn how to contribute to GitLab.' - [Performance guidelines](performance.md) - [Merge request performance guidelines](merge_request_performance_guidelines.md) for ensuring merge requests do not negatively impact GitLab performance +- [Profiling](profiling.md) for profiling a URL ## Database guides diff --git a/doc/development/architecture.md b/doc/development/architecture.md index 3e417a44ec1..66d8a4f2f6e 100644 --- a/doc/development/architecture.md +++ b/doc/development/architecture.md @@ -70,7 +70,7 @@ The add-on component gitlab-shell serves repositories over SSH. It manages the S Gitaly executes git operations from gitlab-shell and the GitLab web app, and provides an API to the GitLab web app to get attributes from git (e.g. title, branches, tags, other meta data), and to get blobs (e.g. diffs, commits, files). -You may also be interested in the [production architecture of GitLab.com](https://about.gitlab.com/handbook/infrastructure/production-architecture/). +You may also be interested in the [production architecture of GitLab.com](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/). ### Installation Folder Summary diff --git a/doc/development/feature_flags.md b/doc/development/feature_flags.md index 09ea8c05be6..702caacc74f 100644 --- a/doc/development/feature_flags.md +++ b/doc/development/feature_flags.md @@ -57,3 +57,15 @@ end Features that are developed and are intended to be merged behind a feature flag should not include a changelog entry. The entry should be added in the merge request removing the feature flags. + +### Specs + +In the test environment `Feature.enabled?` is stubbed to always respond to `true`, +so we make sure behavior under feature flag doesn't go untested in some non-specific +contexts. + +If you need to test the feature flag in a different state, you need to stub it with: + +```ruby +stub_feature_flags(my_feature_flag: false) +``` diff --git a/doc/install/installation.md b/doc/install/installation.md index a310f12b29e..2d657163721 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -457,11 +457,35 @@ GitLab-Pages uses [GNU Make](https://www.gnu.org/software/make/). This step is o sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION) sudo -u git -H make +### Install Gitaly + + # Fetch Gitaly source with Git and compile with Go + sudo -u git -H bundle exec rake "gitlab:gitaly:install[/home/git/gitaly]" RAILS_ENV=production + +You can specify a different Git repository by providing it as an extra parameter: + + sudo -u git -H bundle exec rake "gitlab:gitaly:install[/home/git/gitaly,https://example.com/gitaly.git]" RAILS_ENV=production + +Next, make sure gitaly configured: + + # Restrict Gitaly socket access + sudo chmod 0700 /home/git/gitlab/tmp/sockets/private + sudo chown git /home/git/gitlab/tmp/sockets/private + + # If you are using non-default settings you need to update config.toml + cd /home/git/gitaly + sudo -u git -H editor config.toml + +For more information about configuring Gitaly see +[doc/administration/gitaly](../administration/gitaly). + ### Initialize Database and Activate Advanced Features sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production - # Type 'yes' to create the database tables. + + # or you can skip the question by adding force=yes + sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production force=yes # When done you see 'Administrator account created:' @@ -491,28 +515,6 @@ Make GitLab start on boot: sudo update-rc.d gitlab defaults 21 -### Install Gitaly - - # Fetch Gitaly source with Git and compile with Go - sudo -u git -H bundle exec rake "gitlab:gitaly:install[/home/git/gitaly,/home/git/repositories]" RAILS_ENV=production - -You can specify a different Git repository by providing it as an extra parameter: - - sudo -u git -H bundle exec rake "gitlab:gitaly:install[/home/git/gitaly,/home/git/repositories,https://example.com/gitaly.git]" RAILS_ENV=production - -Next, make sure gitaly configured: - - # Restrict Gitaly socket access - sudo chmod 0700 /home/git/gitlab/tmp/sockets/private - sudo chown git /home/git/gitlab/tmp/sockets/private - - # If you are using non-default settings you need to update config.toml - cd /home/git/gitaly - sudo -u git -H editor config.toml - -For more information about configuring Gitaly see -[doc/administration/gitaly](../administration/gitaly). - ### Setup Logrotate sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab diff --git a/doc/university/high-availability/aws/README.md b/doc/university/high-availability/aws/README.md index 8f7bb8636c5..4e7eae19844 100644 --- a/doc/university/high-availability/aws/README.md +++ b/doc/university/high-availability/aws/README.md @@ -30,7 +30,7 @@ we'll be using to configure our cloud infrastructure. ### Reference Architecture -![Reference Architecture](img/reference-arch.png) +![Reference Architecture](img/reference-arch2.png) *** diff --git a/doc/university/high-availability/aws/img/reference-arch.png b/doc/university/high-availability/aws/img/reference-arch.png Binary files differdeleted file mode 100644 index 271ee5bc614..00000000000 --- a/doc/university/high-availability/aws/img/reference-arch.png +++ /dev/null diff --git a/doc/university/high-availability/aws/img/reference-arch2.png b/doc/university/high-availability/aws/img/reference-arch2.png Binary files differnew file mode 100644 index 00000000000..9f50b2f5171 --- /dev/null +++ b/doc/university/high-availability/aws/img/reference-arch2.png diff --git a/doc/update/10.7-to-10.8.md b/doc/update/10.7-to-10.8.md index 13101a987f4..7bb628f9740 100644 --- a/doc/update/10.7-to-10.8.md +++ b/doc/update/10.7-to-10.8.md @@ -38,16 +38,16 @@ You can check which version you are running with `ruby -v`. Download Ruby and compile it: - ```bash - mkdir /tmp/ruby && cd /tmp/ruby - curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.7.tar.gz - echo '540996fec64984ab6099e34d2f5820b14904f15a ruby-2.3.7.tar.gz' | shasum -c - && tar xzf ruby-2.3.7.tar.gz - cd ruby-2.3.7 - - ./configure --disable-install-rdoc - make - sudo make install - ``` +```bash +mkdir /tmp/ruby && cd /tmp/ruby +curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.7.tar.gz +echo '540996fec64984ab6099e34d2f5820b14904f15a ruby-2.3.7.tar.gz' | shasum -c - && tar xzf ruby-2.3.7.tar.gz +cd ruby-2.3.7 + +./configure --disable-install-rdoc +make +sudo make install +``` Install Bundler: diff --git a/lib/api/api.rb b/lib/api/api.rb index e2ad3c5f4e3..c000666d992 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -99,12 +99,13 @@ module API mount ::API::Features mount ::API::Files mount ::API::GroupBoards - mount ::API::Groups mount ::API::GroupMilestones + mount ::API::Groups + mount ::API::GroupVariables mount ::API::Internal mount ::API::Issues - mount ::API::Jobs mount ::API::JobArtifacts + mount ::API::Jobs mount ::API::Keys mount ::API::Labels mount ::API::Lint @@ -122,11 +123,12 @@ module API mount ::API::ProjectExport mount ::API::ProjectImport mount ::API::ProjectHooks - mount ::API::Projects mount ::API::ProjectMilestones + mount ::API::Projects mount ::API::ProjectSnapshots mount ::API::ProjectSnippets mount ::API::ProtectedBranches + mount ::API::ProtectedTags mount ::API::Repositories mount ::API::Runner mount ::API::Runners @@ -143,7 +145,6 @@ module API mount ::API::Triggers mount ::API::Users mount ::API::Variables - mount ::API::GroupVariables mount ::API::Version mount ::API::Wikis diff --git a/lib/api/award_emoji.rb b/lib/api/award_emoji.rb index c3d93996816..bde4b3ff4f6 100644 --- a/lib/api/award_emoji.rb +++ b/lib/api/award_emoji.rb @@ -100,7 +100,7 @@ module API end def can_award_awardable? - awardable.user_can_award?(current_user, params[:name]) + awardable.user_can_award?(current_user) end def awardable diff --git a/lib/api/entities.rb b/lib/api/entities.rb index b6393fdef19..95b25d7351a 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -91,6 +91,7 @@ module API group_link.group.name end expose :group_access, as: :group_access_level + expose :expires_at end class ProjectIdentity < Grape::Entity @@ -428,6 +429,11 @@ module API expose :merge_access_levels, using: Entities::ProtectedRefAccess end + class ProtectedTag < Grape::Entity + expose :name + expose :create_access_levels, using: Entities::ProtectedRefAccess + end + class Milestone < Grape::Entity expose :id, :iid expose :project_id, if: -> (entity, options) { entity&.project_id } diff --git a/lib/api/files.rb b/lib/api/files.rb index 29d7489bd7c..ff4f75c12df 100644 --- a/lib/api/files.rb +++ b/lib/api/files.rb @@ -59,7 +59,7 @@ module API params :simple_file_params do requires :file_path, type: String, desc: 'The url encoded path to the file. Ex. lib%2Fclass%2Erb' requires :branch, type: String, desc: 'Name of the branch to commit into. To create a new branch, also provide `start_branch`.' - requires :commit_message, type: String, desc: 'Commit message' + requires :commit_message, type: String, allow_blank: false, desc: 'Commit message' optional :start_branch, type: String, desc: 'Name of the branch to start the new commit from' optional :author_email, type: String, desc: 'The email of the author' optional :author_name, type: String, desc: 'The name of the author' diff --git a/lib/api/project_snippets.rb b/lib/api/project_snippets.rb index 1de5551fee9..0ada0ef4708 100644 --- a/lib/api/project_snippets.rb +++ b/lib/api/project_snippets.rb @@ -49,7 +49,7 @@ module API params do requires :title, type: String, desc: 'The title of the snippet' requires :file_name, type: String, desc: 'The file name of the snippet' - requires :code, type: String, desc: 'The content of the snippet' + requires :code, type: String, allow_blank: false, desc: 'The content of the snippet' optional :description, type: String, desc: 'The description of a snippet' requires :visibility, type: String, values: Gitlab::VisibilityLevel.string_values, @@ -78,7 +78,7 @@ module API requires :snippet_id, type: Integer, desc: 'The ID of a project snippet' optional :title, type: String, desc: 'The title of the snippet' optional :file_name, type: String, desc: 'The file name of the snippet' - optional :code, type: String, desc: 'The content of the snippet' + optional :code, type: String, allow_blank: false, desc: 'The content of the snippet' optional :description, type: String, desc: 'The description of a snippet' optional :visibility, type: String, values: Gitlab::VisibilityLevel.string_values, diff --git a/lib/api/protected_tags.rb b/lib/api/protected_tags.rb new file mode 100644 index 00000000000..bf0a7184e1c --- /dev/null +++ b/lib/api/protected_tags.rb @@ -0,0 +1,79 @@ +module API + class ProtectedTags < Grape::API + include PaginationParams + + TAG_ENDPOINT_REQUIREMENTS = API::PROJECT_ENDPOINT_REQUIREMENTS.merge(name: API::NO_SLASH_URL_PART_REGEX) + + before { authorize_admin_project } + + params do + requires :id, type: String, desc: 'The ID of a project' + end + resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do + desc "Get a project's protected tags" do + detail 'This feature was introduced in GitLab 11.3.' + success Entities::ProtectedTag + end + params do + use :pagination + end + get ':id/protected_tags' do + protected_tags = user_project.protected_tags.preload(:create_access_levels) + + present paginate(protected_tags), with: Entities::ProtectedTag, project: user_project + end + + desc 'Get a single protected tag' do + detail 'This feature was introduced in GitLab 11.3.' + success Entities::ProtectedTag + end + params do + requires :name, type: String, desc: 'The name of the tag or wildcard' + end + get ':id/protected_tags/:name', requirements: TAG_ENDPOINT_REQUIREMENTS do + protected_tag = user_project.protected_tags.find_by!(name: params[:name]) + + present protected_tag, with: Entities::ProtectedTag, project: user_project + end + + desc 'Protect a single tag or wildcard' do + detail 'This feature was introduced in GitLab 11.3.' + success Entities::ProtectedTag + end + params do + requires :name, type: String, desc: 'The name of the protected tag' + optional :create_access_level, type: Integer, default: Gitlab::Access::MAINTAINER, + values: ProtectedRefAccess::ALLOWED_ACCESS_LEVELS, + desc: 'Access levels allowed to create (defaults: `40`, maintainer access level)' + end + post ':id/protected_tags' do + protected_tags_params = { + name: params[:name], + create_access_levels_attributes: [{ access_level: params[:create_access_level] }] + } + + protected_tag = ::ProtectedTags::CreateService.new(user_project, + current_user, + protected_tags_params).execute + + if protected_tag.persisted? + present protected_tag, with: Entities::ProtectedTag, project: user_project + else + render_api_error!(protected_tag.errors.full_messages, 422) + end + end + + desc 'Unprotect a single tag' do + detail 'This feature was introduced in GitLab 11.3.' + end + params do + requires :name, type: String, desc: 'The name of the protected tag' + end + delete ':id/protected_tags/:name', requirements: TAG_ENDPOINT_REQUIREMENTS do + protected_tag = user_project.protected_tags.find_by!(name: params[:name]) + + destroy_conditionally!(protected_tag) + end + end + end +end diff --git a/lib/banzai/reference_parser/merge_request_parser.rb b/lib/banzai/reference_parser/merge_request_parser.rb index a370ff5b5b3..9e5d55f72bc 100644 --- a/lib/banzai/reference_parser/merge_request_parser.rb +++ b/lib/banzai/reference_parser/merge_request_parser.rb @@ -14,11 +14,12 @@ module Banzai # Eager loading these ensures we don't end up running dozens of # queries in this process. target_project: [ - { namespace: :owner }, + { namespace: [:owner, :route] }, { group: [:owners, :group_members] }, :invited_groups, :project_members, - :project_feature + :project_feature, + :route ] }), self.class.data_attribute diff --git a/lib/feature.rb b/lib/feature.rb index 09c5ef3ad94..24dbcb32fc0 100644 --- a/lib/feature.rb +++ b/lib/feature.rb @@ -47,7 +47,8 @@ class Feature end def disabled?(key, thing = nil) - !enabled?(key, thing) + # we need to make different method calls to make it easy to mock / define expectations in test mode + thing.nil? ? !enabled?(key) : !enabled?(key, thing) end def enable(key, thing = true) diff --git a/lib/gitlab/auth/ldap/access.rb b/lib/gitlab/auth/ldap/access.rb index 865185eb5db..eeab7791643 100644 --- a/lib/gitlab/auth/ldap/access.rb +++ b/lib/gitlab/auth/ldap/access.rb @@ -19,8 +19,10 @@ module Gitlab # Whether user is allowed, or not, we should update # permissions to keep things clean if access.allowed? - access.update_user - Users::UpdateService.new(user, user: user, last_credential_check_at: Time.now).execute + unless Gitlab::Database.read_only? + access.update_user + Users::UpdateService.new(user, user: user, last_credential_check_at: Time.now).execute + end true else @@ -60,6 +62,12 @@ module Gitlab false end + def update_user + # no-op in CE + end + + private + def adapter @adapter ||= Gitlab::Auth::LDAP::Adapter.new(provider) end @@ -68,16 +76,16 @@ module Gitlab Gitlab::Auth::LDAP::Config.new(provider) end - def find_ldap_user - Gitlab::Auth::LDAP::Person.find_by_dn(ldap_identity.extern_uid, adapter) - end - def ldap_user return unless provider @ldap_user ||= find_ldap_user end + def find_ldap_user + Gitlab::Auth::LDAP::Person.find_by_dn(ldap_identity.extern_uid, adapter) + end + def block_user(user, reason) user.ldap_block @@ -102,10 +110,6 @@ module Gitlab "unblocking Gitlab user \"#{user.name}\" (#{user.email})" ) end - - def update_user - # no-op in CE - end end end end diff --git a/lib/gitlab/auth/o_auth/provider.rb b/lib/gitlab/auth/o_auth/provider.rb index e73743944a9..26da9d09ccc 100644 --- a/lib/gitlab/auth/o_auth/provider.rb +++ b/lib/gitlab/auth/o_auth/provider.rb @@ -29,6 +29,7 @@ module Gitlab def self.enabled?(name) return true if name == 'database' + return true if self.ldap_provider?(name) && providers.include?(name.to_sym) Gitlab::Auth.omniauth_enabled? && providers.include?(name.to_sym) end diff --git a/lib/gitlab/bitbucket_server_import/importer.rb b/lib/gitlab/bitbucket_server_import/importer.rb index 268d21a77d1..b591d94668f 100644 --- a/lib/gitlab/bitbucket_server_import/importer.rb +++ b/lib/gitlab/bitbucket_server_import/importer.rb @@ -1,7 +1,10 @@ +# frozen_string_literal: true + module Gitlab module BitbucketServerImport class Importer include Gitlab::ShellAdapter + attr_reader :recover_missing_commits attr_reader :project, :project_key, :repository_slug, :client, :errors, :users @@ -175,21 +178,18 @@ module Gitlab description = '' description += @formatter.author_line(pull_request.author) unless find_user_id(pull_request.author_email) description += pull_request.description if pull_request.description - - source_branch_sha = pull_request.source_branch_sha - target_branch_sha = pull_request.target_branch_sha author_id = gitlab_user_id(pull_request.author_email) attributes = { iid: pull_request.iid, title: pull_request.title, description: description, - source_project: project, + source_project_id: project.id, source_branch: Gitlab::Git.ref_name(pull_request.source_branch_name), - source_branch_sha: source_branch_sha, - target_project: project, + source_branch_sha: pull_request.source_branch_sha, + target_project_id: project.id, target_branch: Gitlab::Git.ref_name(pull_request.target_branch_name), - target_branch_sha: target_branch_sha, + target_branch_sha: pull_request.target_branch_sha, state: pull_request.state, author_id: author_id, assignee_id: nil, @@ -197,7 +197,9 @@ module Gitlab updated_at: pull_request.updated_at } - merge_request = project.merge_requests.create!(attributes) + creator = Gitlab::Import::MergeRequestCreator.new(project) + merge_request = creator.execute(attributes) + import_pull_request_comments(pull_request, merge_request) if merge_request.persisted? end diff --git a/lib/gitlab/github_import.rb b/lib/gitlab/github_import.rb index 65b5e30c70f..d40b06f969f 100644 --- a/lib/gitlab/github_import.rb +++ b/lib/gitlab/github_import.rb @@ -10,24 +10,6 @@ module Gitlab Client.new(token_to_use, parallel: parallel) end - # Inserts a raw row and returns the ID of the inserted row. - # - # attributes - The attributes/columns to set. - # relation - An ActiveRecord::Relation to use for finding the ID of the row - # when using MySQL. - def self.insert_and_return_id(attributes, relation) - # We use bulk_insert here so we can bypass any queries executed by - # callbacks or validation rules, as doing this wouldn't scale when - # importing very large projects. - result = Gitlab::Database - .bulk_insert(relation.table_name, [attributes], return_ids: true) - - # MySQL doesn't support returning the IDs of a bulk insert in a way that - # is not a pain, so in this case we'll issue an extra query instead. - result.first || - relation.where(iid: attributes[:iid]).limit(1).pluck(:id).first - end - # Returns the ID of the ghost user. def self.ghost_user_id key = 'github-import/ghost-user-id' diff --git a/lib/gitlab/github_import/importer/issue_importer.rb b/lib/gitlab/github_import/importer/issue_importer.rb index cb4d7a6a0b6..4226eee85cc 100644 --- a/lib/gitlab/github_import/importer/issue_importer.rb +++ b/lib/gitlab/github_import/importer/issue_importer.rb @@ -4,6 +4,8 @@ module Gitlab module GithubImport module Importer class IssueImporter + include Gitlab::Import::DatabaseHelpers + attr_reader :project, :issue, :client, :user_finder, :milestone_finder, :issuable_finder @@ -55,7 +57,7 @@ module Gitlab updated_at: issue.updated_at } - GithubImport.insert_and_return_id(attributes, project.issues).tap do |id| + insert_and_return_id(attributes, project.issues).tap do |id| # We use .insert_and_return_id which effectively disables all callbacks. # Trigger iid logic here to make sure we track internal id values consistently. project.issues.find(id).ensure_project_iid! diff --git a/lib/gitlab/github_import/importer/pull_request_importer.rb b/lib/gitlab/github_import/importer/pull_request_importer.rb index ed17aa54373..ae7c4cf1b38 100644 --- a/lib/gitlab/github_import/importer/pull_request_importer.rb +++ b/lib/gitlab/github_import/importer/pull_request_importer.rb @@ -4,6 +4,8 @@ module Gitlab module GithubImport module Importer class PullRequestImporter + include Gitlab::Import::MergeRequestHelpers + attr_reader :pull_request, :project, :client, :user_finder, :milestone_finder, :issuable_finder @@ -44,81 +46,27 @@ module Gitlab description = MarkdownText .format(pull_request.description, pull_request.author, author_found) - # This work must be wrapped in a transaction as otherwise we can leave - # behind incomplete data in the event of an error. This can then lead - # to duplicate key errors when jobs are retried. - MergeRequest.transaction do - attributes = { - iid: pull_request.iid, - title: pull_request.truncated_title, - description: description, - source_project_id: project.id, - target_project_id: project.id, - source_branch: pull_request.formatted_source_branch, - target_branch: pull_request.target_branch, - state: pull_request.state, - milestone_id: milestone_finder.id_for(pull_request), - author_id: author_id, - assignee_id: user_finder.assignee_id_for(pull_request), - created_at: pull_request.created_at, - updated_at: pull_request.updated_at - } - - # When creating merge requests there are a lot of hooks that may - # run, for many different reasons. Many of these hooks (e.g. the - # ones used for rendering Markdown) are completely unnecessary and - # may even lead to transaction timeouts. - # - # To ensure importing pull requests has a minimal impact and can - # complete in a reasonable time we bypass all the hooks by inserting - # the row and then retrieving it. We then only perform the - # additional work that is strictly necessary. - merge_request_id = GithubImport - .insert_and_return_id(attributes, project.merge_requests) - - merge_request = project.merge_requests.find(merge_request_id) - - # We use .insert_and_return_id which effectively disables all callbacks. - # Trigger iid logic here to make sure we track internal id values consistently. - merge_request.ensure_target_project_iid! + attributes = { + iid: pull_request.iid, + title: pull_request.truncated_title, + description: description, + source_project_id: project.id, + target_project_id: project.id, + source_branch: pull_request.formatted_source_branch, + target_branch: pull_request.target_branch, + state: pull_request.state, + milestone_id: milestone_finder.id_for(pull_request), + author_id: author_id, + assignee_id: user_finder.assignee_id_for(pull_request), + created_at: pull_request.created_at, + updated_at: pull_request.updated_at + } - [merge_request, false] - end - rescue ActiveRecord::InvalidForeignKey - # It's possible the project has been deleted since scheduling this - # job. In this case we'll just skip creating the merge request. - [] - rescue ActiveRecord::RecordNotUnique - # It's possible we previously created the MR, but failed when updating - # the Git data. In this case we'll just continue working on the - # existing row. - [project.merge_requests.find_by(iid: pull_request.iid), true] + create_merge_request_without_hooks(project, attributes, pull_request.iid) end - def insert_git_data(merge_request, already_exists = false) - # These fields are set so we can create the correct merge request - # diffs. - merge_request.source_branch_sha = pull_request.source_branch_sha - merge_request.target_branch_sha = pull_request.target_branch_sha - - merge_request.keep_around_commit - - # MR diffs normally use an "after_save" hook to pull data from Git. - # All of this happens in the transaction started by calling - # create/save/etc. This in turn can lead to these transactions being - # held open for much longer than necessary. To work around this we - # first save the diff, then populate it. - diff = - if already_exists - merge_request.merge_request_diffs.take || - merge_request.merge_request_diffs.build - else - merge_request.merge_request_diffs.build - end - - diff.importing = true - diff.save - diff.save_git_content + def insert_git_data(merge_request, already_exists) + insert_or_replace_git_data(merge_request, pull_request.source_branch_sha, pull_request.target_branch_sha, already_exists) end end end diff --git a/lib/gitlab/import/database_helpers.rb b/lib/gitlab/import/database_helpers.rb new file mode 100644 index 00000000000..80857061933 --- /dev/null +++ b/lib/gitlab/import/database_helpers.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Gitlab + module Import + module DatabaseHelpers + # Inserts a raw row and returns the ID of the inserted row. + # + # attributes - The attributes/columns to set. + # relation - An ActiveRecord::Relation to use for finding the ID of the row + # when using MySQL. + def insert_and_return_id(attributes, relation) + # We use bulk_insert here so we can bypass any queries executed by + # callbacks or validation rules, as doing this wouldn't scale when + # importing very large projects. + result = Gitlab::Database + .bulk_insert(relation.table_name, [attributes], return_ids: true) + + # MySQL doesn't support returning the IDs of a bulk insert in a way that + # is not a pain, so in this case we'll issue an extra query instead. + result.first || + relation.where(iid: attributes[:iid]).limit(1).pluck(:id).first + end + end + end +end diff --git a/lib/gitlab/import/merge_request_creator.rb b/lib/gitlab/import/merge_request_creator.rb new file mode 100644 index 00000000000..a01951b0762 --- /dev/null +++ b/lib/gitlab/import/merge_request_creator.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +# This module is designed for importers that need to create many merge +# requests quickly. When creating merge requests there are a lot of hooks +# that may run, for many different reasons. Many of these hooks (e.g. the ones +# used for rendering Markdown) are completely unnecessary and may even lead to +# transaction timeouts. +# +# To ensure importing merge requests requests has a minimal impact and can +# complete in a reasonable time we bypass all the hooks by inserting the row +# and then retrieving it. We then only perform the additional work that is +# strictly necessary. +module Gitlab + module Import + class MergeRequestCreator + include ::Gitlab::Import::DatabaseHelpers + include ::Gitlab::Import::MergeRequestHelpers + + attr_accessor :project + + def initialize(project) + @project = project + end + + def execute(attributes) + source_branch_sha = attributes.delete(:source_branch_sha) + target_branch_sha = attributes.delete(:target_branch_sha) + iid = attributes[:iid] + + merge_request, already_exists = create_merge_request_without_hooks(project, attributes, iid) + + if merge_request + insert_or_replace_git_data(merge_request, source_branch_sha, target_branch_sha, already_exists) + end + + merge_request + end + end + end +end diff --git a/lib/gitlab/import/merge_request_helpers.rb b/lib/gitlab/import/merge_request_helpers.rb new file mode 100644 index 00000000000..8ba70700dc1 --- /dev/null +++ b/lib/gitlab/import/merge_request_helpers.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +module Gitlab + module Import + module MergeRequestHelpers + include DatabaseHelpers + + def create_merge_request_without_hooks(project, attributes, iid) + # This work must be wrapped in a transaction as otherwise we can leave + # behind incomplete data in the event of an error. This can then lead + # to duplicate key errors when jobs are retried. + MergeRequest.transaction do + # When creating merge requests there are a lot of hooks that may + # run, for many different reasons. Many of these hooks (e.g. the + # ones used for rendering Markdown) are completely unnecessary and + # may even lead to transaction timeouts. + # + # To ensure importing pull requests has a minimal impact and can + # complete in a reasonable time we bypass all the hooks by inserting + # the row and then retrieving it. We then only perform the + # additional work that is strictly necessary. + merge_request_id = insert_and_return_id(attributes, project.merge_requests) + + merge_request = project.merge_requests.find(merge_request_id) + + # We use .insert_and_return_id which effectively disables all callbacks. + # Trigger iid logic here to make sure we track internal id values consistently. + merge_request.ensure_target_project_iid! + + [merge_request, false] + end + rescue ActiveRecord::InvalidForeignKey + # It's possible the project has been deleted since scheduling this + # job. In this case we'll just skip creating the merge request. + [] + rescue ActiveRecord::RecordNotUnique + # It's possible we previously created the MR, but failed when updating + # the Git data. In this case we'll just continue working on the + # existing row. + [project.merge_requests.find_by(iid: iid), true] + end + + def insert_or_replace_git_data(merge_request, source_branch_sha, target_branch_sha, already_exists = false) + # These fields are set so we can create the correct merge request + # diffs. + merge_request.source_branch_sha = source_branch_sha + merge_request.target_branch_sha = target_branch_sha + + merge_request.keep_around_commit + + # MR diffs normally use an "after_save" hook to pull data from Git. + # All of this happens in the transaction started by calling + # create/save/etc. This in turn can lead to these transactions being + # held open for much longer than necessary. To work around this we + # first save the diff, then populate it. + diff = + if already_exists + merge_request.merge_request_diffs.take || + merge_request.merge_request_diffs.build + else + merge_request.merge_request_diffs.build + end + + diff.importing = true + diff.save + diff.save_git_content + end + end + end +end diff --git a/lib/gitlab/middleware/multipart.rb b/lib/gitlab/middleware/multipart.rb index 18f91db98fc..3d588918adf 100644 --- a/lib/gitlab/middleware/multipart.rb +++ b/lib/gitlab/middleware/multipart.rb @@ -82,9 +82,13 @@ module Gitlab end def open_file(params, key) - ::UploadedFile.from_params( - params, key, - [FileUploader.root, Gitlab.config.uploads.storage_path]) + allowed_paths = [ + FileUploader.root, + Gitlab.config.uploads.storage_path, + File.join(Rails.root, 'public/uploads/tmp') + ] + + ::UploadedFile.from_params(params, key, allowed_paths) end end diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb index 22c9638ecc0..7797bd5fab2 100644 --- a/lib/gitlab/usage_data.rb +++ b/lib/gitlab/usage_data.rb @@ -34,6 +34,7 @@ module Gitlab def system_usage_data { counts: { + assignee_lists: List.assignee.count, boards: Board.count, ci_builds: ::Ci::Build.count, ci_internal_pipelines: ::Ci::Pipeline.internal.count, @@ -61,9 +62,11 @@ module Gitlab groups: Group.count, issues: Issue.count, keys: Key.count, + label_lists: List.label.count, labels: Label.count, lfs_objects: LfsObject.count, merge_requests: MergeRequest.count, + milestone_lists: List.milestone.count, milestones: Milestone.count, notes: Note.count, pages_domains: PagesDomain.count, diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 73bff79aabe..0bf552d6084 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -2508,6 +2508,12 @@ msgstr "" msgid "Error loading project data. Please try again." msgstr "" +msgid "Error loading template types." +msgstr "" + +msgid "Error loading template." +msgstr "" + msgid "Error occurred when toggling the notification subscription" msgstr "" @@ -6700,6 +6706,9 @@ msgstr "" msgid "mrWidget|The source branch has been removed" msgstr "" +msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch" +msgstr "" + msgid "mrWidget|The source branch is being removed" msgstr "" diff --git a/package.json b/package.json index f5fc759f76e..17ff85c9cd0 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "webpack-prod": "NODE_ENV=production webpack --config config/webpack.config.js" }, "dependencies": { - "@gitlab-org/gitlab-svgs": "^1.27.0", + "@gitlab-org/gitlab-svgs": "^1.28.0", "@gitlab-org/gitlab-ui": "1.0.5", "autosize": "^4.0.0", "axios": "^0.17.1", @@ -83,6 +83,7 @@ module QA # Test scenario entrypoints. # module Test + autoload :Instance, 'qa/scenario/test/instance' module Instance autoload :All, 'qa/scenario/test/instance/all' autoload :Smoke, 'qa/scenario/test/instance/smoke' diff --git a/qa/qa/page/project/import/github.rb b/qa/qa/page/project/import/github.rb index 36567927194..1a410a0f8a5 100644 --- a/qa/qa/page/project/import/github.rb +++ b/qa/qa/page/project/import/github.rb @@ -14,7 +14,7 @@ module QA element :project_import_row, 'data: { qa: { repo_path: repo.full_name } }' element :project_namespace_select element :project_namespace_field, 'select_tag :namespace_id' - element :project_path_field, 'text_field_tag :path, repo.name' + element :project_path_field, 'text_field_tag :path, sanitize_project_name(repo.name)' element :import_button, "_('Import')" end diff --git a/qa/qa/scenario/test/instance.rb b/qa/qa/scenario/test/instance.rb new file mode 100644 index 00000000000..b9a73d3ffb8 --- /dev/null +++ b/qa/qa/scenario/test/instance.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +module QA + module Scenario + module Test + # This class exists for back-compatibility so that gitlab-qa can continue + # to call Test::Instance instead of Test::Instance::All until at least + # the current latest GitLab version has the Test::Instance::All class. + # As of Aug, 22nd 2018. Only GitLab >= 11.3 has this class. + module Instance + include Bootable + + def self.perform(*args) + self.tap do |scenario| + yield scenario if block_given? + break scenario.do_perform(*args) + end + end + + def self.do_perform(address, *rspec_options) + Runtime::Scenario.define(:gitlab_address, address) + + Specs::Runner.perform do |specs| + specs.tty = true + specs.options = + if rspec_options.any? + rspec_options + else + ::File.expand_path('../specs/features', __dir__) + end + end + end + end + end + end +end diff --git a/qa/qa/scenario/test/integration/github.rb b/qa/qa/scenario/test/integration/github.rb index 1d22b532aa5..76c3923d68a 100644 --- a/qa/qa/scenario/test/integration/github.rb +++ b/qa/qa/scenario/test/integration/github.rb @@ -2,7 +2,7 @@ module QA module Scenario module Test module Integration - class Github < Test::Instance + class Github < Test::Instance::All tags :github def perform(address, *rspec_options) diff --git a/qa/qa/scenario/test/integration/kubernetes.rb b/qa/qa/scenario/test/integration/kubernetes.rb index 7479073e979..405962caeed 100644 --- a/qa/qa/scenario/test/integration/kubernetes.rb +++ b/qa/qa/scenario/test/integration/kubernetes.rb @@ -2,7 +2,7 @@ module QA module Scenario module Test module Integration - class Kubernetes < Test::Instance + class Kubernetes < Test::Instance::All tags :kubernetes end end diff --git a/qa/qa/scenario/test/integration/ldap.rb b/qa/qa/scenario/test/integration/ldap.rb index 257ed81d9e1..769fa389785 100644 --- a/qa/qa/scenario/test/integration/ldap.rb +++ b/qa/qa/scenario/test/integration/ldap.rb @@ -2,7 +2,7 @@ module QA module Scenario module Test module Integration - class LDAP < Test::Instance + class LDAP < Test::Instance::All tags :ldap end end diff --git a/qa/qa/scenario/test/integration/mattermost.rb b/qa/qa/scenario/test/integration/mattermost.rb index 13bfad28b0b..831c6a9fcff 100644 --- a/qa/qa/scenario/test/integration/mattermost.rb +++ b/qa/qa/scenario/test/integration/mattermost.rb @@ -6,7 +6,7 @@ module QA # Run test suite against any GitLab instance where mattermost is enabled, # including staging and on-premises installation. # - class Mattermost < Test::Instance + class Mattermost < Test::Instance::All tags :core, :mattermost def perform(address, mattermost, *rspec_options) diff --git a/scripts/frontend/extract_gettext_all.js b/scripts/frontend/extract_gettext_all.js index af8cc4c3341..725522a3540 100644 --- a/scripts/frontend/extract_gettext_all.js +++ b/scripts/frontend/extract_gettext_all.js @@ -7,7 +7,7 @@ const { } = require('gettext-extractor-vue'); const ensureSingleLine = require('../../app/assets/javascripts/locale/ensure_single_line.js'); -const arguments = argumentsParser +const args = argumentsParser .option('-f, --file <file>', 'Extract message from one single file') .option('-a, --all', 'Extract message from all js/vue files') .parse(process.argv); @@ -61,12 +61,12 @@ function printJson() { console.log(JSON.stringify(messages)); } -if (arguments.file) { - vueParser.parseFile(arguments.file).then(() => printJson()); -} else if (arguments.all) { +if (args.file) { + vueParser.parseFile(args.file).then(() => printJson()); +} else if (args.all) { vueParser.parseFilesGlob('{ee/app,app}/assets/javascripts/**/*.{js,vue}').then(() => printJson()); } else { console.warn('ERROR: Please use the script correctly:'); - arguments.outputHelp(); + args.outputHelp(); process.exit(1); } diff --git a/spec/controllers/projects/commit_controller_spec.rb b/spec/controllers/projects/commit_controller_spec.rb index 916a4be2567..9e149bc4c3c 100644 --- a/spec/controllers/projects/commit_controller_spec.rb +++ b/spec/controllers/projects/commit_controller_spec.rb @@ -230,7 +230,7 @@ describe Projects::CommitController do id: master_pickable_commit.id) expect(response).to redirect_to project_commits_path(project, 'master') - expect(flash[:notice]).to eq('The commit has been successfully cherry-picked.') + expect(flash[:notice]).to eq('The commit has been successfully cherry-picked into master.') end end diff --git a/spec/controllers/projects/merge_requests/creations_controller_spec.rb b/spec/controllers/projects/merge_requests/creations_controller_spec.rb index d8995f98575..f8c37c0a676 100644 --- a/spec/controllers/projects/merge_requests/creations_controller_spec.rb +++ b/spec/controllers/projects/merge_requests/creations_controller_spec.rb @@ -29,6 +29,55 @@ describe Projects::MergeRequests::CreationsController do expect(response).to be_success end end + + context 'merge request with some commits' do + render_views + + let(:large_diff_params) do + { + namespace_id: fork_project.namespace.to_param, + project_id: fork_project, + merge_request: { + source_branch: 'master', + target_branch: 'fix' + } + } + end + + describe 'with artificial limits' do + before do + # Load MergeRequestdiff so stub_const won't override it with its own definition + # See https://github.com/rspec/rspec-mocks/issues/1079 + stub_const("#{MergeRequestDiff}::COMMITS_SAFE_SIZE", 2) + end + + it 'limits total commits' do + get :new, large_diff_params + + expect(response).to be_success + + total = assigns(:total_commit_count) + expect(assigns(:commits)).to be_an Array + expect(total).to be > 0 + expect(assigns(:hidden_commit_count)).to be > 0 + expect(response).to have_gitlab_http_status(200) + expect(response.body).to match %r(<span class="commits-count">2 commits</span>) + end + end + + it 'shows total commits' do + get :new, large_diff_params + + expect(response).to be_success + + total = assigns(:total_commit_count) + expect(assigns(:commits)).to be_an Array + expect(total).to be > 0 + expect(assigns(:hidden_commit_count)).to eq(0) + expect(response).to have_gitlab_http_status(200) + expect(response.body).to match %r(<span class="commits-count">#{total} commits</span>) + end + end end describe 'GET diffs' do diff --git a/spec/factories/project_group_links.rb b/spec/factories/project_group_links.rb index d5ace9425a0..59c77627ee5 100644 --- a/spec/factories/project_group_links.rb +++ b/spec/factories/project_group_links.rb @@ -2,5 +2,6 @@ FactoryBot.define do factory :project_group_link do project group + expires_at nil end end diff --git a/spec/features/projects/commit/cherry_pick_spec.rb b/spec/features/projects/commit/cherry_pick_spec.rb index bc3c00dafe2..a61b614dbc8 100644 --- a/spec/features/projects/commit/cherry_pick_spec.rb +++ b/spec/features/projects/commit/cherry_pick_spec.rb @@ -21,7 +21,7 @@ describe 'Cherry-pick Commits' do uncheck 'create_merge_request' click_button 'Cherry-pick' end - expect(page).to have_content('The commit has been successfully cherry-picked.') + expect(page).to have_content('The commit has been successfully cherry-picked into master.') end end @@ -32,7 +32,7 @@ describe 'Cherry-pick Commits' do uncheck 'create_merge_request' click_button 'Cherry-pick' end - expect(page).to have_content('The commit has been successfully cherry-picked.') + expect(page).to have_content('The commit has been successfully cherry-picked into master.') end end @@ -59,7 +59,7 @@ describe 'Cherry-pick Commits' do page.within('#modal-cherry-pick-commit') do click_button 'Cherry-pick' end - expect(page).to have_content('The commit has been successfully cherry-picked. You can now submit a merge request to get this change into the original branch.') + expect(page).to have_content("The commit has been successfully cherry-picked into cherry-pick-#{master_pickable_commit.short_id}. You can now submit a merge request to get this change into the original branch.") expect(page).to have_content("From cherry-pick-#{master_pickable_commit.short_id} into master") end end @@ -86,7 +86,7 @@ describe 'Cherry-pick Commits' do click_button 'Cherry-pick' end - expect(page).to have_content('The commit has been successfully cherry-picked.') + expect(page).to have_content('The commit has been successfully cherry-picked into feature.') end end diff --git a/spec/helpers/import_helper_spec.rb b/spec/helpers/import_helper_spec.rb index 033155617c6..cb0ea4e26ba 100644 --- a/spec/helpers/import_helper_spec.rb +++ b/spec/helpers/import_helper_spec.rb @@ -1,6 +1,16 @@ require 'rails_helper' describe ImportHelper do + describe '#sanitize_project_name' do + it 'removes whitespace' do + expect(helper.sanitize_project_name('my test repo')).to eq('my-test-repo') + end + + it 'removes disallowed characters' do + expect(helper.sanitize_project_name('Test&me$over*h_ere')).to eq('Test-me-over-h_ere') + end + end + describe '#import_project_target' do let(:user) { create(:user) } diff --git a/spec/javascripts/badges/dummy_badge.js b/spec/javascripts/badges/dummy_badge.js index 6aaff21c503..f0cdaddbd33 100644 --- a/spec/javascripts/badges/dummy_badge.js +++ b/spec/javascripts/badges/dummy_badge.js @@ -1,8 +1,9 @@ +import _ from 'underscore'; import { PROJECT_BADGE } from '~/badges/constants'; import { DUMMY_IMAGE_URL, TEST_HOST } from 'spec/test_constants'; export const createDummyBadge = () => { - const id = Math.floor(1000 * Math.random()); + const id = _.uniqueId(); return { id, imageUrl: `${TEST_HOST}/badges/${id}/image/url`, diff --git a/spec/javascripts/helpers/vue_mount_component_helper.js b/spec/javascripts/helpers/vue_mount_component_helper.js index 1057f0aca3e..6848c95d95d 100644 --- a/spec/javascripts/helpers/vue_mount_component_helper.js +++ b/spec/javascripts/helpers/vue_mount_component_helper.js @@ -1,3 +1,5 @@ +import Vue from 'vue'; + const mountComponent = (Component, props = {}, el = null) => new Component({ propsData: props, @@ -25,4 +27,12 @@ export const mountComponentWithSlots = (Component, { props, slots }) => { return component.$mount(); }; +/** + * Mount a component with the given render method. + * + * This helps with inserting slots that need to be compiled. + */ +export const mountComponentWithRender = (render, el = null) => + mountComponent(Vue.extend({ render }), {}, el); + export default mountComponent; diff --git a/spec/javascripts/ide/stores/modules/file_templates/actions_spec.js b/spec/javascripts/ide/stores/modules/file_templates/actions_spec.js new file mode 100644 index 00000000000..f831a9f0a5d --- /dev/null +++ b/spec/javascripts/ide/stores/modules/file_templates/actions_spec.js @@ -0,0 +1,336 @@ +import MockAdapter from 'axios-mock-adapter'; +import axios from '~/lib/utils/axios_utils'; +import createState from '~/ide/stores/modules/file_templates/state'; +import * as actions from '~/ide/stores/modules/file_templates/actions'; +import * as types from '~/ide/stores/modules/file_templates/mutation_types'; +import testAction from 'spec/helpers/vuex_action_helper'; + +describe('IDE file templates actions', () => { + let state; + let mock; + + beforeEach(() => { + state = createState(); + + mock = new MockAdapter(axios); + }); + + afterEach(() => { + mock.restore(); + }); + + describe('requestTemplateTypes', () => { + it('commits REQUEST_TEMPLATE_TYPES', done => { + testAction( + actions.requestTemplateTypes, + null, + state, + [{ type: types.REQUEST_TEMPLATE_TYPES }], + [], + done, + ); + }); + }); + + describe('receiveTemplateTypesError', () => { + it('commits RECEIVE_TEMPLATE_TYPES_ERROR and dispatches setErrorMessage', done => { + testAction( + actions.receiveTemplateTypesError, + null, + state, + [{ type: types.RECEIVE_TEMPLATE_TYPES_ERROR }], + [ + { + type: 'setErrorMessage', + payload: { + action: jasmine.any(Function), + actionText: 'Please try again', + text: 'Error loading template types.', + }, + }, + ], + done, + ); + }); + }); + + describe('receiveTemplateTypesSuccess', () => { + it('commits RECEIVE_TEMPLATE_TYPES_SUCCESS', done => { + testAction( + actions.receiveTemplateTypesSuccess, + 'test', + state, + [{ type: types.RECEIVE_TEMPLATE_TYPES_SUCCESS, payload: 'test' }], + [], + done, + ); + }); + }); + + describe('fetchTemplateTypes', () => { + describe('success', () => { + beforeEach(() => { + mock.onGet(/api\/(.*)\/templates\/licenses/).replyOnce(200, [ + { + name: 'MIT', + }, + ]); + }); + + it('rejects if selectedTemplateType is empty', done => { + const dispatch = jasmine.createSpy('dispatch'); + + actions + .fetchTemplateTypes({ dispatch, state }) + .then(done.fail) + .catch(() => { + expect(dispatch).not.toHaveBeenCalled(); + + done(); + }); + }); + + it('dispatches actions', done => { + state.selectedTemplateType = { + key: 'licenses', + }; + + testAction( + actions.fetchTemplateTypes, + null, + state, + [], + [ + { + type: 'requestTemplateTypes', + }, + { + type: 'receiveTemplateTypesSuccess', + payload: [ + { + name: 'MIT', + }, + ], + }, + ], + done, + ); + }); + }); + + describe('error', () => { + beforeEach(() => { + mock.onGet(/api\/(.*)\/templates\/licenses/).replyOnce(500); + }); + + it('dispatches actions', done => { + state.selectedTemplateType = { + key: 'licenses', + }; + + testAction( + actions.fetchTemplateTypes, + null, + state, + [], + [ + { + type: 'requestTemplateTypes', + }, + { + type: 'receiveTemplateTypesError', + }, + ], + done, + ); + }); + }); + }); + + describe('setSelectedTemplateType', () => { + it('commits SET_SELECTED_TEMPLATE_TYPE', done => { + testAction( + actions.setSelectedTemplateType, + 'test', + state, + [{ type: types.SET_SELECTED_TEMPLATE_TYPE, payload: 'test' }], + [], + done, + ); + }); + }); + + describe('receiveTemplateError', () => { + it('dispatches setErrorMessage', done => { + testAction( + actions.receiveTemplateError, + 'test', + state, + [], + [ + { + type: 'setErrorMessage', + payload: { + action: jasmine.any(Function), + actionText: 'Please try again', + text: 'Error loading template.', + actionPayload: 'test', + }, + }, + ], + done, + ); + }); + }); + + describe('fetchTemplate', () => { + describe('success', () => { + beforeEach(() => { + mock.onGet(/api\/(.*)\/templates\/licenses\/mit/).replyOnce(200, { + content: 'MIT content', + }); + mock.onGet(/api\/(.*)\/templates\/licenses\/testing/).replyOnce(200, { + content: 'testing content', + }); + }); + + it('dispatches setFileTemplate if template already has content', done => { + const template = { + content: 'already has content', + }; + + testAction( + actions.fetchTemplate, + template, + state, + [], + [{ type: 'setFileTemplate', payload: template }], + done, + ); + }); + + it('dispatches success', done => { + const template = { + key: 'mit', + }; + + state.selectedTemplateType = { + key: 'licenses', + }; + + testAction( + actions.fetchTemplate, + template, + state, + [], + [{ type: 'setFileTemplate', payload: { content: 'MIT content' } }], + done, + ); + }); + + it('dispatches success and uses name key for API call', done => { + const template = { + name: 'testing', + }; + + state.selectedTemplateType = { + key: 'licenses', + }; + + testAction( + actions.fetchTemplate, + template, + state, + [], + [{ type: 'setFileTemplate', payload: { content: 'testing content' } }], + done, + ); + }); + }); + + describe('error', () => { + beforeEach(() => { + mock.onGet(/api\/(.*)\/templates\/licenses\/mit/).replyOnce(500); + }); + + it('dispatches error', done => { + const template = { + name: 'testing', + }; + + state.selectedTemplateType = { + key: 'licenses', + }; + + testAction( + actions.fetchTemplate, + template, + state, + [], + [{ type: 'receiveTemplateError', payload: template }], + done, + ); + }); + }); + }); + + describe('setFileTemplate', () => { + it('dispatches changeFileContent', () => { + const dispatch = jasmine.createSpy('dispatch'); + const commit = jasmine.createSpy('commit'); + const rootGetters = { + activeFile: { path: 'test' }, + }; + + actions.setFileTemplate({ dispatch, commit, rootGetters }, { content: 'content' }); + + expect(dispatch).toHaveBeenCalledWith( + 'changeFileContent', + { path: 'test', content: 'content' }, + { root: true }, + ); + }); + + it('commits SET_UPDATE_SUCCESS', () => { + const dispatch = jasmine.createSpy('dispatch'); + const commit = jasmine.createSpy('commit'); + const rootGetters = { + activeFile: { path: 'test' }, + }; + + actions.setFileTemplate({ dispatch, commit, rootGetters }, { content: 'content' }); + + expect(commit).toHaveBeenCalledWith('SET_UPDATE_SUCCESS', true); + }); + }); + + describe('undoFileTemplate', () => { + it('dispatches changeFileContent', () => { + const dispatch = jasmine.createSpy('dispatch'); + const commit = jasmine.createSpy('commit'); + const rootGetters = { + activeFile: { path: 'test', raw: 'raw content' }, + }; + + actions.undoFileTemplate({ dispatch, commit, rootGetters }); + + expect(dispatch).toHaveBeenCalledWith( + 'changeFileContent', + { path: 'test', content: 'raw content' }, + { root: true }, + ); + }); + + it('commits SET_UPDATE_SUCCESS', () => { + const dispatch = jasmine.createSpy('dispatch'); + const commit = jasmine.createSpy('commit'); + const rootGetters = { + activeFile: { path: 'test', raw: 'raw content' }, + }; + + actions.undoFileTemplate({ dispatch, commit, rootGetters }); + + expect(commit).toHaveBeenCalledWith('SET_UPDATE_SUCCESS', false); + }); + }); +}); diff --git a/spec/javascripts/ide/stores/modules/file_templates/getters_spec.js b/spec/javascripts/ide/stores/modules/file_templates/getters_spec.js new file mode 100644 index 00000000000..e337c3f331b --- /dev/null +++ b/spec/javascripts/ide/stores/modules/file_templates/getters_spec.js @@ -0,0 +1,30 @@ +import * as getters from '~/ide/stores/modules/file_templates/getters'; + +describe('IDE file templates getters', () => { + describe('templateTypes', () => { + it('returns list of template types', () => { + expect(getters.templateTypes().length).toBe(4); + }); + }); + + describe('showFileTemplatesBar', () => { + it('finds template type by name', () => { + expect( + getters.showFileTemplatesBar(null, { + templateTypes: getters.templateTypes(), + })('LICENSE'), + ).toEqual({ + name: 'LICENSE', + key: 'licenses', + }); + }); + + it('returns undefined if not found', () => { + expect( + getters.showFileTemplatesBar(null, { + templateTypes: getters.templateTypes(), + })('test'), + ).toBe(undefined); + }); + }); +}); diff --git a/spec/javascripts/ide/stores/modules/file_templates/mutations_spec.js b/spec/javascripts/ide/stores/modules/file_templates/mutations_spec.js new file mode 100644 index 00000000000..a51527d699f --- /dev/null +++ b/spec/javascripts/ide/stores/modules/file_templates/mutations_spec.js @@ -0,0 +1,61 @@ +import createState from '~/ide/stores/modules/file_templates/state'; +import * as types from '~/ide/stores/modules/file_templates/mutation_types'; +import mutations from '~/ide/stores/modules/file_templates/mutations'; + +describe('IDE file templates mutations', () => { + let state; + + beforeEach(() => { + state = createState(); + }); + + describe(types.REQUEST_TEMPLATE_TYPES, () => { + it('sets isLoading', () => { + mutations[types.REQUEST_TEMPLATE_TYPES](state); + + expect(state.isLoading).toBe(true); + }); + }); + + describe(types.RECEIVE_TEMPLATE_TYPES_ERROR, () => { + it('sets isLoading', () => { + state.isLoading = true; + + mutations[types.RECEIVE_TEMPLATE_TYPES_ERROR](state); + + expect(state.isLoading).toBe(false); + }); + }); + + describe(types.RECEIVE_TEMPLATE_TYPES_SUCCESS, () => { + it('sets isLoading to false', () => { + state.isLoading = true; + + mutations[types.RECEIVE_TEMPLATE_TYPES_SUCCESS](state, []); + + expect(state.isLoading).toBe(false); + }); + + it('sets templates', () => { + mutations[types.RECEIVE_TEMPLATE_TYPES_SUCCESS](state, ['test']); + + expect(state.templates).toEqual(['test']); + }); + }); + + describe(types.SET_SELECTED_TEMPLATE_TYPE, () => { + it('sets selectedTemplateType', () => { + mutations[types.SET_SELECTED_TEMPLATE_TYPE](state, 'type'); + + expect(state.selectedTemplateType).toBe('type'); + }); + }); + + describe(types.SET_UPDATE_SUCCESS, () => { + it('sets updateSuccess', () => { + mutations[types.SET_UPDATE_SUCCESS](state, true); + + expect(state.updateSuccess).toBe(true); + }); + }); +}); diff --git a/spec/javascripts/jobs/artifacts_block_spec.js b/spec/javascripts/jobs/components/artifacts_block_spec.js index c544c6f3e89..a06d287b3fa 100644 --- a/spec/javascripts/jobs/artifacts_block_spec.js +++ b/spec/javascripts/jobs/components/artifacts_block_spec.js @@ -1,7 +1,7 @@ import Vue from 'vue'; import { getTimeago } from '~/lib/utils/datetime_utility'; import component from '~/jobs/components/artifacts_block.vue'; -import mountComponent from '../helpers/vue_mount_component_helper'; +import mountComponent from '../../helpers/vue_mount_component_helper'; describe('Artifacts block', () => { const Component = Vue.extend(component); diff --git a/spec/javascripts/jobs/commit_block_spec.js b/spec/javascripts/jobs/components/commit_block_spec.js index f755a5042b5..e21fa9c2874 100644 --- a/spec/javascripts/jobs/commit_block_spec.js +++ b/spec/javascripts/jobs/components/commit_block_spec.js @@ -1,6 +1,6 @@ import Vue from 'vue'; import component from '~/jobs/components/commit_block.vue'; -import mountComponent from '../helpers/vue_mount_component_helper'; +import mountComponent from '../../helpers/vue_mount_component_helper'; describe('Commit block', () => { const Component = Vue.extend(component); diff --git a/spec/javascripts/jobs/empty_state_spec.js b/spec/javascripts/jobs/components/empty_state_spec.js index f8feb069fe0..dcc2b3d8a20 100644 --- a/spec/javascripts/jobs/empty_state_spec.js +++ b/spec/javascripts/jobs/components/empty_state_spec.js @@ -1,6 +1,6 @@ import Vue from 'vue'; import component from '~/jobs/components/empty_state.vue'; -import mountComponent from '../helpers/vue_mount_component_helper'; +import mountComponent from '../../helpers/vue_mount_component_helper'; describe('Empty State', () => { const Component = Vue.extend(component); diff --git a/spec/javascripts/jobs/erased_block_spec.js b/spec/javascripts/jobs/components/erased_block_spec.js index 7cf32e984a2..a4ae0c7c81e 100644 --- a/spec/javascripts/jobs/erased_block_spec.js +++ b/spec/javascripts/jobs/components/erased_block_spec.js @@ -1,7 +1,7 @@ import Vue from 'vue'; import { getTimeago } from '~/lib/utils/datetime_utility'; import component from '~/jobs/components/erased_block.vue'; -import mountComponent from '../helpers/vue_mount_component_helper'; +import mountComponent from '../../helpers/vue_mount_component_helper'; describe('Erased block', () => { const Component = Vue.extend(component); diff --git a/spec/javascripts/jobs/header_spec.js b/spec/javascripts/jobs/components/header_spec.js index e21e2c6d6e3..e21e2c6d6e3 100644 --- a/spec/javascripts/jobs/header_spec.js +++ b/spec/javascripts/jobs/components/header_spec.js diff --git a/spec/javascripts/jobs/job_details_mediator_spec.js b/spec/javascripts/jobs/components/job_details_mediator_spec.js index ca5c9cf87e4..3e2fb7bfbbb 100644 --- a/spec/javascripts/jobs/job_details_mediator_spec.js +++ b/spec/javascripts/jobs/components/job_details_mediator_spec.js @@ -1,7 +1,7 @@ import MockAdapter from 'axios-mock-adapter'; import axios from '~/lib/utils/axios_utils'; import JobMediator from '~/jobs/job_details_mediator'; -import job from './mock_data'; +import job from '../mock_data'; describe('JobMediator', () => { let mediator; diff --git a/spec/javascripts/jobs/job_log_spec.js b/spec/javascripts/jobs/components/job_log_spec.js index 406f1c4ccc5..6a5b375a26c 100644 --- a/spec/javascripts/jobs/job_log_spec.js +++ b/spec/javascripts/jobs/components/job_log_spec.js @@ -1,6 +1,6 @@ import Vue from 'vue'; import component from '~/jobs/components/job_log.vue'; -import mountComponent from '../helpers/vue_mount_component_helper'; +import mountComponent from '../../helpers/vue_mount_component_helper'; describe('Job Log', () => { const Component = Vue.extend(component); diff --git a/spec/javascripts/jobs/job_store_spec.js b/spec/javascripts/jobs/components/job_store_spec.js index d00faf29d1e..0dad5111b32 100644 --- a/spec/javascripts/jobs/job_store_spec.js +++ b/spec/javascripts/jobs/components/job_store_spec.js @@ -1,5 +1,5 @@ import JobStore from '~/jobs/stores/job_store'; -import job from './mock_data'; +import job from '../mock_data'; describe('Job Store', () => { let store; diff --git a/spec/javascripts/jobs/jobs_container_spec.js b/spec/javascripts/jobs/components/jobs_container_spec.js index bf52e65cbc8..f3f8ff0d031 100644 --- a/spec/javascripts/jobs/jobs_container_spec.js +++ b/spec/javascripts/jobs/components/jobs_container_spec.js @@ -1,6 +1,6 @@ import Vue from 'vue'; import component from '~/jobs/components/jobs_container.vue'; -import mountComponent from '../helpers/vue_mount_component_helper'; +import mountComponent from '../../helpers/vue_mount_component_helper'; describe('Artifacts block', () => { const Component = Vue.extend(component); diff --git a/spec/javascripts/jobs/sidebar_detail_row_spec.js b/spec/javascripts/jobs/components/sidebar_detail_row_spec.js index e6bfb0c4adc..e6bfb0c4adc 100644 --- a/spec/javascripts/jobs/sidebar_detail_row_spec.js +++ b/spec/javascripts/jobs/components/sidebar_detail_row_spec.js diff --git a/spec/javascripts/jobs/sidebar_details_block_spec.js b/spec/javascripts/jobs/components/sidebar_details_block_spec.js index 21ef5650b80..ba19534dac2 100644 --- a/spec/javascripts/jobs/sidebar_details_block_spec.js +++ b/spec/javascripts/jobs/components/sidebar_details_block_spec.js @@ -1,7 +1,7 @@ import Vue from 'vue'; import sidebarDetailsBlock from '~/jobs/components/sidebar_details_block.vue'; -import job from './mock_data'; -import mountComponent from '../helpers/vue_mount_component_helper'; +import job from '../mock_data'; +import mountComponent from '../../helpers/vue_mount_component_helper'; describe('Sidebar details block', () => { let SidebarComponent; diff --git a/spec/javascripts/jobs/stages_dropdown_spec.js b/spec/javascripts/jobs/components/stages_dropdown_spec.js index d3a5d48f56c..402289345aa 100644 --- a/spec/javascripts/jobs/stages_dropdown_spec.js +++ b/spec/javascripts/jobs/components/stages_dropdown_spec.js @@ -1,6 +1,6 @@ import Vue from 'vue'; import component from '~/jobs/components/stages_dropdown.vue'; -import mountComponent from '../helpers/vue_mount_component_helper'; +import mountComponent from '../../helpers/vue_mount_component_helper'; describe('Artifacts block', () => { const Component = Vue.extend(component); diff --git a/spec/javascripts/jobs/stuck_block_spec.js b/spec/javascripts/jobs/components/stuck_block_spec.js index 4e2108dfdfb..c320793b2be 100644 --- a/spec/javascripts/jobs/stuck_block_spec.js +++ b/spec/javascripts/jobs/components/stuck_block_spec.js @@ -1,6 +1,6 @@ import Vue from 'vue'; import component from '~/jobs/components/stuck_block.vue'; -import mountComponent from '../helpers/vue_mount_component_helper'; +import mountComponent from '../../helpers/vue_mount_component_helper'; describe('Stuck Block Job component', () => { const Component = Vue.extend(component); diff --git a/spec/javascripts/jobs/trigger_value_spec.js b/spec/javascripts/jobs/components/trigger_value_spec.js index acf91510ed2..3d41a3cfac1 100644 --- a/spec/javascripts/jobs/trigger_value_spec.js +++ b/spec/javascripts/jobs/components/trigger_value_spec.js @@ -1,6 +1,6 @@ import Vue from 'vue'; import component from '~/jobs/components/trigger_block.vue'; -import mountComponent from '../helpers/vue_mount_component_helper'; +import mountComponent from '../../helpers/vue_mount_component_helper'; describe('Trigger block', () => { const Component = Vue.extend(component); diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js index 8ac2f26979b..0e42537faed 100644 --- a/spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js +++ b/spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js @@ -45,7 +45,7 @@ describe('MRWidgetHeader', () => { }); }); - describe('commitsText', () => { + describe('commitsBehindText', () => { it('returns singular when there is one commit', () => { vm = mountComponent(Component, { mr: { @@ -53,11 +53,12 @@ describe('MRWidgetHeader', () => { sourceBranch: 'mr-widget-refactor', sourceBranchLink: '<a href="/foo/bar/mr-widget-refactor">Link</a>', targetBranch: 'master', + targetBranchPath: '/foo/bar/master', statusPath: 'abc', }, }); - expect(vm.commitsText).toEqual('1 commit behind'); + expect(vm.commitsBehindText).toEqual('The source branch is <a href="/foo/bar/master">1 commit behind</a> the target branch'); }); it('returns plural when there is more than one commit', () => { @@ -67,11 +68,12 @@ describe('MRWidgetHeader', () => { sourceBranch: 'mr-widget-refactor', sourceBranchLink: '<a href="/foo/bar/mr-widget-refactor">Link</a>', targetBranch: 'master', + targetBranchPath: '/foo/bar/master', statusPath: 'abc', }, }); - expect(vm.commitsText).toEqual('2 commits behind'); + expect(vm.commitsBehindText).toEqual('The source branch is <a href="/foo/bar/master">2 commits behind</a> the target branch'); }); }); }); @@ -280,9 +282,9 @@ describe('MRWidgetHeader', () => { }); it('renders diverged commits info', () => { - expect(vm.$el.querySelector('.diverged-commits-count').textContent).toMatch( - /(mr-widget-refactor[\s\S]+?is 12 commits behind[\s\S]+?master)/, - ); + expect(vm.$el.querySelector('.diverged-commits-count').textContent).toEqual('The source branch is 12 commits behind the target branch'); + expect(vm.$el.querySelector('.diverged-commits-count a').textContent).toEqual('12 commits behind'); + expect(vm.$el.querySelector('.diverged-commits-count a')).toHaveAttr('href', vm.mr.targetBranchPath); }); }); }); diff --git a/spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js b/spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js index 076d940961d..f1fe2e996fc 100644 --- a/spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js +++ b/spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js @@ -44,7 +44,11 @@ describe('StackedProgressBarComponent', () => { }); it('returns percentage with decimal place from provided count based on `totalCount`', () => { - expect(vm.getPercent(10)).toBe(0.2); + expect(vm.getPercent(67)).toBe(1.3); + }); + + it('returns percentage as `< 1` from provided count based on `totalCount` when evaluated value is less than 1', () => { + expect(vm.getPercent(10)).toBe('< 1'); }); }); diff --git a/spec/javascripts/vue_shared/components/tooltip_on_truncate_spec.js b/spec/javascripts/vue_shared/components/tooltip_on_truncate_spec.js new file mode 100644 index 00000000000..8465757deb6 --- /dev/null +++ b/spec/javascripts/vue_shared/components/tooltip_on_truncate_spec.js @@ -0,0 +1,162 @@ +import { mountComponentWithRender } from 'spec/helpers/vue_mount_component_helper'; +import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue'; + +const TEST_TITLE = 'lorem-ipsum-dolar-sit-amit-consectur-adipiscing-elit-sed-do'; +const CLASS_SHOW_TOOLTIP = 'js-show-tooltip'; +const STYLE_TRUNCATED = { + display: 'inline-block', + 'max-width': '20px', +}; +const STYLE_NORMAL = { + display: 'inline-block', + 'max-width': '1000px', +}; + +function mountTooltipOnTruncate(options, createChildren) { + return mountComponentWithRender(h => h(TooltipOnTruncate, options, createChildren(h)), '#app'); +} + +describe('TooltipOnTruncate component', () => { + let vm; + + beforeEach(() => { + const el = document.createElement('div'); + el.id = 'app'; + document.body.appendChild(el); + }); + + afterEach(() => { + vm.$destroy(); + }); + + describe('with default target', () => { + it('renders tooltip if truncated', done => { + const options = { + style: STYLE_TRUNCATED, + props: { + title: TEST_TITLE, + }, + }; + + vm = mountTooltipOnTruncate(options, () => [TEST_TITLE]); + + vm.$nextTick() + .then(() => { + expect(vm.$el).toHaveClass(CLASS_SHOW_TOOLTIP); + expect(vm.$el).toHaveData('original-title', TEST_TITLE); + expect(vm.$el).toHaveData('placement', 'top'); + }) + .then(done) + .catch(done.fail); + }); + + it('does not render tooltip if normal', done => { + const options = { + style: STYLE_NORMAL, + props: { + title: TEST_TITLE, + }, + }; + + vm = mountTooltipOnTruncate(options, () => [TEST_TITLE]); + + vm.$nextTick() + .then(() => { + expect(vm.$el).not.toHaveClass(CLASS_SHOW_TOOLTIP); + }) + .then(done) + .catch(done.fail); + }); + }); + + describe('with child target', () => { + it('renders tooltip if truncated', done => { + const options = { + style: STYLE_NORMAL, + props: { + title: TEST_TITLE, + truncateTarget: 'child', + }, + }; + + vm = mountTooltipOnTruncate(options, (h) => [ + h('a', { style: STYLE_TRUNCATED }, TEST_TITLE), + ]); + + vm.$nextTick() + .then(() => { + expect(vm.$el).toHaveClass(CLASS_SHOW_TOOLTIP); + }) + .then(done) + .catch(done.fail); + }); + + it('does not render tooltip if normal', done => { + const options = { + props: { + title: TEST_TITLE, + truncateTarget: 'child', + }, + }; + + vm = mountTooltipOnTruncate(options, (h) => [ + h('a', { style: STYLE_NORMAL }, TEST_TITLE), + ]); + + vm.$nextTick() + .then(() => { + expect(vm.$el).not.toHaveClass(CLASS_SHOW_TOOLTIP); + }) + .then(done) + .catch(done.fail); + }); + }); + + describe('with fn target', () => { + it('renders tooltip if truncated', done => { + const options = { + style: STYLE_NORMAL, + props: { + title: TEST_TITLE, + truncateTarget: (el) => el.childNodes[1], + }, + }; + + vm = mountTooltipOnTruncate(options, (h) => [ + h('a', { style: STYLE_NORMAL }, TEST_TITLE), + h('span', { style: STYLE_TRUNCATED }, TEST_TITLE), + ]); + + vm.$nextTick() + .then(() => { + expect(vm.$el).toHaveClass(CLASS_SHOW_TOOLTIP); + }) + .then(done) + .catch(done.fail); + }); + }); + + describe('placement', () => { + it('sets data-placement when tooltip is rendered', done => { + const options = { + props: { + title: TEST_TITLE, + truncateTarget: 'child', + placement: 'bottom', + }, + }; + + vm = mountTooltipOnTruncate(options, (h) => [ + h('a', { style: STYLE_TRUNCATED }, TEST_TITLE), + ]); + + vm.$nextTick() + .then(() => { + expect(vm.$el).toHaveClass(CLASS_SHOW_TOOLTIP); + expect(vm.$el).toHaveData('placement', options.props.placement); + }) + .then(done) + .catch(done.fail); + }); + }); +}); diff --git a/spec/lib/feature_spec.rb b/spec/lib/feature_spec.rb index f313e675654..8bb5a843484 100644 --- a/spec/lib/feature_spec.rb +++ b/spec/lib/feature_spec.rb @@ -1,6 +1,13 @@ require 'spec_helper' describe Feature do + before do + # We mock all calls to .enabled? to return true in order to force all + # specs to run the feature flag gated behavior, but here we need a clean + # behavior from the class + allow(described_class).to receive(:enabled?).and_call_original + end + describe '.get' do let(:feature) { double(:feature) } let(:key) { 'my_feature' } @@ -106,4 +113,63 @@ describe Feature do it_behaves_like 'a memoized Flipper instance' end end + + describe '.enabled?' do + it 'returns false for undefined feature' do + expect(described_class.enabled?(:some_random_feature_flag)).to be_falsey + end + + it 'returns false for existing disabled feature in the database' do + described_class.disable(:disabled_feature_flag) + + expect(described_class.enabled?(:disabled_feature_flag)).to be_falsey + end + + it 'returns true for existing enabled feature in the database' do + described_class.enable(:enabled_feature_flag) + + expect(described_class.enabled?(:enabled_feature_flag)).to be_truthy + end + + context 'with an individual actor' do + CustomActor = Struct.new(:flipper_id) + + let(:actor) { CustomActor.new(flipper_id: 'CustomActor:5') } + let(:another_actor) { CustomActor.new(flipper_id: 'CustomActor:10') } + + before do + described_class.enable(:enabled_feature_flag, actor) + end + + it 'returns true when same actor is informed' do + expect(described_class.enabled?(:enabled_feature_flag, actor)).to be_truthy + end + + it 'returns false when different actor is informed' do + expect(described_class.enabled?(:enabled_feature_flag, another_actor)).to be_falsey + end + + it 'returns false when no actor is informed' do + expect(described_class.enabled?(:enabled_feature_flag)).to be_falsey + end + end + end + + describe '.disable?' do + it 'returns true for undefined feature' do + expect(described_class.disabled?(:some_random_feature_flag)).to be_truthy + end + + it 'returns true for existing disabled feature in the database' do + described_class.disable(:disabled_feature_flag) + + expect(described_class.disabled?(:disabled_feature_flag)).to be_truthy + end + + it 'returns false for existing enabled feature in the database' do + described_class.enable(:enabled_feature_flag) + + expect(described_class.disabled?(:enabled_feature_flag)).to be_falsey + end + end end diff --git a/spec/lib/gitlab/auth/ldap/access_spec.rb b/spec/lib/gitlab/auth/ldap/access_spec.rb index eff21985108..7800c543cdb 100644 --- a/spec/lib/gitlab/auth/ldap/access_spec.rb +++ b/spec/lib/gitlab/auth/ldap/access_spec.rb @@ -3,51 +3,61 @@ require 'spec_helper' describe Gitlab::Auth::LDAP::Access do include LdapHelpers - let(:access) { described_class.new user } let(:user) { create(:omniauth_user) } + subject(:access) { described_class.new(user) } + describe '.allowed?' do - it 'updates the users `last_credential_check_at' do + before do allow(access).to receive(:update_user) - expect(access).to receive(:allowed?) { true } - expect(described_class).to receive(:open).and_yield(access) + allow(access).to receive(:allowed?).and_return(true) + allow(described_class).to receive(:open).and_yield(access) + end + it "updates the user's `last_credential_check_at`" do expect { described_class.allowed?(user) } .to change { user.last_credential_check_at } end - end - describe '#find_ldap_user' do - it 'finds a user by dn first' do - expect(Gitlab::Auth::LDAP::Person).to receive(:find_by_dn).and_return(:ldap_user) + it "does not update user's `last_credential_check_at` when in a read-only GitLab instance" do + allow(Gitlab::Database).to receive(:read_only?).and_return(true) - access.find_ldap_user + expect { described_class.allowed?(user) } + .not_to change { user.last_credential_check_at } end end describe '#allowed?' do - subject { access.allowed? } - context 'when the user cannot be found' do before do - allow(Gitlab::Auth::LDAP::Person).to receive(:find_by_dn).and_return(nil) - allow(Gitlab::Auth::LDAP::Person).to receive(:find_by_email).and_return(nil) + stub_ldap_person_find_by_dn(nil) + stub_ldap_person_find_by_email(user.email, nil) end - it { is_expected.to be_falsey } + it 'returns false' do + expect(access.allowed?).to be_falsey + end it 'blocks user in GitLab' do - expect(access).to receive(:block_user).with(user, 'does not exist anymore') + access.allowed? + + expect(user).to be_blocked + expect(user).to be_ldap_blocked + end + + it 'logs the reason' do + expect(Gitlab::AppLogger).to receive(:info).with( + "LDAP account \"123456\" does not exist anymore, " \ + "blocking Gitlab user \"#{user.name}\" (#{user.email})" + ) access.allowed? end end context 'when the user is found' do - let(:ldap_user) { Gitlab::Auth::LDAP::Person.new(Net::LDAP::Entry.new, 'ldapmain') } - before do - allow(Gitlab::Auth::LDAP::Person).to receive(:find_by_dn).and_return(ldap_user) + stub_ldap_person_find_by_dn(Net::LDAP::Entry.new) end context 'and the user is disabled via active directory' do @@ -55,10 +65,22 @@ describe Gitlab::Auth::LDAP::Access do allow(Gitlab::Auth::LDAP::Person).to receive(:disabled_via_active_directory?).and_return(true) end - it { is_expected.to be_falsey } + it 'returns false' do + expect(access.allowed?).to be_falsey + end it 'blocks user in GitLab' do - expect(access).to receive(:block_user).with(user, 'is disabled in Active Directory') + access.allowed? + + expect(user).to be_blocked + expect(user).to be_ldap_blocked + end + + it 'logs the reason' do + expect(Gitlab::AppLogger).to receive(:info).with( + "LDAP account \"123456\" is disabled in Active Directory, " \ + "blocking Gitlab user \"#{user.name}\" (#{user.email})" + ) access.allowed? end @@ -92,7 +114,17 @@ describe Gitlab::Auth::LDAP::Access do end it 'unblocks user in GitLab' do - expect(access).to receive(:unblock_user).with(user, 'is not disabled anymore') + access.allowed? + + expect(user).not_to be_blocked + expect(user).not_to be_ldap_blocked + end + + it 'logs the reason' do + expect(Gitlab::AppLogger).to receive(:info).with( + "LDAP account \"123456\" is not disabled anymore, " \ + "unblocking Gitlab user \"#{user.name}\" (#{user.email})" + ) access.allowed? end @@ -105,18 +137,32 @@ describe Gitlab::Auth::LDAP::Access do allow_any_instance_of(Gitlab::Auth::LDAP::Config).to receive(:active_directory).and_return(false) end - it { is_expected.to be_truthy } + it 'returns true' do + expect(access.allowed?).to be_truthy + end context 'when user cannot be found' do before do - allow(Gitlab::Auth::LDAP::Person).to receive(:find_by_dn).and_return(nil) - allow(Gitlab::Auth::LDAP::Person).to receive(:find_by_email).and_return(nil) + stub_ldap_person_find_by_dn(nil) + stub_ldap_person_find_by_email(user.email, nil) end - it { is_expected.to be_falsey } + it 'returns false' do + expect(access.allowed?).to be_falsey + end it 'blocks user in GitLab' do - expect(access).to receive(:block_user).with(user, 'does not exist anymore') + access.allowed? + + expect(user).to be_blocked + expect(user).to be_ldap_blocked + end + + it 'logs the reason' do + expect(Gitlab::AppLogger).to receive(:info).with( + "LDAP account \"123456\" does not exist anymore, " \ + "blocking Gitlab user \"#{user.name}\" (#{user.email})" + ) access.allowed? end @@ -128,7 +174,17 @@ describe Gitlab::Auth::LDAP::Access do end it 'unblocks the user if it exists' do - expect(access).to receive(:unblock_user).with(user, 'is available again') + access.allowed? + + expect(user).not_to be_blocked + expect(user).not_to be_ldap_blocked + end + + it 'logs the reason' do + expect(Gitlab::AppLogger).to receive(:info).with( + "LDAP account \"123456\" is available again, " \ + "unblocking Gitlab user \"#{user.name}\" (#{user.email})" + ) access.allowed? end @@ -152,46 +208,4 @@ describe Gitlab::Auth::LDAP::Access do end end end - - describe '#block_user' do - before do - user.activate - allow(Gitlab::AppLogger).to receive(:info) - - access.block_user user, 'reason' - end - - it 'blocks the user' do - expect(user).to be_blocked - expect(user).to be_ldap_blocked - end - - it 'logs the reason' do - expect(Gitlab::AppLogger).to have_received(:info).with( - "LDAP account \"123456\" reason, " \ - "blocking Gitlab user \"#{user.name}\" (#{user.email})" - ) - end - end - - describe '#unblock_user' do - before do - user.ldap_block - allow(Gitlab::AppLogger).to receive(:info) - - access.unblock_user user, 'reason' - end - - it 'activates the user' do - expect(user).not_to be_blocked - expect(user).not_to be_ldap_blocked - end - - it 'logs the reason' do - Gitlab::AppLogger.info( - "LDAP account \"123456\" reason, " \ - "unblocking Gitlab user \"#{user.name}\" (#{user.email})" - ) - end - end end diff --git a/spec/lib/gitlab/auth/o_auth/provider_spec.rb b/spec/lib/gitlab/auth/o_auth/provider_spec.rb index fc35d430917..80d702cf9dc 100644 --- a/spec/lib/gitlab/auth/o_auth/provider_spec.rb +++ b/spec/lib/gitlab/auth/o_auth/provider_spec.rb @@ -1,6 +1,48 @@ require 'spec_helper' describe Gitlab::Auth::OAuth::Provider do + describe '.enabled?' do + before do + allow(described_class).to receive(:providers).and_return([:ldapmain, :google_oauth2]) + end + + context 'when OmniAuth is disabled' do + before do + allow(Gitlab::Auth).to receive(:omniauth_enabled?).and_return(false) + end + + it 'allows database auth' do + expect(described_class.enabled?('database')).to be_truthy + end + + it 'allows LDAP auth' do + expect(described_class.enabled?('ldapmain')).to be_truthy + end + + it 'does not allow other OmniAuth providers' do + expect(described_class.enabled?('google_oauth2')).to be_falsey + end + end + + context 'when OmniAuth is enabled' do + before do + allow(Gitlab::Auth).to receive(:omniauth_enabled?).and_return(true) + end + + it 'allows database auth' do + expect(described_class.enabled?('database')).to be_truthy + end + + it 'allows LDAP auth' do + expect(described_class.enabled?('ldapmain')).to be_truthy + end + + it 'allows other OmniAuth providers' do + expect(described_class.enabled?('google_oauth2')).to be_truthy + end + end + end + describe '#config_for' do context 'for an LDAP provider' do context 'when the provider exists' do diff --git a/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb b/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb index 3f7a12144d5..65a2e1cb5cb 100644 --- a/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb @@ -92,7 +92,7 @@ describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redis_cach .with(issue) .and_return([user.id, true]) - expect(Gitlab::GithubImport) + expect(importer) .to receive(:insert_and_return_id) .with( { @@ -121,7 +121,7 @@ describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redis_cach .with(issue) .and_return([project.creator_id, false]) - expect(Gitlab::GithubImport) + expect(importer) .to receive(:insert_and_return_id) .with( { @@ -150,7 +150,7 @@ describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redis_cach .with(issue) .and_return([user.id, true]) - expect(Gitlab::GithubImport) + expect(importer) .to receive(:insert_and_return_id) .and_raise(ActiveRecord::InvalidForeignKey, 'invalid foreign key') @@ -185,7 +185,7 @@ describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redis_cach .and_return([user.id, true]) issue = build_stubbed(:issue, project: project) - allow(Gitlab::GithubImport) + allow(importer) .to receive(:insert_and_return_id) .and_return(issue.id) allow(project.issues).to receive(:find).with(issue.id).and_return(issue) diff --git a/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb index 44c920043b4..25684ea9e2c 100644 --- a/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb @@ -80,7 +80,7 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi end it 'imports the pull request with the pull request author as the merge request author' do - expect(Gitlab::GithubImport) + expect(importer) .to receive(:insert_and_return_id) .with( { @@ -114,7 +114,7 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi it 'triggers internal_id functionality to track greatest iids' do mr = build_stubbed(:merge_request, source_project: project, target_project: project) - allow(Gitlab::GithubImport).to receive(:insert_and_return_id).and_return(mr.id) + allow(importer).to receive(:insert_and_return_id).and_return(mr.id) allow(project.merge_requests).to receive(:find).with(mr.id).and_return(mr) expect(mr).to receive(:ensure_target_project_iid!) @@ -135,7 +135,7 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi .with(pull_request) .and_return(user.id) - expect(Gitlab::GithubImport) + expect(importer) .to receive(:insert_and_return_id) .with( { @@ -181,7 +181,7 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi .to receive(:source_branch) .and_return('master') - expect(Gitlab::GithubImport) + expect(importer) .to receive(:insert_and_return_id) .with( { @@ -219,7 +219,7 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi .with(pull_request) .and_return(user.id) - expect(Gitlab::GithubImport) + expect(importer) .to receive(:insert_and_return_id) .and_raise(ActiveRecord::InvalidForeignKey, 'invalid foreign key') diff --git a/spec/lib/gitlab/github_import_spec.rb b/spec/lib/gitlab/github_import_spec.rb index 51414800e8c..496244c91bf 100644 --- a/spec/lib/gitlab/github_import_spec.rb +++ b/spec/lib/gitlab/github_import_spec.rb @@ -27,39 +27,6 @@ describe Gitlab::GithubImport do end end - describe '.insert_and_return_id' do - let(:attributes) { { iid: 1, title: 'foo' } } - let(:project) { create(:project) } - - context 'on PostgreSQL' do - it 'returns the ID returned by the query' do - expect(Gitlab::Database) - .to receive(:bulk_insert) - .with(Issue.table_name, [attributes], return_ids: true) - .and_return([10]) - - id = described_class.insert_and_return_id(attributes, project.issues) - - expect(id).to eq(10) - end - end - - context 'on MySQL' do - it 'uses a separate query to retrieve the ID' do - issue = create(:issue, project: project, iid: attributes[:iid]) - - expect(Gitlab::Database) - .to receive(:bulk_insert) - .with(Issue.table_name, [attributes], return_ids: true) - .and_return([]) - - id = described_class.insert_and_return_id(attributes, project.issues) - - expect(id).to eq(issue.id) - end - end - end - describe '.ghost_user_id', :clean_gitlab_redis_cache do it 'returns the ID of the ghost user' do expect(described_class.ghost_user_id).to eq(User.ghost.id) diff --git a/spec/lib/gitlab/import/database_helpers_spec.rb b/spec/lib/gitlab/import/database_helpers_spec.rb new file mode 100644 index 00000000000..e716155b7d5 --- /dev/null +++ b/spec/lib/gitlab/import/database_helpers_spec.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::Import::DatabaseHelpers do + let(:database_helper) do + Class.new do + include Gitlab::Import::DatabaseHelpers + end + end + + subject { database_helper.new } + + describe '.insert_and_return_id' do + let(:attributes) { { iid: 1, title: 'foo' } } + let(:project) { create(:project) } + + context 'on PostgreSQL' do + it 'returns the ID returned by the query' do + expect(Gitlab::Database) + .to receive(:bulk_insert) + .with(Issue.table_name, [attributes], return_ids: true) + .and_return([10]) + + id = subject.insert_and_return_id(attributes, project.issues) + + expect(id).to eq(10) + end + end + + context 'on MySQL' do + it 'uses a separate query to retrieve the ID' do + issue = create(:issue, project: project, iid: attributes[:iid]) + + expect(Gitlab::Database) + .to receive(:bulk_insert) + .with(Issue.table_name, [attributes], return_ids: true) + .and_return([]) + + id = subject.insert_and_return_id(attributes, project.issues) + + expect(id).to eq(issue.id) + end + end + end +end diff --git a/spec/lib/gitlab/import/merge_request_creator_spec.rb b/spec/lib/gitlab/import/merge_request_creator_spec.rb new file mode 100644 index 00000000000..cd3359da341 --- /dev/null +++ b/spec/lib/gitlab/import/merge_request_creator_spec.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::Import::MergeRequestCreator do + let(:project) { create(:project, :repository) } + + subject { described_class.new(project) } + + describe '#execute' do + context 'merge request already exists' do + let(:merge_request) { create(:merge_request, target_project: project, source_project: project) } + let(:commits) { merge_request.merge_request_diffs.first.commits } + let(:attributes) { HashWithIndifferentAccess.new(merge_request.attributes) } + + it 'updates the data' do + commits_count = commits.count + merge_request.merge_request_diffs.destroy_all # rubocop: disable DestroyAll + + expect(merge_request.merge_request_diffs.count).to eq(0) + + subject.execute(attributes) + + expect(merge_request.reload.merge_request_diffs.count).to eq(1) + expect(merge_request.reload.merge_request_diffs.first.commits.count).to eq(commits_count) + end + end + + context 'new merge request' do + let(:merge_request) { build(:merge_request, target_project: project, source_project: project) } + let(:attributes) { HashWithIndifferentAccess.new(merge_request.attributes) } + + it 'creates a new merge request' do + attributes.delete(:id) + + expect { subject.execute(attributes) }.to change { MergeRequest.count }.by(1) + + new_mr = MergeRequest.last + expect(new_mr.merge_request_diffs.count).to eq(1) + end + end + end +end diff --git a/spec/lib/gitlab/middleware/multipart_spec.rb b/spec/lib/gitlab/middleware/multipart_spec.rb index f788f8ee276..daf454665b0 100644 --- a/spec/lib/gitlab/middleware/multipart_spec.rb +++ b/spec/lib/gitlab/middleware/multipart_spec.rb @@ -75,6 +75,26 @@ describe Gitlab::Middleware::Multipart do it_behaves_like 'multipart upload files' end + it 'allows files in uploads/tmp directory' do + Dir.mktmpdir do |dir| + uploads_dir = File.join(dir, 'public/uploads/tmp') + FileUtils.mkdir_p(uploads_dir) + + allow(Rails).to receive(:root).and_return(dir) + allow(Dir).to receive(:tmpdir).and_return(File.join(Dir.tmpdir, 'tmpsubdir')) + + Tempfile.open('top-level', uploads_dir) do |tempfile| + env = post_env({ 'file' => tempfile.path }, { 'file.name' => original_filename, 'file.path' => tempfile.path }, Gitlab::Workhorse.secret, 'gitlab-workhorse') + + expect(app).to receive(:call) do |env| + expect(Rack::Request.new(env).params['file']).to be_a(::UploadedFile) + end + + middleware.call(env) + end + end + end + it 'allows symlinks for uploads dir' do Tempfile.open('two-levels') do |tempfile| symlinked_dir = '/some/dir/uploads' diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb index a19b3c0ba66..de6dd2a9fea 100644 --- a/spec/lib/gitlab/usage_data_spec.rb +++ b/spec/lib/gitlab/usage_data_spec.rb @@ -56,6 +56,7 @@ describe Gitlab::UsageData do expect(count_data[:projects]).to eq(3) expect(count_data.keys).to match_array(%i( + assignee_lists boards ci_builds ci_internal_pipelines @@ -83,9 +84,11 @@ describe Gitlab::UsageData do groups issues keys + label_lists labels lfs_objects merge_requests + milestone_lists milestones notes projects diff --git a/spec/migrations/drop_duplicate_protected_tags_spec.rb b/spec/migrations/drop_duplicate_protected_tags_spec.rb new file mode 100644 index 00000000000..acfb6850722 --- /dev/null +++ b/spec/migrations/drop_duplicate_protected_tags_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' +require Rails.root.join('db', 'migrate', '20180711103851_drop_duplicate_protected_tags.rb') + +describe DropDuplicateProtectedTags, :migration do + let(:namespaces) { table(:namespaces) } + let(:projects) { table(:projects) } + let(:protected_tags) { table(:protected_tags) } + + before do + stub_const("#{described_class}::BATCH_SIZE", 2) + + namespaces.create(id: 1, name: 'gitlab-org', path: 'gitlab-org') + projects.create!(id: 1, namespace_id: 1, name: 'gitlab1', path: 'gitlab1') + projects.create!(id: 2, namespace_id: 1, name: 'gitlab2', path: 'gitlab2') + end + + it 'removes duplicated protected tags' do + protected_tags.create!(id: 1, project_id: 1, name: 'foo') + tag2 = protected_tags.create!(id: 2, project_id: 1, name: 'foo1') + protected_tags.create!(id: 3, project_id: 1, name: 'foo') + tag4 = protected_tags.create!(id: 4, project_id: 1, name: 'foo') + tag5 = protected_tags.create!(id: 5, project_id: 2, name: 'foo') + + migrate! + + expect(protected_tags.all.count).to eq 3 + expect(protected_tags.all.pluck(:id)).to contain_exactly(tag2.id, tag4.id, tag5.id) + end + + it 'does not remove unique protected tags' do + tag1 = protected_tags.create!(id: 1, project_id: 1, name: 'foo1') + tag2 = protected_tags.create!(id: 2, project_id: 1, name: 'foo2') + tag3 = protected_tags.create!(id: 3, project_id: 1, name: 'foo3') + + migrate! + + expect(protected_tags.all.count).to eq 3 + expect(protected_tags.all.pluck(:id)).to contain_exactly(tag1.id, tag2.id, tag3.id) + end +end diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index 5157d8fc645..d5f88e930d4 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -225,6 +225,12 @@ eos end describe 'description' do + it 'returns no_commit_message when safe_message is blank' do + allow(commit).to receive(:safe_message).and_return(nil) + + expect(commit.description).to eq('--no commit message') + end + it 'returns description of commit message if title less than 100 characters' do message = <<eos Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sodales id felis id blandit. diff --git a/spec/models/concerns/awardable_spec.rb b/spec/models/concerns/awardable_spec.rb index a980cff28fb..69083bdc125 100644 --- a/spec/models/concerns/awardable_spec.rb +++ b/spec/models/concerns/awardable_spec.rb @@ -53,21 +53,14 @@ describe Awardable do issue.project.add_guest(user) end - it 'does not allow upvoting or downvoting your own issue' do - issue.update!(author: user) - - expect(issue.user_can_award?(user, AwardEmoji::DOWNVOTE_NAME)).to be_falsy - expect(issue.user_can_award?(user, AwardEmoji::UPVOTE_NAME)).to be_falsy - end - it 'is truthy when the user is allowed to award emoji' do - expect(issue.user_can_award?(user, AwardEmoji::UPVOTE_NAME)).to be_truthy + expect(issue.user_can_award?(user)).to be_truthy end it 'is falsy when the project is archived' do issue.project.update!(archived: true) - expect(issue.user_can_award?(user, AwardEmoji::UPVOTE_NAME)).to be_falsy + expect(issue.user_can_award?(user)).to be_falsy end end diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb index 84edfc3ff00..c21d85fb2a4 100644 --- a/spec/models/issue_spec.rb +++ b/spec/models/issue_spec.rb @@ -188,98 +188,6 @@ describe Issue do end end - describe '#closed_by_merge_requests' do - let(:project) { create(:project, :repository) } - let(:issue) { create(:issue, project: project)} - let(:closed_issue) { build(:issue, :closed, project: project)} - - let(:mr) do - opts = { - title: 'Awesome merge_request', - description: "Fixes #{issue.to_reference}", - source_branch: 'feature', - target_branch: 'master' - } - MergeRequests::CreateService.new(project, project.owner, opts).execute - end - - let(:closed_mr) do - opts = { - title: 'Awesome merge_request 2', - description: "Fixes #{issue.to_reference}", - source_branch: 'feature', - target_branch: 'master', - state: 'closed' - } - MergeRequests::CreateService.new(project, project.owner, opts).execute - end - - it 'returns the merge request to close this issue' do - expect(issue.closed_by_merge_requests(mr.author)).to eq([mr]) - end - - it "returns an empty array when the merge request is closed already" do - expect(issue.closed_by_merge_requests(closed_mr.author)).to eq([]) - end - - it "returns an empty array when the current issue is closed already" do - expect(closed_issue.closed_by_merge_requests(closed_issue.author)).to eq([]) - end - end - - describe '#referenced_merge_requests' do - let(:project) { create(:project, :public) } - let(:issue) do - create(:issue, description: merge_request.to_reference, project: project) - end - let!(:merge_request) do - create(:merge_request, - source_project: project, - source_branch: 'master', - target_branch: 'feature') - end - - it 'returns the referenced merge requests' do - mr2 = create(:merge_request, - source_project: project, - source_branch: 'feature', - target_branch: 'master') - - create(:note_on_issue, - noteable: issue, - note: mr2.to_reference, - project_id: project.id) - - expect(issue.referenced_merge_requests).to eq([merge_request, mr2]) - end - - it 'returns cross project referenced merge requests' do - other_project = create(:project, :public) - cross_project_merge_request = create(:merge_request, source_project: other_project) - create(:note_on_issue, - noteable: issue, - note: cross_project_merge_request.to_reference(issue.project), - project_id: issue.project.id) - - expect(issue.referenced_merge_requests).to eq([merge_request, cross_project_merge_request]) - end - - it 'excludes cross project references if the user cannot read cross project' do - user = create(:user) - allow(Ability).to receive(:allowed?).and_call_original - expect(Ability).to receive(:allowed?).with(user, :read_cross_project) { false } - - other_project = create(:project, :public) - cross_project_merge_request = create(:merge_request, source_project: other_project) - create(:note_on_issue, - noteable: issue, - note: cross_project_merge_request.to_reference(issue.project), - project_id: issue.project.id) - - expect(issue.referenced_merge_requests(user)).to eq([merge_request]) - end - end - describe '#can_move?' do let(:user) { create(:user) } let(:issue) { create(:issue) } @@ -365,7 +273,12 @@ describe Issue do source_project: subject.project, source_branch: "#{subject.iid}-branch" }) merge_request.create_cross_references!(user) - expect(subject.referenced_merge_requests(user)).not_to be_empty + + referenced_merge_requests = Issues::ReferencedMergeRequestsService + .new(subject.project, user) + .referenced_merge_requests(subject) + + expect(referenced_merge_requests).not_to be_empty expect(subject.related_branches(user)).to eq([subject.to_branch_name]) end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 8cb706b54b0..7cfffbde42f 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -2989,6 +2989,7 @@ describe Project do # call. This makes testing a bit easier. allow(project).to receive(:gitlab_shell).and_return(gitlab_shell) allow(project).to receive(:previous_changes).and_return('path' => ['foo']) + stub_feature_flags(skip_hashed_storage_upgrade: false) end it 'renames a repository' do @@ -3160,6 +3161,7 @@ describe Project do # call. This makes testing a bit easier. allow(project).to receive(:gitlab_shell).and_return(gitlab_shell) allow(project).to receive(:previous_changes).and_return('path' => ['foo']) + stub_feature_flags(skip_hashed_storage_upgrade: false) end context 'migration to hashed storage' do diff --git a/spec/models/remote_mirror_spec.rb b/spec/models/remote_mirror_spec.rb index c2ef0435c8e..269d5deca20 100644 --- a/spec/models/remote_mirror_spec.rb +++ b/spec/models/remote_mirror_spec.rb @@ -220,6 +220,18 @@ describe RemoteMirror do end end + context '#ensure_remote!' do + let(:remote_mirror) { create(:project, :repository, :remote_mirror).remote_mirrors.first } + + it 'adds a remote multiple times with no errors' do + expect(remote_mirror.project.repository).to receive(:add_remote).with(remote_mirror.remote_name, remote_mirror.url).twice.and_call_original + + 2.times do + remote_mirror.ensure_remote! + end + end + end + context '#updated_since?' do let(:remote_mirror) { create(:project, :repository, :remote_mirror).remote_mirrors.first } let(:timestamp) { Time.now - 5.minutes } diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 9763477a711..fd99acb3bb2 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -315,6 +315,14 @@ describe User do expect(users_with_two_factor).to eq([user_with_2fa.id]) expect(users_with_two_factor).not_to include(user_without_2fa.id) end + + it 'works with ORDER BY' do + user_with_2fa = create(:user, :two_factor_via_otp, :two_factor_via_u2f) + + expect(described_class + .with_two_factor + .reorder_by_name).to eq([user_with_2fa]) + end end describe ".without_two_factor" do diff --git a/spec/requests/api/award_emoji_spec.rb b/spec/requests/api/award_emoji_spec.rb index 0921fecb933..7f3f3ab0977 100644 --- a/spec/requests/api/award_emoji_spec.rb +++ b/spec/requests/api/award_emoji_spec.rb @@ -167,12 +167,6 @@ describe API::AwardEmoji do expect(response).to have_gitlab_http_status(401) end - it "returns a 404 error if the user authored issue" do - post api("/projects/#{project.id}/issues/#{issue2.id}/award_emoji", user), name: 'thumbsup' - - expect(response).to have_gitlab_http_status(404) - end - it "normalizes +1 as thumbsup award" do post api("/projects/#{project.id}/issues/#{issue.iid}/award_emoji", user), name: '+1' @@ -215,12 +209,6 @@ describe API::AwardEmoji do expect(json_response['user']['username']).to eq(user.username) end - it "it returns 404 error when user authored note" do - post api("/projects/#{project.id}/issues/#{issue.iid}/notes/#{note2.id}/award_emoji", user), name: 'thumbsup' - - expect(response).to have_gitlab_http_status(404) - end - it "normalizes +1 as thumbsup award" do post api("/projects/#{project.id}/issues/#{issue.iid}/notes/#{note.id}/award_emoji", user), name: '+1' diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb index 0aec186f738..a2b41d56b8b 100644 --- a/spec/requests/api/files_spec.rb +++ b/spec/requests/api/files_spec.rb @@ -313,7 +313,7 @@ describe API::Files do describe "POST /projects/:id/repository/files/:file_path" do let!(:file_path) { "new_subfolder%2Fnewfile%2Erb" } - let(:valid_params) do + let(:params) do { branch: "master", content: "puts 8", @@ -322,7 +322,7 @@ describe API::Files do end it "creates a new file in project repo" do - post api(route(file_path), user), valid_params + post api(route(file_path), user), params expect(response).to have_gitlab_http_status(201) expect(json_response["file_path"]).to eq(CGI.unescape(file_path)) @@ -337,20 +337,28 @@ describe API::Files do expect(response).to have_gitlab_http_status(400) end + it 'returns a 400 bad request if the commit message is empty' do + params[:commit_message] = '' + + post api(route(file_path), user), params + + expect(response).to have_gitlab_http_status(400) + end + it "returns a 400 if editor fails to create file" do allow_any_instance_of(Repository).to receive(:create_file) .and_raise(Gitlab::Git::CommitError, 'Cannot create file') - post api(route("any%2Etxt"), user), valid_params + post api(route("any%2Etxt"), user), params expect(response).to have_gitlab_http_status(400) end context "when specifying an author" do it "creates a new file with the specified author" do - valid_params.merge!(author_email: author_email, author_name: author_name) + params.merge!(author_email: author_email, author_name: author_name) - post api(route("new_file_with_author%2Etxt"), user), valid_params + post api(route("new_file_with_author%2Etxt"), user), params expect(response).to have_gitlab_http_status(201) expect(response.content_type).to eq('application/json') @@ -364,7 +372,7 @@ describe API::Files do let!(:project) { create(:project_empty_repo, namespace: user.namespace ) } it "creates a new file in project repo" do - post api(route("newfile%2Erb"), user), valid_params + post api(route("newfile%2Erb"), user), params expect(response).to have_gitlab_http_status(201) expect(json_response['file_path']).to eq('newfile.rb') @@ -376,7 +384,7 @@ describe API::Files do end describe "PUT /projects/:id/repository/files" do - let(:valid_params) do + let(:params) do { branch: 'master', content: 'puts 8', @@ -385,7 +393,7 @@ describe API::Files do end it "updates existing file in project repo" do - put api(route(file_path), user), valid_params + put api(route(file_path), user), params expect(response).to have_gitlab_http_status(200) expect(json_response['file_path']).to eq(CGI.unescape(file_path)) @@ -394,8 +402,16 @@ describe API::Files do expect(last_commit.author_name).to eq(user.name) end + it 'returns a 400 bad request if the commit message is empty' do + params[:commit_message] = '' + + put api(route(file_path), user), params + + expect(response).to have_gitlab_http_status(400) + end + it "returns a 400 bad request if update existing file with stale last commit id" do - params_with_stale_id = valid_params.merge(last_commit_id: 'stale') + params_with_stale_id = params.merge(last_commit_id: 'stale') put api(route(file_path), user), params_with_stale_id @@ -406,7 +422,7 @@ describe API::Files do it "updates existing file in project repo with accepts correct last commit id" do last_commit = Gitlab::Git::Commit .last_for_path(project.repository, 'master', URI.unescape(file_path)) - params_with_correct_id = valid_params.merge(last_commit_id: last_commit.id) + params_with_correct_id = params.merge(last_commit_id: last_commit.id) put api(route(file_path), user), params_with_correct_id @@ -421,9 +437,9 @@ describe API::Files do context "when specifying an author" do it "updates a file with the specified author" do - valid_params.merge!(author_email: author_email, author_name: author_name, content: "New content") + params.merge!(author_email: author_email, author_name: author_name, content: "New content") - put api(route(file_path), user), valid_params + put api(route(file_path), user), params expect(response).to have_gitlab_http_status(200) last_commit = project.repository.commit.raw @@ -434,7 +450,7 @@ describe API::Files do end describe "DELETE /projects/:id/repository/files" do - let(:valid_params) do + let(:params) do { branch: 'master', commit_message: 'Changed file' @@ -442,7 +458,7 @@ describe API::Files do end it "deletes existing file in project repo" do - delete api(route(file_path), user), valid_params + delete api(route(file_path), user), params expect(response).to have_gitlab_http_status(204) end @@ -453,19 +469,27 @@ describe API::Files do expect(response).to have_gitlab_http_status(400) end + it 'returns a 400 bad request if the commit message is empty' do + params[:commit_message] = '' + + delete api(route(file_path), user), params + + expect(response).to have_gitlab_http_status(400) + end + it "returns a 400 if fails to delete file" do allow_any_instance_of(Repository).to receive(:delete_file).and_raise(Gitlab::Git::CommitError, 'Cannot delete file') - delete api(route(file_path), user), valid_params + delete api(route(file_path), user), params expect(response).to have_gitlab_http_status(400) end context "when specifying an author" do it "removes a file with the specified author" do - valid_params.merge!(author_email: author_email, author_name: author_name) + params.merge!(author_email: author_email, author_name: author_name) - delete api(route(file_path), user), valid_params + delete api(route(file_path), user), params expect(response).to have_gitlab_http_status(204) end diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb index a4220f5b2be..b8a4a04a7e4 100644 --- a/spec/requests/api/labels_spec.rb +++ b/spec/requests/api/labels_spec.rb @@ -306,16 +306,16 @@ describe API::Labels do end it 'returns 400 for too long color code' do - post api("/projects/#{project.id}/labels", user), - name: 'Foo', + put api("/projects/#{project.id}/labels", user), + name: 'label1', color: '#FFAAFFFF' expect(response).to have_gitlab_http_status(400) expect(json_response['message']['color']).to eq(['must be a valid color code']) end it 'returns 400 for invalid priority' do - post api("/projects/#{project.id}/labels", user), - name: 'Foo', + put api("/projects/#{project.id}/labels", user), + name: 'label1', priority: 'foo' expect(response).to have_gitlab_http_status(400) diff --git a/spec/requests/api/project_snippets_spec.rb b/spec/requests/api/project_snippets_spec.rb index a3b5e8c6223..5dec0bc778c 100644 --- a/spec/requests/api/project_snippets_spec.rb +++ b/spec/requests/api/project_snippets_spec.rb @@ -116,6 +116,14 @@ describe API::ProjectSnippets do expect(response).to have_gitlab_http_status(400) end + it 'returns 400 for empty code field' do + params[:code] = '' + + post api("/projects/#{project.id}/snippets/", admin), params + + expect(response).to have_gitlab_http_status(400) + end + context 'when the snippet is spam' do def create_snippet(project, snippet_params = {}) project.add_developer(user) @@ -180,6 +188,14 @@ describe API::ProjectSnippets do expect(response).to have_gitlab_http_status(400) end + it 'returns 400 for empty code field' do + new_content = '' + + put api("/projects/#{snippet.project.id}/snippets/#{snippet.id}/", admin), code: new_content + + expect(response).to have_gitlab_http_status(400) + end + context 'when the snippet is spam' do def update_snippet(snippet_params = {}) put api("/projects/#{snippet.project.id}/snippets/#{snippet.id}", admin), snippet_params diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 881eff5d09d..b6f92042ecc 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -913,12 +913,28 @@ describe API::Projects do expect(json_response['shared_with_groups'][0]['group_id']).to eq(group.id) expect(json_response['shared_with_groups'][0]['group_name']).to eq(group.name) expect(json_response['shared_with_groups'][0]['group_access_level']).to eq(link.group_access) + expect(json_response['shared_with_groups'][0]['expires_at']).to be_nil expect(json_response['only_allow_merge_if_pipeline_succeeds']).to eq(project.only_allow_merge_if_pipeline_succeeds) expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to eq(project.only_allow_merge_if_all_discussions_are_resolved) expect(json_response['merge_method']).to eq(project.merge_method.to_s) expect(json_response['readme_url']).to eq(project.readme_url) end + it 'returns a group link with expiration date' do + group = create(:group) + expires_at = 5.days.from_now.to_date + link = create(:project_group_link, project: project, group: group, expires_at: expires_at) + + get api("/projects/#{project.id}", user) + + expect(json_response['shared_with_groups']).to be_an Array + expect(json_response['shared_with_groups'].length).to eq(1) + expect(json_response['shared_with_groups'][0]['group_id']).to eq(group.id) + expect(json_response['shared_with_groups'][0]['group_name']).to eq(group.name) + expect(json_response['shared_with_groups'][0]['group_access_level']).to eq(link.group_access) + expect(json_response['shared_with_groups'][0]['expires_at']).to eq(expires_at.to_s) + end + it 'returns a project by path name' do get api("/projects/#{project.id}", user) expect(response).to have_gitlab_http_status(200) diff --git a/spec/requests/api/protected_tags_spec.rb b/spec/requests/api/protected_tags_spec.rb new file mode 100644 index 00000000000..f4f3ef31bc3 --- /dev/null +++ b/spec/requests/api/protected_tags_spec.rb @@ -0,0 +1,202 @@ +require 'spec_helper' + +describe API::ProtectedTags do + let(:user) { create(:user) } + let!(:project) { create(:project, :repository) } + let(:project2) { create(:project, path: 'project2', namespace: user.namespace) } + let(:protected_name) { 'feature' } + let(:tag_name) { protected_name } + let!(:protected_tag) do + create(:protected_tag, project: project, name: protected_name) + end + + describe 'GET /projects/:id/protected_tags' do + let(:route) { "/projects/#{project.id}/protected_tags" } + + shared_examples_for 'protected tags' do + it 'returns the protected tags' do + get api(route, user), per_page: 100 + + expect(response).to have_gitlab_http_status(200) + expect(response).to include_pagination_headers + expect(json_response).to be_an Array + + protected_tag_names = json_response.map { |x| x['name'] } + expected_tags_names = project.protected_tags.map { |x| x['name'] } + expect(protected_tag_names).to match_array(expected_tags_names) + end + end + + context 'when authenticated as a maintainer' do + before do + project.add_maintainer(user) + end + + it_behaves_like 'protected tags' + end + + context 'when authenticated as a guest' do + before do + project.add_guest(user) + end + + it_behaves_like '403 response' do + let(:request) { get api(route, user) } + end + end + end + + describe 'GET /projects/:id/protected_tags/:tag' do + let(:route) { "/projects/#{project.id}/protected_tags/#{tag_name}" } + + shared_examples_for 'protected tag' do + it 'returns the protected tag' do + get api(route, user) + + expect(response).to have_gitlab_http_status(200) + expect(json_response['name']).to eq(tag_name) + expect(json_response['create_access_levels'][0]['access_level']).to eq(::Gitlab::Access::MAINTAINER) + end + + context 'when protected tag does not exist' do + let(:tag_name) { 'unknown' } + + it_behaves_like '404 response' do + let(:request) { get api(route, user) } + let(:message) { '404 Not found' } + end + end + end + + context 'when authenticated as a maintainer' do + before do + project.add_maintainer(user) + end + + it_behaves_like 'protected tag' + + context 'when protected tag contains a wildcard' do + let(:protected_name) { 'feature*' } + + it_behaves_like 'protected tag' + end + end + + context 'when authenticated as a guest' do + before do + project.add_guest(user) + end + + it_behaves_like '403 response' do + let(:request) { get api(route, user) } + end + end + end + + describe 'POST /projects/:id/protected_tags' do + let(:tag_name) { 'new_tag' } + + context 'when authenticated as a maintainer' do + before do + project.add_maintainer(user) + end + + it 'protects a single tag with maintainers can create tags' do + post api("/projects/#{project.id}/protected_tags", user), name: tag_name + + expect(response).to have_gitlab_http_status(201) + expect(json_response['name']).to eq(tag_name) + expect(json_response['create_access_levels'][0]['access_level']).to eq(Gitlab::Access::MAINTAINER) + end + + it 'protects a single tag with developers can create tags' do + post api("/projects/#{project.id}/protected_tags", user), + name: tag_name, create_access_level: 30 + + expect(response).to have_gitlab_http_status(201) + expect(json_response['name']).to eq(tag_name) + expect(json_response['create_access_levels'][0]['access_level']).to eq(Gitlab::Access::DEVELOPER) + end + + it 'protects a single tag with no one can create tags' do + post api("/projects/#{project.id}/protected_tags", user), + name: tag_name, create_access_level: 0 + + expect(response).to have_gitlab_http_status(201) + expect(json_response['name']).to eq(tag_name) + expect(json_response['create_access_levels'][0]['access_level']).to eq(Gitlab::Access::NO_ACCESS) + end + + it 'returns a 422 error if the same tag is protected twice' do + post api("/projects/#{project.id}/protected_tags", user), name: protected_name + + expect(response).to have_gitlab_http_status(422) + expect(json_response['message'][0]).to eq('Name has already been taken') + end + + it 'returns 201 if the same tag is proteted on different projects' do + post api("/projects/#{project.id}/protected_tags", user), name: protected_name + post api("/projects/#{project2.id}/protected_tags", user), name: protected_name + + expect(response).to have_gitlab_http_status(201) + expect(json_response['name']).to eq(protected_name) + end + + context 'when tag has a wildcard in its name' do + let(:tag_name) { 'feature/*' } + + it 'protects multiple tags with a wildcard in the name' do + post api("/projects/#{project.id}/protected_tags", user), name: tag_name + + expect(response).to have_gitlab_http_status(201) + expect(json_response['name']).to eq(tag_name) + expect(json_response['create_access_levels'][0]['access_level']).to eq(Gitlab::Access::MAINTAINER) + end + end + end + + context 'when authenticated as a guest' do + before do + project.add_guest(user) + end + + it 'returns a 403 error if guest' do + post api("/projects/#{project.id}/protected_tags/", user), name: tag_name + + expect(response).to have_gitlab_http_status(403) + end + end + end + + describe 'DELETE /projects/:id/protected_tags/unprotect/:tag' do + before do + project.add_maintainer(user) + end + + it 'unprotects a single tag' do + delete api("/projects/#{project.id}/protected_tags/#{tag_name}", user) + + expect(response).to have_gitlab_http_status(204) + end + + it_behaves_like '412 response' do + let(:request) { api("/projects/#{project.id}/protected_tags/#{tag_name}", user) } + end + + it "returns 404 if tag does not exist" do + delete api("/projects/#{project.id}/protected_tags/barfoo", user) + + expect(response).to have_gitlab_http_status(404) + end + + context 'when tag has a wildcard in its name' do + let(:protected_name) { 'feature*' } + + it 'unprotects a wildcard tag' do + delete api("/projects/#{project.id}/protected_tags/#{tag_name}", user) + + expect(response).to have_gitlab_http_status(204) + end + end + end +end diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index a3c9a660c2f..d4528256640 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -204,16 +204,37 @@ describe GitPushService, services: true do end describe "Push Event" do - let!(:push_data) { push_data_from_service(project, user, oldrev, newrev, ref) } - let(:event) { Event.find_by_action(Event::PUSHED) } + context "with an existing branch" do + let!(:push_data) { push_data_from_service(project, user, oldrev, newrev, ref) } + let(:event) { Event.find_by_action(Event::PUSHED) } - it { expect(event).to be_an_instance_of(PushEvent) } - it { expect(event.project).to eq(project) } - it { expect(event.action).to eq(Event::PUSHED) } - it { expect(event.push_event_payload).to be_an_instance_of(PushEventPayload) } - it { expect(event.push_event_payload.commit_from).to eq(oldrev) } - it { expect(event.push_event_payload.commit_to).to eq(newrev) } - it { expect(event.push_event_payload.ref).to eq('master') } + it 'generates a push event with one commit' do + expect(event).to be_an_instance_of(PushEvent) + expect(event.project).to eq(project) + expect(event.action).to eq(Event::PUSHED) + expect(event.push_event_payload).to be_an_instance_of(PushEventPayload) + expect(event.push_event_payload.commit_from).to eq(oldrev) + expect(event.push_event_payload.commit_to).to eq(newrev) + expect(event.push_event_payload.ref).to eq('master') + expect(event.push_event_payload.commit_count).to eq(1) + end + end + + context "with a new branch" do + let!(:new_branch_data) { push_data_from_service(project, user, Gitlab::Git::BLANK_SHA, newrev, ref) } + let(:event) { Event.find_by_action(Event::PUSHED) } + + it 'generates a push event with more than one commit' do + expect(event).to be_an_instance_of(PushEvent) + expect(event.project).to eq(project) + expect(event.action).to eq(Event::PUSHED) + expect(event.push_event_payload).to be_an_instance_of(PushEventPayload) + expect(event.push_event_payload.commit_from).to be_nil + expect(event.push_event_payload.commit_to).to eq(newrev) + expect(event.push_event_payload.ref).to eq('master') + expect(event.push_event_payload.commit_count).to be > 1 + end + end context "Updates merge requests" do it "when pushing a new branch for the first time" do @@ -223,9 +244,14 @@ describe GitPushService, services: true do end end - context "Sends System Push data" do - it "when pushing on a branch" do - expect(SystemHookPushWorker).to receive(:perform_async).with(push_data, :push_hooks) + describe 'system hooks' do + let!(:push_data) { push_data_from_service(project, user, oldrev, newrev, ref) } + let(:system_hooks_service) { SystemHooksService.new } + + it "sends a system hook after pushing a branch" do + expect(SystemHooksService).to receive(:new).and_return(system_hooks_service) + expect(system_hooks_service).to receive(:execute_hooks).with(push_data, :push_hooks) + execute_service(project, user, oldrev, newrev, ref) end end diff --git a/spec/services/issues/fetch_referenced_merge_requests_service_spec.rb b/spec/services/issues/fetch_referenced_merge_requests_service_spec.rb deleted file mode 100644 index 4e58179f45f..00000000000 --- a/spec/services/issues/fetch_referenced_merge_requests_service_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -require 'spec_helper.rb' - -describe Issues::FetchReferencedMergeRequestsService do - let(:project) { create(:project) } - let(:issue) { create(:issue, project: project) } - let(:other_project) { create(:project) } - - let(:mr) { create(:merge_request, source_project: project, target_project: project, id: 2)} - let(:other_mr) { create(:merge_request, source_project: other_project, target_project: other_project, id: 1)} - - let(:user) { create(:user) } - let(:service) { described_class.new(project, user) } - - context 'with mentioned merge requests' do - it 'returns a list of sorted merge requests' do - allow(issue).to receive(:referenced_merge_requests).with(user).and_return([other_mr, mr]) - - mrs, closed_by_mrs = service.execute(issue) - - expect(mrs).to match_array([mr, other_mr]) - expect(closed_by_mrs).to match_array([]) - end - end - - context 'with closed-by merge requests' do - it 'returns a list of sorted merge requests' do - allow(issue).to receive(:closed_by_merge_requests).with(user).and_return([other_mr, mr]) - - mrs, closed_by_mrs = service.execute(issue) - - expect(mrs).to match_array([]) - expect(closed_by_mrs).to match_array([mr, other_mr]) - end - end -end diff --git a/spec/services/issues/referenced_merge_requests_service_spec.rb b/spec/services/issues/referenced_merge_requests_service_spec.rb new file mode 100644 index 00000000000..61d1612829f --- /dev/null +++ b/spec/services/issues/referenced_merge_requests_service_spec.rb @@ -0,0 +1,133 @@ +# frozen_string_literal: true + +require 'spec_helper.rb' + +describe Issues::ReferencedMergeRequestsService do + def create_referencing_mr(attributes = {}) + create(:merge_request, attributes).tap do |merge_request| + create(:note, :system, project: project, noteable: issue, author: user, note: merge_request.to_reference(full: true)) + end + end + + def create_closing_mr(attributes = {}) + create_referencing_mr(attributes).tap do |merge_request| + create(:merge_requests_closing_issues, issue: issue, merge_request: merge_request) + end + end + + set(:user) { create(:user) } + set(:project) { create(:project, :public, :repository) } + set(:other_project) { create(:project, :public, :repository) } + set(:issue) { create(:issue, author: user, project: project) } + + set(:closing_mr) { create_closing_mr(source_project: project) } + set(:closing_mr_other_project) { create_closing_mr(source_project: other_project) } + + set(:referencing_mr) { create_referencing_mr(source_project: project, source_branch: 'csv') } + set(:referencing_mr_other_project) { create_referencing_mr(source_project: other_project, source_branch: 'csv') } + + let(:service) { described_class.new(project, user) } + + describe '#execute' do + it 'returns a list of sorted merge requests' do + mrs, closed_by_mrs = service.execute(issue) + + expect(mrs).to eq([closing_mr, referencing_mr, closing_mr_other_project, referencing_mr_other_project]) + expect(closed_by_mrs).to eq([closing_mr, closing_mr_other_project]) + end + + context 'performance' do + it 'does not run extra queries when extra namespaces are included', :use_clean_rails_memory_store_caching do + service.execute(issue) # warm cache + control_count = ActiveRecord::QueryRecorder.new { service.execute(issue) }.count + + third_project = create(:project, :public) + create_closing_mr(source_project: third_project) + service.execute(issue) # warm cache + + expect { service.execute(issue) }.not_to exceed_query_limit(control_count) + end + + it 'preloads the head pipeline for each merge request, and its routes' do + # Hack to ensure no data is preserved on issue before starting the spec, + # to avoid false negatives + reloaded_issue = Issue.find(issue.id) + + pipeline_routes = lambda do |merge_requests| + merge_requests.map { |mr| mr.head_pipeline&.project&.full_path } + end + + closing_mr_other_project.update!(head_pipeline: create(:ci_pipeline)) + control_count = ActiveRecord::QueryRecorder.new { service.execute(reloaded_issue).each(&pipeline_routes) } + + closing_mr.update!(head_pipeline: create(:ci_pipeline)) + + expect { service.execute(issue).each(&pipeline_routes) } + .not_to exceed_query_limit(control_count) + end + + it 'only loads issue notes once' do + expect(issue).to receive(:notes).once.and_call_original + + service.execute(issue) + end + end + end + + describe '#referenced_merge_requests' do + it 'returns the referenced merge requests' do + expect(service.referenced_merge_requests(issue)).to match_array([ + closing_mr, + closing_mr_other_project, + referencing_mr, + referencing_mr_other_project + ]) + end + + it 'excludes cross project references if the user cannot read cross project' do + allow(Ability).to receive(:allowed?).and_call_original + expect(Ability).to receive(:allowed?).with(user, :read_cross_project).at_least(:once).and_return(false) + + expect(service.referenced_merge_requests(issue)).not_to include(closing_mr_other_project) + expect(service.referenced_merge_requests(issue)).not_to include(referencing_mr_other_project) + end + + context 'performance' do + it 'does not run a query for each note author', :use_clean_rails_memory_store_caching do + service.referenced_merge_requests(issue) # warm cache + control_count = ActiveRecord::QueryRecorder.new { service.referenced_merge_requests(issue) }.count + + create(:note, project: project, noteable: issue, author: create(:user)) + service.referenced_merge_requests(issue) # warm cache + + expect { service.referenced_merge_requests(issue) }.not_to exceed_query_limit(control_count) + end + end + end + + describe '#closed_by_merge_requests' do + let(:closed_issue) { build(:issue, :closed, project: project)} + + it 'returns the open merge requests that close this issue' do + create_closing_mr(source_project: project, state: 'closed') + + expect(service.closed_by_merge_requests(issue)).to match_array([closing_mr, closing_mr_other_project]) + end + + it 'returns an empty array when the current issue is closed already' do + expect(service.closed_by_merge_requests(closed_issue)).to eq([]) + end + + context 'performance' do + it 'does not run a query for each note author', :use_clean_rails_memory_store_caching do + service.closed_by_merge_requests(issue) # warm cache + control_count = ActiveRecord::QueryRecorder.new { service.closed_by_merge_requests(issue) }.count + + create(:note, :system, project: project, noteable: issue, author: create(:user)) + service.closed_by_merge_requests(issue) # warm cache + + expect { service.closed_by_merge_requests(issue) }.not_to exceed_query_limit(control_count) + end + end + end +end diff --git a/spec/services/projects/update_remote_mirror_service_spec.rb b/spec/services/projects/update_remote_mirror_service_spec.rb index 5c2e79ff9af..96e8a80b334 100644 --- a/spec/services/projects/update_remote_mirror_service_spec.rb +++ b/spec/services/projects/update_remote_mirror_service_spec.rb @@ -18,6 +18,7 @@ describe Projects::UpdateRemoteMirrorService do end it "fetches the remote repository" do + expect(remote_mirror).to receive(:ensure_remote!).and_call_original expect(repository).to receive(:fetch_remote).with(remote_mirror.remote_name, no_tags: true) do sync_remote(repository, remote_mirror.remote_name, local_branch_names) end diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb index 9572b4110d5..695b9980548 100644 --- a/spec/services/projects/update_service_spec.rb +++ b/spec/services/projects/update_service_spec.rb @@ -249,9 +249,20 @@ describe Projects::UpdateService do expect(project.errors.messages[:base]).to include('There is already a repository with that name on disk') end - context 'when hashed storage enabled' do + it 'renames the project without upgrading it' do + result = update_project(project, admin, path: 'new-path') + + expect(result).not_to include(status: :error) + expect(project).to be_valid + expect(project.errors).to be_empty + expect(project.disk_path).to include('new-path') + expect(project.reload.hashed_storage?(:repository)).to be_falsey + end + + context 'when hashed storage is enabled' do before do stub_application_setting(hashed_storage_enabled: true) + stub_feature_flags(skip_hashed_storage_upgrade: false) end it 'migrates project to a hashed storage instead of renaming the repo to another legacy name' do @@ -262,6 +273,22 @@ describe Projects::UpdateService do expect(project.errors).to be_empty expect(project.reload.hashed_storage?(:repository)).to be_truthy end + + context 'when skip_hashed_storage_upgrade feature flag is enabled' do + before do + stub_feature_flags(skip_hashed_storage_upgrade: true) + end + + it 'renames the project without upgrading it' do + result = update_project(project, admin, path: 'new-path') + + expect(result).not_to include(status: :error) + expect(project).to be_valid + expect(project.errors).to be_empty + expect(project.disk_path).to include('new-path') + expect(project.reload.hashed_storage?(:repository)).to be_falsey + end + end end end diff --git a/spec/support/helpers/cycle_analytics_helpers.rb b/spec/support/helpers/cycle_analytics_helpers.rb index c228bd2393b..e0fceae88de 100644 --- a/spec/support/helpers/cycle_analytics_helpers.rb +++ b/spec/support/helpers/cycle_analytics_helpers.rb @@ -65,7 +65,9 @@ module CycleAnalyticsHelpers end def merge_merge_requests_closing_issue(user, project, issue) - merge_requests = issue.closed_by_merge_requests(user) + merge_requests = Issues::ReferencedMergeRequestsService + .new(project, user) + .closed_by_merge_requests(issue) merge_requests.each { |merge_request| MergeRequests::MergeService.new(project, user).execute(merge_request) } end diff --git a/spec/support/helpers/ldap_helpers.rb b/spec/support/helpers/ldap_helpers.rb index b90bbc4b106..66ca5d7f0a3 100644 --- a/spec/support/helpers/ldap_helpers.rb +++ b/spec/support/helpers/ldap_helpers.rb @@ -37,6 +37,23 @@ module LdapHelpers .to receive(:find_by_uid).with(uid, any_args).and_return(return_value) end + def stub_ldap_person_find_by_dn(entry, provider = 'ldapmain') + person = ::Gitlab::Auth::LDAP::Person.new(entry, provider) if entry.present? + + allow(::Gitlab::Auth::LDAP::Person) + .to receive(:find_by_dn) + .and_return(person) + end + + def stub_ldap_person_find_by_email(email, entry, provider = 'ldapmain') + person = ::Gitlab::Auth::LDAP::Person.new(entry, provider) if entry.present? + + allow(::Gitlab::Auth::LDAP::Person) + .to receive(:find_by_email) + .with(email, anything) + .and_return(person) + end + # Create a simple LDAP user entry. def ldap_user_entry(uid) entry = Net::LDAP::Entry.new diff --git a/spec/support/helpers/stub_configuration.rb b/spec/support/helpers/stub_configuration.rb index 1823099dd9c..8475f91799b 100644 --- a/spec/support/helpers/stub_configuration.rb +++ b/spec/support/helpers/stub_configuration.rb @@ -68,6 +68,10 @@ module StubConfiguration allow(Gitlab.config.repositories).to receive(:storages).and_return(Settingslogic.new(messages)) end + def stub_kerberos_setting(messages) + allow(Gitlab.config.kerberos).to receive_messages(to_settings(messages)) + end + private # Modifies stubbed messages to also stub possible predicate versions diff --git a/spec/support/helpers/stub_feature_flags.rb b/spec/support/helpers/stub_feature_flags.rb index b96338bf548..c54a871b157 100644 --- a/spec/support/helpers/stub_feature_flags.rb +++ b/spec/support/helpers/stub_feature_flags.rb @@ -1,4 +1,7 @@ module StubFeatureFlags + # Stub Feature flags with `flag_name: true/false` + # + # @param [Hash] features where key is feature name and value is boolean whether enabled or not def stub_feature_flags(features) features.each do |feature_name, enabled| allow(Feature).to receive(:enabled?).with(feature_name) { enabled } diff --git a/spec/views/projects/merge_requests/_commits.html.haml_spec.rb b/spec/views/projects/merge_requests/_commits.html.haml_spec.rb index b1c6565c08a..a7628548de6 100644 --- a/spec/views/projects/merge_requests/_commits.html.haml_spec.rb +++ b/spec/views/projects/merge_requests/_commits.html.haml_spec.rb @@ -20,6 +20,7 @@ describe 'projects/merge_requests/_commits.html.haml' do assign(:merge_request, merge_request) assign(:commits, merge_request.commits) + assign(:hidden_commit_count, 0) end it 'shows commits from source project' do @@ -30,4 +31,16 @@ describe 'projects/merge_requests/_commits.html.haml' do expect(rendered).to have_link(href: href) end + + context 'when there are hidden commits' do + before do + assign(:hidden_commit_count, 1) + end + + it 'shows notice about omitted commits' do + render + + expect(rendered).to match(/1 additional commit has been omitted to prevent performance issues/) + end + end end diff --git a/spec/views/projects/merge_requests/creations/_new_submit.html.haml_spec.rb b/spec/views/projects/merge_requests/creations/_new_submit.html.haml_spec.rb index 9ab105c3238..8befae39d3a 100644 --- a/spec/views/projects/merge_requests/creations/_new_submit.html.haml_spec.rb +++ b/spec/views/projects/merge_requests/creations/_new_submit.html.haml_spec.rb @@ -9,6 +9,8 @@ describe 'projects/merge_requests/creations/_new_submit.html.haml' do assign(:merge_request, merge_request) assign(:commits, merge_request.commits) + assign(:hidden_commit_count, 0) + assign(:total_commit_count, merge_request.commits.count) assign(:project, merge_request.target_project) allow(view).to receive(:can?).and_return(true) @@ -29,4 +31,17 @@ describe 'projects/merge_requests/creations/_new_submit.html.haml' do expect(rendered).not_to have_text('Builds') end end + + context 'when there are hidden commits' do + before do + assign(:pipelines, Ci::Pipeline.none) + assign(:hidden_commit_count, 2) + end + + it 'shows notice about omitted commits' do + render + + expect(rendered).to match(/2 additional commits have been omitted to prevent performance issues/) + end + end end diff --git a/yarn.lock b/yarn.lock index 4326245d2ac..db3b0bbe573 100644 --- a/yarn.lock +++ b/yarn.lock @@ -78,10 +78,14 @@ lodash "^4.2.0" to-fast-properties "^2.0.0" -"@gitlab-org/gitlab-svgs@^1.23.0", "@gitlab-org/gitlab-svgs@^1.27.0": +"@gitlab-org/gitlab-svgs@^1.23.0": version "1.27.0" resolved "https://registry.yarnpkg.com/@gitlab-org/gitlab-svgs/-/gitlab-svgs-1.27.0.tgz#638e70399ebd59e503732177316bb9a18bf7a13f" +"@gitlab-org/gitlab-svgs@^1.28.0": + version "1.28.0" + resolved "https://registry.yarnpkg.com/@gitlab-org/gitlab-svgs/-/gitlab-svgs-1.28.0.tgz#f689dfd46504df0a75027d6dd4ea01a71cd46f88" + "@gitlab-org/gitlab-ui@1.0.5": version "1.0.5" resolved "https://registry.yarnpkg.com/@gitlab-org/gitlab-ui/-/gitlab-ui-1.0.5.tgz#a64b402650494115c8b494a44b72c2d6fbf33fff" |