Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/lint-docs-redirects.rb')
-rwxr-xr-xscripts/lint-docs-redirects.rb203
1 files changed, 203 insertions, 0 deletions
diff --git a/scripts/lint-docs-redirects.rb b/scripts/lint-docs-redirects.rb
new file mode 100755
index 00000000000..fb4ac19981d
--- /dev/null
+++ b/scripts/lint-docs-redirects.rb
@@ -0,0 +1,203 @@
+#!/usr/bin/env ruby
+
+# frozen_string_literal: true
+
+#
+# https://docs.gitlab.com/ee/development/documentation/redirects.html
+#
+require 'net/http'
+require 'uri'
+require 'json'
+require 'cgi'
+
+class LintDocsRedirect
+ COLOR_CODE_RED = "\e[31m"
+ COLOR_CODE_RESET = "\e[0m"
+ # All the projects we want this script to run
+ PROJECT_PATHS = ['gitlab-org/gitlab',
+ 'gitlab-org/gitlab-runner',
+ 'gitlab-org/omnibus-gitlab',
+ 'gitlab-org/charts/gitlab',
+ 'gitlab-org/cloud-native/gitlab-operator'].freeze
+
+ def execute
+ return unless project_supported?
+
+ abort_unless_merge_request_iid_exists
+
+ check_renamed_deleted_files
+ end
+
+ private
+
+ # Project slug based on project path
+ # Taken from https://gitlab.com/gitlab-org/gitlab/-/blob/daaa5b6f79049e5bb28cdafaa11d3a0a84d64ab3/scripts/trigger-build.rb#L298-313
+ def project_slug
+ case ENV['CI_PROJECT_PATH']
+ when 'gitlab-org/gitlab'
+ 'ee'
+ when 'gitlab-org/gitlab-runner'
+ 'runner'
+ when 'gitlab-org/omnibus-gitlab'
+ 'omnibus'
+ when 'gitlab-org/charts/gitlab'
+ 'charts'
+ when 'gitlab-org/cloud-native/gitlab-operator'
+ 'operator'
+ end
+ end
+
+ def navigation_file
+ @navigation_file ||= begin
+ url = URI('https://gitlab.com/gitlab-org/gitlab-docs/-/raw/main/content/_data/navigation.yaml')
+ response = Net::HTTP.get_response(url)
+
+ raise "Could not download navigation.yaml. Response code: #{response.code}" if response.code != '200'
+
+ # response.body should be memoized in a method, so that it doesn't
+ # need to be downloaded multiple times in one CI job.
+ response.body
+ end
+ end
+
+ ##
+ ## Check if the deleted/renamed file exists in
+ ## https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/content/_data/navigation.yaml.
+ ##
+ ## We need to first convert the Markdown file to HTML. There are two cases:
+ ##
+ ## - A source doc entry with index.md looks like: doc/administration/index.md
+ ## The navigation.yaml equivalent is: ee/administration/
+ ## - A source doc entry without index.md looks like: doc/administration/appearance.md
+ ## The navigation.yaml equivalent is: ee/administration/appearance.html
+ ##
+ def check_for_missing_nav_entry(file)
+ file_sub = file["old_path"].gsub('doc', project_slug).gsub('index.md', '').gsub('.md', '.html')
+
+ result = navigation_file.include?(file_sub)
+ return unless result
+
+ warning(file)
+
+ abort
+ end
+
+ def warning(file)
+ warn <<~WARNING
+ #{COLOR_CODE_RED}✖ ERROR: Missing redirect for a deleted or moved page#{COLOR_CODE_RESET}
+
+ The following file is linked in the global navigation for docs.gitlab.com:
+
+ => #{file['old_path']}
+
+ Unless you add a redirect or remove the page from the global navigation,
+ this change will break pipelines in the 'gitlab/gitlab-docs' project.
+
+ #{rake_command(file)}
+
+ For more information, see:
+ - Create a redirect : https://docs.gitlab.com/ee/development/documentation/redirects.html
+ - Edit the global nav : https://docs.gitlab.com/ee/development/documentation/site_architecture/global_nav.html#add-a-navigation-entry
+ WARNING
+ end
+
+ # Rake task to use depending on the file being deleted or renamed
+ def rake_command(file)
+ # The Rake task is only available for gitlab-org/gitlab
+ return unless project_slug == 'ee'
+
+ if renamed_doc_file?(file)
+ rake = "bundle exec rake \"gitlab:docs:redirect[#{file['old_path']}, #{file['new_path']}]\""
+ msg = "It seems you renamed a page, run the following Rake task locally and commit the changes.\n"
+ elsif deleted_doc_file?(file)
+ rake = "bundle exec rake \"gitlab:docs:redirect[#{file['old_path']}, doc/new/path.md]\""
+ msg = "It seems you deleted a page. Run the following Rake task by replacing\n" \
+ "'doc/new/path.md' with the page to redirect to, and commit the changes.\n"
+ end
+
+ <<~MSG
+ #{msg}
+ #{rake}
+ MSG
+ end
+
+ # GitLab API URL
+ def gitlab_api_url
+ ENV.fetch('CI_API_V4_URL', 'https://gitlab.com/api/v4')
+ end
+
+ # Take the project path from the CI_PROJECT_PATH predefined variable.
+ def url_encoded_project_path
+ project_path = ENV.fetch('CI_PROJECT_PATH', nil)
+ return unless project_path
+
+ CGI.escape(project_path)
+ end
+
+ # Take the merge request ID from the CI_MERGE_REQUEST_IID predefined
+ # variable.
+ def merge_request_iid
+ ENV.fetch('CI_MERGE_REQUEST_IID', nil)
+ end
+
+ def abort_unless_merge_request_iid_exists
+ abort("Error: CI_MERGE_REQUEST_IID environment variable is missing") if merge_request_iid.nil?
+ end
+
+ # Skip if CI_PROJECT_PATH is not in the designated project paths
+ def project_supported?
+ PROJECT_PATHS.include? ENV['CI_PROJECT_PATH']
+ end
+
+ # Fetch the merge request diff JSON object
+ def merge_request_diff
+ @merge_request_diff ||= begin
+ uri = URI.parse(
+ "#{gitlab_api_url}/projects/#{url_encoded_project_path}/merge_requests/#{merge_request_iid}/diffs?per_page=30"
+ )
+ response = Net::HTTP.get_response(uri)
+
+ unless response.code == '200'
+ raise "API call to get MR diffs failed. Response code: #{response.code}. Response message: #{response.message}"
+ end
+
+ JSON.parse(response.body)
+ end
+ end
+
+ def renamed_doc_file?(file)
+ file['renamed_file'] == true && file['old_path'].start_with?('doc')
+ end
+
+ def deleted_doc_file?(file)
+ file['deleted_file'] == true && file['old_path'].start_with?('doc')
+ end
+
+ # Create a list of hashes of the renamed documentation files
+ def check_renamed_deleted_files
+ renamed_files = merge_request_diff.select do |file|
+ renamed_doc_file?(file)
+ end
+
+ deleted_files = merge_request_diff.select do |file|
+ deleted_doc_file?(file)
+ end
+
+ # Merge the two arrays
+ all_files = renamed_files + deleted_files
+
+ return if all_files.empty?
+
+ all_files.each do |file|
+ status = deleted_doc_file?(file) ? 'deleted' : 'renamed'
+ puts "Checking #{status} file..."
+ puts "=> Old_path: #{file['old_path']}"
+ puts "=> New_path: #{file['new_path']}"
+ puts
+
+ check_for_missing_nav_entry(file)
+ end
+ end
+end
+
+LintDocsRedirect.new.execute if $PROGRAM_NAME == __FILE__