Exemple #1
0
def application_images_build_submit(application_id):
    application = Application.query.filter_by(id=application_id).first()
    if application is None:
        abort(404)
    project = application.project
    organization = application.project.organization

    form = ImageBuildSubmitForm()
    form.application_id.choices = [
        (str(application.id),
         f'{organization.slug}/{project.slug}: {application.slug}')
    ]
    form.application_id.data = str(application.id)

    if form.validate_on_submit():
        organization_slug = organization.slug
        project_slug = project.slug
        application_slug = application.slug
        repository_name = f"cabotage/{organization_slug}/{project_slug}/{application_slug}"

        fileobj = request.files['build_file']
        if fileobj:
            minio_response = minio.write_object(organization_slug,
                                                project_slug, application_slug,
                                                fileobj)
            image = Image(
                application_id=application.id,
                repository_name=repository_name,
                build_slug=minio_response['path'],
            )
            db.session.add(image)
            db.session.flush()
            activity = Activity(verb='submit',
                                object=image,
                                data={
                                    'user_id':
                                    str(current_user.id),
                                    'timestamp':
                                    datetime.datetime.utcnow().isoformat(),
                                })
            db.session.add(activity)
            db.session.commit()
            run_image_build.delay(image_id=image.id)
        return redirect(
            url_for('user.project_application',
                    org_slug=organization.slug,
                    project_slug=project.slug,
                    app_slug=application.slug))
    return render_template('user/application_images_build_submit.html',
                           form=form,
                           application=application)
Exemple #2
0
def process_deployment_hook(hook):
    installation_id = hook.payload['installation']['id']
    deployment = hook.payload['deployment']
    environment = deployment['environment']
    repository = hook.payload['repository']
    sender = hook.payload['sender']
    bearer_token = github_app.bearer_token
    access_token = None

    try:
        slugs = environment.split('/')
        if len(slugs) != 2 or slugs[0] != 'cabotage':
            print('not configured for this environment')
            return False
        _, application_id = slugs

        application = Application.query.filter_by(id=application_id).first()
        if application is None:
            print('could not find application')
            return False

        if application.github_app_installation_id != installation_id:
            print('application not configured with installation id')
            return False

        access_token_response = requests.post(
            f'https://api.github.com/installations/{installation_id}/access_tokens',
            headers={
                'Accept': 'application/vnd.github.machine-man-preview+json',
                'Authorization': f'Bearer {bearer_token}',
            })
        if 'token' not in access_token_response.json():
            print(f'Unable to authenticate for {installation_id}')
            print(access_token_response.json())
            raise HookError(f'Unable to authenticate for {installation_id}')

        access_token = access_token_response.json()

        post_deployment_status_update(access_token["token"],
                                      deployment['statuses_url'], 'pending',
                                      'Deployment is starting!')

        tarball_request = requests.get(
            f'https://api.github.com/repos/{repository["full_name"]}/tarball/{deployment["sha"]}',
            headers={
                'Accept': 'application/vnd.github.machine-man-preview+json',
                'Authorization': f'token {access_token["token"]}',
            },
            stream=True,
        )

        github_tarball_fd, github_tarball_path = tempfile.mkstemp()
        release_tarball_fd, release_tarball_path = tempfile.mkstemp()
        try:
            print('rewriting tarfile... for reasons')
            with open(github_tarball_path, 'wb') as handle:
                for chunk in tarball_request.iter_content(4096):
                    handle.write(chunk)
            with tarfile.open(github_tarball_path, 'r') as github_tarfile:
                with tarfile.open(release_tarball_path,
                                  'w|gz') as release_tarfile:
                    for member in github_tarfile:
                        tar_info = member
                        tar_info.name = f'./{str(Path(*Path(member.name).parts[1:]))}'
                        release_tarfile.addfile(
                            tar_info, github_tarfile.extractfile(member))
            print('uploading tar to minio')
            with open(release_tarball_path, 'rb') as handle:
                minio_response = minio.write_object(
                    application.project.organization.slug,
                    application.project.slug, application.slug, handle)
            print(f'uploaded tar to {minio_response["path"]}')
        finally:
            os.remove(github_tarball_path)
            os.remove(release_tarball_path)

        image = Image(
            application_id=application.id,
            repository_name=
            f"cabotage/{application.project.organization.slug}/{application.project.slug}/{application.slug}",
            build_slug=minio_response['path'],
            image_metadata={
                **deployment, 'installation_id': installation_id,
                'auto_deploy': True
            },
        )
        db.session.add(image)
        db.session.flush()
        activity = Activity(verb='submit',
                            object=image,
                            data={
                                'sender':
                                sender,
                                'timestamp':
                                datetime.datetime.utcnow().isoformat(),
                            })
        db.session.add(activity)
        db.session.commit()

        run_image_build.delay(image_id=image.id)

        post_deployment_status_update(
            access_token["token"], deployment['statuses_url'], 'pending',
            'Code retrieved! Image build commencing.')
        return True
    except HookError as exc:
        if access_token and 'token' in access_token:
            post_deployment_status_update(access_token["token"],
                                          deployment['statuses_url'], 'error',
                                          str(exc))