diff --git a/.gitlab/ci/docs.gitlab-ci.yml b/.gitlab/ci/docs.gitlab-ci.yml index 8745e7d8e9e5170da8fab7a1c291e217b8062136..62546e593682c3878f258cad41eb7bb7369ca523 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 2ea26985fcf77d0cc19c0ff9085575fa38b12432..71d8a8fc7f94d6f06d505d7cc683ea72bd03b546 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 9f0df21e7f184de5f478cb59a41712d101a1a26e..7cca2f3e30b1104d972fded8b19e52a70a162da9 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 2957dde6fc01cd2fbb477800c0dc3676f102db31..0000000000000000000000000000000000000000 --- 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