From 5bcbd38171bff8932b0588bd28bb02ad3778bf9a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9my=20Coutable?= <remy@rymai.me>
Date: Thu, 16 Jul 2020 15:34:13 +0200
Subject: [PATCH] Consolidate `trigger-build-docs` into `trigger-build`
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This consolidates `trigger-build-docs` into `trigger-build` and make
the `review-docs-deploy` job wait for the downstream `gitlab-docs`
pipeline before finishing.

It was reported in Slack that the "Review "View App" button for the
docs Review App was shown even though the Review App wasn't actually
available.

That was because after triggering the downstream pipeline, we didn't
wait for it to be finished before the `review-docs-deploy` job.

Signed-off-by: Rémy Coutable <remy@rymai.me>
---
 .gitlab/ci/docs.gitlab-ci.yml          |   4 +-
 doc/development/documentation/index.md |   4 +-
 scripts/trigger-build                  | 146 +++++++++++++++++++++----
 scripts/trigger-build-docs             | 136 -----------------------
 4 files changed, 129 insertions(+), 161 deletions(-)
 delete mode 100755 scripts/trigger-build-docs

diff --git a/.gitlab/ci/docs.gitlab-ci.yml b/.gitlab/ci/docs.gitlab-ci.yml
index 8745e7d8e9e51..62546e593682c 100644
--- a/.gitlab/ci/docs.gitlab-ci.yml
+++ b/.gitlab/ci/docs.gitlab-ci.yml
@@ -27,7 +27,7 @@
 review-docs-deploy:
   extends: .review-docs
   script:
-    - ./scripts/trigger-build-docs deploy
+    - ./scripts/trigger-build docs deploy
 
 # Cleanup remote environment of gitlab-docs
 review-docs-cleanup:
@@ -36,7 +36,7 @@ review-docs-cleanup:
     name: review-docs/$DOCS_GITLAB_REPO_SUFFIX-$CI_MERGE_REQUEST_IID
     action: stop
   script:
-    - ./scripts/trigger-build-docs cleanup
+    - ./scripts/trigger-build docs cleanup
 
 docs lint:
   extends:
diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md
index 2ea26985fcf77..71d8a8fc7f94d 100644
--- a/doc/development/documentation/index.md
+++ b/doc/development/documentation/index.md
@@ -445,8 +445,8 @@ In case the review app URL returns 404, follow these steps to debug:
 If you want to know the in-depth details, here's what's really happening:
 
 1. You manually run the `review-docs-deploy` job in a merge request.
-1. The job runs the [`scripts/trigger-build-docs`](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/trigger-build-docs)
-   script with the `deploy` flag, which in turn:
+1. The job runs the [`scripts/trigger-build`](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/trigger-build)
+   script with the `docs deploy` flag, which in turn:
    1. Takes your branch name and applies the following:
       - The `docs-preview-` prefix is added.
       - The product slug is used to know the project the review app originated
diff --git a/scripts/trigger-build b/scripts/trigger-build
index 9f0df21e7f184..7cca2f3e30b11 100755
--- a/scripts/trigger-build
+++ b/scripts/trigger-build
@@ -29,10 +29,17 @@ module Trigger
   end
 
   class Base
-    def invoke!(post_comment: false, downstream_job_name: nil)
+    # Can be overridden
+    def self.access_token
+      ENV['GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN']
+    end
+
+    def initialize
       # gitlab-bot's token "GitLab multi-project pipeline polling"
-      Gitlab.private_token = access_token
+      Gitlab.private_token = self.class.access_token
+    end
 
+    def invoke!(post_comment: false, downstream_job_name: nil)
       pipeline_variables = variables
 
       puts "Triggering downstream pipeline on #{downstream_project_path}"
@@ -74,14 +81,9 @@ module Trigger
       raise NotImplementedError
     end
 
-    # Must be overridden
+    # Can be overridden
     def trigger_token
-      raise NotImplementedError
-    end
-
-    # Must be overridden
-    def access_token
-      raise NotImplementedError
+      ENV['CI_JOB_TOKEN']
     end
 
     # Can be overridden
@@ -133,14 +135,6 @@ module Trigger
       ENV['OMNIBUS_BRANCH'] || 'master'
     end
 
-    def trigger_token
-      ENV['CI_JOB_TOKEN']
-    end
-
-    def access_token
-      ENV['GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN']
-    end
-
     def extra_variables
       # Use CI_MERGE_REQUEST_SOURCE_BRANCH_SHA for omnibus checkouts due to pipeline for merged results
       # and fallback to CI_COMMIT_SHA for the `detached` pipelines.
@@ -176,10 +170,6 @@ module Trigger
       ENV['BUILD_TRIGGER_TOKEN']
     end
 
-    def access_token
-      ENV['GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN']
-    end
-
     def extra_variables
       edition = Trigger.ee? ? 'EE' : 'CE'
 
@@ -205,6 +195,108 @@ module Trigger
     end
   end
 
+  class Docs < Base
+    SUCCESS_MESSAGE = <<~MSG
+    => You should now be able to preview your changes under the following URL:
+
+    %<app_url>s
+
+    => For more information, see the documentation
+    => https://docs.gitlab.com/ee/development/documentation/index.html#previewing-the-changes-live
+
+    => If something doesn't work, drop a line in the #docs chat channel.
+    MSG
+
+    # Create a remote branch in gitlab-docs and immediately cancel the pipeline
+    # to avoid race conditions, since a triggered pipeline will also run right
+    # after the branch creation. This only happens the very first time a branch
+    # is created and will be skipped in subsequent runs. Read more in
+    # https://gitlab.com/gitlab-org/gitlab-docs/issues/154.
+    #
+    def deploy!
+      create_remote_branch!
+      cancel_latest_pipeline!
+      invoke!.wait!
+      display_success_message
+    end
+
+    #
+    # Remove a remote branch in gitlab-docs.
+    #
+    def cleanup!
+      Gitlab.delete_branch(downstream_project_path, ref)
+      puts "=> Remote branch '#{downstream_project_path}' deleted"
+    end
+
+    private
+
+    def downstream_project_path
+      ENV['DOCS_PROJECT_PATH'] || 'gitlab-org/gitlab-docs'
+    end
+
+    def ref
+      if ENV['CI_MERGE_REQUEST_IID'].nil?
+        "docs-preview-#{slug}-#{ENV['CI_COMMIT_REF_SLUG']}"
+      else
+        "docs-preview-#{slug}-#{ENV['CI_MERGE_REQUEST_IID']}"
+      end
+    end
+
+    def extra_variables
+      {
+        "BRANCH_#{slug.upcase}" => ENV['CI_COMMIT_REF_NAME']
+      }
+    end
+
+    def slug
+      case ENV['CI_PROJECT_PATH']
+      when 'gitlab-org/gitlab-foss'
+        'ce'
+      when 'gitlab-org/gitlab'
+        'ee'
+      when 'gitlab-org/gitlab-runner'
+        'runner'
+      when 'gitlab-org/omnibus-gitlab'
+        'omnibus'
+      when 'gitlab-org/charts/gitlab'
+        'charts'
+      end
+    end
+
+    def app_url
+      "http://#{ref}.#{ENV['DOCS_REVIEW_APPS_DOMAIN']}/#{slug}"
+    end
+
+    def create_remote_branch!
+      Gitlab.create_branch(downstream_project_path, ref, 'master')
+      puts "=> Remote branch '#{ref}' created"
+    end
+
+    def cancel_latest_pipeline!
+      pipelines = nil
+
+      # Wait until the pipeline is started
+      loop do
+        sleep 1
+        puts "=> Waiting for pipeline to start..."
+        pipelines = Gitlab.pipelines(downstream_project_path, { ref: ref })
+        break if pipelines.any?
+      end
+
+      # Get the first pipeline ID which should be the only one for the branch
+      pipeline_id = pipelines.first.id
+
+      # Cancel the pipeline
+      Gitlab.cancel_pipeline(downstream_project_path, pipeline_id)
+    rescue Gitlab::Error::BadRequest
+      puts "=> Remote branch '#{ref}' already exists!"
+    end
+
+    def display_success_message
+      format(SUCCESS_MESSAGE, app_url: app_url)
+    end
+  end
+
   class CommitComment
     def self.post!(downstream_pipeline)
       Gitlab.create_commit_comment(
@@ -282,6 +374,18 @@ when 'omnibus'
   Trigger::Omnibus.new.invoke!(post_comment: true, downstream_job_name: 'Trigger:qa-test').wait!
 when 'cng'
   Trigger::CNG.new.invoke!.wait!
+when 'docs'
+  docs_trigger = Trigger::Docs.new
+
+  case ARGV[1]
+  when 'deploy'
+    docs_trigger.deploy!
+  when 'cleanup'
+    docs_trigger.cleanup!
+  else
+    puts 'usage: trigger-build docs <deploy|cleanup>'
+    exit 1
+  end
 else
   puts "Please provide a valid option:
   omnibus - Triggers a pipeline that builds the omnibus-gitlab package
diff --git a/scripts/trigger-build-docs b/scripts/trigger-build-docs
deleted file mode 100755
index 2957dde6fc01c..0000000000000
--- a/scripts/trigger-build-docs
+++ /dev/null
@@ -1,136 +0,0 @@
-#!/usr/bin/env ruby
-
-require 'gitlab'
-
-#
-# Configure credentials to be used with gitlab gem
-#
-Gitlab.configure do |config|
-  config.endpoint      = 'https://gitlab.com/api/v4'
-  config.private_token = ENV["DOCS_API_TOKEN"] # GitLab Docs bot access token with Developer access to gitlab-docs
-end
-
-#
-# The remote docs project
-#
-GITLAB_DOCS_REPO = 'gitlab-org/gitlab-docs'.freeze
-
-#
-# This is the branch that will be created in the gitlab-docs project.
-# Name it after the product we're previewing and the ID of the MR that
-# kicked the review app.
-#
-def docs_branch
-  # Check if CI_MERGE_REQUEST_IID is present. This requires pipelines
-  # for merge requests to be enabled.
-  if ENV["CI_MERGE_REQUEST_IID"].nil?
-    "docs-preview-#{slug}-#{ENV["CI_COMMIT_REF_SLUG"]}"
-  else
-    "docs-preview-#{slug}-#{ENV["CI_MERGE_REQUEST_IID"]}"
-  end
-end
-
-#
-# Create a remote branch in gitlab-docs and immediately cancel the pipeline
-# to avoid race conditions, since a triggered pipeline will also run right
-# after the branch creation. This only happens the very first time a branch
-# is created and will be skipped in subsequent runs. Read more in
-# https://gitlab.com/gitlab-org/gitlab-docs/issues/154.
-#
-def create_remote_branch
-  Gitlab.create_branch(GITLAB_DOCS_REPO, docs_branch, 'master')
-  puts "=> Remote branch '#{docs_branch}' created"
-
-  pipelines = nil
-
-  # Wait until the pipeline is started
-  loop do
-    sleep 1
-    puts "=> Waiting for pipeline to start..."
-    pipelines = Gitlab.pipelines(GITLAB_DOCS_REPO, { ref: docs_branch })
-    break if pipelines.any?
-  end
-
-  # Get the first pipeline ID which should be the only one for the branch
-  pipeline_id = pipelines.first.id
-
-  # Cancel the pipeline
-  Gitlab.cancel_pipeline(GITLAB_DOCS_REPO, pipeline_id)
-rescue Gitlab::Error::BadRequest
-  puts "=> Remote branch '#{docs_branch}' already exists"
-end
-
-#
-# Remove a remote branch in gitlab-docs
-#
-def remove_remote_branch
-  Gitlab.delete_branch(GITLAB_DOCS_REPO, docs_branch)
-  puts "=> Remote branch '#{docs_branch}' deleted"
-end
-
-#
-# Define suffix in review app URL based on project
-#
-def slug
-  case ENV["CI_PROJECT_PATH"]
-  when 'gitlab-org/gitlab-foss'
-    'ce'
-  when 'gitlab-org/gitlab'
-    'ee'
-  when 'gitlab-org/gitlab-runner'
-    'runner'
-  when 'gitlab-org/omnibus-gitlab'
-    'omnibus'
-  when 'gitlab-org/charts/gitlab'
-    'charts'
-  end
-end
-
-#
-# Overriding vars in https://gitlab.com/gitlab-org/gitlab-docs/blob/master/.gitlab-ci.yml
-#
-def param_name
-  "BRANCH_#{slug.upcase}"
-end
-
-#
-# Trigger a pipeline in gitlab-docs
-#
-def trigger_pipeline
-  # The review app URL
-  app_url = "http://#{docs_branch}.#{ENV["DOCS_REVIEW_APPS_DOMAIN"]}/#{slug}"
-
-  # Create the cross project pipeline using CI_JOB_TOKEN
-  pipeline = Gitlab.run_trigger(GITLAB_DOCS_REPO, ENV["CI_JOB_TOKEN"], docs_branch, { param_name => ENV["CI_COMMIT_REF_NAME"] })
-
-  puts "=> Follow the status of the triggered pipeline:"
-  puts ""
-  puts pipeline.web_url
-  puts ""
-  puts "=> In a few minutes, you will be able to preview your changes under the following URL:"
-  puts ""
-  puts app_url
-  puts ""
-  puts "=> For more information, see the documentation"
-  puts "=> https://docs.gitlab.com/ee/development/documentation/index.html#previewing-the-changes-live"
-  puts ""
-  puts "=> If something doesn't work, drop a line in the #docs chat channel."
-  puts ""
-end
-
-#
-# When the first argument is deploy then create the branch and trigger pipeline
-# When it is 'stop', it deleted the remote branch. That way, we ensure there
-# are no stale remote branches and the Review server doesn't fill.
-#
-case ARGV[0]
-when 'deploy'
-  create_remote_branch
-  trigger_pipeline
-when 'cleanup'
-  remove_remote_branch
-else
-  puts "Please provide a valid option:
-  deploy  - Creates the remote branch and triggers a pipeline
-  cleanup - Deletes the remote branch and stops the Review App"
-end
-- 
GitLab