Exemplo n.º 1
0
    def send_notifications(self, context):
        exit_code = context['exit_code']
        template = 'test_success' if exit_code == 0 else 'test_failure'
        html = render_template('mail/' + template + '.html', **context)
        html = sanitize_sensitive_data(html)

        # Save log html
        log_dir = os.path.join(current_app.config['BADWOLF_LOG_DIR'],
                               self.commit_hash)
        if not os.path.exists(log_dir):
            os.makedirs(log_dir)
        log_file = os.path.join(log_dir, 'build.html')
        with open(log_file, 'wb') as f:
            f.write(to_binary(html))

        if exit_code == 0:
            subject = 'Test succeed for repository {}'.format(
                self.repo_full_name)
        else:
            subject = 'Test failed for repository {}'.format(
                self.repo_full_name)
        notification = self.spec.notification
        emails = notification['emails']
        if emails:
            send_mail(emails, subject, html)

        slack_webhooks = notification['slack_webhooks']
        if slack_webhooks:
            message = render_template('slack_webhook/' + template + '.md',
                                      **context)
            trigger_slack_webhook(slack_webhooks, message)
Exemplo n.º 2
0
    def send_notifications(self, context):
        exit_code = context['exit_code']
        template = 'test_success' if exit_code == 0 else 'test_failure'
        html = render_template('mail/' + template + '.html', **context)
        html = sanitize_sensitive_data(html)

        # Save log html
        log_dir = os.path.join(current_app.config['BADWOLF_LOG_DIR'],
                               self.commit_hash, self.context.task_id)
        os.makedirs(log_dir, exist_ok=True)
        log_file = os.path.join(log_dir, 'build.html')
        with open(log_file, 'wb') as f:
            f.write(to_binary(html))

        if exit_code == 137:
            logger.info('Build cancelled, will not sending notification')
            return

        test_status = 'succeed' if exit_code == 0 else 'failed'
        subject = 'Test {} for repository {}'.format(test_status,
                                                     self.context.repository)
        notification = self.spec.notification
        email = notification.email
        should_send_mail = email and email.recipients and (
            (exit_code == 0 and email.on_success == 'always') or
            (exit_code != 0 and email.on_failure == 'always'))
        if should_send_mail:
            send_mail(email.recipients, subject, html)

        slack_webhook = notification.slack_webhook
        if slack_webhook and slack_webhook.webhooks:
            if exit_code == 0 and slack_webhook.on_success == 'always':
                trigger_slack_webhook(slack_webhook.webhooks, context)
            if exit_code != 0 and slack_webhook.on_failure == 'always':
                trigger_slack_webhook(slack_webhook.webhooks, context)
Exemplo n.º 3
0
    def shell_script(self):
        def _trace(command):
            return 'echo + {}\n{} '.format(shlex.quote(command), command)

        commands = []
        after_success = [_trace(cmd) for cmd in self.after_success]
        after_failure = [_trace(cmd) for cmd in self.after_failure]
        for service in self.services:
            commands.append(_trace('service {} start'.format(service)))
        for script in self.scripts:
            commands.append(_trace(script))

        command_encoded = shlex.quote(
            to_text(base64.b64encode(to_binary('\n'.join(commands)))))
        context = {
            'command': command_encoded,
            'after_success': '    \n'.join(after_success),
            'after_failure': '    \n'.join(after_failure),
        }
        script = render_template('script.sh', **context)
        logger.debug('Build script: \n%s', script)
        return script
Exemplo n.º 4
0
    def run_in_container(self, docker_image_name):
        environment = {}
        if self.spec.environments:
            # TODO: Support run in multiple environments
            environment = self.spec.environments[0]

        # TODO: Add more test context related env vars
        script = shlex.quote(
            to_text(base64.b64encode(to_binary(self.spec.shell_script))))
        environment.update({
            'DEBIAN_FRONTEND': 'noninteractive',
            'HOME': '/root',
            'SHELL': '/bin/sh',
            'CI': 'true',
            'CI_NAME': 'badwolf',
            'BADWOLF_COMMIT': self.commit_hash,
            'BADWOLF_BUILD_DIR': self.context.clone_path,
            'BADWOLF_REPO_SLUG': self.context.repository,
            'BADWOLF_SCRIPT': script,
        })
        environment.setdefault('TERM', 'xterm-256color')
        branch = self.context.source['branch']
        labels = {
            'repo': self.context.repository,
            'commit': self.commit_hash,
            'task_id': self.context.task_id,
        }
        if self.context.type == 'tag':
            environment['BADWOLF_TAG'] = branch['name']
            labels['tag'] = branch['name']
        else:
            environment['BADWOLF_BRANCH'] = branch['name']
            labels['branch'] = branch['name']
        if self.context.pr_id:
            environment['BADWOLF_PULL_REQUEST'] = str(self.context.pr_id)
            labels['pull_request'] = str(self.context.pr_id)

        volumes = {
            self.context.clone_path: {
                'bind': self.context.clone_path,
                'mode': 'rw',
            },
        }
        if self.spec.docker:
            volumes['/var/run/docker.sock'] = {
                'bind': '/var/run/docker.sock',
                'mode': 'ro',
            }
            environment.setdefault('DOCKER_HOST',
                                   'unix:///var/run/docker.sock')
        self._populate_more_envvars(environment)
        logger.debug('Docker container environment: \n %r', environment)
        container = self.docker.containers.create(
            docker_image_name,
            entrypoint=['/bin/sh', '-c'],
            command=['echo $BADWOLF_SCRIPT | base64 --decode | /bin/sh'],
            environment=environment,
            working_dir=self.context.clone_path,
            volumes=volumes,
            privileged=self.spec.privileged,
            stdin_open=False,
            tty=True,
            labels=labels,
        )
        container_id = container.id
        logger.info('Created container %s from image %s', container_id,
                    docker_image_name)

        output = []
        try:
            container.start()
            self.update_build_status('INPROGRESS',
                                     'Running tests in Docker container')
            exit_code = container.wait(
                timeout=current_app.config['DOCKER_RUN_TIMEOUT'])
        except (APIError, DockerException, ReadTimeout) as e:
            exit_code = -1
            output.append(str(e) + '\n')
            logger.exception('Docker error')
        finally:
            try:
                output.append(to_text(container.logs()))
                container.remove(force=True)
            except NotFound:
                pass
            except APIError as api_e:
                if 'can not get logs from container which is dead or marked for removal' in str(
                        api_e):
                    output.append('Build cancelled')
                else:
                    logger.exception('Error removing docker container')
            except (DockerException, ReadTimeout):
                logger.exception('Error removing docker container')

        return exit_code, ''.join(output)
Exemplo n.º 5
0
 def decrypt(encrypted):
     fernet = Fernet(to_binary(current_app.config['SECURE_TOKEN_KEY']))
     text = fernet.decrypt(to_binary(encrypted))
     return to_text(text)
Exemplo n.º 6
0
 def encrypt(text):
     fernet = Fernet(to_binary(current_app.config['SECURE_TOKEN_KEY']))
     return fernet.encrypt(to_binary(text))