Commit 0d99298a authored by Shinya Maeda's avatar Shinya Maeda

Merge branch 'master' into live-trace-v2

parents 270b5867 87f1736a
...@@ -72,3 +72,4 @@ eslint-report.html ...@@ -72,3 +72,4 @@ eslint-report.html
/locale/**/*.time_stamp /locale/**/*.time_stamp
/.rspec /.rspec
/plugins/* /plugins/*
/.gitlab_pages_secret
...@@ -110,7 +110,7 @@ stages: ...@@ -110,7 +110,7 @@ stages:
# Jobs that only need to pull cache # Jobs that only need to pull cache
.dedicated-no-docs-pull-cache-job: &dedicated-no-docs-pull-cache-job .dedicated-no-docs-pull-cache-job: &dedicated-no-docs-pull-cache-job
<<: *dedicated-runner <<: *dedicated-runner
<<: *except-docs-and-qa <<: *except-docs
<<: *pull-cache <<: *pull-cache
dependencies: dependencies:
- setup-test-env - setup-test-env
...@@ -122,6 +122,10 @@ stages: ...@@ -122,6 +122,10 @@ stages:
variables: variables:
SETUP_DB: "false" SETUP_DB: "false"
.dedicated-no-docs-and-no-qa-pull-cache-job: &dedicated-no-docs-and-no-qa-pull-cache-job
<<: *dedicated-no-docs-pull-cache-job
<<: *except-docs-and-qa
.rake-exec: &rake-exec .rake-exec: &rake-exec
<<: *dedicated-no-docs-no-db-pull-cache-job <<: *dedicated-no-docs-no-db-pull-cache-job
script: script:
...@@ -222,7 +226,7 @@ stages: ...@@ -222,7 +226,7 @@ stages:
- master@gitlab/gitlab-ee - master@gitlab/gitlab-ee
.gitlab-setup: &gitlab-setup .gitlab-setup: &gitlab-setup
<<: *dedicated-no-docs-pull-cache-job <<: *dedicated-no-docs-and-no-qa-pull-cache-job
<<: *use-pg <<: *use-pg
variables: variables:
CREATE_DB_USER: "true" CREATE_DB_USER: "true"
...@@ -262,12 +266,12 @@ stages: ...@@ -262,12 +266,12 @@ stages:
# DB migration, rollback, and seed jobs # DB migration, rollback, and seed jobs
.db-migrate-reset: &db-migrate-reset .db-migrate-reset: &db-migrate-reset
<<: *dedicated-no-docs-pull-cache-job <<: *dedicated-no-docs-and-no-qa-pull-cache-job
script: script:
- bundle exec rake db:migrate:reset - bundle exec rake db:migrate:reset
.migration-paths: &migration-paths .migration-paths: &migration-paths
<<: *dedicated-no-docs-pull-cache-job <<: *dedicated-no-docs-and-no-qa-pull-cache-job
variables: variables:
CREATE_DB_USER: "true" CREATE_DB_USER: "true"
script: script:
...@@ -647,7 +651,7 @@ migration:path-mysql: ...@@ -647,7 +651,7 @@ migration:path-mysql:
<<: *use-mysql <<: *use-mysql
.db-rollback: &db-rollback .db-rollback: &db-rollback
<<: *dedicated-no-docs-pull-cache-job <<: *dedicated-no-docs-and-no-qa-pull-cache-job
script: script:
- bundle exec rake db:migrate VERSION=20170523121229 - bundle exec rake db:migrate VERSION=20170523121229
- bundle exec rake db:migrate - bundle exec rake db:migrate
...@@ -670,7 +674,7 @@ gitlab:setup-mysql: ...@@ -670,7 +674,7 @@ gitlab:setup-mysql:
# Frontend-related jobs # Frontend-related jobs
gitlab:assets:compile: gitlab:assets:compile:
<<: *dedicated-no-docs-no-db-pull-cache-job <<: *dedicated-no-docs-and-no-qa-pull-cache-job
dependencies: [] dependencies: []
variables: variables:
NODE_ENV: "production" NODE_ENV: "production"
...@@ -691,7 +695,7 @@ gitlab:assets:compile: ...@@ -691,7 +695,7 @@ gitlab:assets:compile:
- webpack-report/ - webpack-report/
karma: karma:
<<: *dedicated-no-docs-pull-cache-job <<: *dedicated-no-docs-and-no-qa-pull-cache-job
<<: *use-pg <<: *use-pg
dependencies: dependencies:
- compile-assets - compile-assets
...@@ -815,7 +819,7 @@ coverage: ...@@ -815,7 +819,7 @@ coverage:
- coverage/assets/ - coverage/assets/
lint:javascript:report: lint:javascript:report:
<<: *dedicated-no-docs-no-db-pull-cache-job <<: *dedicated-no-docs-and-no-qa-pull-cache-job
stage: post-test stage: post-test
dependencies: dependencies:
- compile-assets - compile-assets
......
class ListLabel { export default class ListLabel {
constructor(obj) { constructor(obj) {
this.id = obj.id; this.id = obj.id;
this.title = obj.title; this.title = obj.title;
......
...@@ -14,6 +14,7 @@ class PipelinesFinder ...@@ -14,6 +14,7 @@ class PipelinesFinder
items = by_scope(items) items = by_scope(items)
items = by_status(items) items = by_status(items)
items = by_ref(items) items = by_ref(items)
items = by_sha(items)
items = by_name(items) items = by_name(items)
items = by_username(items) items = by_username(items)
items = by_yaml_errors(items) items = by_yaml_errors(items)
...@@ -69,6 +70,14 @@ class PipelinesFinder ...@@ -69,6 +70,14 @@ class PipelinesFinder
end end
end end
def by_sha(items)
if params[:sha].present?
items.where(sha: params[:sha])
else
items
end
end
def by_name(items) def by_name(items)
if params[:name].present? if params[:name].present?
items.joins(:user).where(users: { name: params[:name] }) items.joins(:user).where(users: { name: params[:name] })
......
...@@ -159,7 +159,7 @@ module SystemNoteService ...@@ -159,7 +159,7 @@ module SystemNoteService
body = if noteable.time_estimate == 0 body = if noteable.time_estimate == 0
"removed time estimate" "removed time estimate"
else else
"changed time estimate to #{parsed_time}," "changed time estimate to #{parsed_time}"
end end
create_note(NoteSummary.new(noteable, project, author, body, action: 'time_tracking')) create_note(NoteSummary.new(noteable, project, author, body, action: 'time_tracking'))
......
...@@ -17,14 +17,14 @@ ...@@ -17,14 +17,14 @@
.ci-variable-row-body .ci-variable-row-body
%input.js-ci-variable-input-id{ type: "hidden", name: id_input_name, value: id } %input.js-ci-variable-input-id{ type: "hidden", name: id_input_name, value: id }
%input.js-ci-variable-input-destroy{ type: "hidden", name: destroy_input_name } %input.js-ci-variable-input-destroy{ type: "hidden", name: destroy_input_name }
%input.js-ci-variable-input-key.ci-variable-body-item.form-control{ type: "text", %input.js-ci-variable-input-key.ci-variable-body-item.qa-ci-variable-input-key.form-control{ type: "text",
name: key_input_name, name: key_input_name,
value: key, value: key,
placeholder: s_('CiVariables|Input variable key') } placeholder: s_('CiVariables|Input variable key') }
.ci-variable-body-item .ci-variable-body-item
.form-control.js-secret-value-placeholder{ class: ('hide' unless id) } .form-control.js-secret-value-placeholder.qa-ci-variable-input-value{ class: ('hide' unless id) }
= '*' * 20 = '*' * 20
%textarea.js-ci-variable-input-value.js-secret-value.form-control{ class: ('hide' if id), %textarea.js-ci-variable-input-value.js-secret-value.qa-ci-variable-input-value.form-control{ class: ('hide' if id),
rows: 1, rows: 1,
name: value_input_name, name: value_input_name,
placeholder: s_('CiVariables|Input variable value') } placeholder: s_('CiVariables|Input variable value') }
......
- content_for :merge_access_levels do - content_for :merge_access_levels do
.merge_access_levels-container .merge_access_levels-container
= dropdown_tag('Select', = dropdown_tag('Select',
options: { toggle_class: 'js-allowed-to-merge wide', options: { toggle_class: 'js-allowed-to-merge qa-allowed-to-merge-select wide',
dropdown_class: 'dropdown-menu-selectable capitalize-header', dropdown_class: 'dropdown-menu-selectable qa-allowed-to-merge-dropdown capitalize-header',
data: { field_name: 'protected_branch[merge_access_levels_attributes][0][access_level]', input_id: 'merge_access_levels_attributes' }}) data: { field_name: 'protected_branch[merge_access_levels_attributes][0][access_level]', input_id: 'merge_access_levels_attributes' }})
- content_for :push_access_levels do - content_for :push_access_levels do
.push_access_levels-container .push_access_levels-container
......
%td %td
= hidden_field_tag "allowed_to_merge_#{protected_branch.id}", protected_branch.merge_access_levels.first.access_level = hidden_field_tag "allowed_to_merge_#{protected_branch.id}", protected_branch.merge_access_levels.first.access_level
= dropdown_tag( (protected_branch.merge_access_levels.first.humanize || 'Select') , = dropdown_tag( (protected_branch.merge_access_levels.first.humanize || 'Select') ,
options: { toggle_class: 'js-allowed-to-merge', dropdown_class: 'dropdown-menu-selectable js-allowed-to-merge-container capitalize-header', options: { toggle_class: 'js-allowed-to-merge qa-allowed-to-merge', dropdown_class: 'dropdown-menu-selectable js-allowed-to-merge-container capitalize-header',
data: { field_name: "allowed_to_merge_#{protected_branch.id}", access_level_id: protected_branch.merge_access_levels.first.id }}) data: { field_name: "allowed_to_merge_#{protected_branch.id}", access_level_id: protected_branch.merge_access_levels.first.id }})
%td %td
= hidden_field_tag "allowed_to_push_#{protected_branch.id}", protected_branch.push_access_levels.first.access_level = hidden_field_tag "allowed_to_push_#{protected_branch.id}", protected_branch.push_access_levels.first.access_level
......
...@@ -36,5 +36,6 @@ ...@@ -36,5 +36,6 @@
= form.text_field :domain, class: 'form-control', placeholder: 'domain.com' = form.text_field :domain, class: 'form-control', placeholder: 'domain.com'
.help-block .help-block
= s_('CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages.') = s_('CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages.')
= link_to icon('question-circle'), help_page_path('topics/autodevops/index.md', anchor: 'auto-devops-base-domain'), target: '_blank'
= f.submit 'Save changes', class: "btn btn-success prepend-top-15" = f.submit 'Save changes', class: "btn btn-success prepend-top-15"
---
title: Add sha filter to pipelines list API
merge_request: 18125
author:
type: changed
---
title: Repository#exists? is always executed through Gitaly
merge_request:
author:
type: performance
...@@ -184,18 +184,18 @@ production: &base ...@@ -184,18 +184,18 @@ production: &base
# base_dir: uploads/-/system # base_dir: uploads/-/system
object_store: object_store:
enabled: false enabled: false
# remote_directory: uploads # Bucket name remote_directory: uploads # Bucket name
# direct_upload: false # Use Object Storage directly for uploads instead of background uploads if enabled (Default: false) # direct_upload: false # Use Object Storage directly for uploads instead of background uploads if enabled (Default: false)
# background_upload: false # Temporary option to limit automatic upload (Default: true) # background_upload: false # Temporary option to limit automatic upload (Default: true)
# proxy_download: false # Passthrough all downloads via GitLab instead of using Redirects to Object Storage # proxy_download: false # Passthrough all downloads via GitLab instead of using Redirects to Object Storage
connection: connection:
provider: AWS provider: AWS
aws_access_key_id: AWS_ACCESS_KEY_ID aws_access_key_id: AWS_ACCESS_KEY_ID
aws_secret_access_key: AWS_SECRET_ACCESS_KEY aws_secret_access_key: AWS_SECRET_ACCESS_KEY
region: us-east-1 region: us-east-1
# host: 'localhost' # default: s3.amazonaws.com # host: 'localhost' # default: s3.amazonaws.com
# endpoint: 'http://127.0.0.1:9000' # default: nil # endpoint: 'http://127.0.0.1:9000' # default: nil
# path_style: true # Use 'host/bucket_name/object' instead of 'bucket_name.host/object' # path_style: true # Use 'host/bucket_name/object' instead of 'bucket_name.host/object'
## GitLab Pages ## GitLab Pages
pages: pages:
...@@ -212,6 +212,8 @@ production: &base ...@@ -212,6 +212,8 @@ production: &base
artifacts_server: true artifacts_server: true
# external_http: ["1.1.1.1:80", "[2001::1]:80"] # If defined, enables custom domain support in GitLab Pages # external_http: ["1.1.1.1:80", "[2001::1]:80"] # If defined, enables custom domain support in GitLab Pages
# external_https: ["1.1.1.1:443", "[2001::1]:443"] # If defined, enables custom domain and certificate support in GitLab Pages # external_https: ["1.1.1.1:443", "[2001::1]:443"] # If defined, enables custom domain and certificate support in GitLab Pages
admin:
address: unix:/home/git/gitlab/tmp/sockets/private/pages-admin.socket # TCP connections are supported too (e.g. tcp://host:port)
## Mattermost ## Mattermost
## For enabling Add to Mattermost button ## For enabling Add to Mattermost button
......
...@@ -215,6 +215,9 @@ Settings.pages['external_http'] ||= false unless Settings.pages['external_ht ...@@ -215,6 +215,9 @@ Settings.pages['external_http'] ||= false unless Settings.pages['external_ht
Settings.pages['external_https'] ||= false unless Settings.pages['external_https'].present? Settings.pages['external_https'] ||= false unless Settings.pages['external_https'].present?
Settings.pages['artifacts_server'] ||= Settings.pages['enabled'] if Settings.pages['artifacts_server'].nil? Settings.pages['artifacts_server'] ||= Settings.pages['enabled'] if Settings.pages['artifacts_server'].nil?
Settings.pages['admin'] ||= Settingslogic.new({})
Settings.pages.admin['certificate'] ||= ''
# #
# Git LFS # Git LFS
# #
......
Gitlab::PagesClient.read_or_create_token
Gitlab::PagesClient.load_certificate
...@@ -323,7 +323,7 @@ The prerequisites for a HA Redis setup are the following: ...@@ -323,7 +323,7 @@ The prerequisites for a HA Redis setup are the following:
# machines to connect to it. # machines to connect to it.
redis['port'] = 6379 redis['port'] = 6379
# The same password for Redeis authentication you set up for the master node. # The same password for Redis authentication you set up for the master node.
redis['password'] = 'redis-password-goes-here' redis['password'] = 'redis-password-goes-here'
# The IP of the master Redis node. # The IP of the master Redis node.
......
...@@ -107,7 +107,7 @@ For source installations the following settings are nested under `artifacts:` an ...@@ -107,7 +107,7 @@ For source installations the following settings are nested under `artifacts:` an
| Setting | Description | Default | | Setting | Description | Default |
|---------|-------------|---------| |---------|-------------|---------|
| `enabled` | Enable/disable object storage | `false` | | `enabled` | Enable/disable object storage | `false` |
| `remote_directory` | The bucket name where Artfacts will be stored| | | `remote_directory` | The bucket name where Artifacts will be stored| |
| `direct_upload` | Set to true to enable direct upload of Artifacts without the need of local shared storage. Option may be removed once we decide to support only single storage for all files. Currently only `Google` provider is supported | `false` | | `direct_upload` | Set to true to enable direct upload of Artifacts without the need of local shared storage. Option may be removed once we decide to support only single storage for all files. Currently only `Google` provider is supported | `false` |
| `background_upload` | Set to false to disable automatic upload. Option may be removed once upload is direct to S3 | `true` | | `background_upload` | Set to false to disable automatic upload. Option may be removed once upload is direct to S3 | `true` |
| `proxy_download` | Set to true to enable proxying all files served. Option allows to reduce egress traffic as this allows clients to download directly from remote storage instead of proxying all data | `false` | | `proxy_download` | Set to true to enable proxying all files served. Option allows to reduce egress traffic as this allows clients to download directly from remote storage instead of proxying all data | `false` |
...@@ -148,7 +148,7 @@ _The artifacts are stored by default in ...@@ -148,7 +148,7 @@ _The artifacts are stored by default in
``` ```
NOTE: For GitLab 9.4+, if you are using AWS IAM profiles, be sure to omit the NOTE: For GitLab 9.4+, if you are using AWS IAM profiles, be sure to omit the
AWS access key and secret acces key/value pairs. For example: AWS access key and secret access key/value pairs. For example:
```ruby ```ruby
gitlab_rails['artifacts_object_store_connection'] = { gitlab_rails['artifacts_object_store_connection'] = {
......
...@@ -46,7 +46,7 @@ In this experimental phase, only a few metrics are available: ...@@ -46,7 +46,7 @@ In this experimental phase, only a few metrics are available:
| redis_ping_latency_seconds | Gauge | 9.4 | Round trip time of the redis ping | | redis_ping_latency_seconds | Gauge | 9.4 | Round trip time of the redis ping |
| user_session_logins_total | Counter | 9.4 | Counter of how many users have logged in | | user_session_logins_total | Counter | 9.4 | Counter of how many users have logged in |
| filesystem_circuitbreaker_latency_seconds | Gauge | 9.5 | Time spent validating if a storage is accessible | | filesystem_circuitbreaker_latency_seconds | Gauge | 9.5 | Time spent validating if a storage is accessible |
| filesystem_circuitbreaker | Gauge | 9.5 | Wether or not the circuit for a certain shard is broken or not | | filesystem_circuitbreaker | Gauge | 9.5 | Whether or not the circuit for a certain shard is broken or not |
| circuitbreaker_storage_check_duration_seconds | Histogram | 10.3 | Time a single storage probe took | | circuitbreaker_storage_check_duration_seconds | Histogram | 10.3 | Time a single storage probe took |
## Metrics shared directory ## Metrics shared directory
......
...@@ -31,7 +31,7 @@ GitLab Shell provides a way to authorize SSH users via a fast, indexed lookup ...@@ -31,7 +31,7 @@ GitLab Shell provides a way to authorize SSH users via a fast, indexed lookup
to the GitLab database. GitLab Shell uses the fingerprint of the SSH key to to the GitLab database. GitLab Shell uses the fingerprint of the SSH key to
check whether the user is authorized to access GitLab. check whether the user is authorized to access GitLab.
Add the following to your `sshd_config` file. This is usuaully located at Add the following to your `sshd_config` file. This is usually located at
`/etc/ssh/sshd_config`, but it will be `/assets/sshd_config` if you're using `/etc/ssh/sshd_config`, but it will be `/assets/sshd_config` if you're using
Omnibus Docker: Omnibus Docker:
......
...@@ -104,7 +104,7 @@ _The uploads are stored by default in ...@@ -104,7 +104,7 @@ _The uploads are stored by default in
``` ```
>**Note:** >**Note:**
If you are using AWS IAM profiles, be sure to omit the AWS access key and secret acces key/value pairs. If you are using AWS IAM profiles, be sure to omit the AWS access key and secret access key/value pairs.
```ruby ```ruby
gitlab_rails['uploads_object_store_connection'] = { gitlab_rails['uploads_object_store_connection'] = {
......
...@@ -293,7 +293,7 @@ The following table gives an overview of how the API functions generally behave. ...@@ -293,7 +293,7 @@ The following table gives an overview of how the API functions generally behave.
| `GET` | Access one or more resources and return the result as JSON. | | `GET` | Access one or more resources and return the result as JSON. |
| `POST` | Return `201 Created` if the resource is successfully created and return the newly created resource as JSON. | | `POST` | Return `201 Created` if the resource is successfully created and return the newly created resource as JSON. |
| `GET` / `PUT` | Return `200 OK` if the resource is accessed or modified successfully. The (modified) result is returned as JSON. | | `GET` / `PUT` | Return `200 OK` if the resource is accessed or modified successfully. The (modified) result is returned as JSON. |
| `DELETE` | Returns `204 No Content` if the resuource was deleted successfully. | | `DELETE` | Returns `204 No Content` if the resource was deleted successfully. |
The following table shows the possible return codes for API requests. The following table shows the possible return codes for API requests.
......
...@@ -12,7 +12,7 @@ Badges support placeholders that will be replaced in real time in both the link ...@@ -12,7 +12,7 @@ Badges support placeholders that will be replaced in real time in both the link
- **%{default_branch}**: will be replaced by the project default branch. - **%{default_branch}**: will be replaced by the project default branch.
- **%{commit_sha}**: will be replaced by the last project's commit sha. - **%{commit_sha}**: will be replaced by the last project's commit sha.
Because these enpoints aren't inside a project's context, the information used to replace the placeholders will be Because these endpoints aren't inside a project's context, the information used to replace the placeholders will be
from the first group's project by creation date. If the group hasn't got any project the original URL with the placeholders will be returned. from the first group's project by creation date. If the group hasn't got any project the original URL with the placeholders will be returned.
## List all badges of a group ## List all badges of a group
......
...@@ -108,7 +108,7 @@ POST /projects/:id/pipeline_schedules ...@@ -108,7 +108,7 @@ POST /projects/:id/pipeline_schedules
| `description` | string | yes | The description of pipeline schedule | | `description` | string | yes | The description of pipeline schedule |
| `ref` | string | yes | The branch/tag name will be triggered | | `ref` | string | yes | The branch/tag name will be triggered |
| `cron ` | string | yes | The cron (e.g. `0 1 * * *`) ([Cron syntax](https://en.wikipedia.org/wiki/Cron)) | | `cron ` | string | yes | The cron (e.g. `0 1 * * *`) ([Cron syntax](https://en.wikipedia.org/wiki/Cron)) |
| `cron_timezone ` | string | no | The timezone supproted by `ActiveSupport::TimeZone` (e.g. `Pacific Time (US & Canada)`) (default: `'UTC'`) | | `cron_timezone ` | string | no | The timezone supported by `ActiveSupport::TimeZone` (e.g. `Pacific Time (US & Canada)`) (default: `'UTC'`) |
| `active ` | boolean | no | The activation of pipeline schedule. If false is set, the pipeline schedule will deactivated initially (default: `true`) | | `active ` | boolean | no | The activation of pipeline schedule. If false is set, the pipeline schedule will deactivated initially (default: `true`) |
```sh ```sh
...@@ -153,7 +153,7 @@ PUT /projects/:id/pipeline_schedules/:pipeline_schedule_id ...@@ -153,7 +153,7 @@ PUT /projects/:id/pipeline_schedules/:pipeline_schedule_id
| `description` | string | no | The description of pipeline schedule | | `description` | string | no | The description of pipeline schedule |
| `ref` | string | no | The branch/tag name will be triggered | | `ref` | string | no | The branch/tag name will be triggered |
| `cron ` | string | no | The cron (e.g. `0 1 * * *`) ([Cron syntax](https://en.wikipedia.org/wiki/Cron)) | | `cron ` | string | no | The cron (e.g. `0 1 * * *`) ([Cron syntax](https://en.wikipedia.org/wiki/Cron)) |
| `cron_timezone ` | string | no | The timezone supproted by `ActiveSupport::TimeZone` (e.g. `Pacific Time (US & Canada)`) or `TZInfo::Timezone` (e.g. `America/Los_Angeles`) | | `cron_timezone ` | string | no | The timezone supported by `ActiveSupport::TimeZone` (e.g. `Pacific Time (US & Canada)`) or `TZInfo::Timezone` (e.g. `America/Los_Angeles`) |
| `active ` | boolean | no | The activation of pipeline schedule. If false is set, the pipeline schedule will deactivated initially. | | `active ` | boolean | no | The activation of pipeline schedule. If false is set, the pipeline schedule will deactivated initially. |
```sh ```sh
......
...@@ -14,6 +14,7 @@ GET /projects/:id/pipelines ...@@ -14,6 +14,7 @@ GET /projects/:id/pipelines
| `scope` | string | no | The scope of pipelines, one of: `running`, `pending`, `finished`, `branches`, `tags` | | `scope` | string | no | The scope of pipelines, one of: `running`, `pending`, `finished`, `branches`, `tags` |
| `status` | string | no | The status of pipelines, one of: `running`, `pending`, `success`, `failed`, `canceled`, `skipped` | | `status` | string | no | The status of pipelines, one of: `running`, `pending`, `success`, `failed`, `canceled`, `skipped` |
| `ref` | string | no | The ref of pipelines | | `ref` | string | no | The ref of pipelines |
| `sha` | string | no | The sha or pipelines |
| `yaml_errors`| boolean | no | Returns pipelines with invalid configurations | | `yaml_errors`| boolean | no | Returns pipelines with invalid configurations |
| `name`| string | no | The name of the user who triggered pipelines | | `name`| string | no | The name of the user who triggered pipelines |
| `username`| string | no | The username of the user who triggered pipelines | | `username`| string | no | The username of the user who triggered pipelines |
......
...@@ -509,7 +509,7 @@ and unit tests, all running and deployed at every push to master - with shocking ...@@ -509,7 +509,7 @@ and unit tests, all running and deployed at every push to master - with shocking
Errors can be easily debugged through GitLab's build logs, and within minutes of a successful commit, Errors can be easily debugged through GitLab's build logs, and within minutes of a successful commit,
you can see the changes live on your game. you can see the changes live on your game.
Setting up Continous Integration and Continuous Deployment from the start with Dark Nova enables Setting up Continuous Integration and Continuous Deployment from the start with Dark Nova enables
rapid but stable development. We can easily test changes in a separate [environment](../../../ci/environments.md#introduction-to-environments-and-deployments), rapid but stable development. We can easily test changes in a separate [environment](../../../ci/environments.md#introduction-to-environments-and-deployments),
or multiple environments if needed. Balancing and updating a multiplayer game can be ongoing or multiple environments if needed. Balancing and updating a multiplayer game can be ongoing
and tedious, but having faith in a stable deployment with GitLab CI/CD allows and tedious, but having faith in a stable deployment with GitLab CI/CD allows
......
...@@ -30,7 +30,7 @@ and GitLab UI._ ...@@ -30,7 +30,7 @@ and GitLab UI._
Many components and concepts are similar to Ruby on Rails or Python's Django. High developer Many components and concepts are similar to Ruby on Rails or Python's Django. High developer
productivity and high application performance are only a few advantages on learning how to use it. productivity and high application performance are only a few advantages on learning how to use it.
Working on the MVC pattern, it's was designed to be modular and flexible. Easy to mantain a growing Working on the MVC pattern, it's was designed to be modular and flexible. Easy to maintain a growing
app is a plus. app is a plus.
Phoenix can run in any OS where Erlang is supported: Phoenix can run in any OS where Erlang is supported:
...@@ -48,7 +48,7 @@ Check the [Phoenix learning guide][phoenix-learning-guide] for more information. ...@@ -48,7 +48,7 @@ Check the [Phoenix learning guide][phoenix-learning-guide] for more information.
### What is Elixir? ### What is Elixir?
[Elixir][elixir-site] is a dynamic, functional language created to use all the maturity of Erlang [Elixir][elixir-site] is a dynamic, functional language created to use all the maturity of Erlang
(30 years old!) in these days, in an easy way. It has similarities with Ruby, specially on sintax, (30 years old!) in these days, in an easy way. It has similarities with Ruby, specially on syntax,
so Ruby developers are quite excited with the rapid growing of Elixir. A full-stack Ruby developer so Ruby developers are quite excited with the rapid growing of Elixir. A full-stack Ruby developer
can learn how to use Elixir and Phoenix in just a few weeks! can learn how to use Elixir and Phoenix in just a few weeks!
...@@ -162,7 +162,7 @@ productive, because every time we, or our co-workers push any code, GitLab CI/CD ...@@ -162,7 +162,7 @@ productive, because every time we, or our co-workers push any code, GitLab CI/CD
test the changes, telling us in realtime if anything goes wrong. test the changes, telling us in realtime if anything goes wrong.
Certainly, when our application starts to grow, we'll need more developers working on the same Certainly, when our application starts to grow, we'll need more developers working on the same
project and this process of building and testing can easely become a mess without proper management. project and this process of building and testing can easily become a mess without proper management.
That's also why GitLab CI/CD is so important to our application. Every time someone pushes its code to That's also why GitLab CI/CD is so important to our application. Every time someone pushes its code to
GitLab, we'll quickly know if their changes broke something or not. We don't need to stop everything GitLab, we'll quickly know if their changes broke something or not. We don't need to stop everything
we're doing to test manually and locally every change our team does. we're doing to test manually and locally every change our team does.
...@@ -237,7 +237,7 @@ Finished in 0.7 seconds ...@@ -237,7 +237,7 @@ Finished in 0.7 seconds
Randomized with seed 610000 Randomized with seed 610000
``` ```
Our test was successfull. It's time to push our files to GitLab. Our test was successful. It's time to push our files to GitLab.
## Configuring CI/CD Pipeline ## Configuring CI/CD Pipeline
...@@ -302,7 +302,7 @@ template** and select **Elixir**: ...@@ -302,7 +302,7 @@ template** and select **Elixir**:
``` ```
It's important to install `postgresql-client` to let GitLab CI/CD access PostgreSQL and create our It's important to install `postgresql-client` to let GitLab CI/CD access PostgreSQL and create our
database with the login information provided earlier. More important is to respect the identation, database with the login information provided earlier. More important is to respect the indentation,
to avoid syntax errors when running the build. to avoid syntax errors when running the build.
- And finally, we'll let `mix` session intact. - And finally, we'll let `mix` session intact.
...@@ -333,7 +333,7 @@ mix: ...@@ -333,7 +333,7 @@ mix:
- mix test - mix test
``` ```
For safety, we can check if we get any syntax errors before submiting this file to GitLab. Copy the For safety, we can check if we get any syntax errors before submitting this file to GitLab. Copy the
contents of `.gitlab-ci.yml` and paste it on [GitLab CI/CD Lint tool][ci-lint]. Please note that contents of `.gitlab-ci.yml` and paste it on [GitLab CI/CD Lint tool][ci-lint]. Please note that
this link will only work for logged in users. this link will only work for logged in users.
...@@ -384,7 +384,7 @@ working properly. ...@@ -384,7 +384,7 @@ working properly.
When we have a growing application with many developers working on it, or when we have an open When we have a growing application with many developers working on it, or when we have an open
source project being watched and contributed by the community, it is really important to have our source project being watched and contributed by the community, it is really important to have our
code permanently working. GitLab CI/CD is a time saving powerfull tool to help us mantain our code code permanently working. GitLab CI/CD is a time saving powerful tool to help us maintain our code
organized and working. organized and working.
As we could see in this post, GitLab CI/CD is really really easy to configure and use. We have [many As we could see in this post, GitLab CI/CD is really really easy to configure and use. We have [many
......
...@@ -551,7 +551,7 @@ You can find a full list of unsupported variables below: ...@@ -551,7 +551,7 @@ You can find a full list of unsupported variables below:
- `CI_DEPLOY_USER` - `CI_DEPLOY_USER`
- `CI_DEPLOY_PASSWORD` - `CI_DEPLOY_PASSWORD`
These variables are also not supported in a contex of a These variables are also not supported in a context of a
[dynamic environment name][dynamic-environments]. [dynamic environment name][dynamic-environments].
[ce-13784]: https://gitlab.com/gitlab-org/gitlab-ce/issues/13784 "Simple protection of CI secret variables" [ce-13784]: https://gitlab.com/gitlab-org/gitlab-ce/issues/13784 "Simple protection of CI secret variables"
......
...@@ -24,7 +24,7 @@ Some examples where background migrations can be useful: ...@@ -24,7 +24,7 @@ Some examples where background migrations can be useful:
* Migrating events from one table to multiple separate tables. * Migrating events from one table to multiple separate tables.
* Populating one column based on JSON stored in another column. * Populating one column based on JSON stored in another column.
* Migrating data that depends on the output of exernal services (e.g. an API). * Migrating data that depends on the output of external services (e.g. an API).
## Isolation ## Isolation
...@@ -46,7 +46,7 @@ See [Sidekiq best practices guidelines](https://github.com/mperham/sidekiq/wiki/ ...@@ -46,7 +46,7 @@ See [Sidekiq best practices guidelines](https://github.com/mperham/sidekiq/wiki/
for more details. for more details.
Make sure that in case that your migration job is going to be retried data Make sure that in case that your migration job is going to be retried data
integrity is guarateed. integrity is guaranteed.
## How It Works ## How It Works
......
...@@ -4,7 +4,7 @@ The documentation style guide defines the markup structure used in ...@@ -4,7 +4,7 @@ The documentation style guide defines the markup structure used in
GitLab documentation. Check the GitLab documentation. Check the
[documentation guidelines](writing_documentation.md) for general development instructions. [documentation guidelines](writing_documentation.md) for general development instructions.
Check the GitLab hanbook for the [writing styles guidelines](https://about.gitlab.com/handbook/communication/#writing-style-guidelines). Check the GitLab handbook for the [writing styles guidelines](https://about.gitlab.com/handbook/communication/#writing-style-guidelines).
## Text ## Text
...@@ -19,7 +19,7 @@ Check the GitLab hanbook for the [writing styles guidelines](https://about.gitla ...@@ -19,7 +19,7 @@ Check the GitLab hanbook for the [writing styles guidelines](https://about.gitla
- Unless there's a logical reason not to, add documents in alphabetical order - Unless there's a logical reason not to, add documents in alphabetical order
- Write in US English - Write in US English
- Use [single spaces][] instead of double spaces - Use [single spaces][] instead of double spaces
- Jump a line between different markups (e.g., after every paragraph, hearder, list, etc) - Jump a line between different markups (e.g., after every paragraph, header, list, etc)
- Capitalize "G" and "L" in GitLab - Capitalize "G" and "L" in GitLab
- Capitalize feature, products, and methods names. E.g.: GitLab Runner, Geo, - Capitalize feature, products, and methods names. E.g.: GitLab Runner, Geo,
Issue Boards, Git, Prometheus, Continuous Integration. Issue Boards, Git, Prometheus, Continuous Integration.
......
...@@ -279,7 +279,7 @@ end ...@@ -279,7 +279,7 @@ end
``` ```
In `lib/gitlab/visibility_level.rb` this method is used to return the In `lib/gitlab/visibility_level.rb` this method is used to return the
allowed visibilty levels: allowed visibility levels:
```ruby ```ruby
def levels_for_user(user = nil) def levels_for_user(user = nil)
......
...@@ -236,7 +236,7 @@ export class Foo { ...@@ -236,7 +236,7 @@ export class Foo {
} }
``` ```
On the other hand, if a class only needs to extend a third party/add event listeners in some specific cases, they should be initialized oustside of the constructor. On the other hand, if a class only needs to extend a third party/add event listeners in some specific cases, they should be initialized outside of the constructor.
1. Prefer `.map`, `.reduce` or `.filter` over `.forEach` 1. Prefer `.map`, `.reduce` or `.filter` over `.forEach`
A forEach will most likely cause side effects, it will be mutating the array being iterated. Prefer using `.map`, A forEach will most likely cause side effects, it will be mutating the array being iterated. Prefer using `.map`,
......
...@@ -84,7 +84,7 @@ The `RecordsUploads::Concern` concern will create an `Upload` entry for every fi ...@@ -84,7 +84,7 @@ The `RecordsUploads::Concern` concern will create an `Upload` entry for every fi
By including the `ObjectStorage::Concern` in the `GitlabUploader` derived class, you may enable the object storage for this uploader. To enable the object storage By including the `ObjectStorage::Concern` in the `GitlabUploader` derived class, you may enable the object storage for this uploader. To enable the object storage
in your uploader, you need to either 1) include `RecordsUpload::Concern` and prepend `ObjectStorage::Extension::RecordsUploads` or 2) mount the uploader and create a new field named `<mount>_store`. in your uploader, you need to either 1) include `RecordsUpload::Concern` and prepend `ObjectStorage::Extension::RecordsUploads` or 2) mount the uploader and create a new field named `<mount>_store`.
The `CarrierWave::Uploader#store_dir` is overriden to The `CarrierWave::Uploader#store_dir` is overridden to
- `GitlabUploader.base_dir` + `GitlabUploader.dynamic_segment` when the store is LOCAL - `GitlabUploader.base_dir` + `GitlabUploader.dynamic_segment` when the store is LOCAL
- `GitlabUploader.dynamic_segment` when the store is REMOTE (the bucket name is used to namespace) - `GitlabUploader.dynamic_segment` when the store is REMOTE (the bucket name is used to namespace)
......
...@@ -270,7 +270,7 @@ If there are merge conflicts in the `gitlab.pot` file, you can delete the file ...@@ -270,7 +270,7 @@ If there are merge conflicts in the `gitlab.pot` file, you can delete the file
and regenerate it using the same command. Confirm that you are not deleting any strings accidentally by looking over the diff. and regenerate it using the same command. Confirm that you are not deleting any strings accidentally by looking over the diff.
The command also updates the translation files for each language: `locale/*/gitlab.po` The command also updates the translation files for each language: `locale/*/gitlab.po`
These changes can be discarded, the languange files will be updated by Crowdin These changes can be discarded, the language files will be updated by Crowdin
automatically. automatically.
Discard all of them at once like this: Discard all of them at once like this:
......
...@@ -162,7 +162,7 @@ need for running complex operations to fetch the data. You should use Redis if ...@@ -162,7 +162,7 @@ need for running complex operations to fetch the data. You should use Redis if
data should be cached for a certain time period instead of the duration of the data should be cached for a certain time period instead of the duration of the
transaction. transaction.
For example, say you process multiple snippets of text containiner username For example, say you process multiple snippets of text containing username
mentions (e.g. `Hello @alice` and `How are you doing @alice?`). By caching the mentions (e.g. `Hello @alice` and `How are you doing @alice?`). By caching the
user objects for every username we can remove the need for running the same user objects for every username we can remove the need for running the same
query for every mention of `@alice`. query for every mention of `@alice`.
......
...@@ -30,7 +30,7 @@ example) at the end. ...@@ -30,7 +30,7 @@ example) at the end.
## Type Sizes ## Type Sizes
While the PostgreSQL docuemntation While the PostgreSQL documentation
(https://www.postgresql.org/docs/current/static/datatype.html) contains plenty (https://www.postgresql.org/docs/current/static/datatype.html) contains plenty
of information we will list the sizes of common types here so it's easier to of information we will list the sizes of common types here so it's easier to
look them up. Here "word" refers to the word size, which is 4 bytes for a 32 look them up. Here "word" refers to the word size, which is 4 bytes for a 32
......
...@@ -28,7 +28,7 @@ records should use stubs/doubles as much as possible. ...@@ -28,7 +28,7 @@ records should use stubs/doubles as much as possible.
| `app/uploaders/` | `spec/uploaders/` | RSpec | | | `app/uploaders/` | `spec/uploaders/` | RSpec | |
| `app/views/` | `spec/views/` | RSpec | | | `app/views/` | `spec/views/` | RSpec | |
| `app/workers/` | `spec/workers/` | RSpec | | | `app/workers/` | `spec/workers/` | RSpec | |
| `app/assets/javascripts/` | `spec/javascripts/` | Karma | More details in the [Frontent Testing guide](frontend_testing.md) section. | | `app/assets/javascripts/` | `spec/javascripts/` | Karma | More details in the [Frontend Testing guide](frontend_testing.md) section. |
## Integration tests ## Integration tests
......
...@@ -219,7 +219,7 @@ Blocks are a way to group related information. ...@@ -219,7 +219,7 @@ Blocks are a way to group related information.
#### Content blocks #### Content blocks
Content blocks (`.content-block`) are the basic grouping of content. They are commonly used in [lists](#lists), and are separated by a botton border. Content blocks (`.content-block`) are the basic grouping of content. They are commonly used in [lists](#lists), and are separated by a button border.
![Content block](img/components-contentblock.png) ![Content block](img/components-contentblock.png)
...@@ -281,7 +281,7 @@ Modals are only used for having a conversation and confirmation with the user. T ...@@ -281,7 +281,7 @@ Modals are only used for having a conversation and confirmation with the user. T
| Modal with 2 actions | Modal with 3 actions | Special confirmation | | Modal with 2 actions | Modal with 3 actions | Special confirmation |
| --------------------- | --------------------- | -------------------- | | --------------------- | --------------------- | -------------------- |
| ![two-actions](img/modals-general-confimation-dialog.png) | ![three-actions](img/modals-three-buttons.png) | ![spcial-confirmation](img/modals-special-confimation-dialog.png) | | ![two-actions](img/modals-general-confimation-dialog.png) | ![three-actions](img/modals-three-buttons.png) | ![special-confirmation](img/modals-special-confimation-dialog.png) |
> TODO: Special case for modal. > TODO: Special case for modal.
......
...@@ -255,7 +255,7 @@ otherwise it will raise a `TypeError`. ...@@ -255,7 +255,7 @@ otherwise it will raise a `TypeError`.
## Adding Indexes ## Adding Indexes
Adding indexes is an expensive process that blocks INSERT and UPDATE queries for Adding indexes is an expensive process that blocks INSERT and UPDATE queries for
the duration. When using PostgreSQL one can work arounds this by using the the duration. When using PostgreSQL one can work around this by using the
`CONCURRENTLY` option: `CONCURRENTLY` option:
```sql ```sql
......
...@@ -49,7 +49,7 @@ do before. ...@@ -49,7 +49,7 @@ do before.
**Use cases**: provide at least two, ideally three, use cases for every major feature. **Use cases**: provide at least two, ideally three, use cases for every major feature.
You should answer this question: what can you do with this feature/change? Use cases You should answer this question: what can you do with this feature/change? Use cases
are examples of how this feauture or change can be used in real life. are examples of how this feature or change can be used in real life.
Examples: Examples:
- CE and EE: [Issues](../user/project/issues/index.md#use-cases) - CE and EE: [Issues](../user/project/issues/index.md#use-cases)
......
...@@ -91,7 +91,7 @@ Follow the below instructions to ensure you use the most up to date requirements ...@@ -91,7 +91,7 @@ Follow the below instructions to ensure you use the most up to date requirements
#### Check for InnoDB File-Per-Table Tablespaces #### Check for InnoDB File-Per-Table Tablespaces
We need to check, enable and maybe convert your existing GitLab DB tables to the [InnoDB File-Per-Table Tablespaces](http://dev.mysql.com/doc/refman/5.7/en/innodb-multiple-tablespaces.html) as a prerequise for supporting **utfb8mb4 with long indexes** required by recent GitLab databases. We need to check, enable and maybe convert your existing GitLab DB tables to the [InnoDB File-Per-Table Tablespaces](http://dev.mysql.com/doc/refman/5.7/en/innodb-multiple-tablespaces.html) as a prerequisite for supporting **utfb8mb4 with long indexes** required by recent GitLab databases.
# Login to MySQL # Login to MySQL
mysql -u root -p mysql -u root -p
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
![GCP landing page](img/gcp_landing.png) ![GCP landing page](img/gcp_landing.png)
Gettung started with GitLab on a [Google Cloud Platform (GCP)][gcp] instance is quick and easy. Getting started with GitLab on a [Google Cloud Platform (GCP)][gcp] instance is quick and easy.
## Prerequisites ## Prerequisites
......
...@@ -50,12 +50,12 @@ Here is a snippet of the important settings: ...@@ -50,12 +50,12 @@ Here is a snippet of the important settings:
gitlabUrl: http://gitlab.your-domain.com/ gitlabUrl: http://gitlab.your-domain.com/
## The Registration Token for adding new Runners to the GitLab Server. This must ## The Registration Token for adding new Runners to the GitLab Server. This must
## be retreived from your GitLab Instance. ## be retrieved from your GitLab Instance.
## ref: https://docs.gitlab.com/ce/ci/runners/README.html#creating-and-registering-a-runner ## ref: https://docs.gitlab.com/ce/ci/runners/README.html#creating-and-registering-a-runner
## ##
runnerRegistrationToken: "" runnerRegistrationToken: ""
## Set the certsSecretName in order to pass custom certficates for GitLab Runner to use ## Set the certsSecretName in order to pass custom certificates for GitLab Runner to use
## Provide resource name for a Kubernetes Secret Object in the same namespace, ## Provide resource name for a Kubernetes Secret Object in the same namespace,
## this is used to populate the /etc/gitlab-runner/certs directory ## this is used to populate the /etc/gitlab-runner/certs directory
## ref: https://docs.gitlab.com/runner/configuration/tls-self-signed.html#supported-options-for-self-signed-certificates ## ref: https://docs.gitlab.com/runner/configuration/tls-self-signed.html#supported-options-for-self-signed-certificates
...@@ -130,7 +130,7 @@ runners: ...@@ -130,7 +130,7 @@ runners:
### Enabling RBAC support ### Enabling RBAC support
If your cluster has RBAC enabled, you can choose to either have the chart create its own sevice account or provide one. If your cluster has RBAC enabled, you can choose to either have the chart create its own service account or provide one.
To have the chart create the service account for you, set `rbac.create` to true. To have the chart create the service account for you, set `rbac.create` to true.
...@@ -208,7 +208,7 @@ You then need to provide the secret's name to the GitLab Runner chart. ...@@ -208,7 +208,7 @@ You then need to provide the secret's name to the GitLab Runner chart.
Add the following to your `values.yaml` Add the following to your `values.yaml`
```yaml ```yaml
## Set the certsSecretName in order to pass custom certficates for GitLab Runner to use ## Set the certsSecretName in order to pass custom certificates for GitLab Runner to use
## Provide resource name for a Kubernetes Secret Object in the same namespace, ## Provide resource name for a Kubernetes Secret Object in the same namespace,
## this is used to populate the /etc/gitlab-runner/certs directory ## this is used to populate the /etc/gitlab-runner/certs directory
## ref: https://docs.gitlab.com/runner/configuration/tls-self-signed.html#supported-options-for-self-signed-certificates ## ref: https://docs.gitlab.com/runner/configuration/tls-self-signed.html#supported-options-for-self-signed-certificates
......
...@@ -43,7 +43,7 @@ exclude shibboleth URLs from rewriting, add "RewriteCond %{REQUEST_URI} !/Shibbo ...@@ -43,7 +43,7 @@ exclude shibboleth URLs from rewriting, add "RewriteCond %{REQUEST_URI} !/Shibbo
RequestHeader set X_FORWARDED_PROTO 'https' RequestHeader set X_FORWARDED_PROTO 'https'
``` ```
1. Edit /etc/gitlab/gitlab.rb configuration file, your shibboleth attributes should be in form of "HTTP_ATTRIBUTE" and you should addjust them to your need and environment. Add any other configuration you need. 1. Edit /etc/gitlab/gitlab.rb configuration file, your shibboleth attributes should be in form of "HTTP_ATTRIBUTE" and you should adjust them to your need and environment. Add any other configuration you need.
File should look like this: File should look like this:
``` ```
......
...@@ -196,7 +196,7 @@ This is really useful for integrating repositories to secured, shared Continuous ...@@ -196,7 +196,7 @@ This is really useful for integrating repositories to secured, shared Continuous
Integration (CI) services or other shared services. Integration (CI) services or other shared services.
GitLab administrators can set up the Global Shared Deploy key in GitLab and GitLab administrators can set up the Global Shared Deploy key in GitLab and
add the private key to any shared systems. Individual repositories opt into add the private key to any shared systems. Individual repositories opt into
exposing their repsitory using these keys when a project masters (or higher) exposing their repository using these keys when a project masters (or higher)
authorizes a Global Shared Deploy key to be used with their project. authorizes a Global Shared Deploy key to be used with their project.
Global Shared Keys can provide greater security compared to Per-Project Deploy Global Shared Keys can provide greater security compared to Per-Project Deploy
...@@ -224,7 +224,7 @@ if there is at least one Global Deploy Key configured. ...@@ -224,7 +224,7 @@ if there is at least one Global Deploy Key configured.
CAUTION: **Warning:** CAUTION: **Warning:**
Defining Global Deploy Keys does not expose any given repository via Defining Global Deploy Keys does not expose any given repository via
the key until that respository adds the Global Deploy Key to their project. the key until that repository adds the Global Deploy Key to their project.
In this way the Global Deploy Keys enable access by other systems, but do In this way the Global Deploy Keys enable access by other systems, but do
not implicitly give any access just by setting them up. not implicitly give any access just by setting them up.
......
...@@ -135,6 +135,11 @@ and `1.2.3.4` is the IP address of your load balancer; generally NGINX ...@@ -135,6 +135,11 @@ and `1.2.3.4` is the IP address of your load balancer; generally NGINX
([see prerequisites](#prerequisites)). How to set up the DNS record is beyond ([see prerequisites](#prerequisites)). How to set up the DNS record is beyond
the scope of this document; you should check with your DNS provider. the scope of this document; you should check with your DNS provider.
Alternatively you can use free public services like [xip.io](http://xip.io) or
[nip.io](http://nip.io) which provide automatic wildcard DNS without any
configuration. Just set the Auto DevOps base domain to `1.2.3.4.xip.io` or
`1.2.3.4.nip.io`.
Once set up, all requests will hit the load balancer, which in turn will route Once set up, all requests will hit the load balancer, which in turn will route
them to the Kubernetes pods that run your application(s). them to the Kubernetes pods that run your application(s).
......
...@@ -89,7 +89,7 @@ A [copy](https://git-scm.com/docs/git-clone) of a repository stored on your mach ...@@ -89,7 +89,7 @@ A [copy](https://git-scm.com/docs/git-clone) of a repository stored on your mach
### Code Review ### Code Review
Examination of a progam's code. The main aim is to maintain high quality standards of code that is being shipped. Merge requests [serve as a code review tool](https://about.gitlab.com/2014/09/29/gitlab-flow/) in GitLab. Examination of a program's code. The main aim is to maintain high quality standards of code that is being shipped. Merge requests [serve as a code review tool](https://about.gitlab.com/2014/09/29/gitlab-flow/) in GitLab.
### Code Snippet ### Code Snippet
......
...@@ -354,11 +354,11 @@ add the following script to the User Data section: ...@@ -354,11 +354,11 @@ add the following script to the User Data section:
- mount -a -t nfs - mount -a -t nfs
- sudo gitlab-ctl reconfigure - sudo gitlab-ctl reconfigure
On the security group section we can chosse our existing On the security group section we can choose our existing
`gitlab-ec2-security-group` group which has already been tested. `gitlab-ec2-security-group` group which has already been tested.
After this is launched we are able to start creating our Auto Scaling After this is launched we are able to start creating our Auto Scaling
Group. Start by giving it a name and assinging it our VPC and private Group. Start by giving it a name and assigning it our VPC and private
subnets. We also want to always start with two instances and if you subnets. We also want to always start with two instances and if you
scroll down to Advanced Details we can choose to receive traffic from ELBs. scroll down to Advanced Details we can choose to receive traffic from ELBs.
Lets enable that option and select our ELB. We also want to use the ELB's Lets enable that option and select our ELB. We also want to use the ELB's
......
...@@ -163,7 +163,7 @@ Some tickets need specific knowledge or a deep understanding of a particular com ...@@ -163,7 +163,7 @@ Some tickets need specific knowledge or a deep understanding of a particular com
- Aim to have a good understanding of the problems that customers are facing - Aim to have a good understanding of the problems that customers are facing
- Aim to have gained experience in scheduling and participating in calls with customers - Aim to have gained experience in scheduling and participating in calls with customers
- Aim to have a good understanding of ticket flow through Zendesk and how to interat with our various channels - Aim to have a good understanding of ticket flow through Zendesk and how to interact with our various channels
### Stage 4 ### Stage 4
......
...@@ -27,7 +27,7 @@ project. ...@@ -27,7 +27,7 @@ project.
### Short Story of Git ### Short Story of Git
- 1991-2002: The Linux kernel was being maintaned by sharing archived files - 1991-2002: The Linux kernel was being maintained by sharing archived files
and patches. and patches.
- 2002: The Linux kernel project began using a DVCS called BitKeeper - 2002: The Linux kernel project began using a DVCS called BitKeeper
- 2005: BitKeeper revoked the free-of-charge status and Git was created - 2005: BitKeeper revoked the free-of-charge status and Git was created
......
...@@ -9,7 +9,7 @@ comments: false ...@@ -9,7 +9,7 @@ comments: false
- Useful for marking deployments and releases - Useful for marking deployments and releases
- Annotated tags are an unchangeable part of Git history - Annotated tags are an unchangeable part of Git history
- Soft/lightweight tags can be set and removed at will - Soft/lightweight tags can be set and removed at will
- Many projects combine an anotated release tag with a stable branch - Many projects combine an annotated release tag with a stable branch
- Consider setting deployment/release tags automatically - Consider setting deployment/release tags automatically
---------- ----------
......
...@@ -279,7 +279,7 @@ See GitLab merge requests for examples: ...@@ -279,7 +279,7 @@ See GitLab merge requests for examples:
- Useful for marking deployments and releases - Useful for marking deployments and releases
- Annotated tags are an unchangeable part of Git history - Annotated tags are an unchangeable part of Git history
- Soft/lightweight tags can be set and removed at will - Soft/lightweight tags can be set and removed at will
- Many projects combine an anotated release tag with a stable branch - Many projects combine an annotated release tag with a stable branch
- Consider setting deployment/release tags automatically - Consider setting deployment/release tags automatically
--- ---
......
# Sign-up restrictions # Sign-up restrictions
You can block email addresses of specific domains, or whitelist only some You can block email addresses of specific domains, or whitelist only some
specifc domains via the **Application Settings** in the Admin area. specific domains via the **Application Settings** in the Admin area.
>**Note**: These restrictions are only applied during sign-up. An admin is >**Note**: These restrictions are only applied during sign-up. An admin is
able to add add a user through the admin panel with a disallowed domain. Also able to add add a user through the admin panel with a disallowed domain. Also
......
...@@ -55,7 +55,7 @@ first group being the name of the distro and subsequent groups split like: ...@@ -55,7 +55,7 @@ first group being the name of the distro and subsequent groups split like:
Another example of GitLab as a company would be the following: Another example of GitLab as a company would be the following:
- Organization Group - GitLab - Organization Group - GitLab
- Category Subroup - Marketing - Category Subgroup - Marketing
- (project) Design - (project) Design
- (project) General - (project) General
- Category Subgroup - Software - Category Subgroup - Software
......
...@@ -56,7 +56,7 @@ With GitLab Enterprise Edition, you can also: ...@@ -56,7 +56,7 @@ With GitLab Enterprise Edition, you can also:
[Merge Request Approvals](https://docs.gitlab.com/ee/user/project/merge_requests/index.html#merge-request-approvals), [Merge Request Approvals](https://docs.gitlab.com/ee/user/project/merge_requests/index.html#merge-request-approvals),
[Multiple Assignees for Issues](https://docs.gitlab.com/ee/user/project/issues/multiple_assignees_for_issues.html), [Multiple Assignees for Issues](https://docs.gitlab.com/ee/user/project/issues/multiple_assignees_for_issues.html),
and [Multiple Issue Boards](https://docs.gitlab.com/ee/user/project/issue_board.html#multiple-issue-boards) and [Multiple Issue Boards](https://docs.gitlab.com/ee/user/project/issue_board.html#multiple-issue-boards)
- Create formal relashionships between issues with [Related Issues](https://docs.gitlab.com/ee/user/project/issues/related_issues.html) - Create formal relationships between issues with [Related Issues](https://docs.gitlab.com/ee/user/project/issues/related_issues.html)
- Use [Burndown Charts](https://docs.gitlab.com/ee/user/project/milestones/burndown_charts.html) to track progress during a sprint or while working on a new version of their software. - Use [Burndown Charts](https://docs.gitlab.com/ee/user/project/milestones/burndown_charts.html) to track progress during a sprint or while working on a new version of their software.
- Leverage [Elasticsearch](https://docs.gitlab.com/ee/integration/elasticsearch.html) with [Advanced Global Search](https://docs.gitlab.com/ee/user/search/advanced_global_search.html) and [Advanced Syntax Search](https://docs.gitlab.com/ee/user/search/advanced_search_syntax.html) for faster, more advanced code search across your entire GitLab instance - Leverage [Elasticsearch](https://docs.gitlab.com/ee/integration/elasticsearch.html) with [Advanced Global Search](https://docs.gitlab.com/ee/user/search/advanced_global_search.html) and [Advanced Syntax Search](https://docs.gitlab.com/ee/user/search/advanced_search_syntax.html) for faster, more advanced code search across your entire GitLab instance
- [Authenticate users with Kerberos](https://docs.gitlab.com/ee/integration/kerberos.html) - [Authenticate users with Kerberos](https://docs.gitlab.com/ee/integration/kerberos.html)
......
...@@ -48,12 +48,12 @@ link to each other, but the MR will NOT close the issue(s) when merged. ...@@ -48,12 +48,12 @@ link to each other, but the MR will NOT close the issue(s) when merged.
## From the Issue Board ## From the Issue Board
You can close an issue from [Issue Boards](../issue_board.md) by draging an issue card You can close an issue from [Issue Boards](../issue_board.md) by dragging an issue card
from its list and dropping into **Closed**. from its list and dropping into **Closed**.
![close issue from the Issue Board](img/close_issue_from_board.gif) ![close issue from the Issue Board](img/close_issue_from_board.gif)
## Customizing the issue closing patern ## Customizing the issue closing pattern
Alternatively, a GitLab **administrator** can Alternatively, a GitLab **administrator** can
[customize the issue closing patern](../../../administration/issue_closing_pattern.md). [customize the issue closing pattern](../../../administration/issue_closing_pattern.md).
...@@ -60,4 +60,4 @@ or simply link both issue and merge request as described in the ...@@ -60,4 +60,4 @@ or simply link both issue and merge request as described in the
### Close an issue by merging a merge request ### Close an issue by merging a merge request
To [close an issue when a merge request is merged](closing_issues.md#via-merge-request), use the [automatic issue closing patern](automatic_issue_closing.md). To [close an issue when a merge request is merged](closing_issues.md#via-merge-request), use the [automatic issue closing pattern](automatic_issue_closing.md).
...@@ -152,7 +152,7 @@ know you like it without spamming them. ...@@ -152,7 +152,7 @@ know you like it without spamming them.
These text fields also fully support These text fields also fully support
[GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown-gfm). [GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown-gfm).
#### 17. Comment, start a discusion, or comment and close #### 17. Comment, start a discussion, or comment and close
Once you wrote your comment, you can either: Once you wrote your comment, you can either:
......
...@@ -10,7 +10,7 @@ Milestones allow you to organize issues and merge requests into a cohesive group ...@@ -10,7 +10,7 @@ Milestones allow you to organize issues and merge requests into a cohesive group
- **Project milestones** can be assigned to issues or merge requests in that project only. - **Project milestones** can be assigned to issues or merge requests in that project only.
- **Group milestones** can be assigned to any issue or merge request of any project in that group. - **Group milestones** can be assigned to any issue or merge request of any project in that group.
- In the [future](https://gitlab.com/gitlab-org/gitlab-ce/issues/36862), you will be able to assign group milestones to issues and merge reqeusts of projects in [subgroups](../../group/subgroups/index.md). - In the [future](https://gitlab.com/gitlab-org/gitlab-ce/issues/36862), you will be able to assign group milestones to issues and merge requests of projects in [subgroups](../../group/subgroups/index.md).
## Creating milestones ## Creating milestones
......
...@@ -50,14 +50,14 @@ created for the steps below. ...@@ -50,14 +50,14 @@ created for the steps below.
1. [Fork a sample project](../../../gitlab-basics/fork-project.md) from the [Pages group](https://gitlab.com/pages) 1. [Fork a sample project](../../../gitlab-basics/fork-project.md) from the [Pages group](https://gitlab.com/pages)
1. Trigger a build (push a change to any file) 1. Trigger a build (push a change to any file)
1. As soon as the build passes, your website will have been deployed with GitLab Pages. Your website URL will be available under your project's **Settings** > **Pages** 1. As soon as the build passes, your website will have been deployed with GitLab Pages. Your website URL will be available under your project's **Settings** > **Pages**
1. Optionally, remove the fork relationship by navigating to your project's **Settings** > expanding **Advanced settings** and scrolling down to **Remove fork relashionship**: 1. Optionally, remove the fork relationship by navigating to your project's **Settings** > expanding **Advanced settings** and scrolling down to **Remove fork relationship**:
![remove fork relashionship](img/remove_fork_relashionship.png) ![remove fork relationship](img/remove_fork_relationship.png)
To turn a **project website** forked from the Pages group into a **user/group** website, you'll need to: To turn a **project website** forked from the Pages group into a **user/group** website, you'll need to:
- Rename it to `namespace.gitlab.io`: navigate to project's **Settings** > expand **Advanced settings** > and scroll down to **Rename repository** - Rename it to `namespace.gitlab.io`: navigate to project's **Settings** > expand **Advanced settings** > and scroll down to **Rename repository**
- Adjust your SSG's [base URL](#urls-and-baseurls) to from `"project-name"` to `""`. This setting will be at a different place for each SSG, as each of them have their own structure and file tree. Most likelly, it will be in the SSG's config file. - Adjust your SSG's [base URL](#urls-and-baseurls) to from `"project-name"` to `""`. This setting will be at a different place for each SSG, as each of them have their own structure and file tree. Most likely, it will be in the SSG's config file.
> **Notes:** > **Notes:**
> >
......
# Reducing the repository size using Git # Reducing the repository size using Git
A GitLab Entrerprise Edition administrator can set a [repository size limit][admin-repo-size] A GitLab Enterprise Edition administrator can set a [repository size limit][admin-repo-size]
which will prevent you to exceed it. which will prevent you to exceed it.
When a project has reached its size limit, you will not be able to push to it, When a project has reached its size limit, you will not be able to push to it,
......
...@@ -96,7 +96,7 @@ On the field **Filter by name**, type the project or group name you want to find ...@@ -96,7 +96,7 @@ On the field **Filter by name**, type the project or group name you want to find
will filter them for you as you type. will filter them for you as you type.
You can also look for the projects you starred (**Starred projects**), and **Explore** all You can also look for the projects you starred (**Starred projects**), and **Explore** all
public and internal projects available in GitLab.com, from which you can filter by visibitily, public and internal projects available in GitLab.com, from which you can filter by visibility,
through **Trending**, best rated with **Most starts**, or **All** of them. through **Trending**, best rated with **Most starts**, or **All** of them.
You can also sort them by **Name**, **Last created**, **Oldest created**, **Last updated**, You can also sort them by **Name**, **Last created**, **Oldest created**, **Last updated**,
......
...@@ -243,7 +243,7 @@ GitLab checks files to detect LFS pointers on push. If LFS pointers are detected ...@@ -243,7 +243,7 @@ GitLab checks files to detect LFS pointers on push. If LFS pointers are detected
Verify that LFS in installed locally and consider a manual push with `git lfs push --all`. Verify that LFS in installed locally and consider a manual push with `git lfs push --all`.
If you are storing LFS files outside of GitLab you can disable LFS on the project by settting `lfs_enabled: false` with the [projects api](../../api/projects.md#edit-project). If you are storing LFS files outside of GitLab you can disable LFS on the project by setting `lfs_enabled: false` with the [projects api](../../api/projects.md#edit-project).
### Hosting LFS objects externally ### Hosting LFS objects externally
......
...@@ -19,6 +19,7 @@ module API ...@@ -19,6 +19,7 @@ module API
optional :status, type: String, values: HasStatus::AVAILABLE_STATUSES, optional :status, type: String, values: HasStatus::AVAILABLE_STATUSES,
desc: 'The status of pipelines' desc: 'The status of pipelines'
optional :ref, type: String, desc: 'The ref of pipelines' optional :ref, type: String, desc: 'The ref of pipelines'
optional :sha, type: String, desc: 'The sha of pipelines'
optional :yaml_errors, type: Boolean, desc: 'Returns pipelines with invalid configurations' optional :yaml_errors, type: Boolean, desc: 'Returns pipelines with invalid configurations'
optional :name, type: String, desc: 'The name of the user who triggered pipelines' optional :name, type: String, desc: 'The name of the user who triggered pipelines'
optional :username, type: String, desc: 'The username of the user who triggered pipelines' optional :username, type: String, desc: 'The username of the user who triggered pipelines'
......
...@@ -142,15 +142,7 @@ module Gitlab ...@@ -142,15 +142,7 @@ module Gitlab
end end
def exists? def exists?
Gitlab::GitalyClient.migrate(:repository_exists, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |enabled| gitaly_repository_client.exists?
if enabled
gitaly_repository_client.exists?
else
circuit_breaker.perform do
File.exist?(File.join(path, 'refs'))
end
end
end
end end
# Returns an Array of branch names # Returns an Array of branch names
......
module Gitlab
class PagesClient
class << self
attr_reader :certificate, :token
def call(service, rpc, request, timeout: nil)
kwargs = request_kwargs(timeout)
stub(service).__send__(rpc, request, kwargs) # rubocop:disable GitlabSecurity/PublicSend
end
# This function is not thread-safe. Call it from an initializer only.
def read_or_create_token
@token = read_token
rescue Errno::ENOENT
# TODO: uncomment this when omnibus knows how to write the token file for us
# https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/2466
#
# write_token(SecureRandom.random_bytes(64))
#
# # Read from disk in case someone else won the race and wrote the file
# # before us. If this fails again let the exception bubble up.
# @token = read_token
end
# This function is not thread-safe. Call it from an initializer only.
def load_certificate
cert_path = config.certificate
return unless cert_path.present?
@certificate = File.read(cert_path)
end
def ping
request = Grpc::Health::V1::HealthCheckRequest.new
call(:health_check, :check, request, timeout: 5.seconds)
end
private
def request_kwargs(timeout)
encoded_token = Base64.strict_encode64(token.to_s)
metadata = {
'authorization' => "Bearer #{encoded_token}"
}
result = { metadata: metadata }
return result unless timeout
# Do not use `Time.now` for deadline calculation, since it
# will be affected by Timecop in some tests, but grpc's c-core
# uses system time instead of timecop's time, so tests will fail
# `Time.at(Process.clock_gettime(Process::CLOCK_REALTIME))` will
# circumvent timecop
deadline = Time.at(Process.clock_gettime(Process::CLOCK_REALTIME)) + timeout
result[:deadline] = deadline
result
end
def stub(name)
stub_class(name).new(address, grpc_creds)
end
def stub_class(name)
if name == :health_check
Grpc::Health::V1::Health::Stub
else
# TODO use pages namespace
Gitaly.const_get(name.to_s.camelcase.to_sym).const_get(:Stub)
end
end
def address
addr = config.address
addr = addr.sub(%r{^tcp://}, '') if URI(addr).scheme == 'tcp'
addr
end
def grpc_creds
if address.start_with?('unix:')
:this_channel_is_insecure
elsif @certificate
GRPC::Core::ChannelCredentials.new(@certificate)
else
# Use system certificate pool
GRPC::Core::ChannelCredentials.new
end
end
def config
Gitlab.config.pages.admin
end
def read_token
File.read(token_path)
end
def token_path
Rails.root.join('.gitlab_pages_secret').to_s
end
def write_token(new_token)
Tempfile.open(File.basename(token_path), File.dirname(token_path), encoding: 'ascii-8bit') do |f|
f.write(new_token)
f.close
File.link(f.path, token_path)
end
rescue Errno::EACCES => ex
# TODO stop rescuing this exception in GitLab 11.0 https://gitlab.com/gitlab-org/gitlab-ce/issues/45672
Rails.logger.error("Could not write pages admin token file: #{ex}")
rescue Errno::EEXIST
# Another process wrote the token file concurrently with us. Use their token, not ours.
end
end
end
end
namespace :gitlab do
namespace :pages do
desc 'Ping the pages admin API'
task admin_ping: :gitlab_environment do
Gitlab::PagesClient.ping
puts "OK: gitlab-pages admin API is reachable"
end
end
end
FROM ruby:2.4 FROM ruby:2.4-stretch
LABEL maintainer "Grzegorz Bizon <grzegorz@gitlab.com>" LABEL maintainer "Grzegorz Bizon <grzegorz@gitlab.com>"
ENV DEBIAN_FRONTEND noninteractive ENV DEBIAN_FRONTEND noninteractive
......
...@@ -6,5 +6,4 @@ gem 'capybara-screenshot', '~> 1.0.18' ...@@ -6,5 +6,4 @@ gem 'capybara-screenshot', '~> 1.0.18'
gem 'rake', '~> 12.3.0' gem 'rake', '~> 12.3.0'
gem 'rspec', '~> 3.7' gem 'rspec', '~> 3.7'
gem 'selenium-webdriver', '~> 3.8.0' gem 'selenium-webdriver', '~> 3.8.0'
gem 'net-ssh', require: false
gem 'airborne', '~> 0.2.13' gem 'airborne', '~> 0.2.13'
...@@ -46,7 +46,6 @@ GEM ...@@ -46,7 +46,6 @@ GEM
mini_mime (1.0.0) mini_mime (1.0.0)
mini_portile2 (2.3.0) mini_portile2 (2.3.0)
minitest (5.11.1) minitest (5.11.1)
net-ssh (4.1.0)
netrc (0.11.0) netrc (0.11.0)
nokogiri (1.8.1) nokogiri (1.8.1)
mini_portile2 (~> 2.3.0) mini_portile2 (~> 2.3.0)
...@@ -98,7 +97,6 @@ DEPENDENCIES ...@@ -98,7 +97,6 @@ DEPENDENCIES
airborne (~> 0.2.13) airborne (~> 0.2.13)
capybara (~> 2.16.1) capybara (~> 2.16.1)
capybara-screenshot (~> 1.0.18) capybara-screenshot (~> 1.0.18)
net-ssh
pry-byebug (~> 3.5.1) pry-byebug (~> 3.5.1)
rake (~> 12.3.0) rake (~> 12.3.0)
rspec (~> 3.7) rspec (~> 3.7)
......
...@@ -11,9 +11,15 @@ module QA ...@@ -11,9 +11,15 @@ module QA
autoload :Scenario, 'qa/runtime/scenario' autoload :Scenario, 'qa/runtime/scenario'
autoload :Browser, 'qa/runtime/browser' autoload :Browser, 'qa/runtime/browser'
autoload :Env, 'qa/runtime/env' autoload :Env, 'qa/runtime/env'
autoload :RSAKey, 'qa/runtime/rsa_key'
autoload :Address, 'qa/runtime/address' autoload :Address, 'qa/runtime/address'
autoload :API, 'qa/runtime/api' autoload :API, 'qa/runtime/api'
module Key
autoload :Base, 'qa/runtime/key/base'
autoload :RSA, 'qa/runtime/key/rsa'
autoload :ECDSA, 'qa/runtime/key/ecdsa'
autoload :ED25519, 'qa/runtime/key/ed25519'
end
end end
## ##
......
...@@ -2,7 +2,10 @@ module QA ...@@ -2,7 +2,10 @@ module QA
module Factory module Factory
module Repository module Repository
class Push < Factory::Base class Push < Factory::Base
attr_writer :file_name, :file_content, :commit_message, :branch_name, :new_branch attr_accessor :file_name, :file_content, :commit_message,
:branch_name, :new_branch
attr_writer :remote_branch
dependency Factory::Resource::Project, as: :project do |project| dependency Factory::Resource::Project, as: :project do |project|
project.name = 'project-with-code' project.name = 'project-with-code'
...@@ -17,23 +20,32 @@ module QA ...@@ -17,23 +20,32 @@ module QA
@new_branch = true @new_branch = true
end end
def remote_branch
@remote_branch ||= branch_name
end
def fabricate! def fabricate!
project.visit! project.visit!
Git::Repository.perform do |repository| Git::Repository.perform do |repository|
repository.location = Page::Project::Show.act do repository.uri = Page::Project::Show.act do
choose_repository_clone_http choose_repository_clone_http
repository_location repository_location.uri
end end
repository.use_default_credentials repository.use_default_credentials
repository.clone repository.clone
repository.configure_identity('GitLab QA', 'root@gitlab.com') repository.configure_identity('GitLab QA', 'root@gitlab.com')
repository.checkout(@branch_name) unless @new_branch if new_branch
repository.add_file(@file_name, @file_content) repository.checkout_new_branch(branch_name)
repository.commit(@commit_message) else
repository.push_changes(@branch_name) repository.checkout(branch_name)
end
repository.add_file(file_name, file_content)
repository.commit(commit_message)
repository.push_changes("#{branch_name}:#{remote_branch}")
end end
end end
end end
......
...@@ -2,7 +2,8 @@ module QA ...@@ -2,7 +2,8 @@ module QA
module Factory module Factory
module Resource module Resource
class Branch < Factory::Base class Branch < Factory::Base
attr_accessor :project, :branch_name, :allow_to_push, :protected attr_accessor :project, :branch_name,
:allow_to_push, :allow_to_merge, :protected
dependency Factory::Resource::Project, as: :project do |project| dependency Factory::Resource::Project, as: :project do |project|
project.name = 'protected-branch-project' project.name = 'protected-branch-project'
...@@ -23,6 +24,7 @@ module QA ...@@ -23,6 +24,7 @@ module QA
def initialize def initialize
@branch_name = 'test/branch' @branch_name = 'test/branch'
@allow_to_push = true @allow_to_push = true
@allow_to_merge = true
@protected = false @protected = false
end end
...@@ -39,7 +41,9 @@ module QA ...@@ -39,7 +41,9 @@ module QA
resource.project = project resource.project = project
resource.file_name = 'README.md' resource.file_name = 'README.md'
resource.commit_message = 'Add readme' resource.commit_message = 'Add readme'
resource.branch_name = "master:#{@branch_name}" resource.branch_name = 'master'
resource.new_branch = false
resource.remote_branch = @branch_name
end end
Page::Project::Show.act { wait_for_push } Page::Project::Show.act { wait_for_push }
...@@ -63,7 +67,22 @@ module QA ...@@ -63,7 +67,22 @@ module QA
page.allow_no_one_to_push page.allow_no_one_to_push
end end
if allow_to_merge
page.allow_devs_and_masters_to_merge
else
page.allow_no_one_to_merge
end
page.wait(reload: false) do
!page.first('.btn-create').disabled?
end
page.protect_branch page.protect_branch
# Wait for page load, which resets the expanded sections
page.wait(reload: false) do
!page.has_content?('Collapse')
end
end end
end end
end end
......
...@@ -4,15 +4,15 @@ module QA ...@@ -4,15 +4,15 @@ module QA
class DeployKey < Factory::Base class DeployKey < Factory::Base
attr_accessor :title, :key attr_accessor :title, :key
product :title do product :fingerprint do |resource|
Page::Project::Settings::Repository.act do Page::Project::Settings::Repository.act do
expand_deploy_keys(&:key_title) expand_deploy_keys do |key|
end key_offset = key.key_titles.index do |title|
end title.text == resource.title
end
product :fingerprint do key.key_fingerprints[key_offset].text
Page::Project::Settings::Repository.act do end
expand_deploy_keys(&:key_fingerprint)
end end
end end
......
...@@ -24,12 +24,14 @@ module QA ...@@ -24,12 +24,14 @@ module QA
dependency Factory::Repository::Push, as: :target do |push, factory| dependency Factory::Repository::Push, as: :target do |push, factory|
factory.project.visit! factory.project.visit!
push.project = factory.project push.project = factory.project
push.branch_name = "master:#{factory.target_branch}" push.branch_name = 'master'
push.remote_branch = factory.target_branch
end end
dependency Factory::Repository::Push, as: :source do |push, factory| dependency Factory::Repository::Push, as: :source do |push, factory|
push.project = factory.project push.project = factory.project
push.branch_name = "#{factory.target_branch}:#{factory.source_branch}" push.branch_name = factory.target_branch
push.remote_branch = factory.source_branch
push.file_name = "added_file.txt" push.file_name = "added_file.txt"
push.file_content = "File Added" push.file_content = "File Added"
end end
......
...@@ -17,6 +17,13 @@ module QA ...@@ -17,6 +17,13 @@ module QA
Page::Project::Show.act { project_name } Page::Project::Show.act { project_name }
end end
product :repository_ssh_location do
Page::Project::Show.act do
choose_repository_clone_ssh
repository_location
end
end
def fabricate! def fabricate!
group.visit! group.visit!
......
...@@ -16,8 +16,7 @@ module QA ...@@ -16,8 +16,7 @@ module QA
Page::Project::Settings::CICD.perform do |setting| Page::Project::Settings::CICD.perform do |setting|
setting.expand_secret_variables do |page| setting.expand_secret_variables do |page|
page.fill_variable_key(key) page.fill_variable(key, value)
page.fill_variable_value(value)
page.save_variables page.save_variables
end end
......
...@@ -14,7 +14,7 @@ module QA ...@@ -14,7 +14,7 @@ module QA
def initialize(git_uri) def initialize(git_uri)
@git_uri = git_uri @git_uri = git_uri
@uri = @uri =
if git_uri.start_with?('ssh://') if git_uri =~ %r{\A(?:ssh|http|https)://}
URI.parse(git_uri) URI.parse(git_uri)
else else
*rest, path = git_uri.split(':') *rest, path = git_uri.split(':')
......
...@@ -15,8 +15,7 @@ module QA ...@@ -15,8 +15,7 @@ module QA
end end
end end
def location=(address) def uri=(address)
@location = address
@uri = URI(address) @uri = URI(address)
end end
...@@ -43,6 +42,10 @@ module QA ...@@ -43,6 +42,10 @@ module QA
`git checkout "#{branch_name}"` `git checkout "#{branch_name}"`
end end
def checkout_new_branch(branch_name)
`git checkout -b "#{branch_name}"`
end
def shallow_clone def shallow_clone
clone('--depth 1') clone('--depth 1')
end end
......
...@@ -64,6 +64,10 @@ module QA ...@@ -64,6 +64,10 @@ module QA
find(element_selector_css(name)) find(element_selector_css(name))
end end
def all_elements(name)
all(element_selector_css(name))
end
def click_element(name) def click_element(name)
find_element(name).click find_element(name).click
end end
......
...@@ -42,6 +42,18 @@ module QA ...@@ -42,6 +42,18 @@ module QA
end end
end end
def key_titles
within_project_deploy_keys do
all_elements(:key_title)
end
end
def key_fingerprints
within_project_deploy_keys do
all_elements(:key_fingerprint)
end
end
private private
def within_project_deploy_keys def within_project_deploy_keys
......
...@@ -11,6 +11,13 @@ module QA ...@@ -11,6 +11,13 @@ module QA
view 'app/views/projects/protected_branches/_create_protected_branch.html.haml' do view 'app/views/projects/protected_branches/_create_protected_branch.html.haml' do
element :allowed_to_push_select element :allowed_to_push_select
element :allowed_to_push_dropdown element :allowed_to_push_dropdown
element :allowed_to_merge_select
element :allowed_to_merge_dropdown
end
view 'app/views/projects/protected_branches/_update_protected_branch.html.haml' do
element :allowed_to_push
element :allowed_to_merge
end end
view 'app/views/projects/protected_branches/shared/_branches_list.html.haml' do view 'app/views/projects/protected_branches/shared/_branches_list.html.haml' do
...@@ -30,11 +37,19 @@ module QA ...@@ -30,11 +37,19 @@ module QA
end end
def allow_no_one_to_push def allow_no_one_to_push
allow_to_push('No one') click_allow(:push, 'No one')
end end
def allow_devs_and_masters_to_push def allow_devs_and_masters_to_push
allow_to_push('Developers + Masters') click_allow(:push, 'Developers + Masters')
end
def allow_no_one_to_merge
click_allow(:merge, 'No one')
end
def allow_devs_and_masters_to_merge
click_allow(:merge, 'Developers + Masters')
end end
def protect_branch def protect_branch
...@@ -55,11 +70,15 @@ module QA ...@@ -55,11 +70,15 @@ module QA
private private
def allow_to_push(text) def click_allow(action, text)
click_element :allowed_to_push_select click_element :"allowed_to_#{action}_select"
within_element(:allowed_to_push_dropdown) do within_element(:"allowed_to_#{action}_dropdown") do
click_on text click_on text
wait(reload: false) do
has_css?('.is-active')
end
end end
end end
end end
......
...@@ -7,10 +7,8 @@ module QA ...@@ -7,10 +7,8 @@ module QA
view 'app/views/ci/variables/_variable_row.html.haml' do view 'app/views/ci/variables/_variable_row.html.haml' do
element :variable_row, '.ci-variable-row-body' element :variable_row, '.ci-variable-row-body'
element :variable_key, '.js-ci-variable-input-key' element :variable_key, '.qa-ci-variable-input-key'
element :variable_value, '.js-ci-variable-input-value' element :variable_value, '.qa-ci-variable-input-value'
element :key_placeholder, 'Input variable key'
element :value_placeholder, 'Input variable value'
end end
view 'app/views/ci/variables/_index.html.haml' do view 'app/views/ci/variables/_index.html.haml' do
...@@ -18,12 +16,14 @@ module QA ...@@ -18,12 +16,14 @@ module QA
element :reveal_values, '.js-secret-value-reveal-button' element :reveal_values, '.js-secret-value-reveal-button'
end end
def fill_variable_key(key) def fill_variable(key, value)
fill_in('Input variable key', with: key, match: :first) keys = all_elements(:ci_variable_input_key)
end index = keys.size - 1
def fill_variable_value(value) # After we fill the key, JS would generate another field so
fill_in('Input variable value', with: value, match: :first) # we need to use the same index to find the corresponding one.
keys[index].set(key)
all_elements(:ci_variable_input_value)[index].set(value)
end end
def save_variables def save_variables
...@@ -36,7 +36,7 @@ module QA ...@@ -36,7 +36,7 @@ module QA
def variable_value(key) def variable_value(key)
within('.ci-variable-row-body', text: key) do within('.ci-variable-row-body', text: key) do
find('.js-ci-variable-input-value').value find('.qa-ci-variable-input-value').value
end end
end end
end end
......
...@@ -38,11 +38,7 @@ module QA ...@@ -38,11 +38,7 @@ module QA
end end
def repository_location def repository_location
find('#project_clone').value Git::Location.new(find('#project_clone').value)
end
def repository_location_uri
Git::Location.new(repository_location)
end end
def project_name def project_name
...@@ -91,7 +87,7 @@ module QA ...@@ -91,7 +87,7 @@ module QA
end end
# Ensure git clone textbox was updated # Ensure git clone textbox was updated
repository_location.include?(detect_text) repository_location.git_uri.include?(detect_text)
end end
end end
end end
......
module QA
module Runtime
module Key
class Base
attr_reader :name, :bits, :private_key, :public_key, :fingerprint
def initialize(name, bits)
@name = name
@bits = bits
Dir.mktmpdir do |dir|
path = "#{dir}/id_#{name}"
ssh_keygen(name, bits, path)
populate_key_data(path)
end
end
private
def ssh_keygen(name, bits, path)
cmd = %W[ssh-keygen -t #{name} -b #{bits} -f #{path} -N] << ''
Service::Shellout.shell(cmd)
end
def populate_key_data(path)
@private_key = File.binread(path)
@public_key = File.binread("#{path}.pub")
@fingerprint =
`ssh-keygen -l -E md5 -f #{path} | cut -d' ' -f2 | cut -d: -f2-`.chomp
end
end
end
end
end
# rubocop:disable Naming/FileName
module QA
module Runtime
module Key
class ECDSA < Base
def initialize(bits = 521)
super('ecdsa', bits)
end
end
end
end
end
# rubocop:disable Naming/FileName
module QA
module Runtime
module Key
class ED25519 < Base
def initialize
super('ed25519', 256)
end
end
end
end
end
module QA
module Runtime
module Key
class RSA < Base
def initialize(bits = 4096)
super('rsa', bits)
end
end
end
end
end
require 'net/ssh'
require 'forwardable'
module QA
module Runtime
class RSAKey
extend Forwardable
attr_reader :key
def_delegators :@key, :fingerprint, :to_pem
def initialize(bits = 4096)
@key = OpenSSL::PKey::RSA.new(bits)
end
def public_key
@public_key ||= "#{key.ssh_type} #{[key.to_blob].pack('m0')}"
end
end
end
end
...@@ -5,6 +5,8 @@ module QA ...@@ -5,6 +5,8 @@ module QA
module Shellout module Shellout
CommandError = Class.new(StandardError) CommandError = Class.new(StandardError)
module_function
## ##
# TODO, make it possible to use generic QA framework classes # TODO, make it possible to use generic QA framework classes
# as a library - gitlab-org/gitlab-qa#94 # as a library - gitlab-org/gitlab-qa#94
...@@ -12,7 +14,7 @@ module QA ...@@ -12,7 +14,7 @@ module QA
def shell(command) def shell(command)
puts "Executing `#{command}`" puts "Executing `#{command}`"
Open3.popen2e(command) do |_in, out, wait| Open3.popen2e(*command) do |_in, out, wait|
out.each { |line| puts line } out.each { |line| puts line }
if wait.value.exited? && wait.value.exitstatus.nonzero? if wait.value.exited? && wait.value.exitstatus.nonzero?
......
...@@ -4,7 +4,7 @@ module QA ...@@ -4,7 +4,7 @@ module QA
Runtime::Browser.visit(:gitlab, Page::Main::Login) Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials } Page::Main::Login.act { sign_in_using_credentials }
key = Runtime::RSAKey.new key = Runtime::Key::RSA.new
deploy_key_title = 'deploy key title' deploy_key_title = 'deploy key title'
deploy_key_value = key.public_key deploy_key_value = key.public_key
...@@ -13,7 +13,6 @@ module QA ...@@ -13,7 +13,6 @@ module QA
resource.key = deploy_key_value resource.key = deploy_key_value
end end
expect(deploy_key.title).to eq(deploy_key_title)
expect(deploy_key.fingerprint).to eq(key.fingerprint) expect(deploy_key.fingerprint).to eq(key.fingerprint)
end end
end end
......
...@@ -2,79 +2,103 @@ require 'digest/sha1' ...@@ -2,79 +2,103 @@ require 'digest/sha1'
module QA module QA
feature 'cloning code using a deploy key', :core, :docker do feature 'cloning code using a deploy key', :core, :docker do
let(:runner_name) { "qa-runner-#{Time.now.to_i}" } def login
let(:key) { Runtime::RSAKey.new } Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
end
given(:project) do before(:all) do
Factory::Resource::Project.fabricate! do |resource| login
@runner_name = "qa-runner-#{Time.now.to_i}"
@project = Factory::Resource::Project.fabricate! do |resource|
resource.name = 'deploy-key-clone-project' resource.name = 'deploy-key-clone-project'
end end
end
after do @repository_location = @project.repository_ssh_location
Service::Runner.new(runner_name).remove!
end
scenario 'user sets up a deploy key to clone code using pipelines' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
Factory::Resource::Runner.fabricate! do |resource| Factory::Resource::Runner.fabricate! do |resource|
resource.project = project resource.project = @project
resource.name = runner_name resource.name = @runner_name
resource.tags = %w[qa docker] resource.tags = %w[qa docker]
resource.image = 'gitlab/gitlab-runner:ubuntu' resource.image = 'gitlab/gitlab-runner:ubuntu'
end end
Factory::Resource::DeployKey.fabricate! do |resource| Page::Menu::Main.act { sign_out }
resource.project = project end
resource.title = 'deploy key title'
resource.key = key.public_key
end
Factory::Resource::SecretVariable.fabricate! do |resource| after(:all) do
resource.project = project Service::Runner.new(@runner_name).remove!
resource.key = 'DEPLOY_KEY' end
resource.value = key.to_pem
end
project.visit! keys = [
Runtime::Key::RSA.new(8192),
Runtime::Key::ECDSA.new(521),
Runtime::Key::ED25519.new
]
repository_uri = Page::Project::Show.act do keys.each do |key|
choose_repository_clone_ssh scenario "user sets up a deploy key with #{key.name}(#{key.bits}) to clone code using pipelines" do
repository_location_uri login
end
gitlab_ci = <<~YAML Factory::Resource::DeployKey.fabricate! do |resource|
cat-config: resource.project = @project
script: resource.title = "deploy key #{key.name}(#{key.bits})"
- mkdir -p ~/.ssh resource.key = key.public_key
- ssh-keyscan -p #{repository_uri.port} #{repository_uri.host} >> ~/.ssh/known_hosts end
- eval $(ssh-agent -s)
- echo "$DEPLOY_KEY" | ssh-add - deploy_key_name = "DEPLOY_KEY_#{key.name}_#{key.bits}"
- git clone #{repository_uri.git_uri}
- sha1sum #{project.name}/.gitlab-ci.yml Factory::Resource::SecretVariable.fabricate! do |resource|
tags: resource.project = @project
- qa resource.key = deploy_key_name
- docker resource.value = key.private_key
YAML end
Factory::Repository::Push.fabricate! do |resource| gitlab_ci = <<~YAML
resource.project = project cat-config:
resource.file_name = '.gitlab-ci.yml' script:
resource.commit_message = 'Add .gitlab-ci.yml' - mkdir -p ~/.ssh
resource.file_content = gitlab_ci - ssh-keyscan -p #{@repository_location.port} #{@repository_location.host} >> ~/.ssh/known_hosts
end - eval $(ssh-agent -s)
- ssh-add -D
- echo "$#{deploy_key_name}" | ssh-add -
- git clone #{@repository_location.git_uri}
- cd #{@project.name}
- git checkout #{deploy_key_name}
- sha1sum .gitlab-ci.yml
tags:
- qa
- docker
YAML
Factory::Repository::Push.fabricate! do |resource|
resource.project = @project
resource.file_name = '.gitlab-ci.yml'
resource.commit_message = 'Add .gitlab-ci.yml'
resource.file_content = gitlab_ci
resource.branch_name = deploy_key_name
resource.new_branch = true
end
sha1sum = Digest::SHA1.hexdigest(gitlab_ci)
Page::Project::Show.act { wait_for_push }
Page::Menu::Side.act { click_ci_cd_pipelines }
Page::Project::Pipeline::Index.act { go_to_latest_pipeline }
sha1sum = Digest::SHA1.hexdigest(gitlab_ci) Page::Project::Pipeline::Show.act do
go_to_first_job
Page::Project::Show.act { wait_for_push } wait do
Page::Menu::Side.act { click_ci_cd_pipelines } !has_content?('running')
Page::Project::Pipeline::Index.act { go_to_latest_pipeline } end
Page::Project::Pipeline::Show.act { go_to_first_job } end
Page::Project::Job::Show.perform do |job| Page::Project::Job::Show.perform do |job|
expect(job.output).to include(sha1sum) expect(job.output).to include(sha1sum)
end
end end
end end
end end
......
...@@ -18,7 +18,7 @@ module QA ...@@ -18,7 +18,7 @@ module QA
end end
Git::Repository.perform do |repository| Git::Repository.perform do |repository|
repository.location = location repository.uri = location.uri
repository.use_default_credentials repository.use_default_credentials
repository.act do repository.act do
...@@ -33,7 +33,7 @@ module QA ...@@ -33,7 +33,7 @@ module QA
scenario 'user performs a deep clone' do scenario 'user performs a deep clone' do
Git::Repository.perform do |repository| Git::Repository.perform do |repository|
repository.location = location repository.uri = location.uri
repository.use_default_credentials repository.use_default_credentials
repository.act { clone } repository.act { clone }
...@@ -44,7 +44,7 @@ module QA ...@@ -44,7 +44,7 @@ module QA
scenario 'user performs a shallow clone' do scenario 'user performs a shallow clone' do
Git::Repository.perform do |repository| Git::Repository.perform do |repository|
repository.location = location repository.uri = location.uri
repository.use_default_credentials repository.use_default_credentials
repository.act { shallow_clone } repository.act { shallow_clone }
......
...@@ -19,6 +19,13 @@ module QA ...@@ -19,6 +19,13 @@ module QA
Page::Main::Login.act { sign_in_using_credentials } Page::Main::Login.act { sign_in_using_credentials }
end end
after do
# We need to clear localStorage because we're using it for the dropdown,
# and capybara doesn't do this for us.
# https://github.com/teamcapybara/capybara/issues/1702
Capybara.execute_script 'localStorage.clear()'
end
scenario 'user is able to protect a branch' do scenario 'user is able to protect a branch' do
protected_branch = Factory::Resource::Branch.fabricate! do |resource| protected_branch = Factory::Resource::Branch.fabricate! do |resource|
resource.branch_name = branch_name resource.branch_name = branch_name
...@@ -42,7 +49,7 @@ module QA ...@@ -42,7 +49,7 @@ module QA
project.visit! project.visit!
Git::Repository.perform do |repository| Git::Repository.perform do |repository|
repository.location = location repository.uri = location.uri
repository.use_default_credentials repository.use_default_credentials
repository.act do repository.act do
......
describe QA::Runtime::Key::ECDSA do
describe '#public_key' do
[256, 384, 521].each do |bits|
it "generates a public #{bits}-bits ECDSA key" do
subject = described_class.new(bits).public_key
expect(subject).to match(%r{\Aecdsa\-sha2\-\w+ AAAA[0-9A-Za-z+/]+={0,3}})
end
end
end
describe '#new' do
it 'does not support arbitrary bits' do
expect { described_class.new(123) }
.to raise_error(QA::Service::Shellout::CommandError)
end
end
end
describe QA::Runtime::Key::ED25519 do
describe '#public_key' do
subject { described_class.new.public_key }
it 'generates a public ED25519 key' do
expect(subject).to match(%r{\Assh\-ed25519 AAAA[0-9A-Za-z+/]})
end
end
end
describe QA::Runtime::RSAKey do describe QA::Runtime::Key::RSA do
describe '#public_key' do describe '#public_key' do
subject { described_class.new.public_key } subject { described_class.new.public_key }
it 'generates a public RSA key' do it 'generates a public RSA key' do
expect(subject).to match(%r{\Assh\-rsa AAAA[0-9A-Za-z+/]+={0,3}\z}) expect(subject).to match(%r{\Assh\-rsa AAAA[0-9A-Za-z+/]+={0,3}})
end end
end end
end end
...@@ -35,17 +35,4 @@ feature 'Multi-file editor upload file', :js do ...@@ -35,17 +35,4 @@ feature 'Multi-file editor upload file', :js do
expect(page).to have_selector('.multi-file-tab', text: 'doc_sample.txt') expect(page).to have_selector('.multi-file-tab', text: 'doc_sample.txt')
expect(find('.blob-editor-container .lines-content')['innerText']).to have_content(File.open(txt_file, &:readline)) expect(find('.blob-editor-container .lines-content')['innerText']).to have_content(File.open(txt_file, &:readline))
end end
it 'uploads image file' do
find('.add-to-tree').click
# make the field visible so capybara can use it
execute_script('document.querySelector("#file-upload").classList.remove("hidden")')
attach_file('file-upload', img_file)
find('.add-to-tree').click
expect(page).to have_selector('.multi-file-tab', text: 'dk.png')
expect(page).not_to have_selector('.monaco-editor')
end
end end
...@@ -203,5 +203,25 @@ describe PipelinesFinder do ...@@ -203,5 +203,25 @@ describe PipelinesFinder do
end end
end end
end end
context 'when sha is specified' do
let!(:pipeline) { create(:ci_pipeline, project: project, sha: '97de212e80737a608d939f648d959671fb0a0142') }
context 'when sha exists' do
let(:params) { { sha: '97de212e80737a608d939f648d959671fb0a0142' } }
it 'returns matched pipelines' do
is_expected.to eq([pipeline])
end
end
context 'when sha does not exist' do
let(:params) { { sha: 'invalid-sha' } }
it 'returns empty' do
is_expected.to be_empty
end
end
end
end end
end end
require 'spec_helper'
describe Gitlab::PagesClient do
subject { described_class }
describe '.token' do
it 'returns the token as it is on disk' do
pending 'add omnibus support for generating the secret file https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/2466'
expect(subject.token).to eq(File.read('.gitlab_pages_secret'))
end
end
describe '.read_or_create_token' do
subject { described_class.read_or_create_token }
let(:token_path) { 'tmp/tests/gitlab-pages-secret' }
before do
allow(described_class).to receive(:token_path).and_return(token_path)
FileUtils.rm_f(token_path)
end
it 'uses the existing token file if it exists' do
secret = 'existing secret'
File.write(token_path, secret)
subject
expect(described_class.token).to eq(secret)
end
it 'creates one if none exists' do
pending 'add omnibus support for generating the secret file https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/2466'
old_token = described_class.token
# sanity check
expect(File.exist?(token_path)).to eq(false)
subject
expect(described_class.token.bytesize).to eq(64)
expect(described_class.token).not_to eq(old_token)
end
end
describe '.write_token' do
let(:token_path) { 'tmp/tests/gitlab-pages-secret' }
before do
allow(described_class).to receive(:token_path).and_return(token_path)
FileUtils.rm_f(token_path)
end
it 'writes the secret' do
new_secret = 'hello new secret'
expect(File.exist?(token_path)).to eq(false)
described_class.send(:write_token, new_secret)
expect(File.read(token_path)).to eq(new_secret)
end
it 'does nothing if the file already exists' do
existing_secret = 'hello secret'
File.write(token_path, existing_secret)
described_class.send(:write_token, 'new secret')
expect(File.read(token_path)).to eq(existing_secret)
end
end
describe '.load_certificate' do
subject { described_class.load_certificate }
before do
allow(described_class).to receive(:config).and_return(config)
end
context 'with no certificate in the config' do
let(:config) { double(:config, certificate: '') }
it 'does not set @certificate' do
subject
expect(described_class.certificate).to be_nil
end
end
context 'with a certificate path in the config' do
let(:certificate_path) { 'tmp/tests/fake-certificate' }
let(:config) { double(:config, certificate: certificate_path) }
it 'sets @certificate' do
certificate_data = "--- BEGIN CERTIFICATE ---\nbla\n--- END CERTIFICATE ---\n"
File.write(certificate_path, certificate_data)
subject
expect(described_class.certificate).to eq(certificate_data)
end
end
end
describe '.request_kwargs' do
let(:token) { 'secret token' }
let(:auth_header) { 'Bearer c2VjcmV0IHRva2Vu' }
before do
allow(described_class).to receive(:token).and_return(token)
end
context 'without timeout' do
it { expect(subject.send(:request_kwargs, nil)[:metadata]['authorization']).to eq(auth_header) }
end
context 'with timeout' do
let(:timeout) { 1.second }
it 'still sets the authorization header' do
expect(subject.send(:request_kwargs, timeout)[:metadata]['authorization']).to eq(auth_header)
end
it 'sets a deadline value' do
now = Time.now
deadline = subject.send(:request_kwargs, timeout)[:deadline]
expect(deadline).to be_between(now, now + 2 * timeout)
end
end
end
describe '.stub' do
before do
allow(described_class).to receive(:address).and_return('unix:/foo/bar')
end
it { expect(subject.send(:stub, :health_check)).to be_a(Grpc::Health::V1::Health::Stub) }
end
describe '.address' do
subject { described_class.send(:address) }
before do
allow(described_class).to receive(:config).and_return(config)
end
context 'with a unix: address' do
let(:config) { double(:config, address: 'unix:/foo/bar') }
it { expect(subject).to eq('unix:/foo/bar') }
end
context 'with a tcp:// address' do
let(:config) { double(:config, address: 'tcp://localhost:1234') }
it { expect(subject).to eq('localhost:1234') }
end
end
describe '.grpc_creds' do
subject { described_class.send(:grpc_creds) }
before do
allow(described_class).to receive(:config).and_return(config)
end
context 'with a unix: address' do
let(:config) { double(:config, address: 'unix:/foo/bar') }
it { expect(subject).to eq(:this_channel_is_insecure) }
end
context 'with a tcp:// address' do
let(:config) { double(:config, address: 'tcp://localhost:1234') }
it { expect(subject).to be_a(GRPC::Core::ChannelCredentials) }
end
end
end
This diff is collapsed.
This diff is collapsed.
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