Example #1
0
    def test_it_returns_error_code_when_rvm_install_fails(
            self, mock_get_logger, mock_run, patch_clone_dir):
        version = '2.3'

        mock_run.return_value = 1

        create_file(patch_clone_dir / RUBY_VERSION, version)

        result = setup_ruby()

        assert result == 1

        mock_get_logger.assert_called_once_with('setup-ruby')

        mock_logger = mock_get_logger.return_value

        mock_logger.info.assert_has_calls([
            call('Using ruby version in .ruby-version'),
        ])

        mock_run.assert_called_once_with(mock_logger,
                                         'rvm install 2.3',
                                         cwd=patch_clone_dir,
                                         env={},
                                         ruby=True)
Example #2
0
    def test_it_uses_ruby_version_if_it_exists(self, mock_get_logger, mock_run,
                                               patch_clone_dir):
        version = '2.3'

        create_file(patch_clone_dir / RUBY_VERSION, version)

        mock_run.return_value = 0

        result = setup_ruby()

        assert result == 0

        mock_get_logger.assert_called_once_with('setup-ruby')

        mock_logger = mock_get_logger.return_value

        def callp(cmd):
            return call(mock_logger,
                        cmd,
                        cwd=patch_clone_dir,
                        env={},
                        ruby=True)

        mock_run.assert_has_calls([
            callp(f'rvm install {version}'),
            callp('echo Ruby version: $(ruby -v)')
        ])
Example #3
0
    def test_it_strips_and_quotes_ruby_version(self, mock_get_logger, mock_run,
                                               patch_clone_dir):
        version = '  $2.3  '

        create_file(patch_clone_dir / RUBY_VERSION, version)

        mock_run.return_value = 0

        result = setup_ruby()

        assert result == 0

        mock_get_logger.assert_called_once_with('setup-ruby')

        mock_logger = mock_get_logger.return_value

        def callp(cmd):
            return call(mock_logger,
                        cmd,
                        cwd=patch_clone_dir,
                        env={},
                        ruby=True)

        mock_logger.info.assert_has_calls([
            call('Using ruby version in .ruby-version'),
        ])

        mock_run.assert_has_calls([
            callp("rvm install '$2.3'"),
            callp('echo Ruby version: $(ruby -v)'),
        ])
Example #4
0
    def test_no_ruby_version_file(self, mock_get_logger, mock_run,
                                  patch_clone_dir):
        result = setup_ruby()

        assert result == mock_run.return_value

        mock_get_logger.assert_called_once_with('setup-ruby')

        mock_logger = mock_get_logger.return_value

        mock_run.assert_called_once_with(mock_logger,
                                         'echo Ruby version: $(ruby -v)',
                                         cwd=patch_clone_dir,
                                         env={},
                                         ruby=True)
Example #5
0
def build(aws_access_key_id,
          aws_default_region,
          aws_secret_access_key,
          federalist_builder_callback,
          status_callback,
          baseurl,
          branch,
          bucket,
          build_id,
          config,
          generator,
          github_token,
          owner,
          repository,
          site_prefix,
          user_environment_variables=[]):
    '''
    Main task to run a full site build process.

    All values needed for the build are loaded from
    environment variables.
    '''
    # keep track of total time
    start_time = datetime.now()

    # Make the working directory if it doesn't exist
    WORKING_DIR_PATH.mkdir(exist_ok=True)

    logger = None

    cache_control = os.getenv('CACHE_CONTROL', 'max-age=60')
    database_url = os.environ['DATABASE_URL']
    user_environment_variable_key = os.environ['USER_ENVIRONMENT_VARIABLE_KEY']

    try:
        post_build_processing(status_callback)
        # throw a timeout exception after TIMEOUT_SECONDS
        with Timeout(TIMEOUT_SECONDS, swallow_exc=False):
            build_info = f'{owner}/{repository}@id:{build_id}'

            decrypted_uevs = decrypt_uevs(user_environment_variable_key,
                                          user_environment_variables)

            priv_vals = [uev['value'] for uev in decrypted_uevs]
            priv_vals.append(aws_access_key_id)
            priv_vals.append(aws_secret_access_key)
            if github_token:
                priv_vals.append(github_token)

            logattrs = {
                'branch': branch,
                'buildid': build_id,
                'owner': owner,
                'repository': repository,
            }

            init_logging(priv_vals, logattrs, database_url)

            logger = get_logger('main')

            def run_step(returncode, msg):
                if returncode != 0:
                    raise StepException(msg)

            logger.info(f'Running build for {owner}/{repository}/{branch}')

            if generator not in GENERATORS:
                raise ValueError(f'Invalid generator: {generator}')

            ##
            # FETCH
            #
            run_step(
                fetch_repo(owner, repository, branch, github_token),
                'There was a problem fetching the repository, see the above logs for details.'
            )

            ##
            # BUILD
            #
            run_step(
                setup_node(),
                'There was a problem setting up Node, see the above logs for details.'
            )

            # Run the npm `federalist` task (if it is defined)
            run_step(
                run_federalist_script(branch, owner, repository, site_prefix,
                                      baseurl, decrypted_uevs),
                'There was a problem running the federalist script, see the above logs for details.'
            )

            # Run the appropriate build engine based on generator
            if generator == 'jekyll':
                run_step(
                    setup_ruby(),
                    'There was a problem setting up Ruby, see the above logs for details.'
                )

                run_step(
                    setup_bundler(),
                    'There was a problem setting up Bundler, see the above logs for details.'
                )

                run_step(
                    build_jekyll(branch, owner, repository, site_prefix,
                                 baseurl, config, decrypted_uevs),
                    'There was a problem running Jekyll, see the above logs for details.'
                )

            elif generator == 'hugo':
                # extra: --hugo-version (not yet used)
                run_step(
                    download_hugo(),
                    'There was a problem downloading Hugo, see the above logs for details.'
                )

                run_step(
                    build_hugo(branch, owner, repository, site_prefix, baseurl,
                               decrypted_uevs),
                    'There was a problem running Hugo, see the above logs for details.'
                )

            elif generator == 'static':
                # no build arguments are needed
                build_static()

            elif (generator == 'node.js' or generator == 'script only'):
                logger.info('build already ran in \'npm run federalist\'')

            else:
                raise ValueError(f'Invalid generator: {generator}')

            ##
            # PUBLISH
            #
            publish(baseurl, site_prefix, bucket, cache_control,
                    aws_default_region, aws_access_key_id,
                    aws_secret_access_key)

            delta_string = delta_to_mins_secs(datetime.now() - start_time)
            logger.info(f'Total build time: {delta_string}')

            # Finished!
            post_build_complete(status_callback, federalist_builder_callback)

            sys.exit(0)

    except StepException as err:
        '''
        Thrown when a step itself fails, usually because a command exited
        with a non-zero return code
        '''
        logger.error(str(err))
        post_build_error(status_callback, federalist_builder_callback,
                         str(err))
        sys.exit(1)

    except TimeoutException:
        logger.warning(f'Build({build_info}) has timed out')
        post_build_timeout(status_callback, federalist_builder_callback)

    except Exception as err:  # pylint: disable=W0703
        # Getting here means something really weird has happened
        # since all errors caught during tasks should be caught
        # in the previous block as `UnexpectedExit` exceptions.
        err_string = str(err)

        # log the original exception
        msg = f'Unexpected exception raised during build({build_info}): {err_string}'
        if logger:
            logger.warning(msg)
        else:
            print(msg)

        err_message = (f'Unexpected build({build_info}) error. Please try '
                       'again and contact federalist-support if it persists.')

        post_build_error(status_callback, federalist_builder_callback,
                         err_message)