integtest/spec/all_books_change_detection_spec.rb (930 lines of code) (raw):

# frozen_string_literal: true require_relative 'spec_helper' ## # Assertions about when books are rebuilt based on changes in source # repositories or the book's configuration. RSpec.describe 'building all books' do class Config attr_accessor :target_branch attr_accessor :checkout_branch attr_accessor :keep_hash def initialize(src, dest) @src = src @dest = dest @target_branch = nil @checkout_branch = nil @keep_hash = false @extra = proc {} end def convert_all conversion = @dest.prepare_convert_all @src.conf conversion.target_branch @target_branch if @target_branch conversion.keep_hash if @keep_hash @extra.call conversion conversion.convert end def extra @extra = proc end end describe 'change detection' do TWO_CHAPTERS = <<~ASCIIDOC = Title [[chapter1]] == Chapter 1 Chapter 1 text [[chapter2]] == Chapter 2 Some text. ASCIIDOC STACK_VERSIONS = 'shared/versions/stack/' ECE_VERSIONS = 'shared/versions/ece/' def self.build_twice( before_first_build:, before_second_build: ) convert_before do |src, dest| config = Config.new src, dest # Allow the caller to customize the source. before_first_build.call(src, config) # Convert the first time. This should build the docs. config.convert_all # Take some action between the builds. before_second_build.call(src, config) # Convert the second time. config.convert_all # Checkout the files so we can assert about them. checkout = config.checkout_branch || config.target_branch dest.checkout_conversion branch: checkout end end def self.build_one_book_out_of_one_repo_twice( before_first_build: ->(src, config) {}, before_second_build: ->(src, config) {} ) build_twice( before_first_build: lambda do |src, config| repo = src.repo_with_file 'repo', 'index.asciidoc', TWO_CHAPTERS book = src.book 'Test' book.source repo, 'index.asciidoc' # Allow the caller to customize the source before_first_build.call src, config end, before_second_build: before_second_build ) include_examples 'convert all basics' end def self.build_one_book_out_of_one_repo_and_then_out_of_two( before_second_build: ->(src, config) {} ) build_twice( before_first_build: lambda do |src, _config| repo = src.repo_with_file 'repo', 'index.asciidoc', TWO_CHAPTERS book = src.book 'Test' book.source repo, 'index.asciidoc' end, before_second_build: init_second_book_and_customize(before_second_build) ) include_examples 'convert all basics' end def self.init_second_book_and_customize(before_second_build) lambda do |src, config| repo2 = src.repo 'repo2' repo2.write 'garbage', 'junk' repo2.commit 'adding junk' src.book('Test').source repo2, 'garbage' before_second_build.call src, config end end def self.build_one_book_out_of_two_repos_twice( init: ->(src) { init_include src }, before_first_build: ->(src, config) {}, before_second_build: ->(src, config) {} ) build_twice( before_first_build: lambda do |src, config| init.call src # Allow the caller to customize the source before_first_build.call src, config end, before_second_build: lambda do |src, config| before_second_build.call src, config end ) include_examples 'convert all basics' end def self.init_include(src) repo1 = src.repo_with_file 'repo1', 'index.asciidoc', <<~ASCIIDOC #{TWO_CHAPTERS} Include between here include::../repo2/included.asciidoc[] and here. ASCIIDOC repo2 = src.repo_with_file 'repo2', 'included.asciidoc', 'included text' book = src.book 'Test' book.source repo1, 'index.asciidoc' book.source repo2, 'included.asciidoc' end def self.init_docs(src, included, body) include_ref = included.sub '{branch}', '{source_branch}' repo = src.repo_with_index 'repo', <<~ASCIIDOC include::{docs-root}/#{include_ref}[] #{body} ASCIIDOC docs_repo = src.repo 'docs' docs_repo.copy_shared_conf docs_repo.commit 'add shared conf' book = src.book 'Test' book.source repo, 'index.asciidoc' book.source docs_repo, included end def self.build_one_book_then_two_books( before_second_build: ->(src, config) {} ) build_twice( before_first_build: lambda do |src, _config| src.book_and_repo 'repo', 'Test', 'Some text.' end, before_second_build: lambda do |src, config| src.book('Test2').source src.repo('repo'), 'index.asciidoc' before_second_build.call src, config end ) include_examples 'build one book then two books' end shared_examples 'build one book then two books' do context 'the first build' do let(:out) { outputs[0] } include_examples 'commits changes' it 'does print that it is building the original book' do expect(out).to include('Test: Building master...') end it "doesn't print that it is building the new book" do # The new book doesn't exist at this point in the test expect(out).not_to include('Test2: Building master...') end end page_context 'html/test/current/chapter.html' end shared_examples 'toc and version drop down' do shared_examples 'correct' do context 'the version drop down' do let(:master_option) do <<~HTML.strip <option value="master"#{master_selected}>master</option> HTML end let(:foo_option) do <<~HTML.strip <option value="foo"#{foo_selected}>foo</option> HTML end it 'contains all versions' do expect(body).to include("#{master_option}#{foo_option}") end end context 'the toc' do def chapter(index) <<~HTML <li><span class="chapter"><a href="chapter#{index}.html">Chapter #{index}</a></span> </li> HTML end it 'contains all chapters' do expect(body).to include("#{chapter 1}#{chapter 2}") end end end shared_examples 'correct for branch' do |branch| page_context 'index.html', "html/test/#{branch}/index.html" do include_examples 'correct' end page_context 'toc.html', "html/test/#{branch}/toc.html" do include_examples 'correct' end page_context 'index.html', "raw/test/#{branch}/index.html" do include_examples 'correct' end page_context 'toc.html', "raw/test/#{branch}/toc.html" do include_examples 'correct' end end context 'the master branch' do let(:master_selected) { ' selected' } let(:foo_selected) { '' } include_examples 'correct for branch', 'master' end context 'the current branch' do let(:master_selected) { ' selected' } let(:foo_selected) { '' } include_examples 'correct for branch', 'current' end context 'the foo branch' do let(:master_selected) { '' } let(:foo_selected) { ' selected' } include_examples 'correct for branch', 'foo' end end shared_examples 'second build is noop' do context 'the second build' do let(:out) { outputs[1] } it "doesn't print that it is building any books" do expect(out).not_to include(': Building ') end include_examples "doesn't have anything to push" end end shared_examples "the second build doesn't have anything to push" do context 'the second build' do let(:out) { outputs[1] } include_examples "doesn't have anything to push" end end shared_examples "doesn't have anything to push" do it 'prints that it is not pushing anything' do expect(out).to include('No changes to push') end end shared_examples 'second build is not a noop' do context 'the second build' do let(:out) { outputs[1] } include_examples 'builds all books' end end shared_examples 'second build only changes chapter2' do page_context 'html/test/current/chapter2.html' do it 'includes the new text' do expect(body).to include('New text') end end context 'the sitemap' do context 'the second commit' do let(:commit_info) { @dest.commit_info_for_file('html/sitemap.xml') } # These assertions rely on the shape of `git show -- <file>` it 'updates the changed page' do expect(commit_info).to include(<<~XML) <loc>https://www.elastic.co/guide/test/current/chapter2.html</loc> XML end it "doesn't update the unchanged page" do expect(commit_info).not_to include(<<~XML) <loc>https://www.elastic.co/guide/test/current/chapter1.html</loc> XML end end end end context 'when building one book out of one repo twice' do context 'when the second build is a noop' do context 'because there are no changes to the source repo' do build_one_book_out_of_one_repo_twice include_examples 'second build is noop' end context 'even when there are no changes to the kibana repo' do build_one_book_out_of_one_repo_twice( before_first_build: lambda do |src, _config| # The kibana link checking requires a few things: # 1. A repo named kibana # 2. A special links file in the repo # 3. A book at `en/kibana` kibana_repo = src.repo_with_index 'kibana', 'words' # TODO: remove as part of https://github.com/elastic/docs/issues/2264, # and make "main" the default branch for all repos. kibana_repo.rename_branch 'main' kibana_repo.write( 'src/core/public/doc_links/doc_links_service.ts', 'text but no links actually' ) kibana_repo.commit 'add links file' kibana_book = src.book 'Kibana', prefix: 'en/kibana' kibana_book.source kibana_repo, 'index.asciidoc' # TODO: remove as part of https://github.com/elastic/docs/issues/2264 kibana_book.branches = [{ "main": 'master' }] kibana_book.live_branches = ['main'] kibana_book.current_branch = 'main' end ) include_examples 'second build is noop' end context 'even when there are unrelated changes source repo' do build_one_book_out_of_one_repo_twice( before_second_build: lambda do |src, _config| repo = src.repo 'repo' repo.write 'garbage', 'junk' repo.commit 'adding junk' end ) include_examples 'second build is noop' end context 'even when there are noop changes source repo' do build_one_book_out_of_one_repo_twice( before_second_build: lambda do |src, _config| repo = src.repo 'repo' repo.write 'index.asccidoc', TWO_CHAPTERS + ' ' repo.commit 'adding junk' end ) include_examples 'second build is noop' end context 'when --keep_hash is specified and there are related ' \ 'changes source repo' do build_one_book_out_of_one_repo_twice( before_second_build: lambda do |src, config| repo = src.repo 'repo' repo.write 'index.asciidoc', <<~ASCIIDOC = Title [[chapter]] == Chapter New text. ASCIIDOC repo.commit 'changed text' config.keep_hash = true end ) include_examples 'second build is noop' end context 'when --keep_hash is specified and there is a new branch' do build_one_book_out_of_one_repo_twice( before_second_build: lambda do |src, config| repo = src.repo 'repo' repo.switch_to_new_branch 'foo' book = src.book 'Test' book.branches.push 'foo' config.extra(&:keep_hash) end ) context 'the second build' do let(:out) { outputs[1] } it "doesn't print that it is building the first branch" do # The original book hasn't changed so we don't rebuild it expect(out).not_to include('Test: Building master...') end it "doesn't print that it is building the second branch" do expect(out).not_to include('Test: Building foo...') end it 'does print that it is pushing changes' do # This is because the TOC includes the new branch. That isn't # great but it isn't too bad. expect(out).to include('Pushing changes') end end end context 'when --keep_hash and --sub_dir are specified but there are ' \ 'unrelated changes' do build_one_book_out_of_one_repo_twice( before_second_build: lambda do |src, config| repo = src.repo 'repo' repo.write 'dummy', 'dummy' repo.commit 'dummy' config.extra do |conversion| conversion.keep_hash.sub_dir(repo, 'master') end end ) include_examples "the second build doesn't have anything to push" end context 'even when there is a new target branch' do # Since we fork the target_branch to master we won't have anything # to commit if the book doesn't change build_one_book_out_of_one_repo_twice( before_second_build: lambda do |_src, config| config.target_branch = 'new_target' config.checkout_branch = 'master' end ) include_examples 'second build is noop' end end context "when the second build isn't a noop" do context 'because the source repo changes' do build_one_book_out_of_one_repo_twice( before_second_build: lambda do |src, _config| repo = src.repo 'repo' repo.write 'index.asciidoc', <<~ASCIIDOC #{TWO_CHAPTERS} New text. ASCIIDOC repo.commit 'changed text' end ) include_examples 'second build is not a noop' include_examples 'second build only changes chapter2' end context 'because there is a target_branch and we have changes' do # We always fork the target_branch from master so if the target # branch contains any changes from master we rebuild them every time. build_one_book_out_of_one_repo_twice( before_first_build: lambda do |_src, config| config.target_branch = 'new_target' end ) include_examples 'second build is not a noop' context 'the first build' do let(:out) { outputs[0] } it 'logs that it is forking from master' do expect(out).to include('Forking <new_target> from master') end end context 'the second build' do let(:out) { outputs[1] } it 'logs that it is forking from master' do expect(out).to include('Forking <new_target> from master') end end end context 'because we remove the target_branch' do # Removing the target branch causes us to build into the *empty* # master branch. Being empty, there aren't any books in it to # consider "already built". build_one_book_out_of_one_repo_twice( before_first_build: lambda do |_src, config| config.target_branch = 'new_target' end, before_second_build: lambda do |_src, config| config.target_branch = nil # nil means don't override end ) include_examples 'second build is not a noop' end context 'because we add a new branch' do build_one_book_out_of_one_repo_twice( before_second_build: lambda do |src, _config| repo = src.repo 'repo' repo.switch_to_new_branch 'foo' book = src.book 'Test' book.branches.push 'foo' end ) context 'the second build' do let(:out) { outputs[1] } include_examples 'commits changes' end file_context 'html/branches.yaml' do it 'includes the original branch' do expect(contents).to include('Test/index.asciidoc/master') end it 'includes the added branch' do expect(contents).to include('Test/index.asciidoc/foo') end end include_examples 'toc and version drop down' let(:current) { 'master' } end context 'because we change the current branch' do build_one_book_out_of_one_repo_twice( before_first_build: lambda do |src, _config| repo = src.repo 'repo' repo.switch_to_new_branch 'foo' repo.write 'index.asciidoc', <<~ASCIIDOC = Title [[chapter]] == Chapter Different text. ASCIIDOC repo.commit 'change foo' book = src.book 'Test' book.branches.push 'foo' end, before_second_build: lambda do |src, _config| book = src.book 'Test' book.current_branch = 'foo' end ) context 'the second build' do let(:out) { outputs[1] } include_examples 'commits changes' end file_context 'html/branches.yaml' do it 'includes the original branch' do expect(contents).to include('Test/index.asciidoc/master') end it 'includes the added branch' do expect(contents).to include('Test/index.asciidoc/foo') end end # TODO: these are known to fail! # let(:current) { 'foo' } # include_examples 'toc and version drop down' # TODO: check that we wrote different text into the current book end context 'because we remove a branch from the book' do build_one_book_out_of_one_repo_twice( before_first_build: lambda do |src, _config| repo = src.repo 'repo' repo.switch_to_new_branch 'foo' repo.switch_to_new_branch 'bar' book = src.book 'Test' book.branches.push 'foo' book.branches.push 'bar' end, before_second_build: lambda do |src, _config| book = src.book 'Test' book.branches.delete 'bar' end ) context 'the second build' do let(:out) { outputs[1] } include_examples 'commits changes' end file_context 'html/branches.yaml' do it 'includes the original master branch' do expect(contents).to include('Test/index.asciidoc/master') end it 'includes the original extra branch' do expect(contents).to include('Test/index.asciidoc/foo') end it "doesn't include the removed branch" do expect(contents).not_to include('Test/index.asciidoc/bar') end end include_examples 'toc and version drop down' let(:current) { 'master' } end context 'because we add a branch to the book and specify ' \ '--keep_hash and --sub_dir' do build_one_book_out_of_one_repo_twice( before_second_build: lambda do |src, config| repo = src.repo 'repo' book = src.book 'Test' book.branches.push 'foo' config.extra do |conversion| conversion.keep_hash.sub_dir(repo, 'foo') end end ) context 'the second build' do let(:out) { outputs[1] } it 'builds the new branch' do expect(out).to include 'Test: Building foo...' end include_examples 'commits changes' end end context 'because we add a source to the book and specify ' \ '--keep_hash and --sub_dir' do build_one_book_out_of_one_repo_twice( before_second_build: lambda do |src, config| repo2 = src.repo 'repo2' repo2.write 'dummy', 'words' repo2.commit 'init' book = src.book 'Test' book.source repo2, 'not_used_actually' repo = src.repo 'repo' repo.switch_to_new_branch 'subbed' repo.write 'index.asciidoc', TWO_CHAPTERS + "\nmore words" repo.commit 'sub' config.extra do |conversion| conversion.keep_hash.sub_dir(repo, 'master') end end ) # The new branch is ignored because it wasn't used last time include_examples 'second build is not a noop' context 'the second build' do let(:out) { outputs[1] } it 'prints that it is skipping the new source' do expect(out).to include( 'Test: Skipping new repo repo2 for branch master.' ) end end end end end context 'when building one book out of one repo and then out of two' do context 'when the second build is a noop' do context 'because it was run with --keep_hash' do build_one_book_out_of_one_repo_and_then_out_of_two( before_second_build: lambda do |_src, config| config.keep_hash = true end ) include_examples 'second build is noop' end end context "when the second build isn't a noop" do context 'because it was run without any special flags' do build_one_book_out_of_one_repo_and_then_out_of_two include_examples 'second build is not a noop' end end end context 'when building one book out of two repos twice' do def self.add_branch(src) repo1 = src.repo 'repo1' repo1.switch_to_new_branch 'foo' repo2 = src.repo 'repo2' repo2.switch_to_new_branch 'foo' book = src.book 'Test' book.branches.push 'foo' end context 'when the second build is a noop' do context 'because there are no changes to the either repo' do build_one_book_out_of_two_repos_twice include_examples 'second build is noop' end context 'because there are unrelated changes to the index repo' do build_one_book_out_of_two_repos_twice( before_second_build: lambda do |src, _config| repo1 = src.repo 'repo1' repo1.write 'garbage', 'junk' repo1.commit 'adding junk' end ) include_examples 'second build is noop' end context 'because there are unrelated changes to the included repo' do build_one_book_out_of_two_repos_twice( before_second_build: lambda do |src, _config| repo2 = src.repo 'repo2' repo2.write 'garbage', 'junk' repo2.commit 'adding junk' end ) include_examples 'second build is noop' end context 'because there is an unrelated change in a mapped branch' do build_one_book_out_of_two_repos_twice( before_first_build: lambda do |src, _config| book = src.book 'Test' repo2 = src.repo 'repo2' book.source repo2, 'included.asciidoc', map_branches: { 'master': 'override' } repo2.switch_to_new_branch 'override' end, before_second_build: lambda do |src, _config| repo2 = src.repo 'repo2' repo2.write 'garbage', 'junk' repo2.commit 'adding junk' end ) include_examples 'second build is noop' end context 'because we add a new branch and specify --keep_hash ' \ 'and --sub_dir on the new branch with one repo' do build_one_book_out_of_two_repos_twice( before_second_build: lambda do |src, config| add_branch src config.extra do |conversion| conversion.keep_hash.sub_dir(src.repo('repo1'), 'foo') end end ) context 'the second build' do let(:out) { outputs[1] } include_examples 'commits changes' it "doesn't print that it is building any branch" do # The original book hasn't changed so we don't rebuild it expect(out).not_to include('Test: Building') end end end context "because the docs repo's attribute file doesn't change" do build_one_book_out_of_two_repos_twice( init: lambda do |src| init_docs src, 'shared/attributes.asciidoc', '{stack}' end ) include_examples 'second build is noop' end context 'even though there is an unrelated change to the docs repo' do build_one_book_out_of_two_repos_twice( init: lambda do |src| init_docs src, 'shared/attributes.asciidoc', '{stack}' end, before_second_build: lambda do |src, config| docs_repo = src.repo 'docs' docs_repo.write 'shared/foo.asciidoc', 'bar' docs_repo.commit 'changed' config.keep_hash = true end ) include_examples 'second build is noop' end # It is important that changes to the docs repo don't trigger a rebuild # when `--keep_hash` is specified or else every time we change this # file we'll rebuild all books in every PR build. That is a waste of # time and a potential source of spurious errors. context "because the docs repo's attributes file doesn't change but " \ 'the build has --keep_hash' do build_one_book_out_of_two_repos_twice( init: lambda do |src| init_docs src, 'shared/attributes.asciidoc', '{stack}' end, before_second_build: lambda do |src, config| docs_repo = src.repo 'docs' docs_repo.append 'shared/attributes.asciidoc', <<~ASCIIDOC :stack: Changed Stack ASCIIDOC docs_repo.commit 'changed' config.keep_hash = true end ) include_examples 'second build is noop' end end context "when the second build isn't a noop" do context 'because the index repo changes' do build_one_book_out_of_two_repos_twice( before_second_build: lambda do |src, _config| repo1 = src.repo 'repo1' text = repo1.read 'index.asciidoc' repo1.write 'index.asciidoc', text + 'New text' repo1.commit 'changed text' end ) include_examples 'second build is not a noop' include_examples 'second build only changes chapter2' end context 'because the included repo changes' do build_one_book_out_of_two_repos_twice( before_second_build: lambda do |src, _config| repo2 = src.repo 'repo2' repo2.write 'included.asciidoc', 'New text' repo2.commit 'changed text' end ) include_examples 'second build is not a noop' include_examples 'second build only changes chapter2' end context "because a repo's branch mapping changes" do build_one_book_out_of_two_repos_twice( before_second_build: lambda do |src, _config| book = src.book 'Test' repo2 = src.repo 'repo2' book.source repo2, 'included.asciidoc', map_branches: { 'master': 'override' } repo2.switch_to_new_branch 'override' end ) include_examples 'second build is not a noop' end context 'because there is a change in a mapped branch' do build_one_book_out_of_two_repos_twice( before_first_build: lambda do |src, _config| book = src.book 'Test' repo2 = src.repo 'repo2' book.source repo2, 'included.asciidoc', map_branches: { 'master': 'override' } repo2.switch_to_new_branch 'override' end, before_second_build: lambda do |src, _config| repo2 = src.repo 'repo2' repo2.write 'included.asciidoc', 'New text' repo2.commit 'changed text' end ) include_examples 'second build is not a noop' include_examples 'second build only changes chapter2' end context 'because we add a new branch' do build_one_book_out_of_two_repos_twice( before_second_build: lambda do |src, _config| add_branch src end ) context 'the second build' do let(:out) { outputs[1] } include_examples 'commits changes' it "doesn't print that it is building the original branch" do expect(out).not_to include('Test: Building master...') end end end context 'because we add a new branch and specify --keep_hash ' \ 'and --sub_dir on the new branch with both repos' do build_one_book_out_of_two_repos_twice( before_second_build: lambda do |src, config| add_branch src config.extra do |conversion| conversion.keep_hash .sub_dir(src.repo('repo1'), 'foo') .sub_dir(src.repo('repo2'), 'foo') end end ) context 'the second build' do let(:out) { outputs[1] } include_examples 'commits changes' it "doesn't print that it is building the original branch" do expect(out).not_to include('Test: Building master...') end it 'prints that is buildin the new branch' do expect(out).to include('Test: Building foo...') end end end context "because the docs repo's attribute file changes" do build_one_book_out_of_two_repos_twice( init: lambda do |src| init_docs src, 'shared/attributes.asciidoc', '{stack}' end, before_second_build: lambda do |src, _config| docs_repo = src.repo 'docs' docs_repo.append 'shared/attributes.asciidoc', <<~ASCIIDOC :stack: Changed Stack ASCIIDOC docs_repo.commit 'changed' end ) include_examples 'second build is not a noop' end context "because the docs repo's stack version file " \ 'for master changes' do build_one_book_out_of_two_repos_twice( init: lambda do |src| init_docs src, "#{STACK_VERSIONS}/{branch}.asciidoc", '{version}' end, before_second_build: lambda do |src, _config| docs_repo = src.repo 'docs' docs_repo.append "#{STACK_VERSIONS}/master.asciidoc", <<~ASCIIDOC :version: pig ASCIIDOC docs_repo.commit 'changed' end ) include_examples 'second build is not a noop' end context "because the docs repo's current stack version file changes" do build_one_book_out_of_two_repos_twice( init: lambda do |src| init_docs src, "#{STACK_VERSIONS}/current.asciidoc", '{version}' end, before_second_build: lambda do |src, _config| docs_repo = src.repo 'docs' docs_repo.write "#{STACK_VERSIONS}/current.asciidoc", <<~ASCIIDOC include::master.asciidoc[] ASCIIDOC docs_repo.commit 'changed' end ) include_examples 'second build is not a noop' end context "because the file referenced by the docs repo's current " \ 'stack version file changes' do build_one_book_out_of_two_repos_twice( init: lambda do |src| path = "#{STACK_VERSIONS}/current.asciidoc" init_docs src, path, '{version}' docs_repo = src.repo 'docs' docs_repo.write path, 'include::master.asciidoc[]' docs_repo.commit 'use master' end, before_second_build: lambda do |src, _config| docs_repo = src.repo 'docs' docs_repo.append "#{STACK_VERSIONS}/master.asciidoc", <<~ASCIIDOC :version: cow ASCIIDOC docs_repo.commit 'changed' end ) include_examples 'second build is not a noop' end context "because the docs repo's ece version file " \ 'for master changes' do build_one_book_out_of_two_repos_twice( init: lambda do |src| init_docs src, "#{ECE_VERSIONS}/{branch}.asciidoc", '{ece-version}' end, before_second_build: lambda do |src, _config| docs_repo = src.repo 'docs' docs_repo.append "#{ECE_VERSIONS}/master.asciidoc", <<~ASCIIDOC :ece-version: pig ASCIIDOC docs_repo.commit 'changed' end ) include_examples 'second build is not a noop' end context "because the docs repo's current ece version file changes" do build_one_book_out_of_two_repos_twice( init: lambda do |src| init_docs src, "#{ECE_VERSIONS}/current.asciidoc", '{ece-version}' end, before_second_build: lambda do |src, _config| docs_repo = src.repo 'docs' docs_repo.write "#{ECE_VERSIONS}/current.asciidoc", <<~ASCIIDOC include::master.asciidoc[] ASCIIDOC docs_repo.commit 'changed' end ) include_examples 'second build is not a noop' end context "because the file referenced by the docs repo's current " \ 'ece version file changes' do build_one_book_out_of_two_repos_twice( init: lambda do |src| path = "#{ECE_VERSIONS}/current.asciidoc" init_docs src, path, '{ece-version}' docs_repo = src.repo 'docs' docs_repo.write path, 'include::master.asciidoc[]' docs_repo.commit 'use master' end, before_second_build: lambda do |src, _config| docs_repo = src.repo 'docs' docs_repo.append "#{ECE_VERSIONS}/master.asciidoc", <<~ASCIIDOC :ece-version: cow ASCIIDOC docs_repo.commit 'changed' end ) include_examples 'second build is not a noop' end end end context 'when building one book and then building two books' do context 'without any special flags' do build_one_book_then_two_books context 'the second build' do let(:out) { outputs[1] } include_examples 'commits changes' it "doesn't print that it is building the original book" do # The original book hasn't changed so we don't rebuild it expect(out).not_to include('Test: Building master...') end it 'does print that it is building the new book' do expect(out).to include('Test2: Building master...') end end page_context 'html/test2/current/chapter.html' end context 'when --keep_hash is specified' do build_one_book_then_two_books( before_second_build: lambda do |_src, config| config.keep_hash = true end ) context 'the second build' do let(:out) { outputs[1] } it "doesn't print that it is building the original book" do # The original book hasn't changed so we don't rebuild it expect(out).not_to include('Test: Building master...') end it "doesn't print that it is building the new book" do expect(out).not_to include('Test2: Building master...') end it 'does print that it is pushing changes' do # This is because the TOC includes the new book. That isn't great # but it is fine. expect(out).to include('Pushing changes') end end end end end end