Read about our upcoming Code of Conduct on this issue

Commit ae3644ff authored by Georges Racinet's avatar Georges Racinet 🦑
Browse files

Merged upstream GDK as of roughly GitLab 14.4

This entails an update of the Ruby version to 2.7.4
(totally necessary as it can conflict witht the one for Rails).

With this change also comes the split of the Makefile, a good thing in
the absolute, yet it could take us some time to stabilize.

--HG--
branch : heptapod
......@@ -27,6 +27,10 @@ indent_style = unset
indent_style = tab
indent_size = unset
[*.mk]
indent_style = tab
indent_size = unset
[GDK_ROOT]
end_of_line = unset
trim_trailing_whitespace = unset
......
!/repositories/.gitkeep
node_modules/
*.crt
*.key
*.pem
......@@ -42,8 +41,8 @@ node_modules/
/gitlab-development-kit/**
/gitlab-docs
/gitlab-elasticsearch-indexer
/gitlab-k8s-agent/
/gitlab-k8s-agent-config.yml
/gitlab-k8s-agent/
/gitlab-pages
/gitlab-pages-secret
/gitlab-runner
......@@ -110,3 +109,5 @@ node_modules/
/sv/
/webpack_port
Brewfile.lock.json
haproxy/haproxy.cfg
node_modules/
......@@ -6,20 +6,21 @@ stages:
- deploy
variables:
VERIFY_IMAGE: $CI_REGISTRY_IMAGE/asdf-bootstrapped-verify:$CI_COMMIT_REF_SLUG
DEFAULT_IMAGE: $CI_REGISTRY_IMAGE/asdf-bootstrapped-verify:$CI_COMMIT_REF_SLUG
GITPOD_WORKSPACE_IMAGE_BASE: $CI_REGISTRY_IMAGE/gitpod-workspace
GITPOD_WORKSPACE_IMAGE: $CI_REGISTRY_IMAGE/gitpod-workspace:$CI_COMMIT_REF_SLUG
GDK_DEBUG: "false"
default:
interruptible: true
image: ${DEFAULT_IMAGE}
tags:
- gitlab-org
before_script:
- test -f support/ci/display_debugging && support/ci/display_debugging
include:
- template: 'Workflows/MergeRequest-Pipelines.gitlab-ci.yml'
- template: Workflows/MergeRequest-Pipelines.gitlab-ci.yml
- local: .gitlab/ci/_rules.gitlab-ci.yml
- local: .gitlab/ci/_docker.gitlab-ci.yml
- local: .gitlab/ci/pre.gitlab-ci.yml
......
include:
- template: Code-Quality.gitlab-ci.yml
- template: Container-Scanning.gitlab-ci.yml
- template: Dependency-Scanning.gitlab-ci.yml
- remote: 'https://gitlab.com/gitlab-org/frontend/untamper-my-lockfile/-/raw/main/.gitlab-ci-template.yml'
docs-lint:
extends: .rules:docs-changes
image: registry.gitlab.com/gitlab-org/gitlab-docs/lint-markdown:alpine-3.13-vale-2.10.2-markdownlint-0.26.0
image: registry.gitlab.com/gitlab-org/gitlab-docs/lint-markdown:alpine-3.14-vale-2.10.4-markdownlint-0.28.1
stage: test
needs: []
script:
......@@ -50,11 +51,14 @@ code_quality:
container_scanning:
before_script:
- export DOCKER_IMAGE=${VERIFY_IMAGE}
- export DOCKER_IMAGE=${DEFAULT_IMAGE}
needs:
- release-image
rules: !reference ['.rules:code-changes', rules]
gemnasium-dependency_scanning:
rules: !reference ['.rules:code-changes', rules]
shellcheck:
extends: .rules:code-changes
stage: test
......@@ -67,8 +71,7 @@ checkmake:
stage: test
needs: []
extends: .rules:code-changes
# https://gitlab.com/gitlab-org/gitlab-development-kit/-/issues/1234
image: $CI_REGISTRY_IMAGE/asdf-bootstrapped-verify:main
image: registry.gitlab.com/gitlab-org/gitlab-development-kit/asdf-bootstrapped-verify:main
script:
- make checkmake
......@@ -96,6 +99,21 @@ verify-gdk-example-yml:
script:
- make verify-gdk-example-yml
verify-asdf-combine:
extends: .rules:code-changes
image: ruby:2.7
stage: test
needs: []
script:
- make verify-asdf-combine
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
- if: '$CI_MERGE_REQUEST_IID'
changes:
- ".tool-versions*"
- "support/asdf-combine"
- "support/ci/verify-asdf-combine"
danger-review:
extends:
- .review:rules:danger
......
.verify-job:
stage: verify
extends: .rules:code-changes
image: ${VERIFY_IMAGE}
needs:
- release-image
artifacts:
......
## Overview
<!-- Details of the issue. Include any console output or screenshots. -->
<!-- Details of the issue. Include any console output or screenshots. -->
## Steps to replicate (optional)
......@@ -16,3 +16,5 @@
- The contents of your `gdk.yml`
- Ruby version: `<!-- output of `ruby --version` -->`
- GDK version: `<!-- output of `git rev-parse --short HEAD` -->`
/label ~"Category:GDK" ~Quality ~"Engineering Productivity"
......@@ -4,10 +4,11 @@
## Merge Request checklist
- [ ] This change is backward compatible. If not, please include steps to communicate to our users.
- [ ] This change is backward compatible. If not, please include steps to communicate to our users.
- [ ] Tests added for new functionality. If not, please raise Issue to follow-up.
- [ ] Documentation added/updated, if needed.
- [ ] `gdk doctor` test added, if needed.
- [ ] Add the `~highlight` label if this MR should be included in the [`CHANGELOG.md`](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/CHANGELOG.md).
/label ~"Category:GDK" ~"section::dev" ~"devops::create" ~"group::ecosystem"
/label ~"Category:GDK" ~Quality ~"Engineering Productivity"
/assign me
......@@ -9,10 +9,15 @@ require:
AllCops:
TargetRubyVersion: 2.7.2
Exclude:
- 'GDK_ROOT'
- '.backups/**/*'
- '.cache/**/*'
- '.git/**/*'
- 'Brewfile'
- 'Dangerfile'
- 'charts-gitlab/**/*'
- 'danger/**/*'
- 'dev/**/*'
- 'elasticsearch/**/*'
- 'gitaly/**/*'
- 'gitlab-docs/**/*'
......
# Versions of GDK dependencies managed by asdf.
# support/asdf-combine generates this file from .tool-versions-gdk and the .tool-versions
# files from GDK sub-projects.
#
# New versions must be introduced alongside the current version, and are automatically installed by
# GDK for asdf users.
#
# <default-version> <other-version>
ruby 2.7.2
# At least one Go version must match a Go version set in the `.tool-versions` file of the version of
# the `gitlab-pages` and `gitaly` projects used by GDK. See `pages_version` and `gitaly_version` in
# the GDK Makefile.
golang 1.16.4
nodejs 14.17.2
yarn 1.22.10
minio 2021-02-07T01-31-02Z
# Do not modify this file directly.
golang 1.17.1 1.16.9 1.16.8
minio 2021-04-06T23-11-00Z
nodejs 14.17.5
postgres 12.6 11.9
redis 6.0.10
redis 6.0.15
ruby 2.7.4 3.0.2
yarn 1.22.11
# Versions of GDK dependencies managed by asdf.
#
# New versions must be introduced alongside the current version, and are automatically installed by
# GDK for asdf users.
#
# <default-version> <other-version>
ruby 2.7.4 3.0.2
# At least one Go version must match a Go version set in the `.tool-versions` file of the version of
# the `gitlab-pages` and `gitaly` projects used by GDK. See `pages_version` and `gitaly_version` in
# the GDK Makefile.
golang 1.17.1
nodejs 14.17.5
yarn 1.22.11
minio 2021-04-06T23-11-00Z
postgres 12.6 11.9
redis 6.0.15
......@@ -8,7 +8,7 @@ brew "gpg"
brew "graphicsmagick"
brew "icu4c"
brew "libiconv"
brew "openssl"
brew "openssl@1.1"
brew "pkg-config"
brew "re2"
brew "runit"
......
......@@ -9,7 +9,7 @@ group :development do
end
group :test do
gem 'gitlab-styles', '~> 6.2.0', require: false
gem 'gitlab-styles', '~> 6.3.0', require: false
gem 'pry-byebug', '~> 3.9.0', require: false
gem 'rspec', '~> 3.10.0', require: false
gem 'rspec_junit_formatter', '~> 0.4.0', require: false
......@@ -17,5 +17,5 @@ group :test do
end
group :development, :test, :danger do
gem 'gitlab-dangerfiles', '~> 2.2.0', require: false
gem 'gitlab-dangerfiles', '~> 2.3.0', require: false
end
GEM
remote: https://rubygems.org/
specs:
activesupport (6.1.4)
activesupport (6.1.4.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
......@@ -21,7 +21,7 @@ GEM
concurrent-ruby (1.1.9)
cork (0.3.0)
colored2 (~> 3.1)
danger (8.3.1)
danger (8.4.0)
claide (~> 1.0)
claide-plugins (>= 0.9.2)
colored2 (~> 3.1)
......@@ -39,7 +39,7 @@ GEM
gitlab (~> 4.2, >= 4.2.0)
diff-lcs (1.4.4)
docile (1.4.0)
faraday (1.5.1)
faraday (1.8.0)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
......@@ -47,6 +47,7 @@ GEM
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.1)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
multipart-post (>= 1.2, < 3)
ruby2_keywords (>= 0.0.4)
faraday-em_http (1.0.0)
......@@ -56,23 +57,24 @@ GEM
faraday (>= 0.8)
faraday-httpclient (1.0.1)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.1.0)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
git (1.9.1)
rchardet (~> 1.8)
gitlab (4.17.0)
httparty (~> 0.18)
terminal-table (~> 1.5, >= 1.5.1)
gitlab-dangerfiles (2.2.2)
gitlab-dangerfiles (2.3.1)
danger (>= 8.3.1)
danger-gitlab (>= 8.0.0)
gitlab-styles (6.2.0)
gitlab-styles (6.3.0)
rubocop (~> 0.91, >= 0.91.1)
rubocop-gitlab-security (~> 0.1.1)
rubocop-performance (~> 1.9.2)
rubocop-rails (~> 2.9)
rubocop-rspec (~> 1.44)
httparty (0.18.1)
httparty (0.20.0)
mime-types (~> 3.0)
multi_xml (>= 0.5.2)
i18n (1.8.10)
......@@ -81,11 +83,11 @@ GEM
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
lefthook (0.7.6)
lefthook (0.7.7)
method_source (1.0.0)
mime-types (3.3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2021.0704)
mime-types-data (3.2021.0901)
minitest (5.14.4)
multi_xml (0.6.0)
multipart-post (2.1.1)
......@@ -95,8 +97,8 @@ GEM
faraday (>= 0.9)
sawyer (~> 0.8.0, >= 0.5.3)
open4 (1.3.4)
parallel (1.20.1)
parser (3.0.1.1)
parallel (1.21.0)
parser (3.0.2.0)
ast (~> 2.4.1)
pry (0.13.1)
coderay (~> 1.1)
......@@ -107,7 +109,7 @@ GEM
public_suffix (4.0.6)
rack (2.2.3)
rainbow (3.0.0)
rake (13.0.3)
rake (13.0.6)
rchardet (1.8.0)
regexp_parser (2.1.1)
rexml (3.2.5)
......@@ -135,7 +137,7 @@ GEM
rubocop-ast (>= 0.6.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 2.0)
rubocop-ast (1.7.0)
rubocop-ast (1.12.0)
parser (>= 3.0.1.1)
rubocop-gitlab-security (0.1.1)
rubocop (>= 0.51)
......@@ -150,7 +152,7 @@ GEM
rubocop (~> 0.87)
rubocop-ast (>= 0.7.1)
ruby-progressbar (1.11.0)
ruby2_keywords (0.0.4)
ruby2_keywords (0.0.5)
sawyer (0.8.2)
addressable (>= 2.3.5)
faraday (> 0.8, < 2.0)
......@@ -166,7 +168,7 @@ GEM
unicode-display_width (~> 1.1, >= 1.1.1)
tzinfo (2.0.4)
concurrent-ruby (~> 1.0)
unicode-display_width (1.7.0)
unicode-display_width (1.8.0)
yard (0.9.26)
zeitwerk (2.4.2)
......@@ -174,8 +176,8 @@ PLATFORMS
ruby
DEPENDENCIES
gitlab-dangerfiles (~> 2.2.0)
gitlab-styles (~> 6.2.0)
gitlab-dangerfiles (~> 2.3.0)
gitlab-styles (~> 6.3.0)
lefthook (~> 0.7.0)
pry-byebug (~> 3.9.0)
rake (~> 13.0.0)
......
......@@ -11,6 +11,7 @@ Manage services:
gdk status # See status of all services
gdk restart # Restart everything
gdk restart redis postgresql # Restart specific services
gdk kill # Forcibly kills services
gdk tail # Tail all logs
gdk tail redis postgresql # Tail specific logs
......@@ -39,6 +40,8 @@ Manage GDK:
gdk reset-data # Backs up and creates fresh git
# repository, PostgreSQL data and
# Rails upload directory
gdk reset-praefect-data # Backs up and creates fresh Praefect
# PostgreSQL data
gdk pristine # Restore your GDK to a pristine
# state. Deletes caches, temporary files, and
# reinstalls dependencies. Does not delete data
......
This diff is collapsed.
......@@ -409,18 +409,28 @@ The following installation methods are supported, actively maintained, and teste
```
- [Simple installation](doc/index.md) on your local system. Requires at least
8GB RAM and 12GB disk space. Available for:
| Operating system | Versions |
|:-----------------|:--------------------|
| macOS | 11, 10.15, 10.14 |
| Ubuntu | 20.10, 20.04, 18.04 |
| Debian | 10, 9 |
| Arch | latest |
| Manjaro | latest |
8GB RAM and 12GB disk space. Available for [supported platforms](#supported-platforms).
- [Gitpod](doc/howto/gitpod.md).
### Supported platforms
| Operating system | Versions |
|:-----------------|:--------------------|
| macOS | 11, 10.15, 10.14 |
| Ubuntu | 20.10, 20.04, 18.04 |
| Debian | 10, 9 |
| Arch | latest |
| Manjaro | latest |
#### macOS with Apple silicon
Running GDK on macOS with [Apple silicon](https://en.wikipedia.org/wiki/Apple_silicon)
requires [Rosetta 2](https://en.wikipedia.org/wiki/Rosetta_(software)#Rosetta_2).
Follow [Native Apple silicon support](https://gitlab.com/gitlab-org/gitlab-development-kit/-/issues/1159)
for updates on supporting Apple silicon natively.
### Unsupported methods
The following documentation is provided for those who can benefit from it, but aren't
......
#!/bin/bash
find_gdk_root() {
if [[ "${1}" == "/" ]]; then
exit 1
fi
if [[ -f "${1}/GDK_ROOT" && -x "${1}/gem/bin/gdk" ]]; then
echo "${1}"
else
one_path_back="$(cd "${1}/.." || exit ; pwd -P)"
find_gdk_root "${one_path_back}"
fi
}
gdk_root_path=$(find_gdk_root "$(pwd -P)")
if [[ -d "${gdk_root_path}" ]]; then
exec "${gdk_root_path}/gem/bin/gdk" "${@}"
else
echo "ERROR: The current working directory is not a GDK." >&2
fi
......@@ -87,6 +87,7 @@ Here are a few settings worth mentioning:
| `listen_address` | `127.0.0.1` | Select the IP for GDK to listen on. Note, this will occasionally be used as a hostname/URL (when running feature specs for example), so using 0.0.0.0 can be problematic. |
| `port` | `3000` | Select the port to run GDK on, useful when running multiple GDKs in parallel. |
| `webpack.port` | `3808` | Also useful to configure when running GDKs in parallel. [See below for more webpack options](#webpack-settings). |
| `gitlab.rails.bundle_gemfile` | `Gemfile` | Set this to where GitLab should look for Gemfile. |
| `gitlab.cache_classes` | `false` | Set this to `true` to disable the automatic reloading of Ruby classes when Ruby code is changed. |
| `gitlab_pages.host` | `127.0.0.1.nip.io` | Specify GitLab Pages hostname. See also the [Pages guide](howto/pages.md#hostname). |
| `gitlab_pages.port` | `3010` | Specify on which port GitLab Pages should run. See also the [Pages guide](howto/pages.md#port). |
......@@ -222,6 +223,7 @@ There are also a few settings that configure the behavior of GDK itself:
| `gdk.runit_wait_secs` | `10` | The number of seconds `runit` waits. `runit` is used behind the scenes for `gdk stop/start/restart` and waits for 7 secs by default. |
| `gdk.quiet` | `true` | Set this to `false` to increase the level of output when updating the GDK. |
| `gdk.auto_reconfigure` | `true` | Set this to `false` to not run a `gdk reconfigure` after a successful `gdk update`. |
| `gdk.auto_rebase_projects` | `false` | Set this to `true` to automatically rebase projects as part of a `gdk update`. |
##### Hooks
......@@ -242,24 +244,20 @@ Hooks are executed with the GDK root directory as the working directory. Executi
NOTE:
When running `gdk restart`, `gdk.stop_hooks` (both before & after) are executed before restarting and `gdk.start_hooks` (both before & after) are executed after restarting.
For example, if you're left with changes in `gitlab/db/structure.sql` after a
`gdk update` (see [GitLab#300251](https://gitlab.com/gitlab-org/gitlab/-/issues/300251)),
you can use `gdk.update_hooks.after` in your `gdk.yml`:
```yaml
gdk:
update_hooks:
after:
- cd gitlab; git checkout db/structure.sql
```
A common use for GDK hooks is to [remove uncommitted changes to `gitlab/db/structure.sql`](troubleshooting.md#gdk-update-leaves-gitlabdbstructuresql-with-uncommitted-changes)
after `gdk update`.
### GitLab settings
| Setting | Default | Description |
|---------|---------|-------------|
| `gitlab.cache_classes` | `false` | Set this to `true` to disable the automatic reloading of Ruby classes when Ruby code is changed. |
| `gitlab.rails.hostname` | `127.0.0.1` | Specify the hostname value that Rails uses when generating URLs. |
| `gitlab.rails.port` | `3000` | Specify the port value that Rails uses when generating URLs. |
| `gitlab.rails.https.enabled` | `false` | Specify if HTTPS is enabled which Rails uses when generating URLs. |
| `gitlab.rails.address` | `''` | Specify whether Rails should listen to a UNIX socket or a TCP port. Useful for debugging with Wireshark. Use `host:port` to listen on a TCP port. Do **not** include `http://`. |
| `gitlab.rails.multiple_databases` | `false` | Set this to `true` to configure [multiple databases](https://docs.gitlab.com/ee/development/database/multiple_databases.html) in your `config/database.yml`. |
| `gitlab.rails.separate_db_schemas` | `false` | Set this to `true` to configure `schema_search_path` in your `config/database.yml`. |
| `gitlab.rails.sherlock` | `false` | Set this to `true` to enable [Sherlock profiling](https://docs.gitlab.com/ee/development/profiling.html#sherlock). |
| `gitlab.rails.puma.workers` | `2` | Set this to `0` to prevent Puma (webserver) running in a [Clustered mode](https://github.com/puma/puma/blob/master/docs/architecture.md). Running in Single mode provides significant memory savings if you work within a [memory-constrained environment](https://gitlab.com/groups/gitlab-org/-/epics/5303). |
......@@ -450,7 +448,8 @@ webpack:
port: 3808
static: false
vendor_dll: false
incremental: false
incremental: true
incremental_ttl: 30
```
| Setting | Default | Description |
......@@ -459,13 +458,45 @@ webpack:
| `port` | `3808` | The port your webpack development server is running on. You should change this if you are running multiple GDKs |
| `static` | `false` | Setting this to `true` replaces the webpack development server with a lightweight Ruby server with. See below for more information |
| `vendor_dll` | `false` | Setting this to `true` moves certain dependencies to a webpack DLL. See below for more information |
| `incremental` | `false` | Setting this to `true` enables incremental webpack rendering. See below for more information |
| `incremental` | `true` | Setting this to `false` disables incremental webpack compilation. See below for more information |
| `incremental_ttl` | `30` | Sets the number of days after which a visited page's assets will be evicted from the list of bundles to eagerly compile. Set to `0` to eagerly compile every page's assets ever visited. |
| `sourcemaps` | `true` | Setting this to `false` disables source maps. This reduces memory consumption for those who do not need to debug frontend code. |
| `live_reload` | `true` | Setting this to `false` disables hot module replacement when changes are detected. This feature uses sockets and is currently incompatible with SSL, so it is disabled by default when SSL is enabled. |
#### Incremental webpack compilation
By default, webpack only compiles page bundles for pages that were visited
within the last `webpack.incremental_ttl` days. This is done to keep the memory
consumption of the webpack development server low. If you visit a previously
unvisited page or one visited longer than `webpack.incremental_ttl` days ago,
you see an overlay informing you that the page is being compiled. A page reload
(either manually or via `live_reload`) then ensures the correct assets are
served.
You can change the number of days that page bundles are considered "recent",
and should be eagerly compiled. This number represents the trade-off between
lazy/eager compilation versus low/high memory consumption of the webpack
development server. A higher number means fewer pages needing to be compiled on
demand, at the cost of higher memory consumption. A lower number means lower
memory consumption, at the cost of more pages being compiled on demand. A value
of `0` means that all pages in your history, regardless of how long ago you
visited them, are eagerly compiled.
For instance, if you visited a particular page `webpack.incremental_ttl - 1`
days ago, it would render as normal if you visted it _today_. But, if instead
you visit it _tomorrow_, you would see an initial "compiling" overlay.
The history of previously visited pages is stored in the `WEBPACK_CACHE_PATH`
directory. Clearing this directory will lose that history, meaning subsequent
page visits will trigger on demand compilation. Over time, your history will be
rebuilt.
To disable incremental compilation entirely and always eagerly compile all page
bundles, set `webpack.incremental: false` in your `gdk.yml`.
#### Saving memory on the webpack development server
GDK defaults to memory-intensive settings. GDK uses the webpack development server, which watches
GDK defaults to mostly memory-intensive settings. GDK uses the webpack development server, which watches
file changes and keeps all the frontend assets in memory. This allows for very fast recompilation.
An alternative is to lower the memory requirements of GDK. This is useful for back-end development
......@@ -477,10 +508,8 @@ or where GDK is running in lower-memory environments. To lower the memory requir
- Set `webpack.vendor_dll: true` in your `gdk.yml`. This mode is an alternate memory saving mode,
which takes infrequently updated dependencies and combines them into one long-lived bundle that is
written to disk and does not reside in memory. You may see 200 to 300 MB in memory savings.
- Set `webpack.incremental: true` in your `gdk.yml`. This enables incremental compilation of webpack
assets and only the JavaScript for pages you visit during development are compiled.
If you visit a previously unvisited page, you see an overlay informing you that the recompilation
happens. A page reload then serves the correct assets (either manually or via `live_reload`).
- Reduce the value of `webpack.incremental_ttl` in your `gdk.yml`. This means
fewer page bundles will be eagerly compiled.
This means you pay a high upfront cost of a single memory- and CPU-intenstive compile. However, if
you do not change any frontend files, you just have a lightweight Ruby server running.
......
......@@ -48,6 +48,19 @@ running tests), run:
gdk stop rails
```
## Kill all services
Services can fail to properly stop when running `gdk stop` and must be forcibly
terminated. To terminate unstoppable services, run:
```shell
gdk kill
```
This command is a manual command because it kills all `runsv` processes,
which can include processes outside the current GDK. Don't use this command if you're running
other processes with `runit`, or if you're running multiple instances of GDK (and you don't want to stop them all).
## Update GDK
To update `gitlab` and all of its dependencies, run the following commands:
......
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