Commit ab44f531 authored by Filipa Lacerda's avatar Filipa Lacerda

Merge branch 'master' into 25990-web-terminal-improvements

* master: (66 commits)
  Allows to cancel a Created job
  Enable frozen string in rest of app/models/**/*.rb
  docs: removed duplicate `git_ssh_url` field from build event example
  Bump pry to 0.11.3; pry-byebug to 3.4.3
  Update GitLab Shell to v8.1.1 to fix regressions
  Rails5 fix specs duplicate key value violates unique constraint 'index_gpg_signatures_on_commit_sha'
  Add mock data for spam logs
  Disable danger in preparation branches
  [ci-skip] add changelog
  Add default avatar to group
  Fix label item height when no desc
  Fix docs linting
  Fix missed port
  Consistent padding but correct label-actions-list positioning and label-links margin
  Phase 2: #47282 Improving Contributor On-Boarding Documentation
  Fix label item height when no desc
  Resolve "docs update api for usage with an array of hashes"
  removed un-used commits for currentProject & currentBranchId
  Allow the Web IDE to open empty merge requests
  Add rubocop check for add_reference to require index.
  ...
parents b4f9379e 91795dcd
...@@ -453,6 +453,7 @@ danger-review: ...@@ -453,6 +453,7 @@ danger-review:
- master - master
variables: variables:
- $CI_COMMIT_REF_NAME =~ /^ce-to-ee-.*/ - $CI_COMMIT_REF_NAME =~ /^ce-to-ee-.*/
- $CI_COMMIT_REF_NAME =~ /.*-stable(-ee)?-prepare-.*/
script: script:
- git version - git version
- danger --fail-on-errors=true - danger --fail-on-errors=true
......
...@@ -21,21 +21,24 @@ _This notice should stay as the first item in the CONTRIBUTING.md file._ ...@@ -21,21 +21,24 @@ _This notice should stay as the first item in the CONTRIBUTING.md file._
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
- [Contributing Documentation has been moved](#contributing-documentation-has-been-moved)
- [Contribute to GitLab](#contribute-to-gitlab) - [Contribute to GitLab](#contribute-to-gitlab)
- [Security vulnerability disclosure](#security-vulnerability-disclosure) - [Security vulnerability disclosure](#security-vulnerability-disclosure)
- [Code of conduct](#code-of-conduct)
- [Closing policy for issues and merge requests](#closing-policy-for-issues-and-merge-requests) - [Closing policy for issues and merge requests](#closing-policy-for-issues-and-merge-requests)
- [Helping others](#helping-others) - [Helping others](#helping-others)
- [I want to contribute!](#i-want-to-contribute) - [I want to contribute!](#i-want-to-contribute)
- [Contribution Flow](#contribution-flow)
- [Workflow labels](#workflow-labels) - [Workflow labels](#workflow-labels)
- [Type labels](#type-labels) - [Type labels](#type-labels)
- [Subject labels](#subject-labels) - [Subject labels](#subject-labels)
- [Team labels](#team-labels) - [Team labels](#team-labels)
- [Release Scoping labels](#release-scoping-labels) - [Release Scoping labels](#release-scoping-labels)
- [Bug Priority labels](#bug-priority-labels) - [Priority labels](#priority-labels)
- [Bug Severity labels](#bug-severity-labels) - [Severity labels](#severity-labels)
- [Severity impact guidance](#severity-impact-guidance) - [Severity impact guidance](#severity-impact-guidance)
- [Label for community contributors](#label-for-community-contributors) - [Label for community contributors](#label-for-community-contributors)
- [Implement design & UI elements](#implement-design-ui-elements) - [Implement design & UI elements](#implement-design--ui-elements)
- [Issue tracker](#issue-tracker) - [Issue tracker](#issue-tracker)
- [Issue triaging](#issue-triaging) - [Issue triaging](#issue-triaging)
- [Feature proposals](#feature-proposals) - [Feature proposals](#feature-proposals)
...@@ -49,13 +52,16 @@ _This notice should stay as the first item in the CONTRIBUTING.md file._ ...@@ -49,13 +52,16 @@ _This notice should stay as the first item in the CONTRIBUTING.md file._
- [Contribution acceptance criteria](#contribution-acceptance-criteria) - [Contribution acceptance criteria](#contribution-acceptance-criteria)
- [Definition of done](#definition-of-done) - [Definition of done](#definition-of-done)
- [Style guides](#style-guides) - [Style guides](#style-guides)
- [Code of conduct](#code-of-conduct)
- [Contribution Flow](#contribution-flow)
<!-- END doctoc generated TOC please keep comment here to allow auto update --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->
--- ---
## Contributing Documentation has been moved
As of July 2018, all the documentation for contributing to the GitLab project has been moved to a new location.
[view the new documentation](doc/development/contributing/index.md) to find the latest information.
## Contribute to GitLab ## Contribute to GitLab
For a first-time step-by-step guide to the contribution process, see For a first-time step-by-step guide to the contribution process, see
...@@ -84,6 +90,36 @@ Please report suspected security vulnerabilities in private to ...@@ -84,6 +90,36 @@ Please report suspected security vulnerabilities in private to
Please do **NOT** create publicly viewable issues for suspected security Please do **NOT** create publicly viewable issues for suspected security
vulnerabilities. vulnerabilities.
## Code of conduct
As contributors and maintainers of this project, we pledge to respect all
people who contribute through reporting issues, posting feature requests,
updating documentation, submitting pull requests or patches, and other
activities.
We are committed to making participation in this project a harassment-free
experience for everyone, regardless of level of experience, gender, gender
identity and expression, sexual orientation, disability, personal appearance,
body size, race, ethnicity, age, or religion.
Examples of unacceptable behavior by participants include the use of sexual
language or imagery, derogatory comments or personal attacks, trolling, public
or private harassment, insults, or other unprofessional conduct.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct. Project maintainers who do not
follow the Code of Conduct may be removed from the project team.
This code of conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior can be
reported by emailing `contact@gitlab.com`.
This Code of Conduct is adapted from the [Contributor Covenant][contributor-covenant], version 1.1.0,
available at [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/).
## Closing policy for issues and merge requests ## Closing policy for issues and merge requests
GitLab is a popular open source project and the capacity to deal with issues GitLab is a popular open source project and the capacity to deal with issues
...@@ -123,669 +159,164 @@ learn how to communicate with GitLab. If you're looking for a Gitter or Slack ch ...@@ -123,669 +159,164 @@ learn how to communicate with GitLab. If you're looking for a Gitter or Slack ch
please consider we favor please consider we favor
[asynchronous communication](https://about.gitlab.com/handbook/communication/#internal-communication) over real time communication. Thanks for your contribution! [asynchronous communication](https://about.gitlab.com/handbook/communication/#internal-communication) over real time communication. Thanks for your contribution!
## Workflow labels ## Contribution Flow
To allow for asynchronous issue handling, we use [milestones][milestones-page]
and [labels][labels-page]. Leads and product managers handle most of the
scheduling into milestones. Labelling is a task for everyone.
Most issues will have labels for at least one of the following:
- Type: ~"feature proposal", ~bug, ~customer, etc. When contributing to GitLab, your merge request is subject to review by merge request maintainers of a particular specialty.
- Subject: ~wiki, ~"container registry", ~ldap, ~api, ~frontend, etc.
- Team: ~"CI/CD", ~Plan, ~Manage, ~Quality, etc.
- Release Scoping: ~Deliverable, ~Stretch, ~"Next Patch Release"
- Priority: ~P1, ~P2, ~P3, ~P4
- Severity: ~S1, ~S2, ~S3, ~S4
All labels, their meaning and priority are defined on the When you submit code to GitLab, we really want it to get merged, but there will be times when it will not be merged.
[labels page][labels-page].
If you come across an issue that has none of these, and you're allowed to set When maintainers are reading through a merge request they may request guidance from other maintainers. If merge request maintainers conclude that the code should not be merged, our reasons will be fully disclosed. If it has been decided that the code quality is not up to GitLab’s standards, the merge request maintainer will refer the author to our docs and code style guides, and provide some guidance.
labels, you can _always_ add the team and type, and often also the subject.
[milestones-page]: https://gitlab.com/gitlab-org/gitlab-ce/milestones Sometimes style guides will be followed but the code will lack structural integrity, or the maintainer will have reservations about the code’s overall quality. When there is a reservation the maintainer will inform the author and provide some guidance. The author may then choose to update the merge request. Once the merge request has been updated and reassigned to the maintainer, they will review the code again. Once the code has been resubmitted any number of times, the maintainer may choose to close the merge request with a summary of why it will not be merged, as well as some guidance. If the merge request is closed the maintainer will be open to discussion as to how to improve the code so it can be approved in the future.
[labels-page]: https://gitlab.com/gitlab-org/gitlab-ce/labels
### Type labels GitLab will do its best to review community contributions as quickly as possible. Specially appointed developers review community contributions daily. You may take a look at the [team page](https://about.gitlab.com/team/) for the merge request coach who specializes in the type of code you have written and mention them in the merge request. For example, if you have written some JavaScript in your code then you should mention the frontend merge request coach. If your code has multiple disciplines you may mention multiple merge request coaches.
Type labels are very important. They define what kind of issue this is. Every GitLab receives a lot of community contributions, so if your code has not been reviewed within 4 days of its initial submission feel free to re-mention the appropriate merge request coach.
issue should have one or more.
Examples of type labels are ~"feature proposal", ~bug, ~customer, ~security, When submitting code to GitLab, you may feel that your contribution requires the aid of an external library. If your code includes an external library please provide a link to the library, as well as reasons for including it.
and ~"direction".
A number of type labels have a priority assigned to them, which automatically When your code contains more than 500 changes, any major breaking changes, or an external library, `@mention` a maintainer in the merge request. If you are not sure who to mention, the reviewer will add one early in the merge request process.
makes them float to the top, depending on their importance.
Type labels are always lowercase, and can have any color, besides blue (which is [core team]: https://about.gitlab.com/core-team/
already reserved for subject labels). [team]: https://about.gitlab.com/team/
[getting-help]: https://about.gitlab.com/getting-help/
[codetriage]: http://www.codetriage.com/gitlabhq/gitlabhq
[accepting-mrs-weight]: https://gitlab.com/gitlab-org/gitlab-ce/issues?assignee_id=0&label_name[]=Accepting%20Merge%20Requests&sort=weight_asc
[ce-tracker]: https://gitlab.com/gitlab-org/gitlab-ce/issues
[ee-tracker]: https://gitlab.com/gitlab-org/gitlab-ee/issues
[google-group]: https://groups.google.com/forum/#!forum/gitlabhq
[stackoverflow]: https://stackoverflow.com/questions/tagged/gitlab
[fpl]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=feature+proposal
[accepting-mrs-ce]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=Accepting+Merge+Requests
[accepting-mrs-ee]: https://gitlab.com/gitlab-org/gitlab-ee/issues?label_name=Accepting+Merge+Requests
[gitlab-mr-tracker]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests
[gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit
[git-squash]: https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits
[closed-merge-requests]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests?assignee_id=&label_name=&milestone_id=&scope=&sort=&state=closed
[definition-of-done]: http://guide.agilealliance.org/guide/definition-of-done.html
[contributor-covenant]: http://contributor-covenant.org
[rss-source]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#source-code-layout
[rss-naming]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#naming
[changelog]: doc/development/changelog.md "Generate a changelog entry"
[doc-guidelines]: doc/development/documentation/index.md "Documentation guidelines"
[js-styleguide]: doc/development/fe_guide/style_guide_js.md "JavaScript styleguide"
[scss-styleguide]: doc/development/fe_guide/style_guide_scss.md "SCSS styleguide"
[newlines-styleguide]: doc/development/newlines_styleguide.md "Newlines styleguide"
[UX Guide for GitLab]: http://docs.gitlab.com/ce/development/ux_guide/
[license-finder-doc]: doc/development/licensing.md
[GitLab Inc engineering workflow]: https://about.gitlab.com/handbook/engineering/workflow/#labelling-issues
[polling-etag]: https://docs.gitlab.com/ce/development/polling.html
[testing]: doc/development/testing_guide/index.md
[us-english]: https://en.wikipedia.org/wiki/American_English
The descriptions on the [labels page][labels-page] explain what falls under each type label.
### Subject labels ## Workflow labels
Subject labels are labels that define what area or feature of GitLab this issue This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
hits. They are not always necessary, but very convenient.
Examples of subject labels are ~wiki, ~ldap, ~api,
~issues, ~"merge requests", ~labels, and ~"container registry".
If you are an expert in a particular area, it makes it easier to find issues to ### Type labels
work on. You can also subscribe to those labels to receive an email each time an
issue is labeled with a subject label corresponding to your expertise.
Subject labels are always all-lowercase. This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
### Team labels
Team labels specify what team is responsible for this issue. ### Subject labels
Assigning a team label makes sure issues get the attention of the appropriate
people.
The current team labels are: This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
- ~Configuration
- ~"CI/CD"
- ~Create
- ~Distribution
- ~Documentation
- ~Geo
- ~Gitaly
- ~Manage
- ~Monitoring
- ~Plan
- ~Quality
- ~Release
- ~Secure
- ~UX
The descriptions on the [labels page][labels-page] explain what falls under the ### Team labels
responsibility of each team.
Within those team labels, we also have the ~backend and ~frontend labels to This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
indicate if an issue needs backend work, frontend work, or both.
Team labels are always capitalized so that they show up as the first label for
any issue.
### Release Scoping labels ### Release Scoping labels
Release Scoping labels help us clearly communicate expectations of the work for the This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
release. There are three levels of Release Scoping labels:
- ~Deliverable: Issues that are expected to be delivered in the current
milestone.
- ~Stretch: Issues that are a stretch goal for delivering in the current
milestone. If these issues are not done in the current release, they will
strongly be considered for the next release.
- ~"Next Patch Release": Issues to put in the next patch release. Work on these
first, and add the "Pick Into X" label to the merge request, along with the
appropriate milestone.
Each issue scheduled for the current milestone should be labeled ~Deliverable
or ~"Stretch". Any open issue for a previous milestone should be labeled
~"Next Patch Release", or otherwise rescheduled to a different milestone.
### Priority labels ### Priority labels
Priority labels help us define the time a ~bug fix should be completed. Priority determines how quickly the defect turnaround time must be. This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
If there are multiple defects, the priority decides which defect has to be fixed immediately versus later.
This label documents the planned timeline & urgency which is used to measure against our actual SLA on delivering ~bug fixes.
| Label | Meaning | Estimate time to fix |
|-------|-----------------|------------------------------------------------------------------|
| ~P1 | Urgent Priority | The current release + potentially immediate hotfix to GitLab.com |
| ~P2 | High Priority | The next release |
| ~P3 | Medium Priority | Within the next 3 releases (approx one quarter) |
| ~P4 | Low Priority | Anything outside the next 3 releases (approx beyond one quarter) |
### Severity labels ### Severity labels
Severity labels help us clearly communicate the impact of a ~bug on users. This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
| Label | Meaning | Impact on Functionality | Example |
|-------|-------------------|-------------------------------------------------------|---------|
| ~S1 | Blocker | Outage, broken feature with no workaround | Unable to create an issue. Data corruption/loss. Security breach. |
| ~S2 | Critical Severity | Broken Feature, workaround too complex & unacceptable | Can push commits, but only via the command line. |
| ~S3 | Major Severity | Broken Feature, workaround acceptable | Can create merge requests only from the Merge Requests page, not through the Issue. |
| ~S4 | Low Severity | Functionality inconvenience or cosmetic issue | Label colors are incorrect / not being displayed. |
#### Severity impact guidance #### Severity impact guidance
Severity levels can be applied further depending on the facet of the impact; e.g. Affected customers, GitLab.com availability, performance and etc. The below is a guideline. This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
| Severity | Affected Customers/Users | GitLab.com Availability | Performance Degradation |
|----------|---------------------------------------------------------------------|----------------------------------------------------|------------------------------|
| ~S1 | >50% users affected (possible company extinction level event) | Significant impact on all of GitLab.com | |
| ~S2 | Many users or multiple paid customers affected (but not apocalyptic)| Significant impact on large portions of GitLab.com | Degradation is guaranteed to occur in the near future |
| ~S3 | A few users or a single paid customer affected | Limited impact on important portions of GitLab.com | Degradation is likely to occur in the near future |
| ~S4 | No paid users/customer affected, or expected to in the near future | Minor impact on on GitLab.com | Degradation _may_ occur but it's not likely |
### Label for community contributors ### Label for community contributors
Issues that are beneficial to our users, 'nice to haves', that we currently do This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
not have the capacity for or want to give the priority to, are labeled as
~"Accepting Merge Requests", so the community can make a contribution.
Community contributors can submit merge requests for any issue they want, but
the ~"Accepting Merge Requests" label has a special meaning. It points to
changes that:
1. We already agreed on,
1. Are well-defined,
1. Are likely to get accepted by a maintainer.
We want to avoid a situation when a contributor picks an
~"Accepting Merge Requests" issue and then their merge request gets closed,
because we realize that it does not fit our vision, or we want to solve it in a
different way.
We add the ~"Accepting Merge Requests" label to:
- Low priority ~bug issues (i.e. we do not add it to the bugs that we want to
solve in the ~"Next Patch Release")
- Small ~"feature proposal"
- Small ~"technical debt" issues
After adding the ~"Accepting Merge Requests" label, we try to estimate the
[weight](#issue-weight) of the issue. We use issue weight to let contributors
know how difficult the issue is. Additionally:
- We advertise ["Accepting Merge Requests" issues with weight < 5][up-for-grabs]
as suitable for people that have never contributed to GitLab before on the
[Up For Grabs campaign](http://up-for-grabs.net)
- We encourage people that have never contributed to any open source project to
look for ["Accepting Merge Requests" issues with a weight of 1][firt-timers]
If you've decided that you would like to work on an issue, please @-mention
the [appropriate product manager](https://about.gitlab.com/handbook/product/#who-to-talk-to-for-what)
as soon as possible. The product manager will then pull in appropriate GitLab team
members to further discuss scope, design, and technical considerations. This will
ensure that that your contribution is aligned with the GitLab product and minimize
any rework and delay in getting it merged into master.
GitLab team members who apply the ~"Accepting Merge Requests" label to an issue
should update the issue description with a responsible product manager, inviting
any potential community contributor to @-mention per above.
[up-for-grabs]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=Accepting+Merge+Requests&scope=all&sort=weight_asc&state=opened
[firt-timers]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name%5B%5D=Accepting+Merge+Requests&scope=all&sort=upvotes_desc&state=opened&weight=1
## Implement design & UI elements ## Implement design & UI elements
For guidance on UX implementation at GitLab, please refer to our [Design System](https://design.gitlab.com/). This [documentation](doc/development/contributing/design.md) has been moved.
The UX team uses labels to manage their workflow.
The ~"UX" label on an issue is a signal to the UX team that it will need UX attention.
To better understand the priority by which UX tackles issues, see the [UX section](https://about.gitlab.com/handbook/engineering/ux) of the handbook.
Once an issue has been worked on and is ready for development, a UXer removes the ~"UX" label and applies the ~"UX ready" label to that issue.
The UX team has a special type label called ~"design artifact". This label indicates that the final output
for an issue is a UX solution/design. The solution will be developed by frontend and/or backend in a subsequent milestone.
Any issue labeled ~"design artifact" should not also be labeled ~"frontend" or ~"backend" since no development is
needed until the solution has been decided.
~"design artifact" issues are like any other issue and should contain a milestone label, ~"Deliverable" or ~"Stretch", when scheduled in the current milestone.
To prevent the misunderstanding that a feature will be be delivered in the
assigned milestone, when only UX design is planned for that milestone, the
Product Manager should create a separate issue for the ~"design artifact",
assign the ~UX, ~"design artifact" and ~"Deliverable" labels, add a milestone
and use a title that makes it clear that the scheduled issue is design only
(e.g. `Design exploration for XYZ`).
When the ~"design artifact" issue has been completed, the UXer removes the ~UX
label, adds the ~"UX ready" label and closes the issue. This indicates the
design artifact is complete. The UXer will also copy the designs to related
issues for implementation in an upcoming milestone.
## Issue tracker ## Issue tracker
To get support for your particular problem please use the This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
[getting help channels](https://about.gitlab.com/getting-help/).
The [GitLab CE issue tracker on GitLab.com][ce-tracker] is for bugs concerning
the latest GitLab release and [feature proposals](#feature-proposals).
When submitting an issue please conform to the issue submission guidelines
listed below. Not all issues will be addressed and your issue is more likely to
be addressed if you submit a merge request which partially or fully solves
the issue.
If you're unsure where to post, post to the [mailing list][google-group] or
[Stack Overflow][stackoverflow] first. There are a lot of helpful GitLab users
there who may be able to help you quickly. If your particular issue turns out
to be a bug, it will find its way from there.
If it happens that you know the solution to an existing bug, please first
open the issue in order to keep track of it and then open the relevant merge
request that potentially fixes it.
### Issue triaging ### Issue triaging
Our issue triage policies are [described in our handbook]. You are very welcome This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
to help the GitLab team triage issues. We also organize [issue bash events] once
every quarter.
The most important thing is making sure valid issues receive feedback from the
development team. Therefore the priority is mentioning developers that can help
on those issues. Please select someone with relevant experience from the
[GitLab team][team]. If there is nobody mentioned with that expertise look in
the commit history for the affected files to find someone.
We also use [GitLab Triage] to automate some triaging policies. This is
currently setup as a [scheduled pipeline] running on [quality/triage-ops]
project.
[described in our handbook]: https://about.gitlab.com/handbook/engineering/issue-triage/
[issue bash events]: https://gitlab.com/gitlab-org/gitlab-ce/issues/17815
[GitLab Triage]: https://gitlab.com/gitlab-org/gitlab-triage
[scheduled pipeline]: https://gitlab.com/gitlab-org/quality/triage-ops/pipeline_schedules/10512/edit
[quality/triage-ops]: https://gitlab.com/gitlab-org/quality/triage-ops
### Feature proposals ### Feature proposals
To create a feature proposal for CE, open an issue on the This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
[issue tracker of CE][ce-tracker].
For feature proposals for EE, open an issue on the
[issue tracker of EE][ee-tracker].
In order to help track the feature proposals, we have created a
[`feature proposal`][fpl] label. For the time being, users that are not members
of the project cannot add labels. You can instead ask one of the [core team]
members to add the label ~"feature proposal" to the issue or add the following
code snippet right after your description in a new line: `~"feature proposal"`.
Please keep feature proposals as small and simple as possible, complex ones
might be edited to make them small and simple.
Please submit Feature Proposals using the ['Feature Proposal' issue template](.gitlab/issue_templates/Feature Proposal.md) provided on the issue tracker.
For changes in the interface, it is helpful to include a mockup. Issues that add to, or change, the interface should
be given the ~"UX" label. This will allow the UX team to provide input and guidance. You may
need to ask one of the [core team] members to add the label, if you do not have permissions to do it by yourself.
If you want to create something yourself, consider opening an issue first to
discuss whether it is interesting to include this in GitLab.
### Issue tracker guidelines ### Issue tracker guidelines
**[Search the issue tracker][ce-tracker]** for similar entries before This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
submitting your own, there's a good chance somebody else had the same issue or
feature proposal. Show your support with an award emoji and/or join the
discussion.
Please submit bugs using the ['Bug' issue template](.gitlab/issue_templates/Bug.md) provided on the issue tracker.
The text in the parenthesis is there to help you with what to include. Omit it
when submitting the actual issue. You can copy-paste it and then edit as you
see fit.
### Issue weight ### Issue weight
Issue weight allows us to get an idea of the amount of work required to solve This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
one or multiple issues. This makes it possible to schedule work more accurately.
You are encouraged to set the weight of any issue. Following the guidelines
below will make it easy to manage this, without unnecessary overhead.
1. Set weight for any issue at the earliest possible convenience
1. If you don't agree with a set weight, discuss with other developers until
consensus is reached about the weight
1. Issue weights are an abstract measurement of complexity of the issue. Do not
relate issue weight directly to time. This is called [anchoring](https://en.wikipedia.org/wiki/Anchoring)
and something you want to avoid.
1. Something that has a weight of 1 (or no weight) is really small and simple.
Something that is 9 is rewriting a large fundamental part of GitLab,
which might lead to many hard problems to solve. Changing some text in GitLab
is probably 1, adding a new Git Hook maybe 4 or 5, big features 7-9.
1. If something is very large, it should probably be split up in multiple
issues or chunks. You can simply not set the weight of a parent issue and set
weights to children issues.
### Regression issues
Every monthly release has a corresponding issue on the CE issue tracker to keep
track of functionality broken by that release and any fixes that need to be
included in a patch release (see [8.3 Regressions] as an example).
As outlined in the issue description, the intended workflow is to post one note ### Regression issues
with a reference to an issue describing the regression, and then to update that
note with a reference to the merge request that fixes it as it becomes available.
If you're a contributor who doesn't have the required permissions to update
other users' notes, please post a new note with a reference to both the issue
and the merge request.
The release manager will [update the notes] in the regression issue as fixes are This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
addressed.
[8.3 Regressions]: https://gitlab.com/gitlab-org/gitlab-ce/issues/4127
[update the notes]: https://gitlab.com/gitlab-org/release-tools/blob/master/doc/pro-tips.md#update-the-regression-issue
### Technical and UX debt ### Technical and UX debt
In order to track things that can be improved in GitLab's codebase, This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
we use the ~"technical debt" label in [GitLab's issue tracker][ce-tracker].
For user experience improvements, we use the ~"UX debt" label.
These labels should be added to issues that describe things that can be improved,
shortcuts that have been taken, features that need additional attention, and all
other things that have been left behind due to high velocity of development.
For example, code that needs refactoring should use the ~"technical debt" label,
user experience refinements should use the ~"UX debt" label.
Everyone can create an issue, though you may need to ask for adding a specific
label, if you do not have permissions to do it by yourself. Additional labels
can be combined with these labels, to make it easier to schedule
the improvements for a release.
Issues tagged with these labels have the same priority like issues
that describe a new feature to be introduced in GitLab, and should be scheduled
for a release by the appropriate person.
Make sure to mention the merge request that the ~"technical debt" issue or
~"UX debt" issue is associated with in the description of the issue.
### Stewardship ### Stewardship
For issues related to the open source stewardship of GitLab, This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
there is the ~"stewardship" label.
This label is to be used for issues in which the stewardship of GitLab
is a topic of discussion. For instance if GitLab Inc. is planning to add
features from GitLab EE to GitLab CE, related issues would be labelled with
~"stewardship".
A recent example of this was the issue for
[bringing the time tracking API to GitLab CE][time-tracking-issue].
[time-tracking-issue]: https://gitlab.com/gitlab-org/gitlab-ce/issues/25517#note_20019084
## Merge requests ## Merge requests
We welcome merge requests with fixes and improvements to GitLab code, tests, This [documentation](doc/development/contributing/merge_request_workflow.md) has been moved.
and/or documentation. The issues that are specifically suitable for
community contributions are listed with the label
[`Accepting Merge Requests` on our issue tracker for CE][accepting-mrs-ce]
and [EE][accepting-mrs-ee], but you are free to contribute to any other issue
you want.
Please note that if an issue is marked for the current milestone either before
or while you are working on it, a team member may take over the merge request
in order to ensure the work is finished before the release date.
If you want to add a new feature that is not labeled it is best to first create
a feedback issue (if there isn't one already) and leave a comment asking for it
to be marked as `Accepting Merge Requests`. Please include screenshots or
wireframes if the feature will also change the UI.
Merge requests should be opened at [GitLab.com][gitlab-mr-tracker].
If you are new to GitLab development (or web development in general), see the
[I want to contribute!](#i-want-to-contribute) section to get you started with
some potentially easy issues.
To start with GitLab development download the [GitLab Development Kit][gdk] and
see the [Development section](doc/development/README.md) for some guidelines.
### Merge request guidelines ### Merge request guidelines
If you can, please submit a merge request with the fix or improvements This [documentation](doc/development/contributing/merge_request_workflow.md) has been moved.
including tests. If you don't know how to fix the issue but can write a test
that exposes the issue we will accept that as well. In general bug fixes that
include a regression test are merged quickly while new features without proper
tests are least likely to receive timely feedback. The workflow to make a merge
request is as follows:
1. Fork the project into your personal space on GitLab.com
1. Create a feature branch, branch away from `master`
1. Write [tests](https://docs.gitlab.com/ee/development/rake_tasks.html#run-tests) and code
1. [Generate a changelog entry with `bin/changelog`][changelog]
1. If you are writing documentation, make sure to follow the
[documentation guidelines][doc-guidelines]
1. If you have multiple commits please combine them into a few logically
organized commits by [squashing them][git-squash]
1. Push the commit(s) to your fork
1. Submit a merge request (MR) to the `master` branch
1. Your merge request needs at least 1 approval but feel free to require more.
For instance if you're touching backend and frontend code, it's a good idea
to require 2 approvals: 1 from a backend maintainer and 1 from a frontend
maintainer
1. You don't have to select any approvers, but you can if you really want
specific people to approve your merge request
1. The MR title should describe the change you want to make
1. The MR description should give a motive for your change and the method you
used to achieve it.
1. If you are contributing code, fill in the template already provided in the
"Description" field.
1. If you are contributing documentation, choose `Documentation` from the
"Choose a template" menu and fill in the template.
1. Mention the issue(s) your merge request solves, using the `Solves #XXX` or
`Closes #XXX` syntax to auto-close the issue(s) once the merge request will
be merged.
1. If you're allowed to, set a relevant milestone and labels
1. If the MR changes the UI it should include *Before* and *After* screenshots
1. If the MR changes CSS classes please include the list of affected pages,
`grep css-class ./app -R`
1. Be prepared to answer questions and incorporate feedback even if requests
for this arrive weeks or months after your MR submission
1. If a discussion has been addressed, select the "Resolve discussion" button
beneath it to mark it resolved.
1. If your MR touches code that executes shell commands, reads or opens files or
handles paths to files on disk, make sure it adheres to the
[shell command guidelines](doc/development/shell_commands.md)
1. If your code creates new files on disk please read the
[shared files guidelines](doc/development/shared_files.md).
1. When writing commit messages please follow
[these](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
[guidelines](http://chris.beams.io/posts/git-commit/).
1. If your merge request adds one or more migrations, make sure to execute all
migrations on a fresh database before the MR is reviewed. If the review leads
to large changes in the MR, do this again once the review is complete.
1. For more complex migrations, write tests.
1. Merge requests **must** adhere to the [merge request performance
guidelines](doc/development/merge_request_performance_guidelines.md).
1. For tests that use Capybara or PhantomJS, see this [article on how
to write reliable asynchronous tests](https://robots.thoughtbot.com/write-reliable-asynchronous-integration-tests-with-capybara).
Please keep the change in a single MR **as small as possible**. If you want to
contribute a large feature think very hard what the minimum viable change is.
Can you split the functionality? Can you only submit the backend/API code? Can
you start with a very simple UI? Can you do part of the refactor? The increased
reviewability of small MRs that leads to higher code quality is more important
to us than having a minimal commit log. The smaller an MR is the more likely it
is it will be merged (quickly). After that you can send more MRs to enhance it.
The ['How to get faster PR reviews' document of Kubernetes](https://github.com/kubernetes/community/blob/master/contributors/devel/faster_reviews.md) also has some great points regarding this.
For examples of feedback on merge requests please look at already
[closed merge requests][closed-merge-requests]. If you would like quick feedback
on your merge request feel free to mention someone from the [core team] or one
of the [Merge request coaches][team].
Please ensure that your merge request meets the contribution acceptance criteria.
When having your code reviewed and when reviewing merge requests please take the
[code review guidelines](doc/development/code_review.md) into account.
### Contribution acceptance criteria
1. The change is as small as possible
1. Include proper tests and make all tests pass (unless it contains a test
exposing a bug in existing code). Every new class should have corresponding
unit tests, even if the class is exercised at a higher level, such as a feature test.
1. If you suspect a failing CI build is unrelated to your contribution, you may
try and restart the failing CI job or ask a developer to fix the
aforementioned failing test
1. Your MR initially contains a single commit (please use `git rebase -i` to
squash commits)
1. Your changes can merge without problems (if not please rebase if you're the
only one working on your feature branch, otherwise, merge `master`)
1. Does not break any existing functionality
1. Fixes one specific issue or implements one specific feature (do not combine
things, send separate merge requests if needed)
1. Migrations should do only one thing (e.g., either create a table, move data
to a new table or remove an old table) to aid retrying on failure
1. Keeps the GitLab code base clean and well structured
1. Contains functionality we think other users will benefit from too
1. Doesn't add configuration options or settings options since they complicate
making and testing future changes
1. Changes do not adversely degrade performance.
- Avoid repeated polling of endpoints that require a significant amount of overhead
- Check for N+1 queries via the SQL log or [`QueryRecorder`](https://docs.gitlab.com/ce/development/merge_request_performance_guidelines.html)
- Avoid repeated access of filesystem
1. If you need polling to support real-time features, please use
[polling with ETag caching][polling-etag].
1. Changes after submitting the merge request should be in separate commits
(no squashing).
1. It conforms to the [style guides](#style-guides) and the following:
- If your change touches a line that does not follow the style, modify the
entire line to follow it. This prevents linting tools from generating warnings.
- Don't touch neighbouring lines. As an exception, automatic mass
refactoring modifications may leave style non-compliant.
1. If the merge request adds any new libraries (gems, JavaScript libraries,
etc.), they should conform to our [Licensing guidelines][license-finder-doc].
See the instructions in that document for help if your MR fails the
"license-finder" test with a "Dependencies that need approval" error.
1. The merge request meets the [definition of done](#definition-of-done).
## Definition of done
If you contribute to GitLab please know that changes involve more than just
code. We have the following [definition of done][definition-of-done]. Please ensure you support
the feature you contribute through all of these steps.
1. Description explaining the relevancy (see following item)
1. Working and clean code that is commented where needed
1. [Unit, integration, and system tests][testing] that pass on the CI server
1. Performance/scalability implications have been considered, addressed, and tested
1. [Documented][doc-guidelines] in the `/doc` directory
1. [Changelog entry added][changelog], if necessary
1. Reviewed and any concerns are addressed
1. Merged by a project maintainer
1. Added to the release blog article, if relevant
1. Added to [the website](https://gitlab.com/gitlab-com/www-gitlab-com/), if relevant
1. Community questions answered
1. Answers to questions radiated (in docs/wiki/support etc.)
If you add a dependency in GitLab (such as an operating system package) please
consider updating the following and note the applicability of each in your
merge request:
1. Note the addition in the release blog post (create one if it doesn't exist yet) https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/
1. Upgrade guide, for example https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/7.5-to-7.6.md
1. Upgrader https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/upgrader.md#2-run-gitlab-upgrade-tool
1. Installation guide https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies
1. GitLab Development Kit https://gitlab.com/gitlab-org/gitlab-development-kit
1. Test suite https://gitlab.com/gitlab-org/gitlab-ce/blob/master/scripts/prepare_build.sh
1. Omnibus package creator https://gitlab.com/gitlab-org/omnibus-gitlab
## Style guides ### Contribution acceptance criteria
1. [Ruby](https://github.com/bbatsov/ruby-style-guide).
Important sections include [Source Code Layout][rss-source] and
[Naming][rss-naming]. Use:
- multi-line method chaining style **Option A**: dot `.` on the second line
- string literal quoting style **Option A**: single quoted by default
1. [Rails](https://github.com/bbatsov/rails-style-guide)
1. [Newlines styleguide][newlines-styleguide]
1. [Testing][testing]
1. [JavaScript styleguide][js-styleguide]
1. [SCSS styleguide][scss-styleguide]
1. [Shell commands](doc/development/shell_commands.md) created by GitLab
contributors to enhance security
1. [Database Migrations](doc/development/migration_style_guide.md)
1. [Markdown](http://www.cirosantilli.com/markdown-styleguide)
1. [Documentation styleguide](https://docs.gitlab.com/ee/development/documentation/styleguide.html)
1. Interface text should be written subjectively instead of objectively. It
should be the GitLab core team addressing a person. It should be written in
present time and never use past tense (has been/was). For example instead
of _prohibited this user from being saved due to the following errors:_ the
text should be _sorry, we could not create your account because:_
1. Code should be written in [US English][us-english]
This is also the style used by linting tools such as
[RuboCop](https://github.com/bbatsov/rubocop),
[PullReview](https://www.pullreview.com/) and [Hound CI](https://houndci.com).
## Code of conduct
As contributors and maintainers of this project, we pledge to respect all
people who contribute through reporting issues, posting feature requests,
updating documentation, submitting pull requests or patches, and other
activities.
We are committed to making participation in this project a harassment-free
experience for everyone, regardless of level of experience, gender, gender
identity and expression, sexual orientation, disability, personal appearance,
body size, race, ethnicity, age, or religion.
Examples of unacceptable behavior by participants include the use of sexual
language or imagery, derogatory comments or personal attacks, trolling, public
or private harassment, insults, or other unprofessional conduct.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct. Project maintainers who do not
follow the Code of Conduct may be removed from the project team.
This code of conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior can be
reported by emailing `contact@gitlab.com`.
This Code of Conduct is adapted from the [Contributor Covenant][contributor-covenant], version 1.1.0,
available at [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/).
## Contribution Flow
When contributing to GitLab, your merge request is subject to review by merge request maintainers of a particular specialty.
When you submit code to GitLab, we really want it to get merged, but there will be times when it will not be merged.
When maintainers are reading through a merge request they may request guidance from other maintainers. If merge request maintainers conclude that the code should not be merged, our reasons will be fully disclosed. If it has been decided that the code quality is not up to GitLab’s standards, the merge request maintainer will refer the author to our docs and code style guides, and provide some guidance. This [documentation](doc/development/contributing/merge_request_workflow.md) has been moved.
Sometimes style guides will be followed but the code will lack structural integrity, or the maintainer will have reservations about the code’s overall quality. When there is a reservation the maintainer will inform the author and provide some guidance. The author may then choose to update the merge request. Once the merge request has been updated and reassigned to the maintainer, they will review the code again. Once the code has been resubmitted any number of times, the maintainer may choose to close the merge request with a summary of why it will not be merged, as well as some guidance. If the merge request is closed the maintainer will be open to discussion as to how to improve the code so it can be approved in the future.
GitLab will do its best to review community contributions as quickly as possible. Specially appointed developers review community contributions daily. You may take a look at the [team page](https://about.gitlab.com/team/) for the merge request coach who specializes in the type of code you have written and mention them in the merge request. For example, if you have written some JavaScript in your code then you should mention the frontend merge request coach. If your code has multiple disciplines you may mention multiple merge request coaches. ## Definition of done
GitLab receives a lot of community contributions, so if your code has not been reviewed within 4 days of its initial submission feel free to re-mention the appropriate merge request coach. This [documentation](doc/development/contributing/merge_request_workflow.md)) has been moved.
When submitting code to GitLab, you may feel that your contribution requires the aid of an external library. If your code includes an external library please provide a link to the library, as well as reasons for including it.
When your code contains more than 500 changes, any major breaking changes, or an external library, `@mention` a maintainer in the merge request. If you are not sure who to mention, the reviewer will add one early in the merge request process. ## Style guides
[core team]: https://about.gitlab.com/core-team/ This [documentation](doc/development/contributing/design.md) has been moved.
[team]: https://about.gitlab.com/team/
[getting-help]: https://about.gitlab.com/getting-help/
[codetriage]: http://www.codetriage.com/gitlabhq/gitlabhq
[accepting-mrs-weight]: https://gitlab.com/gitlab-org/gitlab-ce/issues?assignee_id=0&label_name[]=Accepting%20Merge%20Requests&sort=weight_asc
[ce-tracker]: https://gitlab.com/gitlab-org/gitlab-ce/issues
[ee-tracker]: https://gitlab.com/gitlab-org/gitlab-ee/issues
[google-group]: https://groups.google.com/forum/#!forum/gitlabhq
[stackoverflow]: https://stackoverflow.com/questions/tagged/gitlab
[fpl]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=feature+proposal
[accepting-mrs-ce]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=Accepting+Merge+Requests
[accepting-mrs-ee]: https://gitlab.com/gitlab-org/gitlab-ee/issues?label_name=Accepting+Merge+Requests
[gitlab-mr-tracker]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests
[gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit
[git-squash]: https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits
[closed-merge-requests]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests?assignee_id=&label_name=&milestone_id=&scope=&sort=&state=closed
[definition-of-done]: http://guide.agilealliance.org/guide/definition-of-done.html
[contributor-covenant]: http://contributor-covenant.org
[rss-source]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#source-code-layout
[rss-naming]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#naming
[changelog]: doc/development/changelog.md "Generate a changelog entry"
[doc-guidelines]: doc/development/documentation/index.md "Documentation guidelines"
[js-styleguide]: doc/development/fe_guide/style_guide_js.md "JavaScript styleguide"
[scss-styleguide]: doc/development/fe_guide/style_guide_scss.md "SCSS styleguide"
[newlines-styleguide]: doc/development/newlines_styleguide.md "Newlines styleguide"
[UX Guide for GitLab]: http://docs.gitlab.com/ce/development/ux_guide/
[license-finder-doc]: doc/development/licensing.md
[GitLab Inc engineering workflow]: https://about.gitlab.com/handbook/engineering/workflow/#labelling-issues
[polling-etag]: https://docs.gitlab.com/ce/development/polling.html
[testing]: doc/development/testing_guide/index.md
[us-english]: https://en.wikipedia.org/wiki/American_English
...@@ -123,7 +123,7 @@ GEM ...@@ -123,7 +123,7 @@ GEM
numerizer (~> 0.1.1) numerizer (~> 0.1.1)
chunky_png (1.3.5) chunky_png (1.3.5)
citrus (3.0.2) citrus (3.0.2)
coderay (1.1.1) coderay (1.1.2)
coercible (1.0.0) coercible (1.0.0)
descendants_tracker (~> 0.0.1) descendants_tracker (~> 0.0.1)
commonmarker (0.17.8) commonmarker (0.17.8)
...@@ -494,7 +494,7 @@ GEM ...@@ -494,7 +494,7 @@ GEM
memoist (0.16.0) memoist (0.16.0)
memoizable (0.4.2) memoizable (0.4.2)
thread_safe (~> 0.3, >= 0.3.1) thread_safe (~> 0.3, >= 0.3.1)
method_source (0.8.2) method_source (0.9.0)
mime-types (3.1) mime-types (3.1)
mime-types-data (~> 3.2015) mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521) mime-types-data (3.2016.0521)
...@@ -636,12 +636,11 @@ GEM ...@@ -636,12 +636,11 @@ GEM
unparser unparser
procto (0.0.3) procto (0.0.3)
prometheus-client-mmap (0.9.4) prometheus-client-mmap (0.9.4)
pry (0.10.4) pry (0.11.3)
coderay (~> 1.1.0) coderay (~> 1.1.0)
method_source (~> 0.8.1) method_source (~> 0.9.0)
slop (~> 3.4) pry-byebug (3.4.3)
pry-byebug (3.4.2) byebug (>= 9.0, < 9.1)
byebug (~> 9.0)
pry (~> 0.10) pry (~> 0.10)
pry-rails (0.3.5) pry-rails (0.3.5)
pry (>= 0.9.10) pry (>= 0.9.10)
...@@ -872,7 +871,6 @@ GEM ...@@ -872,7 +871,6 @@ GEM
simplecov-html (~> 0.10.0) simplecov-html (~> 0.10.0)
simplecov-html (0.10.0) simplecov-html (0.10.0)
slack-notifier (1.5.1) slack-notifier (1.5.1)
slop (3.6.0)
spring (2.0.1) spring (2.0.1)
activesupport (>= 4.2) activesupport (>= 4.2)
spring-commands-rspec (1.0.4) spring-commands-rspec (1.0.4)
...@@ -1207,4 +1205,4 @@ DEPENDENCIES ...@@ -1207,4 +1205,4 @@ DEPENDENCIES
wikicloth (= 0.8.1) wikicloth (= 0.8.1)
BUNDLED WITH BUNDLED WITH
1.16.2 1.16.3
...@@ -117,7 +117,7 @@ router.beforeEach((to, from, next) => { ...@@ -117,7 +117,7 @@ router.beforeEach((to, from, next) => {
mergeRequestId: to.params.mrid, mergeRequestId: to.params.mrid,
}) })
.then(mr => { .then(mr => {
store.dispatch('updateActivityBarView', activityBarViews.review); store.dispatch('setCurrentBranchId', mr.source_branch);
store.dispatch('getBranchData', { store.dispatch('getBranchData', {
projectId: fullProjectId, projectId: fullProjectId,
...@@ -144,6 +144,10 @@ router.beforeEach((to, from, next) => { ...@@ -144,6 +144,10 @@ router.beforeEach((to, from, next) => {
}), }),
) )
.then(mrChanges => { .then(mrChanges => {
if (mrChanges.changes.length) {
store.dispatch('updateActivityBarView', activityBarViews.review);
}
mrChanges.changes.forEach((change, ind) => { mrChanges.changes.forEach((change, ind) => {
const changeTreeEntry = store.state.entries[change.new_path]; const changeTreeEntry = store.state.entries[change.new_path];
......
...@@ -54,9 +54,6 @@ export const setFileActive = ({ commit, state, getters, dispatch }, path) => { ...@@ -54,9 +54,6 @@ export const setFileActive = ({ commit, state, getters, dispatch }, path) => {
commit(types.SET_FILE_ACTIVE, { path, active: true }); commit(types.SET_FILE_ACTIVE, { path, active: true });
dispatch('scrollToTab'); dispatch('scrollToTab');
commit(types.SET_CURRENT_PROJECT, file.projectId);
commit(types.SET_CURRENT_BRANCH, file.branchId);
}; };
export const getFileData = ({ state, commit, dispatch }, { path, makeFileActive = true }) => { export const getFileData = ({ state, commit, dispatch }, { path, makeFileActive = true }) => {
......
import initForm from '../form'; import initForm from '../form';
import MirrorRepos from './mirror_repos';
document.addEventListener('DOMContentLoaded', initForm); document.addEventListener('DOMContentLoaded', () => {
initForm();
const mirrorReposContainer = document.querySelector('.js-mirror-settings');
if (mirrorReposContainer) new MirrorRepos(mirrorReposContainer).init();
});
import $ from 'jquery';
import _ from 'underscore';
import { __ } from '~/locale';
import Flash from '~/flash';
import axios from '~/lib/utils/axios_utils';
export default class MirrorRepos {
constructor(container) {
this.$container = $(container);
this.$form = $('.js-mirror-form', this.$container);
this.$urlInput = $('.js-mirror-url', this.$form);
this.$protectedBranchesInput = $('.js-mirror-protected', this.$form);
this.$table = $('.js-mirrors-table-body', this.$container);
this.mirrorEndpoint = this.$form.data('projectMirrorEndpoint');
}
init() {
this.initMirrorPush();
this.registerUpdateListeners();
}
initMirrorPush() {
this.$passwordGroup = $('.js-password-group', this.$container);
this.$password = $('.js-password', this.$passwordGroup);
this.$authMethod = $('.js-auth-method', this.$form);
this.$authMethod.on('change', () => this.togglePassword());
this.$password.on('input.updateUrl', () => this.debouncedUpdateUrl());
}
updateUrl() {
let val = this.$urlInput.val();
if (this.$password) {
const password = this.$password.val();
if (password) val = val.replace('@', `:${password}@`);
}
$('.js-mirror-url-hidden', this.$form).val(val);
}
updateProtectedBranches() {
const val = this.$protectedBranchesInput.get(0).checked
? this.$protectedBranchesInput.val()
: '0';
$('.js-mirror-protected-hidden', this.$form).val(val);
}
registerUpdateListeners() {
this.debouncedUpdateUrl = _.debounce(() => this.updateUrl(), 200);
this.$urlInput.on('input', () => this.debouncedUpdateUrl());
this.$protectedBranchesInput.on('change', () => this.updateProtectedBranches());
this.$table.on('click', '.js-delete-mirror', event => this.deleteMirror(event));
}
togglePassword() {
const isPassword = this.$authMethod.val() === 'password';
if (!isPassword) {
this.$password.val('');
this.updateUrl();
}
this.$passwordGroup.collapse(isPassword ? 'show' : 'hide');
}
deleteMirror(event, existingPayload) {
const $target = $(event.currentTarget);
let payload = existingPayload;
if (!payload) {
payload = {
project: {
remote_mirrors_attributes: {
id: $target.data('mirrorId'),
enabled: 0,
},
},
};
}
return axios
.put(this.mirrorEndpoint, payload)
.then(() => this.removeRow($target))
.catch(() => Flash(__('Failed to remove mirror.')));
}
/* eslint-disable class-methods-use-this */
removeRow($target) {
const row = $target.closest('tr');
$('.js-delete-mirror', row).tooltip('hide');
row.remove();
}
/* eslint-enable class-methods-use-this */
}
<script> <script>
import { mapActions, mapGetters, mapState } from 'vuex'; import { mapActions, mapGetters, mapState } from 'vuex';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import { componentNames } from '~/vue_shared/components/reports/issue_body'; import { componentNames } from './issue_body';
import ReportSection from '~/vue_shared/components/reports/report_section.vue'; import ReportSection from './report_section.vue';
import SummaryRow from '~/vue_shared/components/reports/summary_row.vue'; import SummaryRow from './summary_row.vue';
import IssuesList from '~/vue_shared/components/reports/issues_list.vue'; import IssuesList from './issues_list.vue';
import Modal from './modal.vue'; import Modal from './modal.vue';
import createStore from '../store'; import createStore from '../store';
import { summaryTextBuilder, reportTextBuilder, statusIcon } from '../store/utils'; import { summaryTextBuilder, reportTextBuilder, statusIcon } from '../store/utils';
......
import TestIssueBody from '~/reports/components/test_issue_body.vue'; import TestIssueBody from './test_issue_body.vue';
export const components = { export const components = {
TestIssueBody, TestIssueBody,
......
<script> <script>
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import { import {
STATUS_FAILED, STATUS_FAILED,
STATUS_NEUTRAL, STATUS_NEUTRAL,
STATUS_SUCCESS, STATUS_SUCCESS,
} from '~/vue_shared/components/reports/constants'; } from '../constants';
export default { export default {
name: 'IssueStatusIcon', name: 'IssueStatusIcon',
......
<script> <script>
import IssuesBlock from '~/vue_shared/components/reports/report_issues.vue'; import IssuesBlock from './report_issues.vue';
import { import {
STATUS_SUCCESS, STATUS_SUCCESS,
STATUS_FAILED, STATUS_FAILED,
STATUS_NEUTRAL, STATUS_NEUTRAL,
} from '~/vue_shared/components/reports/constants'; } from '../constants';
/** /**
* Renders block of issues * Renders block of issues
......
<script> <script>
import IssueStatusIcon from '~/vue_shared/components/reports/issue_status_icon.vue'; import IssueStatusIcon from './issue_status_icon.vue';
import { components, componentNames } from '~/vue_shared/components/reports/issue_body'; import { components, componentNames } from './issue_body';
export default { export default {
name: 'ReportIssues', name: 'ReportIssues',
......
<script> <script>
import { __ } from '~/locale'; import { __ } from '~/locale';
import StatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue'; import StatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue';
import Popover from '~/vue_shared/components/help_popover.vue';
import IssuesList from './issues_list.vue'; import IssuesList from './issues_list.vue';
import Popover from '../help_popover.vue';
const LOADING = 'LOADING'; const LOADING = 'LOADING';
const ERROR = 'ERROR'; const ERROR = 'ERROR';
......
<script> <script>
import CiIcon from '~/vue_shared/components/ci_icon.vue'; import CiIcon from '~/vue_shared/components/ci_icon.vue';
import LoadingIcon from '~/vue_shared/components/loading_icon.vue'; import LoadingIcon from '~/vue_shared/components/loading_icon.vue';
import Popover from '../help_popover.vue'; import Popover from '~/vue_shared/components/help_popover.vue';
/** /**
* Renders the summary row for each report * Renders the summary row for each report
......
...@@ -11,6 +11,8 @@ export const SUCCESS = 'SUCCESS'; ...@@ -11,6 +11,8 @@ export const SUCCESS = 'SUCCESS';
export const STATUS_FAILED = 'failed'; export const STATUS_FAILED = 'failed';
export const STATUS_SUCCESS = 'success'; export const STATUS_SUCCESS = 'success';
export const STATUS_NEUTRAL = 'neutral';
export const ICON_WARNING = 'warning'; export const ICON_WARNING = 'warning';
export const ICON_SUCCESS = 'success'; export const ICON_SUCCESS = 'success';
export const ICON_NOTFOUND = 'notfound'; export const ICON_NOTFOUND = 'notfound';
export const STATUS_FAILED = 'failed';
export const STATUS_SUCCESS = 'success';
export const STATUS_NEUTRAL = 'neutral';
...@@ -103,6 +103,7 @@ ...@@ -103,6 +103,7 @@
display: flex; display: flex;
a { a {
width: 100%;
display: flex; display: flex;
} }
......
...@@ -201,7 +201,7 @@ label { ...@@ -201,7 +201,7 @@ label {
} }
.gl-show-field-errors { .gl-show-field-errors {
.form-control { .form-control:not(textarea) {
height: 34px; height: 34px;
} }
......
...@@ -253,7 +253,7 @@ ...@@ -253,7 +253,7 @@
text-align: right; text-align: right;
padding: 0; padding: 0;
position: relative; position: relative;
top: -3px; margin: 0;
} }
.label-badge { .label-badge {
...@@ -274,6 +274,7 @@ ...@@ -274,6 +274,7 @@
.label-links { .label-links {
list-style: none; list-style: none;
margin: 0;
padding: 0; padding: 0;
white-space: nowrap; white-space: nowrap;
} }
......
...@@ -823,10 +823,6 @@ pre.light-well { ...@@ -823,10 +823,6 @@ pre.light-well {
.avatar-container { .avatar-container {
align-self: flex-start; align-self: flex-start;
> a {
width: 100%;
}
} }
.project-details { .project-details {
......
...@@ -301,3 +301,17 @@ ...@@ -301,3 +301,17 @@
margin-bottom: 0; margin-bottom: 0;
} }
} }
.mirror-error-badge {
background-color: $error-bg;
border-radius: $border-radius-default;
color: $white-light;
}
.push-pull-table {
margin-top: 1em;
.mirror-action-buttons {
padding-right: 0;
}
}
module AvatarsHelper module AvatarsHelper
def project_icon(project_id, options = {}) def project_icon(project_id, options = {})
project = source_icon(Project, project_id, options)
if project_id.respond_to?(:avatar_url)
project_id
else
Project.find_by_full_path(project_id)
end
if project.avatar_url
image_tag project.avatar_url, options
else # generated icon
project_identicon(project, options)
end end
end
def project_identicon(project, options = {})
bg_key = (project.id % 7) + 1
options[:class] ||= ''
options[:class] << ' identicon'
options[:class] << " bg#{bg_key}"
content_tag(:div, class: options[:class]) do def group_icon(group_id, options = {})
project.name[0, 1].upcase source_icon(Group, group_id, options)
end
end end
# Takes both user and email and returns the avatar_icon by # Takes both user and email and returns the avatar_icon by
...@@ -123,4 +105,32 @@ module AvatarsHelper ...@@ -123,4 +105,32 @@ module AvatarsHelper
mail_to(options[:user_email], avatar) mail_to(options[:user_email], avatar)
end end
end end
private
def source_icon(klass, source_id, options = {})
source =
if source_id.respond_to?(:avatar_url)
source_id
else
klass.find_by_full_path(source_id)
end
if source.avatar_url
image_tag source.avatar_url, options
else
source_identicon(source, options)
end
end
def source_identicon(source, options = {})
bg_key = (source.id % 7) + 1
options[:class] ||= ''
options[:class] << ' identicon'
options[:class] << " bg#{bg_key}"
content_tag(:div, class: options[:class].strip) do
source.name[0, 1].upcase
end
end
end end
...@@ -33,11 +33,6 @@ module GroupsHelper ...@@ -33,11 +33,6 @@ module GroupsHelper
.count .count
end end
def group_icon(group, options = {})
img_path = group_icon_url(group, options)
image_tag img_path, options
end
def group_icon_url(group, options = {}) def group_icon_url(group, options = {})
if group.is_a?(String) if group.is_a?(String)
group = Group.find_by_full_path(group) group = Group.find_by_full_path(group)
......
module MirrorHelper
def mirrors_form_data_attributes
{ project_mirror_endpoint: project_mirror_path(@project) }
end
end
...@@ -226,7 +226,7 @@ module Ci ...@@ -226,7 +226,7 @@ module Ci
end end
def cancelable? def cancelable?
active? active? || created?
end end
def retryable? def retryable?
......
# frozen_string_literal: true
class ProgrammingLanguage < ActiveRecord::Base class ProgrammingLanguage < ActiveRecord::Base
validates :name, presence: true validates :name, presence: true
validates :color, allow_blank: false, color: true validates :color, allow_blank: false, color: true
......
...@@ -470,6 +470,24 @@ class Project < ActiveRecord::Base ...@@ -470,6 +470,24 @@ class Project < ActiveRecord::Base
}x }x
end end
def reference_postfix
'>'
end
def reference_postfix_escaped
'&gt;'
end
# Pattern used to extract `namespace/project>` project references from text.
# '>' or its escaped form ('&gt;') are checked for because '>' is sometimes escaped
# when the reference comes from an external source.
def markdown_reference_pattern
%r{
#{reference_pattern}
(#{reference_postfix}|#{reference_postfix_escaped})
}x
end
def trending def trending
joins('INNER JOIN trending_projects ON projects.id = trending_projects.project_id') joins('INNER JOIN trending_projects ON projects.id = trending_projects.project_id')
.reorder('trending_projects.id ASC') .reorder('trending_projects.id ASC')
...@@ -908,6 +926,10 @@ class Project < ActiveRecord::Base ...@@ -908,6 +926,10 @@ class Project < ActiveRecord::Base
end end
end end
def to_reference_with_postfix
"#{to_reference(full: true)}#{self.class.reference_postfix}"
end
# `from` argument can be a Namespace or Project. # `from` argument can be a Namespace or Project.
def to_reference(from = nil, full: false) def to_reference(from = nil, full: false)
if full || cross_namespace_reference?(from) if full || cross_namespace_reference?(from)
......
# frozen_string_literal: true
require 'asana' require 'asana'
class AsanaService < Service class AsanaService < Service
......
# frozen_string_literal: true
class AssemblaService < Service class AssemblaService < Service
prop_accessor :token, :subdomain prop_accessor :token, :subdomain
validates :token, presence: true, if: :activated? validates :token, presence: true, if: :activated?
......
# frozen_string_literal: true
class BambooService < CiService class BambooService < CiService
include ReactiveService include ReactiveService
......
# frozen_string_literal: true
class BugzillaService < IssueTrackerService class BugzillaService < IssueTrackerService
validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated? validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated?
......
# frozen_string_literal: true
require "addressable/uri" require "addressable/uri"
class BuildkiteService < CiService class BuildkiteService < CiService
......
# frozen_string_literal: true
# This class is to be removed with 9.1 # This class is to be removed with 9.1
# We should also by then remove BuildsEmailService from database # We should also by then remove BuildsEmailService from database
class BuildsEmailService < Service class BuildsEmailService < Service
......
# frozen_string_literal: true
class CampfireService < Service class CampfireService < Service
prop_accessor :token, :subdomain, :room prop_accessor :token, :subdomain, :room
validates :token, presence: true, if: :activated? validates :token, presence: true, if: :activated?
...@@ -82,7 +84,7 @@ class CampfireService < Service ...@@ -82,7 +84,7 @@ class CampfireService < Service
before = push[:before] before = push[:before]
after = push[:after] after = push[:after]
message = "" message = []
message << "[#{project.full_name}] " message << "[#{project.full_name}] "
message << "#{push[:user_name]} " message << "#{push[:user_name]} "
...@@ -95,6 +97,6 @@ class CampfireService < Service ...@@ -95,6 +97,6 @@ class CampfireService < Service
message << "#{project.web_url}/compare/#{before}...#{after}" message << "#{project.web_url}/compare/#{before}...#{after}"
end end
message message.join
end end
end end
# frozen_string_literal: true
require 'slack-notifier' require 'slack-notifier'
module ChatMessage module ChatMessage
......
# frozen_string_literal: true
module ChatMessage module ChatMessage
class IssueMessage < BaseMessage class IssueMessage < BaseMessage
attr_reader :title attr_reader :title
......
# frozen_string_literal: true
module ChatMessage module ChatMessage
class MergeMessage < BaseMessage class MergeMessage < BaseMessage
attr_reader :merge_request_iid attr_reader :merge_request_iid
......
# frozen_string_literal: true
module ChatMessage module ChatMessage
class NoteMessage < BaseMessage class NoteMessage < BaseMessage
attr_reader :note attr_reader :note
......
# frozen_string_literal: true
module ChatMessage module ChatMessage
class PipelineMessage < BaseMessage class PipelineMessage < BaseMessage
attr_reader :ref_type attr_reader :ref_type
......
# frozen_string_literal: true
module ChatMessage module ChatMessage
class PushMessage < BaseMessage class PushMessage < BaseMessage
attr_reader :after attr_reader :after
......
# frozen_string_literal: true
module ChatMessage module ChatMessage
class WikiPageMessage < BaseMessage class WikiPageMessage < BaseMessage
attr_reader :title attr_reader :title
......
# frozen_string_literal: true
# Base class for Chat notifications services # Base class for Chat notifications services
# This class is not meant to be used directly, but only to inherit from. # This class is not meant to be used directly, but only to inherit from.
class ChatNotificationService < Service class ChatNotificationService < Service
......
# frozen_string_literal: true
# Base class for CI services # Base class for CI services
# List methods you need to implement to get your CI service # List methods you need to implement to get your CI service
# working with GitLab Merge Requests # working with GitLab Merge Requests
......
# frozen_string_literal: true
class CustomIssueTrackerService < IssueTrackerService class CustomIssueTrackerService < IssueTrackerService
validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated? validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated?
......
# frozen_string_literal: true
# Base class for deployment services # Base class for deployment services
# #
# These services integrate with a deployment solution like Kubernetes/OpenShift, # These services integrate with a deployment solution like Kubernetes/OpenShift,
......
# frozen_string_literal: true
class DroneCiService < CiService class DroneCiService < CiService
include ReactiveService include ReactiveService
......
# frozen_string_literal: true
class EmailsOnPushService < Service class EmailsOnPushService < Service
boolean_accessor :send_from_committer_email boolean_accessor :send_from_committer_email
boolean_accessor :disable_diffs boolean_accessor :disable_diffs
......
# frozen_string_literal: true
class ExternalWikiService < Service class ExternalWikiService < Service
prop_accessor :external_wiki_url prop_accessor :external_wiki_url
......
# frozen_string_literal: true
require "flowdock-git-hook" require "flowdock-git-hook"
# Flow dock depends on Grit to compute the number of commits between two given # Flow dock depends on Grit to compute the number of commits between two given
......
# frozen_string_literal: true
require "gemnasium/gitlab_service" require "gemnasium/gitlab_service"
class GemnasiumService < Service class GemnasiumService < Service
......
# frozen_string_literal: true
class GitlabIssueTrackerService < IssueTrackerService class GitlabIssueTrackerService < IssueTrackerService
include Gitlab::Routing include Gitlab::Routing
......
# frozen_string_literal: true
require 'hangouts_chat' require 'hangouts_chat'
class HangoutsChatService < ChatNotificationService class HangoutsChatService < ChatNotificationService
......
# frozen_string_literal: true
class HipchatService < Service class HipchatService < Service
include ActionView::Helpers::SanitizeHelper include ActionView::Helpers::SanitizeHelper
...@@ -108,7 +110,7 @@ class HipchatService < Service ...@@ -108,7 +110,7 @@ class HipchatService < Service
before = push[:before] before = push[:before]
after = push[:after] after = push[:after]
message = "" message = []
message << "#{push[:user_name]} " message << "#{push[:user_name]} "
if Gitlab::Git.blank_ref?(before) if Gitlab::Git.blank_ref?(before)
...@@ -132,7 +134,7 @@ class HipchatService < Service ...@@ -132,7 +134,7 @@ class HipchatService < Service
end end
end end
message message.join
end end
def markdown(text, options = {}) def markdown(text, options = {})
...@@ -165,11 +167,11 @@ class HipchatService < Service ...@@ -165,11 +167,11 @@ class HipchatService < Service
description = obj_attr[:description] description = obj_attr[:description]
issue_link = "<a href=\"#{issue_url}\">issue ##{issue_iid}</a>" issue_link = "<a href=\"#{issue_url}\">issue ##{issue_iid}</a>"
message = "#{user_name} #{state} #{issue_link} in #{project_link}: <b>#{title}</b>"
message = ["#{user_name} #{state} #{issue_link} in #{project_link}: <b>#{title}</b>"]
message << "<pre>#{markdown(description)}</pre>" message << "<pre>#{markdown(description)}</pre>"
message message.join
end end
def create_merge_request_message(data) def create_merge_request_message(data)
...@@ -184,12 +186,11 @@ class HipchatService < Service ...@@ -184,12 +186,11 @@ class HipchatService < Service
merge_request_url = "#{project_url}/merge_requests/#{merge_request_id}" merge_request_url = "#{project_url}/merge_requests/#{merge_request_id}"
merge_request_link = "<a href=\"#{merge_request_url}\">merge request !#{merge_request_id}</a>" merge_request_link = "<a href=\"#{merge_request_url}\">merge request !#{merge_request_id}</a>"
message = "#{user_name} #{state} #{merge_request_link} in " \ message = ["#{user_name} #{state} #{merge_request_link} in " \
"#{project_link}: <b>#{title}</b>" "#{project_link}: <b>#{title}</b>"]
message << "<pre>#{markdown(description)}</pre>" message << "<pre>#{markdown(description)}</pre>"
message.join
message
end end
def format_title(title) def format_title(title)
...@@ -235,12 +236,11 @@ class HipchatService < Service ...@@ -235,12 +236,11 @@ class HipchatService < Service
end end
subject_html = "<a href=\"#{note_url}\">#{subject_type} #{subject_desc}</a>" subject_html = "<a href=\"#{note_url}\">#{subject_type} #{subject_desc}</a>"
message = "#{user_name} commented on #{subject_html} in #{project_link}: " message = ["#{user_name} commented on #{subject_html} in #{project_link}: "]
message << title message << title
message << "<pre>#{markdown(note, ref: commit_id)}</pre>" message << "<pre>#{markdown(note, ref: commit_id)}</pre>"
message.join
message
end end
def create_pipeline_message(data) def create_pipeline_message(data)
......
# frozen_string_literal: true
require 'uri' require 'uri'
class IrkerService < Service class IrkerService < Service
......
# frozen_string_literal: true
class IssueTrackerService < Service class IssueTrackerService < Service
validate :one_issue_tracker, if: :activated?, on: :manual_change validate :one_issue_tracker, if: :activated?, on: :manual_change
......
# frozen_string_literal: true
class JiraService < IssueTrackerService class JiraService < IssueTrackerService
include Gitlab::Routing include Gitlab::Routing
include ApplicationHelper include ApplicationHelper
......
# frozen_string_literal: true
## ##
# NOTE: # NOTE:
# We'll move this class to Clusters::Platforms::Kubernetes, which contains exactly the same logic. # We'll move this class to Clusters::Platforms::Kubernetes, which contains exactly the same logic.
......
# frozen_string_literal: true
class MattermostService < ChatNotificationService class MattermostService < ChatNotificationService
def title def title
'Mattermost notifications' 'Mattermost notifications'
......
# frozen_string_literal: true
class MattermostSlashCommandsService < SlashCommandsService class MattermostSlashCommandsService < SlashCommandsService
include TriggersHelper include TriggersHelper
......
# frozen_string_literal: true
class MicrosoftTeamsService < ChatNotificationService class MicrosoftTeamsService < ChatNotificationService
def title def title
'Microsoft Teams Notification' 'Microsoft Teams Notification'
......
# frozen_string_literal: true
# For an example companion mocking service, see https://gitlab.com/gitlab-org/gitlab-mock-ci-service # For an example companion mocking service, see https://gitlab.com/gitlab-org/gitlab-mock-ci-service
class MockCiService < CiService class MockCiService < CiService
ALLOWED_STATES = %w[failed canceled running pending success success_with_warnings skipped not_found].freeze ALLOWED_STATES = %w[failed canceled running pending success success_with_warnings skipped not_found].freeze
......
# frozen_string_literal: true
class MockDeploymentService < DeploymentService class MockDeploymentService < DeploymentService
def title def title
'Mock deployment' 'Mock deployment'
......
# frozen_string_literal: true
class MockMonitoringService < MonitoringService class MockMonitoringService < MonitoringService
def title def title
'Mock monitoring' 'Mock monitoring'
......
# frozen_string_literal: true
# Base class for monitoring services # Base class for monitoring services
# #
# These services integrate with a deployment solution like Prometheus # These services integrate with a deployment solution like Prometheus
......
# frozen_string_literal: true
class PackagistService < Service class PackagistService < Service
prop_accessor :username, :token, :server prop_accessor :username, :token, :server
......
# frozen_string_literal: true
class PipelinesEmailService < Service class PipelinesEmailService < Service
prop_accessor :recipients prop_accessor :recipients
boolean_accessor :notify_only_broken_pipelines boolean_accessor :notify_only_broken_pipelines
......
# frozen_string_literal: true
class PivotaltrackerService < Service class PivotaltrackerService < Service
API_ENDPOINT = 'https://www.pivotaltracker.com/services/v5/source_commits'.freeze API_ENDPOINT = 'https://www.pivotaltracker.com/services/v5/source_commits'.freeze
......
# frozen_string_literal: true
class PrometheusService < MonitoringService class PrometheusService < MonitoringService
include PrometheusAdapter include PrometheusAdapter
......
# frozen_string_literal: true
class PushoverService < Service class PushoverService < Service
BASE_URI = 'https://api.pushover.net/1'.freeze BASE_URI = 'https://api.pushover.net/1'.freeze
...@@ -79,7 +81,7 @@ class PushoverService < Service ...@@ -79,7 +81,7 @@ class PushoverService < Service
end end
if data[:total_commits_count] > 0 if data[:total_commits_count] > 0
message << "\nTotal commits count: #{data[:total_commits_count]}" message = [message, "Total commits count: #{data[:total_commits_count]}"].join("\n")
end end
pushover_data = { pushover_data = {
......
# frozen_string_literal: true
class RedmineService < IssueTrackerService class RedmineService < IssueTrackerService
validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated? validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated?
......
# frozen_string_literal: true
class SlackService < ChatNotificationService class SlackService < ChatNotificationService
def title def title
'Slack notifications' 'Slack notifications'
......
# frozen_string_literal: true
class SlackSlashCommandsService < SlashCommandsService class SlackSlashCommandsService < SlashCommandsService
include TriggersHelper include TriggersHelper
......
# frozen_string_literal: true
# Base class for Chat services # Base class for Chat services
# This class is not meant to be used directly, but only to inherrit from. # This class is not meant to be used directly, but only to inherrit from.
class SlashCommandsService < Service class SlashCommandsService < Service
......
# frozen_string_literal: true
class TeamcityService < CiService class TeamcityService < CiService
include ReactiveService include ReactiveService
......
# frozen_string_literal: true
class ProtectedBranch::MergeAccessLevel < ActiveRecord::Base class ProtectedBranch::MergeAccessLevel < ActiveRecord::Base
include ProtectedBranchAccess include ProtectedBranchAccess
end end
# frozen_string_literal: true
class ProtectedBranch::PushAccessLevel < ActiveRecord::Base class ProtectedBranch::PushAccessLevel < ActiveRecord::Base
include ProtectedBranchAccess include ProtectedBranchAccess
end end
# frozen_string_literal: true
class ProtectedTag::CreateAccessLevel < ActiveRecord::Base class ProtectedTag::CreateAccessLevel < ActiveRecord::Base
include ProtectedTagAccess include ProtectedTagAccess
......
# frozen_string_literal: true
class RepositoryLanguage < ActiveRecord::Base class RepositoryLanguage < ActiveRecord::Base
belongs_to :project belongs_to :project
belongs_to :programming_language belongs_to :programming_language
......
# frozen_string_literal: true
class SiteStatistic < ActiveRecord::Base class SiteStatistic < ActiveRecord::Base
# prevents the creation of multiple rows # prevents the creation of multiple rows
default_value_for :id, 1 default_value_for :id, 1
......
# frozen_string_literal: true
module Storage module Storage
class HashedProject class HashedProject
attr_accessor :project attr_accessor :project
......
# frozen_string_literal: true
module Storage module Storage
class LegacyProject class LegacyProject
attr_accessor :project attr_accessor :project
......
class ProjectMirrorSerializer < BaseSerializer
entity ProjectMirrorEntity
end
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
.bordered-box.fork-thumbnail.text-center.prepend-left-default.append-right-default.prepend-top-default.append-bottom-default.forked .bordered-box.fork-thumbnail.text-center.prepend-left-default.append-right-default.prepend-top-default.append-bottom-default.forked
= link_to project_path(forked_project) do = link_to project_path(forked_project) do
- if /no_((\w*)_)*avatar/.match(avatar) - if /no_((\w*)_)*avatar/.match(avatar)
= project_identicon(namespace, class: "avatar s100 identicon") = project_icon(namespace, class: "avatar s100 identicon")
- else - else
.avatar-container.s100 .avatar-container.s100
= image_tag(avatar, class: "avatar s100") = image_tag(avatar, class: "avatar s100")
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
class: ("disabled has-tooltip" unless can_create_project), class: ("disabled has-tooltip" unless can_create_project),
title: (_('You have reached your project limit') unless can_create_project) do title: (_('You have reached your project limit') unless can_create_project) do
- if /no_((\w*)_)*avatar/.match(avatar) - if /no_((\w*)_)*avatar/.match(avatar)
= project_identicon(namespace, class: "avatar s100 identicon") = project_icon(namespace, class: "avatar s100 identicon")
- else - else
.avatar-container.s100 .avatar-container.s100
= image_tag(avatar, class: "avatar s100") = image_tag(avatar, class: "avatar s100")
......
.account-well.prepend-top-default.append-bottom-default .account-well.prepend-top-default.append-bottom-default
%ul %ul
%li %li
The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> or <code>git://</code>. = _('The repository must be accessible over <code>http://</code>,
%li <code>https://</code>, <code>ssh://</code> and <code>git://</code>.').html_safe
Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>. %li= _('Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>.').html_safe
%li %li= _('The update action will time out after 15 minutes. For big repositories, use a clone/push combination.')
The update action will time out after 10 minutes. For big repositories, use a clone/push combination. %li= _('The Git LFS objects will <strong>not</strong> be synced.').html_safe
%li %li
The Git LFS objects will <strong>not</strong> be synced. = _('This user will be the author of all events in the activity feed that are the result of an update,
like new branches being created or new commits being pushed to existing branches.')
- expanded = Rails.env.test?
- protocols = Gitlab::UrlSanitizer::ALLOWED_SCHEMES.join('|')
%section.settings.project-mirror-settings.js-mirror-settings.no-animate{ class: ('expanded' if expanded) }
.settings-header
%h4= _('Mirroring repositories')
%button.btn.js-settings-toggle
= expanded ? _('Collapse') : _('Expand')
%p
= _('Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically.')
= link_to _('Read more'), help_page_path('workflow/repository_mirroring'), target: '_blank'
.settings-content
= form_for @project, url: project_mirror_path(@project), html: { class: 'gl-show-field-errors js-mirror-form', autocomplete: 'false', data: mirrors_form_data_attributes } do |f|
.panel.panel-default
.panel-heading
%h3.panel-title= _('Mirror a repository')
.panel-body
%div= form_errors(@project)
.form-group.has-feedback
= label_tag :url, _('Git repository URL'), class: 'label-light'
= text_field_tag :url, nil, class: 'form-control js-mirror-url js-repo-url', placeholder: _('Input your repository URL'), required: true, pattern: "(#{protocols}):\/\/.+"
= render 'projects/mirrors/instructions'
= render 'projects/mirrors/mirror_repos_form', f: f
.form-check.append-bottom-10
= check_box_tag :only_protected_branches, '1', false, class: 'js-mirror-protected form-check-input'
= label_tag :only_protected_branches, _('Only mirror protected branches'), class: 'form-check-label'
= link_to icon('question-circle'), help_page_path('user/project/protected_branches')
.panel-footer
= f.submit _('Mirror repository'), class: 'btn btn-create', name: :update_remote_mirror
.panel.panel-default
.table-responsive
%table.table.push-pull-table
%thead
%tr
%th
= _('Mirrored repositories')
= render_if_exists 'projects/mirrors/mirrored_repositories_count'
%th= _('Direction')
%th= _('Last update')
%th
%th
%tbody.js-mirrors-table-body
= render_if_exists 'projects/mirrors/table_pull_row'
- @project.remote_mirrors.each_with_index do |mirror, index|
- if mirror.enabled
%tr
%td= mirror.safe_url
%td= _('Push')
%td= mirror.last_update_at.present? ? time_ago_with_tooltip(mirror.last_update_at) : _('Never')
%td
- if mirror.last_error.present?
.badge.mirror-error-badge{ data: { toggle: 'tooltip', html: 'true' }, title: html_escape(mirror.last_error.try(:strip)) }= _('Error')
%td.mirror-action-buttons
.btn-group.mirror-actions-group.pull-right{ role: 'group' }
= render 'shared/remote_mirror_update_button', remote_mirror: mirror
%button.js-delete-mirror.btn.btn-danger{ type: 'button', data: { mirror_id: mirror.id, toggle: 'tooltip', container: 'body' }, title: _('Remove') }= icon('trash-o')
- protocols = Gitlab::UrlSanitizer::ALLOWED_SCHEMES.join('|')
.form-group
= label_tag :mirror_direction, _('Mirror direction'), class: 'label-light'
= select_tag :mirror_direction, options_for_select([[_('Push'), 'push']]), class: 'form-control js-mirror-direction', disabled: true
= f.fields_for :remote_mirrors, @project.remote_mirrors.build do |rm_f|
= rm_f.hidden_field :enabled, value: '1'
= rm_f.hidden_field :url, class: 'js-mirror-url-hidden', required: true, pattern: "(#{protocols}):\/\/.+"
= rm_f.hidden_field :only_protected_branches, class: 'js-mirror-protected-hidden'
.form-group
= label_tag :auth_method, _('Authentication method'), class: 'label-bold'
= select_tag :auth_method, options_for_select([[_('None'), 'none'], [_('Password'), 'password']], 'none'), { class: "form-control js-auth-method" }
.form-group.js-password-group.collapse
= label_tag :password, _('Password'), class: 'label-bold'
= text_field_tag :password, '', class: 'form-control js-password'
- expanded = Rails.env.test?
%section.settings.no-animate#js-push-remote-settings{ class: ('expanded' if expanded) }
.settings-header
%h4
Push to a remote repository
%button.btn.js-settings-toggle
= expanded ? 'Collapse' : 'Expand'
%p
Set up the remote repository that you want to update with the content of the current repository
every time someone pushes to it.
= link_to 'Read more', help_page_path('workflow/repository_mirroring', anchor: 'pushing-to-a-remote-repository'), target: '_blank'
.settings-content
= form_for @project, url: project_mirror_path(@project) do |f|
%div
= form_errors(@project)
= render "shared/remote_mirror_update_button", remote_mirror: @remote_mirror
- if @remote_mirror.last_error.present?
.panel.panel-danger
.panel-heading
- if @remote_mirror.last_update_at
The remote repository failed to update #{time_ago_with_tooltip(@remote_mirror.last_update_at)}.
- else
The remote repository failed to update.
- if @remote_mirror.last_successful_update_at
Last successful update #{time_ago_with_tooltip(@remote_mirror.last_successful_update_at)}.
.panel-body
%pre
:preserve
#{h(@remote_mirror.last_error.strip)}
= f.fields_for :remote_mirrors, @remote_mirror do |rm_form|
.form-group
= rm_form.check_box :enabled, class: "float-left"
.prepend-left-20
= rm_form.label :enabled, "Remote mirror repository", class: "label-bold append-bottom-0"
%p.light.append-bottom-0
Automatically update the remote mirror's branches, tags, and commits from this repository every time someone pushes to it.
.form-group.has-feedback
= rm_form.label :url, "Git repository URL", class: "label-bold"
= rm_form.text_field :url, class: "form-control", placeholder: 'https://username:password@gitlab.company.com/group/project.git'
= render "projects/mirrors/instructions"
.form-group
= rm_form.check_box :only_protected_branches, class: 'float-left'
.prepend-left-20
= rm_form.label :only_protected_branches, class: 'label-bold'
= link_to icon('question-circle'), help_page_path('user/project/protected_branches')
= f.submit 'Save changes', class: 'btn btn-create', name: 'update_remote_mirror'
- if can?(current_user, :admin_remote_mirror, @project) = render 'projects/mirrors/mirror_repos'
= render 'projects/mirrors/push'
- if @project.has_remote_mirror? - if remote_mirror.update_in_progress?
.append-bottom-default %button.btn.disabled{ type: 'button', data: { toggle: 'tooltip', container: 'body' }, title: _('Updating') }
- if remote_mirror.update_in_progress?
%span.btn.disabled
= icon("refresh spin") = icon("refresh spin")
Updating&hellip; - else
- else = link_to update_now_project_mirror_path(@project, sync_remote: true), method: :post, class: "btn", data: { toggle: 'tooltip', container: 'body' }, title: _('Update now') do
= link_to update_now_project_mirror_path(@project, sync_remote: true), method: :post, class: "btn" do
= icon("refresh") = icon("refresh")
Update Now
- if @remote_mirror.last_successful_update_at
%p.inline.prepend-left-10
Successfully updated #{time_ago_with_tooltip(@remote_mirror.last_successful_update_at)}.
title: First Improvements made to the contributor on-boarding experience.
merge_request: 20682
author: Eddie Stubbington
type: added
---
title: Add the ability to reference projects in comments and other markdown text.
merge_request: 20285
author: Reuben Pereira
type: added
---
title: Allows to cancel a Created job
merge_request: 20635
author: Jacopo Beschi @jacopo-beschi
type: added
---
title: Add default avatar to group
merge_request: 17271
author: George Tsiolis
type: changed
---
title: Fix label list item container height when there is no label description
merge_request: 21106
author:
type: fixed
---
title: Enable frozen string in rest of app/models/**/*.rb
merge_request: gfyoung
author:
type: performance
---
title: Fix empty merge requests not opening in the Web IDE
merge_request: 21102
author:
type: fixed
---
title: Rails5 fix specs duplicate key value violates unique constraint 'index_gpg_signatures_on_commit_sha'
merge_request: 21119
author: Jasper Maes
type: fixed
# frozen_string_literal: true
module Db
module Fixtures
module Development
class SpamLog
def self.seed
Gitlab::Seeder.quiet do
(::SpamLog.default_per_page + 3).times do |i|
::SpamLog.create(
user: self.random_user,
user_agent: FFaker::Lorem.sentence,
source_ip: FFaker::Internet.ip_v4_address,
title: FFaker::Lorem.sentence,
description: FFaker::Lorem.paragraph,
via_api: FFaker::Boolean.random,
submitted_as_ham: FFaker::Boolean.random,
recaptcha_verified: FFaker::Boolean.random)
print '.'
end
end
end
def self.random_user
User.find(User.pluck(:id).sample)
end
end
end
end
end
Db::Fixtures::Development::SpamLog.seed
class AddMovedToToIssue < ActiveRecord::Migration class AddMovedToToIssue < ActiveRecord::Migration
def change def change
add_reference :issues, :moved_to, references: :issues add_reference :issues, :moved_to, references: :issues # rubocop:disable Migration/AddReference
end end
end end
...@@ -401,14 +401,13 @@ GET /api/v4/projects/1/branches/my%2Fbranch/commits ...@@ -401,14 +401,13 @@ GET /api/v4/projects/1/branches/my%2Fbranch/commits
## Encoding API parameters of `array` and `hash` types ## Encoding API parameters of `array` and `hash` types
When making an API call with parameters of type `array` and/or `hash`, the parameters may be We can call the API with `array` and `hash` types parameters as shown below:
specified as shown below.
### `array` ### `array`
`import_sources` is a parameter of type `array`: `import_sources` is a parameter of type `array`:
``` ```bash
curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" \ curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" \
-d "import_sources[]=github" \ -d "import_sources[]=github" \
-d "import_sources[]=bitbucket" \ -d "import_sources[]=bitbucket" \
...@@ -419,7 +418,7 @@ curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" \ ...@@ -419,7 +418,7 @@ curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" \
`override_params` is a parameter of type `hash`: `override_params` is a parameter of type `hash`:
``` ```bash
curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" \ curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" \
--form "namespace=email" \ --form "namespace=email" \
--form "path=impapi" \ --form "path=impapi" \
...@@ -429,6 +428,20 @@ curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" \ ...@@ -429,6 +428,20 @@ curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" \
https://gitlab.example.com/api/v4/projects/import https://gitlab.example.com/api/v4/projects/import
``` ```
### Array of hashes
`variables` is a parameter of type `array` containing hash key/value pairs `[{ 'key' => 'UPLOAD_TO_S3', 'value' => 'true' }]`:
```bash
curl --globoff --request POST --header "PRIVATE-TOKEN: ********************" \
"https://gitlab.example.com/api/v4/projects/169/pipeline?ref=master&variables[][key]=VAR1&variables[][value]=hello&variables[][key]=VAR2&variables[][value]=world"
curl --request POST --header "PRIVATE-TOKEN: ********************" \
--header "Content-Type: application/json" \
--data '{ "ref": "master", "variables": [ {"key": "VAR1", "value": "hello"}, {"key": "VAR2", "value": "world"} ] }' \
"https://gitlab.example.com/api/v4/projects/169/pipeline"
```
## `id` vs `iid` ## `id` vs `iid`
When you work with the API, you may notice two similar fields in API entities: When you work with the API, you may notice two similar fields in API entities:
......
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
- [Implement design & UI elements](#implement-design--ui-elements)
- [Style guides](#style-guides)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Implement design & UI elements
For guidance on UX implementation at GitLab, please refer to our [Design System](https://design.gitlab.com/).
The UX team uses labels to manage their workflow.
The ~"UX" label on an issue is a signal to the UX team that it will need UX attention.
To better understand the priority by which UX tackles issues, see the [UX section](https://about.gitlab.com/handbook/engineering/ux) of the handbook.
Once an issue has been worked on and is ready for development, a UXer removes the ~"UX" label and applies the ~"UX ready" label to that issue.
The UX team has a special type label called ~"design artifact". This label indicates that the final output
for an issue is a UX solution/design. The solution will be developed by frontend and/or backend in a subsequent milestone.
Any issue labeled ~"design artifact" should not also be labeled ~"frontend" or ~"backend" since no development is
needed until the solution has been decided.
~"design artifact" issues are like any other issue and should contain a milestone label, ~"Deliverable" or ~"Stretch", when scheduled in the current milestone.
To prevent the misunderstanding that a feature will be be delivered in the
assigned milestone, when only UX design is planned for that milestone, the
Product Manager should create a separate issue for the ~"design artifact",
assign the ~UX, ~"design artifact" and ~"Deliverable" labels, add a milestone
and use a title that makes it clear that the scheduled issue is design only
(e.g. `Design exploration for XYZ`).
When the ~"design artifact" issue has been completed, the UXer removes the ~UX
label, adds the ~"UX ready" label and closes the issue. This indicates the
design artifact is complete. The UXer will also copy the designs to related
issues for implementation in an upcoming milestone.
## Style guides
1. [Ruby](https://github.com/bbatsov/ruby-style-guide).
Important sections include [Source Code Layout][rss-source] and
[Naming][rss-naming]. Use:
- multi-line method chaining style **Option A**: dot `.` on the second line
- string literal quoting style **Option A**: single quoted by default
1. [Rails](https://github.com/bbatsov/rails-style-guide)
1. [Newlines styleguide][newlines-styleguide]
1. [Testing][testing]
1. [JavaScript styleguide][js-styleguide]
1. [SCSS styleguide][scss-styleguide]
1. [Shell commands](../shell_commands.md) created by GitLab
contributors to enhance security
1. [Database Migrations](../migration_style_guide.md)
1. [Markdown](http://www.cirosantilli.com/markdown-styleguide)
1. [Documentation styleguide](https://docs.gitlab.com/ee/development/documentation/styleguide.html)
1. Interface text should be written subjectively instead of objectively. It
should be the GitLab core team addressing a person. It should be written in
present time and never use past tense (has been/was). For example instead
of _prohibited this user from being saved due to the following errors:_ the
text should be _sorry, we could not create your account because:_
1. Code should be written in [US English][us-english]
This is also the style used by linting tools such as
[RuboCop](https://github.com/bbatsov/rubocop),
[PullReview](https://www.pullreview.com/) and [Hound CI](https://houndci.com).
---
[Return to Contributing documentation](index.md)
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
- [Contribute to GitLab](#contribute-to-gitlab)
- [Security vulnerability disclosure](#security-vulnerability-disclosure)
- [Code of conduct](#code-of-conduct)
- [Closing policy for issues and merge requests](#closing-policy-for-issues-and-merge-requests)
- [Helping others](#helping-others)
- [I want to contribute!](#i-want-to-contribute)
- [Contribution Flow](#contribution-flow)
- [Workflow labels](#workflow-labels)
- [Type labels](#type-labels)
- [Subject labels](#subject-labels)
- [Team labels](#team-labels)
- [Milestone labels](#milestone-labels)
- [Bug Priority labels](#bug-priority-labels)
- [Bug Severity labels](#bug-severity-labels)
- [Severity impact guidance](#severity-impact-guidance)
- [Label for community contributors](#label-for-community-contributors)
- [Implement design & UI elements](#implement-design--ui-elements)
- [Issue tracker](#issue-tracker)
- [Issue triaging](#issue-triaging)
- [Feature proposals](#feature-proposals)
- [Issue tracker guidelines](#issue-tracker-guidelines)
- [Issue weight](#issue-weight)
- [Regression issues](#regression-issues)
- [Technical and UX debt](#technical-and-ux-debt)
- [Stewardship](#stewardship)
- [Merge requests](#merge-requests)
- [Merge request guidelines](#merge-request-guidelines)
- [Contribution acceptance criteria](#contribution-acceptance-criteria)
- [Definition of done](#definition-of-done)
- [Style guides](#style-guides)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Contribute to GitLab
For a first-time step-by-step guide to the contribution process, see
["Contributing to GitLab"](https://about.gitlab.com/contributing/).
Thank you for your interest in contributing to GitLab. This guide details how
to contribute to GitLab in a way that is efficient for everyone.
Looking for something to work on? Look for issues with the label [Accepting Merge Requests](#i-want-to-contribute).
GitLab comes into two flavors, GitLab Community Edition (CE) our free and open
source edition, and GitLab Enterprise Edition (EE) which is our commercial
edition. Throughout this guide you will see references to CE and EE for
abbreviation.
If you have read this guide and want to know how the GitLab [core team]
operates please see [the GitLab contributing process](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/PROCESS.md).
- [GitLab Inc engineers should refer to the engineering workflow document](https://about.gitlab.com/handbook/engineering/workflow/)
## Security vulnerability disclosure
Please report suspected security vulnerabilities in private to
`support@gitlab.com`, also see the
[disclosure section on the GitLab.com website](https://about.gitlab.com/disclosure/).
Please do **NOT** create publicly viewable issues for suspected security
vulnerabilities.
## Code of conduct
As contributors and maintainers of this project, we pledge to respect all
people who contribute through reporting issues, posting feature requests,
updating documentation, submitting pull requests or patches, and other
activities.
We are committed to making participation in this project a harassment-free
experience for everyone, regardless of level of experience, gender, gender
identity and expression, sexual orientation, disability, personal appearance,
body size, race, ethnicity, age, or religion.
Examples of unacceptable behavior by participants include the use of sexual
language or imagery, derogatory comments or personal attacks, trolling, public
or private harassment, insults, or other unprofessional conduct.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct. Project maintainers who do not
follow the Code of Conduct may be removed from the project team.
This code of conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior can be
reported by emailing `contact@gitlab.com`.
This Code of Conduct is adapted from the [Contributor Covenant][contributor-covenant], version 1.1.0,
available at [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/).
## Closing policy for issues and merge requests
GitLab is a popular open source project and the capacity to deal with issues
and merge requests is limited. Out of respect for our volunteers, issues and
merge requests not in line with the guidelines listed in this document may be
closed without notice.
Please treat our volunteers with courtesy and respect, it will go a long way
towards getting your issue resolved.
Issues and merge requests should be in English and contain appropriate language
for audiences of all ages.
If a contributor is no longer actively working on a submitted merge request
we can decide that the merge request will be finished by one of our
[Merge request coaches][team] or close the merge request. We make this decision
based on how important the change is for our product vision. If a Merge request
coach is going to finish the merge request we assign the
~"coach will finish" label.
## Helping others
Please help other GitLab users when you can.
The methods people will use to seek help can be found on the [getting help page][getting-help].
Sign up for the mailing list, answer GitLab questions on StackOverflow or
respond in the IRC channel. You can also sign up on [CodeTriage][codetriage] to help with
the remaining issues on the GitHub issue tracker.
## I want to contribute!
If you want to contribute to GitLab [issues with the label `Accepting Merge Requests` and small weight][accepting-mrs-weight]
is a great place to start. Issues with a lower weight (1 or 2) are deemed
suitable for beginners. These issues will be of reasonable size and challenge,
for anyone to start contributing to GitLab. If you have any questions or need help visit [Getting Help](https://about.gitlab.com/getting-help/#discussion) to
learn how to communicate with GitLab. If you're looking for a Gitter or Slack channel
please consider we favor
[asynchronous communication](https://about.gitlab.com/handbook/communication/#internal-communication) over real time communication. Thanks for your contribution!
## Contribution Flow
When contributing to GitLab, your merge request is subject to review by merge request maintainers of a particular specialty.
When you submit code to GitLab, we really want it to get merged, but there will be times when it will not be merged.
When maintainers are reading through a merge request they may request guidance from other maintainers. If merge request maintainers conclude that the code should not be merged, our reasons will be fully disclosed. If it has been decided that the code quality is not up to GitLab’s standards, the merge request maintainer will refer the author to our docs and code style guides, and provide some guidance.
Sometimes style guides will be followed but the code will lack structural integrity, or the maintainer will have reservations about the code’s overall quality. When there is a reservation the maintainer will inform the author and provide some guidance. The author may then choose to update the merge request. Once the merge request has been updated and reassigned to the maintainer, they will review the code again. Once the code has been resubmitted any number of times, the maintainer may choose to close the merge request with a summary of why it will not be merged, as well as some guidance. If the merge request is closed the maintainer will be open to discussion as to how to improve the code so it can be approved in the future.
GitLab will do its best to review community contributions as quickly as possible. Specially appointed developers review community contributions daily. You may take a look at the [team page](https://about.gitlab.com/team/) for the merge request coach who specializes in the type of code you have written and mention them in the merge request. For example, if you have written some JavaScript in your code then you should mention the frontend merge request coach. If your code has multiple disciplines you may mention multiple merge request coaches.
GitLab receives a lot of community contributions, so if your code has not been reviewed within 4 days of its initial submission feel free to re-mention the appropriate merge request coach.
When submitting code to GitLab, you may feel that your contribution requires the aid of an external library. If your code includes an external library please provide a link to the library, as well as reasons for including it.
When your code contains more than 500 changes, any major breaking changes, or an external library, `@mention` a maintainer in the merge request. If you are not sure who to mention, the reviewer will add one early in the merge request process.
## Workflow labels
This [documentation](issue_workflow.md) outlines the current workflow labels.
### Type labels
This [documentation](issue_workflow.md) outlines the current type labels.
### Subject labels
This [documentation](issue_workflow.md) outlines the current subject labels.
### Team labels
This [documentation](issue_workflow.md) outlines the current team labels.
### Milestone labels
This [documentation](issue_workflow.md) outlines the current milestone labels.
### Bug Priority labels
This [documentation](issue_workflow.md) outlines the current bug priority labels.
### Bug Severity labels
This [documentation](issue_workflow.md) outlines the current severity labels.
#### Severity impact guidance
This [documentation](issue_workflow.md) outlines the current severity impact guidance.
### Label for community contributors
This [documentation](issue_workflow.md) outlines the current policy regarding community contributor issues.
## Implement design & UI elements
This [documentation](design.md) outlines the current design and UI guidelines.
## Issue tracker
This [documentation](issue_workflow.md) outlines the issue tracker process.
### Issue triaging
This [documentation](issue_workflow.md) outlines the current issue triaging process.
### Feature proposals
This [documentation](issue_workflow.md) outlines the feature proposal process.
### Issue tracker guidelines
This [documentation](issue_workflow.md) outlines the issue tracker guidelines.
### Issue weight
This [documentation](issue_workflow.md) outlines the issue weight guidelines.
### Regression issues
This [documentation](issue_workflow.md) outlines the regression issue process.
### Technical and UX debt
This [documentation](issue_workflow.md) about technical and UX debt has been moved.
### Stewardship
This [documentation](issue_workflow.md) outlines the stewardship process.
## Merge requests
This [documentation](merge_request_workflow.md) outlines the current merge request process.
### Merge request guidelines
This [documentation](merge_request_workflow.md) outlines the current merge request guidelines.
### Contribution acceptance criteria
This [documentation](merge_request_workflow.md) outlines the current acceptance criteria for contributions.
## Definition of done
This [documentation](merge_request_workflow.md) outlines the definition of done.
## Style guides
This [documentation](design.md) outlines the current style guidelines.
---
[Return to Development documentation](../README.md)
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
- [Workflow labels](#workflow-labels)
- [Type labels](#type-labels)
- [Subject labels](#subject-labels)
- [Team labels](#team-labels)
- [Release Scoping labels](#release-scoping-labels)
- [Priority labels](#priority-labels)
- [Severity labels](#severity-labels)
- [Severity impact guidance](#severity-impact-guidance)
- [Label for community contributors](#label-for-community-contributors)
- [Issue triaging](#issue-triaging)
- [Feature proposals](#feature-proposals)
- [Issue tracker guidelines](#issue-tracker-guidelines)
- [Issue weight](#issue-weight)
- [Regression issues](#regression-issues)
- [Technical and UX debt](#technical-and-ux-debt)
- [Stewardship](#stewardship)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Workflow labels
To allow for asynchronous issue handling, we use [milestones][milestones-page]
and [labels][labels-page]. Leads and product managers handle most of the
scheduling into milestones. Labelling is a task for everyone.
Most issues will have labels for at least one of the following:
- Type: ~"feature proposal", ~bug, ~customer, etc.
- Subject: ~wiki, ~"container registry", ~ldap, ~api, ~frontend, etc.
- Team: ~"CI/CD", ~Plan, ~Manage, ~Quality, etc.
- Release Scoping: ~Deliverable, ~Stretch, ~"Next Patch Release"
- Priority: ~P1, ~P2, ~P3, ~P4
- Severity: ~S1, ~S2, ~S3, ~S4
All labels, their meaning and priority are defined on the
[labels page][labels-page].
If you come across an issue that has none of these, and you're allowed to set
labels, you can _always_ add the team and type, and often also the subject.
[milestones-page]: https://gitlab.com/gitlab-org/gitlab-ce/milestones
[labels-page]: https://gitlab.com/gitlab-org/gitlab-ce/labels
### Type labels
Type labels are very important. They define what kind of issue this is. Every
issue should have one or more.
Examples of type labels are ~"feature proposal", ~bug, ~customer, ~security,
and ~"direction".
A number of type labels have a priority assigned to them, which automatically
makes them float to the top, depending on their importance.
Type labels are always lowercase, and can have any color, besides blue (which is
already reserved for subject labels).
The descriptions on the [labels page][labels-page] explain what falls under each type label.
### Subject labels
Subject labels are labels that define what area or feature of GitLab this issue
hits. They are not always necessary, but very convenient.
Examples of subject labels are ~wiki, ~ldap, ~api,
~issues, ~"merge requests", ~labels, and ~"container registry".
If you are an expert in a particular area, it makes it easier to find issues to
work on. You can also subscribe to those labels to receive an email each time an
issue is labeled with a subject label corresponding to your expertise.
Subject labels are always all-lowercase.
### Team labels
Team labels specify what team is responsible for this issue.
Assigning a team label makes sure issues get the attention of the appropriate
people.
The current team labels are:
- ~Configuration
- ~"CI/CD"
- ~Create
- ~Distribution
- ~Documentation
- ~Geo
- ~Gitaly
- ~Manage
- ~Monitoring
- ~Plan
- ~Quality
- ~Release
- ~Secure
- ~UX
The descriptions on the [labels page][labels-page] explain what falls under the
responsibility of each team.
Within those team labels, we also have the ~backend and ~frontend labels to
indicate if an issue needs backend work, frontend work, or both.
Team labels are always capitalized so that they show up as the first label for
any issue.
### Release Scoping labels
Release Scoping labels help us clearly communicate expectations of the work for the
release. There are three levels of Release Scoping labels:
- ~Deliverable: Issues that are expected to be delivered in the current
milestone.
- ~Stretch: Issues that are a stretch goal for delivering in the current
milestone. If these issues are not done in the current release, they will
strongly be considered for the next release.
- ~"Next Patch Release": Issues to put in the next patch release. Work on these
first, and add the "Pick Into X" label to the merge request, along with the
appropriate milestone.
Each issue scheduled for the current milestone should be labeled ~Deliverable
or ~"Stretch". Any open issue for a previous milestone should be labeled
~"Next Patch Release", or otherwise rescheduled to a different milestone.
### Priority labels
Priority labels help us define the time a ~bug fix should be completed. Priority determines how quickly the defect turnaround time must be.
If there are multiple defects, the priority decides which defect has to be fixed immediately versus later.
This label documents the planned timeline & urgency which is used to measure against our actual SLA on delivering ~bug fixes.
| Label | Meaning | Estimate time to fix |
|-------|-----------------|------------------------------------------------------------------|
| ~P1 | Urgent Priority | The current release + potentially immediate hotfix to GitLab.com |
| ~P2 | High Priority | The next release |
| ~P3 | Medium Priority | Within the next 3 releases (approx one quarter) |
| ~P4 | Low Priority | Anything outside the next 3 releases (approx beyond one quarter) |
### Severity labels
Severity labels help us clearly communicate the impact of a ~bug on users.
| Label | Meaning | Impact on Functionality | Example |
|-------|-------------------|-------------------------------------------------------|---------|
| ~S1 | Blocker | Outage, broken feature with no workaround | Unable to create an issue. Data corruption/loss. Security breach. |
| ~S2 | Critical Severity | Broken Feature, workaround too complex & unacceptable | Can push commits, but only via the command line. |
| ~S3 | Major Severity | Broken Feature, workaround acceptable | Can create merge requests only from the Merge Requests page, not through the Issue. |
| ~S4 | Low Severity | Functionality inconvenience or cosmetic issue | Label colors are incorrect / not being displayed. |
#### Severity impact guidance
Severity levels can be applied further depending on the facet of the impact; e.g. Affected customers, GitLab.com availability, performance and etc. The below is a guideline.
| Severity | Affected Customers/Users | GitLab.com Availability | Performance Degradation |
|----------|---------------------------------------------------------------------|----------------------------------------------------|------------------------------|
| ~S1 | >50% users affected (possible company extinction level event) | Significant impact on all of GitLab.com | |
| ~S2 | Many users or multiple paid customers affected (but not apocalyptic)| Significant impact on large portions of GitLab.com | Degradation is guaranteed to occur in the near future |
| ~S3 | A few users or a single paid customer affected | Limited impact on important portions of GitLab.com | Degradation is likely to occur in the near future |
| ~S4 | No paid users/customer affected, or expected to in the near future | Minor impact on on GitLab.com | Degradation _may_ occur but it's not likely |
### Label for community contributors
Issues that are beneficial to our users, 'nice to haves', that we currently do
not have the capacity for or want to give the priority to, are labeled as
~"Accepting Merge Requests", so the community can make a contribution.
Community contributors can submit merge requests for any issue they want, but
the ~"Accepting Merge Requests" label has a special meaning. It points to
changes that:
1. We already agreed on,
1. Are well-defined,
1. Are likely to get accepted by a maintainer.
We want to avoid a situation when a contributor picks an
~"Accepting Merge Requests" issue and then their merge request gets closed,
because we realize that it does not fit our vision, or we want to solve it in a
different way.
We add the ~"Accepting Merge Requests" label to:
- Low priority ~bug issues (i.e. we do not add it to the bugs that we want to
solve in the ~"Next Patch Release")
- Small ~"feature proposal"
- Small ~"technical debt" issues
After adding the ~"Accepting Merge Requests" label, we try to estimate the
[weight](#issue-weight) of the issue. We use issue weight to let contributors
know how difficult the issue is. Additionally:
- We advertise ["Accepting Merge Requests" issues with weight < 5][up-for-grabs]
as suitable for people that have never contributed to GitLab before on the
[Up For Grabs campaign](http://up-for-grabs.net)
- We encourage people that have never contributed to any open source project to
look for ["Accepting Merge Requests" issues with a weight of 1][firt-timers]
If you've decided that you would like to work on an issue, please @-mention
the [appropriate product manager](https://about.gitlab.com/handbook/product/#who-to-talk-to-for-what)
as soon as possible. The product manager will then pull in appropriate GitLab team
members to further discuss scope, design, and technical considerations. This will
ensure that that your contribution is aligned with the GitLab product and minimize
any rework and delay in getting it merged into master.
GitLab team members who apply the ~"Accepting Merge Requests" label to an issue
should update the issue description with a responsible product manager, inviting
any potential community contributor to @-mention per above.
[up-for-grabs]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=Accepting+Merge+Requests&scope=all&sort=weight_asc&state=opened
[firt-timers]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name%5B%5D=Accepting+Merge+Requests&scope=all&sort=upvotes_desc&state=opened&weight=1
### Issue triaging
Our issue triage policies are [described in our handbook]. You are very welcome
to help the GitLab team triage issues. We also organize [issue bash events] once
every quarter.
The most important thing is making sure valid issues receive feedback from the
development team. Therefore the priority is mentioning developers that can help
on those issues. Please select someone with relevant experience from the
[GitLab team][team]. If there is nobody mentioned with that expertise look in
the commit history for the affected files to find someone.
We also use [GitLab Triage] to automate some triaging policies. This is
currently setup as a [scheduled pipeline] running on [quality/triage-ops]
project.
[described in our handbook]: https://about.gitlab.com/handbook/engineering/issue-triage/
[issue bash events]: https://gitlab.com/gitlab-org/gitlab-ce/issues/17815
[GitLab Triage]: https://gitlab.com/gitlab-org/gitlab-triage
[scheduled pipeline]: https://gitlab.com/gitlab-org/quality/triage-ops/pipeline_schedules/10512/edit
[quality/triage-ops]: https://gitlab.com/gitlab-org/quality/triage-ops
### Feature proposals
To create a feature proposal for CE, open an issue on the
[issue tracker of CE][ce-tracker].
For feature proposals for EE, open an issue on the
[issue tracker of EE][ee-tracker].
In order to help track the feature proposals, we have created a
[`feature proposal`][fpl] label. For the time being, users that are not members
of the project cannot add labels. You can instead ask one of the [core team]
members to add the label ~"feature proposal" to the issue or add the following
code snippet right after your description in a new line: `~"feature proposal"`.
Please keep feature proposals as small and simple as possible, complex ones
might be edited to make them small and simple.
Please submit Feature Proposals using the ['Feature Proposal' issue template](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab/issue_templates/Feature Proposal.md) provided on the issue tracker.
For changes in the interface, it is helpful to include a mockup. Issues that add to, or change, the interface should
be given the ~"UX" label. This will allow the UX team to provide input and guidance. You may
need to ask one of the [core team] members to add the label, if you do not have permissions to do it by yourself.
If you want to create something yourself, consider opening an issue first to
discuss whether it is interesting to include this in GitLab.
### Issue tracker guidelines
**[Search the issue tracker][ce-tracker]** for similar entries before
submitting your own, there's a good chance somebody else had the same issue or
feature proposal. Show your support with an award emoji and/or join the
discussion.
Please submit bugs using the ['Bug' issue template](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab/issue_templates/Bug.md) provided on the issue tracker.
The text in the parenthesis is there to help you with what to include. Omit it
when submitting the actual issue. You can copy-paste it and then edit as you
see fit.
### Issue weight
Issue weight allows us to get an idea of the amount of work required to solve
one or multiple issues. This makes it possible to schedule work more accurately.
You are encouraged to set the weight of any issue. Following the guidelines
below will make it easy to manage this, without unnecessary overhead.
1. Set weight for any issue at the earliest possible convenience
1. If you don't agree with a set weight, discuss with other developers until
consensus is reached about the weight
1. Issue weights are an abstract measurement of complexity of the issue. Do not
relate issue weight directly to time. This is called [anchoring](https://en.wikipedia.org/wiki/Anchoring)
and something you want to avoid.
1. Something that has a weight of 1 (or no weight) is really small and simple.
Something that is 9 is rewriting a large fundamental part of GitLab,
which might lead to many hard problems to solve. Changing some text in GitLab
is probably 1, adding a new Git Hook maybe 4 or 5, big features 7-9.
1. If something is very large, it should probably be split up in multiple
issues or chunks. You can simply not set the weight of a parent issue and set
weights to children issues.
### Regression issues
Every monthly release has a corresponding issue on the CE issue tracker to keep
track of functionality broken by that release and any fixes that need to be
included in a patch release (see [8.3 Regressions] as an example).
As outlined in the issue description, the intended workflow is to post one note
with a reference to an issue describing the regression, and then to update that
note with a reference to the merge request that fixes it as it becomes available.
If you're a contributor who doesn't have the required permissions to update
other users' notes, please post a new note with a reference to both the issue
and the merge request.
The release manager will [update the notes] in the regression issue as fixes are
addressed.
[8.3 Regressions]: https://gitlab.com/gitlab-org/gitlab-ce/issues/4127
[update the notes]: https://gitlab.com/gitlab-org/release-tools/blob/master/doc/pro-tips.md#update-the-regression-issue
### Technical and UX debt
In order to track things that can be improved in GitLab's codebase,
we use the ~"technical debt" label in [GitLab's issue tracker][ce-tracker].
For user experience improvements, we use the ~"UX debt" label.
These labels should be added to issues that describe things that can be improved,
shortcuts that have been taken, features that need additional attention, and all
other things that have been left behind due to high velocity of development.
For example, code that needs refactoring should use the ~"technical debt" label,
user experience refinements should use the ~"UX debt" label.
Everyone can create an issue, though you may need to ask for adding a specific
label, if you do not have permissions to do it by yourself. Additional labels
can be combined with these labels, to make it easier to schedule
the improvements for a release.
Issues tagged with these labels have the same priority like issues
that describe a new feature to be introduced in GitLab, and should be scheduled
for a release by the appropriate person.
Make sure to mention the merge request that the ~"technical debt" issue or
~"UX debt" issue is associated with in the description of the issue.
### Stewardship
For issues related to the open source stewardship of GitLab,
there is the ~"stewardship" label.
This label is to be used for issues in which the stewardship of GitLab
is a topic of discussion. For instance if GitLab Inc. is planning to add
features from GitLab EE to GitLab CE, related issues would be labelled with
~"stewardship".
A recent example of this was the issue for
[bringing the time tracking API to GitLab CE][time-tracking-issue].
[time-tracking-issue]: https://gitlab.com/gitlab-org/gitlab-ce/issues/25517#note_20019084
---
[Return to Contributing documentation](index.md)
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
- [Merge requests](#merge-requests)
- [Merge request guidelines](#merge-request-guidelines)
- [Contribution acceptance criteria](#contribution-acceptance-criteria)
- [Definition of done](#definition-of-done)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Merge requests
We welcome merge requests with fixes and improvements to GitLab code, tests,
and/or documentation. The issues that are specifically suitable for
community contributions are listed with the label
[`Accepting Merge Requests` on our issue tracker for CE][accepting-mrs-ce]
and [EE][accepting-mrs-ee], but you are free to contribute to any other issue
you want.
Please note that if an issue is marked for the current milestone either before
or while you are working on it, a team member may take over the merge request
in order to ensure the work is finished before the release date.
If you want to add a new feature that is not labeled it is best to first create
a feedback issue (if there isn't one already) and leave a comment asking for it
to be marked as `Accepting Merge Requests`. Please include screenshots or
wireframes if the feature will also change the UI.
Merge requests should be opened at [GitLab.com][gitlab-mr-tracker].
If you are new to GitLab development (or web development in general), see the
[I want to contribute!](#i-want-to-contribute) section to get you started with
some potentially easy issues.
To start with GitLab development download the [GitLab Development Kit][gdk] and
see the [Development section](../README.md) for some guidelines.
### Merge request guidelines
If you can, please submit a merge request with the fix or improvements
including tests. If you don't know how to fix the issue but can write a test
that exposes the issue we will accept that as well. In general bug fixes that
include a regression test are merged quickly while new features without proper
tests are least likely to receive timely feedback. The workflow to make a merge
request is as follows:
1. Fork the project into your personal space on GitLab.com
1. Create a feature branch, branch away from `master`
1. Write [tests](https://docs.gitlab.com/ee/development/rake_tasks.html#run-tests) and code
1. [Generate a changelog entry with `bin/changelog`][changelog]
1. If you are writing documentation, make sure to follow the
[documentation guidelines][doc-guidelines]
1. If you have multiple commits please combine them into a few logically
organized commits by [squashing them][git-squash]
1. Push the commit(s) to your fork
1. Submit a merge request (MR) to the `master` branch
1. Your merge request needs at least 1 approval but feel free to require more.
For instance if you're touching backend and frontend code, it's a good idea
to require 2 approvals: 1 from a backend maintainer and 1 from a frontend
maintainer
1. You don't have to select any approvers, but you can if you really want
specific people to approve your merge request
1. The MR title should describe the change you want to make
1. The MR description should give a motive for your change and the method you
used to achieve it.
1. If you are contributing code, fill in the template already provided in the
"Description" field.
1. If you are contributing documentation, choose `Documentation` from the
"Choose a template" menu and fill in the template.
1. Mention the issue(s) your merge request solves, using the `Solves #XXX` or
`Closes #XXX` syntax to auto-close the issue(s) once the merge request will
be merged.
1. If you're allowed to, set a relevant milestone and labels
1. If the MR changes the UI it should include *Before* and *After* screenshots
1. If the MR changes CSS classes please include the list of affected pages,
`grep css-class ./app -R`
1. Be prepared to answer questions and incorporate feedback even if requests
for this arrive weeks or months after your MR submission
1. If a discussion has been addressed, select the "Resolve discussion" button
beneath it to mark it resolved.
1. If your MR touches code that executes shell commands, reads or opens files or
handles paths to files on disk, make sure it adheres to the
[shell command guidelines](../shell_commands.md)
1. If your code creates new files on disk please read the
[shared files guidelines](../shared_files.md).
1. When writing commit messages please follow
[these](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
[guidelines](http://chris.beams.io/posts/git-commit/).
1. If your merge request adds one or more migrations, make sure to execute all
migrations on a fresh database before the MR is reviewed. If the review leads
to large changes in the MR, do this again once the review is complete.
1. For more complex migrations, write tests.
1. Merge requests **must** adhere to the [merge request performance
guidelines](../merge_request_performance_guidelines.md).
1. For tests that use Capybara or PhantomJS, see this [article on how
to write reliable asynchronous tests](https://robots.thoughtbot.com/write-reliable-asynchronous-integration-tests-with-capybara).
Please keep the change in a single MR **as small as possible**. If you want to
contribute a large feature think very hard what the minimum viable change is.
Can you split the functionality? Can you only submit the backend/API code? Can
you start with a very simple UI? Can you do part of the refactor? The increased
reviewability of small MRs that leads to higher code quality is more important
to us than having a minimal commit log. The smaller an MR is the more likely it
is it will be merged (quickly). After that you can send more MRs to enhance it.
The ['How to get faster PR reviews' document of Kubernetes](https://github.com/kubernetes/community/blob/master/contributors/devel/faster_reviews.md) also has some great points regarding this.
For examples of feedback on merge requests please look at already
[closed merge requests][closed-merge-requests]. If you would like quick feedback
on your merge request feel free to mention someone from the [core team] or one
of the [Merge request coaches][team].
Please ensure that your merge request meets the contribution acceptance criteria.
When having your code reviewed and when reviewing merge requests please take the
[code review guidelines](../code_review.md) into account.
### Contribution acceptance criteria
1. The change is as small as possible
1. Include proper tests and make all tests pass (unless it contains a test
exposing a bug in existing code). Every new class should have corresponding
unit tests, even if the class is exercised at a higher level, such as a feature test.
1. If you suspect a failing CI build is unrelated to your contribution, you may
try and restart the failing CI job or ask a developer to fix the
aforementioned failing test
1. Your MR initially contains a single commit (please use `git rebase -i` to
squash commits)
1. Your changes can merge without problems (if not please rebase if you're the
only one working on your feature branch, otherwise, merge `master`)
1. Does not break any existing functionality
1. Fixes one specific issue or implements one specific feature (do not combine
things, send separate merge requests if needed)
1. Migrations should do only one thing (e.g., either create a table, move data
to a new table or remove an old table) to aid retrying on failure
1. Keeps the GitLab code base clean and well structured
1. Contains functionality we think other users will benefit from too
1. Doesn't add configuration options or settings options since they complicate
making and testing future changes
1. Changes do not adversely degrade performance.
- Avoid repeated polling of endpoints that require a significant amount of overhead
- Check for N+1 queries via the SQL log or [`QueryRecorder`](https://docs.gitlab.com/ce/development/mer ge_request_performance_guidelines.html)
- Avoid repeated access of filesystem
1. If you need polling to support real-time features, please use
[polling with ETag caching][polling-etag].
1. Changes after submitting the merge request should be in separate commits
(no squashing).
1. It conforms to the [style guides](#style-guides) and the following:
- If your change touches a line that does not follow the style, modify the
entire line to follow it. This prevents linting tools from generating warnings.
- Don't touch neighbouring lines. As an exception, automatic mass
refactoring modifications may leave style non-compliant.
1. If the merge request adds any new libraries (gems, JavaScript libraries,
etc.), they should conform to our [Licensing guidelines][license-finder-doc].
See the instructions in that document for help if your MR fails the
"license-finder" test with a "Dependencies that need approval" error.
1. The merge request meets the [definition of done](#definition-of-done).
## Definition of done
If you contribute to GitLab please know that changes involve more than just
code. We have the following [definition of done][definition-of-done]. Please ensure you support
the feature you contribute through all of these steps.
1. Description explaining the relevancy (see following item)
1. Working and clean code that is commented where needed
1. [Unit, integration, and system tests][testing] that pass on the CI server
1. Performance/scalability implications have been considered, addressed, and tested
1. [Documented][doc-guidelines] in the `/doc` directory
1. [Changelog entry added][changelog], if necessary
1. Reviewed and any concerns are addressed
1. Merged by a project maintainer
1. Added to the release blog article, if relevant
1. Added to [the website](https://gitlab.com/gitlab-com/www-gitlab-com/), if relevant
1. Community questions answered
1. Answers to questions radiated (in docs/wiki/support etc.)
If you add a dependency in GitLab (such as an operating system package) please
consider updating the following and note the applicability of each in your
merge request:
1. Note the addition in the release blog post (create one if it doesn't exist yet) https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/
1. Upgrade guide, for example https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/7.5-to-7.6.md
1. Upgrader https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/upgrader.md#2-run-gitlab-upgrade-tool
1. Installation guide https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies
1. GitLab Development Kit https://gitlab.com/gitlab-org/gitlab-development-kit
1. Test suite https://gitlab.com/gitlab-org/gitlab-ce/blob/master/scripts/prepare_build.sh
1. Omnibus package creator https://gitlab.com/gitlab-org/omnibus-gitlab
---
[Return to Contributing documentation](index.md)
...@@ -182,6 +182,34 @@ class MyMigration < ActiveRecord::Migration ...@@ -182,6 +182,34 @@ class MyMigration < ActiveRecord::Migration
end end
``` ```
## Adding foreign-key constraints
When adding a foreign-key constraint to either an existing or new
column remember to also add a index on the column.
This is _required_ if the foreign-key constraint specifies
`ON DELETE CASCADE` or `ON DELETE SET NULL` behavior. On a cascading
delete, the [corresponding record needs to be retrieved using an
index](https://www.cybertec-postgresql.com/en/postgresql-indexes-and-foreign-keys/)
(otherwise, we'd need to scan the whole table) for subsequent update or
deletion.
Here's an example where we add a new column with a foreign key
constraint. Note it includes `index: true` to create an index for it.
```ruby
class Migration < ActiveRecord::Migration
def change
add_reference :model, :other_model, index: true, foreign_key: { on_delete: :cascade }
end
end
```
When adding a foreign-key constraint to an existing column, we
have to employ `add_concurrent_foreign_key` and `add_concurrent_index`
instead of `add_reference`.
## Adding Columns With Default Values ## Adding Columns With Default Values
When adding columns with default values you must use the method When adding columns with default values you must use the method
......
...@@ -259,6 +259,7 @@ GFM will recognize the following: ...@@ -259,6 +259,7 @@ GFM will recognize the following:
| `@user_name` | specific user | | `@user_name` | specific user |
| `@group_name` | specific group | | `@group_name` | specific group |
| `@all` | entire team | | `@all` | entire team |
| `namespace/project>` | project |
| `#12345` | issue | | `#12345` | issue |
| `!123` | merge request | | `!123` | merge request |
| `$123` | snippet | | `$123` | snippet |
......
...@@ -1122,7 +1122,6 @@ X-Gitlab-Event: Build Hook ...@@ -1122,7 +1122,6 @@ X-Gitlab-Event: Build Hook
}, },
"repository": { "repository": {
"name": "gitlab_test", "name": "gitlab_test",
"git_ssh_url": "git@192.168.64.1:gitlab-org/gitlab-test.git",
"description": "Atque in sunt eos similique dolores voluptatem.", "description": "Atque in sunt eos similique dolores voluptatem.",
"homepage": "http://192.168.64.1:3005/gitlab-org/gitlab-test", "homepage": "http://192.168.64.1:3005/gitlab-org/gitlab-test",
"git_ssh_url": "git@192.168.64.1:gitlab-org/gitlab-test.git", "git_ssh_url": "git@192.168.64.1:gitlab-org/gitlab-test.git",
......
module Banzai
module Filter
# HTML filter that replaces project references with links.
class ProjectReferenceFilter < ReferenceFilter
self.reference_type = :project
# Public: Find `namespace/project>` project references in text
#
# ProjectReferenceFilter.references_in(text) do |match, project|
# "<a href=...>#{project}></a>"
# end
#
# text - String text to search.
#
# Yields the String match, and the String project name.
#
# Returns a String replaced with the return of the block.
def self.references_in(text)
text.gsub(Project.markdown_reference_pattern) do |match|
yield match, "#{$~[:namespace]}/#{$~[:project]}"
end
end
def call
ref_pattern = Project.markdown_reference_pattern
ref_pattern_start = /\A#{ref_pattern}\z/
nodes.each do |node|
if text_node?(node)
replace_text_when_pattern_matches(node, ref_pattern) do |content|
project_link_filter(content)
end
elsif element_node?(node)
yield_valid_link(node) do |link, inner_html|
if link =~ ref_pattern_start
replace_link_node_with_href(node, link) do
project_link_filter(link, link_content: inner_html)
end
end
end
end
end
doc
end
# Replace `namespace/project>` project references in text with links to the referenced
# project page.
#
# text - String text to replace references in.
# link_content - Original content of the link being replaced.
#
# Returns a String with `namespace/project>` references replaced with links. All links
# have `gfm` and `gfm-project` class names attached for styling.
def project_link_filter(text, link_content: nil)
self.class.references_in(text) do |match, project_path|
cached_call(:banzai_url_for_object, match, path: [Project, project_path.downcase]) do
if project = projects_hash[project_path.downcase]
link_to_project(project, link_content: link_content) || match
else
match
end
end
end
end
# Returns a Hash containing all Project objects for the project
# references in the current document.
#
# The keys of this Hash are the project paths, the values the
# corresponding Project objects.
def projects_hash
@projects ||= Project.eager_load(:route, namespace: [:route])
.where_full_path_in(projects)
.index_by(&:full_path)
.transform_keys(&:downcase)
end
# Returns all projects referenced in the current document.
def projects
refs = Set.new
nodes.each do |node|
node.to_html.scan(Project.markdown_reference_pattern) do
refs << "#{$~[:namespace]}/#{$~[:project]}"
end
end
refs.to_a
end
private
def urls
Gitlab::Routing.url_helpers
end
def link_class
reference_class(:project)
end
def link_to_project(project, link_content: nil)
url = urls.project_url(project, only_path: context[:only_path])
data = data_attribute(project: project.id)
content = link_content || project.to_reference_with_postfix
link_tag(url, data, content, project.name)
end
def link_tag(url, data, link_content, title)
%(<a href="#{url}" #{data} class="#{link_class}" title="#{escape_once(title)}">#{link_content}</a>)
end
end
end
end
...@@ -36,6 +36,7 @@ module Banzai ...@@ -36,6 +36,7 @@ module Banzai
def self.reference_filters def self.reference_filters
[ [
Filter::UserReferenceFilter, Filter::UserReferenceFilter,
Filter::ProjectReferenceFilter,
Filter::IssueReferenceFilter, Filter::IssueReferenceFilter,
Filter::ExternalIssueReferenceFilter, Filter::ExternalIssueReferenceFilter,
Filter::MergeRequestReferenceFilter, Filter::MergeRequestReferenceFilter,
......
module Banzai
module ReferenceParser
class ProjectParser < BaseParser
include Gitlab::Utils::StrongMemoize
self.reference_type = :project
def references_relation
Project
end
private
# Returns an Array of Project ids that can be read by the given user.
#
# user - The User for which to check the projects
def readable_project_ids_for(user)
@project_ids_by_user ||= {}
@project_ids_by_user[user] ||=
Project.public_or_visible_to_user(user).where("projects.id IN (?)", @projects_for_nodes.values.map(&:id)).pluck(:id)
end
def can_read_reference?(user, ref_project, node)
readable_project_ids_for(user).include?(ref_project.try(:id))
end
end
end
end
...@@ -640,6 +640,9 @@ msgstr "" ...@@ -640,6 +640,9 @@ msgstr ""
msgid "Authentication log" msgid "Authentication log"
msgstr "" msgstr ""
msgid "Authentication method"
msgstr ""
msgid "Author" msgid "Author"
msgstr "" msgstr ""
...@@ -2169,6 +2172,9 @@ msgstr "" ...@@ -2169,6 +2172,9 @@ msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines." msgid "Diffs|Something went wrong while fetching diff lines."
msgstr "" msgstr ""
msgid "Direction"
msgstr ""
msgid "Directory name" msgid "Directory name"
msgstr "" msgstr ""
...@@ -2391,6 +2397,9 @@ msgstr "" ...@@ -2391,6 +2397,9 @@ msgstr ""
msgid "Environments|You don't have any environments right now." msgid "Environments|You don't have any environments right now."
msgstr "" msgstr ""
msgid "Error"
msgstr ""
msgid "Error Reporting and Logging" msgid "Error Reporting and Logging"
msgstr "" msgstr ""
...@@ -2517,6 +2526,9 @@ msgstr "" ...@@ -2517,6 +2526,9 @@ msgstr ""
msgid "Failed to remove issue from board, please try again." msgid "Failed to remove issue from board, please try again."
msgstr "" msgstr ""
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule" msgid "Failed to remove the pipeline schedule"
msgstr "" msgstr ""
...@@ -3031,12 +3043,18 @@ msgstr "" ...@@ -3031,12 +3043,18 @@ msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept." msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr "" msgstr ""
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
msgid "Incompatible Project" msgid "Incompatible Project"
msgstr "" msgstr ""
msgid "Inline" msgid "Inline"
msgstr "" msgstr ""
msgid "Input your repository URL"
msgstr ""
msgid "Install GitLab Runner" msgid "Install GitLab Runner"
msgstr "" msgstr ""
...@@ -3468,6 +3486,21 @@ msgstr "" ...@@ -3468,6 +3486,21 @@ msgstr ""
msgid "Milestones|Promote Milestone" msgid "Milestones|Promote Milestone"
msgstr "" msgstr ""
msgid "Mirror a repository"
msgstr ""
msgid "Mirror direction"
msgstr ""
msgid "Mirror repository"
msgstr ""
msgid "Mirrored repositories"
msgstr ""
msgid "Mirroring repositories"
msgstr ""
msgid "MissingSSHKeyWarningLink|add an SSH key" msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "" msgstr ""
...@@ -3528,6 +3561,9 @@ msgstr "" ...@@ -3528,6 +3561,9 @@ msgstr ""
msgid "Network" msgid "Network"
msgstr "" msgstr ""
msgid "Never"
msgstr ""
msgid "New" msgid "New"
msgstr "" msgstr ""
...@@ -3791,6 +3827,9 @@ msgstr "" ...@@ -3791,6 +3827,9 @@ msgstr ""
msgid "Only comments from the following commit are shown below" msgid "Only comments from the following commit are shown below"
msgstr "" msgstr ""
msgid "Only mirror protected branches"
msgstr ""
msgid "Only project members can comment." msgid "Only project members can comment."
msgstr "" msgstr ""
...@@ -4379,6 +4418,9 @@ msgstr "" ...@@ -4379,6 +4418,9 @@ msgstr ""
msgid "Public pipelines" msgid "Public pipelines"
msgstr "" msgstr ""
msgid "Push"
msgstr ""
msgid "Push events" msgid "Push events"
msgstr "" msgstr ""
...@@ -4780,6 +4822,9 @@ msgstr "" ...@@ -4780,6 +4822,9 @@ msgstr ""
msgid "Set up Koding" msgid "Set up Koding"
msgstr "" msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
msgid "SetPasswordToCloneLink|set a password" msgid "SetPasswordToCloneLink|set a password"
msgstr "" msgstr ""
...@@ -5189,6 +5234,9 @@ msgstr "" ...@@ -5189,6 +5234,9 @@ msgstr ""
msgid "Test coverage parsing" msgid "Test coverage parsing"
msgstr "" msgstr ""
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project" msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
msgstr "" msgstr ""
...@@ -5246,6 +5294,9 @@ msgstr "" ...@@ -5246,6 +5294,9 @@ msgstr ""
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>." msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr "" msgstr ""
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request." msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "" msgstr ""
...@@ -5270,6 +5321,9 @@ msgstr "" ...@@ -5270,6 +5321,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage." msgid "The time taken by each data entry gathered by that stage."
msgstr "" msgstr ""
msgid "The update action will time out after 15 minutes. For big repositories, use a clone/push combination."
msgstr ""
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side." msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr "" msgstr ""
...@@ -5408,6 +5462,9 @@ msgstr "" ...@@ -5408,6 +5462,9 @@ msgstr ""
msgid "This user has no identities" msgid "This user has no identities"
msgstr "" msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
msgid "Time before an issue gets scheduled" msgid "Time before an issue gets scheduled"
msgstr "" msgstr ""
...@@ -5721,9 +5778,15 @@ msgstr "" ...@@ -5721,9 +5778,15 @@ msgstr ""
msgid "Update" msgid "Update"
msgstr "" msgstr ""
msgid "Update now"
msgstr ""
msgid "Update your group name, description, avatar, and other general settings." msgid "Update your group name, description, avatar, and other general settings."
msgstr "" msgstr ""
msgid "Updating"
msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:" msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr "" msgstr ""
......
# frozen_string_literal: true
require_relative '../../migration_helpers'
module RuboCop
module Cop
module Migration
# Cop that checks if a foreign key constraint is added and require a index for it
class AddReference < RuboCop::Cop::Cop
include MigrationHelpers
MSG = '`add_reference` requires `index: true`'
def on_send(node)
return unless in_migration?(node)
name = node.children[1]
return unless name == :add_reference
opts = node.children.last
add_offense(node, location: :selector) unless opts && opts.type == :hash
index_present = false
opts.each_node(:pair) do |pair|
index_present ||= index_enabled?(pair)
end
add_offense(node, location: :selector) unless index_present
end
private
def index_enabled?(pair)
hash_key_type(pair) == :sym && hash_key_name(pair) == :index && pair.children[1].true_type?
end
def hash_key_type(pair)
pair.children[0].type
end
def hash_key_name(pair)
pair.children[0].children[0]
end
end
end
end
end
...@@ -11,6 +11,7 @@ require_relative 'cop/migration/add_column' ...@@ -11,6 +11,7 @@ require_relative 'cop/migration/add_column'
require_relative 'cop/migration/add_concurrent_foreign_key' require_relative 'cop/migration/add_concurrent_foreign_key'
require_relative 'cop/migration/add_concurrent_index' require_relative 'cop/migration/add_concurrent_index'
require_relative 'cop/migration/add_index' require_relative 'cop/migration/add_index'
require_relative 'cop/migration/add_reference'
require_relative 'cop/migration/add_timestamps' require_relative 'cop/migration/add_timestamps'
require_relative 'cop/migration/datetime' require_relative 'cop/migration/datetime'
require_relative 'cop/migration/hash_index' require_relative 'cop/migration/hash_index'
......
...@@ -68,10 +68,12 @@ describe "Admin::Users" do ...@@ -68,10 +68,12 @@ describe "Admin::Users" do
end end
describe "GET /admin/users/new" do describe "GET /admin/users/new" do
let(:user_username) { 'bang' }
before do before do
visit new_admin_user_path visit new_admin_user_path
fill_in "user_name", with: "Big Bang" fill_in "user_name", with: "Big Bang"
fill_in "user_username", with: "bang" fill_in "user_username", with: user_username
fill_in "user_email", with: "bigbang@mail.com" fill_in "user_email", with: "bigbang@mail.com"
end end
...@@ -112,6 +114,17 @@ describe "Admin::Users" do ...@@ -112,6 +114,17 @@ describe "Admin::Users" do
expect(email.text_part.body).to have_content(user.email) expect(email.text_part.body).to have_content(user.email)
expect(email.text_part.body).to have_content('password') expect(email.text_part.body).to have_content('password')
end end
context 'username contains spaces' do
let(:user_username) { 'Bing bang' }
it "doesn't create the user and shows an error message" do
expect { click_button "Create user" }.to change {User.count}.by(0)
expect(page).to have_content('The form contains the following error')
expect(page).to have_content('Username can contain only letters, digits')
end
end
end end
describe "GET /admin/users/:id" do describe "GET /admin/users/:id" do
......
require 'spec_helper' require 'spec_helper'
describe 'Blob shortcuts' do describe 'Blob shortcuts', :js do
include TreeHelper include TreeHelper
let(:project) { create(:project, :public, :repository) } let(:project) { create(:project, :public, :repository) }
let(:path) { project.repository.ls_files(project.repository.root_ref)[0] } let(:path) { project.repository.ls_files(project.repository.root_ref)[0] }
......
...@@ -210,7 +210,7 @@ describe "User browses files" do ...@@ -210,7 +210,7 @@ describe "User browses files" do
end end
end end
context "when browsing a file content" do context "when browsing a file content", :js do
before do before do
visit(tree_path_root_ref) visit(tree_path_root_ref)
......
require 'spec_helper' require 'spec_helper'
describe 'Projects > Files > User deletes files' do describe 'Projects > Files > User deletes files', :js do
let(:fork_message) do let(:fork_message) do
"You're not allowed to make changes to this project directly. "\ "You're not allowed to make changes to this project directly. "\
"A fork of this project has been created that you can make changes in, so you can submit a merge request." "A fork of this project has been created that you can make changes in, so you can submit a merge request."
......
require 'spec_helper' require 'spec_helper'
describe 'Projects > Files > User edits files' do describe 'Projects > Files > User edits files', :js do
include ProjectForksHelper include ProjectForksHelper
let(:project) { create(:project, :repository, name: 'Shop') } let(:project) { create(:project, :repository, name: 'Shop') }
let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') } let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') }
......
require 'spec_helper' require 'spec_helper'
describe 'Projects > Files > User replaces files' do describe 'Projects > Files > User replaces files', :js do
include DropzoneHelper include DropzoneHelper
let(:fork_message) do let(:fork_message) do
......
...@@ -17,7 +17,7 @@ describe 'Project remote mirror', :feature do ...@@ -17,7 +17,7 @@ describe 'Project remote mirror', :feature do
visit project_mirror_path(project) visit project_mirror_path(project)
expect(page).to have_content('The remote repository failed to update.') expect_mirror_to_have_error_and_timeago('Never')
end end
end end
...@@ -27,8 +27,14 @@ describe 'Project remote mirror', :feature do ...@@ -27,8 +27,14 @@ describe 'Project remote mirror', :feature do
visit project_mirror_path(project) visit project_mirror_path(project)
expect(page).to have_content('The remote repository failed to update 5 minutes ago.') expect_mirror_to_have_error_and_timeago('5 minutes ago')
end end
end end
def expect_mirror_to_have_error_and_timeago(timeago)
row = first('.js-mirrors-table-body tr')
expect(row).to have_content('Error')
expect(row).to have_content(timeago)
end
end end
end end
...@@ -129,9 +129,8 @@ describe 'Projects > Settings > Repository settings' do ...@@ -129,9 +129,8 @@ describe 'Projects > Settings > Repository settings' do
visit project_settings_repository_path(project) visit project_settings_repository_path(project)
end end
it 'shows push mirror settings' do it 'shows push mirror settings', :js do
expect(page).to have_selector('#project_remote_mirrors_attributes_0_enabled') expect(page).to have_selector('#mirror_direction')
expect(page).to have_selector('#project_remote_mirrors_attributes_0_url')
end end
end end
end end
......
...@@ -5,12 +5,67 @@ describe AvatarsHelper do ...@@ -5,12 +5,67 @@ describe AvatarsHelper do
let(:user) { create(:user) } let(:user) { create(:user) }
describe '#project_icon' do describe '#project_icon & #group_icon' do
it 'returns an url for the avatar' do shared_examples 'resource with a default avatar' do |source_type|
project = create(:project, :public, avatar: File.open(uploaded_image_temp_path)) it 'returns a default avatar div' do
expect(public_send("#{source_type}_icon", *helper_args))
.to match(%r{<div class="identicon bg\d+">F</div>})
end
end
shared_examples 'resource with a custom avatar' do |source_type|
it 'returns a custom avatar image' do
expect(public_send("#{source_type}_icon", *helper_args))
.to eq "<img src=\"#{resource.avatar.url}\" alt=\"Banana sample\" />"
end
end
context 'when providing a project' do
it_behaves_like 'resource with a default avatar', 'project' do
let(:resource) { create(:project, name: 'foo') }
let(:helper_args) { [resource] }
end
it_behaves_like 'resource with a custom avatar', 'project' do
let(:resource) { create(:project, :public, avatar: File.open(uploaded_image_temp_path)) }
let(:helper_args) { [resource] }
end
end
context 'when providing a project path' do
it_behaves_like 'resource with a default avatar', 'project' do
let(:resource) { create(:project, name: 'foo') }
let(:helper_args) { [resource.full_path] }
end
expect(helper.project_icon(project.full_path).to_s) it_behaves_like 'resource with a custom avatar', 'project' do
.to eq "<img data-src=\"#{project.avatar.url}\" class=\" lazy\" src=\"#{LazyImageTagHelper.placeholder_image}\" />" let(:resource) { create(:project, :public, avatar: File.open(uploaded_image_temp_path)) }
let(:helper_args) { [resource.full_path] }
end
end
context 'when providing a group' do
it_behaves_like 'resource with a default avatar', 'group' do
let(:resource) { create(:group, name: 'foo') }
let(:helper_args) { [resource] }
end
it_behaves_like 'resource with a custom avatar', 'group' do
let(:resource) { create(:group, avatar: File.open(uploaded_image_temp_path)) }
let(:helper_args) { [resource] }
end
end
context 'when providing a group path' do
it_behaves_like 'resource with a default avatar', 'group' do
let(:resource) { create(:group, name: 'foo') }
let(:helper_args) { [resource.full_path] }
end
it_behaves_like 'resource with a custom avatar', 'group' do
let(:resource) { create(:group, avatar: File.open(uploaded_image_temp_path)) }
let(:helper_args) { [resource.full_path] }
end
end end
end end
......
...@@ -3,19 +3,6 @@ require 'spec_helper' ...@@ -3,19 +3,6 @@ require 'spec_helper'
describe GroupsHelper do describe GroupsHelper do
include ApplicationHelper include ApplicationHelper
describe 'group_icon' do
it 'returns an url for the avatar' do
avatar_file_path = File.join('spec', 'fixtures', 'banana_sample.gif')
group = create(:group)
group.avatar = fixture_file_upload(avatar_file_path)
group.save!
expect(helper.group_icon(group).to_s)
.to eq "<img data-src=\"#{group.avatar.url}\" class=\" lazy\" src=\"#{LazyImageTagHelper.placeholder_image}\" />"
end
end
describe 'group_icon_url' do describe 'group_icon_url' do
it 'returns an url for the avatar' do it 'returns an url for the avatar' do
avatar_file_path = File.join('spec', 'fixtures', 'banana_sample.gif') avatar_file_path = File.join('spec', 'fixtures', 'banana_sample.gif')
......
import Vue from 'vue'; import Vue from 'vue';
import Vuex from 'vuex'; import Vuex from 'vuex';
import component from '~/vue_shared/components/reports/modal_open_name.vue'; import component from '~/reports/components/modal_open_name.vue';
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper'; import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
describe('Modal open name', () => { describe('Modal open name', () => {
......
import Vue from 'vue'; import Vue from 'vue';
import component from '~/vue_shared/components/reports/report_link.vue'; import component from '~/reports/components/report_link.vue';
import mountComponent from '../../../helpers/vue_mount_component_helper'; import mountComponent from '../../helpers/vue_mount_component_helper';
describe('report link', () => { describe('report link', () => {
let vm; let vm;
......
import Vue from 'vue'; import Vue from 'vue';
import reportSection from '~/vue_shared/components/reports/report_section.vue'; import reportSection from '~/reports/components/report_section.vue';
import mountComponent, { mountComponentWithSlots } from 'spec/helpers/vue_mount_component_helper'; import mountComponent, { mountComponentWithSlots } from 'spec/helpers/vue_mount_component_helper';
describe('Report section', () => { describe('Report section', () => {
......
import Vue from 'vue'; import Vue from 'vue';
import component from '~/vue_shared/components/reports/summary_row.vue'; import component from '~/reports/components/summary_row.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper'; import mountComponent from 'spec/helpers/vue_mount_component_helper';
describe('Summary row', () => { describe('Summary row', () => {
......
require 'spec_helper'
describe Banzai::Filter::ProjectReferenceFilter do
include FilterSpecHelper
def invalidate_reference(reference)
"#{reference.reverse}"
end
def get_reference(project)
project.to_reference_with_postfix
end
let(:project) { create(:project, :public) }
subject { project }
let(:subject_name) { "project" }
let(:reference) { get_reference(project) }
it_behaves_like 'user reference or project reference'
it 'ignores invalid projects' do
exp = act = "Hey #{invalidate_reference(reference)}"
expect(reference_filter(act).to_html).to eq(CGI.escapeHTML(exp))
end
it 'allows references with text after the > character' do
doc = reference_filter("Hey #{reference}foo")
expect(doc.css('a').first.attr('href')).to eq urls.project_url(subject)
end
%w(pre code a style).each do |elem|
it "ignores valid references contained inside '#{elem}' element" do
exp = act = "<#{elem}>Hey #{CGI.escapeHTML(reference)}</#{elem}>"
expect(reference_filter(act).to_html).to eq exp
end
end
it 'includes default classes' do
doc = reference_filter("Hey #{reference}")
expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-project has-tooltip'
end
context 'in group context' do
let(:group) { create(:group) }
let(:project) { create(:project, group: group) }
let(:nested_group) { create(:group, :nested) }
let(:nested_project) { create(:project, group: nested_group) }
it 'supports mentioning a project' do
reference = get_reference(project)
doc = reference_filter("Hey #{reference}")
expect(doc.css('a').first.attr('href')).to eq urls.project_url(project)
end
it 'supports mentioning a project in a nested group' do
reference = get_reference(nested_project)
doc = reference_filter("Hey #{reference}")
expect(doc.css('a').first.attr('href')).to eq urls.project_url(nested_project)
end
end
describe '#projects_hash' do
it 'returns a Hash containing all Projects' do
document = Nokogiri::HTML.fragment("<p>#{get_reference(project)}</p>")
filter = described_class.new(document, project: project)
expect(filter.projects_hash).to eq({ project.full_path => project })
end
end
describe '#projects' do
it 'returns the projects mentioned in a document' do
document = Nokogiri::HTML.fragment("<p>#{get_reference(project)}</p>")
filter = described_class.new(document, project: project)
expect(filter.projects).to eq([project.full_path])
end
end
end
...@@ -3,9 +3,17 @@ require 'spec_helper' ...@@ -3,9 +3,17 @@ require 'spec_helper'
describe Banzai::Filter::UserReferenceFilter do describe Banzai::Filter::UserReferenceFilter do
include FilterSpecHelper include FilterSpecHelper
def get_reference(user)
user.to_reference
end
let(:project) { create(:project, :public) } let(:project) { create(:project, :public) }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:reference) { user.to_reference } subject { user }
let(:subject_name) { "user" }
let(:reference) { get_reference(user) }
it_behaves_like 'user reference or project reference'
it 'requires project context' do it 'requires project context' do
expect { described_class.call('') }.to raise_error(ArgumentError, /:project/) expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
...@@ -66,45 +74,6 @@ describe Banzai::Filter::UserReferenceFilter do ...@@ -66,45 +74,6 @@ describe Banzai::Filter::UserReferenceFilter do
end end
end end
context 'mentioning a user' do
it_behaves_like 'a reference containing an element node'
it 'links to a User' do
doc = reference_filter("Hey #{reference}")
expect(doc.css('a').first.attr('href')).to eq urls.user_url(user)
end
it 'links to a User with a period' do
user = create(:user, name: 'alphA.Beta')
doc = reference_filter("Hey #{user.to_reference}")
expect(doc.css('a').length).to eq 1
end
it 'links to a User with an underscore' do
user = create(:user, name: 'ping_pong_king')
doc = reference_filter("Hey #{user.to_reference}")
expect(doc.css('a').length).to eq 1
end
it 'links to a User with different case-sensitivity' do
user = create(:user, username: 'RescueRanger')
doc = reference_filter("Hey #{user.to_reference.upcase}")
expect(doc.css('a').length).to eq 1
expect(doc.css('a').text).to eq(user.to_reference)
end
it 'includes a data-user attribute' do
doc = reference_filter("Hey #{reference}")
link = doc.css('a').first
expect(link).to have_attribute('data-user')
expect(link.attr('data-user')).to eq user.namespace.owner_id.to_s
end
end
context 'mentioning a group' do context 'mentioning a group' do
it_behaves_like 'a reference containing an element node' it_behaves_like 'a reference containing an element node'
...@@ -154,36 +123,6 @@ describe Banzai::Filter::UserReferenceFilter do ...@@ -154,36 +123,6 @@ describe Banzai::Filter::UserReferenceFilter do
expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-project_member has-tooltip' expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-project_member has-tooltip'
end end
it 'supports an :only_path context' do
doc = reference_filter("Hey #{reference}", only_path: true)
link = doc.css('a').first.attr('href')
expect(link).not_to match %r(https?://)
expect(link).to eq urls.user_path(user)
end
context 'referencing a user in a link href' do
let(:reference) { %Q{<a href="#{user.to_reference}">User</a>} }
it 'links to a User' do
doc = reference_filter("Hey #{reference}")
expect(doc.css('a').first.attr('href')).to eq urls.user_url(user)
end
it 'links with adjacent text' do
doc = reference_filter("Mention me (#{reference}.)")
expect(doc.to_html).to match(%r{\(<a.+>User</a>\.\)})
end
it 'includes a data-user attribute' do
doc = reference_filter("Hey #{reference}")
link = doc.css('a').first
expect(link).to have_attribute('data-user')
expect(link.attr('data-user')).to eq user.namespace.owner_id.to_s
end
end
context 'when a project is not specified' do context 'when a project is not specified' do
let(:project) { nil } let(:project) { nil }
...@@ -227,7 +166,7 @@ describe Banzai::Filter::UserReferenceFilter do ...@@ -227,7 +166,7 @@ describe Banzai::Filter::UserReferenceFilter do
end end
it 'supports mentioning a single user' do it 'supports mentioning a single user' do
reference = group_member.to_reference reference = get_reference(group_member)
doc = reference_filter("Hey #{reference}", context) doc = reference_filter("Hey #{reference}", context)
expect(doc.css('a').first.attr('href')).to eq urls.user_url(group_member) expect(doc.css('a').first.attr('href')).to eq urls.user_url(group_member)
...@@ -243,7 +182,7 @@ describe Banzai::Filter::UserReferenceFilter do ...@@ -243,7 +182,7 @@ describe Banzai::Filter::UserReferenceFilter do
describe '#namespaces' do describe '#namespaces' do
it 'returns a Hash containing all Namespaces' do it 'returns a Hash containing all Namespaces' do
document = Nokogiri::HTML.fragment("<p>#{user.to_reference}</p>") document = Nokogiri::HTML.fragment("<p>#{get_reference(user)}</p>")
filter = described_class.new(document, project: project) filter = described_class.new(document, project: project)
ns = user.namespace ns = user.namespace
...@@ -253,7 +192,7 @@ describe Banzai::Filter::UserReferenceFilter do ...@@ -253,7 +192,7 @@ describe Banzai::Filter::UserReferenceFilter do
describe '#usernames' do describe '#usernames' do
it 'returns the usernames mentioned in a document' do it 'returns the usernames mentioned in a document' do
document = Nokogiri::HTML.fragment("<p>#{user.to_reference}</p>") document = Nokogiri::HTML.fragment("<p>#{get_reference(user)}</p>")
filter = described_class.new(document, project: project) filter = described_class.new(document, project: project)
expect(filter.usernames).to eq([user.username]) expect(filter.usernames).to eq([user.username])
......
require 'spec_helper'
describe Banzai::ReferenceParser::ProjectParser do
include ReferenceParserHelpers
let(:project) { create(:project, :public) }
let(:user) { create(:user) }
subject { described_class.new(Banzai::RenderContext.new(project, user)) }
let(:link) { empty_html_link }
describe '#referenced_by' do
describe 'when the link has a data-project attribute' do
context 'using an existing project ID' do
it 'returns an Array of projects' do
link['data-project'] = project.id.to_s
expect(subject.gather_references([link])).to eq([project])
end
end
context 'using a non-existing project ID' do
it 'returns an empty Array' do
link['data-project'] = ''
expect(subject.gather_references([link])).to eq([])
end
end
context 'using a private project ID' do
it 'returns an empty Array when unauthorized' do
private_project = create(:project, :private)
link['data-project'] = private_project.id.to_s
expect(subject.gather_references([link])).to eq([])
end
it 'returns an Array when authorized' do
private_project = create(:project, :private, namespace: user.namespace)
link['data-project'] = private_project.id.to_s
expect(subject.gather_references([link])).to eq([private_project])
end
end
end
end
end
...@@ -1103,6 +1103,12 @@ describe Ci::Build do ...@@ -1103,6 +1103,12 @@ describe Ci::Build do
it { is_expected.to be_cancelable } it { is_expected.to be_cancelable }
end end
context 'when build is created' do
let(:build) { create(:ci_build, :created) }
it { is_expected.to be_cancelable }
end
end end
context 'when build is not cancelable' do context 'when build is not cancelable' do
......
...@@ -364,6 +364,15 @@ describe Project do ...@@ -364,6 +364,15 @@ describe Project do
it { is_expected.to delegate_method(:name).to(:owner).with_prefix(true).with_arguments(allow_nil: true) } it { is_expected.to delegate_method(:name).to(:owner).with_prefix(true).with_arguments(allow_nil: true) }
end end
describe '#to_reference_with_postfix' do
it 'returns the full path with reference_postfix' do
namespace = create(:namespace, path: 'sample-namespace')
project = create(:project, path: 'sample-project', namespace: namespace)
expect(project.to_reference_with_postfix).to eq 'sample-namespace/sample-project>'
end
end
describe '#to_reference' do describe '#to_reference' do
let(:owner) { create(:user, name: 'Gitlab') } let(:owner) { create(:user, name: 'Gitlab') }
let(:namespace) { create(:namespace, path: 'sample-namespace', owner: owner) } let(:namespace) { create(:namespace, path: 'sample-namespace', owner: owner) }
......
require 'spec_helper'
require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/migration/add_reference'
describe RuboCop::Cop::Migration::AddReference do
include CopHelper
let(:cop) { described_class.new }
context 'outside of a migration' do
it 'does not register any offenses' do
expect_no_offenses(<<~RUBY)
def up
add_reference(:projects, :users)
end
RUBY
end
end
context 'in a migration' do
before do
allow(cop).to receive(:in_migration?).and_return(true)
end
it 'registers an offense when using add_reference without index' do
expect_offense(<<~RUBY)
call do
add_reference(:projects, :users)
^^^^^^^^^^^^^ `add_reference` requires `index: true`
end
RUBY
end
it 'registers an offense when using add_reference index disabled' do
expect_offense(<<~RUBY)
def up
add_reference(:projects, :users, index: false)
^^^^^^^^^^^^^ `add_reference` requires `index: true`
end
RUBY
end
it 'does not register an offense when using add_reference with index enabled' do
expect_no_offenses(<<~RUBY)
def up
add_reference(:projects, :users, index: true)
end
RUBY
end
end
end
require 'spec_helper'
describe ProjectMirrorSerializer do
it 'represents ProjectMirror entities' do
expect(described_class.entity_class).to eq(ProjectMirrorEntity)
end
end
...@@ -11,3 +11,76 @@ shared_examples 'a reference containing an element node' do ...@@ -11,3 +11,76 @@ shared_examples 'a reference containing an element node' do
expect(doc.children.first.inner_html).to eq(inner_html) expect(doc.children.first.inner_html).to eq(inner_html)
end end
end end
# Requires a reference, subject and subject_name:
# subject { create(:user) }
# let(:reference) { subject.to_reference }
# let(:subject_name) { 'user' }
shared_examples 'user reference or project reference' do
shared_examples 'it contains a data- attribute' do
it 'includes a data- attribute' do
doc = reference_filter("Hey #{reference}")
link = doc.css('a').first
expect(link).to have_attribute("data-#{subject_name}")
expect(link.attr("data-#{subject_name}")).to eq subject.id.to_s
end
end
context 'mentioning a resource' do
it_behaves_like 'a reference containing an element node'
it_behaves_like 'it contains a data- attribute'
it "links to a resource" do
doc = reference_filter("Hey #{reference}")
expect(doc.css('a').first.attr('href')).to eq urls.send("#{subject_name}_url", subject)
end
it 'links to a resource with a period' do
subject = create(subject_name.to_sym, name: 'alphA.Beta')
doc = reference_filter("Hey #{get_reference(subject)}")
expect(doc.css('a').length).to eq 1
end
it 'links to a resource with an underscore' do
subject = create(subject_name.to_sym, name: 'ping_pong_king')
doc = reference_filter("Hey #{get_reference(subject)}")
expect(doc.css('a').length).to eq 1
end
it 'links to a resource with different case-sensitivity' do
subject = create(subject_name.to_sym, name: 'RescueRanger')
reference = get_reference(subject)
doc = reference_filter("Hey #{reference.upcase}")
expect(doc.css('a').length).to eq 1
expect(doc.css('a').text).to eq(reference)
end
end
it 'supports an :only_path context' do
doc = reference_filter("Hey #{reference}", only_path: true)
link = doc.css('a').first.attr('href')
expect(link).not_to match %r(https?://)
expect(link).to eq urls.send "#{subject_name}_path", subject
end
context 'referencing a resource in a link href' do
let(:reference) { %Q{<a href="#{get_reference(subject)}">Some text</a>} }
it_behaves_like 'it contains a data- attribute'
it 'links to the resource' do
doc = reference_filter("Hey #{reference}")
expect(doc.css('a').first.attr('href')).to eq urls.send "#{subject_name}_url", subject
end
it 'links with adjacent text' do
doc = reference_filter("Mention me (#{reference}.)")
expect(doc.to_html).to match(%r{\(<a.+>Some text</a>\.\)})
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment