diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-03-18 06:09:43 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-03-18 06:09:43 +0300 |
commit | b4b9b3854eddd2a4829113ebfc1812c3a332a7d9 (patch) | |
tree | 6a21e491917e1606d81329af710459b0217eb1a4 /doc | |
parent | 2e31c85a97183814ffa7ba5cc58f7bbad668fb2b (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'doc')
-rw-r--r-- | doc/api/graphql/reference/gitlab_schema.graphql | 130 | ||||
-rw-r--r-- | doc/api/graphql/reference/gitlab_schema.json | 309 | ||||
-rw-r--r-- | doc/api/graphql/reference/index.md | 1 | ||||
-rw-r--r-- | doc/development/contributing/issue_workflow.md | 2 | ||||
-rw-r--r-- | doc/development/insert_into_tables_in_batches.md | 50 | ||||
-rw-r--r-- | doc/policy/maintenance.md | 18 | ||||
-rw-r--r-- | doc/user/clusters/applications.md | 90 |
7 files changed, 591 insertions, 9 deletions
diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql index 74ec8efbe99..e3f988016fe 100644 --- a/doc/api/graphql/reference/gitlab_schema.graphql +++ b/doc/api/graphql/reference/gitlab_schema.graphql @@ -6001,6 +6001,76 @@ type Project { requestAccessEnabled: Boolean """ + Find a single requirement. Available only when feature flag `requirements_management` is enabled. + """ + requirement( + """ + IID of the requirement, e.g., "1" + """ + iid: ID + + """ + List of IIDs of requirements, e.g., [1, 2] + """ + iids: [ID!] + + """ + List requirements by sort order + """ + sort: Sort + + """ + Filter requirements by state + """ + state: RequirementState + ): Requirement + + """ + Find requirements. Available only when feature flag `requirements_management` is enabled. + """ + requirements( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + IID of the requirement, e.g., "1" + """ + iid: ID + + """ + List of IIDs of requirements, e.g., [1, 2] + """ + iids: [ID!] + + """ + Returns the last _n_ elements from the list. + """ + last: Int + + """ + List requirements by sort order + """ + sort: Sort + + """ + Filter requirements by state + """ + state: RequirementState + ): RequirementConnection + + """ Detailed version of a Sentry error on the project """ sentryDetailedError( @@ -6665,6 +6735,41 @@ type Requirement { } """ +The connection type for Requirement. +""" +type RequirementConnection { + """ + A list of edges. + """ + edges: [RequirementEdge] + + """ + A list of nodes. + """ + nodes: [Requirement] + + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! +} + +""" +An edge in a connection. +""" +type RequirementEdge { + """ + A cursor for use in pagination. + """ + cursor: String! + + """ + The item at the end of the edge. + """ + node: Requirement +} + +""" Check permissions for the current user on a requirement """ type RequirementPermissions { @@ -7463,6 +7568,31 @@ type SnippetPermissions { updateSnippet: Boolean! } +""" +Common sort values +""" +enum Sort { + """ + Created at ascending order + """ + created_asc + + """ + Created at descending order + """ + created_desc + + """ + Updated at ascending order + """ + updated_asc + + """ + Updated at descending order + """ + updated_desc +} + type Submodule implements Entry { """ Flat path of the entry diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json index 8eb9b53af04..3d941d9cc69 100644 --- a/doc/api/graphql/reference/gitlab_schema.json +++ b/doc/api/graphql/reference/gitlab_schema.json @@ -18033,6 +18033,168 @@ "deprecationReason": null }, { + "name": "requirement", + "description": "Find a single requirement. Available only when feature flag `requirements_management` is enabled.", + "args": [ + { + "name": "iid", + "description": "IID of the requirement, e.g., \"1\"", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "iids", + "description": "List of IIDs of requirements, e.g., [1, 2]", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "sort", + "description": "List requirements by sort order", + "type": { + "kind": "ENUM", + "name": "Sort", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "state", + "description": "Filter requirements by state", + "type": { + "kind": "ENUM", + "name": "RequirementState", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "Requirement", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "requirements", + "description": "Find requirements. Available only when feature flag `requirements_management` is enabled.", + "args": [ + { + "name": "iid", + "description": "IID of the requirement, e.g., \"1\"", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "iids", + "description": "List of IIDs of requirements, e.g., [1, 2]", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "sort", + "description": "List requirements by sort order", + "type": { + "kind": "ENUM", + "name": "Sort", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "state", + "description": "Filter requirements by state", + "type": { + "kind": "ENUM", + "name": "RequirementState", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "RequirementConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "sentryDetailedError", "description": "Detailed version of a Sentry error on the project", "args": [ @@ -20108,6 +20270,118 @@ }, { "kind": "OBJECT", + "name": "RequirementConnection", + "description": "The connection type for Requirement.", + "fields": [ + { + "name": "edges", + "description": "A list of edges.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "RequirementEdge", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodes", + "description": "A list of nodes.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Requirement", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageInfo", + "description": "Information to aid in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "RequirementEdge", + "description": "An edge in a connection.", + "fields": [ + { + "name": "cursor", + "description": "A cursor for use in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "node", + "description": "The item at the end of the edge.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "Requirement", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", "name": "RequirementPermissions", "description": "Check permissions for the current user on a requirement", "fields": [ @@ -22644,6 +22918,41 @@ "possibleTypes": null }, { + "kind": "ENUM", + "name": "Sort", + "description": "Common sort values", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "updated_desc", + "description": "Updated at descending order", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "updated_asc", + "description": "Updated at ascending order", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "created_desc", + "description": "Created at descending order", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "created_asc", + "description": "Created at ascending order", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { "kind": "SCALAR", "name": "String", "description": "Represents textual data as UTF-8 character sequences. This type is most often used by GraphQL to represent free-form human-readable text.", diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index d6a427d045c..38067b275d5 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -898,6 +898,7 @@ Information about pagination in a connection. | `removeSourceBranchAfterMerge` | Boolean | Indicates if `Delete source branch` option should be enabled by default for all new merge requests of the project | | `repository` | Repository | Git repository of the project | | `requestAccessEnabled` | Boolean | Indicates if users can request member access to the project | +| `requirement` | Requirement | Find a single requirement. Available only when feature flag `requirements_management` is enabled. | | `sentryDetailedError` | SentryDetailedError | Detailed version of a Sentry error on the project | | `sentryErrors` | SentryErrorCollection | Paginated collection of Sentry errors on the project | | `serviceDeskAddress` | String | E-mail address of the service desk. | diff --git a/doc/development/contributing/issue_workflow.md b/doc/development/contributing/issue_workflow.md index 46d1d4c2414..94cf1c223dd 100644 --- a/doc/development/contributing/issue_workflow.md +++ b/doc/development/contributing/issue_workflow.md @@ -81,7 +81,7 @@ already reserved for category labels). The descriptions on the [labels page](https://gitlab.com/groups/gitlab-org/-/labels) explain what falls under each type label. -The GitLab handbook documents [when something is a bug and when it is a feature request.](https://about.gitlab.com/handbook/product/product-management/process/feature-or-bug.html) +The GitLab handbook documents [when something is a bug and when it is a feature request](https://about.gitlab.com/handbook/product/product-management/process/feature-or-bug.html). ### Facet labels diff --git a/doc/development/insert_into_tables_in_batches.md b/doc/development/insert_into_tables_in_batches.md index 763185013c9..de62d2cca52 100644 --- a/doc/development/insert_into_tables_in_batches.md +++ b/doc/development/insert_into_tables_in_batches.md @@ -32,12 +32,12 @@ The `BulkInsertSafe` concern has two functions: - It performs checks against your model class to ensure that it does not use ActiveRecord APIs that are not safe to use with respect to bulk insertions (more on that below). -- It adds a new class method `bulk_insert!`, which you can use to insert many records at once. +- It adds new class methods `bulk_insert!` and `bulk_upsert!`, which you can use to insert many records at once. -## Insert records via `bulk_insert!` +## Insert records with `bulk_insert!` and `bulk_upsert!` -If the target class passes the checks performed by `BulkInsertSafe`, you can proceed to use -the `bulk_insert!` class method as follows: +If the target class passes the checks performed by `BulkInsertSafe`, you can insert an array of +ActiveRecord model objects as follows: ```ruby records = [MyModel.new, ...] @@ -45,6 +45,28 @@ records = [MyModel.new, ...] MyModel.bulk_insert!(records) ``` +Note that calls to `bulk_insert!` will always attempt to insert _new records_. If instead +you would like to replace existing records with new values, while still inserting those +that do not already exist, then you can use `bulk_upsert!`: + +```ruby +records = [MyModel.new, existing_model, ...] + +MyModel.bulk_upsert!(records, unique_by: [:name]) +``` + +In this example, `unique_by` specifies the columns by which records are considered to be +unique and as such will be updated if they existed prior to insertion. For example, if +`existing_model` has a `name` attribute, and if a record with the same `name` value already +exists, its fields will be updated with those of `existing_model`. + +The `unique_by` parameter can also be passed as a `Symbol`, in which case it specifies +a database index by which a column is considered unique: + +```ruby +MyModel.bulk_insert!(records, unique_by: :index_on_name) +``` + ### Record validation The `bulk_insert!` method guarantees that `records` will be inserted transactionally, and @@ -74,6 +96,23 @@ Since this will also affect the number of `INSERT`s that occur, make sure you me performance impact this might have on your code. There is a trade-off between the number of `INSERT` statements the database has to process and the size and cost of each `INSERT`. +### Handling duplicate records + +NOTE: **Note:** +This parameter applies only to `bulk_insert!`. If you intend to update existing +records, use `bulk_upsert!` instead. + +It may happen that some records you are trying to insert already exist, which would result in +primary key conflicts. There are two ways to address this problem: failing fast by raising an +error or skipping duplicate records. The default behavior of `bulk_insert!` is to fail fast +and raise an `ActiveRecord::RecordNotUnique` error. + +If this is undesirable, you can instead skip duplicate records with the `skip_duplicates` flag: + +```ruby +MyModel.bulk_insert!(records, skip_duplicates: true) +``` + ### Requirements for safe bulk insertions Large parts of ActiveRecord's persistence API are built around the notion of callbacks. Many @@ -145,11 +184,12 @@ simply be treated as if you had invoked `save` from outside the block. There are a few restrictions to how these APIs can be used: -- Bulk inserts only work for new records; `UPDATE`s or "upserts" are not supported yet. - `ON CONFLICT` behavior cannot currently be configured; an error will be raised on primary key conflicts. - `BulkInsertableAssociations` furthermore has the following restrictions: - only compatible with `has_many` relations. - does not support `has_many through: ...` relations. +- Writing [`jsonb`](https://www.postgresql.org/docs/current/datatype-json.html) content is +[not currently supported](https://gitlab.com/gitlab-org/gitlab/-/issues/210560). Moreover, input data should either be limited to around 1000 records at most, or already batched prior to calling bulk insert. The `INSERT` statement will run in a single diff --git a/doc/policy/maintenance.md b/doc/policy/maintenance.md index 028e372985d..441360aa812 100644 --- a/doc/policy/maintenance.md +++ b/doc/policy/maintenance.md @@ -144,10 +144,20 @@ It's also important to ensure that any background migrations have been fully com before upgrading to a new major version. To see the current size of the `background_migration` queue, [Check for background migrations before upgrading](../update/README.md#checking-for-background-migrations-before-upgrading). -From version 12 onwards, an additional step is required. More significant migrations may occur during major release upgrades. To ensure these are successful, increment to the first minor version (`x.0.x`) during the major version jump. Then proceed with upgrading to a newer release. +### Version 12 onwards: Extra step for major upgrades + +From version 12 onwards, an additional step is required. More significant migrations +may occur during major release upgrades. + +To ensure these are successful: + +1. Increment to the first minor version (`x.0.x`) during the major version jump. +1. Proceed with upgrading to a newer release. For example: `11.11.x` -> `12.0.x` -> `12.8.x` +### Example upgrade paths + Please see the table below for some examples: | Latest stable version | Your version | Recommended upgrade path | Note | @@ -155,8 +165,10 @@ Please see the table below for some examples: | 9.4.5 | 8.13.4 | `8.13.4` -> `8.17.7` -> `9.4.5` | `8.17.7` is the last version in version `8` | | 10.1.4 | 8.13.4 | `8.13.4 -> 8.17.7 -> 9.5.10 -> 10.1.4` | `8.17.7` is the last version in version `8`, `9.5.10` is the last version in version `9` | | 11.3.4 | 8.13.4 | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7` is the last version in version `8`, `9.5.10` is the last version in version `9`, `10.8.7` is the last version in version `10` | -| 12.5.8 | 11.3.4 | `11.3.4` -> `11.11.8` -> `12.0.12` -> `12.5.8` | `11.11.8` is the last version in version `11`. `12.0.x` [is a required step.](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23211#note_272842444) | -| 12.8.5 | 9.2.6 | `9.2.6` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.8.5` | Four intermediate versions required: the final 9.5, 10.8, 11.11 releases, plus 12.0 | +| 12.5.8 | 11.3.4 | `11.3.4` -> `11.11.8` -> `12.0.12` -> `12.5.8` | `11.11.8` is the last version in version `11`. `12.0.x` [is a required step](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23211#note_272842444). | +| 12.8.5 | 9.2.6 | `9.2.6` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.8.5` | Four intermediate versions are required: the final 9.5, 10.8, 11.11 releases, plus 12.0. | + +## More information More information about the release procedures can be found in our [release documentation](https://gitlab.com/gitlab-org/release/docs). You may also want to read our diff --git a/doc/user/clusters/applications.md b/doc/user/clusters/applications.md index 0fa5e62dc68..4768fcc2970 100644 --- a/doc/user/clusters/applications.md +++ b/doc/user/clusters/applications.md @@ -548,6 +548,7 @@ Supported applications: - [Sentry](#install-sentry-using-gitlab-ci) - [GitLab Runner](#install-gitlab-runner-using-gitlab-ci) - [Cilium](#install-cilium-using-gitlab-ci) +- [Vault](#install-vault-using-gitlab-ci) - [JupyterHub](#install-jupyterhub-using-gitlab-ci) - [Elastic Stack](#install-elastic-stack-using-gitlab-ci) - [Crossplane](#install-crossplane-using-gitlab-ci) @@ -813,6 +814,95 @@ agent: enabled: false ``` +### Install Vault using GitLab CI + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/9982) in GitLab 12.9. + +[Hashicorp Vault](https://vaultproject.io/) is a secrets management solution which +can be used to safely manage and store passwords, credentials, certificates and more. A Vault +installation could be leveraged to provide a single secure data store for credentials +used in your applications, GitLab CI jobs, and more. It could also serve as a way of +providing SSL/TLS certificates to systems and deployments in your infrastructure. Leveraging +Vault as a single source for all these credentials allows greater security by having +a single source of access, control, and auditability around all your sensitive +credentials and certificates. + +To install Vault, enable it in the `.gitlab/managed-apps/config.yaml` file: + +```yaml +vault: + installed: true +``` + +By default you will get a basic Vault setup with no high availability nor any scalable +storage backend. This is enough for simple testing and small scale deployments, though has limits +to how much it can scale, and as it is a single instance deployment, you will experience downtime +when upgrading the Vault application. + +To optimally use Vault in a production environment, it's ideal to have a good understanding +of the internals of Vault and how to configure it. This can be done by reading the +[the Vault documentation](https://www.vaultproject.io/docs/internals/) as well as +the Vault Helm chart [values.yaml file](https://github.com/hashicorp/vault-helm/blob/v0.3.3/values.yaml). + +At a minimum you will likely set up: + +- A [seal](https://www.vaultproject.io/docs/configuration/seal/) for extra encryption + of the master key. +- A [storage backend](https://www.vaultproject.io/docs/configuration/storage/) that is + suitable for environment and storage security requirements. +- [HA Mode](https://www.vaultproject.io/docs/concepts/ha/). +- [The Vault UI](https://www.vaultproject.io/docs/configuration/ui/). + +The following is an example values file (`.gitlab/managed-apps/vault/values.yaml`) +that configures Google Key Management Service for auto-unseal, using a Google Cloud Storage backend, enabling +the Vault UI, and enabling HA with 3 pod replicas. The `storage` and `seal` stanzas +below are examples and should be replaced with settings specific to your environment. + +```yaml +# Enable the Vault WebUI +ui: + enabled: true +server: + # Disable the built in data storage volume as it's not safe for Hight Availablity mode + dataStorage: + enabled: false + # Enable High Availability Mode + ha: + enabled: true + # Configure Vault to listen on port 8200 for normal traffic and port 8201 for inter-cluster traffic + config: | + listener "tcp" { + tls_disable = 1 + address = "[::]:8200" + cluster_address = "[::]:8201" + } + # Configure Vault to store its data in a GCS Bucket backend + storage "gcs" { + path = "gcs://my-vault-storage/vault-bucket" + ha_enabled = "true" + } + # Configure Vault to automatically unseal storage using a GKMS key + seal "gcpckms" { + project = "vault-helm-dev-246514" + region = "global" + key_ring = "vault-helm-unseal-kr" + crypto_key = "vault-helm-unseal-key" + } +``` + +Once you have successfully installed Vault, you will need to [initialize the Vault](https://learn.hashicorp.com/vault/getting-started/deploy#initializing-the-vault) +and obtain the initial root token. You will need access to your Kubernetes cluster that Vault has been deployed into in order to do this. +To initialise the Vault, get a shell to one of the Vault pods running inside Kubernetes (typically this is done by using the `kubectl` command line tool). +Once you have a shell into the pod, run the `vault operator init` command: + +```shell +kubectl -n gitlab-managed-apps exec -it vault-0 sh +/ $ vault operator init +``` + +This should give you your unseal keys and initial root token. Make sure to note these down +and keep these safe as you will need them to unseal the Vault throughout its lifecycle. + ### Install JupyterHub using GitLab CI > [Introduced](https://gitlab.com/gitlab-org/cluster-integration/cluster-applications/-/merge_requests/40) in GitLab 12.8. |