`gitlab-ctl reconfigure` fails when `gitlab_rails['uploads_directory']` points to symlink to directory instead of pointing to directory

Summary

gitlab-ctl reconfigure fails when gitlab_rails['uploads_directory'] points to symlink to directory instead of pointing directly to directory.

Occured during upgrade from gitlab-ce 8.12.3-ce.0 to 8.11.5-ce.0

Steps to reproduce

  1. Make a symlink to uploads directory
  2. Point gitlab_rails['uploads_directory'] to this symlink.
  3. Run gitlab-ctl reconfigure.

Expected behavior

No errors.

Actual behavior

See the log below.

Relevant logs and/or screenshots

# gitlab-ctl reconfigure
...
Recipe: gitlab::gitlab-rails
  * directory[/var/log/gitlab] action create (up to date)
  * ruby_block[directory resource: /srv/git/shared] action run (skipped due to not_if)
  * ruby_block[directory resource: /srv/git/artifacts] action run (skipped due to not_if)
  * ruby_block[directory resource: /srv/git/lfs-objects] action run (skipped due to not_if)
  * ruby_block[directory resource: /var/opt/gitlab/gitlab-rails/uploads] action run
    
    ================================================================================
    Error executing action `run` on resource 'ruby_block[directory resource: /var/opt/gitlab/gitlab-rails/uploads]'
    ================================================================================
    
    Mixlib::ShellOut::ShellCommandFailed
    ------------------------------------
    Expected process to exit with [0], but received '1'
    ---- Begin output of test -d "/var/opt/gitlab/gitlab-rails/uploads" -a "$(stat --printf='%U %04a' /var/opt/gitlab/gitlab-rails/uploads)" = 'git 0700' ----
    STDOUT: 
    STDERR: 
    ---- End output of test -d "/var/opt/gitlab/gitlab-rails/uploads" -a "$(stat --printf='%U %04a' /var/opt/gitlab/gitlab-rails/uploads)" = 'git 0700' ----
    Ran test -d "/var/opt/gitlab/gitlab-rails/uploads" -a "$(stat --printf='%U %04a' /var/opt/gitlab/gitlab-rails/uploads)" = 'git 0700' returned 1
    
    Cookbook Trace:
    ---------------
    /opt/gitlab/embedded/cookbooks/cache/cookbooks/gitlab/libraries/storage_directory_helper.rb:35:in `run_command'
    /opt/gitlab/embedded/cookbooks/cache/cookbooks/gitlab/libraries/storage_directory_helper.rb:89:in `validate'
    /opt/gitlab/embedded/cookbooks/cache/cookbooks/gitlab/libraries/storage_directory_helper.rb:82:in `validate!'
    /opt/gitlab/embedded/cookbooks/cache/cookbooks/gitlab/definitions/storage_directory.rb:35:in `block (3 levels) in from_file'
    
    Resource Declaration:
    ---------------------
    # In /opt/gitlab/embedded/cookbooks/cache/cookbooks/gitlab/definitions/storage_directory.rb
    
     26:   ruby_block "directory resource: #{params[:path]}" do
     27:     block do
     28:       # Ensure the directory exists
     29:       storage_helper.ensure_directory_exists(params[:path])
     30: 
     31:       # Ensure the permissions are set
     32:       storage_helper.ensure_permissions_set(params[:path])
     33: 
     34:       # Error out if we have not achieved the target permissions
     35:       storage_helper.validate!(params[:path])
     36:     end
     37:     not_if { storage_helper.validate(params[:path]) }
     38:   end
     39: end
    
    Compiled Resource:
    ------------------
    # Declared in /opt/gitlab/embedded/cookbooks/cache/cookbooks/gitlab/definitions/storage_directory.rb:26:in `block in from_file'
    
    ruby_block("directory resource: /var/opt/gitlab/gitlab-rails/uploads") do
      params {:path=>"/var/opt/gitlab/gitlab-rails/uploads", :owner=>"git", :group=>nil, :mode=>"0700", :name=>"/var/opt/gitlab/gitlab-rails/uploads"}
      action [:run]
      retries 0
      retry_delay 2
      default_guard_interpreter :default
      block_name "directory resource: /var/opt/gitlab/gitlab-rails/uploads"
      declared_type :ruby_block
      cookbook_name "gitlab"
      recipe_name "gitlab-rails"
      block #<Proc:0x00000004f73a10@/opt/gitlab/embedded/cookbooks/cache/cookbooks/gitlab/definitions/storage_directory.rb:27>
      not_if { #code block }
    end
    
    Platform:
    ---------
    x86_64-linux
    

Running handlers:
Running handlers complete
Chef Client failed. 2 resources updated in 23 seconds

Output of checks

Results of GitLab application Check

All green (after changing the option to the actual directory instead of symlink).

Results of GitLab environment info

System information
System:         Debian 8.6
Current User:   git
Using RVM:      no
Ruby Version:   2.3.1p112
Gem Version:    2.6.6
Bundler Version:1.13.1
Rake Version:   10.5.0
Sidekiq Version:4.1.4

GitLab information
Version:        8.12.3
Revision:       467e1ca
Directory:      /opt/gitlab/embedded/service/gitlab-rails
DB Adapter:     postgresql
URL:            https://***
HTTP Clone URL: https://***/some-group/some-project.git
SSH Clone URL:  git@***:some-group/some-project.git
Using LDAP:     no
Using Omniauth: yes
Omniauth Providers: gitlab, github

GitLab Shell
Version:        3.6.1
Repository storage paths:
- default:      /srv/git/repositories
Hooks:          /opt/gitlab/embedded/service/gitlab-shell/hooks/
Git:            /opt/gitlab/embedded/bin/git

Possible fixes

Once the option is pointed to directory instead of symlink everything works as expected.

I believe the check should pass with a symlink to a directory.

This issue may also be relevant to other options and directory checks.