Exemple #1
0
    def send_deploy(self, deploy, task, config, event):
        webhook_url = config["webhook_url"]

        app = App.query.get(deploy.app_id)

        payload = {
            "number": deploy.number,
            "app_name": app.name,
            "params": dict(task.params or {}),
            "env": deploy.environment,
            "ref": task.ref,
            "sha": task.sha,
            "duration": task.duration,
            "event": "started" if event == NotifierEvent.TASK_STARTED else "finished",
            "dateStarted": task.date_started.isoformat() + "Z"
            if task.date_started
            else None,
            "dateReleased": task.date_finished.isoformat() + "Z"
            if task.date_finished
            else None,
            "link": http.absolute_uri(
                f"/deploys/{app.name}/{deploy.environment}/{deploy.number}/"
            ),
        }

        http.post(webhook_url, json=payload)
Exemple #2
0
    def send_deploy(self, deploy, task, config, event):
        webhook_url = config['webhook_url']

        app = App.query.get(deploy.app_id)

        payload = {
            'number':
            deploy.number,
            'app_name':
            app.name,
            'params':
            dict(task.params or {}),
            'env':
            deploy.environment,
            'ref':
            task.ref,
            'sha':
            task.sha,
            'duration':
            task.duration,
            'event':
            'started' if event == NotifierEvent.TASK_STARTED else 'finished',
            'dateStarted':
            task.date_started.isoformat() + 'Z' if task.date_started else None,
            'dateFinished':
            task.date_finished.isoformat() +
            'Z' if task.date_finished else None,
            'link':
            http.absolute_uri('/deploys/{}/{}/{}/'.format(
                app.name, deploy.environment, deploy.number)),
        }

        http.post(webhook_url, json=payload)
Exemple #3
0
def generate_event_title(app, deploy, task, user, event):
    number = deploy.number
    app_name = app.name
    params = dict(task.params or {})
    env = deploy.environment
    ref = task.ref
    sha = task.sha[:7] if task.sha else task.ref
    status_label = task.status_label
    duration = task.duration
    user = user.name.split(
        "@", 1)[0]  # Usernames can either be 'user' or '*****@*****.**'
    link = http.absolute_uri(
        f"/deploys/{app.name}/{deploy.environment}/{deploy.number}")

    # TODO(dcramer): show the ref when it differs from the sha
    if event == NotifierEvent.TASK_QUEUED:
        return f"[{app_name}/{env}] {user} queued deploy <{link}|#{number}> ({sha})"
    if event == NotifierEvent.TASK_STARTED:
        return f"[{app_name}/{env}] {user} started deploy <{link}|#{number}> ({sha})"
    if task.status == TaskStatus.failed:
        return f"[{app_name}/{env}] Failed to finish {user}'s deploy <{link}|#{number}> ({sha}) after {duration}s"
    if task.status == TaskStatus.cancelled:
        return f"[{app_name}/{env}] {user}'s deploy <{link}|#{number}> ({sha}) was cancelled after {duration}s"
    if task.status == TaskStatus.finished:
        return f"[{app_name}/{env}] Successfully finished {user}'s deploy <{link}|#{number}> ({sha}) after {duration}s"
    raise NotImplementedError(task.status)
Exemple #4
0
    def send_deploy(self, deploy, task, config, event):
        webhook_url = config['webhook_url']

        app = App.query.get(deploy.app_id)
        task = Task.query.get(deploy.task_id)
        user = User.query.get(task.user_id)

        params = {
            'number':
            deploy.number,
            'app_name':
            app.name,
            'params':
            dict(task.params or {}),
            'env':
            deploy.environment,
            'ref':
            task.ref,
            'sha':
            task.sha[:7] if task.sha else task.ref,
            'status_label':
            task.status_label,
            'duration':
            task.duration,
            'user':
            user.name.split(
                '@',
                1)[0],  # Usernames can either be 'user' or '*****@*****.**'
            'link':
            http.absolute_uri('/deploys/{}/{}/{}'.format(
                app.name, deploy.environment, deploy.number)),
        }

        # TODO(dcramer): show the ref when it differs from the sha
        if event == NotifierEvent.TASK_QUEUED:
            title = "[{app_name}/{env}] {user} queued deploy <{link}|#{number}> ({sha})".format(
                **params)
        elif event == NotifierEvent.TASK_STARTED:
            title = "[{app_name}/{env}] {user} started deploy <{link}|#{number}> ({sha})".format(
                **params)
        elif task.status == TaskStatus.failed:
            title = "[{app_name}/{env}] Failed to finish {user}'s deploy <{link}|#{number}> ({sha}) after {duration}s".format(
                **params)
        elif task.status == TaskStatus.cancelled:
            title = "[{app_name}/{env}] {user}'s deploy <{link}|#{number}> ({sha}) was cancelled after {duration}s".format(
                **params)
        elif task.status == TaskStatus.finished:
            title = "[{app_name}/{env}] Successfully finished {user}'s deploy <{link}|#{number}> ({sha}) after {duration}s".format(
                **params)
        else:
            raise NotImplementedError(task.status)

        payload = {
            'parse': 'none',
            'text': title,
        }

        values = {'payload': json.dumps(payload)}

        http.post(webhook_url, values)
Exemple #5
0
    def send(self, task, config, event):
        webhook_url = config['webhook_url']

        app = App.query.get(task.app_id)

        params = {
            'number':
            task.number,
            'app_name':
            app.name,
            'params':
            dict(task.params or {}),
            'env':
            task.environment,
            'ref':
            task.ref,
            'sha':
            task.sha[:7] if task.sha else task.ref,
            'status_label':
            task.status_label,
            'duration':
            task.duration,
            'link':
            http.absolute_uri('/{}/{}/{}'.format(app.name, task.environment,
                                                 task.number)),
        }

        # TODO(dcramer): show the ref when it differs from the sha
        if event == NotifierEvent.TASK_QUEUED:
            title = "[{app_name}/{env}] Queued deploy <{link}|#{number}> ({sha})".format(
                **params)
        elif event == NotifierEvent.TASK_STARTED:
            title = "[{app_name}/{env}] Starting deploy <{link}|#{number}> ({sha})".format(
                **params)
        elif task.status == TaskStatus.failed:
            title = "[{app_name}/{env}] Failed to deploy <{link}|#{number}> ({sha}) after {duration}s".format(
                **params)
        elif task.status == TaskStatus.cancelled:
            title = "[{app_name}/{env}] Deploy <{link}|#{number}> ({sha}) was cancelled after {duration}s".format(
                **params)
        elif task.status == TaskStatus.finished:
            title = "[{app_name}/{env}] Successfully deployed <{link}|#{number}> ({sha}) after {duration}s".format(
                **params)
        else:
            raise NotImplementedError(task.status)

        payload = {
            'parse': 'none',
            'text': title,
        }

        values = {'payload': json.dumps(payload)}

        http.post(webhook_url, values)
Exemple #6
0
    def send_deploy(self, deploy, task, config, event):
        token = current_app.config['GITHUB_TOKEN']
        if not token:
            raise ValueError('GITHUB_TOKEN is not set')
        headers = {
            'Accept': 'application/vnd.github.v3+json',
            'Authorization': 'token {}'.format(token),
        }

        app = App.query.get(deploy.app_id)
        task = Task.query.get(deploy.task_id)

        api_root = (config.get('api_root')
                    or current_app.config['GITHUB_API_ROOT']).rstrip('/')

        url = '{api_root}/repos/{repo}/statuses/{sha}'.format(
            api_root=api_root,
            repo=config['repo'],
            sha=task.sha,
        )

        target_url = http.absolute_uri('/deploys/{}/{}/{}'.format(
            app.name, deploy.environment, deploy.number))

        if event == NotifierEvent.TASK_QUEUED:
            state = 'pending'
            description = 'Freight deploy #{number} is currently queued.'
        elif event == NotifierEvent.TASK_STARTED:
            state = 'pending'
            description = 'Freight deploy #{number} has started.'
        elif task.status == TaskStatus.failed:
            state = 'failure'
            description = 'Freight deploy #{number} has failed.'
        elif task.status == TaskStatus.cancelled:
            state = 'error'
            description = 'Freight deploy #{number} has been cancelled.'
        elif task.status == TaskStatus.finished:
            state = 'success'
            description = 'Freight deploy #{number} has finished successfully.'
        else:
            raise NotImplementedError(task.status)

        payload = {
            'state': state,
            'target_url': target_url,
            'description': description.format(number=deploy.number),
            'context': 'continuous-integration/freight/deploy',
        }

        http.post(url, headers=headers, json=payload)
Exemple #7
0
    def send_deploy(self, deploy, task, config, event):
        token = current_app.config["GITHUB_TOKEN"]
        if not token:
            raise ValueError("GITHUB_TOKEN is not set")
        headers = {
            "Accept": "application/vnd.github.v3+json",
            "Authorization": f"token {token}",
        }

        app = App.query.get(deploy.app_id)
        task = Task.query.get(deploy.task_id)

        api_root = (config.get("api_root")
                    or current_app.config["GITHUB_API_ROOT"]).rstrip("/")

        url = f"{api_root}/repos/{config['repo']}/statuses/{task.sha}"

        target_url = http.absolute_uri(
            f"/deploys/{app.name}/{deploy.environment}/{deploy.number}")

        if event == NotifierEvent.TASK_QUEUED:
            state = "pending"
            description = f"Freight deploy #{deploy.number} is currently queued."
        elif event == NotifierEvent.TASK_STARTED:
            state = "pending"
            description = f"Freight deploy #{deploy.number} has started."
        elif task.status == TaskStatus.failed:
            state = "failure"
            description = f"Freight deploy #{deploy.number} has failed."
        elif task.status == TaskStatus.cancelled:
            state = "error"
            description = f"Freight deploy #{deploy.number} has been cancelled."
        elif task.status == TaskStatus.finished:
            state = "success"
            description = f"Freight deploy #{deploy.number} has finished successfully."
        else:
            raise NotImplementedError(task.status)

        payload = {
            "state": state,
            "target_url": target_url,
            "description": description,
            "context": "continuous-integration/freight/deploy",
        }

        http.post(url, headers=headers, json=payload)
Exemple #8
0
    def send_deploy(self, deploy, task, config, event):
        url = config["url"]

        app = App.query.get(deploy.app_id)
        task = Task.query.get(deploy.task_id)
        user = User.query.get(task.user_id)
        title = generate_event_title(app, deploy, task, user, event)

        payload = {
            "app_name":
            app.name,
            "date_created":
            stringify_date(task.date_created),
            "date_started":
            stringify_date(task.date_started),
            "date_finished":
            stringify_date(task.date_finished),
            "deploy_number":
            deploy.number,
            "duration":
            task.duration,
            "environment":
            deploy.environment,
            "link":
            http.absolute_uri(
                f"/deploys/{app.name}/{deploy.environment}/{deploy.number}/"),
            "params":
            dict(task.params or {}),
            "previous_sha":
            app.get_previous_sha(deploy.environment, current_sha=task.sha),
            "ref":
            task.ref,
            "sha":
            task.sha,
            "status":
            str(event),
            "title":
            title,
            "user":
            user.name,
            "user_id":
            user.id,
        }

        http.post(url, headers=config.get("headers", {}), json=payload)
Exemple #9
0
def generate_event_title(app, deploy, task, user, event):
    params = {
        'number':
        deploy.number,
        'app_name':
        app.name,
        'params':
        dict(task.params or {}),
        'env':
        deploy.environment,
        'ref':
        task.ref,
        'sha':
        task.sha[:7] if task.sha else task.ref,
        'status_label':
        task.status_label,
        'duration':
        task.duration,
        'user':
        user.name.split(
            '@', 1)[0],  # Usernames can either be 'user' or '*****@*****.**'
        'link':
        http.absolute_uri('/deploys/{}/{}/{}'.format(app.name,
                                                     deploy.environment,
                                                     deploy.number)),
    }

    # TODO(dcramer): show the ref when it differs from the sha
    if event == NotifierEvent.TASK_QUEUED:
        return "[{app_name}/{env}] {user} queued deploy <{link}|#{number}> ({sha})".format(
            **params)
    if event == NotifierEvent.TASK_STARTED:
        return "[{app_name}/{env}] {user} started deploy <{link}|#{number}> ({sha})".format(
            **params)
    if task.status == TaskStatus.failed:
        return "[{app_name}/{env}] Failed to finish {user}'s deploy <{link}|#{number}> ({sha}) after {duration}s".format(
            **params)
    if task.status == TaskStatus.cancelled:
        return "[{app_name}/{env}] {user}'s deploy <{link}|#{number}> ({sha}) was cancelled after {duration}s".format(
            **params)
    if task.status == TaskStatus.finished:
        return "[{app_name}/{env}] Successfully finished {user}'s deploy <{link}|#{number}> ({sha}) after {duration}s".format(
            **params)
    raise NotImplementedError(task.status)
Exemple #10
0
    def send_deploy(self, deploy, task, config, event):
        webhook_url = config['webhook_url']

        app = App.query.get(deploy.app_id)
        task = Task.query.get(deploy.task_id)
        user = User.query.get(task.user_id)

        params = {
            'number': deploy.number,
            'app_name': app.name,
            'params': dict(task.params or {}),
            'env': deploy.environment,
            'ref': task.ref,
            'sha': task.sha[:7] if task.sha else task.ref,
            'status_label': task.status_label,
            'duration': task.duration,
            'user': user.name.split('@', 1)[0],  # Usernames can either be 'user' or '*****@*****.**'
            'link': http.absolute_uri('/deploys/{}/{}/{}'.format(app.name, deploy.environment, deploy.number)),
        }

        # TODO(dcramer): show the ref when it differs from the sha
        if event == NotifierEvent.TASK_QUEUED:
            title = "[{app_name}/{env}] {user} queued deploy <{link}|#{number}> ({sha})".format(**params)
        elif event == NotifierEvent.TASK_STARTED:
            title = "[{app_name}/{env}] {user} started deploy <{link}|#{number}> ({sha})".format(**params)
        elif task.status == TaskStatus.failed:
            title = "[{app_name}/{env}] Failed to finish {user}'s deploy <{link}|#{number}> ({sha}) after {duration}s".format(**params)
        elif task.status == TaskStatus.cancelled:
            title = "[{app_name}/{env}] {user}'s deploy <{link}|#{number}> ({sha}) was cancelled after {duration}s".format(**params)
        elif task.status == TaskStatus.finished:
            title = "[{app_name}/{env}] Successfully finished {user}'s deploy <{link}|#{number}> ({sha}) after {duration}s".format(**params)
        else:
            raise NotImplementedError(task.status)

        payload = {
            'parse': 'none',
            'text': title,
        }

        values = {'payload': json.dumps(payload)}

        http.post(webhook_url, values)
Exemple #11
0
    def send(self, task, config, event):
        webhook_url = config['webhook_url']

        app = App.query.get(task.app_id)

        payload = {
            'number': task.number,
            'app_name': app.name,
            'task_name': task.name,
            'env': task.environment,
            'ref': task.ref,
            'sha': task.sha,
            'duration': task.duration,
            'event': 'started' if event == NotifierEvent.TASK_STARTED else 'finished',
            'dateStarted': task.date_started.isoformat() + 'Z' if task.date_started else None,
            'dateFinished': task.date_finished.isoformat() + 'Z' if task.date_finished else None,
            'link': http.absolute_uri('/tasks/{}/{}/{}/'.format(app.name, task.environment, task.number)),
        }

        http.post(webhook_url, json=payload)
Exemple #12
0
    def send(self, task, config, event):
        webhook_url = config['webhook_url']

        app = App.query.get(task.app_id)

        params = {
            'number': task.number,
            'app_name': app.name,
            'task_name': task.name,
            'env': task.environment,
            'ref': task.ref,
            'sha': task.sha[:7] if task.sha else task.ref,
            'status_label': task.status_label,
            'duration': task.duration,
            'link': http.absolute_uri('/tasks/{}/{}/{}/'.format(app.name, task.environment, task.number)),
        }

        # TODO(dcramer): show the ref when it differs from the sha
        if event == NotifierEvent.TASK_QUEUED:
            title = "[{app_name}/{env}] Queued deploy <{link}|#{number}> ({sha})".format(**params)
        elif event == NotifierEvent.TASK_STARTED:
            title = "[{app_name}/{env}] Starting deploy <{link}|#{number}> ({sha})".format(**params)
        elif task.status == TaskStatus.failed:
            title = "[{app_name}/{env}] Failed to deploy <{link}|#{number}> ({sha}) after {duration}s".format(**params)
        elif task.status == TaskStatus.cancelled:
            title = "[{app_name}/{env}] Deploy <{link}|#{number}> ({sha}) was cancelled after {duration}s".format(**params)
        elif task.status == TaskStatus.finished:
            title = "[{app_name}/{env}] Successfully deployed <{link}|#{number}> ({sha}) after {duration}s".format(**params)
        else:
            raise NotImplementedError(task.status)

        payload = {
            'parse': 'none',
            'text': title,
        }

        values = {'payload': json.dumps(payload)}

        http.post(webhook_url, values)
Exemple #13
0
    def send(self, task, config, event):
        webhook_url = config["webhook_url"]

        app = App.query.get(task.app_id)

        params = {
            "number": task.number,
            "app_name": app.name,
            "task_name": task.name,
            "env": task.environment,
            "ref": task.ref,
            "sha": task.sha[:7] if task.sha else task.ref,
            "status_label": task.status_label,
            "duration": task.duration,
            "link": http.absolute_uri("/tasks/{}/{}/{}/".format(app.name, task.environment, task.number)),
        }

        if event == NotifierEvent.TASK_STARTED:
            title = "[{app_name}/{env}] Starting deploy <{link}|#{number}> ({sha})".format(**params)
        elif task.status == TaskStatus.failed:
            title = "[{app_name}/{env}] Failed to deploy <{link}|#{number}> ({sha}) after {duration}s".format(**params)
        elif task.status == TaskStatus.cancelled:
            title = "[{app_name}/{env}] Deploy <{link}|#{number}> ({sha}) was cancelled after {duration}s".format(
                **params
            )
        elif task.status == TaskStatus.finished:
            title = "[{app_name}/{env}] Successfully deployed <{link}|#{number}> ({sha}) after {duration}s".format(
                **params
            )
        else:
            raise NotImplementedError(task.status)

        payload = {"parse": "none", "text": title}

        values = {"payload": json.dumps(payload)}

        http.post(webhook_url, values)
Exemple #14
0
    def execute_deploy(self, workspace, deploy, task) -> None:
        date_started = datetime.utcnow()

        app = App.query.get(task.app_id)
        prev_sha = app.get_previous_sha(deploy.environment,
                                        current_sha=task.sha) or ""

        config = self.get_config(workspace, task)

        sentry_context: Optional[SentryContext]
        if config.get("sentry", {}):
            sentry_context = make_sentry_context(config["sentry"])
        else:
            sentry_context = None

        kube_context: Optional[KubernetesContext]
        if config.get("kubernetes", {}):
            kube_context = make_kube_context(config["kubernetes"])
        else:
            kube_context = None

        ssh_key = self.get_ssh_key()
        task_context = TaskContext(
            id=str(deploy.id),
            date_created=str(task.date_created),
            name=app.name,
            environment=deploy.environment,
            sha=task.sha,
            prev_sha=prev_sha,
            ref=task.ref,
            url=http.absolute_uri(
                f"/deploys/{app.name}/{deploy.environment}/{deploy.number}"),
            ssh_key=ssh_key.name,
        )

        context = PipelineContext(task=task_context,
                                  kube=kube_context,
                                  workspace=workspace)

        if not config["steps"]:
            raise StepFailed("No steps to run")

        if sentry_context:
            workspace.log.info(
                f"Creating new Sentry release: {sentry_context.repository}@{task_context.sha}"
            )
            sentry_context.client.post(
                f"https://sentry.io/api/0/organizations/{sentry_context.organization}/releases/",
                json={
                    "version":
                    task_context.sha,
                    "refs": [{
                        "repository": sentry_context.repository,
                        "previousCommit": task_context.prev_sha,
                        "commit": task_context.sha,
                    }],
                    "projects": [sentry_context.project],
                },
            ).raise_for_status()

        for i, step in enumerate(config["steps"]):
            workspace.log.info(f"Running Step {i+1} ({step['kind']})")
            run_step(step, context)
            workspace.log.info(f"Finished Step {i+1}")

        date_finished = datetime.utcnow()

        if sentry_context:
            workspace.log.info(f"Tagging Sentry release as deployed.")
            sentry_context.client.put(
                f"https://sentry.io/api/0/organizations/{sentry_context.organization}/releases/{task_context.sha}/",
                json={
                    "dateReleased": date_finished.isoformat() + "Z"
                },
            ).raise_for_status()
            sentry_context.client.post(
                f"https://sentry.io/api/0/organizations/{sentry_context.organization}/releases/{task_context.sha}/deploys/",
                json={
                    "environment": deploy.environment,
                    "url": task_context.url,
                    "dateStarted": date_started.isoformat() + "Z",
                    "dateFinished": date_finished.isoformat() + "Z",
                },
            ).raise_for_status()